[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/lib/yuilib/3.17.2/frame/ -> frame-debug.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('frame', function (Y, NAME) {
   9  
  10      /*jshint maxlen: 500 */
  11      /**
  12       * Creates a wrapper around an iframe. It loads the content either from a local
  13       * file or from script and creates a local YUI instance bound to that new window and document.
  14       * @class Frame
  15       * @for Frame
  16       * @extends Base
  17       * @constructor
  18       * @module editor
  19       * @submodule frame
  20       */
  21  
  22      var Lang = Y.Lang,
  23  
  24          EVENT_CONTENT_READY = 'contentready',
  25  
  26          HOST = 'host',
  27  
  28      Frame = function() {
  29          Frame.superclass.constructor.apply(this, arguments);
  30      };
  31  
  32  
  33      Y.extend(Frame, Y.Plugin.Base, {
  34          /**
  35          * @private
  36          * @property _ready
  37          * @description Internal reference set when the content is ready.
  38          * @type Boolean
  39          */
  40          _ready: null,
  41          /**
  42          * @private
  43          * @property _rendered
  44          * @description Internal reference set when render is called.
  45          * @type Boolean
  46          */
  47          _rendered: null,
  48          /**
  49          * @private
  50          * @property _iframe
  51          * @description Internal Node reference to the iFrame or the window
  52          * @type Node
  53          */
  54          _iframe: null,
  55          /**
  56          * @private
  57          * @property _instance
  58          * @description Internal reference to the YUI instance bound to the iFrame or window
  59          * @type YUI
  60          */
  61          _instance: null,
  62          /**
  63          * @private
  64          * @method _create
  65          * @description Create the iframe or Window and get references to the Document & Window
  66          * @return {Object} Hash table containing references to the new Document & Window
  67          */
  68          _create: function(cb) {
  69              var res, html = '', timer,
  70                  //if the src attr is different than the default, don't create the document
  71                  create = (this.get('src') === Frame.ATTRS.src.value),
  72                  extra_css = ((this.get('extracss')) ? '<style id="extra_css">' + this.get('extracss') + '</style>' : '');
  73  
  74              this._iframe = Y.one(Y.config.doc.createElement('iframe'));
  75              this._iframe.setAttrs(Frame.IFRAME_ATTRS);
  76  
  77              this._iframe.setStyle('visibility', 'hidden');
  78              this._iframe.set('src', this.get('src'));
  79              this.get('container').append(this._iframe);
  80              this._iframe.set('height', '99%');
  81  
  82              if (create) {
  83                  Y.log('Creating the document from javascript', 'info', 'frame');
  84                  html = Y.Lang.sub(Frame.PAGE_HTML, {
  85                      DIR: this.get('dir'),
  86                      LANG: this.get('lang'),
  87                      TITLE: this.get('title'),
  88                      META: Frame.META,
  89                      LINKED_CSS: this.get('linkedcss'),
  90                      CONTENT: this.get('content'),
  91                      BASE_HREF: this.get('basehref'),
  92                      DEFAULT_CSS: Frame.DEFAULT_CSS,
  93                      EXTRA_CSS: extra_css
  94                  });
  95                  if (Y.config.doc.compatMode !== 'BackCompat') {
  96                      Y.log('Adding Doctype to frame: ' + Frame.getDocType(), 'info', 'frame');
  97  
  98                      //html = Frame.DOC_TYPE + "\n" + html;
  99                      html = Frame.getDocType() + "\n" + html;
 100                  } else {
 101                      Y.log('DocType skipped because we are in BackCompat Mode.', 'warn', 'frame');
 102                  }
 103  
 104                  Y.log('Injecting content into iframe', 'info', 'frame');
 105              }
 106  
 107              res = this._resolveWinDoc();
 108  
 109              if (html) {
 110                  Y.log('Writing HTML to new document', 'info', 'frame');
 111                  res.doc.open();
 112                  res.doc.write(html);
 113                  res.doc.close();
 114              }
 115  
 116              if (!res.doc.documentElement) {
 117                  Y.log('document.documentElement was not found, running timer', 'warn', 'frame');
 118                  timer = Y.later(1, this, function() {
 119                      if (res.doc && res.doc.documentElement) {
 120                          Y.log('document.documentElement found inside timer', 'info', 'frame');
 121                          cb(res);
 122                          timer.cancel();
 123                      }
 124                  }, null, true);
 125              } else {
 126                  Y.log('document.documentElement found', 'info', 'frame');
 127                  cb(res);
 128              }
 129  
 130          },
 131          /**
 132          * @private
 133          * @method _resolveWinDoc
 134          * @description Resolves the document and window from an iframe or window instance
 135          * @param {Object} c The YUI Config to add the window and document to
 136          * @return {Object} Object hash of window and document references, if a YUI config was passed, it is returned.
 137          */
 138          _resolveWinDoc: function(c) {
 139              var config = (c) ? c : {};
 140              config.win = Y.Node.getDOMNode(this._iframe.get('contentWindow'));
 141              config.doc = Y.Node.getDOMNode(this._iframe.get('contentWindow.document'));
 142              if (!config.doc) {
 143                  config.doc = Y.config.doc;
 144              }
 145              if (!config.win) {
 146                  config.win = Y.config.win;
 147              }
 148              return config;
 149          },
 150          /**
 151          * @private
 152          * @method _onDomEvent
 153          * @description Generic handler for all DOM events fired by the iframe or window. This handler
 154          * takes the current EventFacade and augments it to fire on the Frame host. It adds two new properties
 155          * to the EventFacade called frameX and frameY which adds the scroll and xy position of the iframe
 156          * to the original pageX and pageY of the event so external nodes can be positioned over the frame.
 157          * @param {EventFacade} e
 158          */
 159          _onDomEvent: function(e) {
 160              var xy, node;
 161  
 162              if (!Y.Node.getDOMNode(this._iframe)) {
 163                  //The iframe is null for some reason, bail on sending events.
 164                  return;
 165              }
 166  
 167              //Y.log('onDOMEvent: ' + e.type, 'info', 'frame');
 168              e.frameX = e.frameY = 0;
 169  
 170              if (e.pageX > 0 || e.pageY > 0) {
 171                  if (e.type.substring(0, 3) !== 'key') {
 172                      node = this._instance.one('win');
 173                      xy = this._iframe.getXY();
 174                      e.frameX = xy[0] + e.pageX - node.get('scrollLeft');
 175                      e.frameY = xy[1] + e.pageY - node.get('scrollTop');
 176                  }
 177              }
 178  
 179              e.frameTarget = e.target;
 180              e.frameCurrentTarget = e.currentTarget;
 181              e.frameEvent = e;
 182  
 183              this.fire('dom:' + e.type, e);
 184          },
 185          initializer: function() {
 186              var host = this.get(HOST);
 187  
 188              if (host) {
 189                  host.frame = this;
 190              }
 191  
 192              this.publish('ready', {
 193                  emitFacade: true,
 194                  defaultFn: this._defReadyFn
 195              });
 196          },
 197          destructor: function() {
 198              var inst = this.getInstance();
 199  
 200              inst.one('doc').detachAll();
 201              inst = null;
 202              this._iframe.remove();
 203          },
 204          /**
 205          * @private
 206          * @method _DOMPaste
 207          * @description Simple pass thru handler for the paste event so we can do content cleanup
 208          * @param {EventFacade} e
 209          */
 210          _DOMPaste: function(e) {
 211              var inst = this.getInstance(),
 212                  data = '', win = inst.config.win;
 213  
 214              if (e._event.originalTarget) {
 215                  data = e._event.originalTarget;
 216              }
 217              if (e._event.clipboardData) {
 218                  data = e._event.clipboardData.getData('Text');
 219              }
 220  
 221              if (win.clipboardData) {
 222                  data = win.clipboardData.getData('Text');
 223                  if (data === '') { // Could be empty, or failed
 224                      // Verify failure
 225                      if (!win.clipboardData.setData('Text', data)) {
 226                          data = null;
 227                      }
 228                  }
 229              }
 230  
 231  
 232              e.frameTarget = e.target;
 233              e.frameCurrentTarget = e.currentTarget;
 234              e.frameEvent = e;
 235  
 236              if (data) {
 237                  e.clipboardData = {
 238                      data: data,
 239                      getData: function() {
 240                          return data;
 241                      }
 242                  };
 243              } else {
 244                  Y.log('Failed to collect clipboard data', 'warn', 'frame');
 245                  e.clipboardData = null;
 246              }
 247  
 248              this.fire('dom:paste', e);
 249          },
 250          /**
 251          * @private
 252          * @method _defReadyFn
 253          * @description Binds DOM events, sets the iframe to visible and fires the ready event
 254          */
 255          _defReadyFn: function() {
 256              var inst = this.getInstance();
 257  
 258              Y.each(Frame.DOM_EVENTS, function(v, k) {
 259                  var fn = Y.bind(this._onDomEvent, this),
 260                      kfn = ((Y.UA.ie && Frame.THROTTLE_TIME > 0) ? Y.throttle(fn, Frame.THROTTLE_TIME) : fn);
 261  
 262                  if (!inst.Node.DOM_EVENTS[k]) {
 263                      inst.Node.DOM_EVENTS[k] = 1;
 264                  }
 265                  if (v === 1) {
 266                      if (k !== 'focus' && k !== 'blur' && k !== 'paste') {
 267                          //Y.log('Adding DOM event to frame: ' + k, 'info', 'frame');
 268                          if (k.substring(0, 3) === 'key') {
 269                              //Throttle key events in IE
 270                              inst.on(k, kfn, inst.config.doc);
 271                          } else {
 272                              inst.on(k, fn, inst.config.doc);
 273                          }
 274                      }
 275                  }
 276              }, this);
 277  
 278              inst.Node.DOM_EVENTS.paste = 1;
 279  
 280              inst.on('paste', Y.bind(this._DOMPaste, this), inst.one('body'));
 281  
 282              //Adding focus/blur to the window object
 283              inst.on('focus', Y.bind(this._onDomEvent, this), inst.config.win);
 284              inst.on('blur', Y.bind(this._onDomEvent, this), inst.config.win);
 285  
 286              inst.__use = inst.use;
 287              inst.use = Y.bind(this.use, this);
 288              this._iframe.setStyles({
 289                  visibility: 'inherit'
 290              });
 291              inst.one('body').setStyle('display', 'block');
 292          },
 293          /**
 294          * It appears that having a BR tag anywhere in the source "below" a table with a percentage width (in IE 7 & 8)
 295          * if there is any TEXTINPUT's outside the iframe, the cursor will rapidly flickr and the CPU would occasionally
 296          * spike. This method finds all <BR>'s below the sourceIndex of the first table. Does some checks to see if they
 297          * can be modified and replaces then with a <WBR> so the layout will remain in tact, but the flickering will
 298          * no longer happen.
 299          * @method _fixIECursors
 300          * @private
 301          */
 302          _fixIECursors: function() {
 303              var inst = this.getInstance(),
 304                  tables = inst.all('table'),
 305                  brs = inst.all('br'), si;
 306  
 307              if (tables.size() && brs.size()) {
 308                  //First Table
 309                  si = tables.item(0).get('sourceIndex');
 310                  brs.each(function(n) {
 311                      var p = n.get('parentNode'),
 312                          c = p.get('children'), b = p.all('>br');
 313  
 314                      if (p.test('div')) {
 315                          if (c.size() > 2) {
 316                              n.replace(inst.Node.create('<wbr>'));
 317                          } else {
 318                              if (n.get('sourceIndex') > si) {
 319                                  if (b.size()) {
 320                                      n.replace(inst.Node.create('<wbr>'));
 321                                  }
 322                              } else {
 323                                  if (b.size() > 1) {
 324                                      n.replace(inst.Node.create('<wbr>'));
 325                                  }
 326                              }
 327                          }
 328                      }
 329  
 330                  });
 331              }
 332          },
 333          /**
 334          * @private
 335          * @method _onContentReady
 336          * @description Called once the content is available in the frame/window and calls the final use call
 337          * on the internal instance so that the modules are loaded properly.
 338          */
 339          _onContentReady: function(e) {
 340              if (!this._ready) {
 341                  this._ready = true;
 342                  var inst = this.getInstance(),
 343                      args = Y.clone(this.get('use'));
 344  
 345                  this.fire('contentready');
 346  
 347                  Y.log('On available for body of iframe', 'info', 'frame');
 348                  if (e) {
 349                      inst.config.doc = Y.Node.getDOMNode(e.target);
 350                  }
 351                  //TODO Circle around and deal with CSS loading...
 352                  args.push(Y.bind(function() {
 353                      Y.log('Callback from final internal use call', 'info', 'frame');
 354                      if (inst.EditorSelection) {
 355                          inst.EditorSelection.DEFAULT_BLOCK_TAG = this.get('defaultblock');
 356                      }
 357                      //Moved to here so that the iframe is ready before allowing editing..
 358                      if (this.get('designMode')) {
 359                          if(Y.UA.ie) {
 360                              inst.config.doc.body.contentEditable = 'true';
 361                              this._ieSetBodyHeight();
 362                              inst.on('keyup', Y.bind(this._ieSetBodyHeight, this), inst.config.doc);
 363                          } else {
 364                              inst.config.doc.designMode = 'on';
 365                          }
 366                      }
 367                      this.fire('ready');
 368                  }, this));
 369                  Y.log('Calling use on internal instance: ' + args, 'info', 'frame');
 370                  inst.use.apply(inst, args);
 371  
 372                  inst.one('doc').get('documentElement').addClass('yui-js-enabled');
 373              }
 374          },
 375          _ieHeightCounter: null,
 376          /**
 377          * Internal method to set the height of the body to the height of the document in IE.
 378          * With contenteditable being set, the document becomes unresponsive to clicks, this
 379          * method expands the body to be the height of the document so that doesn't happen.
 380          * @private
 381          * @method _ieSetBodyHeight
 382          */
 383          _ieSetBodyHeight: function(e) {
 384              if (!this._ieHeightCounter) {
 385                  this._ieHeightCounter = 0;
 386              }
 387              this._ieHeightCounter++;
 388              var run = false, inst, h, bh;
 389              if (!e) {
 390                  run = true;
 391              }
 392              if (e) {
 393                  switch (e.keyCode) {
 394                      case 8:
 395                      case 13:
 396                          run = true;
 397                          break;
 398                  }
 399                  if (e.ctrlKey || e.shiftKey) {
 400                      run = true;
 401                  }
 402              }
 403              if (run) {
 404                  try {
 405                      inst = this.getInstance();
 406                      h = this._iframe.get('offsetHeight');
 407                      bh = inst.config.doc.body.scrollHeight;
 408                      if (h > bh) {
 409                          h = (h - 15) + 'px';
 410                          inst.config.doc.body.style.height = h;
 411                      } else {
 412                          inst.config.doc.body.style.height = 'auto';
 413                      }
 414                  } catch (e) {
 415                      if (this._ieHeightCounter < 100) {
 416                          Y.later(200, this, this._ieSetBodyHeight);
 417                      } else {
 418                          Y.log('Failed to set body height in IE', 'error', 'frame');
 419                      }
 420                  }
 421              }
 422          },
 423          /**
 424          * @private
 425          * @method _resolveBaseHref
 426          * @description Resolves the basehref of the page the frame is created on. Only applies to dynamic content.
 427          * @param {String} href The new value to use, if empty it will be resolved from the current url.
 428          * @return {String}
 429          */
 430          _resolveBaseHref: function(href) {
 431              if (!href || href === '') {
 432                  href = Y.config.doc.location.href;
 433                  if (href.indexOf('?') !== -1) { //Remove the query string
 434                      href = href.substring(0, href.indexOf('?'));
 435                  }
 436                  href = href.substring(0, href.lastIndexOf('/')) + '/';
 437              }
 438              return href;
 439          },
 440          /**
 441          * @private
 442          * @method _getHTML
 443          * @description Get the content from the iframe
 444          * @param {String} html The raw HTML from the body of the iframe.
 445          * @return {String}
 446          */
 447          _getHTML: function(html) {
 448              if (this._ready) {
 449                  var inst = this.getInstance();
 450                  html = inst.one('body').get('innerHTML');
 451              }
 452              return html;
 453          },
 454          /**
 455          * @private
 456          * @method _setHTML
 457          * @description Set the content of the iframe
 458          * @param {String} html The raw HTML to set the body of the iframe to.
 459          * @return {String}
 460          */
 461          _setHTML: function(html) {
 462              if (this._ready) {
 463                  var inst = this.getInstance();
 464                  inst.one('body').set('innerHTML', html);
 465              } else {
 466                  this.once(EVENT_CONTENT_READY, Y.bind(this._setHTML, this, html));
 467              }
 468  
 469              return html;
 470          },
 471          /**
 472          * @private
 473          * @method _getLinkedCSS
 474          * @description Get the linked CSS on the instance.
 475          */
 476          _getLinkedCSS: function(urls) {
 477              if (!Y.Lang.isArray(urls)) {
 478                  urls = [urls];
 479              }
 480              var str = '';
 481              if (!this._ready) {
 482                  Y.each(urls, function(v) {
 483                      if (v) {
 484                          str += '<link rel="stylesheet" href="' + v + '" type="text/css">';
 485                      }
 486                  });
 487              } else {
 488                  str = urls;
 489              }
 490              return str;
 491          },
 492          /**
 493          * @private
 494          * @method _setLinkedCSS
 495          * @description Sets the linked CSS on the instance..
 496          */
 497          _setLinkedCSS: function(css) {
 498              if (this._ready) {
 499                  var inst = this.getInstance();
 500                  inst.Get.css(css);
 501              }
 502              return css;
 503          },
 504          /**
 505          * @private
 506          * @method _setExtraCSS
 507          * @description Set's the extra CSS on the instance..
 508          */
 509          _setExtraCSS: function(css) {
 510              if (this._ready) {
 511                  var inst = this.getInstance(),
 512                      node = inst.one('#extra_css');
 513  
 514                  if (node) {
 515                      node.remove();
 516                  }
 517  
 518                  inst.one('head').append('<style id="extra_css">' + css + '</style>');
 519              } else {
 520                  //This needs to be wrapped in a contentready callback for the !_ready state
 521                  this.once(EVENT_CONTENT_READY, Y.bind(this._setExtraCSS, this, css));
 522              }
 523  
 524              return css;
 525          },
 526          /**
 527          * @private
 528          * @method _instanceLoaded
 529          * @description Called from the first YUI instance that sets up the internal instance.
 530          * This loads the content into the window/frame and attaches the contentready event.
 531          * @param {YUI} inst The internal YUI instance bound to the frame/window
 532          */
 533          _instanceLoaded: function(inst) {
 534              this._instance = inst;
 535              this._onContentReady();
 536  
 537              var doc = this._instance.config.doc;
 538  
 539              if (this.get('designMode')) {
 540                  if (!Y.UA.ie) {
 541                      try {
 542                          //Force other browsers into non CSS styling
 543                          doc.execCommand('styleWithCSS', false, false);
 544                          doc.execCommand('insertbronreturn', false, false);
 545                      } catch (err) {}
 546                  }
 547              }
 548          },
 549          //BEGIN PUBLIC METHODS
 550          /**
 551          * @method use
 552          * @description This is a scoped version of the normal YUI.use method & is bound to this frame/window.
 553          * At setup, the inst.use method is mapped to this method.
 554          */
 555          use: function() {
 556              Y.log('Calling augmented use after ready', 'info', 'frame');
 557              var inst = this.getInstance(),
 558                  args = Y.Array(arguments),
 559                  cb = false;
 560  
 561              if (Y.Lang.isFunction(args[args.length - 1])) {
 562                  cb = args.pop();
 563              }
 564              if (cb) {
 565                  args.push(function() {
 566                      Y.log('Internal callback from augmented use', 'info', 'frame');
 567                      cb.apply(inst, arguments);
 568  
 569                  });
 570              }
 571  
 572              return inst.__use.apply(inst, args);
 573          },
 574          /**
 575          * @method delegate
 576          * @description A delegate method passed to the instance's delegate method
 577          * @param {String} type The type of event to listen for
 578          * @param {Function} fn The method to attach
 579          * @param {String} cont The container to act as a delegate, if no "sel" passed, the body is assumed as the container.
 580          * @param {String} sel The selector to match in the event (optional)
 581          * @return {EventHandle} The Event handle returned from Y.delegate
 582          */
 583          delegate: function(type, fn, cont, sel) {
 584              var inst = this.getInstance();
 585              if (!inst) {
 586                  Y.log('Delegate events can not be attached until after the ready event has fired.', 'error', 'iframe');
 587                  return false;
 588              }
 589              if (!sel) {
 590                  sel = cont;
 591                  cont = 'body';
 592              }
 593              return inst.delegate(type, fn, cont, sel);
 594          },
 595          /**
 596          * @method getInstance
 597          * @description Get a reference to the internal YUI instance.
 598          * @return {YUI} The internal YUI instance
 599          */
 600          getInstance: function() {
 601              return this._instance;
 602          },
 603          /**
 604          * @method render
 605          * @description Render the iframe into the container config option or open the window.
 606          * @param {String/HTMLElement/Node} node The node to render to
 607          * @return {Frame}
 608          * @chainable
 609          */
 610          render: function(node) {
 611              if (this._rendered) {
 612                  Y.log('Frame already rendered.', 'warn', 'frame');
 613                  return this;
 614              }
 615              this._rendered = true;
 616              if (node) {
 617                  this.set('container', node);
 618              }
 619  
 620              this._create(Y.bind(function(res) {
 621  
 622                  var inst, timer,
 623                      cb = Y.bind(function(i) {
 624                          Y.log('Internal instance loaded with node-base', 'info', 'frame');
 625                          this._instanceLoaded(i);
 626                      }, this),
 627                      args = Y.clone(this.get('use')),
 628                      config = {
 629                          debug: false,
 630                          win: res.win,
 631                          doc: res.doc
 632                      },
 633                      fn = Y.bind(function() {
 634                          Y.log('New Modules Loaded into main instance', 'info', 'frame');
 635                          config = this._resolveWinDoc(config);
 636                          inst = YUI(config);
 637                          inst.host = this.get(HOST); //Cross reference to Editor
 638                          inst.log = Y.log; //Dump the instance logs to the parent instance.
 639  
 640                          Y.log('Creating new internal instance with node-base only', 'info', 'frame');
 641                          try {
 642                              inst.use('node-base', cb);
 643                              if (timer) {
 644                                  clearInterval(timer);
 645                              }
 646                          } catch (e) {
 647                              timer = setInterval(function() {
 648                                  Y.log('[TIMER] Internal use call failed, retrying', 'info', 'frame');
 649                                  fn();
 650                              }, 350);
 651                              Y.log('Internal use call failed, retrying', 'info', 'frame');
 652                          }
 653                      }, this);
 654  
 655                  args.push(fn);
 656  
 657                  Y.log('Adding new modules to main instance: ' + args, 'info', 'frame');
 658                  Y.use.apply(Y, args);
 659  
 660              }, this));
 661  
 662              return this;
 663          },
 664          /**
 665          * @private
 666          * @method _handleFocus
 667          * @description Does some tricks on focus to set the proper cursor position.
 668          */
 669          _handleFocus: function() {
 670              var inst = this.getInstance(),
 671                  sel = new inst.EditorSelection(),
 672                  n, c, b, par;
 673  
 674              if (sel.anchorNode) {
 675                  Y.log('_handleFocus being called..', 'info', 'frame');
 676                  n = sel.anchorNode;
 677  
 678                  if (n.test('p') && n.get('innerHTML') === '') {
 679                      n = n.get('parentNode');
 680                  }
 681                  c = n.get('childNodes');
 682  
 683                  if (c.size()) {
 684                      if (c.item(0).test('br')) {
 685                          sel.selectNode(n, true, false);
 686                      } else if (c.item(0).test('p')) {
 687                          n = c.item(0).one('br.yui-cursor');
 688                          if (n) {
 689                              n = n.get('parentNode');
 690                          }
 691                          if (!n) {
 692                              n = c.item(0).get('firstChild');
 693                          }
 694                          if (!n) {
 695                              n = c.item(0);
 696                          }
 697                          if (n) {
 698                              sel.selectNode(n, true, false);
 699                          }
 700                      } else {
 701                          b = inst.one('br.yui-cursor');
 702                          if (b) {
 703                              par = b.get('parentNode');
 704                              if (par) {
 705                                  sel.selectNode(par, true, false);
 706                              }
 707                          }
 708                      }
 709                  }
 710              }
 711          },
 712          /**
 713          * Validates linkedcss property
 714          *
 715          * @method _validateLinkedCSS
 716          * @private
 717          */
 718          _validateLinkedCSS: function(value) {
 719              return Lang.isString(value) || Lang.isArray(value);
 720          },
 721          /**
 722          * @method focus
 723          * @description Set the focus to the iframe
 724          * @param {Function} fn Callback function to execute after focus happens
 725          * @return {Frame}
 726          * @chainable
 727          */
 728          focus: function(fn) {
 729              if (Y.UA.ie && Y.UA.ie < 9) {
 730                  try {
 731                      Y.one('win').focus();
 732                      if (this.getInstance()) {
 733                          if (this.getInstance().one('win')) {
 734                              this.getInstance().one('win').focus();
 735                          }
 736                      }
 737                  } catch (ierr) {
 738                      Y.log('Frame focus failed', 'warn', 'frame');
 739                  }
 740                  if (fn === true) {
 741                      this._handleFocus();
 742                  }
 743                  if (Y.Lang.isFunction(fn)) {
 744                      fn();
 745                  }
 746              } else {
 747                  try {
 748                      Y.one('win').focus();
 749                      Y.later(100, this, function() {
 750                          if (this.getInstance()) {
 751                              if (this.getInstance().one('win')) {
 752                                  this.getInstance().one('win').focus();
 753                              }
 754                          }
 755                          if (fn === true) {
 756                              this._handleFocus();
 757                          }
 758                          if (Y.Lang.isFunction(fn)) {
 759                              fn();
 760                          }
 761                      });
 762                  } catch (ferr) {
 763                      Y.log('Frame focus failed', 'warn', 'frame');
 764                  }
 765              }
 766              return this;
 767          },
 768          /**
 769          * @method show
 770          * @description Show the iframe instance
 771          * @return {Frame}
 772          * @chainable
 773          */
 774          show: function() {
 775              this._iframe.setStyles({
 776                  position: 'static',
 777                  left: ''
 778              });
 779              if (Y.UA.gecko) {
 780                  try {
 781                      if (this.getInstance()) {
 782                          this.getInstance().config.doc.designMode = 'on';
 783                      }
 784                  } catch (e) { }
 785                  this.focus();
 786              }
 787              return this;
 788          },
 789          /**
 790          * @method hide
 791          * @description Hide the iframe instance
 792          * @return {Frame}
 793          * @chainable
 794          */
 795          hide: function() {
 796              this._iframe.setStyles({
 797                  position: 'absolute',
 798                  left: '-999999px'
 799              });
 800              return this;
 801          }
 802      }, {
 803          /**
 804          * @static
 805          * @property THROTTLE_TIME
 806          * @description The throttle time for key events in IE
 807          * @type Number
 808          * @default 100
 809          */
 810          THROTTLE_TIME: 100,
 811          /**
 812          * @static
 813          * @property DOM_EVENTS
 814          * @description The DomEvents that the frame automatically attaches and bubbles
 815          * @type Object
 816          */
 817          DOM_EVENTS: {
 818              dblclick: 1,
 819              click: 1,
 820              paste: 1,
 821              mouseup: 1,
 822              mousedown: 1,
 823              keyup: 1,
 824              keydown: 1,
 825              keypress: 1,
 826              activate: 1,
 827              deactivate: 1,
 828              beforedeactivate: 1,
 829              focusin: 1,
 830              focusout: 1
 831          },
 832  
 833          /**
 834          * @static
 835          * @property DEFAULT_CSS
 836          * @description The default css used when creating the document.
 837          * @type String
 838          */
 839          DEFAULT_CSS: 'body { background-color: #fff; font: 13px/1.22 arial,helvetica,clean,sans-serif;*font-size:small;*font:x-small; } a, a:visited, a:hover { color: blue !important; text-decoration: underline !important; cursor: text !important; } img { cursor: pointer !important; border: none; }',
 840          /**
 841          * The template string used to create the iframe, deprecated to use DOM instead of innerHTML
 842          * @static
 843          * @property HTML
 844          * @type String
 845          * @deprecated
 846          */
 847          //HTML: '<iframe border="0" frameBorder="0" marginWidth="0" marginHeight="0" leftMargin="0" topMargin="0" allowTransparency="true" width="100%" height="99%"></iframe>',
 848          /**
 849          * Attributes to auto add to the dynamic iframe under the hood
 850          * @static
 851          * @property IFRAME_ATTRS
 852          * @type Object
 853          */
 854          IFRAME_ATTRS: {
 855              border: '0',
 856              frameBorder: '0',
 857              marginWidth: '0',
 858              marginHeight: '0',
 859              leftMargin: '0',
 860              topMargin: '0',
 861              allowTransparency: 'true',
 862              width: "100%",
 863              height: "99%"
 864          },
 865          /**
 866          * @static
 867          * @property PAGE_HTML
 868          * @description The template used to create the page when created dynamically.
 869          * @type String
 870          */
 871          PAGE_HTML: '<html dir="{DIR}" lang="{LANG}"><head><title>{TITLE}</title>{META}<base href="{BASE_HREF}"/>{LINKED_CSS}<style id="editor_css">{DEFAULT_CSS}</style>{EXTRA_CSS}</head><body>{CONTENT}</body></html>',
 872  
 873          /**
 874          * @static
 875          * @method getDocType
 876          * @description Parses document.doctype and generates a DocType to match the parent page, if supported.
 877          * For IE8, it grabs document.all[0].nodeValue and uses that. For IE < 8, it falls back to Frame.DOC_TYPE.
 878          * @return {String} The normalized DocType to apply to the iframe
 879          */
 880          getDocType: function() {
 881              var dt = Y.config.doc.doctype,
 882                  str = Frame.DOC_TYPE;
 883  
 884              if (dt) {
 885                  str = '<!DOCTYPE ' + dt.name + ((dt.publicId) ? ' ' + dt.publicId : '') + ((dt.systemId) ? ' ' + dt.systemId : '') + '>';
 886              } else {
 887                  if (Y.config.doc.all) {
 888                      dt = Y.config.doc.all[0];
 889                      if (dt.nodeType) {
 890                          if (dt.nodeType === 8) {
 891                              if (dt.nodeValue) {
 892                                  if (dt.nodeValue.toLowerCase().indexOf('doctype') !== -1) {
 893                                      str = '<!' + dt.nodeValue + '>';
 894                                  }
 895                              }
 896                          }
 897                      }
 898                  }
 899              }
 900              return str;
 901          },
 902          /**
 903          * @static
 904          * @property DOC_TYPE
 905          * @description The DOCTYPE to prepend to the new document when created. Should match the one on the page being served.
 906          * @type String
 907          */
 908          DOC_TYPE: '<!DOCTYPE HTML PUBLIC "-/'+'/W3C/'+'/DTD HTML 4.01/'+'/EN" "http:/'+'/www.w3.org/TR/html4/strict.dtd">',
 909          /**
 910          * @static
 911          * @property META
 912          * @description The meta-tag for Content-Type to add to the dynamic document
 913          * @type String
 914          */
 915          META: '<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/><meta http-equiv="X-UA-Compatible" content="IE=7">',
 916          //META: '<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>',
 917          /**
 918          * @static
 919          * @property NAME
 920          * @description The name of the class (frame)
 921          * @type String
 922          */
 923          NAME: 'frame',
 924          /**
 925          * The namespace on which Frame plugin will reside.
 926          *
 927          * @property NS
 928          * @type String
 929          * @default 'frame'
 930          * @static
 931          */
 932          NS: 'frame',
 933          ATTRS: {
 934              /**
 935              * @attribute title
 936              * @description The title to give the blank page.
 937              * @type String
 938              */
 939              title: {
 940                  value: 'Blank Page'
 941              },
 942              /**
 943              * @attribute dir
 944              * @description The default text direction for this new frame. Default: ltr
 945              * @type String
 946              */
 947              dir: {
 948                  value: 'ltr'
 949              },
 950              /**
 951              * @attribute lang
 952              * @description The default language. Default: en-US
 953              * @type String
 954              */
 955              lang: {
 956                  value: 'en-US'
 957              },
 958              /**
 959              * @attribute src
 960              * @description The src of the iframe/window. Defaults to javascript:;
 961              * @type String
 962              */
 963              src: {
 964                  //Hackish, IE needs the false in the Javascript URL
 965                  value: 'javascript' + ((Y.UA.ie) ? ':false' : ':') + ';'
 966              },
 967              /**
 968              * @attribute designMode
 969              * @description Should designMode be turned on after creation.
 970              * @writeonce
 971              * @type Boolean
 972              */
 973              designMode: {
 974                  writeOnce: true,
 975                  value: false
 976              },
 977              /**
 978              * @attribute content
 979              * @description The string to inject into the body of the new frame/window.
 980              * @type String
 981              */
 982              content: {
 983                  validator: Lang.isString,
 984                  value: '<br>',
 985                  setter: '_setHTML',
 986                  getter: '_getHTML'
 987              },
 988              /**
 989              * @attribute basehref
 990              * @description The base href to use in the iframe.
 991              * @type String
 992              */
 993              basehref: {
 994                  value: false,
 995                  getter: '_resolveBaseHref'
 996              },
 997              /**
 998              * @attribute use
 999              * @description Array of modules to include in the scoped YUI instance at render time. Default: ['none', 'selector-css2']
1000              * @writeonce
1001              * @type Array
1002              */
1003              use: {
1004                  writeOnce: true,
1005                  value: ['node', 'node-style', 'selector-css3']
1006              },
1007              /**
1008              * @attribute container
1009              * @description The container to append the iFrame to on render.
1010              * @type String/HTMLElement/Node
1011              */
1012              container: {
1013                  value: 'body',
1014                  setter: function(n) {
1015                      return Y.one(n);
1016                  }
1017              },
1018              /**
1019              * @attribute node
1020              * @description The Node instance of the iframe.
1021              * @type Node
1022              */
1023              node: {
1024                  readOnly: true,
1025                  value: null,
1026                  getter: function() {
1027                      return this._iframe;
1028                  }
1029              },
1030              /**
1031              * @attribute id
1032              * @description Set the id of the new Node. (optional)
1033              * @type String
1034              * @writeonce
1035              */
1036              id: {
1037                  writeOnce: true,
1038                  getter: function(id) {
1039                      if (!id) {
1040                          id = 'iframe-' + Y.guid();
1041                      }
1042                      return id;
1043                  }
1044              },
1045              /**
1046              * @attribute linkedcss
1047              * @description An array of url's to external linked style sheets
1048              * @type String|Array
1049              */
1050              linkedcss: {
1051                  validator: '_validateLinkedCSS',
1052                  getter: '_getLinkedCSS',
1053                  setter: '_setLinkedCSS'
1054              },
1055              /**
1056              * @attribute extracss
1057              * @description A string of CSS to add to the Head of the Editor
1058              * @type String
1059              */
1060              extracss: {
1061                  validator: Lang.isString,
1062                  setter: '_setExtraCSS'
1063              },
1064              /**
1065              * @attribute defaultblock
1066              * @description The default tag to use for block level items, defaults to: p
1067              * @type String
1068              */
1069              defaultblock: {
1070                  value: 'p'
1071              }
1072          }
1073      });
1074  
1075      Y.namespace('Plugin');
1076  
1077      Y.Plugin.Frame = Frame;
1078  
1079      Y.Frame = Frame;
1080  
1081  
1082  
1083  }, '3.17.2', {"requires": ["base", "node", "plugin", "selector-css3", "yui-throttle"]});


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