API Docs for: 3.8.0
Show:

File: editor/js/exec-command.js


  1.     /**
  2.      * Plugin for the frame module to handle execCommands for Editor
  3.      * @class Plugin.ExecCommand
  4.      * @extends Base
  5.      * @constructor
  6.      * @module editor
  7.      * @submodule exec-command
  8.      */
  9.         var ExecCommand = function() {
  10.             ExecCommand.superclass.constructor.apply(this, arguments);
  11.         },
  12.         /**
  13.         * This method is meant to normalize IE's in ability to exec the proper command on elements with CSS styling.
  14.         * @method fixIETags
  15.         * @protected
  16.         * @param {String} cmd The command to execute
  17.         * @param {String} tag The tag to create
  18.         * @param {String} rule The rule that we are looking for.
  19.         */
  20.         fixIETags = function(cmd, tag, rule) {
  21.             var inst = this.getInstance(),
  22.                 doc = inst.config.doc,
  23.                 sel = doc.selection.createRange(),
  24.                 o = doc.queryCommandValue(cmd),
  25.                 html, reg, m, p, d, s, c;

  26.             if (o) {
  27.                 html = sel.htmlText;
  28.                 reg = new RegExp(rule, 'g');
  29.                 m = html.match(reg);

  30.                 if (m) {
  31.                     html = html.replace(rule + ';', '').replace(rule, '');

  32.                     sel.pasteHTML('<var id="yui-ie-bs">');

  33.                     p = doc.getElementById('yui-ie-bs');
  34.                     d = doc.createElement('div');
  35.                     s = doc.createElement(tag);

  36.                     d.innerHTML = html;
  37.                     if (p.parentNode !== inst.config.doc.body) {
  38.                         p = p.parentNode;
  39.                     }

  40.                     c = d.childNodes;

  41.                     p.parentNode.replaceChild(s, p);

  42.                     Y.each(c, function(f) {
  43.                         s.appendChild(f);
  44.                     });
  45.                     sel.collapse();
  46.                     if (sel.moveToElementText) {
  47.                         sel.moveToElementText(s);
  48.                     }
  49.                     sel.select();
  50.                 }
  51.             }
  52.             this._command(cmd);
  53.         };

  54.         Y.extend(ExecCommand, Y.Base, {
  55.             /**
  56.             * An internal reference to the keyCode of the last key that was pressed.
  57.             * @private
  58.             * @property _lastKey
  59.             */
  60.             _lastKey: null,
  61.             /**
  62.             * An internal reference to the instance of the frame plugged into.
  63.             * @private
  64.             * @property _inst
  65.             */
  66.             _inst: null,
  67.             /**
  68.             * Execute a command on the frame's document.
  69.             * @method command
  70.             * @param {String} action The action to perform (bold, italic, fontname)
  71.             * @param {String} value The optional value (helvetica)
  72.             * @return {Node/NodeList} Should return the Node/Nodelist affected
  73.             */
  74.             command: function(action, value) {
  75.                 var fn = ExecCommand.COMMANDS[action];

  76.                 Y.log('execCommand(' + action + '): "' + value + '"', 'info', 'exec-command');
  77.                 if (fn) {
  78.                     Y.log('OVERIDE execCommand(' + action + '): "' + value + '"', 'info', 'exec-command');
  79.                     return fn.call(this, action, value);
  80.                 } else {
  81.                     return this._command(action, value);
  82.                 }
  83.             },
  84.             /**
  85.             * The private version of execCommand that doesn't filter for overrides.
  86.             * @private
  87.             * @method _command
  88.             * @param {String} action The action to perform (bold, italic, fontname)
  89.             * @param {String} value The optional value (helvetica)
  90.             */
  91.             _command: function(action, value) {
  92.                 var inst = this.getInstance();
  93.                 try {
  94.                     try {
  95.                         inst.config.doc.execCommand('styleWithCSS', null, 1);
  96.                     } catch (e1) {
  97.                         try {
  98.                             inst.config.doc.execCommand('useCSS', null, 0);
  99.                         } catch (e2) {
  100.                         }
  101.                     }
  102.                     Y.log('Using default browser execCommand(' + action + '): "' + value + '"', 'info', 'exec-command');
  103.                     inst.config.doc.execCommand(action, null, value);
  104.                 } catch (e) {
  105.                     Y.log(e.message, 'warn', 'exec-command');
  106.                 }
  107.             },
  108.             /**
  109.             * Get's the instance of YUI bound to the parent frame
  110.             * @method getInstance
  111.             * @return {YUI} The YUI instance bound to the parent frame
  112.             */
  113.             getInstance: function() {
  114.                 if (!this._inst) {
  115.                     this._inst = this.get('host').getInstance();
  116.                 }
  117.                 return this._inst;
  118.             },
  119.             initializer: function() {
  120.                 Y.mix(this.get('host'), {
  121.                     execCommand: function(action, value) {
  122.                         return this.exec.command(action, value);
  123.                     },
  124.                     _execCommand: function(action, value) {
  125.                         return this.exec._command(action, value);
  126.                     }
  127.                 });

  128.                 this.get('host').on('dom:keypress', Y.bind(function(e) {
  129.                     this._lastKey = e.keyCode;
  130.                 }, this));
  131.             },
  132.             _wrapContent: function(str, override) {
  133.                 var useP = (this.getInstance().host.editorPara && !override ? true : false);

  134.                 if (useP) {
  135.                     str = '<p>' + str + '</p>';
  136.                 } else {
  137.                     str = str + '<br>';
  138.                 }
  139.                 return str;
  140.             }
  141.         }, {
  142.             /**
  143.             * execCommand
  144.             * @property NAME
  145.             * @static
  146.             */
  147.             NAME: 'execCommand',
  148.             /**
  149.             * exec
  150.             * @property NS
  151.             * @static
  152.             */
  153.             NS: 'exec',
  154.             ATTRS: {
  155.                 host: {
  156.                     value: false
  157.                 }
  158.             },
  159.             /**
  160.             * Static object literal of execCommand overrides
  161.             * @property COMMANDS
  162.             * @static
  163.             */
  164.             COMMANDS: {
  165.                 /**
  166.                 * Wraps the content with a new element of type (tag)
  167.                 * @method COMMANDS.wrap
  168.                 * @static
  169.                 * @param {String} cmd The command executed: wrap
  170.                 * @param {String} tag The tag to wrap the selection with
  171.                 * @return {NodeList} NodeList of the items touched by this command.
  172.                 */
  173.                 wrap: function(cmd, tag) {
  174.                     var inst = this.getInstance();
  175.                     return (new inst.EditorSelection()).wrapContent(tag);
  176.                 },
  177.                 /**
  178.                 * Inserts the provided HTML at the cursor, should be a single element.
  179.                 * @method COMMANDS.inserthtml
  180.                 * @static
  181.                 * @param {String} cmd The command executed: inserthtml
  182.                 * @param {String} html The html to insert
  183.                 * @return {Node} Node instance of the item touched by this command.
  184.                 */
  185.                 inserthtml: function(cmd, html) {
  186.                     var inst = this.getInstance();
  187.                     if (inst.EditorSelection.hasCursor() || Y.UA.ie) {
  188.                         return (new inst.EditorSelection()).insertContent(html);
  189.                     } else {
  190.                         this._command('inserthtml', html);
  191.                     }
  192.                 },
  193.                 /**
  194.                 * Inserts the provided HTML at the cursor, and focuses the cursor afterwards.
  195.                 * @method COMMANDS.insertandfocus
  196.                 * @static
  197.                 * @param {String} cmd The command executed: insertandfocus
  198.                 * @param {String} html The html to insert
  199.                 * @return {Node} Node instance of the item touched by this command.
  200.                 */
  201.                 insertandfocus: function(cmd, html) {
  202.                     var inst = this.getInstance(), out, sel;
  203.                     if (inst.EditorSelection.hasCursor()) {
  204.                         html += inst.EditorSelection.CURSOR;
  205.                         out = this.command('inserthtml', html);
  206.                         sel = new inst.EditorSelection();
  207.                         sel.focusCursor(true, true);
  208.                     } else {
  209.                         this.command('inserthtml', html);
  210.                     }
  211.                     return out;
  212.                 },
  213.                 /**
  214.                 * Inserts a BR at the current cursor position
  215.                 * @method COMMANDS.insertbr
  216.                 * @static
  217.                 * @param {String} cmd The command executed: insertbr
  218.                 */
  219.                 insertbr: function() {
  220.                     var inst = this.getInstance(),
  221.                         sel = new inst.EditorSelection(),
  222.                         html = '<var>|</var>', last = null,
  223.                         q = (Y.UA.webkit) ? 'span.Apple-style-span,var' : 'var',
  224.                         insert = function(n) {
  225.                             var c = inst.Node.create('<br>');
  226.                             n.insert(c, 'before');
  227.                             return c;
  228.                         };

  229.                     if (sel._selection.pasteHTML) {
  230.                         sel._selection.pasteHTML(html);
  231.                     } else {
  232.                         this._command('inserthtml', html);
  233.                     }


  234.                     inst.all(q).each(function(n) {
  235.                         var g = true, s;
  236.                         if (Y.UA.webkit) {
  237.                             g = false;
  238.                             if (n.get('innerHTML') === '|') {
  239.                                 g = true;
  240.                             }
  241.                         }
  242.                         if (g) {
  243.                             last = insert(n);
  244.                             if ((!last.previous() || !last.previous().test('br')) && Y.UA.gecko) {
  245.                                 s = last.cloneNode();
  246.                                 last.insert(s, 'after');
  247.                                 last = s;
  248.                             }
  249.                             n.remove();
  250.                         }
  251.                     });
  252.                     if (Y.UA.webkit && last) {
  253.                         insert(last);
  254.                         sel.selectNode(last);
  255.                     }
  256.                 },
  257.                 /**
  258.                 * Inserts an image at the cursor position
  259.                 * @method COMMANDS.insertimage
  260.                 * @static
  261.                 * @param {String} cmd The command executed: insertimage
  262.                 * @param {String} img The url of the image to be inserted
  263.                 * @return {Node} Node instance of the item touched by this command.
  264.                 */
  265.                 insertimage: function(cmd, img) {
  266.                     return this.command('inserthtml', '<img src="' + img + '">');
  267.                 },
  268.                 /**
  269.                 * Add a class to all of the elements in the selection
  270.                 * @method COMMANDS.addclass
  271.                 * @static
  272.                 * @param {String} cmd The command executed: addclass
  273.                 * @param {String} cls The className to add
  274.                 * @return {NodeList} NodeList of the items touched by this command.
  275.                 */
  276.                 addclass: function(cmd, cls) {
  277.                     var inst = this.getInstance();
  278.                     return (new inst.EditorSelection()).getSelected().addClass(cls);
  279.                 },
  280.                 /**
  281.                 * Remove a class from all of the elements in the selection
  282.                 * @method COMMANDS.removeclass
  283.                 * @static
  284.                 * @param {String} cmd The command executed: removeclass
  285.                 * @param {String} cls The className to remove
  286.                 * @return {NodeList} NodeList of the items touched by this command.
  287.                 */
  288.                 removeclass: function(cmd, cls) {
  289.                     var inst = this.getInstance();
  290.                     return (new inst.EditorSelection()).getSelected().removeClass(cls);
  291.                 },
  292.                 /**
  293.                 * Adds a forecolor to the current selection, or creates a new element and applies it
  294.                 * @method COMMANDS.forecolor
  295.                 * @static
  296.                 * @param {String} cmd The command executed: forecolor
  297.                 * @param {String} val The color value to apply
  298.                 * @return {NodeList} NodeList of the items touched by this command.
  299.                 */
  300.                 forecolor: function(cmd, val) {
  301.                     var inst = this.getInstance(),
  302.                         sel = new inst.EditorSelection(), n;

  303.                     if (!Y.UA.ie) {
  304.                         this._command('useCSS', false);
  305.                     }
  306.                     if (inst.EditorSelection.hasCursor()) {
  307.                         if (sel.isCollapsed) {
  308.                             if (sel.anchorNode && (sel.anchorNode.get('innerHTML') === '&nbsp;')) {
  309.                                 sel.anchorNode.setStyle('color', val);
  310.                                 n = sel.anchorNode;
  311.                             } else {
  312.                                 n = this.command('inserthtml', '<span style="color: ' + val + '">' + inst.EditorSelection.CURSOR + '</span>');
  313.                                 sel.focusCursor(true, true);
  314.                             }
  315.                             return n;
  316.                         } else {
  317.                             return this._command(cmd, val);
  318.                         }
  319.                     } else {
  320.                         this._command(cmd, val);
  321.                     }
  322.                 },
  323.                 /**
  324.                 * Adds a background color to the current selection, or creates a new element and applies it
  325.                 * @method COMMANDS.backcolor
  326.                 * @static
  327.                 * @param {String} cmd The command executed: backcolor
  328.                 * @param {String} val The color value to apply
  329.                 * @return {NodeList} NodeList of the items touched by this command.
  330.                 */
  331.                 backcolor: function(cmd, val) {
  332.                     var inst = this.getInstance(),
  333.                         sel = new inst.EditorSelection(), n;

  334.                     if (Y.UA.gecko || Y.UA.opera) {
  335.                         cmd = 'hilitecolor';
  336.                     }
  337.                     if (!Y.UA.ie) {
  338.                         this._command('useCSS', false);
  339.                     }
  340.                     if (inst.EditorSelection.hasCursor()) {
  341.                         if (sel.isCollapsed) {
  342.                             if (sel.anchorNode && (sel.anchorNode.get('innerHTML') === '&nbsp;')) {
  343.                                 sel.anchorNode.setStyle('backgroundColor', val);
  344.                                 n = sel.anchorNode;
  345.                             } else {
  346.                                 n = this.command('inserthtml',
  347.                                     '<span style="background-color: ' + val + '">' + inst.EditorSelection.CURSOR + '</span>');
  348.                                 sel.focusCursor(true, true);
  349.                             }
  350.                             return n;
  351.                         } else {
  352.                             return this._command(cmd, val);
  353.                         }
  354.                     } else {
  355.                         this._command(cmd, val);
  356.                     }
  357.                 },
  358.                 /**
  359.                 * Sugar method, calles backcolor
  360.                 * @method COMMANDS.hilitecolor
  361.                 * @static
  362.                 * @param {String} cmd The command executed: backcolor
  363.                 * @param {String} val The color value to apply
  364.                 * @return {NodeList} NodeList of the items touched by this command.
  365.                 */
  366.                 hilitecolor: function() {
  367.                     return ExecCommand.COMMANDS.backcolor.apply(this, arguments);
  368.                 },
  369.                 /**
  370.                 * Adds a font name to the current selection, or creates a new element and applies it
  371.                 * @method COMMANDS.fontname2
  372.                 * @deprecated
  373.                 * @static
  374.                 * @param {String} cmd The command executed: fontname
  375.                 * @param {String} val The font name to apply
  376.                 * @return {NodeList} NodeList of the items touched by this command.
  377.                 */
  378.                 fontname2: function(cmd, val) {
  379.                     this._command('fontname', val);
  380.                     var inst = this.getInstance(),
  381.                         sel = new inst.EditorSelection();

  382.                     if (sel.isCollapsed && (this._lastKey !== 32)) {
  383.                         if (sel.anchorNode.test('font')) {
  384.                             sel.anchorNode.set('face', val);
  385.                         }
  386.                     }
  387.                 },
  388.                 /**
  389.                 * Adds a fontsize to the current selection, or creates a new element and applies it
  390.                 * @method COMMANDS.fontsize2
  391.                 * @deprecated
  392.                 * @static
  393.                 * @param {String} cmd The command executed: fontsize
  394.                 * @param {String} val The font size to apply
  395.                 * @return {NodeList} NodeList of the items touched by this command.
  396.                 */
  397.                 fontsize2: function(cmd, val) {
  398.                     this._command('fontsize', val);

  399.                     var inst = this.getInstance(),
  400.                         sel = new inst.EditorSelection(), p;

  401.                     if (sel.isCollapsed && sel.anchorNode && (this._lastKey !== 32)) {
  402.                         if (Y.UA.webkit) {
  403.                             if (sel.anchorNode.getStyle('lineHeight')) {
  404.                                 sel.anchorNode.setStyle('lineHeight', '');
  405.                             }
  406.                         }
  407.                         if (sel.anchorNode.test('font')) {
  408.                             sel.anchorNode.set('size', val);
  409.                         } else if (Y.UA.gecko) {
  410.                             p = sel.anchorNode.ancestor(inst.EditorSelection.DEFAULT_BLOCK_TAG);
  411.                             if (p) {
  412.                                 p.setStyle('fontSize', '');
  413.                             }
  414.                         }
  415.                     }
  416.                 },
  417.                 /**
  418.                 * Overload for COMMANDS.list
  419.                 * @method COMMANDS.insertorderedlist
  420.                 * @static
  421.                 * @param {String} cmd The command executed: list, ul
  422.                 */
  423.                 insertunorderedlist: function() {
  424.                     this.command('list', 'ul');
  425.                 },
  426.                 /**
  427.                 * Overload for COMMANDS.list
  428.                 * @method COMMANDS.insertunorderedlist
  429.                 * @static
  430.                 * @param {String} cmd The command executed: list, ol
  431.                 */
  432.                 insertorderedlist: function() {
  433.                     this.command('list', 'ol');
  434.                 },
  435.                 /**
  436.                 * Noramlizes lists creation/destruction for IE. All others pass through to native calls
  437.                 * @method COMMANDS.list
  438.                 * @static
  439.                 * @param {String} cmd The command executed: list (not used)
  440.                 * @param {String} tag The tag to deal with
  441.                 */
  442.                 list: function(cmd, tag) {
  443.                     var inst = this.getInstance(), html, self = this,
  444.                         /*
  445.                         The yui3- class name below is not a skinnable class,
  446.                         it's a utility class used internally by editor and
  447.                         stripped when completed, calling getClassName on this
  448.                         is a waste of resources.
  449.                         */
  450.                         DIR = 'dir', cls = 'yui3-touched',
  451.                         dir, range, div, elm, n, str, s, par, list, lis,
  452.                         useP = (inst.host.editorPara ? true : false), tmp,
  453.                         sdir, hasPParent, fc,
  454.                         sel = new inst.EditorSelection();

  455.                     cmd = 'insert' + ((tag === 'ul') ? 'un' : '') + 'orderedlist';

  456.                     if (Y.UA.ie && !sel.isCollapsed) {
  457.                         range = sel._selection;
  458.                         html = range.htmlText;
  459.                         div = inst.Node.create(html) || inst.one('body');

  460.                         if (div.test('li') || div.one('li')) {
  461.                             this._command(cmd, null);
  462.                             return;
  463.                         }
  464.                         if (div.test(tag)) {
  465.                             elm = range.item ? range.item(0) : range.parentElement();
  466.                             n = inst.one(elm);
  467.                             lis = n.all('li');

  468.                             str = '<div>';
  469.                             lis.each(function(l) {
  470.                                 str = self._wrapContent(l.get('innerHTML'));
  471.                             });
  472.                             str += '</div>';
  473.                             s = inst.Node.create(str);
  474.                             if (n.get('parentNode').test('div')) {
  475.                                 n = n.get('parentNode');
  476.                             }
  477.                             if (n && n.hasAttribute(DIR)) {
  478.                                 if (useP) {
  479.                                     s.all('p').setAttribute(DIR, n.getAttribute(DIR));
  480.                                 } else {
  481.                                     s.setAttribute(DIR, n.getAttribute(DIR));
  482.                                 }
  483.                             }
  484.                             if (useP) {
  485.                                 n.replace(s.get('innerHTML'));
  486.                             } else {
  487.                                 n.replace(s);
  488.                             }
  489.                             if (range.moveToElementText) {
  490.                                 range.moveToElementText(s._node);
  491.                             }
  492.                             range.select();
  493.                         } else {
  494.                             par = Y.one(range.parentElement());
  495.                             if (!par.test(inst.EditorSelection.BLOCKS)) {
  496.                                 par = par.ancestor(inst.EditorSelection.BLOCKS);
  497.                             }
  498.                             if (par) {
  499.                                 if (par.hasAttribute(DIR)) {
  500.                                     dir = par.getAttribute(DIR);
  501.                                 }
  502.                             }
  503.                             if (html.indexOf('<br>') > -1) {
  504.                                 html = html.split(/<br>/i);
  505.                             } else {
  506.                                 tmp = inst.Node.create(html),
  507.                                 ps = tmp ? tmp.all('p') : null;

  508.                                 if (ps && ps.size()) {
  509.                                     html = [];
  510.                                     ps.each(function(n) {
  511.                                         html.push(n.get('innerHTML'));
  512.                                     });
  513.                                 } else {
  514.                                     html = [html];
  515.                                 }
  516.                             }
  517.                             list = '<' + tag + ' id="ie-list">';
  518.                             Y.each(html, function(v) {
  519.                                 var a = inst.Node.create(v);
  520.                                 if (a && a.test('p')) {
  521.                                     if (a.hasAttribute(DIR)) {
  522.                                         dir = a.getAttribute(DIR);
  523.                                     }
  524.                                     v = a.get('innerHTML');
  525.                                 }
  526.                                 list += '<li>' + v + '</li>';
  527.                             });
  528.                             list += '</' + tag + '>';
  529.                             range.pasteHTML(list);
  530.                             elm = inst.config.doc.getElementById('ie-list');
  531.                             elm.id = '';
  532.                             if (dir) {
  533.                                 elm.setAttribute(DIR, dir);
  534.                             }
  535.                             if (range.moveToElementText) {
  536.                                 range.moveToElementText(elm);
  537.                             }
  538.                             range.select();
  539.                         }
  540.                     } else if (Y.UA.ie) {
  541.                         par = inst.one(sel._selection.parentElement());
  542.                         if (par.test('p')) {
  543.                             if (par && par.hasAttribute(DIR)) {
  544.                                 dir = par.getAttribute(DIR);
  545.                             }
  546.                             html = Y.EditorSelection.getText(par);
  547.                             if (html === '') {
  548.                                 sdir = '';
  549.                                 if (dir) {
  550.                                     sdir = ' dir="' + dir + '"';
  551.                                 }
  552.                                 list = inst.Node.create(Y.Lang.sub('<{tag}{dir}><li></li></{tag}>', { tag: tag, dir: sdir }));
  553.                                 par.replace(list);
  554.                                 sel.selectNode(list.one('li'));
  555.                             } else {
  556.                                 this._command(cmd, null);
  557.                             }
  558.                         } else {
  559.                             this._command(cmd, null);
  560.                         }
  561.                     } else {
  562.                         inst.all(tag).addClass(cls);
  563.                         if (sel.anchorNode.test(inst.EditorSelection.BLOCKS)) {
  564.                             par = sel.anchorNode;
  565.                         } else {
  566.                             par = sel.anchorNode.ancestor(inst.EditorSelection.BLOCKS);
  567.                         }
  568.                         if (!par) { //No parent, find the first block under the anchorNode
  569.                             par = sel.anchorNode.one(inst.EditorSelection.BLOCKS);
  570.                         }

  571.                         if (par && par.hasAttribute(DIR)) {
  572.                             dir = par.getAttribute(DIR);
  573.                         }
  574.                         if (par && par.test(tag)) {
  575.                             hasPParent = par.ancestor('p');
  576.                             html = inst.Node.create('<div/>');
  577.                             elm = par.all('li');
  578.                             elm.each(function(h) {
  579.                                 html.append(self._wrapContent(h.get('innerHTML'), hasPParent));
  580.                             });
  581.                             if (dir) {
  582.                                 if (useP) {
  583.                                     html.all('p').setAttribute(DIR, dir);
  584.                                 } else {
  585.                                     html.setAttribute(DIR, dir);
  586.                                 }
  587.                             }
  588.                             if (useP) {
  589.                                 html = inst.Node.create(html.get('innerHTML'));
  590.                             }
  591.                             fc = html.get('firstChild');
  592.                             par.replace(html);
  593.                             sel.selectNode(fc);
  594.                         } else {
  595.                             this._command(cmd, null);
  596.                         }
  597.                         list = inst.all(tag);
  598.                         if (dir) {
  599.                             if (list.size()) {
  600.                                 //Changed to a List
  601.                                 list.each(function(n) {
  602.                                     if (!n.hasClass(cls)) {
  603.                                         n.setAttribute(DIR, dir);
  604.                                     }
  605.                                 });
  606.                             }
  607.                         }

  608.                         list.removeClass(cls);
  609.                     }
  610.                 },
  611.                 /**
  612.                 * Noramlizes alignment for Webkit Browsers
  613.                 * @method COMMANDS.justify
  614.                 * @static
  615.                 * @param {String} cmd The command executed: justify (not used)
  616.                 * @param {String} val The actual command from the justify{center,all,left,right} stubs
  617.                 */
  618.                 justify: function(cmd, val) {
  619.                     if (Y.UA.webkit) {
  620.                         var inst = this.getInstance(),
  621.                             sel = new inst.EditorSelection(),
  622.                             aNode = sel.anchorNode, html,
  623.                             bgColor = aNode.getStyle('backgroundColor');

  624.                             this._command(val);
  625.                             sel = new inst.EditorSelection();
  626.                             if (sel.anchorNode.test('div')) {
  627.                                 html = '<span>' + sel.anchorNode.get('innerHTML') + '</span>';
  628.                                 sel.anchorNode.set('innerHTML', html);
  629.                                 sel.anchorNode.one('span').setStyle('backgroundColor', bgColor);
  630.                                 sel.selectNode(sel.anchorNode.one('span'));
  631.                             }
  632.                     } else {
  633.                         this._command(val);
  634.                     }
  635.                 },
  636.                 /**
  637.                 * Override method for COMMANDS.justify
  638.                 * @method COMMANDS.justifycenter
  639.                 * @static
  640.                 */
  641.                 justifycenter: function() {
  642.                     this.command('justify', 'justifycenter');
  643.                 },
  644.                 /**
  645.                 * Override method for COMMANDS.justify
  646.                 * @method COMMANDS.justifyleft
  647.                 * @static
  648.                 */
  649.                 justifyleft: function() {
  650.                     this.command('justify', 'justifyleft');
  651.                 },
  652.                 /**
  653.                 * Override method for COMMANDS.justify
  654.                 * @method COMMANDS.justifyright
  655.                 * @static
  656.                 */
  657.                 justifyright: function() {
  658.                     this.command('justify', 'justifyright');
  659.                 },
  660.                 /**
  661.                 * Override method for COMMANDS.justify
  662.                 * @method COMMANDS.justifyfull
  663.                 * @static
  664.                 */
  665.                 justifyfull: function() {
  666.                     this.command('justify', 'justifyfull');
  667.                 }
  668.             }
  669.         });

  670.         if (Y.UA.ie) {
  671.             ExecCommand.COMMANDS.bold = function() {
  672.                 fixIETags.call(this, 'bold', 'b', 'FONT-WEIGHT: bold');
  673.             };
  674.             ExecCommand.COMMANDS.italic = function() {
  675.                 fixIETags.call(this, 'italic', 'i', 'FONT-STYLE: italic');
  676.             };
  677.             ExecCommand.COMMANDS.underline = function() {
  678.                 fixIETags.call(this, 'underline', 'u', 'TEXT-DECORATION: underline');
  679.             };
  680.         }

  681.         Y.namespace('Plugin');
  682.         Y.Plugin.ExecCommand = ExecCommand;


  683.