[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/lib/yuilib/3.17.2/editor-base/ -> editor-base.js (source)

   1  /*
   2  YUI 3.17.2 (build 9c3c78e)
   3  Copyright 2014 Yahoo! Inc. All rights reserved.
   4  Licensed under the BSD License.
   5  http://yuilibrary.com/license/
   6  */
   7  
   8  YUI.add('editor-base', function (Y, NAME) {
   9  
  10  
  11      /**
  12       * Base class for Editor. Handles the business logic of Editor, no GUI involved only utility methods and events.
  13       *
  14       *      var editor = new Y.EditorBase({
  15       *          content: 'Foo'
  16       *      });
  17       *      editor.render('#demo');
  18       *
  19       * @class EditorBase
  20       * @extends Base
  21       * @module editor
  22       * @main editor
  23       * @submodule editor-base
  24       * @constructor
  25       */
  26  
  27      var Lang = Y.Lang,
  28  
  29      EditorBase = function() {
  30          EditorBase.superclass.constructor.apply(this, arguments);
  31      }, LAST_CHILD = ':last-child';
  32  
  33      Y.extend(EditorBase, Y.Base, {
  34          /**
  35          * Internal reference to the Y.ContentEditable instance
  36          * @property frame
  37          */
  38          frame: null,
  39  
  40          initializer: function() {
  41              this.publish('nodeChange', {
  42                  emitFacade: true,
  43                  bubbles: true,
  44                  defaultFn: this._defNodeChangeFn
  45              });
  46  
  47              //this.plug(Y.Plugin.EditorPara);
  48          },
  49          destructor: function() {
  50              this.detachAll();
  51          },
  52          /**
  53          * Copy certain styles from one node instance to another (used for new paragraph creation mainly)
  54          * @method copyStyles
  55          * @param {Node} from The Node instance to copy the styles from
  56          * @param {Node} to The Node instance to copy the styles to
  57          */
  58          copyStyles: function(from, to) {
  59              if (from.test('a')) {
  60                  //Don't carry the A styles
  61                  return;
  62              }
  63              var styles = ['color', 'fontSize', 'fontFamily', 'backgroundColor', 'fontStyle' ],
  64                  newStyles = {};
  65  
  66              Y.each(styles, function(v) {
  67                  newStyles[v] = from.getStyle(v);
  68              });
  69              if (from.ancestor('b,strong')) {
  70                  newStyles.fontWeight = 'bold';
  71              }
  72              if (from.ancestor('u')) {
  73                  if (!newStyles.textDecoration) {
  74                      newStyles.textDecoration = 'underline';
  75                  }
  76              }
  77              to.setStyles(newStyles);
  78          },
  79          /**
  80          * Holder for the selection bookmark in IE.
  81          * @property _lastBookmark
  82          * @private
  83          */
  84          _lastBookmark: null,
  85          /**
  86          * Resolves the e.changedNode in the nodeChange event if it comes from the document. If
  87          * the event came from the document, it will get the last child of the last child of the document
  88          * and return that instead.
  89          * @method _resolveChangedNode
  90          * @param {Node} n The node to resolve
  91          * @private
  92          */
  93          _resolveChangedNode: function(n) {
  94              var inst = this.getInstance(), lc, lc2, found, root = this._getRoot(), sel;
  95  
  96              if (n && n.compareTo(root)) {
  97                  sel = new inst.EditorSelection();
  98                  if (sel && sel.anchorNode) {
  99                      n = sel.anchorNode;
 100                  }
 101              }
 102              if (inst && n && n.test('html')) {
 103                  lc = root.one(LAST_CHILD);
 104                  while (!found) {
 105                      if (lc) {
 106                          lc2 = lc.one(LAST_CHILD);
 107                          if (lc2) {
 108                              lc = lc2;
 109                          } else {
 110                              found = true;
 111                          }
 112                      } else {
 113                          found = true;
 114                      }
 115                  }
 116                  if (lc) {
 117                      if (lc.test('br')) {
 118                          if (lc.previous()) {
 119                              lc = lc.previous();
 120                          } else {
 121                              lc = lc.get('parentNode');
 122                          }
 123                      }
 124                      if (lc) {
 125                          n = lc;
 126                      }
 127                  }
 128              }
 129              if (!n) {
 130                  //Fallback to make sure a node is attached to the event
 131                  n = root;
 132              }
 133              return n;
 134          },
 135          /**
 136          * Resolves the ROOT editor element.
 137          * @method _getRoot
 138          * @private
 139          */
 140          _getRoot: function() {
 141              return this.getInstance().EditorSelection.ROOT;
 142          },
 143          /**
 144          * The default handler for the nodeChange event.
 145          * @method _defNodeChangeFn
 146          * @param {Event} e The event
 147          * @private
 148          */
 149          _defNodeChangeFn: function(e) {
 150              var startTime = (new Date()).getTime(),
 151                  inst = this.getInstance(), sel,
 152                  changed, endTime,
 153                  cmds = {}, family, fsize, classes = [],
 154                  fColor = '', bColor = '', bq,
 155                  normal = false,
 156                  root = this._getRoot();
 157  
 158              if (Y.UA.ie && Y.UA.ie < 11) {
 159                  try {
 160                      sel = inst.config.doc.selection.createRange();
 161                      if (sel.getBookmark) {
 162                          this._lastBookmark = sel.getBookmark();
 163                      }
 164                  } catch (ie) {}
 165              }
 166  
 167              e.changedNode = this._resolveChangedNode(e.changedNode);
 168  
 169  
 170              /*
 171              * @TODO
 172              * This whole method needs to be fixed and made more dynamic.
 173              * Maybe static functions for the e.changeType and an object bag
 174              * to walk through and filter to pass off the event to before firing..
 175              */
 176  
 177              switch (e.changedType) {
 178                  case 'tab':
 179                      if (!e.changedNode.test('li, li *') && !e.changedEvent.shiftKey) {
 180                          e.changedEvent.frameEvent.preventDefault();
 181                          if (Y.UA.webkit) {
 182                              this.execCommand('inserttext', '\t');
 183                          } else if (Y.UA.gecko) {
 184                              this.frame.exec._command('inserthtml', EditorBase.TABKEY);
 185                          } else if (Y.UA.ie) {
 186                              this.execCommand('inserthtml', EditorBase.TABKEY);
 187                          }
 188                      }
 189                      break;
 190                  case 'backspace-up':
 191                      // Fixes #2531090 - Joins text node strings so they become one for bidi
 192                      if (Y.UA.webkit && e.changedNode) {
 193                          e.changedNode.set('innerHTML', e.changedNode.get('innerHTML'));
 194                      }
 195                      break;
 196              }
 197              if (Y.UA.webkit && e.commands && (e.commands.indent || e.commands.outdent)) {
 198                  /*
 199                  * When executing execCommand 'indent or 'outdent' Webkit applies
 200                  * a class to the BLOCKQUOTE that adds left/right margin to it
 201                  * This strips that style so it is just a normal BLOCKQUOTE
 202                  */
 203                  bq = root.all('.webkit-indent-blockquote, blockquote');
 204                  if (bq.size()) {
 205                      bq.setStyle('margin', '');
 206                  }
 207              }
 208  
 209              changed = this.getDomPath(e.changedNode, false);
 210  
 211              if (e.commands) {
 212                  cmds = e.commands;
 213              }
 214  
 215  
 216              Y.each(changed, function(el) {
 217                  var tag = el.tagName.toLowerCase(),
 218                      cmd = EditorBase.TAG2CMD[tag], s,
 219                      n, family2, cls, bColor2;
 220  
 221                  if (cmd) {
 222                      cmds[cmd] = 1;
 223                  }
 224  
 225                  //Bold and Italic styles
 226                  s = el.currentStyle || el.style;
 227  
 228                  if ((''+s.fontWeight) === 'normal') {
 229                      normal = true;
 230                  }
 231                  if ((''+s.fontWeight) === 'bold') { //Cast this to a string
 232                      cmds.bold = 1;
 233                  }
 234                  if (Y.UA.ie) {
 235                      if (s.fontWeight > 400) {
 236                          cmds.bold = 1;
 237                      }
 238                  }
 239                  if (s.fontStyle === 'italic') {
 240                      cmds.italic = 1;
 241                  }
 242  
 243                  if (s.textDecoration.indexOf('underline') > -1) {
 244                      cmds.underline = 1;
 245                  }
 246                  if (s.textDecoration.indexOf('line-through') > -1) {
 247                      cmds.strikethrough = 1;
 248                  }
 249  
 250                  n = inst.one(el);
 251                  if (n.getStyle('fontFamily')) {
 252                      family2 = n.getStyle('fontFamily').split(',')[0].toLowerCase();
 253                      if (family2) {
 254                          family = family2;
 255                      }
 256                      if (family) {
 257                          family = family.replace(/'/g, '').replace(/"/g, '');
 258                      }
 259                  }
 260  
 261                  fsize = EditorBase.NORMALIZE_FONTSIZE(n);
 262  
 263  
 264                  cls = el.className.split(' ');
 265                  Y.each(cls, function(v) {
 266                      if (v !== '' && (v.substr(0, 4) !== 'yui_')) {
 267                          classes.push(v);
 268                      }
 269                  });
 270  
 271                  fColor = EditorBase.FILTER_RGB(n.getStyle('color'));
 272                  bColor2 = EditorBase.FILTER_RGB(s.backgroundColor);
 273                  if (bColor2 !== 'transparent') {
 274                      if (bColor2 !== '') {
 275                          bColor = bColor2;
 276                      }
 277                  }
 278  
 279              });
 280  
 281              if (normal) {
 282                  delete cmds.bold;
 283                  delete cmds.italic;
 284              }
 285  
 286              e.dompath = inst.all(changed);
 287              e.classNames = classes;
 288              e.commands = cmds;
 289  
 290              //TODO Dont' like this, not dynamic enough..
 291              if (!e.fontFamily) {
 292                  e.fontFamily = family;
 293              }
 294              if (!e.fontSize) {
 295                  e.fontSize = fsize;
 296              }
 297              if (!e.fontColor) {
 298                  e.fontColor = fColor;
 299              }
 300              if (!e.backgroundColor) {
 301                  e.backgroundColor = bColor;
 302              }
 303  
 304              endTime = (new Date()).getTime();
 305          },
 306          /**
 307          * Walk the dom tree from this node up to body, returning a reversed array of parents.
 308          * @method getDomPath
 309          * @param {Node} node The Node to start from
 310          */
 311          getDomPath: function(node, nodeList) {
 312              var domPath = [], domNode, rootNode,
 313                  root = this._getRoot(),
 314                  inst = this.frame.getInstance();
 315  
 316              domNode = inst.Node.getDOMNode(node);
 317              rootNode = inst.Node.getDOMNode(root);
 318              //return inst.all(domNode);
 319  
 320              while (domNode !== null) {
 321  
 322                  if ((domNode === inst.config.doc.documentElement) || (domNode === inst.config.doc) || !domNode.tagName) {
 323                      domNode = null;
 324                      break;
 325                  }
 326  
 327                  if (!inst.DOM.inDoc(domNode)) {
 328                      domNode = null;
 329                      break;
 330                  }
 331  
 332                  //Check to see if we get el.nodeName and nodeType
 333                  if (domNode.nodeName && domNode.nodeType && (domNode.nodeType === 1)) {
 334                      domPath.push(domNode);
 335                  }
 336  
 337                  if (domNode === rootNode) {
 338                      domNode = null;
 339                      break;
 340                  }
 341  
 342                  domNode = domNode.parentNode;
 343              }
 344  
 345              /*{{{ Using Node
 346              while (node !== null) {
 347                  if (node.test('html') || node.test('doc') || !node.get('tagName')) {
 348                      node = null;
 349                      break;
 350                  }
 351                  if (!node.inDoc()) {
 352                      node = null;
 353                      break;
 354                  }
 355                  //Check to see if we get el.nodeName and nodeType
 356                  if (node.get('nodeName') && node.get('nodeType') && (node.get('nodeType') == 1)) {
 357                      domPath.push(inst.Node.getDOMNode(node));
 358                  }
 359  
 360                  if (node.test('body')) {
 361                      node = null;
 362                      break;
 363                  }
 364  
 365                  node = node.get('parentNode');
 366              }
 367              }}}*/
 368  
 369              if (domPath.length === 0) {
 370                  domPath[0] = inst.config.doc.body;
 371              }
 372  
 373              if (nodeList) {
 374                  return inst.all(domPath.reverse());
 375              } else {
 376                  return domPath.reverse();
 377              }
 378  
 379          },
 380          /**
 381          * After frame ready, bind mousedown & keyup listeners
 382          * @method _afterFrameReady
 383          * @private
 384          */
 385          _afterFrameReady: function() {
 386              var inst = this.frame.getInstance();
 387  
 388              this.frame.on('dom:mouseup', Y.bind(this._onFrameMouseUp, this));
 389              this.frame.on('dom:mousedown', Y.bind(this._onFrameMouseDown, this));
 390              this.frame.on('dom:keydown', Y.bind(this._onFrameKeyDown, this));
 391  
 392              if (Y.UA.ie && Y.UA.ie < 11) {
 393                  this.frame.on('dom:activate', Y.bind(this._onFrameActivate, this));
 394                  this.frame.on('dom:beforedeactivate', Y.bind(this._beforeFrameDeactivate, this));
 395              }
 396              this.frame.on('dom:keyup', Y.bind(this._onFrameKeyUp, this));
 397              this.frame.on('dom:keypress', Y.bind(this._onFrameKeyPress, this));
 398              this.frame.on('dom:paste', Y.bind(this._onPaste, this));
 399  
 400              inst.EditorSelection.filter();
 401              this.fire('ready');
 402          },
 403          /**
 404          * Caches the current cursor position in IE.
 405          * @method _beforeFrameDeactivate
 406          * @private
 407          */
 408          _beforeFrameDeactivate: function(e) {
 409              if (e.frameTarget.test('html')) { //Means it came from a scrollbar
 410                  return;
 411              }
 412              var inst = this.getInstance(),
 413                  sel = inst.config.doc.selection.createRange();
 414  
 415              if (sel.compareEndPoints && !sel.compareEndPoints('StartToEnd', sel)) {
 416                  sel.pasteHTML('<var id="yui-ie-cursor">');
 417              }
 418          },
 419          /**
 420          * Moves the cached selection bookmark back so IE can place the cursor in the right place.
 421          * @method _onFrameActivate
 422          * @private
 423          */
 424          _onFrameActivate: function(e) {
 425              if (e.frameTarget.test('html')) { //Means it came from a scrollbar
 426                  return;
 427              }
 428              var inst = this.getInstance(),
 429                  sel = new inst.EditorSelection(),
 430                  range = sel.createRange(),
 431                  root = this._getRoot(),
 432                  cur = root.all('#yui-ie-cursor');
 433  
 434              if (cur.size()) {
 435                  cur.each(function(n) {
 436                      n.set('id', '');
 437                      if (range.moveToElementText) {
 438                          try {
 439                              range.moveToElementText(n._node);
 440                              var moved = range.move('character', -1);
 441                              if (moved === -1) { //Only move up if we actually moved back.
 442                                  range.move('character', 1);
 443                              }
 444                              range.select();
 445                              range.text = '';
 446                          } catch (e) {}
 447                      }
 448                      n.remove();
 449                  });
 450              }
 451          },
 452          /**
 453          * Fires nodeChange event
 454          * @method _onPaste
 455          * @private
 456          */
 457          _onPaste: function(e) {
 458              this.fire('nodeChange', { changedNode: e.frameTarget, changedType: 'paste', changedEvent: e.frameEvent });
 459          },
 460          /**
 461          * Fires nodeChange event
 462          * @method _onFrameMouseUp
 463          * @private
 464          */
 465          _onFrameMouseUp: function(e) {
 466              this.fire('nodeChange', { changedNode: e.frameTarget, changedType: 'mouseup', changedEvent: e.frameEvent  });
 467          },
 468          /**
 469          * Fires nodeChange event
 470          * @method _onFrameMouseDown
 471          * @private
 472          */
 473          _onFrameMouseDown: function(e) {
 474              this.fire('nodeChange', { changedNode: e.frameTarget, changedType: 'mousedown', changedEvent: e.frameEvent  });
 475          },
 476          /**
 477          * Caches a copy of the selection for key events. Only creating the selection on keydown
 478          * @property _currentSelection
 479          * @private
 480          */
 481          _currentSelection: null,
 482          /**
 483          * Holds the timer for selection clearing
 484          * @property _currentSelectionTimer
 485          * @private
 486          */
 487          _currentSelectionTimer: null,
 488          /**
 489          * Flag to determine if we can clear the selection or not.
 490          * @property _currentSelectionClear
 491          * @private
 492          */
 493          _currentSelectionClear: null,
 494          /**
 495          * Fires nodeChange event
 496          * @method _onFrameKeyDown
 497          * @private
 498          */
 499          _onFrameKeyDown: function(e) {
 500              var inst, sel;
 501              if (!this._currentSelection) {
 502                  if (this._currentSelectionTimer) {
 503                      this._currentSelectionTimer.cancel();
 504                  }
 505                  this._currentSelectionTimer = Y.later(850, this, function() {
 506                      this._currentSelectionClear = true;
 507                  });
 508  
 509                  inst = this.frame.getInstance();
 510                  sel = new inst.EditorSelection(e);
 511  
 512                  this._currentSelection = sel;
 513              } else {
 514                  sel = this._currentSelection;
 515              }
 516  
 517              inst = this.frame.getInstance();
 518              sel = new inst.EditorSelection();
 519  
 520              this._currentSelection = sel;
 521  
 522              if (sel && sel.anchorNode) {
 523                  this.fire('nodeChange', { changedNode: sel.anchorNode, changedType: 'keydown', changedEvent: e.frameEvent });
 524                  if (EditorBase.NC_KEYS[e.keyCode]) {
 525                      this.fire('nodeChange', {
 526                          changedNode: sel.anchorNode,
 527                          changedType: EditorBase.NC_KEYS[e.keyCode],
 528                          changedEvent: e.frameEvent
 529                      });
 530                      this.fire('nodeChange', {
 531                          changedNode: sel.anchorNode,
 532                          changedType: EditorBase.NC_KEYS[e.keyCode] + '-down',
 533                          changedEvent: e.frameEvent
 534                      });
 535                  }
 536              }
 537          },
 538          /**
 539          * Fires nodeChange event
 540          * @method _onFrameKeyPress
 541          * @private
 542          */
 543          _onFrameKeyPress: function(e) {
 544              var sel = this._currentSelection;
 545  
 546              if (sel && sel.anchorNode) {
 547                  this.fire('nodeChange', { changedNode: sel.anchorNode, changedType: 'keypress', changedEvent: e.frameEvent });
 548                  if (EditorBase.NC_KEYS[e.keyCode]) {
 549                      this.fire('nodeChange', {
 550                          changedNode: sel.anchorNode,
 551                          changedType: EditorBase.NC_KEYS[e.keyCode] + '-press',
 552                          changedEvent: e.frameEvent
 553                      });
 554                  }
 555              }
 556          },
 557          /**
 558          * Fires nodeChange event for keyup on specific keys
 559          * @method _onFrameKeyUp
 560          * @private
 561          */
 562          _onFrameKeyUp: function(e) {
 563              var inst = this.frame.getInstance(),
 564                  sel = new inst.EditorSelection(e);
 565  
 566              if (sel && sel.anchorNode) {
 567                  this.fire('nodeChange', { changedNode: sel.anchorNode, changedType: 'keyup', selection: sel, changedEvent: e.frameEvent  });
 568                  if (EditorBase.NC_KEYS[e.keyCode]) {
 569                      this.fire('nodeChange', {
 570                          changedNode: sel.anchorNode,
 571                          changedType: EditorBase.NC_KEYS[e.keyCode] + '-up',
 572                          selection: sel,
 573                          changedEvent: e.frameEvent
 574                      });
 575                  }
 576              }
 577              if (this._currentSelectionClear) {
 578                  this._currentSelectionClear = this._currentSelection = null;
 579              }
 580          },
 581          /**
 582          * Validates linkedcss property
 583          *
 584          * @method _validateLinkedCSS
 585          * @private
 586          */
 587          _validateLinkedCSS: function(value) {
 588              return Lang.isString(value) || Lang.isArray(value);
 589          },
 590          /**
 591          * Pass through to the frame.execCommand method
 592          * @method execCommand
 593          * @param {String} cmd The command to pass: inserthtml, insertimage, bold
 594          * @param {String} val The optional value of the command: Helvetica
 595          * @return {Node/NodeList} The Node or Nodelist affected by the command. Only returns on override commands, not browser defined commands.
 596          */
 597          execCommand: function(cmd, val) {
 598              var ret = this.frame.execCommand(cmd, val),
 599                  inst = this.frame.getInstance(),
 600                  sel = new inst.EditorSelection(), cmds = {},
 601                  e = { changedNode: sel.anchorNode, changedType: 'execcommand', nodes: ret };
 602  
 603              switch (cmd) {
 604                  case 'forecolor':
 605                      e.fontColor = val;
 606                      break;
 607                  case 'backcolor':
 608                      e.backgroundColor = val;
 609                      break;
 610                  case 'fontsize':
 611                      e.fontSize = val;
 612                      break;
 613                  case 'fontname':
 614                      e.fontFamily = val;
 615                      break;
 616              }
 617  
 618              cmds[cmd] = 1;
 619              e.commands = cmds;
 620  
 621              this.fire('nodeChange', e);
 622  
 623              return ret;
 624          },
 625          /**
 626          * Get the YUI instance of the frame
 627          * @method getInstance
 628          * @return {YUI} The YUI instance bound to the frame.
 629          */
 630          getInstance: function() {
 631              return this.frame.getInstance();
 632          },
 633          /**
 634          * Renders the Y.ContentEditable to the passed node.
 635          * @method render
 636          * @param {Selector/HTMLElement/Node} node The node to append the Editor to
 637          * @return {EditorBase}
 638          * @chainable
 639          */
 640          render: function(node) {
 641              var frame = this.frame;
 642  
 643              if (!frame) {
 644                  this.plug(Y.Plugin.Frame, {
 645                      designMode: true,
 646                      title: EditorBase.STRINGS.title,
 647                      use: EditorBase.USE,
 648                      dir: this.get('dir'),
 649                      extracss: this.get('extracss'),
 650                      linkedcss: this.get('linkedcss'),
 651                      defaultblock: this.get('defaultblock')
 652                  });
 653  
 654                  frame = this.frame;
 655              }
 656  
 657              if (!frame.hasPlugin('exec')) {
 658                  frame.plug(Y.Plugin.ExecCommand);
 659              }
 660  
 661              frame.after('ready', Y.bind(this._afterFrameReady, this));
 662  
 663              frame.addTarget(this);
 664  
 665              frame.set('content', this.get('content'));
 666  
 667              frame.render(node);
 668  
 669              return this;
 670          },
 671          /**
 672          * Focus the contentWindow of the iframe
 673          * @method focus
 674          * @param {Function} fn Callback function to execute after focus happens
 675          * @return {EditorBase}
 676          * @chainable
 677          */
 678          focus: function(fn) {
 679              this.frame.focus(fn);
 680              return this;
 681          },
 682          /**
 683          * Handles the showing of the Editor instance. Currently only handles the iframe
 684          * @method show
 685          * @return {EditorBase}
 686          * @chainable
 687          */
 688          show: function() {
 689              this.frame.show();
 690              return this;
 691          },
 692          /**
 693          * Handles the hiding of the Editor instance. Currently only handles the iframe
 694          * @method hide
 695          * @return {EditorBase}
 696          * @chainable
 697          */
 698          hide: function() {
 699              this.frame.hide();
 700              return this;
 701          },
 702          /**
 703          * (Un)Filters the content of the Editor, cleaning YUI related code. //TODO better filtering
 704          * @method getContent
 705          * @return {String} The filtered content of the Editor
 706          */
 707          getContent: function() {
 708              var html = '', inst = this.getInstance();
 709              if (inst && inst.EditorSelection) {
 710                  html = inst.EditorSelection.unfilter();
 711              }
 712              //Removing the _yuid from the objects in IE
 713              html = html.replace(/ _yuid="([^>]*)"/g, '');
 714              return html;
 715          }
 716      }, {
 717          /**
 718          * @static
 719          * @method NORMALIZE_FONTSIZE
 720          * @description Pulls the fontSize from a node, then checks for string values (x-large, x-small)
 721          * and converts them to pixel sizes. If the parsed size is different from the original, it calls
 722          * node.setStyle to update the node with a pixel size for normalization.
 723          */
 724          NORMALIZE_FONTSIZE: function(n) {
 725              var size = n.getStyle('fontSize'), oSize = size;
 726  
 727              switch (size) {
 728                  case '-webkit-xxx-large':
 729                      size = '48px';
 730                      break;
 731                  case 'xx-large':
 732                      size = '32px';
 733                      break;
 734                  case 'x-large':
 735                      size = '24px';
 736                      break;
 737                  case 'large':
 738                      size = '18px';
 739                      break;
 740                  case 'medium':
 741                      size = '16px';
 742                      break;
 743                  case 'small':
 744                      size = '13px';
 745                      break;
 746                  case 'x-small':
 747                      size = '10px';
 748                      break;
 749              }
 750              if (oSize !== size) {
 751                  n.setStyle('fontSize', size);
 752              }
 753              return size;
 754          },
 755          /**
 756          * @static
 757          * @property TABKEY
 758          * @description The HTML markup to use for the tabkey
 759          */
 760          TABKEY: '<span class="tab">&nbsp;&nbsp;&nbsp;&nbsp;</span>',
 761          /**
 762          * @static
 763          * @method FILTER_RGB
 764          * @param String css The CSS string containing rgb(#,#,#);
 765          * @description Converts an RGB color string to a hex color, example: rgb(0, 255, 0) converts to #00ff00
 766          * @return String
 767          */
 768          FILTER_RGB: function(css) {
 769              if (css.toLowerCase().indexOf('rgb') !== -1) {
 770                  var exp = new RegExp("(.*?)rgb\\s*?\\(\\s*?([0-9]+).*?,\\s*?([0-9]+).*?,\\s*?([0-9]+).*?\\)(.*?)", "gi"),
 771                      rgb = css.replace(exp, "$1,$2,$3,$4,$5").split(','),
 772                      r, g, b;
 773  
 774                  if (rgb.length === 5) {
 775                      r = parseInt(rgb[1], 10).toString(16);
 776                      g = parseInt(rgb[2], 10).toString(16);
 777                      b = parseInt(rgb[3], 10).toString(16);
 778  
 779                      r = r.length === 1 ? '0' + r : r;
 780                      g = g.length === 1 ? '0' + g : g;
 781                      b = b.length === 1 ? '0' + b : b;
 782  
 783                      css = "#" + r + g + b;
 784                  }
 785              }
 786              return css;
 787          },
 788          /**
 789          * @static
 790          * @property TAG2CMD
 791          * @description A hash table of tags to their execcomand's
 792          */
 793          TAG2CMD: {
 794              'b': 'bold',
 795              'strong': 'bold',
 796              'i': 'italic',
 797              'em': 'italic',
 798              'u': 'underline',
 799              'sup': 'superscript',
 800              'sub': 'subscript',
 801              'img': 'insertimage',
 802              'a' : 'createlink',
 803              'ul' : 'insertunorderedlist',
 804              'ol' : 'insertorderedlist'
 805          },
 806          /**
 807          * Hash table of keys to fire a nodeChange event for.
 808          * @static
 809          * @property NC_KEYS
 810          * @type Object
 811          */
 812          NC_KEYS: {
 813              8: 'backspace',
 814              9: 'tab',
 815              13: 'enter',
 816              32: 'space',
 817              33: 'pageup',
 818              34: 'pagedown',
 819              35: 'end',
 820              36: 'home',
 821              37: 'left',
 822              38: 'up',
 823              39: 'right',
 824              40: 'down',
 825              46: 'delete'
 826          },
 827          /**
 828          * The default modules to use inside the Frame
 829          * @static
 830          * @property USE
 831          * @type Array
 832          */
 833          USE: ['node', 'selector-css3', 'editor-selection', 'stylesheet'],
 834          /**
 835          * The Class Name: editorBase
 836          * @static
 837          * @property NAME
 838          */
 839          NAME: 'editorBase',
 840          /**
 841          * Editor Strings.  By default contains only the `title` property for the
 842          * Title of frame document (default "Rich Text Editor").
 843          *
 844          * @static
 845          * @property STRINGS
 846          */
 847          STRINGS: {
 848              title: 'Rich Text Editor'
 849          },
 850          ATTRS: {
 851              /**
 852              * The content to load into the Editor Frame
 853              * @attribute content
 854              */
 855              content: {
 856                  validator: Lang.isString,
 857                  value: '<br class="yui-cursor">',
 858                  setter: function(str) {
 859                      if (str.substr(0, 1) === "\n") {
 860                          str = str.substr(1);
 861                      }
 862                      if (str === '') {
 863                          str = '<br class="yui-cursor">';
 864                      }
 865                      if (str === ' ') {
 866                          if (Y.UA.gecko) {
 867                              str = '<br class="yui-cursor">';
 868                          }
 869                      }
 870                      return this.frame.set('content', str);
 871                  },
 872                  getter: function() {
 873                      return this.frame.get('content');
 874                  }
 875              },
 876              /**
 877              * The value of the dir attribute on the HTML element of the frame. Default: ltr
 878              * @attribute dir
 879              */
 880              dir: {
 881                  validator: Lang.isString,
 882                  writeOnce: true,
 883                  value: 'ltr'
 884              },
 885              /**
 886              * @attribute linkedcss
 887              * @description An array of url's to external linked style sheets
 888              * @type String|Array
 889              */
 890              linkedcss: {
 891                  validator: '_validateLinkedCSS',
 892                  value: '',
 893                  setter: function(css) {
 894                      if (this.frame) {
 895                          this.frame.set('linkedcss', css);
 896                      }
 897                      return css;
 898                  }
 899              },
 900              /**
 901              * @attribute extracss
 902              * @description A string of CSS to add to the Head of the Editor
 903              * @type String
 904              */
 905              extracss: {
 906                  validator: Lang.isString,
 907                  value: '',
 908                  setter: function(css) {
 909                      if (this.frame) {
 910                          this.frame.set('extracss', css);
 911                      }
 912                      return css;
 913                  }
 914              },
 915              /**
 916              * @attribute defaultblock
 917              * @description The default tag to use for block level items, defaults to: p
 918              * @type String
 919              */
 920              defaultblock: {
 921                  validator: Lang.isString,
 922                  value: 'p'
 923              }
 924          }
 925      });
 926  
 927      Y.EditorBase = EditorBase;
 928  
 929      /**
 930      * @event nodeChange
 931      * @description Fired from several mouse/key/paste event points.
 932      * @param {EventFacade} event An Event Facade object with the following specific properties added:
 933      * <dl>
 934      *   <dt>changedEvent</dt><dd>The event that caused the nodeChange</dd>
 935      *   <dt>changedNode</dt><dd>The node that was interacted with</dd>
 936      *   <dt>changedType</dt><dd>The type of change: mousedown, mouseup, right, left, backspace, tab, enter, etc..</dd>
 937      *   <dt>commands</dt><dd>The list of execCommands that belong to this change and the dompath that's associated with the changedNode</dd>
 938      *   <dt>classNames</dt><dd>An array of classNames that are applied to the changedNode and all of it's parents</dd>
 939      *   <dt>dompath</dt><dd>A sorted array of node instances that make up the DOM path from the changedNode to body.</dd>
 940      *   <dt>backgroundColor</dt><dd>The cascaded backgroundColor of the changedNode</dd>
 941      *   <dt>fontColor</dt><dd>The cascaded fontColor of the changedNode</dd>
 942      *   <dt>fontFamily</dt><dd>The cascaded fontFamily of the changedNode</dd>
 943      *   <dt>fontSize</dt><dd>The cascaded fontSize of the changedNode</dd>
 944      * </dl>
 945      */
 946  
 947      /**
 948      * @event ready
 949      * @description Fired after the frame is ready.
 950      * @param {EventFacade} event An Event Facade object.
 951      */
 952  
 953  
 954  
 955  
 956  
 957  }, '3.17.2', {"requires": ["base", "frame", "node", "exec-command", "editor-selection"]});


Generated: Thu Aug 11 10:00:09 2016 Cross-referenced by PHPXref 0.7.1