MDL-45515 atto/plugins: Added border style and BG colour to table
authorjinhofer <jinhofer@umn.edu>
Thu, 20 Aug 2015 14:59:34 +0000 (09:59 -0500)
committerRyan Wyllie <ryan@moodle.com>
Fri, 23 Oct 2015 02:57:50 +0000 (02:57 +0000)
This commit adds the option for borders to be added and
styled, background colours to be set, and width to be set for tables
in the Atto HTML Editor. For those that desire to restrict
use of this, the plugin settings allow the admins to restrict
how much freedom their users have with borders.

lib/editor/atto/plugins/table/lang/en/atto_table.php
lib/editor/atto/plugins/table/lib.php
lib/editor/atto/plugins/table/settings.php [new file with mode: 0644]
lib/editor/atto/plugins/table/styles.css
lib/editor/atto/plugins/table/tests/behat/table.feature
lib/editor/atto/plugins/table/yui/build/moodle-atto_table-button/moodle-atto_table-button-debug.js
lib/editor/atto/plugins/table/yui/build/moodle-atto_table-button/moodle-atto_table-button-min.js
lib/editor/atto/plugins/table/yui/build/moodle-atto_table-button/moodle-atto_table-button.js
lib/editor/atto/plugins/table/yui/src/button/js/button.js

index fa0c076..950e076 100644 (file)
 
 $string['addcolumnafter'] = 'Insert column after';
 $string['addrowafter'] = 'Insert row after';
+$string['all'] = 'Around each cell';
+$string['allowbackgroundcolour'] = 'Allow background colour';
+$string['allowbackgroundcolour_desc'] = 'Allow users to set the background colour for the table';
+$string['allowborder'] = 'Allow borders';
+$string['allowborder_desc'] = 'If checked, users will be able to customize borders when creating and editing a table';
+$string['allowborderstyle'] = 'Allow border styling';
+$string['allowborderstyle_desc'] = 'Allow users to style borders on tables. If this is not checked, but allowborder is checked, the default style is solid.<br>NOTE that this setting will not have an impact unless allowborder is checked';
+$string['allowbordersize'] = 'Allow border size control';
+$string['allowbordersize_desc'] = 'Allow users to set the size of borders on tables. If this is not checked, but allowborder is checked, the default size is 1px.<br>NOTE that this setting will not have an impact unless allowborder is checked';
+$string['allowbordercolour'] = 'Allow border colour';
+$string['allowbordercolour_desc'] = 'Allow users to set the colour of the borders on tables. If this is not checked, but allowborder is checked, the default colour is black.<br>NOTE that this setting will not have an impact unless allowborder is checked';
+$string['allowwidth'] = 'Allow width';
+$string['allowwidth_desc'] = 'Allow users to set the width of the tables.';
+$string['appearance'] = 'Appearance';
+$string['backgroundcolour'] = 'Background colour';
 $string['both'] = 'Both';
+$string['bordercolour'] = 'Border colour';
+$string['borders'] = 'Borders';
+$string['bordersize'] = 'Size of borders';
+$string['borderstyles'] = 'Style of borders';
+$string['borderstyles_desc'] = 'Allowed border styles, separated by commas';
+$string['borderstyles_default'] = 'solid,dashed,dotted';
 $string['caption'] = 'Caption';
 $string['captionposition'] = 'Caption position';
 $string['columns'] = 'Columns';
@@ -37,8 +58,15 @@ $string['movecolumnleft'] = 'Move column left';
 $string['movecolumnright'] = 'Move column right';
 $string['moverowdown'] = 'Move row down';
 $string['moverowup'] = 'Move row up';
+$string['noborder'] = 'No border';
+$string['none'] = 'None';
 $string['numberofcolumns'] = 'Number of columns';
 $string['numberofrows'] = 'Number of rows';
+$string['outer'] = 'Around table';
 $string['pluginname'] = 'Table';
 $string['rows'] = 'Rows';
+$string['settings'] = 'Table settings';
 $string['updatetable'] = 'Update table';
