src/cm/media/js/lib/yui/yui_3.10.3/build/exec-command/exec-command.js
changeset 525 89ef5ed3c48b
equal deleted inserted replaced
524:322d0feea350 525:89ef5ed3c48b
       
     1 /*
       
     2 YUI 3.10.3 (build 2fb5187)
       
     3 Copyright 2013 Yahoo! Inc. All rights reserved.
       
     4 Licensed under the BSD License.
       
     5 http://yuilibrary.com/license/
       
     6 */
       
     7 
       
     8 YUI.add('exec-command', function (Y, NAME) {
       
     9 
       
    10 
       
    11     /**
       
    12      * Plugin for the frame module to handle execCommands for Editor
       
    13      * @class Plugin.ExecCommand
       
    14      * @extends Base
       
    15      * @constructor
       
    16      * @module editor
       
    17      * @submodule exec-command
       
    18      */
       
    19         var ExecCommand = function() {
       
    20             ExecCommand.superclass.constructor.apply(this, arguments);
       
    21         },
       
    22         /**
       
    23         * This method is meant to normalize IE's in ability to exec the proper command on elements with CSS styling.
       
    24         * @method fixIETags
       
    25         * @protected
       
    26         * @param {String} cmd The command to execute
       
    27         * @param {String} tag The tag to create
       
    28         * @param {String} rule The rule that we are looking for.
       
    29         */
       
    30         fixIETags = function(cmd, tag, rule) {
       
    31             var inst = this.getInstance(),
       
    32                 doc = inst.config.doc,
       
    33                 sel = doc.selection.createRange(),
       
    34                 o = doc.queryCommandValue(cmd),
       
    35                 html, reg, m, p, d, s, c;
       
    36 
       
    37             if (o) {
       
    38                 html = sel.htmlText;
       
    39                 reg = new RegExp(rule, 'g');
       
    40                 m = html.match(reg);
       
    41 
       
    42                 if (m) {
       
    43                     html = html.replace(rule + ';', '').replace(rule, '');
       
    44 
       
    45                     sel.pasteHTML('<var id="yui-ie-bs">');
       
    46 
       
    47                     p = doc.getElementById('yui-ie-bs');
       
    48                     d = doc.createElement('div');
       
    49                     s = doc.createElement(tag);
       
    50 
       
    51                     d.innerHTML = html;
       
    52                     if (p.parentNode !== inst.config.doc.body) {
       
    53                         p = p.parentNode;
       
    54                     }
       
    55 
       
    56                     c = d.childNodes;
       
    57 
       
    58                     p.parentNode.replaceChild(s, p);
       
    59 
       
    60                     Y.each(c, function(f) {
       
    61                         s.appendChild(f);
       
    62                     });
       
    63                     sel.collapse();
       
    64                     if (sel.moveToElementText) {
       
    65                         sel.moveToElementText(s);
       
    66                     }
       
    67                     sel.select();
       
    68                 }
       
    69             }
       
    70             this._command(cmd);
       
    71         };
       
    72 
       
    73         Y.extend(ExecCommand, Y.Base, {
       
    74             /**
       
    75             * An internal reference to the keyCode of the last key that was pressed.
       
    76             * @private
       
    77             * @property _lastKey
       
    78             */
       
    79             _lastKey: null,
       
    80             /**
       
    81             * An internal reference to the instance of the frame plugged into.
       
    82             * @private
       
    83             * @property _inst
       
    84             */
       
    85             _inst: null,
       
    86             /**
       
    87             * Execute a command on the frame's document.
       
    88             * @method command
       
    89             * @param {String} action The action to perform (bold, italic, fontname)
       
    90             * @param {String} value The optional value (helvetica)
       
    91             * @return {Node/NodeList} Should return the Node/Nodelist affected
       
    92             */
       
    93             command: function(action, value) {
       
    94                 var fn = ExecCommand.COMMANDS[action];
       
    95 
       
    96                 if (fn) {
       
    97                     return fn.call(this, action, value);
       
    98                 } else {
       
    99                     return this._command(action, value);
       
   100                 }
       
   101             },
       
   102             /**
       
   103             * The private version of execCommand that doesn't filter for overrides.
       
   104             * @private
       
   105             * @method _command
       
   106             * @param {String} action The action to perform (bold, italic, fontname)
       
   107             * @param {String} value The optional value (helvetica)
       
   108             */
       
   109             _command: function(action, value) {
       
   110                 var inst = this.getInstance();
       
   111                 try {
       
   112                     try {
       
   113                         inst.config.doc.execCommand('styleWithCSS', null, 1);
       
   114                     } catch (e1) {
       
   115                         try {
       
   116                             inst.config.doc.execCommand('useCSS', null, 0);
       
   117                         } catch (e2) {
       
   118                         }
       
   119                     }
       
   120                     inst.config.doc.execCommand(action, null, value);
       
   121                 } catch (e) {
       
   122                 }
       
   123             },
       
   124             /**
       
   125             * Get's the instance of YUI bound to the parent frame
       
   126             * @method getInstance
       
   127             * @return {YUI} The YUI instance bound to the parent frame
       
   128             */
       
   129             getInstance: function() {
       
   130                 if (!this._inst) {
       
   131                     this._inst = this.get('host').getInstance();
       
   132                 }
       
   133                 return this._inst;
       
   134             },
       
   135             initializer: function() {
       
   136                 Y.mix(this.get('host'), {
       
   137                     execCommand: function(action, value) {
       
   138                         return this.exec.command(action, value);
       
   139                     },
       
   140                     _execCommand: function(action, value) {
       
   141                         return this.exec._command(action, value);
       
   142                     }
       
   143                 });
       
   144 
       
   145                 this.get('host').on('dom:keypress', Y.bind(function(e) {
       
   146                     this._lastKey = e.keyCode;
       
   147                 }, this));
       
   148             },
       
   149             _wrapContent: function(str, override) {
       
   150                 var useP = (this.getInstance().host.editorPara && !override ? true : false);
       
   151 
       
   152                 if (useP) {
       
   153                     str = '<p>' + str + '</p>';
       
   154                 } else {
       
   155                     str = str + '<br>';
       
   156                 }
       
   157                 return str;
       
   158             }
       
   159         }, {
       
   160             /**
       
   161             * execCommand
       
   162             * @property NAME
       
   163             * @static
       
   164             */
       
   165             NAME: 'execCommand',
       
   166             /**
       
   167             * exec
       
   168             * @property NS
       
   169             * @static
       
   170             */
       
   171             NS: 'exec',
       
   172             ATTRS: {
       
   173                 host: {
       
   174                     value: false
       
   175                 }
       
   176             },
       
   177             /**
       
   178             * Static object literal of execCommand overrides
       
   179             * @property COMMANDS
       
   180             * @static
       
   181             */
       
   182             COMMANDS: {
       
   183                 /**
       
   184                 * Wraps the content with a new element of type (tag)
       
   185                 * @method COMMANDS.wrap
       
   186                 * @static
       
   187                 * @param {String} cmd The command executed: wrap
       
   188                 * @param {String} tag The tag to wrap the selection with
       
   189                 * @return {NodeList} NodeList of the items touched by this command.
       
   190                 */
       
   191                 wrap: function(cmd, tag) {
       
   192                     var inst = this.getInstance();
       
   193                     return (new inst.EditorSelection()).wrapContent(tag);
       
   194                 },
       
   195                 /**
       
   196                 * Inserts the provided HTML at the cursor, should be a single element.
       
   197                 * @method COMMANDS.inserthtml
       
   198                 * @static
       
   199                 * @param {String} cmd The command executed: inserthtml
       
   200                 * @param {String} html The html to insert
       
   201                 * @return {Node} Node instance of the item touched by this command.
       
   202                 */
       
   203                 inserthtml: function(cmd, html) {
       
   204                     var inst = this.getInstance();
       
   205                     if (inst.EditorSelection.hasCursor() || Y.UA.ie) {
       
   206                         return (new inst.EditorSelection()).insertContent(html);
       
   207                     } else {
       
   208                         this._command('inserthtml', html);
       
   209                     }
       
   210                 },
       
   211                 /**
       
   212                 * Inserts the provided HTML at the cursor, and focuses the cursor afterwards.
       
   213                 * @method COMMANDS.insertandfocus
       
   214                 * @static
       
   215                 * @param {String} cmd The command executed: insertandfocus
       
   216                 * @param {String} html The html to insert
       
   217                 * @return {Node} Node instance of the item touched by this command.
       
   218                 */
       
   219                 insertandfocus: function(cmd, html) {
       
   220                     var inst = this.getInstance(), out, sel;
       
   221                     if (inst.EditorSelection.hasCursor()) {
       
   222                         html += inst.EditorSelection.CURSOR;
       
   223                         out = this.command('inserthtml', html);
       
   224                         sel = new inst.EditorSelection();
       
   225                         sel.focusCursor(true, true);
       
   226                     } else {
       
   227                         this.command('inserthtml', html);
       
   228                     }
       
   229                     return out;
       
   230                 },
       
   231                 /**
       
   232                 * Inserts a BR at the current cursor position
       
   233                 * @method COMMANDS.insertbr
       
   234                 * @static
       
   235                 * @param {String} cmd The command executed: insertbr
       
   236                 */
       
   237                 insertbr: function() {
       
   238                     var inst = this.getInstance(),
       
   239                         sel = new inst.EditorSelection(),
       
   240                         html = '<var>|</var>', last = null,
       
   241                         q = (Y.UA.webkit) ? 'span.Apple-style-span,var' : 'var',
       
   242                         insert = function(n) {
       
   243                             var c = inst.Node.create('<br>');
       
   244                             n.insert(c, 'before');
       
   245                             return c;
       
   246                         };
       
   247 
       
   248                     if (sel._selection.pasteHTML) {
       
   249                         sel._selection.pasteHTML(html);
       
   250                     } else {
       
   251                         this._command('inserthtml', html);
       
   252                     }
       
   253 
       
   254 
       
   255                     inst.all(q).each(function(n) {
       
   256                         var g = true, s;
       
   257                         if (Y.UA.webkit) {
       
   258                             g = false;
       
   259                             if (n.get('innerHTML') === '|') {
       
   260                                 g = true;
       
   261                             }
       
   262                         }
       
   263                         if (g) {
       
   264                             last = insert(n);
       
   265                             if ((!last.previous() || !last.previous().test('br')) && Y.UA.gecko) {
       
   266                                 s = last.cloneNode();
       
   267                                 last.insert(s, 'after');
       
   268                                 last = s;
       
   269                             }
       
   270                             n.remove();
       
   271                         }
       
   272                     });
       
   273                     if (Y.UA.webkit && last) {
       
   274                         insert(last);
       
   275                         sel.selectNode(last);
       
   276                     }
       
   277                 },
       
   278                 /**
       
   279                 * Inserts an image at the cursor position
       
   280                 * @method COMMANDS.insertimage
       
   281                 * @static
       
   282                 * @param {String} cmd The command executed: insertimage
       
   283                 * @param {String} img The url of the image to be inserted
       
   284                 * @return {Node} Node instance of the item touched by this command.
       
   285                 */
       
   286                 insertimage: function(cmd, img) {
       
   287                     return this.command('inserthtml', '<img src="' + img + '">');
       
   288                 },
       
   289                 /**
       
   290                 * Add a class to all of the elements in the selection
       
   291                 * @method COMMANDS.addclass
       
   292                 * @static
       
   293                 * @param {String} cmd The command executed: addclass
       
   294                 * @param {String} cls The className to add
       
   295                 * @return {NodeList} NodeList of the items touched by this command.
       
   296                 */
       
   297                 addclass: function(cmd, cls) {
       
   298                     var inst = this.getInstance();
       
   299                     return (new inst.EditorSelection()).getSelected().addClass(cls);
       
   300                 },
       
   301                 /**
       
   302                 * Remove a class from all of the elements in the selection
       
   303                 * @method COMMANDS.removeclass
       
   304                 * @static
       
   305                 * @param {String} cmd The command executed: removeclass
       
   306                 * @param {String} cls The className to remove
       
   307                 * @return {NodeList} NodeList of the items touched by this command.
       
   308                 */
       
   309                 removeclass: function(cmd, cls) {
       
   310                     var inst = this.getInstance();
       
   311                     return (new inst.EditorSelection()).getSelected().removeClass(cls);
       
   312                 },
       
   313                 /**
       
   314                 * Adds a forecolor to the current selection, or creates a new element and applies it
       
   315                 * @method COMMANDS.forecolor
       
   316                 * @static
       
   317                 * @param {String} cmd The command executed: forecolor
       
   318                 * @param {String} val The color value to apply
       
   319                 * @return {NodeList} NodeList of the items touched by this command.
       
   320                 */
       
   321                 forecolor: function(cmd, val) {
       
   322                     var inst = this.getInstance(),
       
   323                         sel = new inst.EditorSelection(), n;
       
   324 
       
   325                     if (!Y.UA.ie) {
       
   326                         this._command('useCSS', false);
       
   327                     }
       
   328                     if (inst.EditorSelection.hasCursor()) {
       
   329                         if (sel.isCollapsed) {
       
   330                             if (sel.anchorNode && (sel.anchorNode.get('innerHTML') === '&nbsp;')) {
       
   331                                 sel.anchorNode.setStyle('color', val);
       
   332                                 n = sel.anchorNode;
       
   333                             } else {
       
   334                                 n = this.command('inserthtml', '<span style="color: ' + val + '">' + inst.EditorSelection.CURSOR + '</span>');
       
   335                                 sel.focusCursor(true, true);
       
   336                             }
       
   337                             return n;
       
   338                         } else {
       
   339                             return this._command(cmd, val);
       
   340                         }
       
   341                     } else {
       
   342                         this._command(cmd, val);
       
   343                     }
       
   344                 },
       
   345                 /**
       
   346                 * Adds a background color to the current selection, or creates a new element and applies it
       
   347                 * @method COMMANDS.backcolor
       
   348                 * @static
       
   349                 * @param {String} cmd The command executed: backcolor
       
   350                 * @param {String} val The color value to apply
       
   351                 * @return {NodeList} NodeList of the items touched by this command.
       
   352                 */
       
   353                 backcolor: function(cmd, val) {
       
   354                     var inst = this.getInstance(),
       
   355                         sel = new inst.EditorSelection(), n;
       
   356 
       
   357                     if (Y.UA.gecko || Y.UA.opera) {
       
   358                         cmd = 'hilitecolor';
       
   359                     }
       
   360                     if (!Y.UA.ie) {
       
   361                         this._command('useCSS', false);
       
   362                     }
       
   363                     if (inst.EditorSelection.hasCursor()) {
       
   364                         if (sel.isCollapsed) {
       
   365                             if (sel.anchorNode && (sel.anchorNode.get('innerHTML') === '&nbsp;')) {
       
   366                                 sel.anchorNode.setStyle('backgroundColor', val);
       
   367                                 n = sel.anchorNode;
       
   368                             } else {
       
   369                                 n = this.command('inserthtml',
       
   370                                     '<span style="background-color: ' + val + '">' + inst.EditorSelection.CURSOR + '</span>');
       
   371                                 sel.focusCursor(true, true);
       
   372                             }
       
   373                             return n;
       
   374                         } else {
       
   375                             return this._command(cmd, val);
       
   376                         }
       
   377                     } else {
       
   378                         this._command(cmd, val);
       
   379                     }
       
   380                 },
       
   381                 /**
       
   382                 * Sugar method, calles backcolor
       
   383                 * @method COMMANDS.hilitecolor
       
   384                 * @static
       
   385                 * @param {String} cmd The command executed: backcolor
       
   386                 * @param {String} val The color value to apply
       
   387                 * @return {NodeList} NodeList of the items touched by this command.
       
   388                 */
       
   389                 hilitecolor: function() {
       
   390                     return ExecCommand.COMMANDS.backcolor.apply(this, arguments);
       
   391                 },
       
   392                 /**
       
   393                 * Adds a font name to the current selection, or creates a new element and applies it
       
   394                 * @method COMMANDS.fontname2
       
   395                 * @deprecated
       
   396                 * @static
       
   397                 * @param {String} cmd The command executed: fontname
       
   398                 * @param {String} val The font name to apply
       
   399                 * @return {NodeList} NodeList of the items touched by this command.
       
   400                 */
       
   401                 fontname2: function(cmd, val) {
       
   402                     this._command('fontname', val);
       
   403                     var inst = this.getInstance(),
       
   404                         sel = new inst.EditorSelection();
       
   405 
       
   406                     if (sel.isCollapsed && (this._lastKey !== 32)) {
       
   407                         if (sel.anchorNode.test('font')) {
       
   408                             sel.anchorNode.set('face', val);
       
   409                         }
       
   410                     }
       
   411                 },
       
   412                 /**
       
   413                 * Adds a fontsize to the current selection, or creates a new element and applies it
       
   414                 * @method COMMANDS.fontsize2
       
   415                 * @deprecated
       
   416                 * @static
       
   417                 * @param {String} cmd The command executed: fontsize
       
   418                 * @param {String} val The font size to apply
       
   419                 * @return {NodeList} NodeList of the items touched by this command.
       
   420                 */
       
   421                 fontsize2: function(cmd, val) {
       
   422                     this._command('fontsize', val);
       
   423 
       
   424                     var inst = this.getInstance(),
       
   425                         sel = new inst.EditorSelection(), p;
       
   426 
       
   427                     if (sel.isCollapsed && sel.anchorNode && (this._lastKey !== 32)) {
       
   428                         if (Y.UA.webkit) {
       
   429                             if (sel.anchorNode.getStyle('lineHeight')) {
       
   430                                 sel.anchorNode.setStyle('lineHeight', '');
       
   431                             }
       
   432                         }
       
   433                         if (sel.anchorNode.test('font')) {
       
   434                             sel.anchorNode.set('size', val);
       
   435                         } else if (Y.UA.gecko) {
       
   436                             p = sel.anchorNode.ancestor(inst.EditorSelection.DEFAULT_BLOCK_TAG);
       
   437                             if (p) {
       
   438                                 p.setStyle('fontSize', '');
       
   439                             }
       
   440                         }
       
   441                     }
       
   442                 },
       
   443                 /**
       
   444                 * Overload for COMMANDS.list
       
   445                 * @method COMMANDS.insertorderedlist
       
   446                 * @static
       
   447                 * @param {String} cmd The command executed: list, ul
       
   448                 */
       
   449                 insertunorderedlist: function() {
       
   450                     this.command('list', 'ul');
       
   451                 },
       
   452                 /**
       
   453                 * Overload for COMMANDS.list
       
   454                 * @method COMMANDS.insertunorderedlist
       
   455                 * @static
       
   456                 * @param {String} cmd The command executed: list, ol
       
   457                 */
       
   458                 insertorderedlist: function() {
       
   459                     this.command('list', 'ol');
       
   460                 },
       
   461                 /**
       
   462                 * Noramlizes lists creation/destruction for IE. All others pass through to native calls
       
   463                 * @method COMMANDS.list
       
   464                 * @static
       
   465                 * @param {String} cmd The command executed: list (not used)
       
   466                 * @param {String} tag The tag to deal with
       
   467                 */
       
   468                 list: function(cmd, tag) {
       
   469                     var inst = this.getInstance(), html, self = this,
       
   470                         /*
       
   471                         The yui3- class name below is not a skinnable class,
       
   472                         it's a utility class used internally by editor and
       
   473                         stripped when completed, calling getClassName on this
       
   474                         is a waste of resources.
       
   475                         */
       
   476                         DIR = 'dir', cls = 'yui3-touched',
       
   477                         dir, range, div, elm, n, str, s, par, list, lis,
       
   478                         useP = (inst.host.editorPara ? true : false), tmp,
       
   479                         sdir, hasPParent, fc,
       
   480                         sel = new inst.EditorSelection();
       
   481 
       
   482                     cmd = 'insert' + ((tag === 'ul') ? 'un' : '') + 'orderedlist';
       
   483 
       
   484                     if (Y.UA.ie && !sel.isCollapsed) {
       
   485                         range = sel._selection;
       
   486                         html = range.htmlText;
       
   487                         div = inst.Node.create(html) || inst.one('body');
       
   488 
       
   489                         if (div.test('li') || div.one('li')) {
       
   490                             this._command(cmd, null);
       
   491                             return;
       
   492                         }
       
   493                         if (div.test(tag)) {
       
   494                             elm = range.item ? range.item(0) : range.parentElement();
       
   495                             n = inst.one(elm);
       
   496                             lis = n.all('li');
       
   497 
       
   498                             str = '<div>';
       
   499                             lis.each(function(l) {
       
   500                                 str = self._wrapContent(l.get('innerHTML'));
       
   501                             });
       
   502                             str += '</div>';
       
   503                             s = inst.Node.create(str);
       
   504                             if (n.get('parentNode').test('div')) {
       
   505                                 n = n.get('parentNode');
       
   506                             }
       
   507                             if (n && n.hasAttribute(DIR)) {
       
   508                                 if (useP) {
       
   509                                     s.all('p').setAttribute(DIR, n.getAttribute(DIR));
       
   510                                 } else {
       
   511                                     s.setAttribute(DIR, n.getAttribute(DIR));
       
   512                                 }
       
   513                             }
       
   514                             if (useP) {
       
   515                                 n.replace(s.get('innerHTML'));
       
   516                             } else {
       
   517                                 n.replace(s);
       
   518                             }
       
   519                             if (range.moveToElementText) {
       
   520                                 range.moveToElementText(s._node);
       
   521                             }
       
   522                             range.select();
       
   523                         } else {
       
   524                             par = Y.one(range.parentElement());
       
   525                             if (!par.test(inst.EditorSelection.BLOCKS)) {
       
   526                                 par = par.ancestor(inst.EditorSelection.BLOCKS);
       
   527                             }
       
   528                             if (par) {
       
   529                                 if (par.hasAttribute(DIR)) {
       
   530                                     dir = par.getAttribute(DIR);
       
   531                                 }
       
   532                             }
       
   533                             if (html.indexOf('<br>') > -1) {
       
   534                                 html = html.split(/<br>/i);
       
   535                             } else {
       
   536                                 tmp = inst.Node.create(html),
       
   537                                 ps = tmp ? tmp.all('p') : null;
       
   538 
       
   539                                 if (ps && ps.size()) {
       
   540                                     html = [];
       
   541                                     ps.each(function(n) {
       
   542                                         html.push(n.get('innerHTML'));
       
   543                                     });
       
   544                                 } else {
       
   545                                     html = [html];
       
   546                                 }
       
   547                             }
       
   548                             list = '<' + tag + ' id="ie-list">';
       
   549                             Y.each(html, function(v) {
       
   550                                 var a = inst.Node.create(v);
       
   551                                 if (a && a.test('p')) {
       
   552                                     if (a.hasAttribute(DIR)) {
       
   553                                         dir = a.getAttribute(DIR);
       
   554                                     }
       
   555                                     v = a.get('innerHTML');
       
   556                                 }
       
   557                                 list += '<li>' + v + '</li>';
       
   558                             });
       
   559                             list += '</' + tag + '>';
       
   560                             range.pasteHTML(list);
       
   561                             elm = inst.config.doc.getElementById('ie-list');
       
   562                             elm.id = '';
       
   563                             if (dir) {
       
   564                                 elm.setAttribute(DIR, dir);
       
   565                             }
       
   566                             if (range.moveToElementText) {
       
   567                                 range.moveToElementText(elm);
       
   568                             }
       
   569                             range.select();
       
   570                         }
       
   571                     } else if (Y.UA.ie) {
       
   572                         par = inst.one(sel._selection.parentElement());
       
   573                         if (par.test('p')) {
       
   574                             if (par && par.hasAttribute(DIR)) {
       
   575                                 dir = par.getAttribute(DIR);
       
   576                             }
       
   577                             html = Y.EditorSelection.getText(par);
       
   578                             if (html === '') {
       
   579                                 sdir = '';
       
   580                                 if (dir) {
       
   581                                     sdir = ' dir="' + dir + '"';
       
   582                                 }
       
   583                                 list = inst.Node.create(Y.Lang.sub('<{tag}{dir}><li></li></{tag}>', { tag: tag, dir: sdir }));
       
   584                                 par.replace(list);
       
   585                                 sel.selectNode(list.one('li'));
       
   586                             } else {
       
   587                                 this._command(cmd, null);
       
   588                             }
       
   589                         } else {
       
   590                             this._command(cmd, null);
       
   591                         }
       
   592                     } else {
       
   593                         inst.all(tag).addClass(cls);
       
   594                         if (sel.anchorNode.test(inst.EditorSelection.BLOCKS)) {
       
   595                             par = sel.anchorNode;
       
   596                         } else {
       
   597                             par = sel.anchorNode.ancestor(inst.EditorSelection.BLOCKS);
       
   598                         }
       
   599                         if (!par) { //No parent, find the first block under the anchorNode
       
   600                             par = sel.anchorNode.one(inst.EditorSelection.BLOCKS);
       
   601                         }
       
   602 
       
   603                         if (par && par.hasAttribute(DIR)) {
       
   604                             dir = par.getAttribute(DIR);
       
   605                         }
       
   606                         if (par && par.test(tag)) {
       
   607                             hasPParent = par.ancestor('p');
       
   608                             html = inst.Node.create('<div/>');
       
   609                             elm = par.all('li');
       
   610                             elm.each(function(h) {
       
   611                                 html.append(self._wrapContent(h.get('innerHTML'), hasPParent));
       
   612                             });
       
   613                             if (dir) {
       
   614                                 if (useP) {
       
   615                                     html.all('p').setAttribute(DIR, dir);
       
   616                                 } else {
       
   617                                     html.setAttribute(DIR, dir);
       
   618                                 }
       
   619                             }
       
   620                             if (useP) {
       
   621                                 html = inst.Node.create(html.get('innerHTML'));
       
   622                             }
       
   623                             fc = html.get('firstChild');
       
   624                             par.replace(html);
       
   625                             sel.selectNode(fc);
       
   626                         } else {
       
   627                             this._command(cmd, null);
       
   628                         }
       
   629                         list = inst.all(tag);
       
   630                         if (dir) {
       
   631                             if (list.size()) {
       
   632                                 //Changed to a List
       
   633                                 list.each(function(n) {
       
   634                                     if (!n.hasClass(cls)) {
       
   635                                         n.setAttribute(DIR, dir);
       
   636                                     }
       
   637                                 });
       
   638                             }
       
   639                         }
       
   640 
       
   641                         list.removeClass(cls);
       
   642                     }
       
   643                 },
       
   644                 /**
       
   645                 * Noramlizes alignment for Webkit Browsers
       
   646                 * @method COMMANDS.justify
       
   647                 * @static
       
   648                 * @param {String} cmd The command executed: justify (not used)
       
   649                 * @param {String} val The actual command from the justify{center,all,left,right} stubs
       
   650                 */
       
   651                 justify: function(cmd, val) {
       
   652                     if (Y.UA.webkit) {
       
   653                         var inst = this.getInstance(),
       
   654                             sel = new inst.EditorSelection(),
       
   655                             aNode = sel.anchorNode, html,
       
   656                             bgColor = aNode.getStyle('backgroundColor');
       
   657 
       
   658                             this._command(val);
       
   659                             sel = new inst.EditorSelection();
       
   660                             if (sel.anchorNode.test('div')) {
       
   661                                 html = '<span>' + sel.anchorNode.get('innerHTML') + '</span>';
       
   662                                 sel.anchorNode.set('innerHTML', html);
       
   663                                 sel.anchorNode.one('span').setStyle('backgroundColor', bgColor);
       
   664                                 sel.selectNode(sel.anchorNode.one('span'));
       
   665                             }
       
   666                     } else {
       
   667                         this._command(val);
       
   668                     }
       
   669                 },
       
   670                 /**
       
   671                 * Override method for COMMANDS.justify
       
   672                 * @method COMMANDS.justifycenter
       
   673                 * @static
       
   674                 */
       
   675                 justifycenter: function() {
       
   676                     this.command('justify', 'justifycenter');
       
   677                 },
       
   678                 /**
       
   679                 * Override method for COMMANDS.justify
       
   680                 * @method COMMANDS.justifyleft
       
   681                 * @static
       
   682                 */
       
   683                 justifyleft: function() {
       
   684                     this.command('justify', 'justifyleft');
       
   685                 },
       
   686                 /**
       
   687                 * Override method for COMMANDS.justify
       
   688                 * @method COMMANDS.justifyright
       
   689                 * @static
       
   690                 */
       
   691                 justifyright: function() {
       
   692                     this.command('justify', 'justifyright');
       
   693                 },
       
   694                 /**
       
   695                 * Override method for COMMANDS.justify
       
   696                 * @method COMMANDS.justifyfull
       
   697                 * @static
       
   698                 */
       
   699                 justifyfull: function() {
       
   700                     this.command('justify', 'justifyfull');
       
   701                 }
       
   702             }
       
   703         });
       
   704 
       
   705         if (Y.UA.ie) {
       
   706             ExecCommand.COMMANDS.bold = function() {
       
   707                 fixIETags.call(this, 'bold', 'b', 'FONT-WEIGHT: bold');
       
   708             };
       
   709             ExecCommand.COMMANDS.italic = function() {
       
   710                 fixIETags.call(this, 'italic', 'i', 'FONT-STYLE: italic');
       
   711             };
       
   712             ExecCommand.COMMANDS.underline = function() {
       
   713                 fixIETags.call(this, 'underline', 'u', 'TEXT-DECORATION: underline');
       
   714             };
       
   715         }
       
   716 
       
   717         Y.namespace('Plugin');
       
   718         Y.Plugin.ExecCommand = ExecCommand;
       
   719 
       
   720 
       
   721 
       
   722 }, '3.10.3', {"requires": ["frame"]});