[ Index ] |
PHP Cross Reference of Unnamed Project |
[Summary view] [Print] [Text view]
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"]});
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Thu Aug 11 10:00:09 2016 | Cross-referenced by PHPXref 0.7.1 |