Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

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