+$string['width'] = 'Table width (in %)';
+$string['themedefault'] = 'Theme default';
+$string['transparent'] = 'Transparent';
index f9c0b5e..d865713 100644 (file)
@@ -32,6 +32,7 @@ function atto_table_strings_for_js() {
 
     $PAGE->requires->strings_for_js(array('createtable',
                                           'updatetable',
+                                          'appearance',
                                           'headers',
                                           'caption',
                                           'columns',
@@ -48,7 +49,19 @@ function atto_table_strings_for_js() {
                                           'moverowup',
                                           'deleterow',
                                           'deletecolumn',
-                                          'captionposition'),
+                                          'captionposition',
+                                          'borders',
+                                          'bordersize',
+                                          'bordercolour',
+                                          'borderstyles',
+                                          'none',
+                                          'all',
+                                          'backgroundcolour',
+                                          'width',
+                                          'outer',
+                                          'noborder',
+                                          'transparent',
+                                          'themedefault'),
                                     'atto_table');
 
     $PAGE->requires->strings_for_js(array('top',
@@ -56,3 +69,20 @@ function atto_table_strings_for_js() {
                                     'editor');
 }
 
+/**
+ * Set params for this plugin
+ * @param string $elementid
+ * @param string $options
+ * @param string $foptions
+ */
+function atto_table_params_for_js($elementid, $options, $foptions) {
+    $params = array('allowBorders' => (bool) get_config('atto_table', 'allowborders'),
+                    'allowBorderStyles' => (bool) get_config('atto_table', 'allowborderstyles'),
+                    'borderStyles' => get_config('atto_table', 'borderstyles'),
+                    'allowBorderSize' => (bool) get_config('atto_table', 'allowbordersize'),
+                    'allowBorderColour' => (bool) get_config('atto_table', 'allowbordercolour'),
+                    'allowWidth' => (bool) get_config('atto_table', 'allowwidth'),
+                    'availableColors' => get_config('atto_table', 'availablecolors'),
+                    'allowBackgroundColour' => (bool) get_config('atto_table', 'allowbackgroundcolour'));
+    return $params;
+}
diff --git a/lib/editor/atto/plugins/table/settings.php b/lib/editor/atto/plugins/table/settings.php
new file mode 100644 (file)
index 0000000..4462a95
--- /dev/null
@@ -0,0 +1,110 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Settings that allow turning on and off various table features
+ *
+ * @package     atto_table
+ * @copyright   2015 Joseph Inhofer <jinhofer@umn.edu>
+ * @license     http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+$ADMIN->add('editoratto', new admin_category('atto_table', new lang_string('pluginname', 'atto_table')));
+
+$settings = new admin_settingpage('atto_table_settings', new lang_string('settings', 'atto_table'));
+if ($ADMIN->fulltree) {
+    $name = new lang_string('allowborder', 'atto_table');
+    $desc = new lang_string('allowborder_desc', 'atto_table');
+    $default = 0;
+
+    $setting = new admin_setting_configcheckbox('atto_table/allowborders',
+                                                $name,
+                                                $desc,
+                                                $default);
+    $settings->add($setting);
+
+    $name = new lang_string('allowborderstyle', 'atto_table');
+    $desc = new lang_string('allowborderstyle_desc', 'atto_table');
+    $default = 0;
+
+    $setting = new admin_setting_configcheckbox('atto_table/allowborderstyles',
+                                                $name,
+                                                $desc,
+                                                $default);
+    $settings->add($setting);
+
+    $name = new lang_string('borderstyles', 'atto_table');
+    $desc = new lang_string('borderstyles_desc', 'atto_table');
+    $default = ['none' => 'none',
+    'hidden' => 'hidden',
+    'dotted' => 'dotted',
+    'dashed' => 'dashed',
+    'solid' => 'solid',
+    'double' => 'double',
+    'groove' => 'groove',
+    'ridge' => 'ridge',
+    'inset' => 'inset',
+    'outset' => 'outset'];
+
+    $setting = new admin_setting_configmultiselect('atto_table/borderstyles',
+                                                $name,
+                                                $desc,
+                                                array_keys($default),
+                                                $default);
+    $settings->add($setting);
+
+    $name = new lang_string('allowbordersize', 'atto_table');
+    $desc = new lang_string('allowbordersize_desc', 'atto_table');
+    $default = 0;
+
+    $setting = new admin_setting_configcheckbox('atto_table/allowbordersize',
+                                                $name,
+                                                $desc,
+                                                $default);
+    $settings->add($setting);
+
+    $name = new lang_string('allowbordercolour', 'atto_table');
+    $desc = new lang_string('allowbordercolour_desc', 'atto_table');
+    $default = 0;
+
+    $setting = new admin_setting_configcheckbox('atto_table/allowbordercolour',
+                                                $name,
+                                                $desc,
+                                                $default);
+    $settings->add($setting);
+
+    $name = new lang_string('allowbackgroundcolour', 'atto_table');
+    $desc = new lang_string('allowbackgroundcolour_desc', 'atto_table');
+    $default = 0;
+
+    $setting = new admin_setting_configcheckbox('atto_table/allowbackgroundcolour',
+                                                $name,
+                                                $desc,
+                                                $default);
+    $settings->add($setting);
+
+    $name = new lang_string('allowwidth', 'atto_table');
+    $desc = new lang_string('allowwidth_desc', 'atto_table');
+    $default = 0;
+
+    $setting = new admin_setting_configcheckbox('atto_table/allowwidth',
+                                                $name,
+                                                $desc,
+                                                $default);
+    $settings->add($setting);
+}
index 69967c6..dbdcb5b 100644 (file)
@@ -9,3 +9,28 @@ div.editor_atto_content caption {
 div.editor_atto_content caption {
     height: auto;
 }
+
+div.availablecolors {
+    max-width: 55%;
+    display: inline-block;
+    vertical-align: middle;
+}
+
+div.availablecolors label:not(.hideborder) {
+    border: 1px solid #ddd;
+}
+
+div.availablecolors label {
+    border-radius: 4px;
+    display: inline-block;
+    font-size: 0.1em;
+    padding: 2px;
+    padding-left: 22px;
+}
+
+div.availablecolors label input[type="radio"] {
+    float: none;
+    margin: 0;
+    margin-left: -15px;
+}
+
index 3c6507e..99bcf3d 100644 (file)
@@ -34,5 +34,3 @@ Feature: Atto tables
     And I press "Update table"
     And I press "Save changes"
     Then ".blog_entry table caption" "css_element" should be visible
-
-
index 48f3a7a..1beb527 100644 (file)
Binary files a/lib/editor/atto/plugins/table/yui/build/moodle-atto_table-button/moodle-atto_table-button-debug.js and b/lib/editor/atto/plugins/table/yui/build/moodle-atto_table-button/moodle-atto_table-button-debug.js differ
index c7b367e..eea33a8 100644 (file)
Binary files a/lib/editor/atto/plugins/table/yui/build/moodle-atto_table-button/moodle-atto_table-button-min.js and b/lib/editor/atto/plugins/table/yui/build/moodle-atto_table-button/moodle-atto_table-button-min.js differ
index 48f3a7a..1beb527 100644 (file)
Binary files a/lib/editor/atto/plugins/table/yui/build/moodle-atto_table-button/moodle-atto_table-button.js and b/lib/editor/atto/plugins/table/yui/build/moodle-atto_table-button/moodle-atto_table-button.js differ
index 1c4f4df..b72ef94 100644 (file)
  */
 
 var COMPONENT = 'atto_table',
-    EDITTEMPLATE = '' +
-        '<form class="{{CSS.FORM}}">' +
-            '<label for="{{elementid}}_atto_table_caption">{{get_string "caption" component}}</label>' +
-            '<input class="{{CSS.CAPTION}} fullwidth" id="{{elementid}}_atto_table_caption" required />' +
-            '<br/>' +
-            '<br/>' +
-            '<label for="{{elementid}}_atto_table_captionposition" class="sameline">{{get_string "captionposition" component}}</label>' +
-            '<select class="{{CSS.CAPTIONPOSITION}}" id="{{elementid}}_atto_table_captionposition">' +
-                '<option value=""></option>' +
-                '<option value="top">{{get_string "top" "editor"}}</option>' +
-                '<option value="bottom">{{get_string "bottom" "editor"}}</option>' +
-            '</select>' +
-            '<br/>' +
-            '<label for="{{elementid}}_atto_table_headers" class="sameline">{{get_string "headers" component}}</label>' +
-            '<select class="{{CSS.HEADERS}}" id="{{elementid}}_atto_table_headers">' +
-                '<option value="columns">{{get_string "columns" component}}' + '</option>' +
-                '<option value="rows">{{get_string "rows" component}}' + '</option>' +
-                '<option value="both">{{get_string "both" component}}' + '</option>' +
-            '</select>' +
-            '<br/>' +
-            '<div class="mdl-align">' +
-                '<br/>' +
-                '<button class="submit" type="submit">{{get_string "updatetable" component}}</button>' +
-            '</div>' +
-        '</form>',
+    DEFAULT = {
+        BORDERSTYLE: 'solid',
+        BORDERWIDTH: '1'
+    },
+    DIALOGUE = {
+        WIDTH: '450px'
+    },
     TEMPLATE = '' +
         '<form class="{{CSS.FORM}}">' +
             '<label for="{{elementid}}_atto_table_caption">{{get_string "caption" component}}</label>' +
             '<input class="{{CSS.CAPTION}} fullwidth" id="{{elementid}}_atto_table_caption" required />' +
             '<br/>' +
             '<br/>' +
-            '<label for="{{elementid}}_atto_table_captionposition" class="sameline">{{get_string "captionposition" component}}</label>' +
+            '<label for="{{elementid}}_atto_table_captionposition" class="sameline">' +
+            '{{get_string "captionposition" component}}</label>' +
             '<select class="{{CSS.CAPTIONPOSITION}}" id="{{elementid}}_atto_table_captionposition">' +
                 '<option value=""></option>' +
                 '<option value="top">{{get_string "top" "editor"}}</option>' +
@@ -77,16 +60,120 @@ var COMPONENT = 'atto_table',
                 '<option value="both">{{get_string "both" component}}' + '</option>' +
             '</select>' +
             '<br/>' +
-            '<label for="{{elementid}}_atto_table_rows" class="sameline">{{get_string "numberofrows" component}}</label>' +
-            '<input class="{{CSS.ROWS}}" type="number" value="3" id="{{elementid}}_atto_table_rows" size="8" min="1" max="50"/>' +
-            '<br/>' +
-            '<label for="{{elementid}}_atto_table_columns" class="sameline">{{get_string "numberofcolumns" component}}</label>' +
-            '<input class="{{CSS.COLUMNS}}" type="number" value="3" id="{{elementid}}_atto_table_columns" ' +
-                    'size="8" min="1" max="20"/>' +
-            '<br/>' +
-            '<div class="mdl-align">' +
+            '{{#if nonedit}}' +
+                '<label for="{{elementid}}_atto_table_rows" class="sameline">{{get_string "numberofrows" component}}</label>' +
+                '<input class="{{CSS.ROWS}}" type="number" value="3" ' +
+                'id="{{elementid}}_atto_table_rows" size="8" min="1" max="50"/>' +
+                '<br/>' +
+                '<label for="{{elementid}}_atto_table_columns" ' +
+                'class="sameline">{{get_string "numberofcolumns" component}}</label>' +
+                '<input class="{{CSS.COLUMNS}}" type="number" value="3" id="{{elementid}}_atto_table_columns"' +
+                'size="8" min="1" max="20"/>' +
                 '<br/>' +
-                '<button class="{{CSS.SUBMIT}}" type="submit">{{get_string "createtable" component}}</button>' +
+            '{{/if}}' +
+            '{{#if allowStyling}}' +
+                '<fieldset>' +
+                '<legend class="mdl-align">{{get_string "appearance" component}}</legend>' +
+                '{{#if allowBorders}}' +
+                    '<label for="{{elementid}}_atto_table_borders" class="sameline">{{get_string "borders" component}}</label>' +
+                    '<select class="{{CSS.BORDERS}}" id="{{elementid}}_atto_table_borders">' +
+                        '<option value="default">{{get_string "themedefault" component}}' + '</option>' +
+                        '<option value="none">{{get_string "noborder" component}}' + '</option>' +
+                        '<option value="outer">{{get_string "outer" component}}' + '</option>' +
+                        '<option value="all">{{get_string "all" component}}' + '</option>' +
+                    '</select>' +
+                    '<br>' +
+                    '{{#if allowBorderStyles}}' +
+                        '<label for="{{elementid}}_atto_table_borderstyle" class="sameline">' +
+                        '{{get_string "borderstyles" component}}</label>' +
+                        '<select class="{{CSS.BORDERSTYLE}}" id="{{elementid}}_atto_table_borderstyle">' +
+                            '{{#each borderStyles}}' +
+                                '<option value="' + '{{this}}' + '">' + '{{this}}' + '</option>' +
+                            '{{/each}}' +
+                        '</select>' +
+                        '<br>' +
+                    '{{/if}}' +
+                    '{{#if allowBorderSize}}' +
+                        '<label for="{{elementid}}_atto_table_bordersize" class="sameline">' +
+                        '{{get_string "bordersize" component}}</label>' +
+                        '<input id="{{elementid}}_atto_table_bordersize" class="{{CSS.BORDERSIZE}}"' +
+                        'type="number" value="1" size="8" min="1" max="50"/>' +
+                        '<label style="display: inline-block;">{{CSS.BORDERSIZEUNIT}}</label>' +
+                        '<br>' +
+                    '{{/if}}' +
+                    '{{#if allowBorderColour}}' +
+                        '<label for="{{elementid}}_atto_table_bordercolour" class="sameline">' +
+                        '{{get_string "bordercolour" component}}</label>' +
+                        '<div id="{{elementid}}_atto_table_bordercolour"' +
+                        'class="{{CSS.BORDERCOLOUR}} {{CSS.AVAILABLECOLORS}}" size="1">' +
+                            '<label class="hideborder" for="{{../elementid}}_atto_table_bordercolour_-1"' +
+                            'style="background-color:transparent;color:transparent">' +
+
+                                '<input id="{{../elementid}}_atto_table_bordercolour_-1"' +
+                                'type="radio" name="borderColour" value="transparent" checked="checked"'+
+                                'title="{{get_string "transparent" component}}"></input>' +
+
+                                '{{get_string "transparent" component}}' +
+                            '</label>' +
+                            '{{#each availableColours}}' +
+                                '<label for="{{../elementid}}_atto_table_bordercolour_{{@index}}"' +
+                                'style="background-color:{{this}};color:{{this}}">' +
+
+                                    '<input id="{{../elementid}}_atto_table_bordercolour_{{@index}}"' +
+                                    'type="radio" name="borderColour" value="' + '{{this}}' + '" title="{{this}}">' +
+
+                                    '{{this}}' +
+                                '</label>' +
+                            '{{/each}}' +
+                        '</div>' +
+                        '<br>' +
+                    '{{/if}}' +
+                '{{/if}}' +
+                '{{#if allowBackgroundColour}}' +
+                    '<label for="{{elementid}}_atto_table_backgroundcolour" class="sameline">' +
+                    '{{get_string "backgroundcolour" component}}</label>' +
+                    '<div id="{{elementid}}_atto_table_backgroundcolour"' +
+                    'class="{{CSS.BACKGROUNDCOLOUR}} {{CSS.AVAILABLECOLORS}}" size="1">' +
+                        '<label class="hideborder" for="{{../elementid}}_atto_table_backgroundcolour_-1"' +
+                        'style="background-color:transparent;color:transparent">' +
+
+                            '<input id="{{../elementid}}_atto_table_backgroundcolour_-1"' +
+                            'type="radio" name="backgroundColour" value="transparent" checked="checked"'+
+                            'title="{{get_string "transparent" component}}"></input>' +
+
+                            '{{get_string "transparent" component}}' +
+                        '</label>' +
+
+                        '{{#each availableColours}}' +
+                            '<label for="{{../elementid}}_atto_table_backgroundcolour_{{@index}}"' +
+                            'style="background-color:{{this}};color:{{this}}">'+
+
+                                '<input id="{{../elementid}}_atto_table_backgroundcolour_{{@index}}"' +
+                                'type="radio" name="backgroundColour" value="' + '{{this}}' + '" title="{{this}}">' +
+
+                                '{{this}}' +
+                            '</label>' +
+                        '{{/each}}' +
+                    '</div>' +
+                    '<br>' +
+                '{{/if}}' +
+                '{{#if allowWidth}}' +
+                    '<label for="{{elementid}}_atto_table_width" class="sameline">' +
+                    '{{get_string "width" component}}</label>' +
+                    '<input id="{{elementid}}_atto_table_width" class="{{CSS.WIDTH}}" size="8" type="number" min="0" max="100"/>' +
+                    '<label style="display: inline-block;">{{CSS.WIDTHUNIT}}</label>' +
+                    '<br>' +
+                '{{/if}}' +
+                '</fieldset>' +
+            '{{/if}}' +
+            '<div class="mdl-align">' +
+            '<br/>' +
+            '{{#if edit}}' +
+                '<button class="submit" type="submit">{{get_string "updatetable" component}}</button>' +
+            '{{/if}}' +
+            '{{#if nonedit}}' +
+                '<button class="submit" type="submit">{{get_string "createtable" component}}</button>' +
+            '{{/if}}' +
             '</div>' +
         '</form>',
     CSS = {
@@ -96,7 +183,17 @@ var COMPONENT = 'atto_table',
         ROWS: 'rows',
         COLUMNS: 'columns',
         SUBMIT: 'submit',
-        FORM: 'atto_form'
+        FORM: 'atto_form',
+        BORDERS: 'borders',
+        BORDERSIZE: 'bordersize',
+        BORDERSIZEUNIT: 'px',
+        BORDERCOLOUR: 'bordercolour',
+        BORDERSTYLE: 'borderstyle',
+        BACKGROUNDCOLOUR: 'backgroundcolour',
+        WIDTH: 'customwidth',
+        WIDTHUNIT: '%',
+        AVAILABLECOLORS: 'availablecolors',
+        COLOURROW: 'colourrow'
     },
     SELECTORS = {
         CAPTION: '.' + CSS.CAPTION,
@@ -105,7 +202,16 @@ var COMPONENT = 'atto_table',
         ROWS: '.' + CSS.ROWS,
         COLUMNS: '.' + CSS.COLUMNS,
         SUBMIT: '.' + CSS.SUBMIT,
-        FORM: '.atto_form'
+        BORDERS: '.' + CSS.BORDERS,
+        BORDERSIZE: '.' + CSS.BORDERSIZE,
+        BORDERCOLOURS: '.' + CSS.BORDERCOLOUR + ' input[name="borderColour"]',
+        SELECTEDBORDERCOLOUR: '.' + CSS.BORDERCOLOUR + ' input[name="borderColour"]:checked',
+        BORDERSTYLE: '.' + CSS.BORDERSTYLE,
+        BACKGROUNDCOLOURS: '.' + CSS.BACKGROUNDCOLOUR + ' input[name="backgroundColour"]',
+        SELECTEDBACKGROUNDCOLOUR: '.' + CSS.BACKGROUNDCOLOUR + ' input[name="backgroundColour"]:checked',
+        FORM: '.atto_form',
+        WIDTH: '.' + CSS.WIDTH,
+        AVAILABLECOLORS: '.' + CSS.AVAILABLECOLORS
     };
 
 Y.namespace('M.atto_table').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], {
@@ -153,7 +259,6 @@ Y.namespace('M.atto_table').Button = Y.Base.create('button', Y.M.editor_atto.Edi
             callback: this._displayTableEditor,
             tags: 'table'
         });
-
         // Disable mozilla table controls.
         if (Y.UA.gecko) {
             document.execCommand("enableInlineTableEditing", false, false);
@@ -175,11 +280,12 @@ Y.namespace('M.atto_table').Button = Y.Base.create('button', Y.M.editor_atto.Edi
             var dialogue = this.getDialogue({
                 headerContent: M.util.get_string('createtable', COMPONENT),
                 focusAfterHide: true,
-                focusOnShowSelector: SELECTORS.CAPTION
+                focusOnShowSelector: SELECTORS.CAPTION,
+                width: DIALOGUE.WIDTH
             });
 
             // Set the dialogue content, and then show the dialogue.
-            dialogue.set('bodyContent', this._getDialogueContent())
+            dialogue.set('bodyContent', this._getDialogueContent(false))
                     .show();
         }
     },
@@ -216,28 +322,6 @@ Y.namespace('M.atto_table').Button = Y.Base.create('button', Y.M.editor_atto.Edi
         this.editor.contains(node);
     },
 
-    /**
-     * Return the edit table dialogue content, attaching any required
-     * events.
-     *
-     * @method _getEditDialogueContent
-     * @private
-     * @return {Node} The content to place in the dialogue.
-     */
-    _getEditDialogueContent: function() {
-        var template = Y.Handlebars.compile(EDITTEMPLATE);
-        this._content = Y.Node.create(template({
-                CSS: CSS,
-                elementid: this.get('host').get('elementid'),
-                component: COMPONENT
-            }));
-
-        // Handle table setting.
-        this._content.one('.submit').on('click', this._updateTable, this);
-
-        return this._content;
-    },
-
     /**
      * Return the dialogue content for the tool, attaching any required
      * events.
@@ -246,16 +330,33 @@ Y.namespace('M.atto_table').Button = Y.Base.create('button', Y.M.editor_atto.Edi
      * @private
      * @return {Node} The content to place in the dialogue.
      */
-    _getDialogueContent: function() {
+    _getDialogueContent: function(edit) {
         var template = Y.Handlebars.compile(TEMPLATE);
+        var availableColours = this.get('availableColors');
+
         this._content = Y.Node.create(template({
                 CSS: CSS,
                 elementid: this.get('host').get('elementid'),
-                component: COMPONENT
+                component: COMPONENT,
+                edit: edit,
+                nonedit: !edit,
+                allowStyling: this.get('allowStyling'),
+                allowBorders: this.get('allowBorders'),
+                allowBorderStyles: this.get('allowBorderStyles'),
+                borderStyles: this.get('borderStyles'),
+                allowBorderSize: this.get('allowBorderSize'),
+                allowBorderColour: this.get('allowBorderColour'),
+                allowBackgroundColour: this.get('allowBackgroundColour'),
+                availableColours: availableColours,
+                allowWidth: this.get('allowWidth')
             }));
 
         // Handle table setting.
-        this._content.one('.submit').on('click', this._setTable, this);
+        if (edit) {
+            this._content.one('.submit').on('click', this._updateTable, this);
+        } else {
+            this._content.one('.submit').on('click', this._setTable, this);
+        }
 
         return this._content;
     },
@@ -328,7 +429,17 @@ Y.namespace('M.atto_table').Button = Y.Base.create('button', Y.M.editor_atto.Edi
         var caption,
             captionposition,
             headers,
+            borders,
+            bordersize,
+            borderstyle,
+            bordercolour,
+            backgroundcolour,
+            backgroundcolourvalue = '#FFFFFF',
+            borderSizeValue = '1',
+            borderStyleValue = 'solid',
+            borderhex = '#FFFFFF',
             table,
+            width,
             captionnode;
 
         e.preventDefault();
@@ -341,8 +452,57 @@ Y.namespace('M.atto_table').Button = Y.Base.create('button', Y.M.editor_atto.Edi
         caption = e.currentTarget.ancestor(SELECTORS.FORM).one(SELECTORS.CAPTION);
         captionposition = e.currentTarget.ancestor(SELECTORS.FORM).one(SELECTORS.CAPTIONPOSITION);
         headers = e.currentTarget.ancestor(SELECTORS.FORM).one(SELECTORS.HEADERS);
+        borders = e.currentTarget.ancestor(SELECTORS.FORM).one(SELECTORS.BORDERS);
+        bordersize = e.currentTarget.ancestor(SELECTORS.FORM).one(SELECTORS.BORDERSIZE);
+        bordercolour = e.currentTarget.ancestor(SELECTORS.FORM).one(SELECTORS.SELECTEDBORDERCOLOUR);
+        borderstyle = e.currentTarget.ancestor(SELECTORS.FORM).one(SELECTORS.BORDERSTYLE);
+        backgroundcolour = e.currentTarget.ancestor(SELECTORS.FORM).one(SELECTORS.SELECTEDBACKGROUNDCOLOUR);
+        width = e.currentTarget.ancestor(SELECTORS.FORM).one(SELECTORS.WIDTH);
+
+        if (bordercolour) {
+            borderhex = bordercolour.get('value');
+        }
+
+        if (bordersize) {
+            borderSizeValue = bordersize.get('value');
+        }
+
+        if (borderstyle) {
+            borderStyleValue = borderstyle.get('value');
+        }
+
+        if (backgroundcolour) {
+            backgroundcolourvalue = backgroundcolour.get('value');
+        }
 
         table = this._lastTarget.ancestor('table');
+        // Clear the inline border styling
+        table.removeAttribute('style');
+        table.all('td, th').each(function() {
+            this.removeAttribute('style');
+        });
+
+        if (borders) {
+            if (borders.get('value') === 'outer') {
+                table.setStyle('border', borderSizeValue + CSS.BORDERSIZEUNIT + ' ' +
+                              borderStyleValue + ' ' + borderhex);
+            } else if (borders.get('value') === 'all') {
+                table.all('td, th').each(function() {
+                    this.setStyle('border', borderSizeValue + CSS.BORDERSIZEUNIT + ' ' +
+                             borderStyleValue + ' ' + borderhex);
+                });
+            } else if (borders.get('value') === 'none') {
+                table.setStyle('border', 'none');
+            }
+        }
+
+        if (width && width.get('value')) {
+            table.setStyle('width', width.get('value') + CSS.WIDTHUNIT);
+        }
+
+        if (backgroundcolourvalue !== '') {
+            table.setStyle('background-color', backgroundcolourvalue);
+        }
 
         captionnode = table.one('caption');
         if (!captionnode) {
@@ -426,10 +586,21 @@ Y.namespace('M.atto_table').Button = Y.Base.create('button', Y.M.editor_atto.Edi
     _setTable: function(e) {
         var caption,
             captionposition,
+            borders,
+            bordertable = '',
+            bordercell = '',
+            bordersize,
+            borderstyle,
+            bordercolour,
+            borderSizeValue = '1',
+            borderStyleValue = 'solid',
+            borderhex = '#FFFFFF',
             rows,
             cols,
             headers,
             tablehtml,
+            backgroundcolour,
+            width,
             i, j;
 
         e.preventDefault();
@@ -441,16 +612,62 @@ Y.namespace('M.atto_table').Button = Y.Base.create('button', Y.M.editor_atto.Edi
 
         caption = e.currentTarget.ancestor(SELECTORS.FORM).one(SELECTORS.CAPTION);
         captionposition = e.currentTarget.ancestor(SELECTORS.FORM).one(SELECTORS.CAPTIONPOSITION);
+        borders = e.currentTarget.ancestor(SELECTORS.FORM).one(SELECTORS.BORDERS);
+        bordersize = e.currentTarget.ancestor(SELECTORS.FORM).one(SELECTORS.BORDERSIZE);
+        bordercolour = e.currentTarget.ancestor(SELECTORS.FORM).one(SELECTORS.SELECTEDBORDERCOLOUR);
+        borderstyle = e.currentTarget.ancestor(SELECTORS.FORM).one(SELECTORS.BORDERSTYLE);
+        backgroundcolour = e.currentTarget.ancestor(SELECTORS.FORM).one(SELECTORS.SELECTEDBACKGROUNDCOLOUR);
         rows = e.currentTarget.ancestor(SELECTORS.FORM).one(SELECTORS.ROWS);
         cols = e.currentTarget.ancestor(SELECTORS.FORM).one(SELECTORS.COLUMNS);
         headers = e.currentTarget.ancestor(SELECTORS.FORM).one(SELECTORS.HEADERS);
+        width = e.currentTarget.ancestor(SELECTORS.FORM).one(SELECTORS.WIDTH);
+
+        if (bordercolour) {
+            borderhex = bordercolour.get('value');
+        }
+
+        if (bordersize) {
+            borderSizeValue = bordersize.get('value');
+        }
+
+        if (borderstyle) {
+            borderStyleValue = borderstyle.get('value');
+        }
+
+        if (borders) {
+            if (borders.get('value') === 'outer') {
+                bordertable = ' style="border: ' + borderSizeValue + CSS.BORDERSIZEUNIT + ' ' +
+                              borderStyleValue + ' ' + borderhex + ';"';
+            } else if (borders.get('value') === 'all') {
+                bordercell = ' style="border: ' + borderSizeValue + CSS.BORDERSIZEUNIT + ' ' +
+                             borderStyleValue + ' ' + borderhex + ';"';
+            }
+        }
+
+        if (backgroundcolour) {
+            if (bordertable !== '') {
+                bordertable = bordertable.substring(0, bordertable.length-1) +
+                              'background-color: ' + backgroundcolour.get('value') + ';"';
+            } else {
+                bordertable = ' style="background-color: ' + backgroundcolour.get('value') + ';"';
+            }
+        }
+
+        if (width && width.get('value')) {
+            if (bordertable !== '') {
+                bordertable = bordertable.substring(0, bordertable.length-1) + 'width: ' +
+                              width.get('value') + CSS.WIDTHUNIT + ';"';
+            } else {
+                bordertable = ' style="width: ' + width.get('value') + CSS.WIDTHUNIT + ';"';
+            }
+        }
 
         // Set the selection.
         this.get('host').setSelection(this._currentSelection);
 
         // Note there are some spaces inserted in the cells and before and after, so that users have somewhere to click.
         var nl = "\n";
-        tablehtml = '<br/>' + nl + '<table>' + nl;
+        tablehtml = '<br/>' + nl + '<table' + bordertable + '>' + nl;
 
         var captionstyle = '';
         if (captionposition.get('value')) {
@@ -462,7 +679,7 @@ Y.namespace('M.atto_table').Button = Y.Base.create('button', Y.M.editor_atto.Edi
             i = 1;
             tablehtml += '<thead>' + nl + '<tr>' + nl;
             for (j = 0; j < parseInt(cols.get('value'), 10); j++) {
-                tablehtml += '<th scope="col"></th>' + nl;
+                tablehtml += '<th scope="col"' + bordercell + '></th>' + nl;
             }
             tablehtml += '</tr>' + nl + '</thead>' + nl;
         }
@@ -471,9 +688,9 @@ Y.namespace('M.atto_table').Button = Y.Base.create('button', Y.M.editor_atto.Edi
             tablehtml += '<tr>' + nl;
             for (j = 0; j < parseInt(cols.get('value'), 10); j++) {
                 if (j === 0 && (headers.get('value') === 'rows' || headers.get('value') === 'both')) {
-                    tablehtml += '<th scope="row"></th>' + nl;
+                    tablehtml += '<th scope="row"' + bordercell + '></th>' + nl;
                 } else {
-                    tablehtml += '<td></td>' + nl;
+                    tablehtml += '<td ' + bordercell + '></td>' + nl;
                 }
             }
             tablehtml += '</tr>' + nl;
@@ -900,6 +1117,35 @@ Y.namespace('M.atto_table').Button = Y.Base.create('button', Y.M.editor_atto.Edi
         this.markUpdated();
     },
 
+    /**
+     * Obtain values for the table borders
+     *
+     * @method _getBorderConfiguration
+     * @param {Node} node
+     * @private
+     * @return {Array} or {Boolean} Returns the settings, if presents, or else returns false
+     */
+    _getBorderConfiguration: function(node) {
+        // We need to make a clone of the node in order to avoid grabbing any
+        // of the computed styles from the DOM. We only want inline styles set by us.
+        var shadowNode = node.cloneNode(true);
+        var borderStyle = shadowNode.getStyle('borderStyle'),
+            borderColor = shadowNode.getStyle('borderColor'),
+            borderWidth = shadowNode.getStyle('borderWidth');
+
+        if (borderStyle || borderColor || borderWidth) {
+            var hexColour = Y.Color.toHex(borderColor);
+            var width = parseInt(borderWidth, 10);
+            return {
+                borderStyle: borderStyle,
+                borderColor: hexColour === "#" ? null : hexColour,
+                borderWidth: isNaN(width) ? null : width
+            };
+        }
+
+        return false;
+    },
+
     /**
      * Edit table (show the dialogue).
      *
@@ -910,14 +1156,21 @@ Y.namespace('M.atto_table').Button = Y.Base.create('button', Y.M.editor_atto.Edi
         var dialogue = this.getDialogue({
             headerContent: M.util.get_string('edittable', COMPONENT),
             focusAfterHide: false,
-            focusOnShowSelector: SELECTORS.CAPTION
+            focusOnShowSelector: SELECTORS.CAPTION,
+            width: DIALOGUE.WIDTH
         });
 
         // Set the dialogue content, and then show the dialogue.
-        var node = this._getEditDialogueContent(),
+        var node = this._getDialogueContent(true),
             captioninput = node.one(SELECTORS.CAPTION),
             captionpositioninput = node.one(SELECTORS.CAPTIONPOSITION),
             headersinput = node.one(SELECTORS.HEADERS),
+            borderinput = node.one(SELECTORS.BORDERS),
+            borderstyle = node.one(SELECTORS.BORDERSTYLE),
+            bordercolours = node.all(SELECTORS.BORDERCOLOURS),
+            bordersize = node.one(SELECTORS.BORDERSIZE),
+            backgroundcolours = node.all(SELECTORS.BACKGROUNDCOLOURS),
+            width = node.one(SELECTORS.WIDTH),
             table = this._lastTarget.ancestor('table'),
             captionnode = table.one('caption');
 
@@ -927,6 +1180,10 @@ Y.namespace('M.atto_table').Button = Y.Base.create('button', Y.M.editor_atto.Edi
             captioninput.set('value', '');
         }
 
+        if (width && table.getStyle('width').indexOf('px') === -1) {
+            width.set('value', parseInt(table.getStyle('width'), 10));
+        }
+
         if (captionpositioninput && captionnode && captionnode.getAttribute('style')) {
             captionpositioninput.set('value', captionnode.getStyle('caption-side'));
         } else {
@@ -934,6 +1191,48 @@ Y.namespace('M.atto_table').Button = Y.Base.create('button', Y.M.editor_atto.Edi
             captionpositioninput.set('value', '');
         }
 
+        if (table.getStyle('background-color') !== 'transparent' && this.get('allowBackgroundColour')) {
+            var hexColour = Y.Color.toHex(table.getStyle('background-color'));
+            var matchedInput = backgroundcolours.filter('[value="' + hexColour + '"]');
+
+            if (matchedInput) {
+                matchedInput.set("checked", true);
+            }
+        }
+
+        if (this.get('allowBorders')) {
+            var borderValue = 'default',
+                borderConfiguration = this._getBorderConfiguration(table);
+
+            if (borderConfiguration) {
+                if (borderConfiguration.borderStyle && borderConfiguration.borderStyle === 'none') {
+                    borderValue = 'none';
+                } else {
+                    borderValue = 'outer';
+                }
+            } else {
+                borderConfiguration = this._getBorderConfiguration(table.one('td'));
+                if (borderConfiguration) {
+                     borderValue = 'all';
+                }
+            }
+
+            if (borderConfiguration) {
+                var borderStyle = borderConfiguration.borderStyle || DEFAULT.BORDERSTYLE;
+                var borderSize = borderConfiguration.borderWidth || DEFAULT.BORDERWIDTH;
+                borderstyle.set('value', borderStyle);
+                bordersize.set('value', borderSize);
+                borderinput.set('value', borderValue);
+
+                var hexColour = borderConfiguration.borderColor;
+                var matchedInput = bordercolours.filter('[value="' + hexColour + '"]');
+
+                if (matchedInput) {
+                    matchedInput.set("checked", true);
+                }
+            }
+        }
+
         var headersvalue = 'columns';
         if (table.one('th[scope="row"]')) {
             headersvalue = 'rows';
@@ -1054,4 +1353,117 @@ Y.namespace('M.atto_table').Button = Y.Base.create('button', Y.M.editor_atto.Edi
         this.markUpdated();
     }
 
+}, {
+    ATTRS: {
+        /**
+         * Whether or not to allow borders
+         *
+         * @attribute allowBorder
+         * @type Boolean
+         */
+        allowBorders: {
+            value: true
+        },
+
+        /**
+         * Whether or not to allow style of borders
+         *
+         * @attribute allowBorderStyle
+         * @type Boolean
+         */
+        allowBorderStyles: {
+            value: true
+        },
+
+        /**
+         * What border styles to allow
+         *
+         * @attribute borderStyles
+         * @type Array
+         */
+        borderStyles: {
+            value: [
+                'solid',
+                'dashed',
+                'dotted'
+            ],
+            setter: function(value) {
+                if (value) {
+                    return value.replace(/ /g,'').split(',');
+                } else {
+                    // Not a valid value - revert to default value.
+                    return Y.Attribute.INVALID_VALUE;
+                }
+            }
+        },
+
+        /**
+         * Whether or not to allow border size
+         *
+         * @attribute allowBorderSize
+         * @type Boolean
+         */
+        allowBorderSize: {
+            value: true
+        },
+
+        /**
+         * Whether or not to allow colourizing borders
+         *
+         * @attribute allowBorderColours
+         * @type Boolean
+         */
+        allowBorderColour: {
+            value: true
+        },
+
+        /**
+         * Whether or not to allow colourizing the background
+         *
+         * @attribute allowBackgroundColour
+         * @type Boolean
+         */
+        allowBackgroundColour: {
+            value: true
+        },
+
+        /**
+         * Whether or not to allow setting the table width
+         *
+         * @attribute allowWidth
+         * @type Boolean
+         */
+        allowWidth: {
+            value: true
+        },
+
+        /**
+         * Whether we allow styling
+         * @attribute allowStyling
+         * @type Boolean
+         */
+        allowStyling: {
+            readOnly: true,
+            getter: function() {
+                return this.get('allowBorders') || this.get('allowBackgroundColour') || this.get('allowWidth');
+            }
+        },
+
+        /**
+         * Available colors
+         * @attribute availableColors
+         * @type Array
+         */
+        availableColors: {
+            value: [
+                '#FFFFFF',
+                '#EF4540',
+                '#FFCF35',
+                '#98CA3E',
+                '#7D9FD3',
+                '#333333'
+            ],
+            readOnly: true
+        }
+    }
 });