123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403 |
- /**
- * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md or http://ckeditor.com/license
- */
- ( function() {
- CKEDITOR.plugins.add( 'panel', {
- beforeInit: function( editor ) {
- editor.ui.addHandler( CKEDITOR.UI_PANEL, CKEDITOR.ui.panel.handler );
- }
- } );
- /**
- * Panel UI element.
- *
- * @readonly
- * @property {String} [='panel']
- * @member CKEDITOR
- */
- CKEDITOR.UI_PANEL = 'panel';
- /**
- * @class
- * @constructor Creates a panel class instance.
- * @param {CKEDITOR.dom.document} document
- * @param {Object} definition
- */
- CKEDITOR.ui.panel = function( document, definition ) {
- // Copy all definition properties to this object.
- if ( definition )
- CKEDITOR.tools.extend( this, definition );
- // Set defaults.
- CKEDITOR.tools.extend( this, {
- className: '',
- css: []
- } );
- this.id = CKEDITOR.tools.getNextId();
- this.document = document;
- this.isFramed = this.forceIFrame || this.css.length;
- this._ = {
- blocks: {}
- };
- };
- /**
- * Represents panel handler object.
- *
- * @class
- * @singleton
- * @extends CKEDITOR.ui.handlerDefinition
- */
- CKEDITOR.ui.panel.handler = {
- /**
- * Transforms a panel definition in a {@link CKEDITOR.ui.panel} instance.
- *
- * @param {Object} definition
- * @returns {CKEDITOR.ui.panel}
- */
- create: function( definition ) {
- return new CKEDITOR.ui.panel( definition );
- }
- };
- var panelTpl = CKEDITOR.addTemplate( 'panel', '<div lang="{langCode}" id="{id}" dir={dir}' +
- ' class="cke cke_reset_all {editorId} cke_panel cke_panel {cls} cke_{dir}"' +
- ' style="z-index:{z-index}" role="presentation">' +
- '{frame}' +
- '</div>' );
- var frameTpl = CKEDITOR.addTemplate( 'panel-frame', '<iframe id="{id}" class="cke_panel_frame" role="presentation" frameborder="0" src="{src}"></iframe>' );
- var frameDocTpl = CKEDITOR.addTemplate( 'panel-frame-inner', '<!DOCTYPE html>' +
- '<html class="cke_panel_container {env}" dir="{dir}" lang="{langCode}">' +
- '<head>{css}</head>' +
- '<body class="cke_{dir}"' +
- ' style="margin:0;padding:0" onload="{onload}"></body>' +
- '<\/html>' );
- /** @class CKEDITOR.ui.panel */
- CKEDITOR.ui.panel.prototype = {
- /**
- * Renders the combo.
- *
- * @param {CKEDITOR.editor} editor The editor instance which this button is
- * to be used by.
- * @param {Array} [output] The output array to which append the HTML relative
- * to this button.
- */
- render: function( editor, output ) {
- this.getHolderElement = function() {
- var holder = this._.holder;
- if ( !holder ) {
- if ( this.isFramed ) {
- var iframe = this.document.getById( this.id + '_frame' ),
- parentDiv = iframe.getParent(),
- doc = iframe.getFrameDocument();
- // Make it scrollable on iOS. (#8308)
- CKEDITOR.env.iOS && parentDiv.setStyles( {
- 'overflow': 'scroll',
- '-webkit-overflow-scrolling': 'touch'
- } );
- var onLoad = CKEDITOR.tools.addFunction( CKEDITOR.tools.bind( function() {
- this.isLoaded = true;
- if ( this.onLoad )
- this.onLoad();
- }, this ) );
- doc.write( frameDocTpl.output( CKEDITOR.tools.extend( {
- css: CKEDITOR.tools.buildStyleHtml( this.css ),
- onload: 'window.parent.CKEDITOR.tools.callFunction(' + onLoad + ');'
- }, data ) ) );
- var win = doc.getWindow();
- // Register the CKEDITOR global.
- win.$.CKEDITOR = CKEDITOR;
- // Arrow keys for scrolling is only preventable with 'keypress' event in Opera (#4534).
- doc.on( 'keydown', function( evt ) {
- var keystroke = evt.data.getKeystroke(),
- dir = this.document.getById( this.id ).getAttribute( 'dir' );
- // Delegate key processing to block.
- if ( this._.onKeyDown && this._.onKeyDown( keystroke ) === false ) {
- evt.data.preventDefault();
- return;
- }
- // ESC/ARROW-LEFT(ltr) OR ARROW-RIGHT(rtl)
- if ( keystroke == 27 || keystroke == ( dir == 'rtl' ? 39 : 37 ) ) {
- if ( this.onEscape && this.onEscape( keystroke ) === false )
- evt.data.preventDefault();
- }
- }, this );
- holder = doc.getBody();
- holder.unselectable();
- CKEDITOR.env.air && CKEDITOR.tools.callFunction( onLoad );
- } else {
- holder = this.document.getById( this.id );
- }
- this._.holder = holder;
- }
- return holder;
- };
- var data = {
- editorId: editor.id,
- id: this.id,
- langCode: editor.langCode,
- dir: editor.lang.dir,
- cls: this.className,
- frame: '',
- env: CKEDITOR.env.cssClass,
- 'z-index': editor.config.baseFloatZIndex + 1
- };
- if ( this.isFramed ) {
- // With IE, the custom domain has to be taken care at first,
- // for other browers, the 'src' attribute should be left empty to
- // trigger iframe's 'load' event.
- var src =
- CKEDITOR.env.air ? 'javascript:void(0)' : // jshint ignore:line
- CKEDITOR.env.ie ? 'javascript:void(function(){' + encodeURIComponent( // jshint ignore:line
- 'document.open();' +
- // In IE, the document domain must be set any time we call document.open().
- '(' + CKEDITOR.tools.fixDomain + ')();' +
- 'document.close();'
- ) + '}())' :
- '';
- data.frame = frameTpl.output( {
- id: this.id + '_frame',
- src: src
- } );
- }
- var html = panelTpl.output( data );
- if ( output )
- output.push( html );
- return html;
- },
- /**
- * @todo
- */
- addBlock: function( name, block ) {
- block = this._.blocks[ name ] = block instanceof CKEDITOR.ui.panel.block ? block : new CKEDITOR.ui.panel.block( this.getHolderElement(), block );
- if ( !this._.currentBlock )
- this.showBlock( name );
- return block;
- },
- /**
- * @todo
- */
- getBlock: function( name ) {
- return this._.blocks[ name ];
- },
- /**
- * @todo
- */
- showBlock: function( name ) {
- var blocks = this._.blocks,
- block = blocks[ name ],
- current = this._.currentBlock;
- // ARIA role works better in IE on the body element, while on the iframe
- // for FF. (#8864)
- var holder = !this.forceIFrame || CKEDITOR.env.ie ? this._.holder : this.document.getById( this.id + '_frame' );
- if ( current )
- current.hide();
- this._.currentBlock = block;
- CKEDITOR.fire( 'ariaWidget', holder );
- // Reset the focus index, so it will always go into the first one.
- block._.focusIndex = -1;
- this._.onKeyDown = block.onKeyDown && CKEDITOR.tools.bind( block.onKeyDown, block );
- block.show();
- return block;
- },
- /**
- * @todo
- */
- destroy: function() {
- this.element && this.element.remove();
- }
- };
- /**
- * @class
- *
- * @todo class and all methods
- */
- CKEDITOR.ui.panel.block = CKEDITOR.tools.createClass( {
- /**
- * Creates a block class instances.
- *
- * @constructor
- * @todo
- */
- $: function( blockHolder, blockDefinition ) {
- this.element = blockHolder.append( blockHolder.getDocument().createElement( 'div', {
- attributes: {
- 'tabindex': -1,
- 'class': 'cke_panel_block'
- },
- styles: {
- display: 'none'
- }
- } ) );
- // Copy all definition properties to this object.
- if ( blockDefinition )
- CKEDITOR.tools.extend( this, blockDefinition );
- // Set the a11y attributes of this element ...
- this.element.setAttributes( {
- 'role': this.attributes.role || 'presentation',
- 'aria-label': this.attributes[ 'aria-label' ],
- 'title': this.attributes.title || this.attributes[ 'aria-label' ]
- } );
- this.keys = {};
- this._.focusIndex = -1;
- // Disable context menu for panels.
- this.element.disableContextMenu();
- },
- _: {
- /**
- * Mark the item specified by the index as current activated.
- */
- markItem: function( index ) {
- if ( index == -1 )
- return;
- var links = this.element.getElementsByTag( 'a' );
- var item = links.getItem( this._.focusIndex = index );
- // Safari need focus on the iframe window first(#3389), but we need
- // lock the blur to avoid hiding the panel.
- if ( CKEDITOR.env.webkit )
- item.getDocument().getWindow().focus();
- item.focus();
- this.onMark && this.onMark( item );
- }
- },
- proto: {
- show: function() {
- this.element.setStyle( 'display', '' );
- },
- hide: function() {
- if ( !this.onHide || this.onHide.call( this ) !== true )
- this.element.setStyle( 'display', 'none' );
- },
- onKeyDown: function( keystroke, noCycle ) {
- var keyAction = this.keys[ keystroke ];
- switch ( keyAction ) {
- // Move forward.
- case 'next':
- var index = this._.focusIndex,
- links = this.element.getElementsByTag( 'a' ),
- link;
- while ( ( link = links.getItem( ++index ) ) ) {
- // Move the focus only if the element is marked with
- // the _cke_focus and it it's visible (check if it has
- // width).
- if ( link.getAttribute( '_cke_focus' ) && link.$.offsetWidth ) {
- this._.focusIndex = index;
- link.focus();
- break;
- }
- }
- // If no link was found, cycle and restart from the top. (#11125)
- if ( !link && !noCycle ) {
- this._.focusIndex = -1;
- return this.onKeyDown( keystroke, 1 );
- }
- return false;
- // Move backward.
- case 'prev':
- index = this._.focusIndex;
- links = this.element.getElementsByTag( 'a' );
- while ( index > 0 && ( link = links.getItem( --index ) ) ) {
- // Move the focus only if the element is marked with
- // the _cke_focus and it it's visible (check if it has
- // width).
- if ( link.getAttribute( '_cke_focus' ) && link.$.offsetWidth ) {
- this._.focusIndex = index;
- link.focus();
- break;
- }
- // Make sure link is null when the loop ends and nothing was
- // found (#11125).
- link = null;
- }
- // If no link was found, cycle and restart from the bottom. (#11125)
- if ( !link && !noCycle ) {
- this._.focusIndex = links.count();
- return this.onKeyDown( keystroke, 1 );
- }
- return false;
- case 'click':
- case 'mouseup':
- index = this._.focusIndex;
- link = index >= 0 && this.element.getElementsByTag( 'a' ).getItem( index );
- if ( link )
- link.$[ keyAction ] ? link.$[ keyAction ]() : link.$[ 'on' + keyAction ]();
- return false;
- }
- return true;
- }
- }
- } );
- } )();
- /**
- * Fired when a panel is added to the document.
- *
- * @event ariaWidget
- * @member CKEDITOR
- * @param {Object} data The element wrapping the panel.
- */
|