diff --git a/LICENCE.txt b/LICENCE.txt old mode 100644 new mode 100755 diff --git a/README.markdown b/README.markdown old mode 100644 new mode 100755 index 2d5cca4..94c9b43 --- a/README.markdown +++ b/README.markdown @@ -1,13 +1,67 @@ -# CKEditor for Symphony CMS (EXPERIMENTAL) - -- Version: 0.71 beta -- Date: Tuesday, 26 June 2010 -- Author: Tony Arnold, tony@tonyarnold.com -- Repository: -- Requirements: Symphony CMS 2.0.8 +# CKEditor for Symphony CMS ## Introduction -This extension provides [CKEditor](http://ckeditor.com/) as text-formatter for Symphony CMS. For further information about the editor please visit [www.ckeditor.com](http://ckeditor.com/). +This extension provides [CKEditor](http://ckeditor.com/) as text-formatter for Symphony CMS. It also has an integrated file browser which uses Symphony sections to get it's files from. +For further information about the editor please visit [www.ckeditor.com](http://ckeditor.com/). + +It is based upon code found in [Nils Hörrmann's WYMEditor](http://github.com/nilshoerrmann/wymeditor). + +## Contributors + +Significant work and bug fixes have been contributed by the following users: + + * Twisted Interactive - contributed major clean-ups and a new Symphony file browser that is compatible with CKEditor; + * Rob Stanford - contributed bug fixes. + +For full details, please see the Github commit log - . + +## Special notes + +The version of CKEditor included with this Symphony extension is stripped down to the bare essentials. This means: + + * Text formatting is limited to the following functions: + * Paragraph Format + * Bold + * Italic + * Strike-through + * Subscript / Superscript + * Ordered list / Unordered list + * Indent / Outdent + * Block quote + * Hyperlinks + * Horizontal rule + * View source + * Full screen + * *Most of CKEditor's plug-ins have been removed*: if you wish to add more plug-ins, please download the original [CKEditor](http://ckeditor.com) package and extract the plugins you'd like to include. + * *All languages other than US English are removed*: If you wish to make use of additional languages, please download the original version of [CKEditor](http://ckeditor.com) and extract the languages you'd like to include. + +## Built-in file browser + +This Symphony extension comes with a built-in file browser that is compatible with CKEditor. This file browser uses Symphony sections to store and retrieve uploaded files. It works as follows: + + * Make sure you have created at least one section for your uploaded files with a 'File Upload' field attached; + * Go to Symphony's System Preferences and make the CKEditor file browser available to one or more of your sections; + * Once you've enabled the file browser for at least one of your sections, you make use of the 'Browse Server' button in CKEditor to select existing files from within your section and add them to the entry you are editing. You can also upload new files using the file browser on the fly! + +## Link templates + +As of version 1.3, it's possible to create link templates for CKEditor. This works as following: + +Say, you got a page called 'News', and a section called 'News articles' in which you store all your news articles. This means +your news articles probably got URL's like: + + * /news/detail/25/my-new-site/ + * /news/detail/31/grand-opening/ + * /news/detail/40/visit-of-the-queen/ + +You might want to link to these pages from other pages, but you don't want to copy/paste those links. You just want them to +be there in your dropdown of Symphony Pages when you select a link. This is where link templates come in: You can create +a link template like: `/news/detail/{$id}/{$title}/`, choose a section the generate the list from, and select the page +from where to show these links. You can set these in the preferences page of your Symphony installation. + +## Styles -It is based upon code found in [Nils Hörrmann's WYMEditor](http://github.com/nilshoerrmann/wymeditor). \ No newline at end of file +As of version 1.3.3 you can add styles to your content. And not as in: you can add a color and stuff, but you can add +style in the form of a class to your element, so you can maintain the styling of your frontend with a CSS file instead of +inline CSS. diff --git a/assets/filebrowser.css b/assets/filebrowser.css new file mode 100755 index 0000000..4de2e20 --- /dev/null +++ b/assets/filebrowser.css @@ -0,0 +1,34 @@ +form { top: 0; left: 0; margin: 0; padding: 0; } + +div.left { width: 23%; float: left; background: #eee; padding: 1%; } +div.right { width: 73%; float: right; padding: 1%; } + +ul { list-style-type: none; } +li { border-bottom: 1px solid #ccc; } +li a { display: block; padding: 5px; text-decoration: none; color: #333; outline: none; } +li a.active { background: #aaa; color: #fff; } +li a:hover { color: #fff; background: #333; } + +/* +table { border-collapse: collapse; width: 100%; margin-bottom: 1em; margin-top: 15px; } +td, th { border: 1px solid #eee; text-align: left; vertical-align: top; padding: 5px !important; } +td a { color: #333; } +*/ + +tr.hover td { background: #eee; cursor: pointer; } + +a.button { font-size: 1em; } +a.create { float: right; } + +#thumb { width: 80px; height: 60px; padding: 5px; background: #fff; position: absolute; display: none; + -moz-box-shadow: 0 0 20px rgba(0, 0, 0, .3); + -webkit-box-shadow: 0 0 20px rgba(0, 0, 0, .3); + box-shadow: 0 0 20px rgba(0, 0, 0, .3); +} + +input[type=button], input[type=submit] { padding: 5px; } + +div.items { float: left; clear: both; border-top: 1px solid #ccc; width: 100%; margin-top: 10px; } +div.items div { float: left; width: 100px; height: 120px; overflow: hidden; margin-top: 10px; border: 1px solid #ccc; padding: 10px; margin-right: 10px; font-size: 10px; text-align: center; } +div.items img.icon { margin: 18px; } +div.items div a { text-decoration: none; color: #333; } \ No newline at end of file diff --git a/assets/filebrowser.js b/assets/filebrowser.js new file mode 100755 index 0000000..d0508f0 --- /dev/null +++ b/assets/filebrowser.js @@ -0,0 +1,98 @@ +var funcNum; +var urlNew; + +if (typeof Symphony == "undefined") { + var Symphony = {}; +} +if (typeof Symphony.WEBSITE == "undefined") { + Symphony.WEBSITE = window.location.toString().match(/^(.+?)\/symphony/)[1]; +} +if (typeof Symphony.ADMIN == "undefined") { + Symphony.ADMIN = Symphony.WEBSITE + "/symphony"; +} + +$(function(){ + var $ = jQuery; + + funcNum = getUrlParam('CKEditorFuncNum'); + + $("div.left a").click(function(){ + $("div.left a").removeClass("active"); + $(this).addClass("active"); + loadRightPanel(Symphony.ADMIN + "/extension/ckeditor/filebrowserajax/?id=" + $(this).attr("id")); + return false; + }); + + // Default: activate the first category: + $("div.left a:first").click(); +}); + +function loadRightPanel(url) +{ + var $ = jQuery; + + $("div.right").load(url/*+ " form>*"*/, function(){ + // some magic mumbo jumbo: + // Hover on the table rows: + $("div.right tr").hover(function(){ + $(this).addClass("hover"); + }, function(){ + $(this).removeClass("hover"); + }).click(function(){ + // If the row is clicked, the first anchor is selected. This is because an entry could also have multiple files + $("a:first", this).click(); + }); + // Click on an anchor + $("a", $("div.items")).click(function(){ + // Send URL to CKEditor: + window.opener.CKEDITOR.tools.callFunction(funcNum, $(this).attr("href")); + window.close(); + return false; + }); + // Create new-functionality: + $("a.create").click(function(){ + urlNew = $(this).attr("href"); + $.get(urlNew, function(data){ + buildForm(data); + }); + return false; + }); + }); +} + +function buildForm(data) +{ + var $ = jQuery; + + $("div.right").html('
'); + $("div.field", data).each(function(){ + $("div.right form").append('
' + $(this).html() + '
'); + }); + $("div.right form").append(''); + $("div.right form").append(''); + $("input[name='cancel']").click(function(){ + loadRightPanel(Symphony.ADMIN + "/extension/ckeditor/filebrowserajax/?id=" + $("div.left a.active").attr("id")); + }); + // Ajax form: + $("div.right form").ajaxForm({ + success: function(responseText, statusText, xhr) + { + if($("p.error", responseText).length > 0) + { + // Reload the form: + buildForm(responseText); + } else { + // No error found! Content stored! + loadRightPanel(Symphony.ADMIN + "/extension/ckeditor/filebrowserajax/?id=" + $("div.left a.active").attr("id")); + } + } + }); +} + +// Helper function to get parameters from the query string. +function getUrlParam(paramName) +{ + var reParam = new RegExp('(?:[\?&]|&)' + paramName + '=([^&]+)', 'i') ; + var match = window.location.search.match(reParam) ; + return (match && match.length > 1) ? match[1] : '' ; +} \ No newline at end of file diff --git a/assets/images/doc.png b/assets/images/doc.png new file mode 100755 index 0000000..2436b01 Binary files /dev/null and b/assets/images/doc.png differ diff --git a/assets/images/font.png b/assets/images/font.png new file mode 100755 index 0000000..35cde64 Binary files /dev/null and b/assets/images/font.png differ diff --git a/assets/images/html.png b/assets/images/html.png new file mode 100755 index 0000000..bfc4662 Binary files /dev/null and b/assets/images/html.png differ diff --git a/assets/images/image.png b/assets/images/image.png new file mode 100755 index 0000000..1c3657b Binary files /dev/null and b/assets/images/image.png differ diff --git a/assets/images/pdf.png b/assets/images/pdf.png new file mode 100755 index 0000000..2a968ec Binary files /dev/null and b/assets/images/pdf.png differ diff --git a/assets/images/presentation.png b/assets/images/presentation.png new file mode 100755 index 0000000..da5dbc7 Binary files /dev/null and b/assets/images/presentation.png differ diff --git a/assets/images/sound.png b/assets/images/sound.png new file mode 100755 index 0000000..accfcad Binary files /dev/null and b/assets/images/sound.png differ diff --git a/assets/images/spreadsheet.png b/assets/images/spreadsheet.png new file mode 100755 index 0000000..a5c46b8 Binary files /dev/null and b/assets/images/spreadsheet.png differ diff --git a/assets/images/swf.png b/assets/images/swf.png new file mode 100755 index 0000000..f47037f Binary files /dev/null and b/assets/images/swf.png differ diff --git a/assets/images/txt.png b/assets/images/txt.png new file mode 100755 index 0000000..a056da9 Binary files /dev/null and b/assets/images/txt.png differ diff --git a/assets/images/unknown.png b/assets/images/unknown.png new file mode 100755 index 0000000..35df7f4 Binary files /dev/null and b/assets/images/unknown.png differ diff --git a/assets/images/video.png b/assets/images/video.png new file mode 100755 index 0000000..c5b1339 Binary files /dev/null and b/assets/images/video.png differ diff --git a/assets/images/zip.png b/assets/images/zip.png new file mode 100755 index 0000000..ff81858 Binary files /dev/null and b/assets/images/zip.png differ diff --git a/assets/jquery.ba-serializeobject.min.js b/assets/jquery.ba-serializeobject.min.js new file mode 100755 index 0000000..0163077 --- /dev/null +++ b/assets/jquery.ba-serializeobject.min.js @@ -0,0 +1,9 @@ +/* + * jQuery serializeObject - v0.2 - 1/20/2010 + * http://benalman.com/projects/jquery-misc-plugins/ + * + * Copyright (c) 2010 "Cowboy" Ben Alman + * Dual licensed under the MIT and GPL licenses. + * http://benalman.com/about/license/ + */ +(function($,a){$.fn.serializeObject=function(){var b={};$.each(this.serializeArray(),function(d,e){var f=e.name,c=e.value;b[f]=b[f]===a?c:$.isArray(b[f])?b[f].concat(c):[b[f],c]});return b}})(jQuery); \ No newline at end of file diff --git a/assets/jquery.form.js b/assets/jquery.form.js new file mode 100755 index 0000000..9e13b5d --- /dev/null +++ b/assets/jquery.form.js @@ -0,0 +1,1076 @@ +/*! + * jQuery Form Plugin + * version: 3.09 (16-APR-2012) + * @requires jQuery v1.3.2 or later + * + * Examples and documentation at: http://malsup.com/jquery/form/ + * Project repository: https://github.com/malsup/form + * Dual licensed under the MIT and GPL licenses: + * http://malsup.github.com/mit-license.txt + * http://malsup.github.com/gpl-license-v2.txt + */ +/*global ActiveXObject alert */ +;(function($) { +"use strict"; + +/* + Usage Note: + ----------- + Do not use both ajaxSubmit and ajaxForm on the same form. These + functions are mutually exclusive. Use ajaxSubmit if you want + to bind your own submit handler to the form. For example, + + $(document).ready(function() { + $('#myForm').on('submit', function(e) { + e.preventDefault(); // <-- important + $(this).ajaxSubmit({ + target: '#output' + }); + }); + }); + + Use ajaxForm when you want the plugin to manage all the event binding + for you. For example, + + $(document).ready(function() { + $('#myForm').ajaxForm({ + target: '#output' + }); + }); + + You can also use ajaxForm with delegation (requires jQuery v1.7+), so the + form does not have to exist when you invoke ajaxForm: + + $('#myForm').ajaxForm({ + delegation: true, + target: '#output' + }); + + When using ajaxForm, the ajaxSubmit function will be invoked for you + at the appropriate time. +*/ + +/** + * Feature detection + */ +var feature = {}; +feature.fileapi = $("").get(0).files !== undefined; +feature.formdata = window.FormData !== undefined; + +/** + * ajaxSubmit() provides a mechanism for immediately submitting + * an HTML form using AJAX. + */ +$.fn.ajaxSubmit = function(options) { + /*jshint scripturl:true */ + + // fast fail if nothing selected (http://dev.jquery.com/ticket/2752) + if (!this.length) { + log('ajaxSubmit: skipping submit process - no element selected'); + return this; + } + + var method, action, url, $form = this; + + if (typeof options == 'function') { + options = { success: options }; + } + + method = this.attr('method'); + action = this.attr('action'); + url = (typeof action === 'string') ? $.trim(action) : ''; + url = url || window.location.href || ''; + if (url) { + // clean url (don't include hash vaue) + url = (url.match(/^([^#]+)/)||[])[1]; + } + + options = $.extend(true, { + url: url, + success: $.ajaxSettings.success, + type: method || 'GET', + iframeSrc: /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank' + }, options); + + // hook for manipulating the form data before it is extracted; + // convenient for use with rich editors like tinyMCE or FCKEditor + var veto = {}; + this.trigger('form-pre-serialize', [this, options, veto]); + if (veto.veto) { + log('ajaxSubmit: submit vetoed via form-pre-serialize trigger'); + return this; + } + + // provide opportunity to alter form data before it is serialized + if (options.beforeSerialize && options.beforeSerialize(this, options) === false) { + log('ajaxSubmit: submit aborted via beforeSerialize callback'); + return this; + } + + var traditional = options.traditional; + if ( traditional === undefined ) { + traditional = $.ajaxSettings.traditional; + } + + var elements = []; + var qx, a = this.formToArray(options.semantic, elements); + if (options.data) { + options.extraData = options.data; + qx = $.param(options.data, traditional); + } + + // give pre-submit callback an opportunity to abort the submit + if (options.beforeSubmit && options.beforeSubmit(a, this, options) === false) { + log('ajaxSubmit: submit aborted via beforeSubmit callback'); + return this; + } + + // fire vetoable 'validate' event + this.trigger('form-submit-validate', [a, this, options, veto]); + if (veto.veto) { + log('ajaxSubmit: submit vetoed via form-submit-validate trigger'); + return this; + } + + var q = $.param(a, traditional); + if (qx) { + q = ( q ? (q + '&' + qx) : qx ); + } + if (options.type.toUpperCase() == 'GET') { + options.url += (options.url.indexOf('?') >= 0 ? '&' : '?') + q; + options.data = null; // data is null for 'get' + } + else { + options.data = q; // data is the query string for 'post' + } + + var callbacks = []; + if (options.resetForm) { + callbacks.push(function() { $form.resetForm(); }); + } + if (options.clearForm) { + callbacks.push(function() { $form.clearForm(options.includeHidden); }); + } + + // perform a load on the target only if dataType is not provided + if (!options.dataType && options.target) { + var oldSuccess = options.success || function(){}; + callbacks.push(function(data) { + var fn = options.replaceTarget ? 'replaceWith' : 'html'; + $(options.target)[fn](data).each(oldSuccess, arguments); + }); + } + else if (options.success) { + callbacks.push(options.success); + } + + options.success = function(data, status, xhr) { // jQuery 1.4+ passes xhr as 3rd arg + var context = options.context || options; // jQuery 1.4+ supports scope context + for (var i=0, max=callbacks.length; i < max; i++) { + callbacks[i].apply(context, [data, status, xhr || $form, $form]); + } + }; + + // are there files to upload? + var fileInputs = $('input:file:enabled[value]', this); // [value] (issue #113) + var hasFileInputs = fileInputs.length > 0; + var mp = 'multipart/form-data'; + var multipart = ($form.attr('enctype') == mp || $form.attr('encoding') == mp); + + var fileAPI = feature.fileapi && feature.formdata; + log("fileAPI :" + fileAPI); + var shouldUseFrame = (hasFileInputs || multipart) && !fileAPI; + + // options.iframe allows user to force iframe mode + // 06-NOV-09: now defaulting to iframe mode if file input is detected + if (options.iframe !== false && (options.iframe || shouldUseFrame)) { + // hack to fix Safari hang (thanks to Tim Molendijk for this) + // see: http://groups.google.com/group/jquery-dev/browse_thread/thread/36395b7ab510dd5d + if (options.closeKeepAlive) { + $.get(options.closeKeepAlive, function() { + fileUploadIframe(a); + }); + } + else { + fileUploadIframe(a); + } + } + else if ((hasFileInputs || multipart) && fileAPI) { + fileUploadXhr(a); + } + else { + $.ajax(options); + } + + // clear element array + for (var k=0; k < elements.length; k++) + elements[k] = null; + + // fire 'notify' event + this.trigger('form-submit-notify', [this, options]); + return this; + + // XMLHttpRequest Level 2 file uploads (big hat tip to francois2metz) + function fileUploadXhr(a) { + var formdata = new FormData(); + + for (var i=0; i < a.length; i++) { + formdata.append(a[i].name, a[i].value); + } + + if (options.extraData) { + for (var p in options.extraData) + if (options.extraData.hasOwnProperty(p)) + formdata.append(p, options.extraData[p]); + } + + options.data = null; + + var s = $.extend(true, {}, $.ajaxSettings, options, { + contentType: false, + processData: false, + cache: false, + type: 'POST' + }); + + if (options.uploadProgress) { + // workaround because jqXHR does not expose upload property + s.xhr = function() { + var xhr = jQuery.ajaxSettings.xhr(); + if (xhr.upload) { + xhr.upload.onprogress = function(event) { + var percent = 0; + var position = event.loaded || event.position; /*event.position is deprecated*/ + var total = event.total; + if (event.lengthComputable) { + percent = Math.ceil(position / total * 100); + } + options.uploadProgress(event, position, total, percent); + }; + } + return xhr; + }; + } + + s.data = null; + var beforeSend = s.beforeSend; + s.beforeSend = function(xhr, o) { + o.data = formdata; + if(beforeSend) + beforeSend.call(o, xhr, options); + }; + $.ajax(s); + } + + // private function for handling file uploads (hat tip to YAHOO!) + function fileUploadIframe(a) { + var form = $form[0], el, i, s, g, id, $io, io, xhr, sub, n, timedOut, timeoutHandle; + var useProp = !!$.fn.prop; + + if ($(':input[name=submit],:input[id=submit]', form).length) { + // if there is an input with a name or id of 'submit' then we won't be + // able to invoke the submit fn on the form (at least not x-browser) + alert('Error: Form elements must not have name or id of "submit".'); + return; + } + + if (a) { + // ensure that every serialized input is still enabled + for (i=0; i < elements.length; i++) { + el = $(elements[i]); + if ( useProp ) + el.prop('disabled', false); + else + el.removeAttr('disabled'); + } + } + + s = $.extend(true, {}, $.ajaxSettings, options); + s.context = s.context || s; + id = 'jqFormIO' + (new Date().getTime()); + if (s.iframeTarget) { + $io = $(s.iframeTarget); + n = $io.attr('name'); + if (!n) + $io.attr('name', id); + else + id = n; + } + else { + $io = $('' ); - - iframe.on( 'load', function( e ) - { - e.removeListener(); - var doc = iframe.getFrameDocument().$; - // Custom domain handling is needed after each document.open(). - doc.open(); - if ( isCustomDomain ) - doc.domain = document.domain; - doc.write( htmlToLoad ); - doc.close(); - }, this ); - - iframe.setStyles( - { - width : '346px', - height : '130px', - 'background-color' : 'white', - border : '1px solid black' - } ); - iframe.setCustomData( 'dialog', this ); - - var field = this.getContentElement( 'general', 'editing_area' ), - container = field.getElement(); - container.setHtml( '' ); - container.append( iframe ); - - // IE need a redirect on focus to make - // the cursor blinking inside iframe. (#5461) - if ( CKEDITOR.env.ie ) - { - var focusGrabber = CKEDITOR.dom.element.createFromHtml( '' ); - focusGrabber.on( 'focus', function() - { - iframe.$.contentWindow.focus(); - }); - container.append( focusGrabber ); - - // Override focus handler on field. - field.focus = function() - { - focusGrabber.focus(); - this.fire( 'focus' ); - }; - } - - field.getInputElement = function(){ return iframe; }; - - // Force container to scale in IE. - if ( CKEDITOR.env.ie ) - { - container.setStyle( 'display', 'block' ); - container.setStyle( 'height', ( iframe.$.offsetHeight + 2 ) + 'px' ); - } - }, - - onHide : function() - { - if ( CKEDITOR.env.ie ) - this.getParentEditor().document.getBody().$.contentEditable = 'true'; - }, - - onLoad : function() - { - if ( ( CKEDITOR.env.ie7Compat || CKEDITOR.env.ie6Compat ) && editor.lang.dir == 'rtl' ) - this.parts.contents.setStyle( 'overflow', 'hidden' ); - }, - - onOk : function() - { - var container = this.getContentElement( 'general', 'editing_area' ).getElement(), - iframe = container.getElementsByTag( 'iframe' ).getItem( 0 ), - editor = this.getParentEditor(), - html = iframe.$.contentWindow.document.body.innerHTML; - - setTimeout( function(){ - editor.fire( 'paste', { 'html' : html } ); - }, 0 ); - - }, - - contents : [ - { - id : 'general', - label : editor.lang.common.generalTab, - elements : [ - { - type : 'html', - id : 'securityMsg', - html : '
' + lang.securityMsg + '
' - }, - { - type : 'html', - id : 'pasteMsg', - html : '
'+lang.pasteMsg +'
' - }, - { - type : 'html', - id : 'editing_area', - style : 'width: 100%; height: 100%;', - html : '', - focus : function() - { - var win = this.getInputElement().$.contentWindow; - - // #3291 : JAWS needs the 500ms delay to detect that the editor iframe - // iframe is no longer editable. So that it will put the focus into the - // Paste from Word dialog's editable area instead. - setTimeout( function() - { - win.focus(); - }, 500 ); - } - } - ] - } - ] - }; -}); diff --git a/lib/ckeditor/_source/plugins/clipboard/plugin.js b/lib/ckeditor/_source/plugins/clipboard/plugin.js deleted file mode 100644 index f3cb0c0..0000000 --- a/lib/ckeditor/_source/plugins/clipboard/plugin.js +++ /dev/null @@ -1,413 +0,0 @@ -/* -Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved. -For licensing, see LICENSE.html or http://ckeditor.com/license -*/ - -/** - * @file Clipboard support - */ - -(function() -{ - // Tries to execute any of the paste, cut or copy commands in IE. Returns a - // boolean indicating that the operation succeeded. - var execIECommand = function( editor, command ) - { - var doc = editor.document, - body = doc.getBody(); - - var enabled = false; - var onExec = function() - { - enabled = true; - }; - - // The following seems to be the only reliable way to detect that - // clipboard commands are enabled in IE. It will fire the - // onpaste/oncut/oncopy events only if the security settings allowed - // the command to execute. - body.on( command, onExec ); - - // IE6/7: document.execCommand has problem to paste into positioned element. - ( CKEDITOR.env.version > 7 ? doc.$ : doc.$.selection.createRange() ) [ 'execCommand' ]( command ); - - body.removeListener( command, onExec ); - - return enabled; - }; - - // Attempts to execute the Cut and Copy operations. - var tryToCutCopy = - CKEDITOR.env.ie ? - function( editor, type ) - { - return execIECommand( editor, type ); - } - : // !IE. - function( editor, type ) - { - try - { - // Other browsers throw an error if the command is disabled. - return editor.document.$.execCommand( type ); - } - catch( e ) - { - return false; - } - }; - - // A class that represents one of the cut or copy commands. - var cutCopyCmd = function( type ) - { - this.type = type; - this.canUndo = ( this.type == 'cut' ); // We can't undo copy to clipboard. - }; - - cutCopyCmd.prototype = - { - exec : function( editor, data ) - { - this.type == 'cut' && fixCut( editor ); - - var success = tryToCutCopy( editor, this.type ); - - if ( !success ) - alert( editor.lang.clipboard[ this.type + 'Error' ] ); // Show cutError or copyError. - - return success; - } - }; - - // Paste command. - var pasteCmd = - { - canUndo : false, - - exec : - CKEDITOR.env.ie ? - function( editor ) - { - // Prevent IE from pasting at the begining of the document. - editor.focus(); - - if ( !editor.document.getBody().fire( 'beforepaste' ) - && !execIECommand( editor, 'paste' ) ) - { - editor.fire( 'pasteDialog' ); - return false; - } - } - : - function( editor ) - { - try - { - if ( !editor.document.getBody().fire( 'beforepaste' ) - && !editor.document.$.execCommand( 'Paste', false, null ) ) - { - throw 0; - } - } - catch ( e ) - { - setTimeout( function() - { - editor.fire( 'pasteDialog' ); - }, 0 ); - return false; - } - } - }; - - // Listens for some clipboard related keystrokes, so they get customized. - var onKey = function( event ) - { - if ( this.mode != 'wysiwyg' ) - return; - - switch ( event.data.keyCode ) - { - // Paste - case CKEDITOR.CTRL + 86 : // CTRL+V - case CKEDITOR.SHIFT + 45 : // SHIFT+INS - - var body = this.document.getBody(); - - // Simulate 'beforepaste' event for all none-IEs. - if ( !CKEDITOR.env.ie && body.fire( 'beforepaste' ) ) - event.cancel(); - // Simulate 'paste' event for Opera/Firefox2. - else if ( CKEDITOR.env.opera - || CKEDITOR.env.gecko && CKEDITOR.env.version < 10900 ) - body.fire( 'paste' ); - return; - - // Cut - case CKEDITOR.CTRL + 88 : // CTRL+X - case CKEDITOR.SHIFT + 46 : // SHIFT+DEL - - // Save Undo snapshot. - var editor = this; - this.fire( 'saveSnapshot' ); // Save before paste - setTimeout( function() - { - editor.fire( 'saveSnapshot' ); // Save after paste - }, 0 ); - } - }; - - // Allow to peek clipboard content by redirecting the - // pasting content into a temporary bin and grab the content of it. - function getClipboardData( evt, mode, callback ) - { - var doc = this.document; - - // Avoid recursions on 'paste' event for IE. - if ( CKEDITOR.env.ie && doc.getById( 'cke_pastebin' ) ) - return; - - // If the browser supports it, get the data directly - if (mode == 'text' && evt.data && evt.data.$.clipboardData) - { - // evt.data.$.clipboardData.types contains all the flavours in Mac's Safari, but not on windows. - var plain = evt.data.$.clipboardData.getData( 'text/plain' ); - if (plain) - { - evt.data.preventDefault(); - callback( plain ); - return; - } - } - - var sel = this.getSelection(), - range = new CKEDITOR.dom.range( doc ); - - // Create container to paste into - var pastebin = new CKEDITOR.dom.element( mode == 'text' ? 'textarea' : CKEDITOR.env.webkit ? 'body' : 'div', doc ); - pastebin.setAttribute( 'id', 'cke_pastebin' ); - // Safari requires a filler node inside the div to have the content pasted into it. (#4882) - CKEDITOR.env.webkit && pastebin.append( doc.createText( '\xa0' ) ); - doc.getBody().append( pastebin ); - - pastebin.setStyles( - { - position : 'absolute', - // Position the bin exactly at the position of the selected element - // to avoid any subsequent document scroll. - top : sel.getStartElement().getDocumentPosition().y + 'px', - width : '1px', - height : '1px', - overflow : 'hidden' - }); - - // It's definitely a better user experience if we make the paste-bin pretty unnoticed - // by pulling it off the screen. - pastebin.setStyle( this.config.contentsLangDirection == 'ltr' ? 'left' : 'right', '-1000px' ); - - var bms = sel.createBookmarks(); - - // Turn off design mode temporarily before give focus to the paste bin. - if ( mode == 'text' ) - { - if ( CKEDITOR.env.ie ) - { - var ieRange = doc.getBody().$.createTextRange(); - ieRange.moveToElementText( pastebin.$ ); - ieRange.execCommand( 'Paste' ); - evt.data.preventDefault(); - } - else - { - doc.$.designMode = 'off'; - pastebin.$.focus(); - } - } - else - { - range.setStartAt( pastebin, CKEDITOR.POSITION_AFTER_START ); - range.setEndAt( pastebin, CKEDITOR.POSITION_BEFORE_END ); - range.select( true ); - } - - // Wait a while and grab the pasted contents - window.setTimeout( function() - { - mode == 'text' && !CKEDITOR.env.ie && ( doc.$.designMode = 'on' ); - pastebin.remove(); - - // Grab the HTML contents. - // We need to look for a apple style wrapper on webkit it also adds - // a div wrapper if you copy/paste the body of the editor. - // Remove hidden div and restore selection. - var bogusSpan; - pastebin = ( CKEDITOR.env.webkit - && ( bogusSpan = pastebin.getFirst() ) - && ( bogusSpan.is && bogusSpan.hasClass( 'Apple-style-span' ) ) ? - bogusSpan : pastebin ); - - sel.selectBookmarks( bms ); - callback( pastebin[ 'get' + ( mode == 'text' ? 'Value' : 'Html' ) ]() ); - }, 0 ); - } - - // Cutting off control type element in IE standards breaks the selection entirely. (#4881) - function fixCut( editor ) - { - if ( !CKEDITOR.env.ie || editor.document.$.compatMode == 'BackCompat' ) - return; - - var sel = editor.getSelection(); - var control; - if( ( sel.getType() == CKEDITOR.SELECTION_ELEMENT ) && ( control = sel.getSelectedElement() ) ) - { - var range = sel.getRanges()[ 0 ]; - var dummy = editor.document.createText( '' ); - dummy.insertBefore( control ); - range.setStartBefore( dummy ); - range.setEndAfter( control ); - sel.selectRanges( [ range ] ); - - // Clear up the fix if the paste wasn't succeeded. - setTimeout( function() - { - // Element still online? - if ( control.getParent() ) - { - dummy.remove(); - sel.selectElement( control ); - } - }, 0 ); - } - } - - // Register the plugin. - CKEDITOR.plugins.add( 'clipboard', - { - requires : [ 'dialog', 'htmldataprocessor' ], - init : function( editor ) - { - // Inserts processed data into the editor at the end of the - // events chain. - editor.on( 'paste', function( evt ) - { - var data = evt.data; - if ( data[ 'html' ] ) - editor.insertHtml( data[ 'html' ] ); - else if ( data[ 'text' ] ) - editor.insertText( data[ 'text' ] ); - - }, null, null, 1000 ); - - editor.on( 'pasteDialog', function( evt ) - { - setTimeout( function() - { - // Open default paste dialog. - editor.openDialog( 'paste' ); - }, 0 ); - }); - - function addButtonCommand( buttonName, commandName, command, ctxMenuOrder ) - { - var lang = editor.lang[ commandName ]; - - editor.addCommand( commandName, command ); - editor.ui.addButton( buttonName, - { - label : lang, - command : commandName - }); - - // If the "menu" plugin is loaded, register the menu item. - if ( editor.addMenuItems ) - { - editor.addMenuItem( commandName, - { - label : lang, - command : commandName, - group : 'clipboard', - order : ctxMenuOrder - }); - } - } - - addButtonCommand( 'Cut', 'cut', new cutCopyCmd( 'cut' ), 1 ); - addButtonCommand( 'Copy', 'copy', new cutCopyCmd( 'copy' ), 4 ); - addButtonCommand( 'Paste', 'paste', pasteCmd, 8 ); - - CKEDITOR.dialog.add( 'paste', CKEDITOR.getUrl( this.path + 'dialogs/paste.js' ) ); - - editor.on( 'key', onKey, editor ); - - var mode = editor.config.forcePasteAsPlainText ? 'text' : 'html'; - - // We'll be catching all pasted content in one line, regardless of whether the - // it's introduced by a document command execution (e.g. toolbar buttons) or - // user paste behaviors. (e.g. Ctrl-V) - editor.on( 'contentDom', function() - { - var body = editor.document.getBody(); - body.on( ( (mode == 'text' && CKEDITOR.env.ie) || CKEDITOR.env.webkit ) ? 'paste' : 'beforepaste', - function( evt ) - { - if ( depressBeforeEvent ) - return; - - getClipboardData.call( editor, evt, mode, function ( data ) - { - // The very last guard to make sure the - // paste has successfully happened. - if ( !data ) - return; - - var dataTransfer = {}; - dataTransfer[ mode ] = data; - editor.fire( 'paste', dataTransfer ); - } ); - }); - - body.on( 'beforecut', function() { !depressBeforeEvent && fixCut( editor ); } ); - }); - - // If the "contextmenu" plugin is loaded, register the listeners. - if ( editor.contextMenu ) - { - var depressBeforeEvent; - function stateFromNamedCommand( command ) - { - // IE Bug: queryCommandEnabled('paste') fires also 'beforepaste(copy/cut)', - // guard to distinguish from the ordinary sources( either - // keyboard paste or execCommand ) (#4874). - CKEDITOR.env.ie && ( depressBeforeEvent = 1 ); - - var retval = editor.document.$.queryCommandEnabled( command ) ? CKEDITOR.TRISTATE_OFF : CKEDITOR.TRISTATE_DISABLED; - depressBeforeEvent = 0; - return retval; - } - - editor.contextMenu.addListener( function() - { - return { - cut : stateFromNamedCommand( 'Cut' ), - - // Browser bug: 'Cut' has the correct states for both Copy and Cut. - copy : stateFromNamedCommand( 'Cut' ), - paste : CKEDITOR.env.webkit ? CKEDITOR.TRISTATE_OFF : stateFromNamedCommand( 'Paste' ) - }; - }); - } - } - }); -})(); - -/** - * Fired when a clipboard operation is about to be taken into the editor. - * Listeners can manipulate the data to be pasted before having it effectively - * inserted into the document. - * @name CKEDITOR.editor#paste - * @since 3.1 - * @event - * @param {String} [data.html] The HTML data to be pasted. If not available, e.data.text will be defined. - * @param {String} [data.text] The plain text data to be pasted, available when plain text operations are to used. If not available, e.data.html will be defined. - */ diff --git a/lib/ckeditor/_source/plugins/colorbutton/plugin.js b/lib/ckeditor/_source/plugins/colorbutton/plugin.js deleted file mode 100644 index f2a8f2b..0000000 --- a/lib/ckeditor/_source/plugins/colorbutton/plugin.js +++ /dev/null @@ -1,248 +0,0 @@ -/* -Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved. -For licensing, see LICENSE.html or http://ckeditor.com/license -*/ - -CKEDITOR.plugins.add( 'colorbutton', -{ - requires : [ 'panelbutton', 'floatpanel', 'styles' ], - - init : function( editor ) - { - var config = editor.config, - lang = editor.lang.colorButton; - - var clickFn; - - if ( !CKEDITOR.env.hc ) - { - addButton( 'TextColor', 'fore', lang.textColorTitle ); - addButton( 'BGColor', 'back', lang.bgColorTitle ); - } - - function addButton( name, type, title ) - { - editor.ui.add( name, CKEDITOR.UI_PANELBUTTON, - { - label : title, - title : title, - className : 'cke_button_' + name.toLowerCase(), - modes : { wysiwyg : 1 }, - - panel : - { - css : editor.skin.editor.css, - attributes : { role : 'listbox', 'aria-label' : lang.panelTitle } - }, - - onBlock : function( panel, block ) - { - block.autoSize = true; - block.element.addClass( 'cke_colorblock' ); - block.element.setHtml( renderColors( panel, type ) ); - - var keys = block.keys; - keys[ 39 ] = 'next'; // ARROW-RIGHT - keys[ 40 ] = 'next'; // ARROW-DOWN - keys[ 9 ] = 'next'; // TAB - keys[ 37 ] = 'prev'; // ARROW-LEFT - keys[ 38 ] = 'prev'; // ARROW-UP - keys[ CKEDITOR.SHIFT + 9 ] = 'prev'; // SHIFT + TAB - keys[ 32 ] = 'click'; // SPACE - } - }); - } - - - function renderColors( panel, type ) - { - var output = [], - colors = config.colorButton_colors.split( ',' ), - total = colors.length + ( config.colorButton_enableMore ? 2 : 1 ); - - var clickFn = CKEDITOR.tools.addFunction( function( color, type ) - { - if ( color == '?' ) - { - var applyColorStyle = arguments.callee; - function onColorDialogClose( evt ) - { - this.removeListener( 'ok', onColorDialogClose ); - this.removeListener( 'cancel', onColorDialogClose ); - - evt.name == 'ok' && applyColorStyle( this.getContentElement( 'picker', 'selectedColor' ).getValue(), type ); - } - - editor.openDialog( 'colordialog', function() - { - this.on( 'ok', onColorDialogClose ); - this.on( 'cancel', onColorDialogClose ); - } ); - - return; - } - - editor.focus(); - - panel.hide(); - - - editor.fire( 'saveSnapshot' ); - - // Clean up any conflicting style within the range. - new CKEDITOR.style( config['colorButton_' + type + 'Style'], { color : 'inherit' } ).remove( editor.document ); - - if ( color ) - { - var colorStyle = config['colorButton_' + type + 'Style']; - - colorStyle.childRule = type == 'back' ? - // It's better to apply background color as the innermost style. (#3599) - function(){ return false; } : - // Fore color style must be applied inside links instead of around it. - function( element ){ return element.getName() != 'a'; }; - - new CKEDITOR.style( colorStyle, { color : color } ).apply( editor.document ); - } - - editor.fire( 'saveSnapshot' ); - }); - - // Render the "Automatic" button. - output.push( - '' + - '' + - '' + - '' + - '' + - '' + - '
' + - '' + - '', - lang.auto, - '
' + - '
' + - '' ); - - // Render the color boxes. - for ( var i = 0 ; i < colors.length ; i++ ) - { - if ( ( i % 8 ) === 0 ) - output.push( '' ); - - var parts = colors[ i ].split( '/' ), - colorName = parts[ 0 ], - colorCode = parts[ 1 ] || colorName; - - // The data can be only a color code (without #) or colorName + color code - // If only a color code is provided, then the colorName is the color with the hash - // Convert the color from RGB to RRGGBB for better compatibility with IE and . See #5676 - if (!parts[1]) - colorName = '#' + colorName.replace( /^(.)(.)(.)$/, '$1$1$2$2$3$3' ); - - var colorLabel = editor.lang.colors[ colorCode ] || colorCode; - output.push( - '' ); - } - - // Render the "More Colors" button. - if ( config.colorButton_enableMore ) - { - output.push( - '' + - '' + - '' ); // It is later in the code. - } - - output.push( '
' + - '' + - '' + - '' + - '
' + - '', - lang.more, - '' + - '
' ); - - return output.join( '' ); - } - } -}); - -/** - * Whether to enable the "More Colors..." button in the color selectors. - * @default false - * @type Boolean - * @example - * config.colorButton_enableMore = false; - */ -CKEDITOR.config.colorButton_enableMore = true; - -/** - * Defines the colors to be displayed in the color selectors. It's a string - * containing the hexadecimal notation for HTML colors, without the "#" prefix. - * - * Since 3.3: A name may be optionally defined by prefixing the entries with the - * name and the slash character. For example, "FontColor1/FF9900" will be - * displayed as the color #FF9900 in the selector, but will be outputted as "FontColor1". - * @type String - * @default '000,800000,8B4513,2F4F4F,008080,000080,4B0082,696969,B22222,A52A2A,DAA520,006400,40E0D0,0000CD,800080,808080,F00,FF8C00,FFD700,008000,0FF,00F,EE82EE,A9A9A9,FFA07A,FFA500,FFFF00,00FF00,AFEEEE,ADD8E6,DDA0DD,D3D3D3,FFF0F5,FAEBD7,FFFFE0,F0FFF0,F0FFFF,F0F8FF,E6E6FA,FFF' - * @example - * // Brazil colors only. - * config.colorButton_colors = '00923E,F8C100,28166F'; - * @example - * config.colorButton_colors = 'FontColor1/FF9900,FontColor2/0066CC,FontColor3/F00' - */ -CKEDITOR.config.colorButton_colors = - '000,800000,8B4513,2F4F4F,008080,000080,4B0082,696969,' + - 'B22222,A52A2A,DAA520,006400,40E0D0,0000CD,800080,808080,' + - 'F00,FF8C00,FFD700,008000,0FF,00F,EE82EE,A9A9A9,' + - 'FFA07A,FFA500,FFFF00,00FF00,AFEEEE,ADD8E6,DDA0DD,D3D3D3,' + - 'FFF0F5,FAEBD7,FFFFE0,F0FFF0,F0FFFF,F0F8FF,E6E6FA,FFF'; - -/** - * Holds the style definition to be used to apply the text foreground color. - * @type Object - * @example - * // This is basically the default setting value. - * config.colorButton_foreStyle = - * { - * element : 'span', - * styles : { 'color' : '#(color)' } - * }; - */ -CKEDITOR.config.colorButton_foreStyle = - { - element : 'span', - styles : { 'color' : '#(color)' }, - overrides : [ { element : 'font', attributes : { 'color' : null } } ] - }; - -/** - * Holds the style definition to be used to apply the text background color. - * @type Object - * @example - * // This is basically the default setting value. - * config.colorButton_backStyle = - * { - * element : 'span', - * styles : { 'background-color' : '#(color)' } - * }; - */ -CKEDITOR.config.colorButton_backStyle = - { - element : 'span', - styles : { 'background-color' : '#(color)' } - }; diff --git a/lib/ckeditor/_source/plugins/colordialog/dialogs/colordialog.js b/lib/ckeditor/_source/plugins/colordialog/dialogs/colordialog.js deleted file mode 100644 index 3259e7f..0000000 --- a/lib/ckeditor/_source/plugins/colordialog/dialogs/colordialog.js +++ /dev/null @@ -1,339 +0,0 @@ -/* -Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved. -For licensing, see LICENSE.html or http://ckeditor.com/license -*/ - -CKEDITOR.dialog.add( 'colordialog', function( editor ) - { - // Define some shorthands. - var $el = CKEDITOR.dom.element, - $doc = CKEDITOR.document, - $tools = CKEDITOR.tools, - lang = editor.lang.colordialog; - - // Reference the dialog. - var dialog; - - function spacer() - { - return { - type : 'html', - html : ' ' - }; - } - - function clearSelected() - { - $doc.getById( selHiColorId ).removeStyle( 'background-color' ); - dialog.getContentElement( 'picker', 'selectedColor' ).setValue( '' ); - } - - function updateSelected( evt ) - { - if ( ! (evt instanceof CKEDITOR.dom.event ) ) - evt = new CKEDITOR.dom.event( evt ); - - var target = evt.getTarget(), - color; - - if ( target.getName() == 'a' && ( color = target.getChild( 0 ).getHtml() ) ) - dialog.getContentElement( 'picker', 'selectedColor' ).setValue( color ); - } - - function updateHighlight( event ) - { - if ( ! (event instanceof CKEDITOR.dom.event ) ) - event = event.data; - - var target = event.getTarget(), - color; - - if ( target.getName() == 'a' && ( color = target.getChild( 0 ).getHtml() ) ) - { - $doc.getById( hicolorId ).setStyle( 'background-color', color ); - $doc.getById( hicolorTextId ).setHtml( color ); - } - } - - function clearHighlight() - { - $doc.getById( hicolorId ).removeStyle( 'background-color' ); - $doc.getById( hicolorTextId ).setHtml( ' ' ); - } - - var onMouseout = $tools.addFunction( clearHighlight ); - - var onClick = updateSelected, - onClickHandler = CKEDITOR.tools.addFunction( onClick ); - - var onFocus = updateHighlight, - onBlur = clearHighlight; - - var onKeydownHandler = CKEDITOR.tools.addFunction( function( ev ) - { - ev = new CKEDITOR.dom.event( ev ); - var element = ev.getTarget(); - var relative, nodeToMove; - var keystroke = ev.getKeystroke(); - var rtl = editor.lang.dir == 'rtl'; - - switch ( keystroke ) - { - // UP-ARROW - case 38 : - // relative is TR - if ( ( relative = element.getParent().getParent().getPrevious() ) ) - { - nodeToMove = relative.getChild( [element.getParent().getIndex(), 0] ); - nodeToMove.focus(); - onBlur( ev, element ); - onFocus( ev, nodeToMove ); - } - ev.preventDefault(); - break; - // DOWN-ARROW - case 40 : - // relative is TR - if ( ( relative = element.getParent().getParent().getNext() ) ) - { - nodeToMove = relative.getChild( [ element.getParent().getIndex(), 0 ] ); - if ( nodeToMove && nodeToMove.type == 1 ) - { - nodeToMove.focus(); - onBlur( ev, element ); - onFocus( ev, nodeToMove ); - } - } - ev.preventDefault(); - break; - // SPACE - // ENTER is already handled as onClick - case 32 : - onClick( ev ); - ev.preventDefault(); - break; - - // RIGHT-ARROW - case rtl ? 37 : 39 : - // relative is TD - if ( ( relative = element.getParent().getNext() ) ) - { - nodeToMove = relative.getChild( 0 ); - if ( nodeToMove.type == 1 ) - { - nodeToMove.focus(); - onBlur( ev, element ); - onFocus( ev, nodeToMove ); - ev.preventDefault( true ); - } - else - onBlur( null, element ); - } - // relative is TR - else if ( ( relative = element.getParent().getParent().getNext() ) ) - { - nodeToMove = relative.getChild( [ 0, 0 ] ); - if ( nodeToMove && nodeToMove.type == 1 ) - { - nodeToMove.focus(); - onBlur( ev, element ); - onFocus( ev, nodeToMove ); - ev.preventDefault( true ); - } - else - onBlur( null, element ); - } - break; - - // LEFT-ARROW - case rtl ? 39 : 37 : - // relative is TD - if ( ( relative = element.getParent().getPrevious() ) ) - { - nodeToMove = relative.getChild( 0 ); - nodeToMove.focus(); - onBlur( ev, element ); - onFocus( ev, nodeToMove ); - ev.preventDefault( true ); - } - // relative is TR - else if ( ( relative = element.getParent().getParent().getPrevious() ) ) - { - nodeToMove = relative.getLast().getChild( 0 ); - nodeToMove.focus(); - onBlur( ev, element ); - onFocus( ev, nodeToMove ); - ev.preventDefault( true ); - } - else - onBlur( null, element ); - break; - default : - // Do not stop not handled events. - return; - } - }); - - function createColorTable() - { - // Create the base colors array. - var aColors = ['00','33','66','99','cc','ff']; - - // This function combines two ranges of three values from the color array into a row. - function appendColorRow( rangeA, rangeB ) - { - for ( var i = rangeA ; i < rangeA + 3 ; i++ ) - { - var row = table.$.insertRow(-1); - - for ( var j = rangeB ; j < rangeB + 3 ; j++ ) - { - for ( var n = 0 ; n < 6 ; n++ ) - { - appendColorCell( row, '#' + aColors[j] + aColors[n] + aColors[i] ); - } - } - } - } - - // This function create a single color cell in the color table. - function appendColorCell( targetRow, color ) - { - var cell = new $el( targetRow.insertCell( -1 ) ); - cell.setAttribute( 'class', 'ColorCell' ); - cell.setStyle( 'background-color', color ); - - cell.setStyle( 'width', '15px' ); - cell.setStyle( 'height', '15px' ); - - var index = cell.$.cellIndex + 1 + 18 * targetRow.rowIndex; - cell.append( CKEDITOR.dom.element.createFromHtml( - '' + color + ' ', CKEDITOR.document ) ); - } - - appendColorRow( 0, 0 ); - appendColorRow( 3, 0 ); - appendColorRow( 0, 3 ); - appendColorRow( 3, 3 ); - - // Create the last row. - var oRow = table.$.insertRow(-1) ; - - // Create the gray scale colors cells. - for ( var n = 0 ; n < 6 ; n++ ) - { - appendColorCell( oRow, '#' + aColors[n] + aColors[n] + aColors[n] ) ; - } - - // Fill the row with black cells. - for ( var i = 0 ; i < 12 ; i++ ) - { - appendColorCell( oRow, '#000000' ) ; - } - } - - var table = new $el( 'table' ); - createColorTable(); - - var numbering = function( id ) - { - return id + CKEDITOR.tools.getNextNumber(); - }, - hicolorId = numbering( 'hicolor' ), - hicolorTextId = numbering( 'hicolortext' ), - selHiColorId = numbering( 'selhicolor' ); - - return { - title : lang.title, - minWidth : 360, - minHeight : 220, - onLoad : function() - { - // Update reference. - dialog = this; - }, - contents : [ - { - id : 'picker', - label : lang.title, - accessKey : 'I', - elements : - [ - { - type : 'hbox', - padding : 0, - widths : [ '70%', '10%', '30%' ], - children : - [ - { - type : 'html', - html : '' + table.getHtml() + '
' + - '' + lang.options +'', - onLoad : function() - { - var table = CKEDITOR.document.getById( this.domId ); - table.on( 'mouseover', updateHighlight ); - }, - focus: function() - { - var firstColor = this.getElement().getElementsByTag( 'a' ).getItem( 0 ); - firstColor.focus(); - } - }, - spacer(), - { - type : 'vbox', - padding : 0, - widths : [ '70%', '5%', '25%' ], - children : - [ - { - type : 'html', - html : '' + lang.highlight +'\ -
\ -
 
' + lang.selected + '\ -
' - }, - { - type : 'text', - label : lang.selected, - labelStyle: 'display:none', - id : 'selectedColor', - style : 'width: 74px', - onChange : function() - { - // Try to update color preview with new value. If fails, then set it no none. - try - { - $doc.getById( selHiColorId ).setStyle( 'background-color', this.getValue() ); - } - catch ( e ) - { - clearSelected(); - } - } - }, - spacer(), - { - type : 'button', - id : 'clear', - style : 'margin-top: 5px', - label : lang.clear, - onClick : clearSelected - } - ] - } - ] - } - ] - } - ] - }; - } - ); diff --git a/lib/ckeditor/_source/plugins/colordialog/plugin.js b/lib/ckeditor/_source/plugins/colordialog/plugin.js deleted file mode 100644 index 7006d68..0000000 --- a/lib/ckeditor/_source/plugins/colordialog/plugin.js +++ /dev/null @@ -1,13 +0,0 @@ -( function() -{ - CKEDITOR.plugins.colordialog = - { - init : function( editor ) - { - editor.addCommand( 'colordialog', new CKEDITOR.dialogCommand( 'colordialog' ) ); - CKEDITOR.dialog.add( 'colordialog', this.path + 'dialogs/colordialog.js' ); - } - }; - - CKEDITOR.plugins.add( 'colordialog', CKEDITOR.plugins.colordialog ); -} )(); diff --git a/lib/ckeditor/_source/plugins/contextmenu/plugin.js b/lib/ckeditor/_source/plugins/contextmenu/plugin.js deleted file mode 100644 index b009dee..0000000 --- a/lib/ckeditor/_source/plugins/contextmenu/plugin.js +++ /dev/null @@ -1,276 +0,0 @@ -/* -Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved. -For licensing, see LICENSE.html or http://ckeditor.com/license -*/ - -CKEDITOR.plugins.add( 'contextmenu', -{ - requires : [ 'menu' ], - - beforeInit : function( editor ) - { - editor.contextMenu = new CKEDITOR.plugins.contextMenu( editor ); - - editor.addCommand( 'contextMenu', - { - exec : function() - { - editor.contextMenu.show( editor.document.getBody() ); - } - }); - } -}); - -CKEDITOR.plugins.contextMenu = CKEDITOR.tools.createClass( -{ - $ : function( editor ) - { - this.id = 'cke_' + CKEDITOR.tools.getNextNumber(); - this.editor = editor; - this._.listeners = []; - this._.functionId = CKEDITOR.tools.addFunction( function( commandName ) - { - this._.panel.hide(); - editor.focus(); - editor.execCommand( commandName ); - }, - this); - - this.definition = - { - panel: - { - className : editor.skinClass + ' cke_contextmenu', - attributes : - { - 'aria-label' : editor.lang.contextmenu.options - } - } - }; - }, - - _ : - { - onMenu : function( offsetParent, corner, offsetX, offsetY ) - { - var menu = this._.menu, - editor = this.editor; - - if ( menu ) - { - menu.hide(); - menu.removeAll(); - } - else - { - menu = this._.menu = new CKEDITOR.menu( editor, this.definition ); - menu.onClick = CKEDITOR.tools.bind( function( item ) - { - menu.hide(); - - if ( item.onClick ) - item.onClick(); - else if ( item.command ) - editor.execCommand( item.command ); - - }, this ); - - menu.onEscape = function( keystroke ) - { - var parent = this.parent; - // 1. If it's sub-menu, restore the last focused item - // of upper level menu. - // 2. In case of a top-menu, close it. - if ( parent ) - { - parent._.panel.hideChild(); - // Restore parent block item focus. - var parentBlock = parent._.panel._.panel._.currentBlock, - parentFocusIndex = parentBlock._.focusIndex; - parentBlock._.markItem( parentFocusIndex ); - } - else if ( keystroke == 27 ) - { - this.hide(); - editor.focus(); - } - return false; - }; - } - - var listeners = this._.listeners, - includedItems = []; - - var selection = this.editor.getSelection(), - element = selection && selection.getStartElement(); - - menu.onHide = CKEDITOR.tools.bind( function() - { - menu.onHide = null; - - if ( CKEDITOR.env.ie ) - { - var selection = editor.getSelection(); - selection && selection.unlock(); - } - - this.onHide && this.onHide(); - }, - this ); - - // Call all listeners, filling the list of items to be displayed. - for ( var i = 0 ; i < listeners.length ; i++ ) - { - var listenerItems = listeners[ i ]( element, selection ); - - if ( listenerItems ) - { - for ( var itemName in listenerItems ) - { - var item = this.editor.getMenuItem( itemName ); - - if ( item ) - { - item.state = listenerItems[ itemName ]; - menu.add( item ); - } - } - } - } - - // Don't show context menu with zero items. - menu.items.length && menu.show( offsetParent, corner || ( editor.lang.dir == 'rtl' ? 2 : 1 ), offsetX, offsetY ); - } - }, - - proto : - { - addTarget : function( element, nativeContextMenuOnCtrl ) - { - // Opera doesn't support 'contextmenu' event, we have duo approaches employed here: - // 1. Inherit the 'button override' hack we introduced in v2 (#4530), while this require the Opera browser - // option 'Allow script to detect context menu/right click events' to be always turned on. - // 2. Considering the fact that ctrl/meta key is not been occupied - // for multiple range selecting (like Gecko), we use this key - // combination as a fallback for triggering context-menu. (#4530) - if ( CKEDITOR.env.opera ) - { - var contextMenuOverrideButton; - element.on( 'mousedown', function( evt ) - { - evt = evt.data; - if ( evt.$.button != 2 ) - { - if ( evt.getKeystroke() == CKEDITOR.CTRL + 1 ) - element.fire( 'contextmenu', evt ); - return; - } - - if ( nativeContextMenuOnCtrl - && ( CKEDITOR.env.mac ? evt.$.metaKey : evt.$.ctrlKey ) ) - return; - - var target = evt.getTarget(); - - if ( !contextMenuOverrideButton ) - { - var ownerDoc = target.getDocument(); - contextMenuOverrideButton = ownerDoc.createElement( 'input' ) ; - contextMenuOverrideButton.$.type = 'button' ; - ownerDoc.getBody().append( contextMenuOverrideButton ) ; - } - - contextMenuOverrideButton.setAttribute( 'style', 'position:absolute;top:' + ( evt.$.clientY - 2 ) + - 'px;left:' + ( evt.$.clientX - 2 ) + - 'px;width:5px;height:5px;opacity:0.01' ); - - } ); - - element.on( 'mouseup', function ( evt ) - { - if ( contextMenuOverrideButton ) - { - contextMenuOverrideButton.remove(); - contextMenuOverrideButton = undefined; - // Simulate 'contextmenu' event. - element.fire( 'contextmenu', evt.data ); - } - } ); - } - - element.on( 'contextmenu', function( event ) - { - var domEvent = event.data; - - if ( nativeContextMenuOnCtrl && - // Safari on Windows always show 'ctrlKey' as true in 'contextmenu' event, - // which make this property unreliable. (#4826) - ( CKEDITOR.env.webkit ? holdCtrlKey : ( CKEDITOR.env.mac ? domEvent.$.metaKey : domEvent.$.ctrlKey ) ) ) - return; - - - // Cancel the browser context menu. - domEvent.preventDefault(); - - var offsetParent = domEvent.getTarget().getDocument().getDocumentElement(), - offsetX = domEvent.$.clientX, - offsetY = domEvent.$.clientY; - - CKEDITOR.tools.setTimeout( function() - { - this.show( offsetParent, null, offsetX, offsetY ); - }, - 0, this ); - }, - this ); - - if ( CKEDITOR.env.webkit ) - { - var holdCtrlKey, - onKeyDown = function( event ) - { - holdCtrlKey = CKEDITOR.env.mac ? event.data.$.metaKey : event.data.$.ctrlKey ; - }, - resetOnKeyUp = function() - { - holdCtrlKey = 0; - }; - - element.on( 'keydown', onKeyDown ); - element.on( 'keyup', resetOnKeyUp ); - element.on( 'contextmenu', resetOnKeyUp ); - } - }, - - addListener : function( listenerFn ) - { - this._.listeners.push( listenerFn ); - }, - - show : function( offsetParent, corner, offsetX, offsetY ) - { - this.editor.focus(); - - // Selection will be unavailable after context menu shows up - // in IE, lock it now. - if ( CKEDITOR.env.ie ) - { - var selection = this.editor.getSelection(); - selection && selection.lock(); - } - - this._.onMenu( offsetParent || CKEDITOR.document.getDocumentElement(), corner, offsetX || 0, offsetY || 0 ); - } - } -}); - -/** - * Whether to show the browser native context menu when the CTRL or the - * META (Mac) key is pressed while opening the context menu. - * @name CKEDITOR.config.browserContextMenuOnCtrl - * @since 3.0.2 - * @type Boolean - * @default true - * @example - * config.browserContextMenuOnCtrl = false; - */ diff --git a/lib/ckeditor/_source/plugins/dialog/dialogDefinition.js b/lib/ckeditor/_source/plugins/dialog/dialogDefinition.js deleted file mode 100644 index a3094f6..0000000 --- a/lib/ckeditor/_source/plugins/dialog/dialogDefinition.js +++ /dev/null @@ -1,315 +0,0 @@ -/* -Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved. -For licensing, see LICENSE.html or http://ckeditor.com/license -*/ - -/** - * @fileOverview Defines the "virtual" dialog, dialog content and dialog button - * definition classes. - */ - -/** - * This class is not really part of the API. It just illustrates the properties - * that developers can use to define and create dialogs. - * @name CKEDITOR.dialog.dialogDefinition - * @constructor - * @example - * // There is no constructor for this class, the user just has to define an - * // object with the appropriate properties. - * - * CKEDITOR.dialog.add( 'testOnly', function( editor ) - * { - * return { - * title : 'Test Dialog', - * resizable : CKEDITOR.DIALOG_RESIZE_BOTH, - * minWidth : 500, - * minHeight : 400, - * contents : [ - * { - * id : 'tab1', - * label : 'First Tab', - * title : 'First Tab Title', - * accessKey : 'Q', - * elements : [ - * { - * type : 'text', - * label : 'Test Text 1', - * id : 'testText1', - * 'default' : 'hello world!' - * } - * ] - * } - * ] - * }; - * }); - */ - -/** - * The dialog title, displayed in the dialog's header. Required. - * @name CKEDITOR.dialog.dialogDefinition.prototype.title - * @field - * @type String - * @example - */ - -/** - * How the dialog can be resized, must be one of the four contents defined below. - *

- * CKEDITOR.DIALOG_RESIZE_NONE
- * CKEDITOR.DIALOG_RESIZE_WIDTH
- * CKEDITOR.DIALOG_RESIZE_HEIGHT
- * CKEDITOR.DIALOG_RESIZE_BOTH
- * @name CKEDITOR.dialog.dialogDefinition.prototype.resizable - * @field - * @type Number - * @default CKEDITOR.DIALOG_RESIZE_NONE - * @example - */ - -/** - * The minimum width of the dialog, in pixels. - * @name CKEDITOR.dialog.dialogDefinition.prototype.minWidth - * @field - * @type Number - * @default 600 - * @example - */ - -/** - * The minimum height of the dialog, in pixels. - * @name CKEDITOR.dialog.dialogDefinition.prototype.minHeight - * @field - * @type Number - * @default 400 - * @example - */ - -/** - * The buttons in the dialog, defined as an array of - * {@link CKEDITOR.dialog.buttonDefinition} objects. - * @name CKEDITOR.dialog.dialogDefinition.prototype.buttons - * @field - * @type Array - * @default [ CKEDITOR.dialog.okButton, CKEDITOR.dialog.cancelButton ] - * @example - */ - -/** - * The contents in the dialog, defined as an array of - * {@link CKEDITOR.dialog.contentDefinition} objects. Required. - * @name CKEDITOR.dialog.dialogDefinition.prototype.contents - * @field - * @type Array - * @example - */ - -/** - * The function to execute when OK is pressed. - * @name CKEDITOR.dialog.dialogDefinition.prototype.onOk - * @field - * @type Function - * @example - */ - -/** - * The function to execute when Cancel is pressed. - * @name CKEDITOR.dialog.dialogDefinition.prototype.onCancel - * @field - * @type Function - * @example - */ - -/** - * The function to execute when the dialog is displayed for the first time. - * @name CKEDITOR.dialog.dialogDefinition.prototype.onLoad - * @field - * @type Function - * @example - */ - -/** - * This class is not really part of the API. It just illustrates the properties - * that developers can use to define and create dialog content pages. - * @name CKEDITOR.dialog.contentDefinition - * @constructor - * @example - * // There is no constructor for this class, the user just has to define an - * // object with the appropriate properties. - */ - -/** - * The id of the content page. - * @name CKEDITOR.dialog.contentDefinition.prototype.id - * @field - * @type String - * @example - */ - -/** - * The tab label of the content page. - * @name CKEDITOR.dialog.contentDefinition.prototype.label - * @field - * @type String - * @example - */ - -/** - * The popup message of the tab label. - * @name CKEDITOR.dialog.contentDefinition.prototype.title - * @field - * @type String - * @example - */ - -/** - * The CTRL hotkey for switching to the tab. - * @name CKEDITOR.dialog.contentDefinition.prototype.accessKey - * @field - * @type String - * @example - * contentDefinition.accessKey = 'Q'; // Switch to this page when CTRL-Q is pressed. - */ - -/** - * The UI elements contained in this content page, defined as an array of - * {@link CKEDITOR.dialog.uiElementDefinition} objects. - * @name CKEDITOR.dialog.contentDefinition.prototype.elements - * @field - * @type Array - * @example - */ - -/** - * This class is not really part of the API. It just illustrates the properties - * that developers can use to define and create dialog buttons. - * @name CKEDITOR.dialog.buttonDefinition - * @constructor - * @example - * // There is no constructor for this class, the user just has to define an - * // object with the appropriate properties. - */ - -/** - * The id of the dialog button. Required. - * @name CKEDITOR.dialog.buttonDefinition.prototype.id - * @type String - * @field - * @example - */ - -/** - * The label of the dialog button. Required. - * @name CKEDITOR.dialog.buttonDefinition.prototype.label - * @type String - * @field - * @example - */ - -/** - * The popup message of the dialog button. - * @name CKEDITOR.dialog.buttonDefinition.prototype.title - * @type String - * @field - * @example - */ - -/** - * The CTRL hotkey for the button. - * @name CKEDITOR.dialog.buttonDefinition.prototype.accessKey - * @type String - * @field - * @example - * exitButton.accessKey = 'X'; // Button will be pressed when user presses CTRL-X - */ - -/** - * Whether the button is disabled. - * @name CKEDITOR.dialog.buttonDefinition.prototype.disabled - * @type Boolean - * @field - * @default false - * @example - */ - -/** - * The function to execute when the button is clicked. - * @name CKEDITOR.dialog.buttonDefinition.prototype.onClick - * @type Function - * @field - * @example - */ - -/** - * This class is not really part of the API. It just illustrates the properties - * that developers can use to define and create dialog UI elements. - * @name CKEDITOR.dialog.uiElementDefinition - * @constructor - * @see CKEDITOR.ui.dialog.uiElement - * @example - * // There is no constructor for this class, the user just has to define an - * // object with the appropriate properties. - */ - -/** - * The id of the UI element. - * @name CKEDITOR.dialog.uiElementDefinition.prototype.id - * @field - * @type String - * @example - */ - -/** - * The type of the UI element. Required. - * @name CKEDITOR.dialog.uiElementDefinition.prototype.type - * @field - * @type String - * @example - */ - -/** - * The popup label of the UI element. - * @name CKEDITOR.dialog.uiElementDefinition.prototype.title - * @field - * @type String - * @example - */ - -/** - * CSS class names to append to the UI element. - * @name CKEDITOR.dialog.uiElementDefinition.prototype.className - * @field - * @type String - * @example - */ - -/** - * Inline CSS classes to append to the UI element. - * @name CKEDITOR.dialog.uiElementDefinition.prototype.style - * @field - * @type String - * @example - */ - -/** - * Function to execute the first time the UI element is displayed. - * @name CKEDITOR.dialog.uiElementDefinition.prototype.onLoad - * @field - * @type Function - * @example - */ - -/** - * Function to execute whenever the UI element's parent dialog is displayed. - * @name CKEDITOR.dialog.uiElementDefinition.prototype.onShow - * @field - * @type Function - * @example - */ - -/** - * Function to execute whenever the UI element's parent dialog is closed. - * @name CKEDITOR.dialog.uiElementDefinition.prototype.onHide - * @field - * @type Function - * @example - */ diff --git a/lib/ckeditor/_source/plugins/dialog/plugin.js b/lib/ckeditor/_source/plugins/dialog/plugin.js deleted file mode 100644 index 5615b11..0000000 --- a/lib/ckeditor/_source/plugins/dialog/plugin.js +++ /dev/null @@ -1,2950 +0,0 @@ -/* -Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved. -For licensing, see LICENSE.html or http://ckeditor.com/license -*/ - -/** - * @fileOverview The floating dialog plugin. - */ - -/** - * No resize for this dialog. - * @constant - */ -CKEDITOR.DIALOG_RESIZE_NONE = 0; - -/** - * Only allow horizontal resizing for this dialog, disable vertical resizing. - * @constant - */ -CKEDITOR.DIALOG_RESIZE_WIDTH = 1; - -/** - * Only allow vertical resizing for this dialog, disable horizontal resizing. - * @constant - */ -CKEDITOR.DIALOG_RESIZE_HEIGHT = 2; - -/* - * Allow the dialog to be resized in both directions. - * @constant - */ -CKEDITOR.DIALOG_RESIZE_BOTH = 3; - -(function() -{ - function isTabVisible( tabId ) - { - return !!this._.tabs[ tabId ][ 0 ].$.offsetHeight; - } - - function getPreviousVisibleTab() - { - var tabId = this._.currentTabId, - length = this._.tabIdList.length, - tabIndex = CKEDITOR.tools.indexOf( this._.tabIdList, tabId ) + length; - - for ( var i = tabIndex - 1 ; i > tabIndex - length ; i-- ) - { - if ( isTabVisible.call( this, this._.tabIdList[ i % length ] ) ) - return this._.tabIdList[ i % length ]; - } - - return null; - } - - function getNextVisibleTab() - { - var tabId = this._.currentTabId, - length = this._.tabIdList.length, - tabIndex = CKEDITOR.tools.indexOf( this._.tabIdList, tabId ); - - for ( var i = tabIndex + 1 ; i < tabIndex + length ; i++ ) - { - if ( isTabVisible.call( this, this._.tabIdList[ i % length ] ) ) - return this._.tabIdList[ i % length ]; - } - - return null; - } - - /** - * This is the base class for runtime dialog objects. An instance of this - * class represents a single named dialog for a single editor instance. - * @param {Object} editor The editor which created the dialog. - * @param {String} dialogName The dialog's registered name. - * @constructor - * @example - * var dialogObj = new CKEDITOR.dialog( editor, 'smiley' ); - */ - CKEDITOR.dialog = function( editor, dialogName ) - { - // Load the dialog definition. - var definition = CKEDITOR.dialog._.dialogDefinitions[ dialogName ]; - - // Completes the definition with the default values. - definition = CKEDITOR.tools.extend( definition( editor ), defaultDialogDefinition ); - - // 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 doc = CKEDITOR.document; - - var themeBuilt = editor.theme.buildDialog( editor ); - - // Initialize some basic parameters. - this._ = - { - editor : editor, - element : themeBuilt.element, - name : dialogName, - contentSize : { width : 0, height : 0 }, - size : { width : 0, height : 0 }, - updateSize : false, - 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. - this.parts.dialog.setStyles( - { - position : CKEDITOR.env.ie6Compat ? 'absolute' : 'fixed', - top : 0, - left: 0, - visibility : 'hidden' - }); - - // 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; - // 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 ) - { - if ( definition.onOk.call( this, evt ) === false ) - evt.data.hide = false; - }); - } - - 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 isValid = item.validate( this ); - - if ( typeof isValid == 'string' ) - { - alert( isValid ); - isValid = false; - } - - if ( isValid === false ) - { - if ( item.select ) - item.select(); - else - item.focus(); - - evt.data.hide = false; - evt.stop(); - return true; - } - } - }); - }, this, null, 0 ); - - this.on( 'cancel', function( evt ) - { - iterContents( function( item ) - { - if ( item.isChanged() ) - { - if ( !confirm( editor.lang.common.confirmCancel ) ) - 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; - } - - function changeFocus( forward ) - { - var focusList = me._.focusList, - offset = forward ? 1 : -1; - if ( focusList.length < 1 ) - return; - - var current = me._.currentFocusIndex; - - // Trigger the 'blur' event of any input element before anything, - // since certain UI updates may depend on it. - try - { - focusList[ current ].getInputElement().$.blur(); - } - catch( e ){} - - var startIndex = ( current + offset + focusList.length ) % focusList.length, - currentIndex = startIndex; - while ( !focusList[ currentIndex ].isFocusable() ) - { - currentIndex = ( currentIndex + offset + focusList.length ) % focusList.length; - if ( currentIndex == startIndex ) - break; - } - focusList[ currentIndex ].focus(); - - // Select whole field content. - if ( focusList[ currentIndex ].type == 'text' ) - focusList[ currentIndex ].select(); - } - - this.changeFocus = changeFocus; - - var processed; - - function focusKeydownHandler( 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'; - - processed = 0; - if ( keystroke == 9 || keystroke == CKEDITOR.SHIFT + 9 ) - { - var shiftPressed = ( keystroke == CKEDITOR.SHIFT + 9 ); - - // Handling Tab and Shift-Tab. - if ( me._.tabBarMode ) - { - // Change tabs. - var nextId = shiftPressed ? getPreviousVisibleTab.call( me ) : getNextVisibleTab.call( me ); - me.selectPage( nextId ); - me._.tabs[ nextId ][ 0 ].focus(); - } - else - { - // Change the focus of inputs. - changeFocus( !shiftPressed ); - } - - 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(); - processed = 1; - } - else if ( ( keystroke == 37 || keystroke == 39 ) && me._.tabBarMode ) - { - // Arrow keys - used for changing tabs. - nextId = ( keystroke == ( rtl ? 39 : 37 ) ? 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( true ); - processed = 1; - } - - if ( processed ) - { - evt.stop(); - evt.data.preventDefault(); - } - } - - function focusKeyPressHandler( evt ) - { - processed && evt.data.preventDefault(); - } - - var dialogElement = this._.element; - // Add the dialog keyboard handlers. - this.on( 'show', function() - { - dialogElement.on( 'keydown', focusKeydownHandler, this, null, 0 ); - // 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) - if ( CKEDITOR.env.opera || ( CKEDITOR.env.gecko && CKEDITOR.env.mac ) ) - dialogElement.on( 'keypress', focusKeyPressHandler, this ); - - } ); - this.on( 'hide', function() - { - dialogElement.removeListener( 'keydown', focusKeydownHandler ); - if ( CKEDITOR.env.opera || ( CKEDITOR.env.gecko && CKEDITOR.env.mac ) ) - dialogElement.removeListener( 'keypress', focusKeyPressHandler ); - } ); - this.on( 'iframeAdded', function( evt ) - { - var doc = new CKEDITOR.dom.document( evt.data.iframe.$.contentWindow.document ); - doc.on( 'keydown', focusKeydownHandler, 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(); - - if ( editor.config.dialog_startupFocusTab - && me._.tabIdList.length > 1 ) - { - me._.tabBarMode = true; - me._.tabs[ me._.currentTabId ][ 0 ].focus(); - } - else if ( !this._.hasFocus ) - { - this._.currentFocusIndex = -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( true ); - - /* - * IE BUG: If the initial focus went into a non-text element (e.g. button), - * then IE would still leave the caret inside the editing area. - */ - if ( this._.editor.mode == 'wysiwyg' && CKEDITOR.env.ie ) - { - var $selection = editor.document.$.selection, - $range = $selection.createRange(); - - if ( $range ) - { - if ( $range.parentElement && $range.parentElement().ownerDocument == editor.document.$ - || $range.item && $range.item( 0 ).ownerDocument == editor.document.$ ) - { - var $myRange = document.body.createTextRange(); - $myRange.moveToElementText( this.getElement().getFirst().$ ); - $myRange.collapse( true ); - $myRange.select(); - } - } - } - } - }, 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( evt ) - { - 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 ( var i = 0 ; i < definition.contents.length ; i++ ) - this.addPage( definition.contents[i] ); - - 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' ) ) - { - var id = target.$.id; - this.selectPage( id.substr( 0, id.lastIndexOf( '_' ) ) ); - if ( this._.tabBarMode ) - { - this._.tabBarMode = false; - this._.currentFocusIndex = -1; - changeFocus( true ); - } - 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]; - }; - - // 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' ); - } ); - } - - CKEDITOR.dialog.prototype = - { - destroy : function() - { - this.hide(); - this._.element.remove(); - }, - - /** - * Resizes the dialog. - * @param {Number} width The width of the dialog in pixels. - * @param {Number} height The height of the dialog in pixels. - * @function - * @example - * dialogObj.resize( 800, 640 ); - */ - resize : (function() - { - return function( width, height ) - { - if ( this._.contentSize && this._.contentSize.width == width && this._.contentSize.height == height ) - return; - - CKEDITOR.dialog.fire( 'resize', - { - dialog : this, - skin : this._.editor.skinName, - width : width, - height : height - }, this._.editor ); - - this._.contentSize = { width : width, height : height }; - this._.updateSize = true; - }; - })(), - - /** - * Gets the current size of the dialog in pixels. - * @returns {Object} An object with "width" and "height" properties. - * @example - * var width = dialogObj.getSize().width; - */ - getSize : function() - { - if ( !this._.updateSize ) - return this._.size; - var element = this._.element.getFirst(); - var size = this._.size = { width : element.$.offsetWidth || 0, height : element.$.offsetHeight || 0}; - - // If either the offsetWidth or offsetHeight is 0, the element isn't visible. - this._.updateSize = !size.width || !size.height; - - return size; - }, - - /** - * Moves the dialog to an (x, y) coordinate relative to the window. - * @function - * @param {Number} x The target x-coordinate. - * @param {Number} y The target y-coordinate. - * @example - * dialogObj.move( 10, 40 ); - */ - move : (function() - { - var isFixed; - return function( x, y ) - { - // The dialog may be fixed positioned or absolute positioned. Ask the - // browser what is the current situation first. - var element = this._.element.getFirst(); - if ( isFixed === undefined ) - isFixed = element.getComputedStyle( 'position' ) == 'fixed'; - - 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; - } - - element.setStyles( - { - 'left' : ( x > 0 ? x : 0 ) + 'px', - 'top' : ( y > 0 ? y : 0 ) + 'px' - }); - }; - })(), - - /** - * Gets the dialog's position in the window. - * @returns {Object} An object with "x" and "y" properties. - * @example - * var dialogX = dialogObj.getPosition().x; - */ - getPosition : function(){ return CKEDITOR.tools.extend( {}, this._.position ); }, - - /** - * Shows the dialog box. - * @example - * dialogObj.show(); - */ - show : function() - { - var editor = this._.editor; - if ( editor.mode == 'wysiwyg' && CKEDITOR.env.ie ) - { - var selection = editor.getSelection(); - selection && selection.lock(); - } - - // 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' ); - - // FIREFOX BUG: Fix vanishing caret for Firefox 2 or Gecko 1.8. - if ( CKEDITOR.env.gecko && CKEDITOR.env.version < 10900 ) - { - var dialogElement = this.parts.dialog; - dialogElement.setStyle( 'position', 'absolute' ); - setTimeout( function() - { - dialogElement.setStyle( 'position', 'fixed' ); - }, 0 ); - } - - - // First, set the dialog to an appropriate size. - this.resize( definition.minWidth, definition.minHeight ); - - // Select the first tab by default. - this.selectPage( this.definition.contents[0].id ); - - // Reset all inputs back to their default value. - this.reset(); - - // 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. - // Also register key handlers if first dialog. - if ( CKEDITOR.dialog._.currentTop === null ) - { - CKEDITOR.dialog._.currentTop = this; - this._.parentDialog = null; - showCover( this._.editor ); - - element.on( 'keydown', accessKeyDownHandler ); - element.on( CKEDITOR.env.opera ? 'keypress' : 'keyup', accessKeyUpHandler ); - - // Prevent some keys from bubbling up. (#4269) - for ( var event in { keyup :1, keydown :1, keypress :1 } ) - element.on( event, preventKeyBubbling ); - } - 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; - } - - // Register the Esc hotkeys. - registerAccessKey( this, this, '\x1b', null, function() - { - this.getButton( 'cancel' ) && this.getButton( 'cancel' ).click(); - } ); - - // Reset the hasFocus state. - this._.hasFocus = false; - - // Rearrange the dialog to the middle of the window. - CKEDITOR.tools.setTimeout( function() - { - var viewSize = CKEDITOR.document.getWindow().getViewPaneSize(); - var dialogSize = this.getSize(); - - // We're using definition size for initial position because of - // offten corrupted data in offsetWidth at this point. (#4084) - this.move( ( viewSize.width - definition.minWidth ) / 2, ( viewSize.height - dialogSize.height ) / 2 ); - - this.parts.dialog.setStyle( 'visibility', '' ); - - // Execute onLoad for the first show. - this.fireOnce( 'load', {} ); - this.fire( 'show', {} ); - this._.editor.fire( 'dialogShow', this ); - - // Save the initial values of the dialog. - this.foreach( function( contentObj ) { contentObj.setInitValue && contentObj.setInitValue(); } ); - - }, - 100, this ); - }, - - /** - * 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( this._.contents[i][j]); - } - return this; - }, - - /** - * Resets all input values in the dialog. - * @example - * dialogObj.reset(); - * @returns {CKEDITOR.dialog} The current dialog object. - */ - reset : (function() - { - var fn = function( widget ){ if ( widget.reset ) widget.reset(); }; - return function(){ this.foreach( fn ); return this; }; - })(), - - setupContent : function() - { - var args = arguments; - this.foreach( function( widget ) - { - if ( widget.setup ) - widget.setup.apply( widget, args ); - }); - }, - - commitContent : function() - { - var args = arguments; - this.foreach( function( widget ) - { - if ( widget.commit ) - widget.commit.apply( widget, args ); - }); - }, - - /** - * Hides the dialog box. - * @example - * dialogObj.hide(); - */ - hide : function() - { - if ( !this.parts.dialog.isVisible() ) - return; - - this.fire( 'hide', {} ); - this._.editor.fire( 'dialogHide', this ); - 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(); - 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( CKEDITOR.env.opera ? 'keypress' : 'keyup', accessKeyUpHandler ); - - // Remove bubbling-prevention handler. (#4269) - for ( var event in { keyup :1, keydown :1, keypress :1 } ) - element.removeListener( event, preventKeyBubbling ); - - var editor = this._.editor; - editor.focus(); - - if ( editor.mode == 'wysiwyg' && CKEDITOR.env.ie ) - { - var selection = editor.getSelection(); - selection && selection.unlock( true ); - } - } - else - CKEDITOR.dialog._.currentZIndex -= 10; - - delete this._.parentDialog; - // Reset the initial values of the dialog. - this.foreach( function( contentObj ) { contentObj.resetInitValue && contentObj.resetInitValue(); } ); - }, - - /** - * Adds a tabbed page into the dialog. - * @param {Object} contents Content definition. - * @example - */ - addPage : function( contents ) - { - var pageHtml = [], - titleHtml = contents.label ? ' title="' + CKEDITOR.tools.htmlEncode( contents.label ) + '"' : '', - elements = contents.elements, - 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%; height: 100%;' - }, pageHtml ); - - // 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 = 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.version >= 10900 && !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(); - - var contentMap = this._.contents[ contents.id ] = {}, - cursor, - children = vbox.getChild(); - - while ( ( cursor = children.shift() ) ) - { - contentMap[ cursor.id ] = cursor; - if ( typeof( cursor.getChild ) == 'function' ) - children.push.apply( children, cursor.getChild() ); - } - - // 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. - * @param {String} id The id of the dialog tab to be activated. - * @example - * dialogObj.selectPage( 'tab_1' ); - */ - selectPage : function( id ) - { - // 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' ); - 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. - * @param {String} id The page's Id. - * @example - * dialog.hidePage( 'tab_3' ); - */ - hidePage : function( id ) - { - var tab = this._.tabs[id] && this._.tabs[id][0]; - if ( !tab || this._.pageCount == 1 ) - 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. - * @param {String} id The page's Id. - * @example - * dialog.showPage( 'tab_2' ); - */ - 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. - * @returns {CKEDITOR.dom.element} The <span> element containing this dialog. - * @example - * var dialogElement = dialogObj.getElement().getFirst(); - * dialogElement.setStyle( 'padding', '5px' ); - */ - getElement : function() - { - return this._.element; - }, - - /** - * Gets the name of the dialog. - * @returns {String} The name of this dialog. - * @example - * var dialogName = dialogObj.getName(); - */ - getName : function() - { - return this._.name; - }, - - /** - * Gets a dialog UI element object from a dialog page. - * @param {String} pageId id of dialog page. - * @param {String} elementId id of UI element. - * @example - * @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. - * @param {String} pageId id of dialog page. - * @param {String} elementId id of UI element. - * @example - * @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. - * @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. - * @example - */ - 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. - * @param {String} id The id of the button. - * @example - * @returns {CKEDITOR.ui.dialog.button} The button object. - */ - getButton : function( id ) - { - return this._.buttons[ id ]; - }, - - /** - * Simulates a click to a dialog button in the dialog's button row. - * @param {String} id The id of the button. - * @example - * @returns The return value of the dialog's "click" event. - */ - click : function( id ) - { - return this._.buttons[ id ].click(); - }, - - /** - * Disables a dialog button. - * @param {String} id The id of the button. - * @example - */ - disableButton : function( id ) - { - return this._.buttons[ id ].disable(); - }, - - /** - * Enables a dialog button. - * @param {String} id The id of the button. - * @example - */ - 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++; - } - } - }; - - CKEDITOR.tools.extend( CKEDITOR.dialog, - /** - * @lends CKEDITOR.dialog - */ - { - /** - * Registers a dialog. - * @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.dialogDefinition}. - * @example - * @see CKEDITOR.dialog.dialogDefinition - */ - add : function( name, dialogDefinition ) - { - // Avoid path registration from multiple instances override definition. - if ( !this._.dialogDefinitions[name] - || typeof dialogDefinition == 'function' ) - this._.dialogDefinitions[name] = dialogDefinition; - }, - - exists : function( name ) - { - return !!this._.dialogDefinitions[ name ]; - }, - - getCurrent : function() - { - return CKEDITOR.dialog._.currentTop; - }, - - /** - * The default OK button for dialogs. Fires the "ok" event and closes the dialog if the event succeeds. - * @static - * @field - * @example - * @type Function - */ - 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 - * @field - * @example - * @type Function - */ - 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. - * @param {String} typeName The name of the UI element. - * @param {Function} builder The function to build the UI element. - * @example - */ - 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, true ); - - var defaultDialogDefinition = - { - resizable : CKEDITOR.DIALOG_RESIZE_BOTH, - minWidth : 600, - minHeight : 400, - buttons : [ CKEDITOR.dialog.okButton, CKEDITOR.dialog.cancelButton ] - }; - - // The buttons in MacOS Apps are in reverse order #4750 - CKEDITOR.env.mac && defaultDialogDefinition.buttons.reverse(); - - // 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. - * @constructor - * @name CKEDITOR.dialog.dialogDefinitionObject - * @extends CKEDITOR.dialog.dialogDefinition - * @example - * CKEDITOR.on( 'dialogDefinition', function( evt ) - * { - * var definition = evt.data.definition; - * var content = definition.getContents( 'page1' ); - * ... - * } ); - */ - 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 ] = new contentObject( dialog, content ); - - CKEDITOR.tools.extend( this, dialogDefinition ); - }; - - definitionObject.prototype = - /** @lends CKEDITOR.dialog.dialogDefinitionObject.prototype */ - { - /** - * Gets a content definition. - * @param {String} id The id of the content definition. - * @returns {CKEDITOR.dialog.contentDefinition} 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.buttonDefinition} 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.contentDefinition} 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.contentDefinition} 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.buttonDefinition} 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.buttonDefinition} 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.contentDefinition} 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.buttonDefinition} 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.dialogDefinitionObject. - * @constructor - * @name CKEDITOR.dialog.contentDefinitionObject - * @example - * CKEDITOR.on( 'dialogDefinition', function( evt ) - * { - * var definition = evt.data.definition; - * var content = definition.getContents( 'page1' ); - * content.remove( 'textInput1' ); - * ... - * } ); - */ - function contentObject( dialog, contentDefinition ) - { - this._ = - { - dialog : dialog - }; - - CKEDITOR.tools.extend( this, contentDefinition ); - } - - contentObject.prototype = - /** @lends CKEDITOR.dialog.contentDefinitionObject.prototype */ - { - /** - * Gets a UI element definition under the content definition. - * @param {String} id The id of the UI element definition. - * @returns {CKEDITOR.dialog.uiElementDefinition} - */ - get : function( id ) - { - return getById( this.elements, id, 'children' ); - }, - - /** - * Adds a UI element definition to the content definition. - * @param {CKEDITOR.dialog.uiElementDefinition} 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.uiElementDefinition} 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.uiElementDefinition} The element - * definition removed. - * @example - */ - remove : function( id ) - { - removeById( this.elements, id, 'children' ); - } - }; - - function initDragAndDrop( dialog ) - { - var lastCoords = null, - abstractDialogCoords = null, - element = dialog.getElement().getFirst(), - editor = dialog.getParentEditor(), - magnetDistance = editor.config.dialog_magnetDistance, - margins = editor.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.data.$.screenX, - y = evt.data.$.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 + 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 ); - - evt.data.preventDefault(); - } - - function mouseUpHandler( evt ) - { - CKEDITOR.document.removeListener( 'mousemove', mouseMoveHandler ); - CKEDITOR.document.removeListener( 'mouseup', mouseUpHandler ); - - if ( CKEDITOR.env.ie6Compat ) - { - var coverDoc = currentCover.getChild( 0 ).getFrameDocument(); - coverDoc.removeListener( 'mousemove', mouseMoveHandler ); - coverDoc.removeListener( 'mouseup', mouseUpHandler ); - } - } - - dialog.parts.title.on( 'mousedown', function( evt ) - { - dialog._.updateSize = true; - - lastCoords = { x : evt.data.$.screenX, y : evt.data.$.screenY }; - - CKEDITOR.document.on( 'mousemove', mouseMoveHandler ); - CKEDITOR.document.on( 'mouseup', mouseUpHandler ); - abstractDialogCoords = dialog.getPosition(); - - if ( CKEDITOR.env.ie6Compat ) - { - var coverDoc = currentCover.getChild( 0 ).getFrameDocument(); - coverDoc.on( 'mousemove', mouseMoveHandler ); - coverDoc.on( 'mouseup', mouseUpHandler ); - } - - evt.data.preventDefault(); - }, dialog ); - } - - function initResizeHandles( dialog ) - { - var definition = dialog.definition, - minWidth = definition.minWidth || 0, - minHeight = definition.minHeight || 0, - resizable = definition.resizable, - margins = dialog.getParentEditor().skin.margins || [ 0, 0, 0, 0 ]; - - function topSizer( coords, dy ) - { - coords.y += dy; - } - - function rightSizer( coords, dx ) - { - coords.x2 += dx; - } - - function bottomSizer( coords, dy ) - { - coords.y2 += dy; - } - - function leftSizer( coords, dx ) - { - coords.x += dx; - } - - var lastCoords = null, - abstractDialogCoords = null, - magnetDistance = dialog._.editor.config.magnetDistance, - parts = [ 'tl', 't', 'tr', 'l', 'r', 'bl', 'b', 'br' ]; - - function mouseDownHandler( evt ) - { - var partName = evt.listenerData.part, size = dialog.getSize(); - abstractDialogCoords = dialog.getPosition(); - CKEDITOR.tools.extend( abstractDialogCoords, - { - x2 : abstractDialogCoords.x + size.width, - y2 : abstractDialogCoords.y + size.height - } ); - lastCoords = { x : evt.data.$.screenX, y : evt.data.$.screenY }; - - CKEDITOR.document.on( 'mousemove', mouseMoveHandler, dialog, { part : partName } ); - CKEDITOR.document.on( 'mouseup', mouseUpHandler, dialog, { part : partName } ); - - if ( CKEDITOR.env.ie6Compat ) - { - var coverDoc = currentCover.getChild( 0 ).getFrameDocument(); - coverDoc.on( 'mousemove', mouseMoveHandler, dialog, { part : partName } ); - coverDoc.on( 'mouseup', mouseUpHandler, dialog, { part : partName } ); - } - - evt.data.preventDefault(); - } - - function mouseMoveHandler( evt ) - { - var x = evt.data.$.screenX, - y = evt.data.$.screenY, - dx = x - lastCoords.x, - dy = y - lastCoords.y, - viewPaneSize = CKEDITOR.document.getWindow().getViewPaneSize(), - partName = evt.listenerData.part; - - if ( partName.search( 't' ) != -1 ) - topSizer( abstractDialogCoords, dy ); - if ( partName.search( 'l' ) != -1 ) - leftSizer( abstractDialogCoords, dx ); - if ( partName.search( 'b' ) != -1 ) - bottomSizer( abstractDialogCoords, dy ); - if ( partName.search( 'r' ) != -1 ) - rightSizer( abstractDialogCoords, dx ); - - lastCoords = { x : x, y : y }; - - var realX, realY, realX2, realY2; - - if ( abstractDialogCoords.x + margins[3] < magnetDistance ) - realX = - margins[3]; - else if ( partName.search( 'l' ) != -1 && abstractDialogCoords.x2 - abstractDialogCoords.x < minWidth + magnetDistance ) - realX = abstractDialogCoords.x2 - minWidth; - else - realX = abstractDialogCoords.x; - - if ( abstractDialogCoords.y + margins[0] < magnetDistance ) - realY = - margins[0]; - else if ( partName.search( 't' ) != -1 && abstractDialogCoords.y2 - abstractDialogCoords.y < minHeight + magnetDistance ) - realY = abstractDialogCoords.y2 - minHeight; - else - realY = abstractDialogCoords.y; - - if ( abstractDialogCoords.x2 - margins[1] > viewPaneSize.width - magnetDistance ) - realX2 = viewPaneSize.width + margins[1] ; - else if ( partName.search( 'r' ) != -1 && abstractDialogCoords.x2 - abstractDialogCoords.x < minWidth + magnetDistance ) - realX2 = abstractDialogCoords.x + minWidth; - else - realX2 = abstractDialogCoords.x2; - - if ( abstractDialogCoords.y2 - margins[2] > viewPaneSize.height - magnetDistance ) - realY2= viewPaneSize.height + margins[2] ; - else if ( partName.search( 'b' ) != -1 && abstractDialogCoords.y2 - abstractDialogCoords.y < minHeight + magnetDistance ) - realY2 = abstractDialogCoords.y + minHeight; - else - realY2 = abstractDialogCoords.y2 ; - - dialog.move( realX, realY ); - dialog.resize( realX2 - realX, realY2 - realY ); - - evt.data.preventDefault(); - } - - function mouseUpHandler( evt ) - { - CKEDITOR.document.removeListener( 'mouseup', mouseUpHandler ); - CKEDITOR.document.removeListener( 'mousemove', mouseMoveHandler ); - - if ( CKEDITOR.env.ie6Compat ) - { - var coverDoc = currentCover.getChild( 0 ).getFrameDocument(); - coverDoc.removeListener( 'mouseup', mouseUpHandler ); - coverDoc.removeListener( 'mousemove', mouseMoveHandler ); - } - } - -// TODO : Simplify the resize logic, having just a single resize grip
. -// var widthTest = /[lr]/, -// heightTest = /[tb]/; -// for ( var i = 0 ; i < parts.length ; i++ ) -// { -// var element = dialog.parts[ parts[i] + '_resize' ]; -// if ( resizable == CKEDITOR.DIALOG_RESIZE_NONE || -// resizable == CKEDITOR.DIALOG_RESIZE_HEIGHT && widthTest.test( parts[i] ) || -// resizable == CKEDITOR.DIALOG_RESIZE_WIDTH && heightTest.test( parts[i] ) ) -// { -// element.hide(); -// continue; -// } -// element.on( 'mousedown', mouseDownHandler, dialog, { part : parts[i] } ); -// } - } - - var resizeCover; - // Caching resuable covers and allowing only one cover - // on screen. - var covers = {}, - currentCover; - - function showCover( editor ) - { - var win = CKEDITOR.document.getWindow(); - var backgroundColorStyle = editor.config.dialog_backgroundCoverColor || 'white', - backgroundCoverOpacity = editor.config.dialog_backgroundCoverOpacity, - baseFloatZIndex = editor.config.baseFloatZIndex, - coverKey = CKEDITOR.tools.genKey( - backgroundColorStyle, - backgroundCoverOpacity, - baseFloatZIndex ), - coverElement = covers[ coverKey ]; - - if ( !coverElement ) - { - var html = [ - '
' - ]; - - if ( CKEDITOR.env.ie6Compat ) - { - // Support for custom document.domain in IE. - var isCustomDomain = CKEDITOR.env.isCustomDomain(), - iframeHtml = ''; - - html.push( - '' + - '' ); - } - - html.push( '
' ); - - coverElement = CKEDITOR.dom.element.createFromHtml( html.join( '' ) ); - coverElement.setOpacity( backgroundCoverOpacity != undefined ? backgroundCoverOpacity : 0.5 ); - - coverElement.appendTo( CKEDITOR.document.getBody() ); - covers[ coverKey ] = coverElement; - } - else - coverElement. show(); - - 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' - }); - - do - { - var dialogPos = cursor.getPosition(); - cursor.move( dialogPos.x, dialogPos.y ); - } while ( ( cursor = cursor._.parentDialog ) ); - }; - - resizeCover = resizeFunc; - win.on( 'resize', resizeFunc ); - resizeFunc(); - 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() - { - if ( !currentCover ) - return; - - 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( dialog, key ) - { - }; - - // ESC, ENTER - var preventKeyBubblingKeys = { 27 :1, 13 :1 }; - var preventKeyBubbling = function( e ) - { - if ( e.data.getKeystroke() in preventKeyBubblingKeys ) - e.data.stopPropagation(); - }; - - (function() - { - CKEDITOR.ui.dialog = - { - /** - * The base class of all dialog UI elements. - * @constructor - * @param {CKEDITOR.dialog} dialog Parent dialog object. - * @param {CKEDITOR.dialog.uiElementDefinition} 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 - * A function returning a string, or a simple string for the node name for - * the root DOM node. Default is 'div'. - * @param {Function|Object} stylesArg - * A function returning an object, or a simple object for CSS styles applied - * to the DOM node. Default is empty object. - * @param {Function|Object} attributesArg - * A fucntion returning an object, or a simple object for attributes applied - * to the DOM node. Default is empty object. - * @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. - * @example - */ - 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.getNextNumber() + '_uiElement', - id = this.id = elementDefinition.id, - i; - - // 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; - 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( ';' ); - 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; - - // 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() - { - if ( me.getInputElement() ) - { - me.getInputElement().on( 'focus', function() - { - dialog._.tabBarMode = false; - dialog._.hasFocus = true; - me.fire( 'focus' ); - }, me ); - } - } ); - - // 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; - } ); - } - - // Completes this object with everything we have in the - // definition. - CKEDITOR.tools.extend( this, elementDefinition ); - }, - - /** - * Horizontal layout box for dialog UI elements, auto-expends to available width of container. - * @constructor - * @extends CKEDITOR.ui.dialog.uiElement - * @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.uiElementDefinition} 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 - *
  • - *
- * @example - */ - 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. - * @constructor - * @extends CKEDITOR.ui.dialog.hbox - * @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.uiElementDefinition} 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.
  • - *
- * @example - */ - 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 ); - } - }; - })(); - - CKEDITOR.ui.dialog.uiElement.prototype = - { - /** - * Gets the root DOM element of this dialog UI object. - * @returns {CKEDITOR.dom.element} Root DOM element of UI object. - * @example - * uiElement.getElement().hide(); - */ - getElement : function() - { - return CKEDITOR.document.getById( this.domId ); - }, - - /** - * Gets the DOM element that the user inputs values. - * This function is used by setValue(), getValue() and focus(). It should - * be overrided in child classes where the input element isn't the root - * element. - * @returns {CKEDITOR.dom.element} The element where the user input values. - * @example - * var rawValue = textInput.getInputElement().$.value; - */ - getInputElement : function() - { - return this.getElement(); - }, - - /** - * Gets the parent dialog object containing this UI element. - * @returns {CKEDITOR.dialog} Parent dialog object. - * @example - * var dialog = uiElement.getDialog(); - */ - getDialog : function() - { - return this._.dialog; - }, - - /** - * Sets the value of this dialog UI object. - * @param {Object} value The new value. - * @returns {CKEDITOR.dialog.uiElement} The current UI element. - * @example - * uiElement.setValue( 'Dingo' ); - */ - setValue : function( value ) - { - this.getInputElement().setValue( value ); - this.fire( 'change', { value : value } ); - return this; - }, - - /** - * Gets the current value of this dialog UI object. - * @returns {Object} The current value. - * @example - * var myValue = uiElement.getValue(); - */ - getValue : function() - { - return this.getInputElement().getValue(); - }, - - /** - * Tells whether the UI object's value has changed. - * @returns {Boolean} true if changed, false if not changed. - * @example - * if ( uiElement.isChanged() ) - *   confirm( 'Value changed! Continue?' ); - */ - isChanged : function() - { - // Override in input classes. - return false; - }, - - /** - * Selects the parent tab of this element. Usually called by focus() or overridden focus() methods. - * @returns {CKEDITOR.dialog.uiElement} The current UI element. - * @example - * focus : function() - * { - * this.selectParentTab(); - * // do something else. - * } - */ - selectParentTab : function() - { - var element = this.getInputElement(), - cursor = element, - tabId; - while ( ( cursor = cursor.getParent() ) && cursor.$.className.search( 'cke_dialog_page_contents' ) == -1 ) - { /*jsl:pass*/ } - - // 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. - * @returns {CKEDITOR.dialog.uiElement} The current UI element. - * @example - * uiElement.focus(); - */ - 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. - *
  3. - * 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 CKEDITOR.ui.dialog.uiElement#getInputElement}). - *
  4. - *
- * This function is only called at UI element instantiation, but can - * be overridded in child classes if they require more flexibility. - * @param {CKEDITOR.dialog.uiElementDefinition} definition The UI element - * definition. - * @returns {CKEDITOR.dialog.uiElement} The current UI element. - * @example - */ - 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. - *
  3. onShow - Called whenever the element's parent dialog opens.
  4. - *
  5. onHide - Called whenever the element's parent dialog closes.
  6. - *
- * @field - * @type Object - * @example - * // 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 ); - */ - 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. - * @example - */ - accessKeyDown : function( dialog, key ) - { - 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. - * @example - */ - accessKeyUp : function( dialog, key ) - { - }, - - /** - * Disables a UI element. - * @example - */ - disable : function() - { - var element = this.getInputElement(); - element.setAttribute( 'disabled', 'true' ); - element.addClass( 'cke_disabled' ); - }, - - /** - * Enables a UI element. - * @example - */ - enable : function() - { - var element = this.getInputElement(); - element.removeAttribute( 'disabled' ); - element.removeClass( 'cke_disabled' ); - }, - - /** - * Determines whether an UI element is enabled or not. - * @returns {Boolean} Whether the UI element is enabled. - * @example - */ - isEnabled : function() - { - return !this.getInputElement().getAttribute( 'disabled' ); - }, - - /** - * Determines whether an UI element is visible or not. - * @returns {Boolean} Whether the UI element is visible. - * @example - */ - 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. - * @example - */ - isFocusable : function() - { - if ( !this.isEnabled() || !this.isVisible() ) - return false; - return true; - } - }; - - CKEDITOR.ui.dialog.hbox.prototype = CKEDITOR.tools.extend( new CKEDITOR.ui.dialog.uiElement, - /** - * @lends CKEDITOR.ui.dialog.hbox.prototype - */ - { - /** - * Gets a child UI element inside this container. - * @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. - * @example - * var checkbox = hbox.getChild( [0,1] ); - * checkbox.setValue( true ); - */ - 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. - * @constructor - * @augments CKEDITOR.commandDefinition - * @param {string} dialogName The name of the dialog to open when executing - * this command. - * @example - * // Register the "link" command, which opens the "link" dialog. - * editor.addCommand( 'link', new CKEDITOR.dialogCommand( 'link' ) ); - */ - CKEDITOR.dialogCommand = function( dialogName ) - { - this.dialogName = dialogName; - }; - - CKEDITOR.dialogCommand.prototype = - { - /** @ignore */ - 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 : CKEDITOR.env.ie || CKEDITOR.env.webkit - }; - - (function() - { - var notEmptyRegex = /^([a]|[^a])+$/, - integerRegex = /^\d*$/, - numberRegex = /^\d*(?:\.\d+)?$/; - - CKEDITOR.VALIDATE_OR = 1; - CKEDITOR.VALIDATE_AND = 2; - - CKEDITOR.dialog.validate = - { - functions : function() - { - 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() : arguments[0]; - - var msg = undefined, - relation = CKEDITOR.VALIDATE_AND, - functions = [], i; - - for ( i = 0 ; i < arguments.length ; i++ ) - { - if ( typeof( arguments[i] ) == 'function' ) - functions.push( arguments[i] ); - else - break; - } - - if ( i < arguments.length && typeof( arguments[i] ) == 'string' ) - { - msg = arguments[i]; - i++; - } - - if ( i < arguments.length && typeof( arguments[i]) == 'number' ) - relation = arguments[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 ); - } - - if ( !passed ) - { - if ( msg !== undefined ) - alert( msg ); - if ( this && ( this.select || this.focus ) ) - ( this.select || this.focus )(); - return false; - } - - return 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]; - if ( !regex.test( value ) ) - { - if ( msg !== undefined ) - alert( msg ); - if ( this && ( this.select || this.focus ) ) - { - if ( this.select ) - this.select(); - else - this.focus(); - } - return false; - } - return 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 ); - }, - - 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, - /** @lends CKEDITOR.editor.prototype */ - { - /** - * Loads and opens a registered dialog. - * @param {String} dialogName The registered name of the dialog. - * @param {Function} callback The function to be invoked after dialog instance created. - * @see CKEDITOR.dialog.add - * @example - * CKEDITOR.instances.editor1.openDialog( 'smiley' ); - * @returns {CKEDITOR.dialog} The dialog object corresponding to the dialog displayed. null if the dialog name is not registered. - */ - openDialog : function( dialogName, callback ) - { - var dialogDefinitions = CKEDITOR.dialog._.dialogDefinitions[ dialogName ], - dialogSkin = this.skin.dialog; - - // If the dialogDefinition is already loaded, open it immediately. - if ( typeof dialogDefinitions == 'function' && dialogSkin._isLoaded ) - { - var storedDialogs = this._.storedDialogs || - ( this._.storedDialogs = {} ); - - var dialog = storedDialogs[ dialogName ] || - ( storedDialogs[ dialogName ] = new CKEDITOR.dialog( this, dialogName ) ); - - callback && callback.call( dialog, dialog ); - dialog.show(); - - return dialog; - } - else if ( dialogDefinitions == 'failed' ) - throw new Error( '[CKEDITOR.dialog.openDialog] Dialog "' + dialogName + '" failed when loading definition.' ); - - // Not loaded? Load the .js file first. - var body = CKEDITOR.document.getBody(), - cursor = body.$.style.cursor, - me = this; - - body.setStyle( 'cursor', 'wait' ); - - function onDialogFileLoaded( success ) - { - var dialogDefinition = CKEDITOR.dialog._.dialogDefinitions[ dialogName ], - skin = me.skin.dialog; - - // Check if both skin part and definition is loaded. - if ( !skin._isLoaded || loadDefinition && typeof success == 'undefined' ) - return; - - // In case of plugin error, mark it as loading failed. - if ( typeof dialogDefinition != 'function' ) - CKEDITOR.dialog._.dialogDefinitions[ dialogName ] = 'failed'; - - me.openDialog( dialogName, callback ); - body.setStyle( 'cursor', cursor ); - } - - if ( typeof dialogDefinitions == 'string' ) - { - var loadDefinition = 1; - CKEDITOR.scriptLoader.load( CKEDITOR.getUrl( dialogDefinitions ), onDialogFileLoaded ); - } - - CKEDITOR.skins.load( this, 'dialog', onDialogFileLoaded ); - - return null; - } - }); - -CKEDITOR.plugins.add( 'dialog', - { - requires : [ 'dialogui' ] - }); - -// Dialog related configurations. - -/** - * The color of the dialog background cover. It should be a valid CSS color - * string. - * @name CKEDITOR.config.dialog_backgroundCoverColor - * @type String - * @default 'white' - * @example - * config.dialog_backgroundCoverColor = 'rgb(255, 254, 253)'; - */ - -/** - * The opacity of the dialog background cover. It should be a number within the - * range [0.0, 1.0]. - * @name CKEDITOR.config.dialog_backgroundCoverOpacity - * @type Number - * @default 0.5 - * @example - * config.dialog_backgroundCoverOpacity = 0.7; - */ - -/** - * If the dialog has more than one tab, put focus into the first tab as soon as dialog is opened. - * @name CKEDITOR.config.dialog_startupFocusTab - * @type Boolean - * @default false - * @example - * config.dialog_startupFocusTab = true; - */ - -/** - * The distance of magnetic borders used in moving and resizing dialogs, - * measured in pixels. - * @name CKEDITOR.config.dialog_magnetDistance - * @type Number - * @default 20 - * @example - * config.dialog_magnetDistance = 30; - */ - -/** - * 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.

- * @name CKEDITOR#dialogDefinition - * @event - * @param {CKEDITOR.dialog.dialogDefinition} data The dialog defination that - * is being loaded. - * @param {CKEDITOR.editor} editor The editor instance that will use the - * dialog. - */ diff --git a/lib/ckeditor/_source/plugins/dialogui/plugin.js b/lib/ckeditor/_source/plugins/dialogui/plugin.js deleted file mode 100644 index fc3a7f4..0000000 --- a/lib/ckeditor/_source/plugins/dialogui/plugin.js +++ /dev/null @@ -1,1415 +0,0 @@ -/* -Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved. -For licensing, see LICENSE.html or http://ckeditor.com/license -*/ - -/** @fileoverview The "dialogui" plugin. */ - -CKEDITOR.plugins.add( 'dialogui' ); - -(function() -{ - var initPrivateObject = function( elementDefinition ) - { - this._ || ( this._ = {} ); - this._['default'] = this._.initValue = elementDefinition['default'] || ''; - this._.required = elementDefinition[ 'required' ] || false; - var args = [ this._ ]; - for ( var i = 1 ; i < arguments.length ; i++ ) - args.push( arguments[i] ); - args.push( true ); - CKEDITOR.tools.extend.apply( CKEDITOR.tools, args ); - return this._; - }, - textBuilder = - { - build : function( dialog, elementDefinition, output ) - { - return new CKEDITOR.ui.dialog.textInput( dialog, elementDefinition, output ); - } - }, - commonBuilder = - { - build : function( dialog, elementDefinition, output ) - { - return new CKEDITOR.ui.dialog[elementDefinition.type]( dialog, elementDefinition, output ); - } - }, - containerBuilder = - { - 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 ); - } - }, - commonPrototype = - { - isChanged : function() - { - return this.getValue() != this.getInitValue(); - }, - - reset : function() - { - this.setValue( this.getInitValue() ); - }, - - setInitValue : function() - { - this._.initValue = this.getValue(); - }, - - resetInitValue : function() - { - this._.initValue = this._['default']; - }, - - getInitValue : function() - { - return this._.initValue; - } - }, - commonEventProcessors = CKEDITOR.tools.extend( {}, CKEDITOR.ui.dialog.uiElement.prototype.eventProcessors, - { - onChange : function( dialog, func ) - { - if ( !this._.domOnChangeRegistered ) - { - dialog.on( 'load', function() - { - this.getInputElement().on( 'change', function() - { - // Make sure 'onchange' doesn't get fired after dialog closed. (#5719) - if ( !dialog.parts.dialog.isVisible() ) - return; - - this.fire( 'change', { value : this.getValue() } ); - }, this ); - }, this ); - this._.domOnChangeRegistered = true; - } - - this.on( 'change', func ); - } - }, true ), - eventRegex = /^on([A-Z]\w+)/, - cleanInnerDefinition = function( def ) - { - // An inner UI element should not have the parent's type, title or events. - for ( var i in def ) - { - if ( eventRegex.test( i ) || i == 'title' || i == 'type' ) - delete def[i]; - } - return def; - }; - - CKEDITOR.tools.extend( CKEDITOR.ui.dialog, - /** @lends CKEDITOR.ui.dialog */ - { - /** - * Base class for all dialog elements with a textual label on the left. - * @constructor - * @example - * @extends CKEDITOR.ui.dialog.uiElement - * @param {CKEDITOR.dialog} dialog - * Parent dialog object. - * @param {CKEDITOR.dialog.uiElementDefinition} elementDefinition - * The element definition. Accepted fields: - *
    - *
  • label (Required) The label string.
  • - *
  • labelLayout (Optional) Put 'horizontal' here if the - * label element is to be layed out horizontally. Otherwise a vertical - * layout will be used.
  • - *
  • widths (Optional) This applies only for horizontal - * layouts - an 2-element array of lengths to specify the widths of the - * label and the content element.
  • - *
- * @param {Array} htmlList - * List of HTML code to output to. - * @param {Function} contentHtml - * A function returning the HTML code string to be added inside the content - * cell. - */ - labeledElement : function( dialog, elementDefinition, htmlList, contentHtml ) - { - if ( arguments.length < 4 ) - return; - - var _ = initPrivateObject.call( this, elementDefinition ); - _.labelId = CKEDITOR.tools.getNextNumber() + '_label'; - var children = this._.children = []; - /** @ignore */ - var innerHTML = function() - { - var html = []; - if ( elementDefinition.labelLayout != 'horizontal' ) - html.push( '', - '' ); - else - { - var hboxDefinition = { - type : 'hbox', - widths : elementDefinition.widths, - padding : 0, - children : - [ - { - type : 'html', - html : '