diff --git a/static/.empty b/static/.empty deleted file mode 100644 index e69de29..0000000 diff --git a/static/djangocms_text_ckeditor/ckeditor/CHANGES.md b/static/djangocms_text_ckeditor/ckeditor/CHANGES.md deleted file mode 100644 index ff58654..0000000 --- a/static/djangocms_text_ckeditor/ckeditor/CHANGES.md +++ /dev/null @@ -1,1219 +0,0 @@ -CKEditor 4 Changelog -==================== - -## CKEditor 4.6.2 - -New Features: - -* [#16733](http://dev.ckeditor.com/ticket/16733): Added a new pastel color palette for the [Color Button](http://ckeditor.com/addon/colorbutton) plugin and a new [`config.colorButton_colorsPerRow`](http://docs.ckeditor.com/#!/api/CKEDITOR.config-cfg-colorButton_colorsPerRow) configuration option for setting the number of rows in the color selector. -* [#16752](http://dev.ckeditor.com/ticket/16752): Added a new Azerbaijani localization. Thanks to the [Azerbaijani language team](https://www.transifex.com/ckeditor/teams/11143/az/)! -* [#13818](http://dev.ckeditor.com/ticket/13818): It is now possible to group [Widget](http://ckeditor.com/addon/widget) [style definitions](http://docs.ckeditor.com/#!/guide/dev_styles-section-widget-styles), so applying one style disables the other. - -Fixed Issues: - -* [#13446](http://dev.ckeditor.com/ticket/13446): [Chrome] Fixed: It is possible to type in an unfocused inline editor. -* [#14856](http://dev.ckeditor.com/ticket/14856): Fixed: [Font size and font family](http://ckeditor.com/addon/font) reset each other when modified at certain positions. -* [#16745](http://dev.ckeditor.com/ticket/16745): [Edge] Fixed: List items are lost when [pasted from Word](http://ckeditor.com/addon/pastefromword). -* [#16682](http://dev.ckeditor.com/ticket/16682): [Edge] Fixed: A list gets [pasted from Word](http://ckeditor.com/addon/pastefromword) as a set of paragraphs. Added the [`config.pasteFromWord_heuristicsEdgeList`](http://docs.ckeditor.com/#!/api/CKEDITOR.config-cfg-pasteFromWord_heuristicsEdgeList) configuration option. -* [#10373](http://dev.ckeditor.com/ticket/10373): Fixed: Context menu items can be dragged into the editor. -* [#16728](http://dev.ckeditor.com/ticket/16728): [IE] Fixed: [Copy Formatting](http://ckeditor.com/addon/copyformatting) breaks the editor in Quirks Mode. -* [#16795](http://dev.ckeditor.com/ticket/16795): [IE] Fixed: [Copy Formatting](http://ckeditor.com/addon/copyformatting) breaks the editor in Compatibility Mode. -* [#16675](http://dev.ckeditor.com/ticket/16675): Fixed: Styles applied with [Copy Formatting](http://ckeditor.com/addon/copyformatting) to a single table cell are applied to the whole table. -* [#16753](http://dev.ckeditor.com/ticket/16753): Fixed: [`element.setSize`](http://docs.ckeditor.com/#!/api/CKEDITOR.dom.element-method-setSize) sets incorrect editor dimensions if the border width is represented as a fraction of pixels. -* [#16705](http://dev.ckeditor.com/ticket/16705): [Firefox] Fixed: Unable to paste images as Base64 strings when using [Clipboard](http://ckeditor.com/addon/clipboard). -* [#14869](http://dev.ckeditor.com/ticket/14869): Fixed: JavaScript error is thrown when trying to use [Find](http://ckeditor.com/addon/find) in a [`
`-based editor](http://ckeditor.com/addon/divarea). - -## CKEditor 4.6.1 - -New Features: - -* [#16639](http://dev.ckeditor.com/ticket/16639): The `callback` parameter in the [CKEDITOR.ajax.post](http://docs.ckeditor.com/#!/api/CKEDITOR.ajax-method-post) method became optional. - -Fixed Issues: - -* [#11064](http://dev.ckeditor.com/ticket/11064): [Blink, WebKit] Fixed: Cannot select all editor content when a widget or a non-editable element is the first or last element of the content. Also fixes this issue in the [Select All](http://ckeditor.com/addon/selectall) plugin. -* [#14755](http://dev.ckeditor.com/ticket/14755): [Blink, WebKit, IE8] Fixed: Browser hangs when a table is inserted in the place of a selected list with an empty last item. -* [#16624](http://dev.ckeditor.com/ticket/16624): Fixed: Improved the [Color Button](http://ckeditor.com/addon/colorbutton) plugin which will now normalize the CSS `background` property if it only contains a color value. This fixes missing background colors when using [Paste from Word](http://ckeditor.com/addon/pastefromword). -* [#16600](http://dev.ckeditor.com/ticket/16600): [Blink, WebKit] Fixed: Error thrown occasionally by an uninitialized editable for multiple CKEditor instances on the same page. - -## CKEditor 4.6 - -New Features: - -* [#14569](http://dev.ckeditor.com/ticket/14569): Added a new, flat, default CKEditor skin called [Moono-Lisa](http://ckeditor.com/addon/moono-lisa). Refreshed default colors available in the [Color Button](http://ckeditor.com/addon/colorbutton) plugin ([Text Color and Background Color](http://docs.ckeditor.com/#!/guide/dev_colorbutton) feature). -* [#14707](http://dev.ckeditor.com/ticket/14707): Added a new [Copy Formatting](http://ckeditor.com/addon/copyformatting) feature to enable easy copying of styles between your document parts. -* Introduced the completely rewritten [Paste from Word](http://ckeditor.com/addon/pastefromword) plugin: - * Backward incompatibility: The [`config.pasteFromWordRemoveFontStyles`](http://docs.ckeditor.com/#!/api/CKEDITOR.config-cfg-pasteFromWordRemoveFontStyles) option now defaults to `false`. This option will be deprecated in the future. Use [Advanced Content Filter](http://docs.ckeditor.com/#!/guide/dev_acf) to replicate the effect of setting it to `true`. - * Backward incompatibility: The [`config.pasteFromWordNumberedHeadingToList`](http://docs.ckeditor.com/#!/api/CKEDITOR.config-cfg-pasteFromWordNumberedHeadingToList) and [`config.pasteFromWordRemoveStyles`](http://docs.ckeditor.com/#!/api/CKEDITOR.config-cfg-pasteFromWordRemoveStyles) options were dropped and no longer have any effect on pasted content. - * Major improvements in preservation of list numbering, styling and indentation (nested lists with multiple levels). - * Major improvements in document structure parsing that fix plenty of issues with distorted or missing content after paste. -* Added new translation: Occitan. Thanks to [Cédric Valmary](https://totenoc.eu/)! -* [#10015](http://dev.ckeditor.com/ticket/10015): Keyboard shortcuts (relevant to the operating system in use) will now be displayed in tooltips and context menus. -* [#13794](http://dev.ckeditor.com/ticket/13794): The [Upload Image](http://ckeditor.com/addon/uploadimage) feature now uses `uploaded.width/height` if set. -* [#12541](http://dev.ckeditor.com/ticket/12541): Added the [Upload File](http://ckeditor.com/addon/uploadfile) plugin that lets you upload a file by drag&dropping it into the editor content. -* [#14449](http://dev.ckeditor.com/ticket/14449): Introduced the [Balloon Panel](http://ckeditor.com/addon/balloonpanel) plugin that lets you create stylish floating UI elements for the editor. -* [#12077](https://dev.ckeditor.com/ticket/12077): Added support for the HTML5 `download` attribute in link (``) elements. Selecting the "Force Download" checkbox in the [Link](http://ckeditor.com/addon/link) dialog will cause the linked file to be downloaded automatically. Thanks to [sbusse](https://github.com/sbusse)! -* [#13518](http://dev.ckeditor.com/ticket/13518): Introduced the [`additionalRequestParameters`](http://docs.ckeditor.com/#!/api/CKEDITOR.fileTools.uploadWidgetDefinition-property-additionalRequestParameters) property for file uploads to make it possible to send additional information about the uploaded file to the server. -* [#14889](http://dev.ckeditor.com/ticket/14889): Added the [`config.image2_altRequired`](http://docs.ckeditor.com/#!/api/CKEDITOR.config-cfg-image2_altRequired) option for the [Enhanced Image](http://ckeditor.com/addon/image2) plugin to allow making alternative text a mandatory field. Thanks to [Andrey Fedoseev](https://github.com/andreyfedoseev)! - -Fixed Issues: - -* [#9991](http://dev.ckeditor.com/ticket/9991): Fixed: [Paste from Word](http://ckeditor.com/addon/pastefromword) should only normalize input data. -* [#7209](http://dev.ckeditor.com/ticket/7209): Fixed: Lists with 3 levels not [pasted from Word](http://ckeditor.com/addon/pastefromword) correctly. -* [#14335](http://dev.ckeditor.com/ticket/14335): Fixed: Pasting a numbered list starting with a value different from "1" from Microsoft Word does not work correctly. -* [#14542](http://dev.ckeditor.com/ticket/14542): Fixed: Copying a numbered list from Microsoft Word does not preserve list formatting. -* [#14544](http://dev.ckeditor.com/ticket/14544): Fixed: Copying a nested list from Microsoft Word results in an empty list. -* [#14660](http://dev.ckeditor.com/ticket/14660): Fixed: [Pasting text from Word](http://ckeditor.com/addon/pastefromword) breaks the styling in some cases. -* [#14867](http://dev.ckeditor.com/ticket/14867): [Firefox] Fixed: Text gets stripped when [pasting content from Word](http://ckeditor.com/addon/pastefromword). -* [#2507](http://dev.ckeditor.com/ticket/2507): Fixed: [Paste from Word](http://ckeditor.com/addon/pastefromword) does not detect pasting a part of a paragraph. -* [#3336](http://dev.ckeditor.com/ticket/3336): Fixed: Extra blank row added on top of the content [pasted from Word](http://ckeditor.com/addon/pastefromword). -* [#6115](http://dev.ckeditor.com/ticket/6115): Fixed: When Right-to-Left text direction is applied to a table [pasted from Word](http://ckeditor.com/addon/pastefromword), borders are missing on one side. -* [#6342](http://dev.ckeditor.com/ticket/6342): Fixed: [Paste from Word](http://ckeditor.com/addon/pastefromword) filters out a basic text style when it is [configured to use attributes](http://docs.ckeditor.com/#!/guide/dev_basicstyles-section-custom-basic-text-style-definition). -* [#6457](http://dev.ckeditor.com/ticket/6457): [IE] Fixed: [Pasting from Word](http://ckeditor.com/addon/pastefromword) is extremely slow. -* [#6789](http://dev.ckeditor.com/ticket/6789): Fixed: The `mso-list: ignore` style is not handled properly when [pasting from Word](http://ckeditor.com/addon/pastefromword). -* [#7262](http://dev.ckeditor.com/ticket/7262): Fixed: Lists in preformatted body disappear when [pasting from Word](http://ckeditor.com/addon/pastefromword). -* [#7662](http://dev.ckeditor.com/ticket/7662): [Opera] Fixed: Extra empty number/bullet shown in the editor body when editing a multi-level list [pasted from Word](http://ckeditor.com/addon/pastefromword). -* [#7807](http://dev.ckeditor.com/ticket/7807): Fixed: Last item in a list not converted to a `
  • ` element after [pasting from Word](http://ckeditor.com/addon/pastefromword). -* [#7950](http://dev.ckeditor.com/ticket/7950): [IE] Fixed: Content [from Word pasted](http://ckeditor.com/addon/pastefromword) differently than in other browsers. -* [#7982](http://dev.ckeditor.com/ticket/7982): Fixed: Multi-level lists get split into smaller ones when [pasting from Word](http://ckeditor.com/addon/pastefromword). -* [#8231](http://dev.ckeditor.com/ticket/8231): [WebKit, Opera] Fixed: [Paste from Word](http://ckeditor.com/addon/pastefromword) inserts empty paragraphs. -* [#8266](http://dev.ckeditor.com/ticket/8266): Fixed: [Paste from Word](http://ckeditor.com/addon/pastefromword) inserts a blank line at the top. -* [#8341](http://dev.ckeditor.com/ticket/8341), [#7646](http://dev.ckeditor.com/ticket/7646): Fixed: Faulty removal of empty `` elements in [Paste from Word](http://ckeditor.com/addon/pastefromword) content cleanup breaking content formatting. -* [#8754](http://dev.ckeditor.com/ticket/8754): [Firefox] Fixed: Incorrect pasting of multiple nested lists in [Paste from Word](http://ckeditor.com/addon/pastefromword). -* [#8983](http://dev.ckeditor.com/ticket/8983): Fixed: Alignment lost when [pasting from Word](http://ckeditor.com/addon/pastefromword) with [`config.enterMode`](http://docs.ckeditor.com/#!/api/CKEDITOR.config-cfg-enterMode) set to [`CKEDITOR.ENTER_BR`](http://docs.ckeditor.com/#!/api/CKEDITOR-property-ENTER_BR). -* [#9331](http://dev.ckeditor.com/ticket/9331): [IE] Fixed: [Pasting text from Word](http://ckeditor.com/addon/pastefromword) creates a simple Caesar cipher. -* [#9422](http://dev.ckeditor.com/ticket/9422): Fixed: [Paste from Word](http://ckeditor.com/addon/pastefromword) leaves an unwanted `color:windowtext` style. -* [#10011](http://dev.ckeditor.com/ticket/10011): [IE9-10] Fixed: [`config.pasteFromWordRemoveFontStyles`](http://docs.ckeditor.com/#!/api/CKEDITOR.config-cfg-pasteFromWordRemoveFontStyles) is ignored under certain conditions. -* [#10643](http://dev.ckeditor.com/ticket/10643): Fixed: Differences between using Ctrl+V and pasting from the [Paste from Word](http://ckeditor.com/addon/pastefromword) dialog. -* [#10784](http://dev.ckeditor.com/ticket/10784): Fixed: Lines missing when [pasting from Word](http://ckeditor.com/addon/pastefromword). -* [#11294](http://dev.ckeditor.com/ticket/11294): [IE10] Fixed: Font size is not preserved when [pasting from Word](http://ckeditor.com/addon/pastefromword). -* [#11627](http://dev.ckeditor.com/ticket/11627): Fixed: Missing words when [pasting from Word](http://ckeditor.com/addon/pastefromword). -* [#12784](http://dev.ckeditor.com/ticket/12784): Fixed: Bulleted list with custom bullets gets changed to a numbered list when [pasting from Word](http://ckeditor.com/addon/pastefromword). -* [#13174](http://dev.ckeditor.com/ticket/13174): Fixed: Data loss after [pasting from Word](http://ckeditor.com/addon/pastefromword). -* [#13828](http://dev.ckeditor.com/ticket/13828): Fixed: Widget classes should be added to the wrapper rather than the widget element. -* [#13829](http://dev.ckeditor.com/ticket/13829): Fixed: No class in [Widget](http://ckeditor.com/addon/widget) wrapper to identify the widget type. -* [#13519](http://dev.ckeditor.com/ticket/13519): Server response received when uploading files should be more flexible. - -Other Changes: - -* Updated [SCAYT](http://ckeditor.com/addon/scayt) (Spell Check As You Type) and [WebSpellChecker](http://ckeditor.com/addon/wsc) plugins: - * Support for the new default Moono-Lisa skin. - * [#121](https://github.com/WebSpellChecker/ckeditor-plugin-scayt/issues/121): Fixed: [Basic Styles](http://ckeditor.com/addon/basicstyles) do not work when SCAYT is enabled. - * [#125](https://github.com/WebSpellChecker/ckeditor-plugin-scayt/issues/125): Fixed: Inline styles are not continued when writing multiple lines of styled text with SCAYT enabled. - * [#127](https://github.com/WebSpellChecker/ckeditor-plugin-scayt/issues/127): Fixed: Uncaught TypeError after enabling SCAYT in the CKEditor `
    ` element. - * [#128](https://github.com/WebSpellChecker/ckeditor-plugin-scayt/issues/128): Fixed: Error thrown after enabling SCAYT caused by conflicts with RequireJS. - -## CKEditor 4.5.11 - -**Security Updates:** - -* [Severity: minor] Fixed the `target="_blank"` vulnerability reported by James Gaskell. - - Issue summary: If a victim had access to a spoofed version of ckeditor.com via HTTP (e.g. due to DNS spoofing, using a hacked public network or mailicious hotspot), then when using a link to the ckeditor.com website it was possible for the attacker to change the current URL of the opening page, even if the opening page was protected with SSL. - - An upgrade is recommended. - -New Features: - -* [#14747](http://dev.ckeditor.com/ticket/14747): The [Enhanced Image](http://ckeditor.com/addon/image2) caption now supports the link `target` attribute. -* [#7154](http://dev.ckeditor.com/ticket/7154): Added support for the "Display Text" field to the [Link](http://ckeditor.com/addon/link) dialog. Thanks to [Ryan Guill](https://github.com/ryanguill)! - -Fixed Issues: - -* [#13362](http://dev.ckeditor.com/ticket/13362): [Blink, WebKit] Fixed: Active widget element is not cached when it is losing focus and it is inside an editable element. -* [#13755](http://dev.ckeditor.com/ticket/13755): [Edge] Fixed: Pasting images does not work. -* [#13548](http://dev.ckeditor.com/ticket/13548): [IE] Fixed: Clicking the [elements path](http://ckeditor.com/addon/elementspath) disables Cut and Copy icons. -* [#13812](http://dev.ckeditor.com/ticket/13812): Fixed: When aborting file upload the placeholder for image is left. -* [#14659](http://dev.ckeditor.com/ticket/14659): [Blink] Fixed: Content scrolled to the top after closing the dialog in a [`
    `-based editor](http://ckeditor.com/addon/divarea). -* [#14825](http://dev.ckeditor.com/ticket/14825): [Edge] Fixed: Focusing the editor causes unwanted scrolling due to dropped support for the `setActive` method. - -## CKEditor 4.5.10 - -Fixed Issues: - -* [#10750](http://dev.ckeditor.com/ticket/10750): Fixed: The editor does not escape the `font-style` family property correctly, removing quotes and whitespace from font names. -* [#14413](http://dev.ckeditor.com/ticket/14413): Fixed: The [Auto Grow](http://ckeditor.com/addon/autogrow) plugin with the [`config.autoGrow_onStartup`](http://docs.ckeditor.com/#!/api/CKEDITOR.config-cfg-autoGrow_onStartup) option set to `true` does not work properly for an editor that is not visible. -* [#14451](http://dev.ckeditor.com/ticket/14451): Fixed: Numeric element ID not escaped properly. Thanks to [Jakub Chalupa](https://github.com/chaluja7)! -* [#14590](http://dev.ckeditor.com/ticket/14590): Fixed: Additional line break appearing after inline elements when switching modes. Thanks to [dpidcock](https://github.com/dpidcock)! -* [#14539](https://dev.ckeditor.com/ticket/14539): Fixed: JAWS reads "selected Blank" instead of "selected " when selecting a widget. -* [#14701](http://dev.ckeditor.com/ticket/14701): Fixed: More precise labels for [Enhanced Image](http://ckeditor.com/addon/image2) and [Placeholder](http://ckeditor.com/addon/placeholder) widgets. -* [#14667](http://dev.ckeditor.com/ticket/14667): [IE] Fixed: Removing background color from selected text removes background color from the whole paragraph. -* [#14252](http://dev.ckeditor.com/ticket/14252): [IE] Fixed: Styles drop-down list does not always reflect the current style of the text line. -* [#14275](http://dev.ckeditor.com/ticket/14275): [IE9+] Fixed: `onerror` and `onload` events are not used in browsers it could have been used when loading scripts dynamically. - -## CKEditor 4.5.9 - -Fixed Issues: - -* [#10685](http://dev.ckeditor.com/ticket/10685): Fixed: Unreadable toolbar icons after updating to the new editor version. Fixed with [6876179](https://github.com/ckeditor/ckeditor-dev/commit/6876179db4ee97e786b07b8fd72e6b4120732185) in [ckeditor-dev](https://github.com/ckeditor/ckeditor-dev) and [6c9189f4](https://github.com/ckeditor/ckeditor-presets/commit/6c9189f46392d2c126854fe8889b820b8c76d291) in [ckeditor-presets](https://github.com/ckeditor/ckeditor-presets). -* [#14573](https://dev.ckeditor.com/ticket/14573): Fixed: Missing [Widget](http://ckeditor.com/addon/widget) drag handler CSS when there are multiple editor instances. -* [#14620](https://dev.ckeditor.com/ticket/14620): Fixed: Setting both the `min-height` style for the `` element and the `height` style for the `` element breaks the [Auto Grow](http://ckeditor.com/addon/autogrow) plugin. -* [#14538](http://dev.ckeditor.com/ticket/14538): Fixed: Keyboard focus goes into an embedded `' ); - iframe.appendTo( body.getParent() ); - } - - // Make the Title and Close Button unselectable. - title.unselectable(); - close.unselectable(); - - return { - element: element, - parts: { - dialog: element.getChild( 0 ), - title: title, - close: close, - tabs: body.getChild( 2 ), - contents: body.getChild( [ 3, 0, 0, 0 ] ), - footer: body.getChild( [ 3, 0, 1, 0 ] ) - } - }; - } - - /** - * This is the base class for runtime dialog objects. An instance of this - * class represents a single named dialog for a single editor instance. - * - * var dialogObj = new CKEDITOR.dialog( editor, 'smiley' ); - * - * @class - * @constructor Creates a dialog class instance. - * @param {Object} editor The editor which created the dialog. - * @param {String} dialogName The dialog's registered name. - */ - CKEDITOR.dialog = function( editor, dialogName ) { - // Load the dialog definition. - var definition = CKEDITOR.dialog._.dialogDefinitions[ dialogName ], - defaultDefinition = CKEDITOR.tools.clone( defaultDialogDefinition ), - buttonsOrder = editor.config.dialog_buttonsOrder || 'OS', - dir = editor.lang.dir, - tabsToRemove = {}, - i, processed, stopPropagation; - - if ( ( buttonsOrder == 'OS' && CKEDITOR.env.mac ) || // The buttons in MacOS Apps are in reverse order (#4750) - ( buttonsOrder == 'rtl' && dir == 'ltr' ) || ( buttonsOrder == 'ltr' && dir == 'rtl' ) ) - defaultDefinition.buttons.reverse(); - - - // Completes the definition with the default values. - definition = CKEDITOR.tools.extend( definition( editor ), defaultDefinition ); - - // Clone a functionally independent copy for this dialog. - definition = CKEDITOR.tools.clone( definition ); - - // Create a complex definition object, extending it with the API - // functions. - definition = new definitionObject( this, definition ); - - var themeBuilt = buildDialog( editor ); - - // Initialize some basic parameters. - this._ = { - editor: editor, - element: themeBuilt.element, - name: dialogName, - contentSize: { width: 0, height: 0 }, - size: { width: 0, height: 0 }, - contents: {}, - buttons: {}, - accessKeyMap: {}, - - // Initialize the tab and page map. - tabs: {}, - tabIdList: [], - currentTabId: null, - currentTabIndex: null, - pageCount: 0, - lastTab: null, - tabBarMode: false, - - // Initialize the tab order array for input widgets. - focusList: [], - currentFocusIndex: 0, - hasFocus: false - }; - - this.parts = themeBuilt.parts; - - CKEDITOR.tools.setTimeout( function() { - editor.fire( 'ariaWidget', this.parts.contents ); - }, 0, this ); - - // Set the startup styles for the dialog, avoiding it enlarging the - // page size on the dialog creation. - var startStyles = { - position: CKEDITOR.env.ie6Compat ? 'absolute' : 'fixed', - top: 0, - visibility: 'hidden' - }; - - startStyles[ dir == 'rtl' ? 'right' : 'left' ] = 0; - this.parts.dialog.setStyles( startStyles ); - - - // Call the CKEDITOR.event constructor to initialize this instance. - CKEDITOR.event.call( this ); - - // Fire the "dialogDefinition" event, making it possible to customize - // the dialog definition. - this.definition = definition = CKEDITOR.fire( 'dialogDefinition', { - name: dialogName, - definition: definition - }, editor ).definition; - - // Cache tabs that should be removed. - if ( !( 'removeDialogTabs' in editor._ ) && editor.config.removeDialogTabs ) { - var removeContents = editor.config.removeDialogTabs.split( ';' ); - - for ( i = 0; i < removeContents.length; i++ ) { - var parts = removeContents[ i ].split( ':' ); - if ( parts.length == 2 ) { - var removeDialogName = parts[ 0 ]; - if ( !tabsToRemove[ removeDialogName ] ) - tabsToRemove[ removeDialogName ] = []; - tabsToRemove[ removeDialogName ].push( parts[ 1 ] ); - } - } - editor._.removeDialogTabs = tabsToRemove; - } - - // Remove tabs of this dialog. - if ( editor._.removeDialogTabs && ( tabsToRemove = editor._.removeDialogTabs[ dialogName ] ) ) { - for ( i = 0; i < tabsToRemove.length; i++ ) - definition.removeContents( tabsToRemove[ i ] ); - } - - // Initialize load, show, hide, ok and cancel events. - if ( definition.onLoad ) - this.on( 'load', definition.onLoad ); - - if ( definition.onShow ) - this.on( 'show', definition.onShow ); - - if ( definition.onHide ) - this.on( 'hide', definition.onHide ); - - if ( definition.onOk ) { - this.on( 'ok', function( evt ) { - // Dialog confirm might probably introduce content changes (#5415). - editor.fire( 'saveSnapshot' ); - setTimeout( function() { - editor.fire( 'saveSnapshot' ); - }, 0 ); - if ( definition.onOk.call( this, evt ) === false ) - evt.data.hide = false; - } ); - } - - // Set default dialog state. - this.state = CKEDITOR.DIALOG_STATE_IDLE; - - if ( definition.onCancel ) { - this.on( 'cancel', function( evt ) { - if ( definition.onCancel.call( this, evt ) === false ) - evt.data.hide = false; - } ); - } - - var me = this; - - // Iterates over all items inside all content in the dialog, calling a - // function for each of them. - var iterContents = function( func ) { - var contents = me._.contents, - stop = false; - - for ( var i in contents ) { - for ( var j in contents[ i ] ) { - stop = func.call( this, contents[ i ][ j ] ); - if ( stop ) - return; - } - } - }; - - this.on( 'ok', function( evt ) { - iterContents( function( item ) { - if ( item.validate ) { - var retval = item.validate( this ), - invalid = ( typeof retval == 'string' ) || retval === false; - - if ( invalid ) { - evt.data.hide = false; - evt.stop(); - } - - handleFieldValidated.call( item, !invalid, typeof retval == 'string' ? retval : undefined ); - return invalid; - } - } ); - }, this, null, 0 ); - - this.on( 'cancel', function( evt ) { - iterContents( function( item ) { - if ( item.isChanged() ) { - if ( !editor.config.dialog_noConfirmCancel && !confirm( editor.lang.common.confirmCancel ) ) // jshint ignore:line - evt.data.hide = false; - return true; - } - } ); - }, this, null, 0 ); - - this.parts.close.on( 'click', function( evt ) { - if ( this.fire( 'cancel', { hide: true } ).hide !== false ) - this.hide(); - evt.data.preventDefault(); - }, this ); - - // Sort focus list according to tab order definitions. - function setupFocus() { - var focusList = me._.focusList; - focusList.sort( function( a, b ) { - // Mimics browser tab order logics; - if ( a.tabIndex != b.tabIndex ) - return b.tabIndex - a.tabIndex; - // Sort is not stable in some browsers, - // fall-back the comparator to 'focusIndex'; - else - return a.focusIndex - b.focusIndex; - } ); - - var size = focusList.length; - for ( var i = 0; i < size; i++ ) - focusList[ i ].focusIndex = i; - } - - // Expects 1 or -1 as an offset, meaning direction of the offset change. - function changeFocus( offset ) { - var focusList = me._.focusList; - offset = offset || 0; - - if ( focusList.length < 1 ) - return; - - var startIndex = me._.currentFocusIndex; - - if ( me._.tabBarMode && offset < 0 ) { - // If we are in tab mode, we need to mimic that we started tabbing back from the first - // focusList (so it will go to the last one). - startIndex = 0; - } - - // Trigger the 'blur' event of any input element before anything, - // since certain UI updates may depend on it. - try { - focusList[ startIndex ].getInputElement().$.blur(); - } catch ( e ) {} - - var currentIndex = startIndex, - hasTabs = me._.pageCount > 1; - - do { - currentIndex = currentIndex + offset; - - if ( hasTabs && !me._.tabBarMode && ( currentIndex == focusList.length || currentIndex == -1 ) ) { - // If the dialog was not in tab mode, then focus the first tab (#13027). - me._.tabBarMode = true; - me._.tabs[ me._.currentTabId ][ 0 ].focus(); - me._.currentFocusIndex = -1; - - // Early return, in order to avoid accessing focusList[ -1 ]. - return; - } - - currentIndex = ( currentIndex + focusList.length ) % focusList.length; - - if ( currentIndex == startIndex ) { - break; - } - } while ( offset && !focusList[ currentIndex ].isFocusable() ); - - focusList[ currentIndex ].focus(); - - // Select whole field content. - if ( focusList[ currentIndex ].type == 'text' ) - focusList[ currentIndex ].select(); - } - - this.changeFocus = changeFocus; - - - function keydownHandler( evt ) { - // If I'm not the top dialog, ignore. - if ( me != CKEDITOR.dialog._.currentTop ) - return; - - var keystroke = evt.data.getKeystroke(), - rtl = editor.lang.dir == 'rtl', - arrowKeys = [ 37, 38, 39, 40 ], - button; - - processed = stopPropagation = 0; - - if ( keystroke == 9 || keystroke == CKEDITOR.SHIFT + 9 ) { - var shiftPressed = ( keystroke == CKEDITOR.SHIFT + 9 ); - changeFocus( shiftPressed ? -1 : 1 ); - processed = 1; - } else if ( keystroke == CKEDITOR.ALT + 121 && !me._.tabBarMode && me.getPageCount() > 1 ) { - // Alt-F10 puts focus into the current tab item in the tab bar. - me._.tabBarMode = true; - me._.tabs[ me._.currentTabId ][ 0 ].focus(); - me._.currentFocusIndex = -1; - processed = 1; - } else if ( CKEDITOR.tools.indexOf( arrowKeys, keystroke ) != -1 && me._.tabBarMode ) { - // Array with key codes that activate previous tab. - var prevKeyCodes = [ - // Depending on the lang dir: right or left key - rtl ? 39 : 37, - // Top/bot arrow: actually for both cases it's the same. - 38 - ], - nextId = CKEDITOR.tools.indexOf( prevKeyCodes, keystroke ) != -1 ? getPreviousVisibleTab.call( me ) : getNextVisibleTab.call( me ); - - me.selectPage( nextId ); - me._.tabs[ nextId ][ 0 ].focus(); - processed = 1; - } else if ( ( keystroke == 13 || keystroke == 32 ) && me._.tabBarMode ) { - this.selectPage( this._.currentTabId ); - this._.tabBarMode = false; - this._.currentFocusIndex = -1; - changeFocus( 1 ); - processed = 1; - } - // If user presses enter key in a text box, it implies clicking OK for the dialog. - else if ( keystroke == 13 /*ENTER*/ ) { - // Don't do that for a target that handles ENTER. - var target = evt.data.getTarget(); - if ( !target.is( 'a', 'button', 'select', 'textarea' ) && ( !target.is( 'input' ) || target.$.type != 'button' ) ) { - button = this.getButton( 'ok' ); - button && CKEDITOR.tools.setTimeout( button.click, 0, button ); - processed = 1; - } - stopPropagation = 1; // Always block the propagation (#4269) - } else if ( keystroke == 27 /*ESC*/ ) { - button = this.getButton( 'cancel' ); - - // If there's a Cancel button, click it, else just fire the cancel event and hide the dialog. - if ( button ) - CKEDITOR.tools.setTimeout( button.click, 0, button ); - else { - if ( this.fire( 'cancel', { hide: true } ).hide !== false ) - this.hide(); - } - stopPropagation = 1; // Always block the propagation (#4269) - } else { - return; - } - - keypressHandler( evt ); - } - - function keypressHandler( evt ) { - if ( processed ) - evt.data.preventDefault( 1 ); - else if ( stopPropagation ) - evt.data.stopPropagation(); - } - - var dialogElement = this._.element; - - editor.focusManager.add( dialogElement, 1 ); - - // Add the dialog keyboard handlers. - this.on( 'show', function() { - dialogElement.on( 'keydown', keydownHandler, this ); - - // Some browsers instead, don't cancel key events in the keydown, but in the - // keypress. So we must do a longer trip in those cases. (#4531,#8985) - if ( CKEDITOR.env.gecko ) - dialogElement.on( 'keypress', keypressHandler, this ); - - } ); - this.on( 'hide', function() { - dialogElement.removeListener( 'keydown', keydownHandler ); - if ( CKEDITOR.env.gecko ) - dialogElement.removeListener( 'keypress', keypressHandler ); - - // Reset fields state when closing dialog. - iterContents( function( item ) { - resetField.apply( item ); - } ); - } ); - this.on( 'iframeAdded', function( evt ) { - var doc = new CKEDITOR.dom.document( evt.data.iframe.$.contentWindow.document ); - doc.on( 'keydown', keydownHandler, this, null, 0 ); - } ); - - // Auto-focus logic in dialog. - this.on( 'show', function() { - // Setup tabIndex on showing the dialog instead of on loading - // to allow dynamic tab order happen in dialog definition. - setupFocus(); - - var hasTabs = me._.pageCount > 1; - - if ( editor.config.dialog_startupFocusTab && hasTabs ) { - me._.tabBarMode = true; - me._.tabs[ me._.currentTabId ][ 0 ].focus(); - me._.currentFocusIndex = -1; - } else if ( !this._.hasFocus ) { - // http://dev.ckeditor.com/ticket/13114#comment:4. - this._.currentFocusIndex = hasTabs ? -1 : this._.focusList.length - 1; - - // Decide where to put the initial focus. - if ( definition.onFocus ) { - var initialFocus = definition.onFocus.call( this ); - // Focus the field that the user specified. - initialFocus && initialFocus.focus(); - } - // Focus the first field in layout order. - else { - changeFocus( 1 ); - } - } - }, this, null, 0xffffffff ); - - // IE6 BUG: Text fields and text areas are only half-rendered the first time the dialog appears in IE6 (#2661). - // This is still needed after [2708] and [2709] because text fields in hidden TR tags are still broken. - if ( CKEDITOR.env.ie6Compat ) { - this.on( 'load', function() { - var outer = this.getElement(), - inner = outer.getFirst(); - inner.remove(); - inner.appendTo( outer ); - }, this ); - } - - initDragAndDrop( this ); - initResizeHandles( this ); - - // Insert the title. - ( new CKEDITOR.dom.text( definition.title, CKEDITOR.document ) ).appendTo( this.parts.title ); - - // Insert the tabs and contents. - for ( i = 0; i < definition.contents.length; i++ ) { - var page = definition.contents[ i ]; - page && this.addPage( page ); - } - - this.parts.tabs.on( 'click', function( evt ) { - var target = evt.data.getTarget(); - // If we aren't inside a tab, bail out. - if ( target.hasClass( 'cke_dialog_tab' ) ) { - // Get the ID of the tab, without the 'cke_' prefix and the unique number suffix. - var id = target.$.id; - this.selectPage( id.substring( 4, id.lastIndexOf( '_' ) ) ); - - if ( this._.tabBarMode ) { - this._.tabBarMode = false; - this._.currentFocusIndex = -1; - changeFocus( 1 ); - } - evt.data.preventDefault(); - } - }, this ); - - // Insert buttons. - var buttonsHtml = [], - buttons = CKEDITOR.dialog._.uiElementBuilders.hbox.build( this, { - type: 'hbox', - className: 'cke_dialog_footer_buttons', - widths: [], - children: definition.buttons - }, buttonsHtml ).getChild(); - this.parts.footer.setHtml( buttonsHtml.join( '' ) ); - - for ( i = 0; i < buttons.length; i++ ) - this._.buttons[ buttons[ i ].id ] = buttons[ i ]; - - /** - * Current state of the dialog. Use the {@link #setState} method to update it. - * See the {@link #event-state} event to know more. - * - * @readonly - * @property {Number} [state=CKEDITOR.DIALOG_STATE_IDLE] - */ - }; - - // Focusable interface. Use it via dialog.addFocusable. - function Focusable( dialog, element, index ) { - this.element = element; - this.focusIndex = index; - // TODO: support tabIndex for focusables. - this.tabIndex = 0; - this.isFocusable = function() { - return !element.getAttribute( 'disabled' ) && element.isVisible(); - }; - this.focus = function() { - dialog._.currentFocusIndex = this.focusIndex; - this.element.focus(); - }; - // Bind events - element.on( 'keydown', function( e ) { - if ( e.data.getKeystroke() in { 32: 1, 13: 1 } ) - this.fire( 'click' ); - } ); - element.on( 'focus', function() { - this.fire( 'mouseover' ); - } ); - element.on( 'blur', function() { - this.fire( 'mouseout' ); - } ); - } - - // Re-layout the dialog on window resize. - function resizeWithWindow( dialog ) { - var win = CKEDITOR.document.getWindow(); - function resizeHandler() { - dialog.layout(); - } - win.on( 'resize', resizeHandler ); - dialog.on( 'hide', function() { - win.removeListener( 'resize', resizeHandler ); - } ); - } - - CKEDITOR.dialog.prototype = { - destroy: function() { - this.hide(); - this._.element.remove(); - }, - - /** - * Resizes the dialog. - * - * dialogObj.resize( 800, 640 ); - * - * @method - * @param {Number} width The width of the dialog in pixels. - * @param {Number} height The height of the dialog in pixels. - */ - resize: ( function() { - return function( width, height ) { - if ( this._.contentSize && this._.contentSize.width == width && this._.contentSize.height == height ) - return; - - CKEDITOR.dialog.fire( 'resize', { - dialog: this, - width: width, - height: height - }, this._.editor ); - - this.fire( 'resize', { - width: width, - height: height - }, this._.editor ); - - var contents = this.parts.contents; - contents.setStyles( { - width: width + 'px', - height: height + 'px' - } ); - - // Update dialog position when dimension get changed in RTL. - if ( this._.editor.lang.dir == 'rtl' && this._.position ) - this._.position.x = CKEDITOR.document.getWindow().getViewPaneSize().width - this._.contentSize.width - parseInt( this._.element.getFirst().getStyle( 'right' ), 10 ); - - this._.contentSize = { width: width, height: height }; - }; - } )(), - - /** - * Gets the current size of the dialog in pixels. - * - * var width = dialogObj.getSize().width; - * - * @returns {Object} - * @returns {Number} return.width - * @returns {Number} return.height - */ - getSize: function() { - var element = this._.element.getFirst(); - return { width: element.$.offsetWidth || 0, height: element.$.offsetHeight || 0 }; - }, - - /** - * Moves the dialog to an `(x, y)` coordinate relative to the window. - * - * dialogObj.move( 10, 40 ); - * - * @method - * @param {Number} x The target x-coordinate. - * @param {Number} y The target y-coordinate. - * @param {Boolean} save Flag indicate whether the dialog position should be remembered on next open up. - */ - move: function( x, y, save ) { - - // The dialog may be fixed positioned or absolute positioned. Ask the - // browser what is the current situation first. - var element = this._.element.getFirst(), rtl = this._.editor.lang.dir == 'rtl'; - var isFixed = element.getComputedStyle( 'position' ) == 'fixed'; - - // (#8888) In some cases of a very small viewport, dialog is incorrectly - // positioned in IE7. It also happens that it remains sticky and user cannot - // scroll down/up to reveal dialog's content below/above the viewport; this is - // cumbersome. - // The only way to fix this is to move mouse out of the browser and - // go back to see that dialog position is automagically fixed. No events, - // no style change - pure magic. This is a IE7 rendering issue, which can be - // fixed with dummy style redraw on each move. - if ( CKEDITOR.env.ie ) - element.setStyle( 'zoom', '100%' ); - - if ( isFixed && this._.position && this._.position.x == x && this._.position.y == y ) - return; - - // Save the current position. - this._.position = { x: x, y: y }; - - // If not fixed positioned, add scroll position to the coordinates. - if ( !isFixed ) { - var scrollPosition = CKEDITOR.document.getWindow().getScrollPosition(); - x += scrollPosition.x; - y += scrollPosition.y; - } - - // Translate coordinate for RTL. - if ( rtl ) { - var dialogSize = this.getSize(), viewPaneSize = CKEDITOR.document.getWindow().getViewPaneSize(); - x = viewPaneSize.width - dialogSize.width - x; - } - - var styles = { 'top': ( y > 0 ? y : 0 ) + 'px' }; - styles[ rtl ? 'right' : 'left' ] = ( x > 0 ? x : 0 ) + 'px'; - - element.setStyles( styles ); - - save && ( this._.moved = 1 ); - }, - - /** - * Gets the dialog's position in the window. - * - * var dialogX = dialogObj.getPosition().x; - * - * @returns {Object} - * @returns {Number} return.x - * @returns {Number} return.y - */ - getPosition: function() { - return CKEDITOR.tools.extend( {}, this._.position ); - }, - - /** - * Shows the dialog box. - * - * dialogObj.show(); - */ - show: function() { - // Insert the dialog's element to the root document. - var element = this._.element; - var definition = this.definition; - if ( !( element.getParent() && element.getParent().equals( CKEDITOR.document.getBody() ) ) ) - element.appendTo( CKEDITOR.document.getBody() ); - else - element.setStyle( 'display', 'block' ); - - // First, set the dialog to an appropriate size. - this.resize( - this._.contentSize && this._.contentSize.width || definition.width || definition.minWidth, - this._.contentSize && this._.contentSize.height || definition.height || definition.minHeight - ); - - // Reset all inputs back to their default value. - this.reset(); - - // Select the first tab by default. - this.selectPage( this.definition.contents[ 0 ].id ); - - // Set z-index. - if ( CKEDITOR.dialog._.currentZIndex === null ) - CKEDITOR.dialog._.currentZIndex = this._.editor.config.baseFloatZIndex; - this._.element.getFirst().setStyle( 'z-index', CKEDITOR.dialog._.currentZIndex += 10 ); - - // Maintain the dialog ordering and dialog cover. - if ( CKEDITOR.dialog._.currentTop === null ) { - CKEDITOR.dialog._.currentTop = this; - this._.parentDialog = null; - showCover( this._.editor ); - - } else { - this._.parentDialog = CKEDITOR.dialog._.currentTop; - var parentElement = this._.parentDialog.getElement().getFirst(); - parentElement.$.style.zIndex -= Math.floor( this._.editor.config.baseFloatZIndex / 2 ); - CKEDITOR.dialog._.currentTop = this; - } - - element.on( 'keydown', accessKeyDownHandler ); - element.on( 'keyup', accessKeyUpHandler ); - - // Reset the hasFocus state. - this._.hasFocus = false; - - for ( var i in definition.contents ) { - if ( !definition.contents[ i ] ) - continue; - - var content = definition.contents[ i ], - tab = this._.tabs[ content.id ], - requiredContent = content.requiredContent, - enableElements = 0; - - if ( !tab ) - continue; - - for ( var j in this._.contents[ content.id ] ) { - var elem = this._.contents[ content.id ][ j ]; - - if ( elem.type == 'hbox' || elem.type == 'vbox' || !elem.getInputElement() ) - continue; - - if ( elem.requiredContent && !this._.editor.activeFilter.check( elem.requiredContent ) ) - elem.disable(); - else { - elem.enable(); - enableElements++; - } - } - - if ( !enableElements || ( requiredContent && !this._.editor.activeFilter.check( requiredContent ) ) ) - tab[ 0 ].addClass( 'cke_dialog_tab_disabled' ); - else - tab[ 0 ].removeClass( 'cke_dialog_tab_disabled' ); - } - - CKEDITOR.tools.setTimeout( function() { - this.layout(); - resizeWithWindow( this ); - - this.parts.dialog.setStyle( 'visibility', '' ); - - // Execute onLoad for the first show. - this.fireOnce( 'load', {} ); - CKEDITOR.ui.fire( 'ready', this ); - - this.fire( 'show', {} ); - this._.editor.fire( 'dialogShow', this ); - - if ( !this._.parentDialog ) - this._.editor.focusManager.lock(); - - // Save the initial values of the dialog. - this.foreach( function( contentObj ) { - contentObj.setInitValue && contentObj.setInitValue(); - } ); - - }, 100, this ); - }, - - /** - * Rearrange the dialog to its previous position or the middle of the window. - * - * @since 3.5 - */ - layout: function() { - var el = this.parts.dialog; - var dialogSize = this.getSize(); - var win = CKEDITOR.document.getWindow(), - viewSize = win.getViewPaneSize(); - - var posX = ( viewSize.width - dialogSize.width ) / 2, - posY = ( viewSize.height - dialogSize.height ) / 2; - - // Switch to absolute position when viewport is smaller than dialog size. - if ( !CKEDITOR.env.ie6Compat ) { - if ( dialogSize.height + ( posY > 0 ? posY : 0 ) > viewSize.height || dialogSize.width + ( posX > 0 ? posX : 0 ) > viewSize.width ) { - el.setStyle( 'position', 'absolute' ); - } else { - el.setStyle( 'position', 'fixed' ); - } - } - - this.move( this._.moved ? this._.position.x : posX, this._.moved ? this._.position.y : posY ); - }, - - /** - * Executes a function for each UI element. - * - * @param {Function} fn Function to execute for each UI element. - * @returns {CKEDITOR.dialog} The current dialog object. - */ - foreach: function( fn ) { - for ( var i in this._.contents ) { - for ( var j in this._.contents[ i ] ) { - fn.call( this, this._.contents[i][j] ); - } - } - - return this; - }, - - /** - * Resets all input values in the dialog. - * - * dialogObj.reset(); - * - * @method - * @chainable - */ - reset: ( function() { - var fn = function( widget ) { - if ( widget.reset ) - widget.reset( 1 ); - }; - return function() { - this.foreach( fn ); - return this; - }; - } )(), - - - /** - * Calls the {@link CKEDITOR.dialog.definition.uiElement#setup} method of each - * of the UI elements, with the arguments passed through it. - * It is usually being called when the dialog is opened, to put the initial value inside the field. - * - * dialogObj.setupContent(); - * - * var timestamp = ( new Date() ).valueOf(); - * dialogObj.setupContent( timestamp ); - */ - setupContent: function() { - var args = arguments; - this.foreach( function( widget ) { - if ( widget.setup ) - widget.setup.apply( widget, args ); - } ); - }, - - /** - * Calls the {@link CKEDITOR.dialog.definition.uiElement#commit} method of each - * of the UI elements, with the arguments passed through it. - * It is usually being called when the user confirms the dialog, to process the values. - * - * dialogObj.commitContent(); - * - * var timestamp = ( new Date() ).valueOf(); - * dialogObj.commitContent( timestamp ); - */ - commitContent: function() { - var args = arguments; - this.foreach( function( widget ) { - // Make sure IE triggers "change" event on last focused input before closing the dialog. (#7915) - if ( CKEDITOR.env.ie && this._.currentFocusIndex == widget.focusIndex ) - widget.getInputElement().$.blur(); - - if ( widget.commit ) - widget.commit.apply( widget, args ); - } ); - }, - - /** - * Hides the dialog box. - * - * dialogObj.hide(); - */ - hide: function() { - if ( !this.parts.dialog.isVisible() ) - return; - - this.fire( 'hide', {} ); - this._.editor.fire( 'dialogHide', this ); - // Reset the tab page. - this.selectPage( this._.tabIdList[ 0 ] ); - var element = this._.element; - element.setStyle( 'display', 'none' ); - this.parts.dialog.setStyle( 'visibility', 'hidden' ); - // Unregister all access keys associated with this dialog. - unregisterAccessKey( this ); - - // Close any child(top) dialogs first. - while ( CKEDITOR.dialog._.currentTop != this ) - CKEDITOR.dialog._.currentTop.hide(); - - // Maintain dialog ordering and remove cover if needed. - if ( !this._.parentDialog ) - hideCover( this._.editor ); - else { - var parentElement = this._.parentDialog.getElement().getFirst(); - parentElement.setStyle( 'z-index', parseInt( parentElement.$.style.zIndex, 10 ) + Math.floor( this._.editor.config.baseFloatZIndex / 2 ) ); - } - CKEDITOR.dialog._.currentTop = this._.parentDialog; - - // Deduct or clear the z-index. - if ( !this._.parentDialog ) { - CKEDITOR.dialog._.currentZIndex = null; - - // Remove access key handlers. - element.removeListener( 'keydown', accessKeyDownHandler ); - element.removeListener( 'keyup', accessKeyUpHandler ); - - var editor = this._.editor; - editor.focus(); - - // Give a while before unlock, waiting for focus to return to the editable. (#172) - setTimeout( function() { - editor.focusManager.unlock(); - - // Fixed iOS focus issue (#12381). - // Keep in mind that editor.focus() does not work in this case. - if ( CKEDITOR.env.iOS ) { - editor.window.focus(); - } - }, 0 ); - - } else { - CKEDITOR.dialog._.currentZIndex -= 10; - } - - delete this._.parentDialog; - // Reset the initial values of the dialog. - this.foreach( function( contentObj ) { - contentObj.resetInitValue && contentObj.resetInitValue(); - } ); - - // Reset dialog state back to IDLE, if busy (#13213). - this.setState( CKEDITOR.DIALOG_STATE_IDLE ); - }, - - /** - * Adds a tabbed page into the dialog. - * - * @param {Object} contents Content definition. - */ - addPage: function( contents ) { - if ( contents.requiredContent && !this._.editor.filter.check( contents.requiredContent ) ) - return; - - var pageHtml = [], - titleHtml = contents.label ? ' title="' + CKEDITOR.tools.htmlEncode( contents.label ) + '"' : '', - vbox = CKEDITOR.dialog._.uiElementBuilders.vbox.build( this, { - type: 'vbox', - className: 'cke_dialog_page_contents', - children: contents.elements, - expand: !!contents.expand, - padding: contents.padding, - style: contents.style || 'width: 100%;' - }, pageHtml ); - - var contentMap = this._.contents[ contents.id ] = {}, - cursor, - children = vbox.getChild(), - enabledFields = 0; - - while ( ( cursor = children.shift() ) ) { - // Count all allowed fields. - if ( !cursor.notAllowed && cursor.type != 'hbox' && cursor.type != 'vbox' ) - enabledFields++; - - contentMap[ cursor.id ] = cursor; - if ( typeof cursor.getChild == 'function' ) - children.push.apply( children, cursor.getChild() ); - } - - // If all fields are disabled (because they are not allowed) hide this tab. - if ( !enabledFields ) - contents.hidden = true; - - // Create the HTML for the tab and the content block. - var page = CKEDITOR.dom.element.createFromHtml( pageHtml.join( '' ) ); - page.setAttribute( 'role', 'tabpanel' ); - - var env = CKEDITOR.env; - var tabId = 'cke_' + contents.id + '_' + CKEDITOR.tools.getNextNumber(), - tab = CKEDITOR.dom.element.createFromHtml( [ - ' 0 ? ' cke_last' : 'cke_first' ), - titleHtml, - ( !!contents.hidden ? ' style="display:none"' : '' ), - ' id="', tabId, '"', - env.gecko && !env.hc ? '' : ' href="javascript:void(0)"', - ' tabIndex="-1"', - ' hidefocus="true"', - ' role="tab">', - contents.label, - '' - ].join( '' ) ); - - page.setAttribute( 'aria-labelledby', tabId ); - - // Take records for the tabs and elements created. - this._.tabs[ contents.id ] = [ tab, page ]; - this._.tabIdList.push( contents.id ); - !contents.hidden && this._.pageCount++; - this._.lastTab = tab; - this.updateStyle(); - - // Attach the DOM nodes. - - page.setAttribute( 'name', contents.id ); - page.appendTo( this.parts.contents ); - - tab.unselectable(); - this.parts.tabs.append( tab ); - - // Add access key handlers if access key is defined. - if ( contents.accessKey ) { - registerAccessKey( this, this, 'CTRL+' + contents.accessKey, tabAccessKeyDown, tabAccessKeyUp ); - this._.accessKeyMap[ 'CTRL+' + contents.accessKey ] = contents.id; - } - }, - - /** - * Activates a tab page in the dialog by its id. - * - * dialogObj.selectPage( 'tab_1' ); - * - * @param {String} id The id of the dialog tab to be activated. - */ - selectPage: function( id ) { - if ( this._.currentTabId == id ) - return; - - if ( this._.tabs[ id ][ 0 ].hasClass( 'cke_dialog_tab_disabled' ) ) - return; - - // If event was canceled - do nothing. - if ( this.fire( 'selectPage', { page: id, currentPage: this._.currentTabId } ) === false ) - return; - - // Hide the non-selected tabs and pages. - for ( var i in this._.tabs ) { - var tab = this._.tabs[ i ][ 0 ], - page = this._.tabs[ i ][ 1 ]; - if ( i != id ) { - tab.removeClass( 'cke_dialog_tab_selected' ); - page.hide(); - } - page.setAttribute( 'aria-hidden', i != id ); - } - - var selected = this._.tabs[ id ]; - selected[ 0 ].addClass( 'cke_dialog_tab_selected' ); - - // [IE] an invisible input[type='text'] will enlarge it's width - // if it's value is long when it shows, so we clear it's value - // before it shows and then recover it (#5649) - if ( CKEDITOR.env.ie6Compat || CKEDITOR.env.ie7Compat ) { - clearOrRecoverTextInputValue( selected[ 1 ] ); - selected[ 1 ].show(); - setTimeout( function() { - clearOrRecoverTextInputValue( selected[ 1 ], 1 ); - }, 0 ); - } else { - selected[ 1 ].show(); - } - - this._.currentTabId = id; - this._.currentTabIndex = CKEDITOR.tools.indexOf( this._.tabIdList, id ); - }, - - /** - * Dialog state-specific style updates. - */ - updateStyle: function() { - // If only a single page shown, a different style is used in the central pane. - this.parts.dialog[ ( this._.pageCount === 1 ? 'add' : 'remove' ) + 'Class' ]( 'cke_single_page' ); - }, - - /** - * Hides a page's tab away from the dialog. - * - * dialog.hidePage( 'tab_3' ); - * - * @param {String} id The page's Id. - */ - hidePage: function( id ) { - var tab = this._.tabs[ id ] && this._.tabs[ id ][ 0 ]; - if ( !tab || this._.pageCount == 1 || !tab.isVisible() ) - return; - // Switch to other tab first when we're hiding the active tab. - else if ( id == this._.currentTabId ) - this.selectPage( getPreviousVisibleTab.call( this ) ); - - tab.hide(); - this._.pageCount--; - this.updateStyle(); - }, - - /** - * Unhides a page's tab. - * - * dialog.showPage( 'tab_2' ); - * - * @param {String} id The page's Id. - */ - showPage: function( id ) { - var tab = this._.tabs[ id ] && this._.tabs[ id ][ 0 ]; - if ( !tab ) - return; - tab.show(); - this._.pageCount++; - this.updateStyle(); - }, - - /** - * Gets the root DOM element of the dialog. - * - * var dialogElement = dialogObj.getElement().getFirst(); - * dialogElement.setStyle( 'padding', '5px' ); - * - * @returns {CKEDITOR.dom.element} The `` element containing this dialog. - */ - getElement: function() { - return this._.element; - }, - - /** - * Gets the name of the dialog. - * - * var dialogName = dialogObj.getName(); - * - * @returns {String} The name of this dialog. - */ - getName: function() { - return this._.name; - }, - - /** - * Gets a dialog UI element object from a dialog page. - * - * dialogObj.getContentElement( 'tabId', 'elementId' ).setValue( 'Example' ); - * - * @param {String} pageId id of dialog page. - * @param {String} elementId id of UI element. - * @returns {CKEDITOR.ui.dialog.uiElement} The dialog UI element. - */ - getContentElement: function( pageId, elementId ) { - var page = this._.contents[ pageId ]; - return page && page[ elementId ]; - }, - - /** - * Gets the value of a dialog UI element. - * - * alert( dialogObj.getValueOf( 'tabId', 'elementId' ) ); - * - * @param {String} pageId id of dialog page. - * @param {String} elementId id of UI element. - * @returns {Object} The value of the UI element. - */ - getValueOf: function( pageId, elementId ) { - return this.getContentElement( pageId, elementId ).getValue(); - }, - - /** - * Sets the value of a dialog UI element. - * - * dialogObj.setValueOf( 'tabId', 'elementId', 'Example' ); - * - * @param {String} pageId id of the dialog page. - * @param {String} elementId id of the UI element. - * @param {Object} value The new value of the UI element. - */ - setValueOf: function( pageId, elementId, value ) { - return this.getContentElement( pageId, elementId ).setValue( value ); - }, - - /** - * Gets the UI element of a button in the dialog's button row. - * - * @returns {CKEDITOR.ui.dialog.button} The button object. - * - * @param {String} id The id of the button. - */ - getButton: function( id ) { - return this._.buttons[ id ]; - }, - - /** - * Simulates a click to a dialog button in the dialog's button row. - * - * @returns The return value of the dialog's `click` event. - * - * @param {String} id The id of the button. - */ - click: function( id ) { - return this._.buttons[ id ].click(); - }, - - /** - * Disables a dialog button. - * - * @param {String} id The id of the button. - */ - disableButton: function( id ) { - return this._.buttons[ id ].disable(); - }, - - /** - * Enables a dialog button. - * - * @param {String} id The id of the button. - */ - enableButton: function( id ) { - return this._.buttons[ id ].enable(); - }, - - /** - * Gets the number of pages in the dialog. - * - * @returns {Number} Page count. - */ - getPageCount: function() { - return this._.pageCount; - }, - - /** - * Gets the editor instance which opened this dialog. - * - * @returns {CKEDITOR.editor} Parent editor instances. - */ - getParentEditor: function() { - return this._.editor; - }, - - /** - * Gets the element that was selected when opening the dialog, if any. - * - * @returns {CKEDITOR.dom.element} The element that was selected, or `null`. - */ - getSelectedElement: function() { - return this.getParentEditor().getSelection().getSelectedElement(); - }, - - /** - * Adds element to dialog's focusable list. - * - * @param {CKEDITOR.dom.element} element - * @param {Number} [index] - */ - addFocusable: function( element, index ) { - if ( typeof index == 'undefined' ) { - index = this._.focusList.length; - this._.focusList.push( new Focusable( this, element, index ) ); - } else { - this._.focusList.splice( index, 0, new Focusable( this, element, index ) ); - for ( var i = index + 1; i < this._.focusList.length; i++ ) - this._.focusList[ i ].focusIndex++; - } - }, - - /** - * Sets the dialog {@link #property-state}. - * - * @since 4.5 - * @param {Number} state Either {@link CKEDITOR#DIALOG_STATE_IDLE} or {@link CKEDITOR#DIALOG_STATE_BUSY}. - */ - setState: function( state ) { - var oldState = this.state; - - if ( oldState == state ) { - return; - } - - this.state = state; - - if ( state == CKEDITOR.DIALOG_STATE_BUSY ) { - // Insert the spinner on demand. - if ( !this.parts.spinner ) { - var dir = this.getParentEditor().lang.dir, - spinnerDef = { - attributes: { - 'class': 'cke_dialog_spinner' - }, - styles: { - 'float': dir == 'rtl' ? 'right' : 'left' - } - }; - - spinnerDef.styles[ 'margin-' + ( dir == 'rtl' ? 'left' : 'right' ) ] = '8px'; - - this.parts.spinner = CKEDITOR.document.createElement( 'div', spinnerDef ); - - this.parts.spinner.setHtml( '⌛' ); - this.parts.spinner.appendTo( this.parts.title, 1 ); - } - - // Finally, show the spinner. - this.parts.spinner.show(); - - this.getButton( 'ok' ).disable(); - } else if ( state == CKEDITOR.DIALOG_STATE_IDLE ) { - // Hide the spinner. But don't do anything if there is no spinner yet. - this.parts.spinner && this.parts.spinner.hide(); - - this.getButton( 'ok' ).enable(); - } - - this.fire( 'state', state ); - } - }; - - CKEDITOR.tools.extend( CKEDITOR.dialog, { - /** - * Registers a dialog. - * - * // Full sample plugin, which does not only register a dialog window but also adds an item to the context menu. - * // To open the dialog window, choose "Open dialog" in the context menu. - * CKEDITOR.plugins.add( 'myplugin', { - * init: function( editor ) { - * editor.addCommand( 'mydialog',new CKEDITOR.dialogCommand( 'mydialog' ) ); - * - * if ( editor.contextMenu ) { - * editor.addMenuGroup( 'mygroup', 10 ); - * editor.addMenuItem( 'My Dialog', { - * label: 'Open dialog', - * command: 'mydialog', - * group: 'mygroup' - * } ); - * editor.contextMenu.addListener( function( element ) { - * return { 'My Dialog': CKEDITOR.TRISTATE_OFF }; - * } ); - * } - * - * CKEDITOR.dialog.add( 'mydialog', function( api ) { - * // CKEDITOR.dialog.definition - * var dialogDefinition = { - * title: 'Sample dialog', - * minWidth: 390, - * minHeight: 130, - * contents: [ - * { - * id: 'tab1', - * label: 'Label', - * title: 'Title', - * expand: true, - * padding: 0, - * elements: [ - * { - * type: 'html', - * html: '

    This is some sample HTML content.

    ' - * }, - * { - * type: 'textarea', - * id: 'textareaId', - * rows: 4, - * cols: 40 - * } - * ] - * } - * ], - * buttons: [ CKEDITOR.dialog.okButton, CKEDITOR.dialog.cancelButton ], - * onOk: function() { - * // "this" is now a CKEDITOR.dialog object. - * // Accessing dialog elements: - * var textareaObj = this.getContentElement( 'tab1', 'textareaId' ); - * alert( "You have entered: " + textareaObj.getValue() ); - * } - * }; - * - * return dialogDefinition; - * } ); - * } - * } ); - * - * CKEDITOR.replace( 'editor1', { extraPlugins: 'myplugin' } ); - * - * @static - * @param {String} name The dialog's name. - * @param {Function/String} dialogDefinition - * A function returning the dialog's definition, or the URL to the `.js` file holding the function. - * The function should accept an argument `editor` which is the current editor instance, and - * return an object conforming to {@link CKEDITOR.dialog.definition}. - * @see CKEDITOR.dialog.definition - */ - add: function( name, dialogDefinition ) { - // Avoid path registration from multiple instances override definition. - if ( !this._.dialogDefinitions[ name ] || typeof dialogDefinition == 'function' ) - this._.dialogDefinitions[ name ] = dialogDefinition; - }, - - /** - * @static - * @todo - */ - exists: function( name ) { - return !!this._.dialogDefinitions[ name ]; - }, - - /** - * @static - * @todo - */ - getCurrent: function() { - return CKEDITOR.dialog._.currentTop; - }, - - /** - * Check whether tab wasn't removed by {@link CKEDITOR.config#removeDialogTabs}. - * - * @since 4.1 - * @static - * @param {CKEDITOR.editor} editor - * @param {String} dialogName - * @param {String} tabName - * @returns {Boolean} - */ - isTabEnabled: function( editor, dialogName, tabName ) { - var cfg = editor.config.removeDialogTabs; - - return !( cfg && cfg.match( new RegExp( '(?:^|;)' + dialogName + ':' + tabName + '(?:$|;)', 'i' ) ) ); - }, - - /** - * The default OK button for dialogs. Fires the `ok` event and closes the dialog if the event succeeds. - * - * @static - * @method - */ - okButton: ( function() { - var retval = function( editor, override ) { - override = override || {}; - return CKEDITOR.tools.extend( { - id: 'ok', - type: 'button', - label: editor.lang.common.ok, - 'class': 'cke_dialog_ui_button_ok', - onClick: function( evt ) { - var dialog = evt.data.dialog; - if ( dialog.fire( 'ok', { hide: true } ).hide !== false ) - dialog.hide(); - } - }, override, true ); - }; - retval.type = 'button'; - retval.override = function( override ) { - return CKEDITOR.tools.extend( function( editor ) { - return retval( editor, override ); - }, { type: 'button' }, true ); - }; - return retval; - } )(), - - /** - * The default cancel button for dialogs. Fires the `cancel` event and - * closes the dialog if no UI element value changed. - * - * @static - * @method - */ - cancelButton: ( function() { - var retval = function( editor, override ) { - override = override || {}; - return CKEDITOR.tools.extend( { - id: 'cancel', - type: 'button', - label: editor.lang.common.cancel, - 'class': 'cke_dialog_ui_button_cancel', - onClick: function( evt ) { - var dialog = evt.data.dialog; - if ( dialog.fire( 'cancel', { hide: true } ).hide !== false ) - dialog.hide(); - } - }, override, true ); - }; - retval.type = 'button'; - retval.override = function( override ) { - return CKEDITOR.tools.extend( function( editor ) { - return retval( editor, override ); - }, { type: 'button' }, true ); - }; - return retval; - } )(), - - /** - * Registers a dialog UI element. - * - * @static - * @param {String} typeName The name of the UI element. - * @param {Function} builder The function to build the UI element. - */ - addUIElement: function( typeName, builder ) { - this._.uiElementBuilders[ typeName ] = builder; - } - } ); - - CKEDITOR.dialog._ = { - uiElementBuilders: {}, - - dialogDefinitions: {}, - - currentTop: null, - - currentZIndex: null - }; - - // "Inherit" (copy actually) from CKEDITOR.event. - CKEDITOR.event.implementOn( CKEDITOR.dialog ); - CKEDITOR.event.implementOn( CKEDITOR.dialog.prototype ); - - var defaultDialogDefinition = { - resizable: CKEDITOR.DIALOG_RESIZE_BOTH, - minWidth: 600, - minHeight: 400, - buttons: [ CKEDITOR.dialog.okButton, CKEDITOR.dialog.cancelButton ] - }; - - // Tool function used to return an item from an array based on its id - // property. - var getById = function( array, id, recurse ) { - for ( var i = 0, item; - ( item = array[ i ] ); i++ ) { - if ( item.id == id ) - return item; - if ( recurse && item[ recurse ] ) { - var retval = getById( item[ recurse ], id, recurse ); - if ( retval ) - return retval; - } - } - return null; - }; - - // Tool function used to add an item into an array. - var addById = function( array, newItem, nextSiblingId, recurse, nullIfNotFound ) { - if ( nextSiblingId ) { - for ( var i = 0, item; - ( item = array[ i ] ); i++ ) { - if ( item.id == nextSiblingId ) { - array.splice( i, 0, newItem ); - return newItem; - } - - if ( recurse && item[ recurse ] ) { - var retval = addById( item[ recurse ], newItem, nextSiblingId, recurse, true ); - if ( retval ) - return retval; - } - } - - if ( nullIfNotFound ) - return null; - } - - array.push( newItem ); - return newItem; - }; - - // Tool function used to remove an item from an array based on its id. - var removeById = function( array, id, recurse ) { - for ( var i = 0, item; - ( item = array[ i ] ); i++ ) { - if ( item.id == id ) - return array.splice( i, 1 ); - if ( recurse && item[ recurse ] ) { - var retval = removeById( item[ recurse ], id, recurse ); - if ( retval ) - return retval; - } - } - return null; - }; - - /** - * This class is not really part of the API. It is the `definition` property value - * passed to `dialogDefinition` event handlers. - * - * CKEDITOR.on( 'dialogDefinition', function( evt ) { - * var definition = evt.data.definition; - * var content = definition.getContents( 'page1' ); - * // ... - * } ); - * - * @private - * @class CKEDITOR.dialog.definitionObject - * @extends CKEDITOR.dialog.definition - * @constructor Creates a definitionObject class instance. - */ - var definitionObject = function( dialog, dialogDefinition ) { - // TODO : Check if needed. - this.dialog = dialog; - - // Transform the contents entries in contentObjects. - var contents = dialogDefinition.contents; - for ( var i = 0, content; - ( content = contents[ i ] ); i++ ) - contents[ i ] = content && new contentObject( dialog, content ); - - CKEDITOR.tools.extend( this, dialogDefinition ); - }; - - definitionObject.prototype = { - /** - * Gets a content definition. - * - * @param {String} id The id of the content definition. - * @returns {CKEDITOR.dialog.definition.content} The content definition matching id. - */ - getContents: function( id ) { - return getById( this.contents, id ); - }, - - /** - * Gets a button definition. - * - * @param {String} id The id of the button definition. - * @returns {CKEDITOR.dialog.definition.button} The button definition matching id. - */ - getButton: function( id ) { - return getById( this.buttons, id ); - }, - - /** - * Adds a content definition object under this dialog definition. - * - * @param {CKEDITOR.dialog.definition.content} contentDefinition The - * content definition. - * @param {String} [nextSiblingId] The id of an existing content - * definition which the new content definition will be inserted - * before. Omit if the new content definition is to be inserted as - * the last item. - * @returns {CKEDITOR.dialog.definition.content} The inserted content definition. - */ - addContents: function( contentDefinition, nextSiblingId ) { - return addById( this.contents, contentDefinition, nextSiblingId ); - }, - - /** - * Adds a button definition object under this dialog definition. - * - * @param {CKEDITOR.dialog.definition.button} buttonDefinition The - * button definition. - * @param {String} [nextSiblingId] The id of an existing button - * definition which the new button definition will be inserted - * before. Omit if the new button definition is to be inserted as - * the last item. - * @returns {CKEDITOR.dialog.definition.button} The inserted button definition. - */ - addButton: function( buttonDefinition, nextSiblingId ) { - return addById( this.buttons, buttonDefinition, nextSiblingId ); - }, - - /** - * Removes a content definition from this dialog definition. - * - * @param {String} id The id of the content definition to be removed. - * @returns {CKEDITOR.dialog.definition.content} The removed content definition. - */ - removeContents: function( id ) { - removeById( this.contents, id ); - }, - - /** - * Removes a button definition from the dialog definition. - * - * @param {String} id The id of the button definition to be removed. - * @returns {CKEDITOR.dialog.definition.button} The removed button definition. - */ - removeButton: function( id ) { - removeById( this.buttons, id ); - } - }; - - /** - * This class is not really part of the API. It is the template of the - * objects representing content pages inside the - * CKEDITOR.dialog.definitionObject. - * - * CKEDITOR.on( 'dialogDefinition', function( evt ) { - * var definition = evt.data.definition; - * var content = definition.getContents( 'page1' ); - * content.remove( 'textInput1' ); - * // ... - * } ); - * - * @private - * @class CKEDITOR.dialog.definition.contentObject - * @constructor Creates a contentObject class instance. - */ - function contentObject( dialog, contentDefinition ) { - this._ = { - dialog: dialog - }; - - CKEDITOR.tools.extend( this, contentDefinition ); - } - - contentObject.prototype = { - /** - * Gets a UI element definition under the content definition. - * - * @param {String} id The id of the UI element definition. - * @returns {CKEDITOR.dialog.definition.uiElement} - */ - get: function( id ) { - return getById( this.elements, id, 'children' ); - }, - - /** - * Adds a UI element definition to the content definition. - * - * @param {CKEDITOR.dialog.definition.uiElement} elementDefinition The - * UI elemnet definition to be added. - * @param {String} nextSiblingId The id of an existing UI element - * definition which the new UI element definition will be inserted - * before. Omit if the new button definition is to be inserted as - * the last item. - * @returns {CKEDITOR.dialog.definition.uiElement} The element definition inserted. - */ - add: function( elementDefinition, nextSiblingId ) { - return addById( this.elements, elementDefinition, nextSiblingId, 'children' ); - }, - - /** - * Removes a UI element definition from the content definition. - * - * @param {String} id The id of the UI element definition to be removed. - * @returns {CKEDITOR.dialog.definition.uiElement} The element definition removed. - */ - remove: function( id ) { - removeById( this.elements, id, 'children' ); - } - }; - - function initDragAndDrop( dialog ) { - var lastCoords = null, - abstractDialogCoords = null, - editor = dialog.getParentEditor(), - magnetDistance = editor.config.dialog_magnetDistance, - margins = CKEDITOR.skin.margins || [ 0, 0, 0, 0 ]; - - if ( typeof magnetDistance == 'undefined' ) - magnetDistance = 20; - - function mouseMoveHandler( evt ) { - var dialogSize = dialog.getSize(), - viewPaneSize = CKEDITOR.document.getWindow().getViewPaneSize(), - x = evt.originalEvent.screenX, - y = evt.originalEvent.screenY, - dx = x - lastCoords.x, - dy = y - lastCoords.y, - realX, realY; - - lastCoords = { x: x, y: y }; - abstractDialogCoords.x += dx; - abstractDialogCoords.y += dy; - - if ( abstractDialogCoords.x + margins[ 3 ] < magnetDistance ) - realX = -margins[ 3 ]; - else if ( abstractDialogCoords.x - margins[ 1 ] > viewPaneSize.width - dialogSize.width - magnetDistance ) - realX = viewPaneSize.width - dialogSize.width + ( editor.lang.dir == 'rtl' ? 0 : margins[ 1 ] ); - else - realX = abstractDialogCoords.x; - - if ( abstractDialogCoords.y + margins[ 0 ] < magnetDistance ) - realY = -margins[ 0 ]; - else if ( abstractDialogCoords.y - margins[ 2 ] > viewPaneSize.height - dialogSize.height - magnetDistance ) - realY = viewPaneSize.height - dialogSize.height + margins[ 2 ]; - else - realY = abstractDialogCoords.y; - - dialog.move( realX, realY, 1 ); - - evt.preventDefault(); - } - - function mouseUpHandler() { - CMS.$(CKEDITOR.document.$).off( 'pointermove', mouseMoveHandler ); - CMS.$(CKEDITOR.document.$).off( 'pointerup', mouseUpHandler ); - - if ( CKEDITOR.env.ie6Compat ) { - var coverDoc = currentCover.getChild( 0 ).getFrameDocument(); - coverDoc.removeListener( 'mousemove', mouseMoveHandler ); - coverDoc.removeListener( 'mouseup', mouseUpHandler ); - } - } - - CMS.$(dialog.parts.title.$).on( 'pointerdown', function( evt ) { - lastCoords = { x: evt.originalEvent.screenX, y: evt.originalEvent.screenY }; - - CMS.$(CKEDITOR.document.$).on( 'pointermove', mouseMoveHandler ); - CMS.$(CKEDITOR.document.$).on( 'pointerup', mouseUpHandler ); - abstractDialogCoords = dialog.getPosition(); - - if ( CKEDITOR.env.ie6Compat ) { - var coverDoc = currentCover.getChild( 0 ).getFrameDocument(); - coverDoc.on( 'mousemove', mouseMoveHandler ); - coverDoc.on( 'mouseup', mouseUpHandler ); - } - - evt.preventDefault(); - }); - } - - function initResizeHandles( dialog ) { - var def = dialog.definition, - resizable = def.resizable; - - if ( resizable == CKEDITOR.DIALOG_RESIZE_NONE ) - return; - - var editor = dialog.getParentEditor(); - var wrapperWidth, wrapperHeight, viewSize, origin, startSize, dialogCover; - - var mouseDownFn = CKEDITOR.tools.addFunction( function( $event ) { - startSize = dialog.getSize(); - - var content = dialog.parts.contents, - iframeDialog = content.$.getElementsByTagName( 'iframe' ).length; - - // Shim to help capturing "mousemove" over iframe. - if ( iframeDialog ) { - CMS.$('.cke_dialog_resize_cover').remove(); - dialogCover = CKEDITOR.dom.element.createFromHtml( '
    ' ); - content.append( dialogCover ); - } - - // Calculate the offset between content and chrome size. - wrapperHeight = startSize.height - dialog.parts.contents.getSize( 'height', !( CKEDITOR.env.gecko || CKEDITOR.env.ie && CKEDITOR.env.quirks ) ); - wrapperWidth = startSize.width - dialog.parts.contents.getSize( 'width', 1 ); - - origin = { x: $event.screenX, y: $event.screenY }; - - viewSize = CKEDITOR.document.getWindow().getViewPaneSize(); - - CMS.$(CKEDITOR.document.$).on( 'pointermove', mouseMoveHandler ); - CMS.$(CKEDITOR.document.$).on( 'pointerup', mouseUpHandler ); - - if ( CKEDITOR.env.ie6Compat ) { - var coverDoc = currentCover.getChild( 0 ).getFrameDocument(); - coverDoc.on( 'mousemove', mouseMoveHandler ); - coverDoc.on( 'mouseup', mouseUpHandler ); - } - - $event.preventDefault && $event.preventDefault(); - } ); - - // Prepend the grip to the dialog. - dialog.on( 'load', function() { - var direction = ''; - if ( resizable == CKEDITOR.DIALOG_RESIZE_WIDTH ) - direction = ' cke_resizer_horizontal'; - else if ( resizable == CKEDITOR.DIALOG_RESIZE_HEIGHT ) - direction = ' cke_resizer_vertical'; - var resizer = CKEDITOR.dom.element.createFromHtml( - '' + - // BLACK LOWER RIGHT TRIANGLE (ltr) - // BLACK LOWER LEFT TRIANGLE (rtl) - ( editor.lang.dir == 'ltr' ? '\u25E2' : '\u25E3' ) + - '
    ' ); - dialog.parts.footer.append( resizer, 1 ); - } ); - editor.on( 'destroy', function() { - CKEDITOR.tools.removeFunction( mouseDownFn ); - } ); - - function mouseMoveHandler( evt ) { - var rtl = editor.lang.dir == 'rtl', - dx = ( evt.originalEvent.screenX - origin.x ) * ( rtl ? -1 : 1 ), - dy = evt.originalEvent.screenY - origin.y, - width = startSize.width, - height = startSize.height, - internalWidth = width + dx * ( dialog._.moved ? 1 : 2 ), - internalHeight = height + dy * ( dialog._.moved ? 1 : 2 ), - element = dialog._.element.getFirst(), - right = rtl && element.getComputedStyle( 'right' ), - position = dialog.getPosition(); - - if ( position.y + internalHeight > viewSize.height ) - internalHeight = viewSize.height - position.y; - - if ( ( rtl ? right : position.x ) + internalWidth > viewSize.width ) - internalWidth = viewSize.width - ( rtl ? right : position.x ); - - // Make sure the dialog will not be resized to the wrong side when it's in the leftmost position for RTL. - if ( ( resizable == CKEDITOR.DIALOG_RESIZE_WIDTH || resizable == CKEDITOR.DIALOG_RESIZE_BOTH ) ) - width = Math.max( def.minWidth || 0, internalWidth - wrapperWidth ); - - if ( resizable == CKEDITOR.DIALOG_RESIZE_HEIGHT || resizable == CKEDITOR.DIALOG_RESIZE_BOTH ) - height = Math.max( def.minHeight || 0, internalHeight - wrapperHeight ); - - dialog.resize( width, height ); - - if ( !dialog._.moved ) - dialog.layout(); - - evt.preventDefault(); - } - - function mouseUpHandler() { - CMS.$(CKEDITOR.document.$).off( 'pointermove', mouseMoveHandler ); - CMS.$(CKEDITOR.document.$).off( 'pointerup', mouseUpHandler ); - - if ( dialogCover ) { - dialogCover.remove(); - dialogCover = null; - } - - if ( CKEDITOR.env.ie6Compat ) { - var coverDoc = currentCover.getChild( 0 ).getFrameDocument(); - coverDoc.removeListener( 'mouseup', mouseUpHandler ); - coverDoc.removeListener( 'mousemove', mouseMoveHandler ); - } - } - } - - var resizeCover; - // Caching resuable covers and allowing only one cover - // on screen. - var covers = {}, - currentCover; - - function cancelEvent( ev ) { - ev.data.preventDefault( 1 ); - } - - function showCover( editor ) { - var win = CKEDITOR.document.getWindow(); - var config = editor.config, - backgroundColorStyle = config.dialog_backgroundCoverColor || 'white', - backgroundCoverOpacity = config.dialog_backgroundCoverOpacity, - baseFloatZIndex = config.baseFloatZIndex, - coverKey = CKEDITOR.tools.genKey( backgroundColorStyle, backgroundCoverOpacity, baseFloatZIndex ), - coverElement = covers[ coverKey ]; - - CMS.$('.cke_dialog_background_cover:not(.cms-ckeditor-dialog-background-cover)').remove(); - if ( !coverElement ) { - covers = {}; - var html = [ - '
    ' - ]; - - if ( CKEDITOR.env.ie6Compat ) { - // Support for custom document.domain in IE. - var iframeHtml = ''; - - html.push( '' + - '' ); - } - - html.push( '
    ' ); - - coverElement = CKEDITOR.dom.element.createFromHtml( html.join( '' ) ); - coverElement.setOpacity( backgroundCoverOpacity !== undefined ? backgroundCoverOpacity : 0.5 ); - - coverElement.on( 'keydown', cancelEvent ); - coverElement.on( 'keypress', cancelEvent ); - coverElement.on( 'keyup', cancelEvent ); - - coverElement.appendTo( CKEDITOR.document.getBody() ); - covers[ coverKey ] = coverElement; - } else { - coverElement.show(); - } - - // Makes the dialog cover a focus holder as well. - editor.focusManager.add( coverElement ); - - currentCover = coverElement; - var resizeFunc = function() { - var size = win.getViewPaneSize(); - coverElement.setStyles( { - width: size.width + 'px', - height: size.height + 'px' - } ); - }; - - var scrollFunc = function() { - var pos = win.getScrollPosition(), - cursor = CKEDITOR.dialog._.currentTop; - coverElement.setStyles( { - left: pos.x + 'px', - top: pos.y + 'px' - } ); - - if ( cursor ) { - do { - var dialogPos = cursor.getPosition(); - cursor.move( dialogPos.x, dialogPos.y ); - } while ( ( cursor = cursor._.parentDialog ) ); - } - }; - - resizeCover = resizeFunc; - win.on( 'resize', resizeFunc ); - resizeFunc(); - // Using Safari/Mac, focus must be kept where it is (#7027) - if ( !( CKEDITOR.env.mac && CKEDITOR.env.webkit ) ) - coverElement.focus(); - - if ( CKEDITOR.env.ie6Compat ) { - // IE BUG: win.$.onscroll assignment doesn't work.. it must be window.onscroll. - // So we need to invent a really funny way to make it work. - var myScrollHandler = function() { - scrollFunc(); - arguments.callee.prevScrollHandler.apply( this, arguments ); - }; - win.$.setTimeout( function() { - myScrollHandler.prevScrollHandler = window.onscroll || - function() {}; - window.onscroll = myScrollHandler; - }, 0 ); - scrollFunc(); - } - } - - function hideCover( editor ) { - CMS.$('.cke_dialog_background_cover:not(.cms-ckeditor-dialog-background-cover)').remove(); - if ( !currentCover ) - return; - - editor.focusManager.remove( currentCover ); - var win = CKEDITOR.document.getWindow(); - currentCover.hide(); - win.removeListener( 'resize', resizeCover ); - - if ( CKEDITOR.env.ie6Compat ) { - win.$.setTimeout( function() { - var prevScrollHandler = window.onscroll && window.onscroll.prevScrollHandler; - window.onscroll = prevScrollHandler || null; - }, 0 ); - } - resizeCover = null; - } - - function removeCovers() { - for ( var coverId in covers ) - covers[ coverId ].remove(); - covers = {}; - } - - var accessKeyProcessors = {}; - - var accessKeyDownHandler = function( evt ) { - var ctrl = evt.data.$.ctrlKey || evt.data.$.metaKey, - alt = evt.data.$.altKey, - shift = evt.data.$.shiftKey, - key = String.fromCharCode( evt.data.$.keyCode ), - keyProcessor = accessKeyProcessors[ ( ctrl ? 'CTRL+' : '' ) + ( alt ? 'ALT+' : '' ) + ( shift ? 'SHIFT+' : '' ) + key ]; - - if ( !keyProcessor || !keyProcessor.length ) - return; - - keyProcessor = keyProcessor[ keyProcessor.length - 1 ]; - keyProcessor.keydown && keyProcessor.keydown.call( keyProcessor.uiElement, keyProcessor.dialog, keyProcessor.key ); - evt.data.preventDefault(); - }; - - var accessKeyUpHandler = function( evt ) { - var ctrl = evt.data.$.ctrlKey || evt.data.$.metaKey, - alt = evt.data.$.altKey, - shift = evt.data.$.shiftKey, - key = String.fromCharCode( evt.data.$.keyCode ), - keyProcessor = accessKeyProcessors[ ( ctrl ? 'CTRL+' : '' ) + ( alt ? 'ALT+' : '' ) + ( shift ? 'SHIFT+' : '' ) + key ]; - - if ( !keyProcessor || !keyProcessor.length ) - return; - - keyProcessor = keyProcessor[ keyProcessor.length - 1 ]; - if ( keyProcessor.keyup ) { - keyProcessor.keyup.call( keyProcessor.uiElement, keyProcessor.dialog, keyProcessor.key ); - evt.data.preventDefault(); - } - }; - - var registerAccessKey = function( uiElement, dialog, key, downFunc, upFunc ) { - var procList = accessKeyProcessors[ key ] || ( accessKeyProcessors[ key ] = [] ); - procList.push( { - uiElement: uiElement, - dialog: dialog, - key: key, - keyup: upFunc || uiElement.accessKeyUp, - keydown: downFunc || uiElement.accessKeyDown - } ); - }; - - var unregisterAccessKey = function( obj ) { - for ( var i in accessKeyProcessors ) { - var list = accessKeyProcessors[ i ]; - for ( var j = list.length - 1; j >= 0; j-- ) { - if ( list[ j ].dialog == obj || list[ j ].uiElement == obj ) - list.splice( j, 1 ); - } - if ( list.length === 0 ) - delete accessKeyProcessors[ i ]; - } - }; - - var tabAccessKeyUp = function( dialog, key ) { - if ( dialog._.accessKeyMap[ key ] ) - dialog.selectPage( dialog._.accessKeyMap[ key ] ); - }; - - var tabAccessKeyDown = function() {}; - - ( function() { - CKEDITOR.ui.dialog = { - /** - * The base class of all dialog UI elements. - * - * @class CKEDITOR.ui.dialog.uiElement - * @constructor Creates a uiElement class instance. - * @param {CKEDITOR.dialog} dialog Parent dialog object. - * @param {CKEDITOR.dialog.definition.uiElement} elementDefinition Element - * definition. - * - * Accepted fields: - * - * * `id` (Required) The id of the UI element. See {@link CKEDITOR.dialog#getContentElement}. - * * `type` (Required) The type of the UI element. The - * value to this field specifies which UI element class will be used to - * generate the final widget. - * * `title` (Optional) The popup tooltip for the UI - * element. - * * `hidden` (Optional) A flag that tells if the element - * should be initially visible. - * * `className` (Optional) Additional CSS class names - * to add to the UI element. Separated by space. - * * `style` (Optional) Additional CSS inline styles - * to add to the UI element. A semicolon (;) is required after the last - * style declaration. - * * `accessKey` (Optional) The alphanumeric access key - * for this element. Access keys are automatically prefixed by CTRL. - * * `on*` (Optional) Any UI element definition field that - * starts with `on` followed immediately by a capital letter and - * probably more letters is an event handler. Event handlers may be further - * divided into registered event handlers and DOM event handlers. Please - * refer to {@link CKEDITOR.ui.dialog.uiElement#registerEvents} and - * {@link CKEDITOR.ui.dialog.uiElement#eventProcessors} for more information. - * - * @param {Array} htmlList - * List of HTML code to be added to the dialog's content area. - * @param {Function/String} [nodeNameArg='div'] - * A function returning a string, or a simple string for the node name for - * the root DOM node. - * @param {Function/Object} [stylesArg={}] - * A function returning an object, or a simple object for CSS styles applied - * to the DOM node. - * @param {Function/Object} [attributesArg={}] - * A fucntion returning an object, or a simple object for attributes applied - * to the DOM node. - * @param {Function/String} [contentsArg=''] - * A function returning a string, or a simple string for the HTML code inside - * the root DOM node. Default is empty string. - */ - uiElement: function( dialog, elementDefinition, htmlList, nodeNameArg, stylesArg, attributesArg, contentsArg ) { - if ( arguments.length < 4 ) - return; - - var nodeName = ( nodeNameArg.call ? nodeNameArg( elementDefinition ) : nodeNameArg ) || 'div', - html = [ '<', nodeName, ' ' ], - styles = ( stylesArg && stylesArg.call ? stylesArg( elementDefinition ) : stylesArg ) || {}, - attributes = ( attributesArg && attributesArg.call ? attributesArg( elementDefinition ) : attributesArg ) || {}, - innerHTML = ( contentsArg && contentsArg.call ? contentsArg.call( this, dialog, elementDefinition ) : contentsArg ) || '', - domId = this.domId = attributes.id || CKEDITOR.tools.getNextId() + '_uiElement', - i; - - if ( elementDefinition.requiredContent && !dialog.getParentEditor().filter.check( elementDefinition.requiredContent ) ) { - styles.display = 'none'; - this.notAllowed = true; - } - - // Set the id, a unique id is required for getElement() to work. - attributes.id = domId; - - // Set the type and definition CSS class names. - var classes = {}; - if ( elementDefinition.type ) - classes[ 'cke_dialog_ui_' + elementDefinition.type ] = 1; - if ( elementDefinition.className ) - classes[ elementDefinition.className ] = 1; - if ( elementDefinition.disabled ) - classes.cke_disabled = 1; - - var attributeClasses = ( attributes[ 'class' ] && attributes[ 'class' ].split ) ? attributes[ 'class' ].split( ' ' ) : []; - for ( i = 0; i < attributeClasses.length; i++ ) { - if ( attributeClasses[ i ] ) - classes[ attributeClasses[ i ] ] = 1; - } - var finalClasses = []; - for ( i in classes ) - finalClasses.push( i ); - attributes[ 'class' ] = finalClasses.join( ' ' ); - - // Set the popup tooltop. - if ( elementDefinition.title ) - attributes.title = elementDefinition.title; - - // Write the inline CSS styles. - var styleStr = ( elementDefinition.style || '' ).split( ';' ); - - // Element alignment support. - if ( elementDefinition.align ) { - var align = elementDefinition.align; - styles[ 'margin-left' ] = align == 'left' ? 0 : 'auto'; - styles[ 'margin-right' ] = align == 'right' ? 0 : 'auto'; - } - - for ( i in styles ) - styleStr.push( i + ':' + styles[ i ] ); - if ( elementDefinition.hidden ) - styleStr.push( 'display:none' ); - for ( i = styleStr.length - 1; i >= 0; i-- ) { - if ( styleStr[ i ] === '' ) - styleStr.splice( i, 1 ); - } - if ( styleStr.length > 0 ) - attributes.style = ( attributes.style ? ( attributes.style + '; ' ) : '' ) + styleStr.join( '; ' ); - - // Write the attributes. - for ( i in attributes ) - html.push( i + '="' + CKEDITOR.tools.htmlEncode( attributes[ i ] ) + '" ' ); - - // Write the content HTML. - html.push( '>', innerHTML, '' ); - - // Add contents to the parent HTML array. - htmlList.push( html.join( '' ) ); - - ( this._ || ( this._ = {} ) ).dialog = dialog; - - // Override isChanged if it is defined in element definition. - if ( typeof elementDefinition.isChanged == 'boolean' ) - this.isChanged = function() { - return elementDefinition.isChanged; - }; - if ( typeof elementDefinition.isChanged == 'function' ) - this.isChanged = elementDefinition.isChanged; - - // Overload 'get(set)Value' on definition. - if ( typeof elementDefinition.setValue == 'function' ) { - this.setValue = CKEDITOR.tools.override( this.setValue, function( org ) { - return function( val ) { - org.call( this, elementDefinition.setValue.call( this, val ) ); - }; - } ); - } - - if ( typeof elementDefinition.getValue == 'function' ) { - this.getValue = CKEDITOR.tools.override( this.getValue, function( org ) { - return function() { - return elementDefinition.getValue.call( this, org.call( this ) ); - }; - } ); - } - - // Add events. - CKEDITOR.event.implementOn( this ); - - this.registerEvents( elementDefinition ); - if ( this.accessKeyUp && this.accessKeyDown && elementDefinition.accessKey ) - registerAccessKey( this, dialog, 'CTRL+' + elementDefinition.accessKey ); - - var me = this; - dialog.on( 'load', function() { - var input = me.getInputElement(); - if ( input ) { - var focusClass = me.type in { 'checkbox': 1, 'ratio': 1 } && CKEDITOR.env.ie && CKEDITOR.env.version < 8 ? 'cke_dialog_ui_focused' : ''; - input.on( 'focus', function() { - dialog._.tabBarMode = false; - dialog._.hasFocus = true; - me.fire( 'focus' ); - focusClass && this.addClass( focusClass ); - - } ); - - input.on( 'blur', function() { - me.fire( 'blur' ); - focusClass && this.removeClass( focusClass ); - } ); - } - } ); - - // Completes this object with everything we have in the - // definition. - CKEDITOR.tools.extend( this, elementDefinition ); - - // Register the object as a tab focus if it can be included. - if ( this.keyboardFocusable ) { - this.tabIndex = elementDefinition.tabIndex || 0; - - this.focusIndex = dialog._.focusList.push( this ) - 1; - this.on( 'focus', function() { - dialog._.currentFocusIndex = me.focusIndex; - } ); - } - }, - - /** - * Horizontal layout box for dialog UI elements, auto-expends to available width of container. - * - * @class CKEDITOR.ui.dialog.hbox - * @extends CKEDITOR.ui.dialog.uiElement - * @constructor Creates a hbox class instance. - * @param {CKEDITOR.dialog} dialog Parent dialog object. - * @param {Array} childObjList - * Array of {@link CKEDITOR.ui.dialog.uiElement} objects inside this container. - * @param {Array} childHtmlList - * Array of HTML code that correspond to the HTML output of all the - * objects in childObjList. - * @param {Array} htmlList - * Array of HTML code that this element will output to. - * @param {CKEDITOR.dialog.definition.uiElement} elementDefinition - * The element definition. Accepted fields: - * - * * `widths` (Optional) The widths of child cells. - * * `height` (Optional) The height of the layout. - * * `padding` (Optional) The padding width inside child cells. - * * `align` (Optional) The alignment of the whole layout. - */ - hbox: function( dialog, childObjList, childHtmlList, htmlList, elementDefinition ) { - if ( arguments.length < 4 ) - return; - - this._ || ( this._ = {} ); - - var children = this._.children = childObjList, - widths = elementDefinition && elementDefinition.widths || null, - height = elementDefinition && elementDefinition.height || null, - styles = {}, - i; - /** @ignore */ - var innerHTML = function() { - var html = [ '' ]; - for ( i = 0; i < childHtmlList.length; i++ ) { - var className = 'cke_dialog_ui_hbox_child', - styles = []; - if ( i === 0 ) { - className = 'cke_dialog_ui_hbox_first'; - } - if ( i == childHtmlList.length - 1 ) { - className = 'cke_dialog_ui_hbox_last'; - } - - html.push( ' 0 ) { - html.push( 'style="' + styles.join( '; ' ) + '" ' ); - } - html.push( '>', childHtmlList[ i ], '' ); - } - html.push( '' ); - return html.join( '' ); - }; - - var attribs = { role: 'presentation' }; - elementDefinition && elementDefinition.align && ( attribs.align = elementDefinition.align ); - - CKEDITOR.ui.dialog.uiElement.call( this, dialog, elementDefinition || { type: 'hbox' }, htmlList, 'table', styles, attribs, innerHTML ); - }, - - /** - * Vertical layout box for dialog UI elements. - * - * @class CKEDITOR.ui.dialog.vbox - * @extends CKEDITOR.ui.dialog.hbox - * @constructor Creates a vbox class instance. - * @param {CKEDITOR.dialog} dialog Parent dialog object. - * @param {Array} childObjList - * Array of {@link CKEDITOR.ui.dialog.uiElement} objects inside this container. - * @param {Array} childHtmlList - * Array of HTML code that correspond to the HTML output of all the - * objects in childObjList. - * @param {Array} htmlList Array of HTML code that this element will output to. - * @param {CKEDITOR.dialog.definition.uiElement} elementDefinition - * The element definition. Accepted fields: - * - * * `width` (Optional) The width of the layout. - * * `heights` (Optional) The heights of individual cells. - * * `align` (Optional) The alignment of the layout. - * * `padding` (Optional) The padding width inside child cells. - * * `expand` (Optional) Whether the layout should expand - * vertically to fill its container. - */ - vbox: function( dialog, childObjList, childHtmlList, htmlList, elementDefinition ) { - if ( arguments.length < 3 ) - return; - - this._ || ( this._ = {} ); - - var children = this._.children = childObjList, - width = elementDefinition && elementDefinition.width || null, - heights = elementDefinition && elementDefinition.heights || null; - /** @ignore */ - var innerHTML = function() { - var html = [ '' ); - for ( var i = 0; i < childHtmlList.length; i++ ) { - var styles = []; - html.push( '' ); - } - html.push( '
    0 ) - html.push( 'style="', styles.join( '; ' ), '" ' ); - html.push( ' class="cke_dialog_ui_vbox_child">', childHtmlList[ i ], '
    ' ); - return html.join( '' ); - }; - CKEDITOR.ui.dialog.uiElement.call( this, dialog, elementDefinition || { type: 'vbox' }, htmlList, 'div', null, { role: 'presentation' }, innerHTML ); - } - }; - } )(); - - /** @class CKEDITOR.ui.dialog.uiElement */ - CKEDITOR.ui.dialog.uiElement.prototype = { - /** - * Gets the root DOM element of this dialog UI object. - * - * uiElement.getElement().hide(); - * - * @returns {CKEDITOR.dom.element} Root DOM element of UI object. - */ - getElement: function() { - return CKEDITOR.document.getById( this.domId ); - }, - - /** - * Gets the DOM element that the user inputs values. - * - * This function is used by {@link #setValue}, {@link #getValue} and {@link #focus}. It should - * be overrided in child classes where the input element isn't the root - * element. - * - * var rawValue = textInput.getInputElement().$.value; - * - * @returns {CKEDITOR.dom.element} The element where the user input values. - */ - getInputElement: function() { - return this.getElement(); - }, - - /** - * Gets the parent dialog object containing this UI element. - * - * var dialog = uiElement.getDialog(); - * - * @returns {CKEDITOR.dialog} Parent dialog object. - */ - getDialog: function() { - return this._.dialog; - }, - - /** - * Sets the value of this dialog UI object. - * - * uiElement.setValue( 'Dingo' ); - * - * @chainable - * @param {Object} value The new value. - * @param {Boolean} noChangeEvent Internal commit, to supress `change` event on this element. - */ - setValue: function( value, noChangeEvent ) { - this.getInputElement().setValue( value ); - !noChangeEvent && this.fire( 'change', { value: value } ); - return this; - }, - - /** - * Gets the current value of this dialog UI object. - * - * var myValue = uiElement.getValue(); - * - * @returns {Object} The current value. - */ - getValue: function() { - return this.getInputElement().getValue(); - }, - - /** - * Tells whether the UI object's value has changed. - * - * if ( uiElement.isChanged() ) - * confirm( 'Value changed! Continue?' ); - * - * @returns {Boolean} `true` if changed, `false` if not changed. - */ - isChanged: function() { - // Override in input classes. - return false; - }, - - /** - * Selects the parent tab of this element. Usually called by focus() or overridden focus() methods. - * - * focus : function() { - * this.selectParentTab(); - * // do something else. - * } - * - * @chainable - */ - selectParentTab: function() { - var element = this.getInputElement(), - cursor = element, - tabId; - while ( ( cursor = cursor.getParent() ) && cursor.$.className.search( 'cke_dialog_page_contents' ) == -1 ) { - - } - - // Some widgets don't have parent tabs (e.g. OK and Cancel buttons). - if ( !cursor ) - return this; - - tabId = cursor.getAttribute( 'name' ); - // Avoid duplicate select. - if ( this._.dialog._.currentTabId != tabId ) - this._.dialog.selectPage( tabId ); - return this; - }, - - /** - * Puts the focus to the UI object. Switches tabs if the UI object isn't in the active tab page. - * - * uiElement.focus(); - * - * @chainable - */ - focus: function() { - this.selectParentTab().getInputElement().focus(); - return this; - }, - - /** - * Registers the `on*` event handlers defined in the element definition. - * - * The default behavior of this function is: - * - * 1. If the on* event is defined in the class's eventProcesors list, - * then the registration is delegated to the corresponding function - * in the eventProcessors list. - * 2. If the on* event is not defined in the eventProcessors list, then - * register the event handler under the corresponding DOM event of - * the UI element's input DOM element (as defined by the return value - * of {@link #getInputElement}). - * - * This function is only called at UI element instantiation, but can - * be overridded in child classes if they require more flexibility. - * - * @chainable - * @param {CKEDITOR.dialog.definition.uiElement} definition The UI element - * definition. - */ - registerEvents: function( definition ) { - var regex = /^on([A-Z]\w+)/, - match; - - var registerDomEvent = function( uiElement, dialog, eventName, func ) { - dialog.on( 'load', function() { - uiElement.getInputElement().on( eventName, func, uiElement ); - } ); - }; - - for ( var i in definition ) { - if ( !( match = i.match( regex ) ) ) - continue; - if ( this.eventProcessors[ i ] ) - this.eventProcessors[ i ].call( this, this._.dialog, definition[ i ] ); - else - registerDomEvent( this, this._.dialog, match[ 1 ].toLowerCase(), definition[ i ] ); - } - - return this; - }, - - /** - * The event processor list used by - * {@link CKEDITOR.ui.dialog.uiElement#getInputElement} at UI element - * instantiation. The default list defines three `on*` events: - * - * 1. `onLoad` - Called when the element's parent dialog opens for the - * first time. - * 2. `onShow` - Called whenever the element's parent dialog opens. - * 3. `onHide` - Called whenever the element's parent dialog closes. - * - * // This connects the 'click' event in CKEDITOR.ui.dialog.button to onClick - * // handlers in the UI element's definitions. - * CKEDITOR.ui.dialog.button.eventProcessors = CKEDITOR.tools.extend( {}, - * CKEDITOR.ui.dialog.uiElement.prototype.eventProcessors, - * { onClick : function( dialog, func ) { this.on( 'click', func ); } }, - * true - * ); - * - * @property {Object} - */ - eventProcessors: { - onLoad: function( dialog, func ) { - dialog.on( 'load', func, this ); - }, - - onShow: function( dialog, func ) { - dialog.on( 'show', func, this ); - }, - - onHide: function( dialog, func ) { - dialog.on( 'hide', func, this ); - } - }, - - /** - * The default handler for a UI element's access key down event, which - * tries to put focus to the UI element. - * - * Can be overridded in child classes for more sophisticaed behavior. - * - * @param {CKEDITOR.dialog} dialog The parent dialog object. - * @param {String} key The key combination pressed. Since access keys - * are defined to always include the `CTRL` key, its value should always - * include a `'CTRL+'` prefix. - */ - accessKeyDown: function() { - this.focus(); - }, - - /** - * The default handler for a UI element's access key up event, which - * does nothing. - * - * Can be overridded in child classes for more sophisticated behavior. - * - * @param {CKEDITOR.dialog} dialog The parent dialog object. - * @param {String} key The key combination pressed. Since access keys - * are defined to always include the `CTRL` key, its value should always - * include a `'CTRL+'` prefix. - */ - accessKeyUp: function() {}, - - /** - * Disables a UI element. - */ - disable: function() { - var element = this.getElement(), - input = this.getInputElement(); - input.setAttribute( 'disabled', 'true' ); - element.addClass( 'cke_disabled' ); - }, - - /** - * Enables a UI element. - */ - enable: function() { - var element = this.getElement(), - input = this.getInputElement(); - input.removeAttribute( 'disabled' ); - element.removeClass( 'cke_disabled' ); - }, - - /** - * Determines whether an UI element is enabled or not. - * - * @returns {Boolean} Whether the UI element is enabled. - */ - isEnabled: function() { - return !this.getElement().hasClass( 'cke_disabled' ); - }, - - /** - * Determines whether an UI element is visible or not. - * - * @returns {Boolean} Whether the UI element is visible. - */ - isVisible: function() { - return this.getInputElement().isVisible(); - }, - - /** - * Determines whether an UI element is focus-able or not. - * Focus-able is defined as being both visible and enabled. - * - * @returns {Boolean} Whether the UI element can be focused. - */ - isFocusable: function() { - if ( !this.isEnabled() || !this.isVisible() ) - return false; - return true; - } - }; - - /** @class CKEDITOR.ui.dialog.hbox */ - CKEDITOR.ui.dialog.hbox.prototype = CKEDITOR.tools.extend( new CKEDITOR.ui.dialog.uiElement(), { - /** - * Gets a child UI element inside this container. - * - * var checkbox = hbox.getChild( [0,1] ); - * checkbox.setValue( true ); - * - * @param {Array/Number} indices An array or a single number to indicate the child's - * position in the container's descendant tree. Omit to get all the children in an array. - * @returns {Array/CKEDITOR.ui.dialog.uiElement} Array of all UI elements in the container - * if no argument given, or the specified UI element if indices is given. - */ - getChild: function( indices ) { - // If no arguments, return a clone of the children array. - if ( arguments.length < 1 ) - return this._.children.concat(); - - // If indices isn't array, make it one. - if ( !indices.splice ) - indices = [ indices ]; - - // Retrieve the child element according to tree position. - if ( indices.length < 2 ) - return this._.children[ indices[ 0 ] ]; - else - return ( this._.children[ indices[ 0 ] ] && this._.children[ indices[ 0 ] ].getChild ) ? this._.children[ indices[ 0 ] ].getChild( indices.slice( 1, indices.length ) ) : null; - } - }, true ); - - CKEDITOR.ui.dialog.vbox.prototype = new CKEDITOR.ui.dialog.hbox(); - - ( function() { - var commonBuilder = { - build: function( dialog, elementDefinition, output ) { - var children = elementDefinition.children, - child, - childHtmlList = [], - childObjList = []; - for ( var i = 0; - ( i < children.length && ( child = children[ i ] ) ); i++ ) { - var childHtml = []; - childHtmlList.push( childHtml ); - childObjList.push( CKEDITOR.dialog._.uiElementBuilders[ child.type ].build( dialog, child, childHtml ) ); - } - return new CKEDITOR.ui.dialog[ elementDefinition.type ]( dialog, childObjList, childHtmlList, output, elementDefinition ); - } - }; - - CKEDITOR.dialog.addUIElement( 'hbox', commonBuilder ); - CKEDITOR.dialog.addUIElement( 'vbox', commonBuilder ); - } )(); - - /** - * Generic dialog command. It opens a specific dialog when executed. - * - * // Register the "link" command, which opens the "link" dialog. - * editor.addCommand( 'link', new CKEDITOR.dialogCommand( 'link' ) ); - * - * @class - * @constructor Creates a dialogCommand class instance. - * @extends CKEDITOR.commandDefinition - * @param {String} dialogName The name of the dialog to open when executing - * this command. - * @param {Object} [ext] Additional command definition's properties. - */ - CKEDITOR.dialogCommand = function( dialogName, ext ) { - this.dialogName = dialogName; - CKEDITOR.tools.extend( this, ext, true ); - }; - - CKEDITOR.dialogCommand.prototype = { - exec: function( editor ) { - editor.openDialog( this.dialogName ); - }, - - // Dialog commands just open a dialog ui, thus require no undo logic, - // undo support should dedicate to specific dialog implementation. - canUndo: false, - - editorFocus: 1 - }; - - ( function() { - var notEmptyRegex = /^([a]|[^a])+$/, - integerRegex = /^\d*$/, - numberRegex = /^\d*(?:\.\d+)?$/, - htmlLengthRegex = /^(((\d*(\.\d+))|(\d*))(px|\%)?)?$/, - cssLengthRegex = /^(((\d*(\.\d+))|(\d*))(px|em|ex|in|cm|mm|pt|pc|\%)?)?$/i, - inlineStyleRegex = /^(\s*[\w-]+\s*:\s*[^:;]+(?:;|$))*$/; - - CKEDITOR.VALIDATE_OR = 1; - CKEDITOR.VALIDATE_AND = 2; - - CKEDITOR.dialog.validate = { - functions: function() { - var args = arguments; - return function() { - /** - * It's important for validate functions to be able to accept the value - * as argument in addition to this.getValue(), so that it is possible to - * combine validate functions together to make more sophisticated - * validators. - */ - var value = this && this.getValue ? this.getValue() : args[ 0 ]; - - var msg, - relation = CKEDITOR.VALIDATE_AND, - functions = [], - i; - - for ( i = 0; i < args.length; i++ ) { - if ( typeof args[ i ] == 'function' ) - functions.push( args[ i ] ); - else - break; - } - - if ( i < args.length && typeof args[ i ] == 'string' ) { - msg = args[ i ]; - i++; - } - - if ( i < args.length && typeof args[ i ] == 'number' ) - relation = args[ i ]; - - var passed = ( relation == CKEDITOR.VALIDATE_AND ? true : false ); - for ( i = 0; i < functions.length; i++ ) { - if ( relation == CKEDITOR.VALIDATE_AND ) - passed = passed && functions[ i ]( value ); - else - passed = passed || functions[ i ]( value ); - } - - return !passed ? msg : true; - }; - }, - - regex: function( regex, msg ) { - /* - * Can be greatly shortened by deriving from functions validator if code size - * turns out to be more important than performance. - */ - return function() { - var value = this && this.getValue ? this.getValue() : arguments[ 0 ]; - return !regex.test( value ) ? msg : true; - }; - }, - - notEmpty: function( msg ) { - return this.regex( notEmptyRegex, msg ); - }, - - integer: function( msg ) { - return this.regex( integerRegex, msg ); - }, - - 'number': function( msg ) { - return this.regex( numberRegex, msg ); - }, - - 'cssLength': function( msg ) { - return this.functions( function( val ) { - return cssLengthRegex.test( CKEDITOR.tools.trim( val ) ); - }, msg ); - }, - - 'htmlLength': function( msg ) { - return this.functions( function( val ) { - return htmlLengthRegex.test( CKEDITOR.tools.trim( val ) ); - }, msg ); - }, - - 'inlineStyle': function( msg ) { - return this.functions( function( val ) { - return inlineStyleRegex.test( CKEDITOR.tools.trim( val ) ); - }, msg ); - }, - - equals: function( value, msg ) { - return this.functions( function( val ) { - return val == value; - }, msg ); - }, - - notEqual: function( value, msg ) { - return this.functions( function( val ) { - return val != value; - }, msg ); - } - }; - - CKEDITOR.on( 'instanceDestroyed', function( evt ) { - // Remove dialog cover on last instance destroy. - if ( CKEDITOR.tools.isEmpty( CKEDITOR.instances ) ) { - var currentTopDialog; - while ( ( currentTopDialog = CKEDITOR.dialog._.currentTop ) ) - currentTopDialog.hide(); - removeCovers(); - } - - var dialogs = evt.editor._.storedDialogs; - for ( var name in dialogs ) - dialogs[ name ].destroy(); - - } ); - - } )(); - - // Extend the CKEDITOR.editor class with dialog specific functions. - CKEDITOR.tools.extend( CKEDITOR.editor.prototype, { - /** - * Loads and opens a registered dialog. - * - * CKEDITOR.instances.editor1.openDialog( 'smiley' ); - * - * @member CKEDITOR.editor - * @param {String} dialogName The registered name of the dialog. - * @param {Function} callback The function to be invoked after dialog instance created. - * @returns {CKEDITOR.dialog} The dialog object corresponding to the dialog displayed. - * `null` if the dialog name is not registered. - * @see CKEDITOR.dialog#add - */ - openDialog: function( dialogName, callback ) { - var dialog = null, dialogDefinitions = CKEDITOR.dialog._.dialogDefinitions[ dialogName ]; - - if ( CKEDITOR.dialog._.currentTop === null ) - showCover( this ); - - // If the dialogDefinition is already loaded, open it immediately. - if ( typeof dialogDefinitions == 'function' ) { - var storedDialogs = this._.storedDialogs || ( this._.storedDialogs = {} ); - - dialog = storedDialogs[ dialogName ] || ( storedDialogs[ dialogName ] = new CKEDITOR.dialog( this, dialogName ) ); - - callback && callback.call( dialog, dialog ); - dialog.show(); - - } else if ( dialogDefinitions == 'failed' ) { - hideCover( this ); - throw new Error( '[CKEDITOR.dialog.openDialog] Dialog "' + dialogName + '" failed when loading definition.' ); - } else if ( typeof dialogDefinitions == 'string' ) { - - CKEDITOR.scriptLoader.load( CKEDITOR.getUrl( dialogDefinitions ), - function() { - var dialogDefinition = CKEDITOR.dialog._.dialogDefinitions[ dialogName ]; - // In case of plugin error, mark it as loading failed. - if ( typeof dialogDefinition != 'function' ) - CKEDITOR.dialog._.dialogDefinitions[ dialogName ] = 'failed'; - - this.openDialog( dialogName, callback ); - }, this, 0, 1 ); - } - - CKEDITOR.skin.loadPart( 'dialog' ); - - return dialog; - } - } ); -} )(); - -CKEDITOR.plugins.add( 'cmsdialog', { - requires: 'dialogui', - init: function( editor ) { - editor.on( 'doubleclick', function( evt ) { - if ( evt.data.dialog ) - editor.openDialog( evt.data.dialog ); - }, null, null, 999 ); - } -} ); - -// Dialog related configurations. - -/** - * The color of the dialog background cover. It should be a valid CSS color string. - * - * config.dialog_backgroundCoverColor = 'rgb(255, 254, 253)'; - * - * @cfg {String} [dialog_backgroundCoverColor='white'] - * @member CKEDITOR.config - */ - -/** - * The opacity of the dialog background cover. It should be a number within the - * range `[0.0, 1.0]`. - * - * config.dialog_backgroundCoverOpacity = 0.7; - * - * @cfg {Number} [dialog_backgroundCoverOpacity=0.5] - * @member CKEDITOR.config - */ - -/** - * If the dialog has more than one tab, put focus into the first tab as soon as dialog is opened. - * - * config.dialog_startupFocusTab = true; - * - * @cfg {Boolean} [dialog_startupFocusTab=false] - * @member CKEDITOR.config - */ - -/** - * The distance of magnetic borders used in moving and resizing dialogs, - * measured in pixels. - * - * config.dialog_magnetDistance = 30; - * - * @cfg {Number} [dialog_magnetDistance=20] - * @member CKEDITOR.config - */ - -/** - * The guideline to follow when generating the dialog buttons. There are 3 possible options: - * - * * `'OS'` - the buttons will be displayed in the default order of the user's OS; - * * `'ltr'` - for Left-To-Right order; - * * `'rtl'` - for Right-To-Left order. - * - * Example: - * - * config.dialog_buttonsOrder = 'rtl'; - * - * @since 3.5 - * @cfg {String} [dialog_buttonsOrder='OS'] - * @member CKEDITOR.config - */ - -/** - * The dialog contents to removed. It's a string composed by dialog name and tab name with a colon between them. - * - * Separate each pair with semicolon (see example). - * - * **Note:** All names are case-sensitive. - * - * **Note:** Be cautious when specifying dialog tabs that are mandatory, - * like `'info'`, dialog functionality might be broken because of this! - * - * config.removeDialogTabs = 'flash:advanced;image:Link'; - * - * @since 3.5 - * @cfg {String} [removeDialogTabs=''] - * @member CKEDITOR.config - */ - -/** - * Tells if user should not be asked to confirm close, if any dialog field was modified. - * By default it is set to `false` meaning that the confirmation dialog will be shown. - * - * config.dialog_noConfirmCancel = true; - * - * @since 4.3 - * @cfg {Boolean} [dialog_noConfirmCancel=false] - * @member CKEDITOR.config - */ - -/** - * Event fired when a dialog definition is about to be used to create a dialog into - * an editor instance. This event makes it possible to customize the definition - * before creating it. - * - * Note that this event is called only the first time a specific dialog is - * opened. Successive openings will use the cached dialog, and this event will - * not get fired. - * - * @event dialogDefinition - * @member CKEDITOR - * @param {CKEDITOR.dialog.definition} data The dialog defination that - * is being loaded. - * @param {CKEDITOR.editor} editor The editor instance that will use the dialog. - */ - -/** - * Event fired when a tab is going to be selected in a dialog. - * - * @event selectPage - * @member CKEDITOR.dialog - * @param data - * @param {String} data.page The id of the page that it's gonna be selected. - * @param {String} data.currentPage The id of the current page. - */ - -/** - * Event fired when the user tries to dismiss a dialog. - * - * @event cancel - * @member CKEDITOR.dialog - * @param data - * @param {Boolean} data.hide Whether the event should proceed or not. - */ - -/** - * Event fired when the user tries to confirm a dialog. - * - * @event ok - * @member CKEDITOR.dialog - * @param data - * @param {Boolean} data.hide Whether the event should proceed or not. - */ - -/** - * Event fired when a dialog is shown. - * - * @event show - * @member CKEDITOR.dialog - */ - -/** - * Event fired when a dialog is shown. - * - * @event dialogShow - * @member CKEDITOR.editor - * @param {CKEDITOR.editor} editor This editor instance. - * @param {CKEDITOR.dialog} data The opened dialog instance. - */ - -/** - * Event fired when a dialog is hidden. - * - * @event hide - * @member CKEDITOR.dialog - */ - -/** - * Event fired when a dialog is hidden. - * - * @event dialogHide - * @member CKEDITOR.editor - * @param {CKEDITOR.editor} editor This editor instance. - * @param {CKEDITOR.dialog} data The hidden dialog instance. - */ - -/** - * Event fired when a dialog is being resized. The event is fired on - * both the {@link CKEDITOR.dialog} object and the dialog instance - * since 3.5.3, previously it was only available in the global object. - * - * @static - * @event resize - * @member CKEDITOR.dialog - * @param data - * @param {CKEDITOR.dialog} data.dialog The dialog being resized (if - * it is fired on the dialog itself, this parameter is not sent). - * @param {String} data.skin The skin name. - * @param {Number} data.width The new width. - * @param {Number} data.height The new height. - */ - -/** - * Event fired when a dialog is being resized. The event is fired on - * both the {@link CKEDITOR.dialog} object and the dialog instance - * since 3.5.3, previously it was only available in the global object. - * - * @since 3.5 - * @event resize - * @member CKEDITOR.dialog - * @param data - * @param {Number} data.width The new width. - * @param {Number} data.height The new height. - */ - -/** - * Event fired when the dialog state changes, usually by {@link CKEDITOR.dialog#setState}. - * - * @since 4.5 - * @event state - * @member CKEDITOR.dialog - * @param data - * @param {Number} data The new state. Either {@link CKEDITOR#DIALOG_STATE_IDLE} or {@link CKEDITOR#DIALOG_STATE_BUSY}. - */ -})(CMS.$); diff --git a/static/djangocms_text_ckeditor/ckeditor_plugins/cmsplugins/icons/.aldryn-folder b/static/djangocms_text_ckeditor/ckeditor_plugins/cmsplugins/icons/.aldryn-folder deleted file mode 100644 index e69de29..0000000 diff --git a/static/djangocms_text_ckeditor/ckeditor_plugins/cmsplugins/icons/cmsplugins.png b/static/djangocms_text_ckeditor/ckeditor_plugins/cmsplugins/icons/cmsplugins.png deleted file mode 100644 index 18d784f..0000000 Binary files a/static/djangocms_text_ckeditor/ckeditor_plugins/cmsplugins/icons/cmsplugins.png and /dev/null differ diff --git a/static/djangocms_text_ckeditor/ckeditor_plugins/cmsplugins/icons/cmsplugins.psd b/static/djangocms_text_ckeditor/ckeditor_plugins/cmsplugins/icons/cmsplugins.psd deleted file mode 100644 index 690326e..0000000 Binary files a/static/djangocms_text_ckeditor/ckeditor_plugins/cmsplugins/icons/cmsplugins.psd and /dev/null differ diff --git a/static/djangocms_text_ckeditor/ckeditor_plugins/cmsplugins/plugin.js b/static/djangocms_text_ckeditor/ckeditor_plugins/cmsplugins/plugin.js deleted file mode 100644 index dd427ec..0000000 --- a/static/djangocms_text_ckeditor/ckeditor_plugins/cmsplugins/plugin.js +++ /dev/null @@ -1,552 +0,0 @@ -(function ($) { - if (CKEDITOR && CKEDITOR.plugins && CKEDITOR.plugins.registered && CKEDITOR.plugins.registered.cmsplugins) { - return; - } - - /** - * Determine if we should return `div` or `span` based on the - * plugin markup. - * - * @function getFakePluginElement - * @private - * @param {String} pluginMarkup valid html hopefully - * @returns {String} div|span - */ - function getFakePluginElement(pluginMarkup) { - var innerTags = (pluginMarkup.match(/<\s*([^>\s]+)[\s\S]*?>/) || [0, false]).splice(1); - - var containsAnyBlockLikeElements = innerTags.some(function (tag) { - return tag && CKEDITOR.dtd.$block[tag]; - }); - - var fakeRealType = 'span'; - - if (containsAnyBlockLikeElements) { - fakeRealType = 'div'; - } - - return fakeRealType; - } - - /** - * @function replaceTagName - * @private - * @param {jQuery} elements - * @param {String} tagName - */ - function replaceTagName(elements, tagName) { - elements.each(function (i, el) { - var newElement; - - var element = $(el); - - newElement = $('<' + tagName + '>'); - - // attributes - $.each(el.attributes, function (index, attribute) { - newElement.attr(attribute.nodeName, attribute.nodeValue); - }); - - // content - newElement.html(element.html()); - - element.replaceWith(newElement); - }); - } - - CKEDITOR.plugins.add('cmsplugins', { - - // Register the icons. They must match command names. - icons: 'cmsplugins', - - // The plugin initialization logic goes inside this method. - init: function (editor) { - var that = this; - - this.options = CMS.CKEditor.options.settings; - this.editor = editor; - - /** - * populated with _fresh_ child plugins - */ - this.child_plugins = []; - this.setupCancelCleanupCallback(this.options); - - // don't do anything if there are no plugins defined - if (this.options === undefined || this.options.plugins === undefined) { - return false; - } - - this.setupDialog(); - - // add the button - this.editor.ui.add('cmsplugins', CKEDITOR.UI_PANELBUTTON, { - toolbar: 'cms,0', - label: this.options.lang.toolbar, - title: this.options.lang.toolbar, - className: 'cke_panelbutton__cmsplugins', - modes: { wysiwyg: 1 }, - editorFocus: 0, - - panel: { - css: [CKEDITOR.skin.getPath('editor')].concat(that.editor.config.contentsCss), - attributes: { 'role': 'cmsplugins', 'aria-label': this.options.lang.aria } - }, - - // this is called when creating the dropdown list - onBlock: function (panel, block) { - block.element.setHtml(that.editor.plugins.cmsplugins.setupDropdown()); - - var anchors = $(block.element.$).find('.cke_panel_listItem a'); - - anchors.bind('click', function (e) { - e.preventDefault(); - - that.addPlugin($(this), panel); - }); - } - }); - - // handle edit event via context menu - if (this.editor.contextMenu) { - this.setupContextMenu(); - } - - this.editor.addCommand('cmspluginsEdit', { - exec: function () { - var element = that.getElementFromSelection(); - var plugin = that.getPluginWidget(element); - - if (plugin) { - that.editPlugin(plugin); - } - } - }); - - // handle edit event on double click - // if event is a jQuery event (touchend), than we mutate - // event a bit so we make the payload similar to what ckeditor.event produces - var handleEdit = function (event) { - var element; - - if (event.type === 'touchend' || event.type === 'click') { - var cmsPluginNode = $(event.currentTarget).closest('cms-plugin')[0]; - - // pick cke_widget span - // eslint-disable-next-line new-cap - element = new CKEDITOR.dom.element(cmsPluginNode).getParent(); - - event.data = event.data || {}; - // have to fake selection to be able to replace markup after editing - that.editor.getSelection().fake(element); - } - - that.editor.execCommand('cmspluginsEdit'); - }; - - this.editor.on('doubleclick', handleEdit); - this.editor.on('instanceReady', function () { - CMS.$('cms-plugin', CMS.$('iframe.cke_wysiwyg_frame')[0] - .contentWindow.document.documentElement).on('click touchend', handleEdit); - }); - - this.setupDataProcessor(); - }, - - getElementFromSelection: function () { - var selection = this.editor.getSelection(); - var element = selection.getSelectedElement() || - selection.getCommonAncestor().getAscendant('cms-plugin', true); - - return element; - }, - - getPluginWidget: function (element) { - if (!element) { - return null; - } - return element.getAscendant('cms-plugin', true) || element.findOne('cms-plugin'); - }, - - setupDialog: function () { - var that = this; - var definition = function () { - return { - title: '', - minWidth: 200, - minHeight: 200, - contents: [{ - elements: [ - { - type: 'html', - html: '');a.appendTo(i.getParent())}return n.unselectable(),o.unselectable(),{element:e,parts:{dialog:e.getChild(0),title:n,close:o,tabs:i.getChild(2),contents:i.getChild([3,0,0,0]),footer:i.getChild([3,0,1,0])}}}function r(t,e,i){this.element=e,this.focusIndex=i,this.tabIndex=0,this.isFocusable=function(){return!e.getAttribute("disabled")&&e.isVisible()},this.focus=function(){t._.currentFocusIndex=this.focusIndex,this.element.focus()},e.on("keydown",function(t){t.data.getKeystroke()in{32:1,13:1}&&this.fire("click")}),e.on("focus",function(){this.fire("mouseover")}),e.on("blur",function(){this.fire("mouseout")})}function l(t){function e(){t.layout()}var i=CKEDITOR.document.getWindow();i.on("resize",e),t.on("hide",function(){i.removeListener("resize",e)})}function d(t,e){this._={dialog:t},CKEDITOR.tools.extend(this,e)}function u(t){function e(e){var i,l,d=t.getSize(),u=CKEDITOR.document.getWindow().getViewPaneSize(),c=e.originalEvent.screenX,h=e.originalEvent.screenY,g=c-n.x,f=h-n.y;n={x:c,y:h},o.x+=g,o.y+=f,i=o.x+r[3]u.width-d.width-a?u.width-d.width+("rtl"==s.lang.dir?0:r[1]):o.x,l=o.y+r[0]u.height-d.height-a?u.height-d.height+r[2]:o.y,t.move(i,l,1),e.preventDefault()}function i(){if(CMS.$(CKEDITOR.document.$).off("pointermove",e),CMS.$(CKEDITOR.document.$).off("pointerup",i),CKEDITOR.env.ie6Compat){var t=b.getChild(0).getFrameDocument();t.removeListener("mousemove",e),t.removeListener("mouseup",i)}}var n=null,o=null,s=t.getParentEditor(),a=s.config.dialog_magnetDistance,r=CKEDITOR.skin.margins||[0,0,0,0];"undefined"==typeof a&&(a=20),CMS.$(t.parts.title.$).on("pointerdown",function(s){if(n={x:s.originalEvent.screenX,y:s.originalEvent.screenY},CMS.$(CKEDITOR.document.$).on("pointermove",e),CMS.$(CKEDITOR.document.$).on("pointerup",i),o=t.getPosition(),CKEDITOR.env.ie6Compat){var a=b.getChild(0).getFrameDocument();a.on("mousemove",e),a.on("mouseup",i)}s.preventDefault()})}function c(t){function e(e){var i="rtl"==c.lang.dir,u=(e.originalEvent.screenX-l.x)*(i?-1:1),h=e.originalEvent.screenY-l.y,g=d.width,f=d.height,p=g+u*(t._.moved?1:2),_=f+h*(t._.moved?1:2),I=t._.element.getFirst(),m=i&&I.getComputedStyle("right"),v=t.getPosition();v.y+_>r.height&&(_=r.height-v.y),(i?m:v.x)+p>r.width&&(p=r.width-(i?m:v.x)),o!=CKEDITOR.DIALOG_RESIZE_WIDTH&&o!=CKEDITOR.DIALOG_RESIZE_BOTH||(g=Math.max(n.minWidth||0,p-s)),o!=CKEDITOR.DIALOG_RESIZE_HEIGHT&&o!=CKEDITOR.DIALOG_RESIZE_BOTH||(f=Math.max(n.minHeight||0,_-a)),t.resize(g,f),t._.moved||t.layout(),e.preventDefault()}function i(){if(CMS.$(CKEDITOR.document.$).off("pointermove",e),CMS.$(CKEDITOR.document.$).off("pointerup",i),u&&(u.remove(),u=null),CKEDITOR.env.ie6Compat){var t=b.getChild(0).getFrameDocument();t.removeListener("mouseup",i),t.removeListener("mousemove",e)}}var n=t.definition,o=n.resizable;if(o!=CKEDITOR.DIALOG_RESIZE_NONE){var s,a,r,l,d,u,c=t.getParentEditor(),h=CKEDITOR.tools.addFunction(function(n){d=t.getSize();var o=t.parts.contents,c=o.$.getElementsByTagName("iframe").length;if(c&&(CMS.$(".cke_dialog_resize_cover").remove(),u=CKEDITOR.dom.element.createFromHtml('
    '),o.append(u)),a=d.height-t.parts.contents.getSize("height",!(CKEDITOR.env.gecko||CKEDITOR.env.ie&&CKEDITOR.env.quirks)),s=d.width-t.parts.contents.getSize("width",1),l={x:n.screenX,y:n.screenY},r=CKEDITOR.document.getWindow().getViewPaneSize(),CMS.$(CKEDITOR.document.$).on("pointermove",e),CMS.$(CKEDITOR.document.$).on("pointerup",i),CKEDITOR.env.ie6Compat){var h=b.getChild(0).getFrameDocument();h.on("mousemove",e),h.on("mouseup",i)}n.preventDefault&&n.preventDefault()});t.on("load",function(){var e="";o==CKEDITOR.DIALOG_RESIZE_WIDTH?e=" cke_resizer_horizontal":o==CKEDITOR.DIALOG_RESIZE_HEIGHT&&(e=" cke_resizer_vertical");var i=CKEDITOR.dom.element.createFromHtml('
    '+("ltr"==c.lang.dir?"◢":"◣")+"
    ");t.parts.footer.append(i,1)}),c.on("destroy",function(){CKEDITOR.tools.removeFunction(h)})}}function h(t){t.data.preventDefault(1)}function g(t){var e=CKEDITOR.document.getWindow(),i=t.config,n=i.dialog_backgroundCoverColor||"white",o=i.dialog_backgroundCoverOpacity,s=i.baseFloatZIndex,a=CKEDITOR.tools.genKey(n,o,s),r=O[a];if(CMS.$(".cke_dialog_background_cover:not(.cms-ckeditor-dialog-background-cover)").remove(),r)r.show();else{O={};var l=['
    '];if(CKEDITOR.env.ie6Compat){var d="";l.push('')}l.push("
    "),r=CKEDITOR.dom.element.createFromHtml(l.join("")),r.setOpacity(void 0!==o?o:.5),r.on("keydown",h),r.on("keypress",h),r.on("keyup",h),r.appendTo(CKEDITOR.document.getBody()),O[a]=r}t.focusManager.add(r),b=r;var u=function(){var t=e.getViewPaneSize();r.setStyles({width:t.width+"px",height:t.height+"px"})},c=function(){var t=e.getScrollPosition(),i=CKEDITOR.dialog._.currentTop;if(r.setStyles({left:t.x+"px",top:t.y+"px"}),i)do{var n=i.getPosition();i.move(n.x,n.y)}while(i=i._.parentDialog)};if(D=u,e.on("resize",u),u(),CKEDITOR.env.mac&&CKEDITOR.env.webkit||r.focus(),CKEDITOR.env.ie6Compat){var g=function(){c(),arguments.callee.prevScrollHandler.apply(this,arguments)};e.$.setTimeout(function(){g.prevScrollHandler=window.onscroll||function(){},window.onscroll=g},0),c()}}function f(t){if(CMS.$(".cke_dialog_background_cover:not(.cms-ckeditor-dialog-background-cover)").remove(),b){t.focusManager.remove(b);var e=CKEDITOR.document.getWindow();b.hide(),e.removeListener("resize",D),CKEDITOR.env.ie6Compat&&e.$.setTimeout(function(){var t=window.onscroll&&window.onscroll.prevScrollHandler;window.onscroll=t||null},0),D=null}}function p(){for(var t in O)O[t].remove();O={}}var _=CKEDITOR.tools.cssLength,I='';CKEDITOR.dialog=function(t,n){function r(){var t=y._.focusList;t.sort(function(t,e){return t.tabIndex!=e.tabIndex?e.tabIndex-t.tabIndex:t.focusIndex-e.focusIndex});for(var e=t.length,i=0;i1;do{if(n+=t,o&&!y._.tabBarMode&&(n==e.length||n==-1))return y._.tabBarMode=!0,y._.tabs[y._.currentTabId][0].focus(),void(y._.currentFocusIndex=-1);if(n=(n+e.length)%e.length,n==i)break}while(t&&!e[n].isFocusable());e[n].focus(),"text"==e[n].type&&e[n].select()}}function d(n){if(y==CKEDITOR.dialog._.currentTop){var o,s=n.data.getKeystroke(),a="rtl"==t.lang.dir,r=[37,38,39,40];if(f=p=0,9==s||s==CKEDITOR.SHIFT+9){var d=s==CKEDITOR.SHIFT+9;l(d?-1:1),f=1}else if(s==CKEDITOR.ALT+121&&!y._.tabBarMode&&y.getPageCount()>1)y._.tabBarMode=!0,y._.tabs[y._.currentTabId][0].focus(),y._.currentFocusIndex=-1,f=1;else if(CKEDITOR.tools.indexOf(r,s)!=-1&&y._.tabBarMode){var u=[a?39:37,38],c=CKEDITOR.tools.indexOf(u,s)!=-1?e.call(y):i.call(y);y.selectPage(c),y._.tabs[c][0].focus(),f=1}else if(13!=s&&32!=s||!y._.tabBarMode)if(13==s){var g=n.data.getTarget();g.is("a","button","select","textarea")||g.is("input")&&"button"==g.$.type||(o=this.getButton("ok"),o&&CKEDITOR.tools.setTimeout(o.click,0,o),f=1),p=1}else{if(27!=s)return;o=this.getButton("cancel"),o?CKEDITOR.tools.setTimeout(o.click,0,o):this.fire("cancel",{hide:!0}).hide!==!1&&this.hide(),p=1}else this.selectPage(this._.currentTabId),this._.tabBarMode=!1,this._.currentFocusIndex=-1,l(1),f=1;h(n)}}function h(t){f?t.data.preventDefault(1):p&&t.data.stopPropagation()}var g,f,p,_=CKEDITOR.dialog._.dialogDefinitions[n],I=CKEDITOR.tools.clone(m),v=t.config.dialog_buttonsOrder||"OS",C=t.lang.dir,E={};("OS"==v&&CKEDITOR.env.mac||"rtl"==v&&"ltr"==C||"ltr"==v&&"rtl"==C)&&I.buttons.reverse(),_=CKEDITOR.tools.extend(_(t),I),_=CKEDITOR.tools.clone(_),_=new T(this,_);var D=a(t);this._={editor:t,element:D.element,name:n,contentSize:{width:0,height:0},size:{width:0,height:0},contents:{},buttons:{},accessKeyMap:{},tabs:{},tabIdList:[],currentTabId:null,currentTabIndex:null,pageCount:0,lastTab:null,tabBarMode:!1,focusList:[],currentFocusIndex:0,hasFocus:!1},this.parts=D.parts,CKEDITOR.tools.setTimeout(function(){t.fire("ariaWidget",this.parts.contents)},0,this);var b={position:CKEDITOR.env.ie6Compat?"absolute":"fixed",top:0,visibility:"hidden"};if(b["rtl"==C?"right":"left"]=0,this.parts.dialog.setStyles(b),CKEDITOR.event.call(this),this.definition=_=CKEDITOR.fire("dialogDefinition",{name:n,definition:_},t).definition,!("removeDialogTabs"in t._)&&t.config.removeDialogTabs){var O=t.config.removeDialogTabs.split(";");for(g=0;g1;if(t.config.dialog_startupFocusTab&&e)y._.tabBarMode=!0,y._.tabs[y._.currentTabId][0].focus(),y._.currentFocusIndex=-1;else if(!this._.hasFocus)if(this._.currentFocusIndex=e?-1:this._.focusList.length-1,_.onFocus){var i=_.onFocus.call(this);i&&i.focus()}else l(1)},this,null,4294967295),CKEDITOR.env.ie6Compat&&this.on("load",function(){var t=this.getElement(),e=t.getFirst();e.remove(),e.appendTo(t)},this),u(this),c(this),new CKEDITOR.dom.text(_.title,CKEDITOR.document).appendTo(this.parts.title),g=0;g<_.contents.length;g++){var w=_.contents[g];w&&this.addPage(w)}this.parts.tabs.on("click",function(t){var e=t.data.getTarget();if(e.hasClass("cke_dialog_tab")){var i=e.$.id;this.selectPage(i.substring(4,i.lastIndexOf("_"))),this._.tabBarMode&&(this._.tabBarMode=!1,this._.currentFocusIndex=-1,l(1)),t.data.preventDefault()}},this);var S=[],L=CKEDITOR.dialog._.uiElementBuilders.hbox.build(this,{type:"hbox",className:"cke_dialog_footer_buttons",widths:[],children:_.buttons},S).getChild();for(this.parts.footer.setHtml(S.join("")),g=0;g0?e:0)+"px"};d[o?"right":"left"]=(t>0?t:0)+"px",n.setStyles(d),i&&(this._.moved=1)}},getPosition:function(){return CKEDITOR.tools.extend({},this._.position)},show:function(){var t=this._.element,e=this.definition;if(t.getParent()&&t.getParent().equals(CKEDITOR.document.getBody())?t.setStyle("display","block"):t.appendTo(CKEDITOR.document.getBody()),this.resize(this._.contentSize&&this._.contentSize.width||e.width||e.minWidth,this._.contentSize&&this._.contentSize.height||e.height||e.minHeight),this.reset(),this.selectPage(this.definition.contents[0].id),null===CKEDITOR.dialog._.currentZIndex&&(CKEDITOR.dialog._.currentZIndex=this._.editor.config.baseFloatZIndex),this._.element.getFirst().setStyle("z-index",CKEDITOR.dialog._.currentZIndex+=10),null===CKEDITOR.dialog._.currentTop)CKEDITOR.dialog._.currentTop=this,this._.parentDialog=null,g(this._.editor);else{this._.parentDialog=CKEDITOR.dialog._.currentTop;var i=this._.parentDialog.getElement().getFirst();i.$.style.zIndex-=Math.floor(this._.editor.config.baseFloatZIndex/2),CKEDITOR.dialog._.currentTop=this}t.on("keydown",R),t.on("keyup",y),this._.hasFocus=!1;for(var n in e.contents)if(e.contents[n]){var o=e.contents[n],s=this._.tabs[o.id],a=o.requiredContent,r=0;if(s){for(var d in this._.contents[o.id]){var u=this._.contents[o.id][d];"hbox"!=u.type&&"vbox"!=u.type&&u.getInputElement()&&(u.requiredContent&&!this._.editor.activeFilter.check(u.requiredContent)?u.disable():(u.enable(),r++))}!r||a&&!this._.editor.activeFilter.check(a)?s[0].addClass("cke_dialog_tab_disabled"):s[0].removeClass("cke_dialog_tab_disabled")}}CKEDITOR.tools.setTimeout(function(){this.layout(),l(this),this.parts.dialog.setStyle("visibility",""),this.fireOnce("load",{}),CKEDITOR.ui.fire("ready",this),this.fire("show",{}),this._.editor.fire("dialogShow",this),this._.parentDialog||this._.editor.focusManager.lock(),this.foreach(function(t){t.setInitValue&&t.setInitValue()})},100,this)},layout:function(){var t=this.parts.dialog,e=this.getSize(),i=CKEDITOR.document.getWindow(),n=i.getViewPaneSize(),o=(n.width-e.width)/2,s=(n.height-e.height)/2;CKEDITOR.env.ie6Compat||(e.height+(s>0?s:0)>n.height||e.width+(o>0?o:0)>n.width?t.setStyle("position","absolute"):t.setStyle("position","fixed")),this.move(this._.moved?this._.position.x:o,this._.moved?this._.position.y:s)},foreach:function(t){for(var e in this._.contents)for(var i in this._.contents[e])t.call(this,this._.contents[e][i]);return this},reset:function(){var t=function(t){t.reset&&t.reset(1)};return function(){return this.foreach(t),this}}(),setupContent:function(){var t=arguments;this.foreach(function(e){e.setup&&e.setup.apply(e,t)})},commitContent:function(){var t=arguments;this.foreach(function(e){CKEDITOR.env.ie&&this._.currentFocusIndex==e.focusIndex&&e.getInputElement().$.blur(),e.commit&&e.commit.apply(e,t)})},hide:function(){if(this.parts.dialog.isVisible()){this.fire("hide",{}),this._.editor.fire("dialogHide",this),this.selectPage(this._.tabIdList[0]);var t=this._.element;for(t.setStyle("display","none"),this.parts.dialog.setStyle("visibility","hidden"),k(this);CKEDITOR.dialog._.currentTop!=this;)CKEDITOR.dialog._.currentTop.hide();if(this._.parentDialog){var e=this._.parentDialog.getElement().getFirst();e.setStyle("z-index",parseInt(e.$.style.zIndex,10)+Math.floor(this._.editor.config.baseFloatZIndex/2))}else f(this._.editor);if(CKEDITOR.dialog._.currentTop=this._.parentDialog,this._.parentDialog)CKEDITOR.dialog._.currentZIndex-=10;else{CKEDITOR.dialog._.currentZIndex=null,t.removeListener("keydown",R),t.removeListener("keyup",y);var i=this._.editor;i.focus(),setTimeout(function(){i.focusManager.unlock(),CKEDITOR.env.iOS&&i.window.focus()},0)}delete this._.parentDialog,this.foreach(function(t){t.resetInitValue&&t.resetInitValue()}),this.setState(CKEDITOR.DIALOG_STATE_IDLE)}},addPage:function(t){if(!t.requiredContent||this._.editor.filter.check(t.requiredContent)){for(var e,i=[],n=t.label?' title="'+CKEDITOR.tools.htmlEncode(t.label)+'"':"",o=CKEDITOR.dialog._.uiElementBuilders.vbox.build(this,{type:"vbox",className:"cke_dialog_page_contents",children:t.elements,expand:!!t.expand,padding:t.padding,style:t.style||"width: 100%;"},i),s=this._.contents[t.id]={},a=o.getChild(),r=0;e=a.shift();)e.notAllowed||"hbox"==e.type||"vbox"==e.type||r++,s[e.id]=e,"function"==typeof e.getChild&&a.push.apply(a,e.getChild());r||(t.hidden=!0);var l=CKEDITOR.dom.element.createFromHtml(i.join(""));l.setAttribute("role","tabpanel");var d=CKEDITOR.env,u="cke_"+t.id+"_"+CKEDITOR.tools.getNextNumber(),c=CKEDITOR.dom.element.createFromHtml(['0?" cke_last":"cke_first",n,t.hidden?' style="display:none"':"",' id="',u,'"',d.gecko&&!d.hc?"":' href="javascript:void(0)"',' tabIndex="-1"',' hidefocus="true"',' role="tab">',t.label,""].join(""));l.setAttribute("aria-labelledby",u),this._.tabs[t.id]=[c,l],this._.tabIdList.push(t.id),!t.hidden&&this._.pageCount++,this._.lastTab=c,this.updateStyle(),l.setAttribute("name",t.id),l.appendTo(this.parts.contents),c.unselectable(),this.parts.tabs.append(c),t.accessKey&&(x(this,this,"CTRL+"+t.accessKey,S,w),this._.accessKeyMap["CTRL+"+t.accessKey]=t.id)}},selectPage:function(t){if(this._.currentTabId!=t&&!this._.tabs[t][0].hasClass("cke_dialog_tab_disabled")&&this.fire("selectPage",{page:t,currentPage:this._.currentTabId})!==!1){for(var e in this._.tabs){var i=this._.tabs[e][0],o=this._.tabs[e][1];e!=t&&(i.removeClass("cke_dialog_tab_selected"),o.hide()),o.setAttribute("aria-hidden",e!=t)}var s=this._.tabs[t];s[0].addClass("cke_dialog_tab_selected"),CKEDITOR.env.ie6Compat||CKEDITOR.env.ie7Compat?(n(s[1]),s[1].show(),setTimeout(function(){n(s[1],1)},0)):s[1].show(),this._.currentTabId=t,this._.currentTabIndex=CKEDITOR.tools.indexOf(this._.tabIdList,t)}},updateStyle:function(){this.parts.dialog[(1===this._.pageCount?"add":"remove")+"Class"]("cke_single_page")},hidePage:function(t){var i=this._.tabs[t]&&this._.tabs[t][0];i&&1!=this._.pageCount&&i.isVisible()&&(t==this._.currentTabId&&this.selectPage(e.call(this)),i.hide(),this._.pageCount--,this.updateStyle())},showPage:function(t){var e=this._.tabs[t]&&this._.tabs[t][0];e&&(e.show(),this._.pageCount++,this.updateStyle())},getElement:function(){return this._.element},getName:function(){return this._.name},getContentElement:function(t,e){var i=this._.contents[t];return i&&i[e]},getValueOf:function(t,e){return this.getContentElement(t,e).getValue()},setValueOf:function(t,e,i){return this.getContentElement(t,e).setValue(i)},getButton:function(t){return this._.buttons[t]},click:function(t){return this._.buttons[t].click()},disableButton:function(t){return this._.buttons[t].disable()},enableButton:function(t){return this._.buttons[t].enable()},getPageCount:function(){return this._.pageCount},getParentEditor:function(){return this._.editor},getSelectedElement:function(){return this.getParentEditor().getSelection().getSelectedElement()},addFocusable:function(t,e){if("undefined"==typeof e)e=this._.focusList.length,this._.focusList.push(new r(this,t,e));else{this._.focusList.splice(e,0,new r(this,t,e));for(var i=e+1;i=0;n--)i[n].dialog!=t&&i[n].uiElement!=t||i.splice(n,1);0===i.length&&delete K[e]}},w=function(t,e){t._.accessKeyMap[e]&&t.selectPage(t._.accessKeyMap[e])},S=function(){};!function(){CKEDITOR.ui.dialog={uiElement:function(t,e,i,n,o,s,a){if(!(arguments.length<4)){var r,l=(n.call?n(e):n)||"div",d=["<",l," "],u=(o&&o.call?o(e):o)||{},c=(s&&s.call?s(e):s)||{},h=(a&&a.call?a.call(this,t,e):a)||"",g=this.domId=c.id||CKEDITOR.tools.getNextId()+"_uiElement";e.requiredContent&&!t.getParentEditor().filter.check(e.requiredContent)&&(u.display="none",this.notAllowed=!0),c.id=g;var f={};e.type&&(f["cke_dialog_ui_"+e.type]=1),e.className&&(f[e.className]=1),e.disabled&&(f.cke_disabled=1);var p=c.class&&c.class.split?c.class.split(" "):[];for(r=0;r=0;r--)""===I[r]&&I.splice(r,1);I.length>0&&(c.style=(c.style?c.style+"; ":"")+I.join("; "));for(r in c)d.push(r+'="'+CKEDITOR.tools.htmlEncode(c[r])+'" ');d.push(">",h,""),i.push(d.join("")),(this._||(this._={})).dialog=t,"boolean"==typeof e.isChanged&&(this.isChanged=function(){return e.isChanged}),"function"==typeof e.isChanged&&(this.isChanged=e.isChanged),"function"==typeof e.setValue&&(this.setValue=CKEDITOR.tools.override(this.setValue,function(t){return function(i){t.call(this,e.setValue.call(this,i))}})),"function"==typeof e.getValue&&(this.getValue=CKEDITOR.tools.override(this.getValue,function(t){return function(){return e.getValue.call(this,t.call(this))}})),CKEDITOR.event.implementOn(this),this.registerEvents(e),this.accessKeyUp&&this.accessKeyDown&&e.accessKey&&x(this,t,"CTRL+"+e.accessKey);var v=this;t.on("load",function(){var e=v.getInputElement();if(e){var i=v.type in{checkbox:1,ratio:1}&&CKEDITOR.env.ie&&CKEDITOR.env.version<8?"cke_dialog_ui_focused":"";e.on("focus",function(){t._.tabBarMode=!1,t._.hasFocus=!0,v.fire("focus"),i&&this.addClass(i)}),e.on("blur",function(){v.fire("blur"),i&&this.removeClass(i)})}}),CKEDITOR.tools.extend(this,e),this.keyboardFocusable&&(this.tabIndex=e.tabIndex||0,this.focusIndex=t._.focusList.push(this)-1,this.on("focus",function(){t._.currentFocusIndex=v.focusIndex}))}},hbox:function(t,e,i,n,o){if(!(arguments.length<4)){this._||(this._={});var s,a=this._.children=e,r=o&&o.widths||null,l=o&&o.height||null,d={},u=function(){var t=[''];for(s=0;s0&&t.push('style="'+n.join("; ")+'" '),t.push(">",i[s],"")}return t.push(""),t.join("")},c={role:"presentation"};o&&o.align&&(c.align=o.align),CKEDITOR.ui.dialog.uiElement.call(this,t,o||{type:"hbox"},n,"table",d,c,u)}},vbox:function(t,e,i,n,o){if(!(arguments.length<3)){this._||(this._={});var s=this._.children=e,a=o&&o.width||null,r=o&&o.heights||null,l=function(){var e=['");for(var n=0;n")}return e.push("
    0&&e.push('style="',l.join("; "),'" '),e.push(' class="cke_dialog_ui_vbox_child">',i[n],"
    "),e.join("")};CKEDITOR.ui.dialog.uiElement.call(this,t,o||{type:"vbox"},n,"div",null,{role:"presentation"},l)}}}}(),CKEDITOR.ui.dialog.uiElement.prototype={getElement:function(){return CKEDITOR.document.getById(this.domId)},getInputElement:function(){ -return this.getElement()},getDialog:function(){return this._.dialog},setValue:function(t,e){return this.getInputElement().setValue(t),!e&&this.fire("change",{value:t}),this},getValue:function(){return this.getInputElement().getValue()},isChanged:function(){return!1},selectParentTab:function(){for(var t,e=this.getInputElement(),i=e;(i=i.getParent())&&i.$.className.search("cke_dialog_page_contents")==-1;);return i?(t=i.getAttribute("name"),this._.dialog._.currentTabId!=t&&this._.dialog.selectPage(t),this):this},focus:function(){return this.selectParentTab().getInputElement().focus(),this},registerEvents:function(t){var e,i=/^on([A-Z]\w+)/,n=function(t,e,i,n){e.on("load",function(){t.getInputElement().on(i,n,t)})};for(var o in t)(e=o.match(i))&&(this.eventProcessors[o]?this.eventProcessors[o].call(this,this._.dialog,t[o]):n(this,this._.dialog,e[1].toLowerCase(),t[o]));return this},eventProcessors:{onLoad:function(t,e){t.on("load",e,this)},onShow:function(t,e){t.on("show",e,this)},onHide:function(t,e){t.on("hide",e,this)}},accessKeyDown:function(){this.focus()},accessKeyUp:function(){},disable:function(){var t=this.getElement(),e=this.getInputElement();e.setAttribute("disabled","true"),t.addClass("cke_disabled")},enable:function(){var t=this.getElement(),e=this.getInputElement();e.removeAttribute("disabled"),t.removeClass("cke_disabled")},isEnabled:function(){return!this.getElement().hasClass("cke_disabled")},isVisible:function(){return this.getInputElement().isVisible()},isFocusable:function(){return!(!this.isEnabled()||!this.isVisible())}},CKEDITOR.ui.dialog.hbox.prototype=CKEDITOR.tools.extend(new CKEDITOR.ui.dialog.uiElement,{getChild:function(t){return arguments.length<1?this._.children.concat():(t.splice||(t=[t]),t.length<2?this._.children[t[0]]:this._.children[t[0]]&&this._.children[t[0]].getChild?this._.children[t[0]].getChild(t.slice(1,t.length)):null)}},!0),CKEDITOR.ui.dialog.vbox.prototype=new CKEDITOR.ui.dialog.hbox,function(){var t={build:function(t,e,i){for(var n,o=e.children,s=[],a=[],r=0;rd.width&&(n.resize_minWidth=d.width),n.resize_minHeight>d.height&&(n.resize_minHeight=d.height),CMS.$(CKEDITOR.document.$).on("pointermove",i),CMS.$(CKEDITOR.document.$).on("pointerup",t),e.document&&(CMS.$(e.document.$).on("pointermove",i),CMS.$(e.document.$).on("pointerup",t)),r.preventDefault&&r.preventDefault()});CMS.$(CKEDITOR.document.$).find("html").attr("data-touch-action","none"),e.on("destroy",function(){CKEDITOR.tools.removeFunction(c)}),e.on("uiSpace",function(i){if("bottom"==i.data.space){var t="";m&&!h&&(t=" cke_resizer_horizontal"),!m&&h&&(t=" cke_resizer_vertical");var n=''+("ltr"==o?"◢":"◣")+"";"ltr"==o&&"ltr"==t?i.data.html+=n:i.data.html=n+i.data.html}},e,null,100),e.on("maximize",function(i){e.ui.space("resizer")[i.data==CKEDITOR.TRISTATE_ON?"hide":"show"]()})}}})}(CMS.$); -!function(e){function t(e){var t=(e.match(/<\s*([^>\s]+)[\s\S]*?>/)||[0,!1]).splice(1),i=t.some(function(e){return e&&CKEDITOR.dtd.$block[e]}),n="span";return i&&(n="div"),n}function i(t,i){t.each(function(t,n){var s,l=e(n);s=e("<"+i+">"),e.each(n.attributes,function(e,t){s.attr(t.nodeName,t.nodeValue)}),s.html(l.html()),l.replaceWith(s)})}CKEDITOR&&CKEDITOR.plugins&&CKEDITOR.plugins.registered&&CKEDITOR.plugins.registered.cmsplugins||CKEDITOR.plugins.add("cmsplugins",{icons:"cmsplugins",init:function(t){var i=this;if(this.options=CMS.CKEditor.options.settings,this.editor=t,this.child_plugins=[],this.setupCancelCleanupCallback(this.options),void 0===this.options||void 0===this.options.plugins)return!1;this.setupDialog(),this.editor.ui.add("cmsplugins",CKEDITOR.UI_PANELBUTTON,{toolbar:"cms,0",label:this.options.lang.toolbar,title:this.options.lang.toolbar,className:"cke_panelbutton__cmsplugins",modes:{wysiwyg:1},editorFocus:0,panel:{css:[CKEDITOR.skin.getPath("editor")].concat(i.editor.config.contentsCss),attributes:{role:"cmsplugins","aria-label":this.options.lang.aria}},onBlock:function(t,n){n.element.setHtml(i.editor.plugins.cmsplugins.setupDropdown());var s=e(n.element.$).find(".cke_panel_listItem a");s.bind("click",function(n){n.preventDefault(),i.addPlugin(e(this),t)})}}),this.editor.contextMenu&&this.setupContextMenu(),this.editor.addCommand("cmspluginsEdit",{exec:function(){var e=i.getElementFromSelection(),t=i.getPluginWidget(e);t&&i.editPlugin(t)}});var n=function(t){var n;if("touchend"===t.type||"click"===t.type){var s=e(t.currentTarget).closest("cms-plugin")[0];n=new CKEDITOR.dom.element(s).getParent(),t.data=t.data||{},i.editor.getSelection().fake(n)}i.editor.execCommand("cmspluginsEdit")};this.editor.on("doubleclick",n),this.editor.on("instanceReady",function(){CMS.$("cms-plugin",CMS.$("iframe.cke_wysiwyg_frame")[0].contentWindow.document.documentElement).on("click touchend",n)}),this.setupDataProcessor()},getElementFromSelection:function(){var e=this.editor.getSelection(),t=e.getSelectedElement()||e.getCommonAncestor().getAscendant("cms-plugin",!0);return t},getPluginWidget:function(e){return e?e.getAscendant("cms-plugin",!0)||e.findOne("cms-plugin"):null},setupDialog:function(){var t=this,i=function(){return{title:"",minWidth:200,minHeight:200,contents:[{elements:[{type:"html",html:'');a.appendTo(i.getParent())}return n.unselectable(),o.unselectable(),{element:e,parts:{dialog:e.getChild(0),title:n,close:o,tabs:i.getChild(2),contents:i.getChild([3,0,0,0]),footer:i.getChild([3,0,1,0])}}}function r(t,e,i){this.element=e,this.focusIndex=i,this.tabIndex=0,this.isFocusable=function(){return!e.getAttribute("disabled")&&e.isVisible()},this.focus=function(){t._.currentFocusIndex=this.focusIndex,this.element.focus()},e.on("keydown",function(t){t.data.getKeystroke()in{32:1,13:1}&&this.fire("click")}),e.on("focus",function(){this.fire("mouseover")}),e.on("blur",function(){this.fire("mouseout")})}function l(t){function e(){t.layout()}var i=CKEDITOR.document.getWindow();i.on("resize",e),t.on("hide",function(){i.removeListener("resize",e)})}function d(t,e){this._={dialog:t},CKEDITOR.tools.extend(this,e)}function u(t){function e(e){var i,l,d=t.getSize(),u=CKEDITOR.document.getWindow().getViewPaneSize(),c=e.originalEvent.screenX,h=e.originalEvent.screenY,g=c-n.x,f=h-n.y;n={x:c,y:h},o.x+=g,o.y+=f,i=o.x+r[3]u.width-d.width-a?u.width-d.width+("rtl"==s.lang.dir?0:r[1]):o.x,l=o.y+r[0]u.height-d.height-a?u.height-d.height+r[2]:o.y,t.move(i,l,1),e.preventDefault()}function i(){if(CMS.$(CKEDITOR.document.$).off("pointermove",e),CMS.$(CKEDITOR.document.$).off("pointerup",i),CKEDITOR.env.ie6Compat){var t=b.getChild(0).getFrameDocument();t.removeListener("mousemove",e),t.removeListener("mouseup",i)}}var n=null,o=null,s=t.getParentEditor(),a=s.config.dialog_magnetDistance,r=CKEDITOR.skin.margins||[0,0,0,0];"undefined"==typeof a&&(a=20),CMS.$(t.parts.title.$).on("pointerdown",function(s){if(n={x:s.originalEvent.screenX,y:s.originalEvent.screenY},CMS.$(CKEDITOR.document.$).on("pointermove",e),CMS.$(CKEDITOR.document.$).on("pointerup",i),o=t.getPosition(),CKEDITOR.env.ie6Compat){var a=b.getChild(0).getFrameDocument();a.on("mousemove",e),a.on("mouseup",i)}s.preventDefault()})}function c(t){function e(e){var i="rtl"==c.lang.dir,u=(e.originalEvent.screenX-l.x)*(i?-1:1),h=e.originalEvent.screenY-l.y,g=d.width,f=d.height,p=g+u*(t._.moved?1:2),_=f+h*(t._.moved?1:2),I=t._.element.getFirst(),m=i&&I.getComputedStyle("right"),v=t.getPosition();v.y+_>r.height&&(_=r.height-v.y),(i?m:v.x)+p>r.width&&(p=r.width-(i?m:v.x)),o!=CKEDITOR.DIALOG_RESIZE_WIDTH&&o!=CKEDITOR.DIALOG_RESIZE_BOTH||(g=Math.max(n.minWidth||0,p-s)),o!=CKEDITOR.DIALOG_RESIZE_HEIGHT&&o!=CKEDITOR.DIALOG_RESIZE_BOTH||(f=Math.max(n.minHeight||0,_-a)),t.resize(g,f),t._.moved||t.layout(),e.preventDefault()}function i(){if(CMS.$(CKEDITOR.document.$).off("pointermove",e),CMS.$(CKEDITOR.document.$).off("pointerup",i),u&&(u.remove(),u=null),CKEDITOR.env.ie6Compat){var t=b.getChild(0).getFrameDocument();t.removeListener("mouseup",i),t.removeListener("mousemove",e)}}var n=t.definition,o=n.resizable;if(o!=CKEDITOR.DIALOG_RESIZE_NONE){var s,a,r,l,d,u,c=t.getParentEditor(),h=CKEDITOR.tools.addFunction(function(n){d=t.getSize();var o=t.parts.contents,c=o.$.getElementsByTagName("iframe").length;if(c&&(CMS.$(".cke_dialog_resize_cover").remove(),u=CKEDITOR.dom.element.createFromHtml('
    '),o.append(u)),a=d.height-t.parts.contents.getSize("height",!(CKEDITOR.env.gecko||CKEDITOR.env.ie&&CKEDITOR.env.quirks)),s=d.width-t.parts.contents.getSize("width",1),l={x:n.screenX,y:n.screenY},r=CKEDITOR.document.getWindow().getViewPaneSize(),CMS.$(CKEDITOR.document.$).on("pointermove",e),CMS.$(CKEDITOR.document.$).on("pointerup",i),CKEDITOR.env.ie6Compat){var h=b.getChild(0).getFrameDocument();h.on("mousemove",e),h.on("mouseup",i)}n.preventDefault&&n.preventDefault()});t.on("load",function(){var e="";o==CKEDITOR.DIALOG_RESIZE_WIDTH?e=" cke_resizer_horizontal":o==CKEDITOR.DIALOG_RESIZE_HEIGHT&&(e=" cke_resizer_vertical");var i=CKEDITOR.dom.element.createFromHtml('
    '+("ltr"==c.lang.dir?"◢":"◣")+"
    ");t.parts.footer.append(i,1)}),c.on("destroy",function(){CKEDITOR.tools.removeFunction(h)})}}function h(t){t.data.preventDefault(1)}function g(t){var e=CKEDITOR.document.getWindow(),i=t.config,n=i.dialog_backgroundCoverColor||"white",o=i.dialog_backgroundCoverOpacity,s=i.baseFloatZIndex,a=CKEDITOR.tools.genKey(n,o,s),r=O[a];if(CMS.$(".cke_dialog_background_cover:not(.cms-ckeditor-dialog-background-cover)").remove(),r)r.show();else{O={};var l=['
    '];if(CKEDITOR.env.ie6Compat){var d="";l.push('')}l.push("
    "),r=CKEDITOR.dom.element.createFromHtml(l.join("")),r.setOpacity(void 0!==o?o:.5),r.on("keydown",h),r.on("keypress",h),r.on("keyup",h),r.appendTo(CKEDITOR.document.getBody()),O[a]=r}t.focusManager.add(r),b=r;var u=function(){var t=e.getViewPaneSize();r.setStyles({width:t.width+"px",height:t.height+"px"})},c=function(){var t=e.getScrollPosition(),i=CKEDITOR.dialog._.currentTop;if(r.setStyles({left:t.x+"px",top:t.y+"px"}),i)do{var n=i.getPosition();i.move(n.x,n.y)}while(i=i._.parentDialog)};if(D=u,e.on("resize",u),u(),CKEDITOR.env.mac&&CKEDITOR.env.webkit||r.focus(),CKEDITOR.env.ie6Compat){var g=function(){c(),arguments.callee.prevScrollHandler.apply(this,arguments)};e.$.setTimeout(function(){g.prevScrollHandler=window.onscroll||function(){},window.onscroll=g},0),c()}}function f(t){if(CMS.$(".cke_dialog_background_cover:not(.cms-ckeditor-dialog-background-cover)").remove(),b){t.focusManager.remove(b);var e=CKEDITOR.document.getWindow();b.hide(),e.removeListener("resize",D),CKEDITOR.env.ie6Compat&&e.$.setTimeout(function(){var t=window.onscroll&&window.onscroll.prevScrollHandler;window.onscroll=t||null},0),D=null}}function p(){for(var t in O)O[t].remove();O={}}var _=CKEDITOR.tools.cssLength,I='';CKEDITOR.dialog=function(t,n){function r(){var t=y._.focusList;t.sort(function(t,e){return t.tabIndex!=e.tabIndex?e.tabIndex-t.tabIndex:t.focusIndex-e.focusIndex});for(var e=t.length,i=0;i1;do{if(n+=t,o&&!y._.tabBarMode&&(n==e.length||n==-1))return y._.tabBarMode=!0,y._.tabs[y._.currentTabId][0].focus(),void(y._.currentFocusIndex=-1);if(n=(n+e.length)%e.length,n==i)break}while(t&&!e[n].isFocusable());e[n].focus(),"text"==e[n].type&&e[n].select()}}function d(n){if(y==CKEDITOR.dialog._.currentTop){var o,s=n.data.getKeystroke(),a="rtl"==t.lang.dir,r=[37,38,39,40];if(f=p=0,9==s||s==CKEDITOR.SHIFT+9){var d=s==CKEDITOR.SHIFT+9;l(d?-1:1),f=1}else if(s==CKEDITOR.ALT+121&&!y._.tabBarMode&&y.getPageCount()>1)y._.tabBarMode=!0,y._.tabs[y._.currentTabId][0].focus(),y._.currentFocusIndex=-1,f=1;else if(CKEDITOR.tools.indexOf(r,s)!=-1&&y._.tabBarMode){var u=[a?39:37,38],c=CKEDITOR.tools.indexOf(u,s)!=-1?e.call(y):i.call(y);y.selectPage(c),y._.tabs[c][0].focus(),f=1}else if(13!=s&&32!=s||!y._.tabBarMode)if(13==s){var g=n.data.getTarget();g.is("a","button","select","textarea")||g.is("input")&&"button"==g.$.type||(o=this.getButton("ok"),o&&CKEDITOR.tools.setTimeout(o.click,0,o),f=1),p=1}else{if(27!=s)return;o=this.getButton("cancel"),o?CKEDITOR.tools.setTimeout(o.click,0,o):this.fire("cancel",{hide:!0}).hide!==!1&&this.hide(),p=1}else this.selectPage(this._.currentTabId),this._.tabBarMode=!1,this._.currentFocusIndex=-1,l(1),f=1;h(n)}}function h(t){f?t.data.preventDefault(1):p&&t.data.stopPropagation()}var g,f,p,_=CKEDITOR.dialog._.dialogDefinitions[n],I=CKEDITOR.tools.clone(m),v=t.config.dialog_buttonsOrder||"OS",C=t.lang.dir,E={};("OS"==v&&CKEDITOR.env.mac||"rtl"==v&&"ltr"==C||"ltr"==v&&"rtl"==C)&&I.buttons.reverse(),_=CKEDITOR.tools.extend(_(t),I),_=CKEDITOR.tools.clone(_),_=new T(this,_);var D=a(t);this._={editor:t,element:D.element,name:n,contentSize:{width:0,height:0},size:{width:0,height:0},contents:{},buttons:{},accessKeyMap:{},tabs:{},tabIdList:[],currentTabId:null,currentTabIndex:null,pageCount:0,lastTab:null,tabBarMode:!1,focusList:[],currentFocusIndex:0,hasFocus:!1},this.parts=D.parts,CKEDITOR.tools.setTimeout(function(){t.fire("ariaWidget",this.parts.contents)},0,this);var b={position:CKEDITOR.env.ie6Compat?"absolute":"fixed",top:0,visibility:"hidden"};if(b["rtl"==C?"right":"left"]=0,this.parts.dialog.setStyles(b),CKEDITOR.event.call(this),this.definition=_=CKEDITOR.fire("dialogDefinition",{name:n,definition:_},t).definition,!("removeDialogTabs"in t._)&&t.config.removeDialogTabs){var O=t.config.removeDialogTabs.split(";");for(g=0;g1;if(t.config.dialog_startupFocusTab&&e)y._.tabBarMode=!0,y._.tabs[y._.currentTabId][0].focus(),y._.currentFocusIndex=-1;else if(!this._.hasFocus)if(this._.currentFocusIndex=e?-1:this._.focusList.length-1,_.onFocus){var i=_.onFocus.call(this);i&&i.focus()}else l(1)},this,null,4294967295),CKEDITOR.env.ie6Compat&&this.on("load",function(){var t=this.getElement(),e=t.getFirst();e.remove(),e.appendTo(t)},this),u(this),c(this),new CKEDITOR.dom.text(_.title,CKEDITOR.document).appendTo(this.parts.title),g=0;g<_.contents.length;g++){var w=_.contents[g];w&&this.addPage(w)}this.parts.tabs.on("click",function(t){var e=t.data.getTarget();if(e.hasClass("cke_dialog_tab")){var i=e.$.id;this.selectPage(i.substring(4,i.lastIndexOf("_"))),this._.tabBarMode&&(this._.tabBarMode=!1,this._.currentFocusIndex=-1,l(1)),t.data.preventDefault()}},this);var S=[],L=CKEDITOR.dialog._.uiElementBuilders.hbox.build(this,{type:"hbox",className:"cke_dialog_footer_buttons",widths:[],children:_.buttons},S).getChild();for(this.parts.footer.setHtml(S.join("")),g=0;g0?e:0)+"px"};d[o?"right":"left"]=(t>0?t:0)+"px",n.setStyles(d),i&&(this._.moved=1)}},getPosition:function(){return CKEDITOR.tools.extend({},this._.position)},show:function(){var t=this._.element,e=this.definition;if(t.getParent()&&t.getParent().equals(CKEDITOR.document.getBody())?t.setStyle("display","block"):t.appendTo(CKEDITOR.document.getBody()),this.resize(this._.contentSize&&this._.contentSize.width||e.width||e.minWidth,this._.contentSize&&this._.contentSize.height||e.height||e.minHeight),this.reset(),this.selectPage(this.definition.contents[0].id),null===CKEDITOR.dialog._.currentZIndex&&(CKEDITOR.dialog._.currentZIndex=this._.editor.config.baseFloatZIndex),this._.element.getFirst().setStyle("z-index",CKEDITOR.dialog._.currentZIndex+=10),null===CKEDITOR.dialog._.currentTop)CKEDITOR.dialog._.currentTop=this,this._.parentDialog=null,g(this._.editor);else{this._.parentDialog=CKEDITOR.dialog._.currentTop;var i=this._.parentDialog.getElement().getFirst();i.$.style.zIndex-=Math.floor(this._.editor.config.baseFloatZIndex/2),CKEDITOR.dialog._.currentTop=this}t.on("keydown",R),t.on("keyup",y),this._.hasFocus=!1;for(var n in e.contents)if(e.contents[n]){var o=e.contents[n],s=this._.tabs[o.id],a=o.requiredContent,r=0;if(s){for(var d in this._.contents[o.id]){var u=this._.contents[o.id][d];"hbox"!=u.type&&"vbox"!=u.type&&u.getInputElement()&&(u.requiredContent&&!this._.editor.activeFilter.check(u.requiredContent)?u.disable():(u.enable(),r++))}!r||a&&!this._.editor.activeFilter.check(a)?s[0].addClass("cke_dialog_tab_disabled"):s[0].removeClass("cke_dialog_tab_disabled")}}CKEDITOR.tools.setTimeout(function(){this.layout(),l(this),this.parts.dialog.setStyle("visibility",""),this.fireOnce("load",{}),CKEDITOR.ui.fire("ready",this),this.fire("show",{}),this._.editor.fire("dialogShow",this),this._.parentDialog||this._.editor.focusManager.lock(),this.foreach(function(t){t.setInitValue&&t.setInitValue()})},100,this)},layout:function(){var t=this.parts.dialog,e=this.getSize(),i=CKEDITOR.document.getWindow(),n=i.getViewPaneSize(),o=(n.width-e.width)/2,s=(n.height-e.height)/2;CKEDITOR.env.ie6Compat||(e.height+(s>0?s:0)>n.height||e.width+(o>0?o:0)>n.width?t.setStyle("position","absolute"):t.setStyle("position","fixed")),this.move(this._.moved?this._.position.x:o,this._.moved?this._.position.y:s)},foreach:function(t){for(var e in this._.contents)for(var i in this._.contents[e])t.call(this,this._.contents[e][i]);return this},reset:function(){var t=function(t){t.reset&&t.reset(1)};return function(){return this.foreach(t),this}}(),setupContent:function(){var t=arguments;this.foreach(function(e){e.setup&&e.setup.apply(e,t)})},commitContent:function(){var t=arguments;this.foreach(function(e){CKEDITOR.env.ie&&this._.currentFocusIndex==e.focusIndex&&e.getInputElement().$.blur(),e.commit&&e.commit.apply(e,t)})},hide:function(){if(this.parts.dialog.isVisible()){this.fire("hide",{}),this._.editor.fire("dialogHide",this),this.selectPage(this._.tabIdList[0]);var t=this._.element;for(t.setStyle("display","none"),this.parts.dialog.setStyle("visibility","hidden"),k(this);CKEDITOR.dialog._.currentTop!=this;)CKEDITOR.dialog._.currentTop.hide();if(this._.parentDialog){var e=this._.parentDialog.getElement().getFirst();e.setStyle("z-index",parseInt(e.$.style.zIndex,10)+Math.floor(this._.editor.config.baseFloatZIndex/2))}else f(this._.editor);if(CKEDITOR.dialog._.currentTop=this._.parentDialog,this._.parentDialog)CKEDITOR.dialog._.currentZIndex-=10;else{CKEDITOR.dialog._.currentZIndex=null,t.removeListener("keydown",R),t.removeListener("keyup",y);var i=this._.editor;i.focus(),setTimeout(function(){i.focusManager.unlock(),CKEDITOR.env.iOS&&i.window.focus()},0)}delete this._.parentDialog,this.foreach(function(t){t.resetInitValue&&t.resetInitValue()}),this.setState(CKEDITOR.DIALOG_STATE_IDLE)}},addPage:function(t){if(!t.requiredContent||this._.editor.filter.check(t.requiredContent)){for(var e,i=[],n=t.label?' title="'+CKEDITOR.tools.htmlEncode(t.label)+'"':"",o=CKEDITOR.dialog._.uiElementBuilders.vbox.build(this,{type:"vbox",className:"cke_dialog_page_contents",children:t.elements,expand:!!t.expand,padding:t.padding,style:t.style||"width: 100%;"},i),s=this._.contents[t.id]={},a=o.getChild(),r=0;e=a.shift();)e.notAllowed||"hbox"==e.type||"vbox"==e.type||r++,s[e.id]=e,"function"==typeof e.getChild&&a.push.apply(a,e.getChild());r||(t.hidden=!0);var l=CKEDITOR.dom.element.createFromHtml(i.join(""));l.setAttribute("role","tabpanel");var d=CKEDITOR.env,u="cke_"+t.id+"_"+CKEDITOR.tools.getNextNumber(),c=CKEDITOR.dom.element.createFromHtml(['0?" cke_last":"cke_first",n,t.hidden?' style="display:none"':"",' id="',u,'"',d.gecko&&!d.hc?"":' href="javascript:void(0)"',' tabIndex="-1"',' hidefocus="true"',' role="tab">',t.label,""].join(""));l.setAttribute("aria-labelledby",u),this._.tabs[t.id]=[c,l],this._.tabIdList.push(t.id),!t.hidden&&this._.pageCount++,this._.lastTab=c,this.updateStyle(),l.setAttribute("name",t.id),l.appendTo(this.parts.contents),c.unselectable(),this.parts.tabs.append(c),t.accessKey&&(x(this,this,"CTRL+"+t.accessKey,S,w),this._.accessKeyMap["CTRL+"+t.accessKey]=t.id)}},selectPage:function(t){if(this._.currentTabId!=t&&!this._.tabs[t][0].hasClass("cke_dialog_tab_disabled")&&this.fire("selectPage",{page:t,currentPage:this._.currentTabId})!==!1){for(var e in this._.tabs){var i=this._.tabs[e][0],o=this._.tabs[e][1];e!=t&&(i.removeClass("cke_dialog_tab_selected"),o.hide()),o.setAttribute("aria-hidden",e!=t)}var s=this._.tabs[t];s[0].addClass("cke_dialog_tab_selected"),CKEDITOR.env.ie6Compat||CKEDITOR.env.ie7Compat?(n(s[1]),s[1].show(),setTimeout(function(){n(s[1],1)},0)):s[1].show(),this._.currentTabId=t,this._.currentTabIndex=CKEDITOR.tools.indexOf(this._.tabIdList,t)}},updateStyle:function(){this.parts.dialog[(1===this._.pageCount?"add":"remove")+"Class"]("cke_single_page")},hidePage:function(t){var i=this._.tabs[t]&&this._.tabs[t][0];i&&1!=this._.pageCount&&i.isVisible()&&(t==this._.currentTabId&&this.selectPage(e.call(this)),i.hide(),this._.pageCount--,this.updateStyle())},showPage:function(t){var e=this._.tabs[t]&&this._.tabs[t][0];e&&(e.show(),this._.pageCount++,this.updateStyle())},getElement:function(){return this._.element},getName:function(){return this._.name},getContentElement:function(t,e){var i=this._.contents[t];return i&&i[e]},getValueOf:function(t,e){return this.getContentElement(t,e).getValue()},setValueOf:function(t,e,i){return this.getContentElement(t,e).setValue(i)},getButton:function(t){return this._.buttons[t]},click:function(t){return this._.buttons[t].click()},disableButton:function(t){return this._.buttons[t].disable()},enableButton:function(t){return this._.buttons[t].enable()},getPageCount:function(){return this._.pageCount},getParentEditor:function(){return this._.editor},getSelectedElement:function(){return this.getParentEditor().getSelection().getSelectedElement()},addFocusable:function(t,e){if("undefined"==typeof e)e=this._.focusList.length,this._.focusList.push(new r(this,t,e));else{this._.focusList.splice(e,0,new r(this,t,e));for(var i=e+1;i=0;n--)i[n].dialog!=t&&i[n].uiElement!=t||i.splice(n,1);0===i.length&&delete K[e]}},w=function(t,e){t._.accessKeyMap[e]&&t.selectPage(t._.accessKeyMap[e])},S=function(){};!function(){CKEDITOR.ui.dialog={uiElement:function(t,e,i,n,o,s,a){if(!(arguments.length<4)){var r,l=(n.call?n(e):n)||"div",d=["<",l," "],u=(o&&o.call?o(e):o)||{},c=(s&&s.call?s(e):s)||{},h=(a&&a.call?a.call(this,t,e):a)||"",g=this.domId=c.id||CKEDITOR.tools.getNextId()+"_uiElement";e.requiredContent&&!t.getParentEditor().filter.check(e.requiredContent)&&(u.display="none",this.notAllowed=!0),c.id=g;var f={};e.type&&(f["cke_dialog_ui_"+e.type]=1),e.className&&(f[e.className]=1),e.disabled&&(f.cke_disabled=1);var p=c.class&&c.class.split?c.class.split(" "):[];for(r=0;r=0;r--)""===I[r]&&I.splice(r,1);I.length>0&&(c.style=(c.style?c.style+"; ":"")+I.join("; "));for(r in c)d.push(r+'="'+CKEDITOR.tools.htmlEncode(c[r])+'" ');d.push(">",h,""),i.push(d.join("")),(this._||(this._={})).dialog=t,"boolean"==typeof e.isChanged&&(this.isChanged=function(){return e.isChanged}),"function"==typeof e.isChanged&&(this.isChanged=e.isChanged),"function"==typeof e.setValue&&(this.setValue=CKEDITOR.tools.override(this.setValue,function(t){return function(i){t.call(this,e.setValue.call(this,i))}})),"function"==typeof e.getValue&&(this.getValue=CKEDITOR.tools.override(this.getValue,function(t){return function(){return e.getValue.call(this,t.call(this))}})),CKEDITOR.event.implementOn(this),this.registerEvents(e),this.accessKeyUp&&this.accessKeyDown&&e.accessKey&&x(this,t,"CTRL+"+e.accessKey);var v=this;t.on("load",function(){var e=v.getInputElement();if(e){var i=v.type in{checkbox:1,ratio:1}&&CKEDITOR.env.ie&&CKEDITOR.env.version<8?"cke_dialog_ui_focused":"";e.on("focus",function(){t._.tabBarMode=!1,t._.hasFocus=!0,v.fire("focus"),i&&this.addClass(i)}),e.on("blur",function(){v.fire("blur"),i&&this.removeClass(i)})}}),CKEDITOR.tools.extend(this,e),this.keyboardFocusable&&(this.tabIndex=e.tabIndex||0,this.focusIndex=t._.focusList.push(this)-1,this.on("focus",function(){t._.currentFocusIndex=v.focusIndex}))}},hbox:function(t,e,i,n,o){if(!(arguments.length<4)){this._||(this._={});var s,a=this._.children=e,r=o&&o.widths||null,l=o&&o.height||null,d={},u=function(){var t=[''];for(s=0;s0&&t.push('style="'+n.join("; ")+'" '),t.push(">",i[s],"")}return t.push(""),t.join("")},c={role:"presentation"};o&&o.align&&(c.align=o.align),CKEDITOR.ui.dialog.uiElement.call(this,t,o||{type:"hbox"},n,"table",d,c,u)}},vbox:function(t,e,i,n,o){if(!(arguments.length<3)){this._||(this._={});var s=this._.children=e,a=o&&o.width||null,r=o&&o.heights||null,l=function(){var e=['");for(var n=0;n")}return e.push("
    0&&e.push('style="',l.join("; "),'" '),e.push(' class="cke_dialog_ui_vbox_child">',i[n],"
    "),e.join("")};CKEDITOR.ui.dialog.uiElement.call(this,t,o||{type:"vbox"},n,"div",null,{role:"presentation"},l)}}}}(),CKEDITOR.ui.dialog.uiElement.prototype={getElement:function(){return CKEDITOR.document.getById(this.domId)},getInputElement:function(){ -return this.getElement()},getDialog:function(){return this._.dialog},setValue:function(t,e){return this.getInputElement().setValue(t),!e&&this.fire("change",{value:t}),this},getValue:function(){return this.getInputElement().getValue()},isChanged:function(){return!1},selectParentTab:function(){for(var t,e=this.getInputElement(),i=e;(i=i.getParent())&&i.$.className.search("cke_dialog_page_contents")==-1;);return i?(t=i.getAttribute("name"),this._.dialog._.currentTabId!=t&&this._.dialog.selectPage(t),this):this},focus:function(){return this.selectParentTab().getInputElement().focus(),this},registerEvents:function(t){var e,i=/^on([A-Z]\w+)/,n=function(t,e,i,n){e.on("load",function(){t.getInputElement().on(i,n,t)})};for(var o in t)(e=o.match(i))&&(this.eventProcessors[o]?this.eventProcessors[o].call(this,this._.dialog,t[o]):n(this,this._.dialog,e[1].toLowerCase(),t[o]));return this},eventProcessors:{onLoad:function(t,e){t.on("load",e,this)},onShow:function(t,e){t.on("show",e,this)},onHide:function(t,e){t.on("hide",e,this)}},accessKeyDown:function(){this.focus()},accessKeyUp:function(){},disable:function(){var t=this.getElement(),e=this.getInputElement();e.setAttribute("disabled","true"),t.addClass("cke_disabled")},enable:function(){var t=this.getElement(),e=this.getInputElement();e.removeAttribute("disabled"),t.removeClass("cke_disabled")},isEnabled:function(){return!this.getElement().hasClass("cke_disabled")},isVisible:function(){return this.getInputElement().isVisible()},isFocusable:function(){return!(!this.isEnabled()||!this.isVisible())}},CKEDITOR.ui.dialog.hbox.prototype=CKEDITOR.tools.extend(new CKEDITOR.ui.dialog.uiElement,{getChild:function(t){return arguments.length<1?this._.children.concat():(t.splice||(t=[t]),t.length<2?this._.children[t[0]]:this._.children[t[0]]&&this._.children[t[0]].getChild?this._.children[t[0]].getChild(t.slice(1,t.length)):null)}},!0),CKEDITOR.ui.dialog.vbox.prototype=new CKEDITOR.ui.dialog.hbox,function(){var t={build:function(t,e,i){for(var n,o=e.children,s=[],a=[],r=0;rd.width&&(n.resize_minWidth=d.width),n.resize_minHeight>d.height&&(n.resize_minHeight=d.height),CMS.$(CKEDITOR.document.$).on("pointermove",i),CMS.$(CKEDITOR.document.$).on("pointerup",t),e.document&&(CMS.$(e.document.$).on("pointermove",i),CMS.$(e.document.$).on("pointerup",t)),r.preventDefault&&r.preventDefault()});CMS.$(CKEDITOR.document.$).find("html").attr("data-touch-action","none"),e.on("destroy",function(){CKEDITOR.tools.removeFunction(c)}),e.on("uiSpace",function(i){if("bottom"==i.data.space){var t="";m&&!h&&(t=" cke_resizer_horizontal"),!m&&h&&(t=" cke_resizer_vertical");var n=''+("ltr"==o?"◢":"◣")+"";"ltr"==o&&"ltr"==t?i.data.html+=n:i.data.html=n+i.data.html}},e,null,100),e.on("maximize",function(i){e.ui.space("resizer")[i.data==CKEDITOR.TRISTATE_ON?"hide":"show"]()})}}})}(CMS.$); -!function(e){function t(e){var t=(e.match(/<\s*([^>\s]+)[\s\S]*?>/)||[0,!1]).splice(1),i=t.some(function(e){return e&&CKEDITOR.dtd.$block[e]}),n="span";return i&&(n="div"),n}function i(t,i){t.each(function(t,n){var s,l=e(n);s=e("<"+i+">"),e.each(n.attributes,function(e,t){s.attr(t.nodeName,t.nodeValue)}),s.html(l.html()),l.replaceWith(s)})}CKEDITOR&&CKEDITOR.plugins&&CKEDITOR.plugins.registered&&CKEDITOR.plugins.registered.cmsplugins||CKEDITOR.plugins.add("cmsplugins",{icons:"cmsplugins",init:function(t){var i=this;if(this.options=CMS.CKEditor.options.settings,this.editor=t,this.child_plugins=[],this.setupCancelCleanupCallback(this.options),void 0===this.options||void 0===this.options.plugins)return!1;this.setupDialog(),this.editor.ui.add("cmsplugins",CKEDITOR.UI_PANELBUTTON,{toolbar:"cms,0",label:this.options.lang.toolbar,title:this.options.lang.toolbar,className:"cke_panelbutton__cmsplugins",modes:{wysiwyg:1},editorFocus:0,panel:{css:[CKEDITOR.skin.getPath("editor")].concat(i.editor.config.contentsCss),attributes:{role:"cmsplugins","aria-label":this.options.lang.aria}},onBlock:function(t,n){n.element.setHtml(i.editor.plugins.cmsplugins.setupDropdown());var s=e(n.element.$).find(".cke_panel_listItem a");s.bind("click",function(n){n.preventDefault(),i.addPlugin(e(this),t)})}}),this.editor.contextMenu&&this.setupContextMenu(),this.editor.addCommand("cmspluginsEdit",{exec:function(){var e=i.getElementFromSelection(),t=i.getPluginWidget(e);t&&i.editPlugin(t)}});var n=function(t){var n;if("touchend"===t.type||"click"===t.type){var s=e(t.currentTarget).closest("cms-plugin")[0];n=new CKEDITOR.dom.element(s).getParent(),t.data=t.data||{},i.editor.getSelection().fake(n)}i.editor.execCommand("cmspluginsEdit")};this.editor.on("doubleclick",n),this.editor.on("instanceReady",function(){CMS.$("cms-plugin",CMS.$("iframe.cke_wysiwyg_frame")[0].contentWindow.document.documentElement).on("click touchend",n)}),this.setupDataProcessor()},getElementFromSelection:function(){var e=this.editor.getSelection(),t=e.getSelectedElement()||e.getCommonAncestor().getAscendant("cms-plugin",!0);return t},getPluginWidget:function(e){return e?e.getAscendant("cms-plugin",!0)||e.findOne("cms-plugin"):null},setupDialog:function(){var t=this,i=function(){return{title:"",minWidth:200,minHeight:200,contents:[{elements:[{type:"html",html:'