diff --git a/oss/vtiger/trunk/include/ckeditor/_source/adapters/jquery.js b/oss/vtiger/trunk/include/ckeditor/_source/adapters/jquery.js new file mode 100644 index 00000000..e633758c --- /dev/null +++ b/oss/vtiger/trunk/include/ckeditor/_source/adapters/jquery.js @@ -0,0 +1,297 @@ +/* +Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.html or http://ckeditor.com/license +*/ + +/** + * @fileOverview jQuery adapter provides easy use of basic CKEditor functions + * and access to internal API. It also integrates some aspects of CKEditor with + * jQuery framework. + * + * Every TEXTAREA, DIV and P elements can be converted to working editor. + * + * Plugin exposes some of editor's event to jQuery event system. All of those are namespaces inside + * ".ckeditor" namespace and can be binded/listened on supported textarea, div and p nodes. + * + * Available jQuery events: + * - instanceReady.ckeditor( editor, rootNode ) + * Triggered when new instance is ready. + * - destroy.ckeditor( editor ) + * Triggered when instance is destroyed. + * - getData.ckeditor( editor, eventData ) + * Triggered when getData event is fired inside editor. It can change returned data using eventData reference. + * - setData.ckeditor( editor ) + * Triggered when getData event is fired inside editor. + * + * @example + * + * + * + */ + +(function() +{ + /** + * Allow CKEditor to override jQuery.fn.val(). This results in ability to use val() + * function on textareas as usual and having those calls synchronized with CKEditor + * Rich Text Editor component. + * + * This config option is global and executed during plugin load. + * Can't be customized across editor instances. + * + * @type Boolean + * @example + * $( 'textarea' ).ckeditor(); + * // ... + * $( 'textarea' ).val( 'New content' ); + */ + CKEDITOR.config.jqueryOverrideVal = typeof CKEDITOR.config.jqueryOverrideVal == 'undefined' + ? true : CKEDITOR.config.jqueryOverrideVal; + + var jQuery = window.jQuery; + + if ( typeof jQuery == 'undefined' ) + return; + + // jQuery object methods. + jQuery.extend( jQuery.fn, + /** @lends jQuery.fn */ + { + /** + * Return existing CKEditor instance for first matched element. + * Allows to easily use internal API. Doesn't return jQuery object. + * + * Raised exception if editor doesn't exist or isn't ready yet. + * + * @name jQuery.ckeditorGet + * @return CKEDITOR.editor + * @see CKEDITOR.editor + */ + ckeditorGet: function() + { + var instance = this.eq( 0 ).data( 'ckeditorInstance' ); + if ( !instance ) + throw "CKEditor not yet initialized, use ckeditor() with callback."; + return instance; + }, + /** + * Triggers creation of CKEditor in all matched elements (reduced to DIV, P and TEXTAREAs). + * Binds callback to instanceReady event of all instances. If editor is already created, than + * callback is fired right away. + * + * Mixed parameter order allowed. + * + * @param callback Function to be run on editor instance. Passed parameters: [ textarea ]. + * Callback is fiered in "this" scope being ckeditor instance and having source textarea as first param. + * + * @param config Configuration options for new instance(s) if not already created. + * See URL + * + * @example + * $( 'textarea' ).ckeditor( function( textarea ) { + * $( textarea ).val( this.getData() ) + * } ); + * + * @name jQuery.fn.ckeditor + * @return jQuery.fn + */ + ckeditor: function( callback, config ) + { + if ( !jQuery.isFunction( callback )) + { + var tmp = config; + config = callback; + callback = tmp; + } + config = config || {}; + + this.filter( 'textarea, div, p' ).each( function() + { + var $element = jQuery( this ), + editor = $element.data( 'ckeditorInstance' ), + instanceLock = $element.data( '_ckeditorInstanceLock' ), + element = this; + + if ( editor && !instanceLock ) + { + if ( callback ) + callback.apply( editor, [ this ] ); + } + else if ( !instanceLock ) + { + // CREATE NEW INSTANCE + + // Handle config.autoUpdateElement inside this plugin if desired. + if ( config.autoUpdateElement + || ( typeof config.autoUpdateElement == 'undefined' && CKEDITOR.config.autoUpdateElement ) ) + { + config.autoUpdateElementJquery = true; + } + + // Always disable config.autoUpdateElement. + config.autoUpdateElement = false; + $element.data( '_ckeditorInstanceLock', true ); + + // Set instance reference in element's data. + editor = CKEDITOR.replace( element, config ); + $element.data( 'ckeditorInstance', editor ); + + // Register callback. + editor.on( 'instanceReady', function( event ) + { + var editor = event.editor; + setTimeout( function() + { + // Delay bit more if editor is still not ready. + if ( !editor.element ) + { + setTimeout( arguments.callee, 100 ); + return; + } + + // Remove this listener. + event.removeListener( 'instanceReady', this.callee ); + + // Forward setData on dataReady. + editor.on( 'dataReady', function() + { + $element.trigger( 'setData' + '.ckeditor', [ editor ] ); + }); + + // Forward getData. + editor.on( 'getData', function( event ) { + $element.trigger( 'getData' + '.ckeditor', [ editor, event.data ] ); + }, 999 ); + + // Forward destroy event. + editor.on( 'destroy', function() + { + $element.trigger( 'destroy.ckeditor', [ editor ] ); + }); + + // Integrate with form submit. + if ( editor.config.autoUpdateElementJquery && $element.is( 'textarea' ) && $element.parents( 'form' ).length ) + { + var onSubmit = function() + { + $element.ckeditor( function() + { + editor.updateElement(); + }); + }; + + // Bind to submit event. + $element.parents( 'form' ).submit( onSubmit ); + + // Bind to form-pre-serialize from jQuery Forms plugin. + $element.parents( 'form' ).bind( 'form-pre-serialize', onSubmit ); + + // Unbind when editor destroyed. + $element.bind( 'destroy.ckeditor', function() + { + $element.parents( 'form' ).unbind( 'submit', onSubmit ); + $element.parents( 'form' ).unbind( 'form-pre-serialize', onSubmit ); + }); + } + + // Garbage collect on destroy. + editor.on( 'destroy', function() + { + $element.data( 'ckeditorInstance', null ); + }); + + // Remove lock. + $element.data( '_ckeditorInstanceLock', null ); + + // Fire instanceReady event. + $element.trigger( 'instanceReady.ckeditor', [ editor ] ); + + // Run given (first) code. + if ( callback ) + callback.apply( editor, [ element ] ); + }, 0 ); + }, null, null, 9999); + } + else + { + // Editor is already during creation process, bind our code to the event. + CKEDITOR.on( 'instanceReady', function( event ) + { + var editor = event.editor; + setTimeout( function() + { + // Delay bit more if editor is still not ready. + if ( !editor.element ) + { + setTimeout( arguments.callee, 100 ); + return; + } + + if ( editor.element.$ == element ) + { + // Run given code. + if ( callback ) + callback.apply( editor, [ element ] ); + } + }, 0 ); + }, null, null, 9999); + } + }); + return this; + } + }); + + // New val() method for objects. + if ( CKEDITOR.config.jqueryOverrideVal ) + { + jQuery.fn.val = CKEDITOR.tools.override( jQuery.fn.val, function( oldValMethod ) + { + /** + * CKEditor-aware val() method. + * + * Acts same as original jQuery val(), but for textareas which have CKEditor instances binded to them, method + * returns editor's content. It also works for settings values. + * + * @param oldValMethod + * @name jQuery.fn.val + */ + return function( newValue, forceNative ) + { + var isSetter = typeof newValue != 'undefined', + result; + + this.each( function() + { + var $this = jQuery( this ), + editor = $this.data( 'ckeditorInstance' ); + + if ( !forceNative && $this.is( 'textarea' ) && editor ) + { + if ( isSetter ) + editor.setData( newValue ); + else + { + result = editor.getData(); + // break; + return null; + } + } + else + { + if ( isSetter ) + oldValMethod.call( $this, newValue ); + else + { + result = oldValMethod.call( $this ); + // break; + return null; + } + } + + return true; + }); + return isSetter ? this : result; + }; + }); + } +})(); diff --git a/oss/vtiger/trunk/include/ckeditor/_source/core/_bootstrap.js b/oss/vtiger/trunk/include/ckeditor/_source/core/_bootstrap.js new file mode 100644 index 00000000..f351ce61 --- /dev/null +++ b/oss/vtiger/trunk/include/ckeditor/_source/core/_bootstrap.js @@ -0,0 +1,91 @@ +/* +Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.html or http://ckeditor.com/license +*/ + +/** + * @fileOverview API initialization code. + */ + +(function() +{ + // Disable HC detaction in WebKit. (#5429) + if ( CKEDITOR.env.webkit ) + { + CKEDITOR.env.hc = false; + return; + } + + // Check is High Contrast is active by creating a temporary element with a + // background image. + + var useSpacer = CKEDITOR.env.ie && CKEDITOR.env.version < 7, + useBlank = CKEDITOR.env.ie && CKEDITOR.env.version == 7; + + var backgroundImageUrl = useSpacer ? ( CKEDITOR.basePath + 'images/spacer.gif' ) : + useBlank ? 'about:blank' : 'data:image/png;base64,'; + + var hcDetect = CKEDITOR.dom.element.createFromHtml( + '
', CKEDITOR.document ); + + hcDetect.appendTo( CKEDITOR.document.getHead() ); + + // Update CKEDITOR.env. + // Catch exception needed sometimes for FF. (#4230) + try + { + CKEDITOR.env.hc = ( hcDetect.getComputedStyle( 'background-image' ) == 'none' ); + } + catch (e) + { + CKEDITOR.env.hc = false; + } + + if ( CKEDITOR.env.hc ) + CKEDITOR.env.cssClass += ' cke_hc'; + + hcDetect.remove(); +})(); + +// Load core plugins. +CKEDITOR.plugins.load( CKEDITOR.config.corePlugins.split( ',' ), function() + { + CKEDITOR.status = 'loaded'; + CKEDITOR.fire( 'loaded' ); + + // Process all instances created by the "basic" implementation. + var pending = CKEDITOR._.pending; + if ( pending ) + { + delete CKEDITOR._.pending; + + for ( var i = 0 ; i < pending.length ; i++ ) + CKEDITOR.add( pending[ i ] ); + } + }); + +/* +TODO: Enable the following and check if effective. + +if ( CKEDITOR.env.ie ) +{ + // Remove IE mouse flickering on IE6 because of background images. + try + { + document.execCommand( 'BackgroundImageCache', false, true ); + } + catch (e) + { + // We have been reported about loading problems caused by the above + // line. For safety, let's just ignore errors. + } +} +*/ + +/** + * Fired when a CKEDITOR core object is fully loaded and ready for interaction. + * @name CKEDITOR#loaded + * @event + */ diff --git a/oss/vtiger/trunk/include/ckeditor/_source/core/ajax.js b/oss/vtiger/trunk/include/ckeditor/_source/core/ajax.js new file mode 100644 index 00000000..078c15a1 --- /dev/null +++ b/oss/vtiger/trunk/include/ckeditor/_source/core/ajax.js @@ -0,0 +1,143 @@ +/* +Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.html or http://ckeditor.com/license +*/ + +/** + * @fileOverview Defines the {@link CKEDITOR.ajax} object, which holds ajax methods for + * data loading. + */ + +/** + * Ajax methods for data loading. + * @namespace + * @example + */ +CKEDITOR.ajax = (function() +{ + var createXMLHttpRequest = function() + { + // In IE, using the native XMLHttpRequest for local files may throw + // "Access is Denied" errors. + if ( !CKEDITOR.env.ie || location.protocol != 'file:' ) + try { return new XMLHttpRequest(); } catch(e) {} + + try { return new ActiveXObject( 'Msxml2.XMLHTTP' ); } catch (e) {} + try { return new ActiveXObject( 'Microsoft.XMLHTTP' ); } catch (e) {} + + return null; + }; + + var checkStatus = function( xhr ) + { + // HTTP Status Codes: + // 2xx : Success + // 304 : Not Modified + // 0 : Returned when running locally (file://) + // 1223 : IE may change 204 to 1223 (see http://dev.jquery.com/ticket/1450) + + return ( xhr.readyState == 4 && + ( ( xhr.status >= 200 && xhr.status < 300 ) || + xhr.status == 304 || + xhr.status === 0 || + xhr.status == 1223 ) ); + }; + + var getResponseText = function( xhr ) + { + if ( checkStatus( xhr ) ) + return xhr.responseText; + return null; + }; + + var getResponseXml = function( xhr ) + { + if ( checkStatus( xhr ) ) + { + var xml = xhr.responseXML; + return new CKEDITOR.xml( xml && xml.firstChild ? xml : xhr.responseText ); + } + return null; + }; + + var load = function( url, callback, getResponseFn ) + { + var async = !!callback; + + var xhr = createXMLHttpRequest(); + + if ( !xhr ) + return null; + + xhr.open( 'GET', url, async ); + + if ( async ) + { + // TODO: perform leak checks on this closure. + /** @ignore */ + xhr.onreadystatechange = function() + { + if ( xhr.readyState == 4 ) + { + callback( getResponseFn( xhr ) ); + xhr = null; + } + }; + } + + xhr.send(null); + + return async ? '' : getResponseFn( xhr ); + }; + + return /** @lends CKEDITOR.ajax */ { + + /** + * Loads data from an URL as plain text. + * @param {String} url The URL from which load data. + * @param {Function} [callback] A callback function to be called on + * data load. If not provided, the data will be loaded + * asynchronously, passing the data value the function on load. + * @returns {String} The loaded data. For asynchronous requests, an + * empty string. For invalid requests, null. + * @example + * // Load data synchronously. + * var data = CKEDITOR.ajax.load( 'somedata.txt' ); + * alert( data ); + * @example + * // Load data asynchronously. + * var data = CKEDITOR.ajax.load( 'somedata.txt', function( data ) + * { + * alert( data ); + * } ); + */ + load : function( url, callback ) + { + return load( url, callback, getResponseText ); + }, + + /** + * Loads data from an URL as XML. + * @param {String} url The URL from which load data. + * @param {Function} [callback] A callback function to be called on + * data load. If not provided, the data will be loaded + * asynchronously, passing the data value the function on load. + * @returns {CKEDITOR.xml} An XML object holding the loaded data. For asynchronous requests, an + * empty string. For invalid requests, null. + * @example + * // Load XML synchronously. + * var xml = CKEDITOR.ajax.loadXml( 'somedata.xml' ); + * alert( xml.getInnerXml( '//' ) ); + * @example + * // Load XML asynchronously. + * var data = CKEDITOR.ajax.loadXml( 'somedata.xml', function( xml ) + * { + * alert( xml.getInnerXml( '//' ) ); + * } ); + */ + loadXml : function( url, callback ) + { + return load( url, callback, getResponseXml ); + } + }; +})(); diff --git a/oss/vtiger/trunk/include/ckeditor/_source/core/ckeditor.js b/oss/vtiger/trunk/include/ckeditor/_source/core/ckeditor.js new file mode 100644 index 00000000..1faddd2d --- /dev/null +++ b/oss/vtiger/trunk/include/ckeditor/_source/core/ckeditor.js @@ -0,0 +1,103 @@ +/* +Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.html or http://ckeditor.com/license +*/ + +/** + * @fileOverview Contains the third and last part of the {@link CKEDITOR} object + * definition. + */ + +// Remove the CKEDITOR.loadFullCore reference defined on ckeditor_basic. +delete CKEDITOR.loadFullCore; + +/** + * Holds references to all editor instances created. The name of the properties + * in this object correspond to instance names, and their values contains the + * {@link CKEDITOR.editor} object representing them. + * @type {Object} + * @example + * alert( CKEDITOR.instances.editor1.name ); // "editor1" + */ +CKEDITOR.instances = {}; + +/** + * The document of the window holding the CKEDITOR object. + * @type {CKEDITOR.dom.document} + * @example + * alert( CKEDITOR.document.getBody().getName() ); // "body" + */ +CKEDITOR.document = new CKEDITOR.dom.document( document ); + +/** + * Adds an editor instance to the global {@link CKEDITOR} object. This function + * is available for internal use mainly. + * @param {CKEDITOR.editor} editor The editor instance to be added. + * @example + */ +CKEDITOR.add = function( editor ) +{ + CKEDITOR.instances[ editor.name ] = editor; + + editor.on( 'focus', function() + { + if ( CKEDITOR.currentInstance != editor ) + { + CKEDITOR.currentInstance = editor; + CKEDITOR.fire( 'currentInstance' ); + } + }); + + editor.on( 'blur', function() + { + if ( CKEDITOR.currentInstance == editor ) + { + CKEDITOR.currentInstance = null; + CKEDITOR.fire( 'currentInstance' ); + } + }); +}; + +/** + * Removes and editor instance from the global {@link CKEDITOR} object. his function + * is available for internal use mainly. + * @param {CKEDITOR.editor} editor The editor instance to be added. + * @example + */ +CKEDITOR.remove = function( editor ) +{ + delete CKEDITOR.instances[ editor.name ]; +}; + +// Load the bootstrap script. +CKEDITOR.loader.load( 'core/_bootstrap' ); // @Packager.RemoveLine + +// Tri-state constants. + +/** + * Used to indicate the ON or ACTIVE state. + * @constant + * @example + */ +CKEDITOR.TRISTATE_ON = 1; + +/** + * Used to indicate the OFF or NON ACTIVE state. + * @constant + * @example + */ +CKEDITOR.TRISTATE_OFF = 2; + +/** + * Used to indicate DISABLED state. + * @constant + * @example + */ +CKEDITOR.TRISTATE_DISABLED = 0; + +/** + * Fired when the CKEDITOR.currentInstance object reference changes. This may + * happen when setting the focus on different editor instances in the page. + * @name CKEDITOR#currentInstance + * @event + */ diff --git a/oss/vtiger/trunk/include/ckeditor/_source/core/ckeditor_base.js b/oss/vtiger/trunk/include/ckeditor/_source/core/ckeditor_base.js new file mode 100644 index 00000000..f608e0f0 --- /dev/null +++ b/oss/vtiger/trunk/include/ckeditor/_source/core/ckeditor_base.js @@ -0,0 +1,193 @@ +/* +Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.html or http://ckeditor.com/license +*/ + +/** + * @fileOverview Contains the first and essential part of the {@link CKEDITOR} + * object definition. + */ + +// #### Compressed Code +// Must be updated on changes in the script, as well as updated in the +// ckeditor_source.js and ckeditor_basic_source.js files. + +// if(!window.CKEDITOR)window.CKEDITOR=(function(){var a={timestamp:'',version:'3.2.1',rev:'5372',_:{},status:'unloaded',basePath:(function(){var d=window.CKEDITOR_BASEPATH||'';if(!d){var e=document.getElementsByTagName('script');for(var f=0;f element, spaces should be touched differently.
+ inPre = false,
+ returnPoint;
+
+ function checkPending( newTagName )
+ {
+ var pendingBRsSent;
+
+ if ( pendingInline.length > 0 )
+ {
+ for ( var i = 0 ; i < pendingInline.length ; i++ )
+ {
+ var pendingElement = pendingInline[ i ],
+ pendingName = pendingElement.name,
+ pendingDtd = CKEDITOR.dtd[ pendingName ],
+ currentDtd = currentNode.name && CKEDITOR.dtd[ currentNode.name ];
+
+ if ( ( !currentDtd || currentDtd[ pendingName ] ) && ( !newTagName || !pendingDtd || pendingDtd[ newTagName ] || !CKEDITOR.dtd[ newTagName ] ) )
+ {
+ if ( !pendingBRsSent )
+ {
+ sendPendingBRs();
+ pendingBRsSent = 1;
+ }
+
+ // Get a clone for the pending element.
+ pendingElement = pendingElement.clone();
+
+ // Add it to the current node and make it the current,
+ // so the new element will be added inside of it.
+ pendingElement.parent = currentNode;
+ currentNode = pendingElement;
+
+ // Remove the pending element (back the index by one
+ // to properly process the next entry).
+ pendingInline.splice( i, 1 );
+ i--;
+ }
+ }
+ }
+ }
+
+ function sendPendingBRs()
+ {
+ while ( pendingBRs.length )
+ currentNode.add( pendingBRs.shift() );
+ }
+
+ function addElement( element, target, enforceCurrent )
+ {
+ target = target || currentNode || fragment;
+
+ // If the target is the fragment and this element can't go inside
+ // body (if fixForBody).
+ if ( fixForBody && !target.type )
+ {
+ var elementName, realElementName;
+ if ( element.attributes
+ && ( realElementName =
+ element.attributes[ '_cke_real_element_type' ] ) )
+ elementName = realElementName;
+ else
+ elementName = element.name;
+ if ( elementName
+ && !( elementName in CKEDITOR.dtd.$body )
+ && !( elementName in CKEDITOR.dtd.$nonBodyContent ) )
+ {
+ var savedCurrent = currentNode;
+
+ // Create a in the fragment.
+ currentNode = target;
+ parser.onTagOpen( fixForBody, {} );
+
+ // The new target now is the
.
+ target = currentNode;
+
+ if ( enforceCurrent )
+ currentNode = savedCurrent;
+ }
+ }
+
+ // Rtrim empty spaces on block end boundary. (#3585)
+ if ( element._.isBlockLike
+ && element.name != 'pre' )
+ {
+
+ var length = element.children.length,
+ lastChild = element.children[ length - 1 ],
+ text;
+ if ( lastChild && lastChild.type == CKEDITOR.NODE_TEXT )
+ {
+ if ( !( text = CKEDITOR.tools.rtrim( lastChild.value ) ) )
+ element.children.length = length -1;
+ else
+ lastChild.value = text;
+ }
+ }
+
+ target.add( element );
+
+ if ( element.returnPoint )
+ {
+ currentNode = element.returnPoint;
+ delete element.returnPoint;
+ }
+ }
+
+ parser.onTagOpen = function( tagName, attributes, selfClosing )
+ {
+ var element = new CKEDITOR.htmlParser.element( tagName, attributes );
+
+ // "isEmpty" will be always "false" for unknown elements, so we
+ // must force it if the parser has identified it as a selfClosing tag.
+ if ( element.isUnknown && selfClosing )
+ element.isEmpty = true;
+
+ // This is a tag to be removed if empty, so do not add it immediately.
+ if ( CKEDITOR.dtd.$removeEmpty[ tagName ] )
+ {
+ pendingInline.push( element );
+ return;
+ }
+ else if ( tagName == 'pre' )
+ inPre = true;
+ else if ( tagName == 'br' && inPre )
+ {
+ currentNode.add( new CKEDITOR.htmlParser.text( '\n' ) );
+ return;
+ }
+
+ if ( tagName == 'br' )
+ {
+ pendingBRs.push( element );
+ return;
+ }
+
+ var currentName = currentNode.name;
+
+ var currentDtd = currentName
+ && ( CKEDITOR.dtd[ currentName ]
+ || ( currentNode._.isBlockLike ? CKEDITOR.dtd.div : CKEDITOR.dtd.span ) );
+
+ // If the element cannot be child of the current element.
+ if ( currentDtd // Fragment could receive any elements.
+ && !element.isUnknown && !currentNode.isUnknown && !currentDtd[ tagName ] )
+ {
+
+ var reApply = false,
+ addPoint; // New position to start adding nodes.
+
+ // Fixing malformed nested lists by moving it into a previous list item. (#3828)
+ if ( tagName in listBlocks
+ && currentName in listBlocks )
+ {
+ var children = currentNode.children,
+ lastChild = children[ children.length - 1 ];
+
+ // Establish the list item if it's not existed.
+ if ( !( lastChild && lastChild.name in listItems ) )
+ addElement( ( lastChild = new CKEDITOR.htmlParser.element( 'li' ) ), currentNode );
+
+ returnPoint = currentNode, addPoint = lastChild;
+ }
+ // If the element name is the same as the current element name,
+ // then just close the current one and append the new one to the
+ // parent. This situation usually happens with
,
.
+ if ( !currentNode._.hasInlineStarted && !inPre )
+ {
+ text = CKEDITOR.tools.ltrim( text );
+
+ if ( text.length === 0 )
+ return;
+ }
+
+ sendPendingBRs();
+ checkPending();
+
+ if ( fixForBody
+ && ( !currentNode.type || currentNode.name == 'body' )
+ && CKEDITOR.tools.trim( text ) )
+ {
+ this.onTagOpen( fixForBody, {} );
+ }
+
+ // Shrinking consequential spaces into one single for all elements
+ // text contents.
+ if ( !inPre )
+ text = text.replace( /[\t\r\n ]{2,}|[\t\r\n]/g, ' ' );
+
+ currentNode.add( new CKEDITOR.htmlParser.text( text ) );
+ };
+
+ parser.onCDATA = function( cdata )
+ {
+ currentNode.add( new CKEDITOR.htmlParser.cdata( cdata ) );
+ };
+
+ parser.onComment = function( comment )
+ {
+ currentNode.add( new CKEDITOR.htmlParser.comment( comment ) );
+ };
+
+ // Parse it.
+ parser.parse( fragmentHtml );
+
+ sendPendingBRs();
+
+ // Close all pending nodes.
+ while ( currentNode.type )
+ {
+ var parent = currentNode.parent,
+ node = currentNode;
+
+ if ( fixForBody
+ && ( !parent.type || parent.name == 'body' )
+ && !CKEDITOR.dtd.$body[ node.name ] )
+ {
+ currentNode = parent;
+ parser.onTagOpen( fixForBody, {} );
+ parent = currentNode;
+ }
+
+ parent.add( node );
+ currentNode = parent;
+ }
+
+ return fragment;
+ };
+
+ CKEDITOR.htmlParser.fragment.prototype =
+ {
+ /**
+ * Adds a node to this fragment.
+ * @param {Object} node The node to be added. It can be any of of the
+ * following types: {@link CKEDITOR.htmlParser.element},
+ * {@link CKEDITOR.htmlParser.text} and
+ * {@link CKEDITOR.htmlParser.comment}.
+ * @example
+ */
+ add : function( node )
+ {
+ var len = this.children.length,
+ previous = len > 0 && this.children[ len - 1 ] || null;
+
+ if ( previous )
+ {
+ // If the block to be appended is following text, trim spaces at
+ // the right of it.
+ if ( node._.isBlockLike && previous.type == CKEDITOR.NODE_TEXT )
+ {
+ previous.value = CKEDITOR.tools.rtrim( previous.value );
+
+ // If we have completely cleared the previous node.
+ if ( previous.value.length === 0 )
+ {
+ // Remove it from the list and add the node again.
+ this.children.pop();
+ this.add( node );
+ return;
+ }
+ }
+
+ previous.next = node;
+ }
+
+ node.previous = previous;
+ node.parent = this;
+
+ this.children.push( node );
+
+ this._.hasInlineStarted = node.type == CKEDITOR.NODE_TEXT || ( node.type == CKEDITOR.NODE_ELEMENT && !node._.isBlockLike );
+ },
+
+ /**
+ * Writes the fragment HTML to a CKEDITOR.htmlWriter.
+ * @param {CKEDITOR.htmlWriter} writer The writer to which write the HTML.
+ * @example
+ * var writer = new CKEDITOR.htmlWriter();
+ * var fragment = CKEDITOR.htmlParser.fragment.fromHtml( '<P><B>Example' );
+ * fragment.writeHtml( writer )
+ * alert( writer.getHtml() ); "<p><b>Example</b></p>"
+ */
+ writeHtml : function( writer, filter )
+ {
+ var isChildrenFiltered;
+ this.filterChildren = function()
+ {
+ var writer = new CKEDITOR.htmlParser.basicWriter();
+ this.writeChildrenHtml.call( this, writer, filter, true );
+ var html = writer.getHtml();
+ this.children = new CKEDITOR.htmlParser.fragment.fromHtml( html ).children;
+ isChildrenFiltered = 1;
+ };
+
+ // Filtering the root fragment before anything else.
+ !this.name && filter && filter.onFragment( this );
+
+ this.writeChildrenHtml( writer, isChildrenFiltered ? null : filter );
+ },
+
+ writeChildrenHtml : function( writer, filter )
+ {
+ for ( var i = 0 ; i < this.children.length ; i++ )
+ this.children[i].writeHtml( writer, filter );
+ }
+ };
+})();
diff --git a/oss/vtiger/trunk/include/ckeditor/_source/core/htmlparser/text.js b/oss/vtiger/trunk/include/ckeditor/_source/core/htmlparser/text.js
new file mode 100644
index 00000000..0d63ac9d
--- /dev/null
+++ b/oss/vtiger/trunk/include/ckeditor/_source/core/htmlparser/text.js
@@ -0,0 +1,55 @@
+/*
+Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+
+(function()
+{
+ var spacesRegex = /[\t\r\n ]{2,}|[\t\r\n]/g;
+
+ /**
+ * A lightweight representation of HTML text.
+ * @constructor
+ * @example
+ */
+ CKEDITOR.htmlParser.text = function( value )
+ {
+ /**
+ * The text value.
+ * @type String
+ * @example
+ */
+ this.value = value;
+
+ /** @private */
+ this._ =
+ {
+ isBlockLike : false
+ };
+ };
+
+ CKEDITOR.htmlParser.text.prototype =
+ {
+ /**
+ * The node type. This is a constant value set to {@link CKEDITOR.NODE_TEXT}.
+ * @type Number
+ * @example
+ */
+ type : CKEDITOR.NODE_TEXT,
+
+ /**
+ * Writes the HTML representation of this text to a CKEDITOR.htmlWriter.
+ * @param {CKEDITOR.htmlWriter} writer The writer to which write the HTML.
+ * @example
+ */
+ writeHtml : function( writer, filter )
+ {
+ var text = this.value;
+
+ if ( filter && !( text = filter.onText( text, this ) ) )
+ return;
+
+ writer.text( text );
+ }
+ };
+})();
diff --git a/oss/vtiger/trunk/include/ckeditor/_source/core/imagecacher.js b/oss/vtiger/trunk/include/ckeditor/_source/core/imagecacher.js
new file mode 100644
index 00000000..07045567
--- /dev/null
+++ b/oss/vtiger/trunk/include/ckeditor/_source/core/imagecacher.js
@@ -0,0 +1,59 @@
+/*
+Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+
+(function()
+{
+ var loaded = {};
+
+ var loadImage = function( image, callback )
+ {
+ var doCallback = function()
+ {
+ img.removeAllListeners();
+ loaded[ image ] = 1;
+ callback();
+ };
+
+ var img = new CKEDITOR.dom.element( 'img' );
+ img.on( 'load', doCallback );
+ img.on( 'error', doCallback );
+ img.setAttribute( 'src', image );
+ };
+
+ /**
+ * Load images into the browser cache.
+ * @namespace
+ * @example
+ */
+ CKEDITOR.imageCacher =
+ {
+ /**
+ * Loads one or more images.
+ * @param {Array} images The URLs for the images to be loaded.
+ * @param {Function} callback The function to be called once all images
+ * are loaded.
+ */
+ load : function( images, callback )
+ {
+ var pendingCount = images.length;
+
+ var checkPending = function()
+ {
+ if ( --pendingCount === 0 )
+ callback();
+ };
+
+ for ( var i = 0 ; i < images.length ; i++ )
+ {
+ var image = images[ i ];
+
+ if ( loaded[ image ] )
+ checkPending();
+ else
+ loadImage( image, checkPending );
+ }
+ }
+ };
+})();
diff --git a/oss/vtiger/trunk/include/ckeditor/_source/core/lang.js b/oss/vtiger/trunk/include/ckeditor/_source/core/lang.js
new file mode 100644
index 00000000..add99825
--- /dev/null
+++ b/oss/vtiger/trunk/include/ckeditor/_source/core/lang.js
@@ -0,0 +1,152 @@
+/*
+Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+
+(function()
+{
+ var loadedLangs = {};
+
+ CKEDITOR.lang =
+ {
+ /**
+ * The list of languages available in the editor core.
+ * @type Object
+ * @example
+ * alert( CKEDITOR.lang.en ); // "true"
+ */
+ languages :
+ {
+ 'af' : 1,
+ 'ar' : 1,
+ 'bg' : 1,
+ 'bn' : 1,
+ 'bs' : 1,
+ 'ca' : 1,
+ 'cs' : 1,
+ 'cy' : 1,
+ 'da' : 1,
+ 'de' : 1,
+ 'el' : 1,
+ 'en-au' : 1,
+ 'en-ca' : 1,
+ 'en-gb' : 1,
+ 'en' : 1,
+ 'eo' : 1,
+ 'es' : 1,
+ 'et' : 1,
+ 'eu' : 1,
+ 'fa' : 1,
+ 'fi' : 1,
+ 'fo' : 1,
+ 'fr-ca' : 1,
+ 'fr' : 1,
+ 'gl' : 1,
+ 'gu' : 1,
+ 'he' : 1,
+ 'hi' : 1,
+ 'hr' : 1,
+ 'hu' : 1,
+ 'is' : 1,
+ 'it' : 1,
+ 'ja' : 1,
+ 'km' : 1,
+ 'ko' : 1,
+ 'lt' : 1,
+ 'lv' : 1,
+ 'mn' : 1,
+ 'ms' : 1,
+ 'nb' : 1,
+ 'nl' : 1,
+ 'no' : 1,
+ 'pl' : 1,
+ 'pt-br' : 1,
+ 'pt' : 1,
+ 'ro' : 1,
+ 'ru' : 1,
+ 'sk' : 1,
+ 'sl' : 1,
+ 'sr-latn' : 1,
+ 'sr' : 1,
+ 'sv' : 1,
+ 'th' : 1,
+ 'tr' : 1,
+ 'uk' : 1,
+ 'vi' : 1,
+ 'zh-cn' : 1,
+ 'zh' : 1
+ },
+
+ /**
+ * Loads a specific language file, or auto detect it. A callback is
+ * then called when the file gets loaded.
+ * @param {String} languageCode The code of the language file to be
+ * loaded. If "autoDetect" is set to true, this language will be
+ * used as the default one, if the detect language is not
+ * available in the core.
+ * @param {Boolean} autoDetect Indicates that the function must try to
+ * detect the user language and load it instead.
+ * @param {Function} callback The function to be called once the
+ * language file is loaded. Two parameters are passed to this
+ * function: the language code and the loaded language entries.
+ * @example
+ */
+ load : function( languageCode, defaultLanguage, callback )
+ {
+ // If no languageCode - fallback to browser or default.
+ // If languageCode - fallback to no-localized version or default.
+ if ( !languageCode || !CKEDITOR.lang.languages[ languageCode ] )
+ languageCode = this.detect( defaultLanguage, languageCode );
+
+ if ( !this[ languageCode ] )
+ {
+ CKEDITOR.scriptLoader.load( CKEDITOR.getUrl(
+ '_source/' + // @Packager.RemoveLine
+ 'lang/' + languageCode + '.js' ),
+ function()
+ {
+ callback( languageCode, this[ languageCode ] );
+ }
+ , this );
+ }
+ else
+ callback( languageCode, this[ languageCode ] );
+ },
+
+ /**
+ * Returns the language that best fit the user language. For example,
+ * suppose that the user language is "pt-br". If this language is
+ * supported by the editor, it is returned. Otherwise, if only "pt" is
+ * supported, it is returned instead. If none of the previous are
+ * supported, a default language is then returned.
+ * @param {String} defaultLanguage The default language to be returned
+ * if the user language is not supported.
+ * @returns {String} The detected language code.
+ * @example
+ * alert( CKEDITOR.lang.detect( 'en' ) ); // e.g., in a German browser: "de"
+ */
+ detect : function( defaultLanguage, probeLanguage )
+ {
+ var languages = this.languages;
+ probeLanguage = probeLanguage || navigator.userLanguage || navigator.language;
+
+ var parts = probeLanguage
+ .toLowerCase()
+ .match( /([a-z]+)(?:-([a-z]+))?/ ),
+ lang = parts[1],
+ locale = parts[2];
+
+ if ( languages[ lang + '-' + locale ] )
+ lang = lang + '-' + locale;
+ else if ( !languages[ lang ] )
+ lang = null;
+
+ CKEDITOR.lang.detect = lang ?
+ function() { return lang; } :
+ function( defaultLanguage ) { return defaultLanguage; };
+
+ return lang || defaultLanguage;
+ }
+ };
+
+})();
diff --git a/oss/vtiger/trunk/include/ckeditor/_source/core/loader.js b/oss/vtiger/trunk/include/ckeditor/_source/core/loader.js
new file mode 100644
index 00000000..4c408fb8
--- /dev/null
+++ b/oss/vtiger/trunk/include/ckeditor/_source/core/loader.js
@@ -0,0 +1,242 @@
+/*
+Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+
+/**
+ * @fileOverview Defines the {@link CKEDITOR.loader} objects, which is used to
+ * load core scripts and their dependencies from _source.
+ */
+
+if ( typeof CKEDITOR == 'undefined' )
+ CKEDITOR = {};
+
+if ( !CKEDITOR.loader )
+{
+ /**
+ * Load core scripts and their dependencies from _source.
+ * @namespace
+ * @example
+ */
+ CKEDITOR.loader = (function()
+ {
+ // Table of script names and their dependencies.
+ var scripts =
+ {
+ 'core/_bootstrap' : [ 'core/config', 'core/ckeditor', 'core/plugins', 'core/scriptloader', 'core/tools', /* The following are entries that we want to force loading at the end to avoid dependence recursion */ 'core/dom/comment', 'core/dom/elementpath', 'core/dom/text', 'core/dom/range' ],
+ 'core/ajax' : [ 'core/xml' ],
+ 'core/ckeditor' : [ 'core/ckeditor_basic', 'core/dom', 'core/dtd', 'core/dom/document', 'core/dom/element', 'core/editor', 'core/event', 'core/htmlparser', 'core/htmlparser/element', 'core/htmlparser/fragment', 'core/htmlparser/filter', 'core/htmlparser/basicwriter', 'core/tools' ],
+ 'core/ckeditor_base' : [],
+ 'core/ckeditor_basic' : [ 'core/editor_basic', 'core/env', 'core/event' ],
+ 'core/command' : [],
+ 'core/config' : [ 'core/ckeditor_base' ],
+ 'core/dom' : [],
+ 'core/dom/comment' : [ 'core/dom/node' ],
+ 'core/dom/document' : [ 'core/dom', 'core/dom/domobject', 'core/dom/window' ],
+ 'core/dom/documentfragment' : [ 'core/dom/element' ],
+ 'core/dom/element' : [ 'core/dom', 'core/dom/document', 'core/dom/domobject', 'core/dom/node', 'core/dom/nodelist', 'core/tools' ],
+ 'core/dom/elementpath' : [ 'core/dom/element' ],
+ 'core/dom/event' : [],
+ 'core/dom/node' : [ 'core/dom/domobject', 'core/tools' ],
+ 'core/dom/nodelist' : [ 'core/dom/node' ],
+ 'core/dom/domobject' : [ 'core/dom/event' ],
+ 'core/dom/range' : [ 'core/dom/document', 'core/dom/documentfragment', 'core/dom/element', 'core/dom/walker' ],
+ 'core/dom/text' : [ 'core/dom/node', 'core/dom/domobject' ],
+ 'core/dom/walker' : [ 'core/dom/node' ],
+ 'core/dom/window' : [ 'core/dom/domobject' ],
+ 'core/dtd' : [ 'core/tools' ],
+ 'core/editor' : [ 'core/command', 'core/config', 'core/editor_basic', 'core/focusmanager', 'core/lang', 'core/plugins', 'core/skins', 'core/themes', 'core/tools', 'core/ui' ],
+ 'core/editor_basic' : [ 'core/event' ],
+ 'core/env' : [],
+ 'core/event' : [],
+ 'core/focusmanager' : [],
+ 'core/htmlparser' : [],
+ 'core/htmlparser/comment' : [ 'core/htmlparser' ],
+ 'core/htmlparser/element' : [ 'core/htmlparser', 'core/htmlparser/fragment' ],
+ 'core/htmlparser/fragment' : [ 'core/htmlparser', 'core/htmlparser/comment', 'core/htmlparser/text', 'core/htmlparser/cdata' ],
+ 'core/htmlparser/text' : [ 'core/htmlparser' ],
+ 'core/htmlparser/cdata' : [ 'core/htmlparser' ],
+ 'core/htmlparser/filter' : [ 'core/htmlparser' ],
+ 'core/htmlparser/basicwriter': [ 'core/htmlparser' ],
+ 'core/imagecacher' : [ 'core/dom/element' ],
+ 'core/lang' : [],
+ 'core/plugins' : [ 'core/resourcemanager' ],
+ 'core/resourcemanager' : [ 'core/scriptloader', 'core/tools' ],
+ 'core/scriptloader' : [ 'core/dom/element', 'core/env' ],
+ 'core/skins' : [ 'core/imagecacher', 'core/scriptloader' ],
+ 'core/themes' : [ 'core/resourcemanager' ],
+ 'core/tools' : [ 'core/env' ],
+ 'core/ui' : [],
+ 'core/xml' : [ 'core/env' ]
+ };
+
+ var basePath = (function()
+ {
+ // This is a copy of CKEDITOR.basePath, but requires the script having
+ // "_source/core/loader.js".
+ if ( CKEDITOR && CKEDITOR.basePath )
+ return CKEDITOR.basePath;
+
+ // Find out the editor directory path, based on its