JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
vanilla ckeditor-3.1
[ckeditor.git] / _source / adapters / jquery.js
diff --git a/_source/adapters/jquery.js b/_source/adapters/jquery.js
new file mode 100644 (file)
index 0000000..314c8ed
--- /dev/null
@@ -0,0 +1,293 @@
+/*\r
+Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved.\r
+For licensing, see LICENSE.html or http://ckeditor.com/license\r
+*/\r
+\r
+/**\r
+ * @fileOverview jQuery adapter provides easy use of basic CKEditor functions\r
+ *   and access to internal API. It also integrates some aspects of CKEditor with\r
+ *   jQuery framework.\r
+ *\r
+ * Every TEXTAREA, DIV and P elements can be converted to working editor.\r
+ *\r
+ * Plugin exposes some of editor's event to jQuery event system. All of those are namespaces inside\r
+ * ".ckeditor" namespace and can be binded/listened on supported textarea, div and p nodes.\r
+ *\r
+ * Available jQuery events:\r
+ * - instanceReady.ckeditor( editor, rootNode )\r
+ *   Triggered when new instance is ready.\r
+ * - destroy.ckeditor( editor )\r
+ *   Triggered when instance is destroyed.\r
+ * - getData.ckeditor( editor, eventData )\r
+ *   Triggered when getData event is fired inside editor. It can change returned data using eventData reference.\r
+ * - setData.ckeditor( editor )\r
+ *   Triggered when getData event is fired inside editor.\r
+ *\r
+ * @example\r
+ * <script src="jquery.js"></script>\r
+ * <script src="ckeditor.js"></script>\r
+ * <script src="adapters/jquery/adapter.js"></script>\r
+ */\r
+\r
+(function()\r
+{\r
+       /**\r
+        * Allow CKEditor to override jQuery.fn.val(). This results in ability to use val()\r
+        * function on textareas as usual and having those calls synchronized with CKEditor\r
+        * Rich Text Editor component.\r
+        *\r
+        * This config option is global and executed during plugin load.\r
+        * Can't be customized across editor instances.\r
+        *\r
+        * @type Boolean\r
+        * @example\r
+        * $( 'textarea' ).ckeditor();\r
+        * // ...\r
+        * $( 'textarea' ).val( 'New content' );\r
+        */\r
+       CKEDITOR.config.jqueryOverrideVal = typeof CKEDITOR.config.jqueryOverrideVal == 'undefined'\r
+               ? true : CKEDITOR.config.jqueryOverrideVal;\r
+\r
+       var jQuery = window.jQuery;\r
+\r
+       if ( typeof jQuery == 'undefined' )\r
+               return;\r
+\r
+       // jQuery object methods.\r
+       jQuery.extend( jQuery.fn,\r
+       /** @lends jQuery.fn */\r
+       {\r
+               /**\r
+                * Return existing CKEditor instance for first matched element.\r
+                * Allows to easily use internal API. Doesn't return jQuery object.\r
+                *\r
+                * Raised exception if editor doesn't exist or isn't ready yet.\r
+                *\r
+                * @name jQuery.ckeditorGet\r
+                * @return CKEDITOR.editor\r
+                * @see CKEDITOR.editor\r
+                */\r
+               ckeditorGet: function()\r
+               {\r
+                       var instance = this.eq( 0 ).data( 'ckeditorInstance' );\r
+                       if ( !instance )\r
+                               throw "CKEditor not yet initialized, use ckeditor() with callback.";\r
+                       return instance;\r
+               },\r
+               /**\r
+                * Triggers creation of CKEditor in all matched elements (reduced to DIV, P and TEXTAREAs).\r
+                * Binds callback to instanceReady event of all instances. If editor is already created, than\r
+                * callback is fired right away.\r
+                *\r
+                * Mixed parameter order allowed.\r
+                *\r
+                * @param callback Function to be run on editor instance. Passed parameters: [ textarea ].\r
+                * Callback is fiered in "this" scope being ckeditor instance and having source textarea as first param.\r
+                *\r
+                * @param config Configuration options for new instance(s) if not already created.\r
+                * See URL\r
+                *\r
+                * @example\r
+                * $( 'textarea' ).ckeditor( function( textarea ) {\r
+                *   $( textarea ).val( this.getData() )\r
+                * } );\r
+                *\r
+                * @name jQuery.fn.ckeditor\r
+                * @return jQuery.fn\r
+                */\r
+               ckeditor: function( callback, config )\r
+               {\r
+                       if ( !jQuery.isFunction( callback ))\r
+                       {\r
+                               var tmp = config;\r
+                               config = callback;\r
+                               callback = tmp;\r
+                       }\r
+                       config = config || {};\r
+\r
+                       this.filter( 'textarea, div, p' ).each( function()\r
+                       {\r
+                               var $element = jQuery( this ),\r
+                                       editor = $element.data( 'ckeditorInstance' ),\r
+                                       instanceLock = $element.data( '_ckeditorInstanceLock' ),\r
+                                       element = this;\r
+\r
+                               if ( editor && !instanceLock )\r
+                               {\r
+                                       if ( callback )\r
+                                               callback.apply( editor, [ this ] );\r
+                               }\r
+                               else if ( !instanceLock )\r
+                               {\r
+                                       // CREATE NEW INSTANCE\r
+\r
+                                       // Handle config.autoUpdateElement inside this plugin if desired.\r
+                                       if ( config.autoUpdateElement\r
+                                               || ( typeof config.autoUpdateElement == 'undefined' && CKEDITOR.config.autoUpdateElement ) )\r
+                                       {\r
+                                               config.autoUpdateElementJquery = true;\r
+                                       }\r
+\r
+                                       // Always disable config.autoUpdateElement.\r
+                                       config.autoUpdateElement = false;\r
+                                       $element.data( '_ckeditorInstanceLock', true );\r
+\r
+                                       // Set instance reference in element's data.\r
+                                       editor = CKEDITOR.replace( element, config );\r
+                                       $element.data( 'ckeditorInstance', editor );\r
+\r
+                                       // Register callback.\r
+                                       editor.on( 'instanceReady', function( event )\r
+                                       {\r
+                                               var editor = event.editor;\r
+                                               setTimeout( function()\r
+                                               {\r
+                                                       // Delay bit more if editor is still not ready.\r
+                                                       if ( !editor.element )\r
+                                                       {\r
+                                                               setTimeout( arguments.callee, 100 );\r
+                                                               return;\r
+                                                       }\r
+\r
+                                                       // Remove this listener.\r
+                                                       event.removeListener( 'instanceReady', this.callee );\r
+\r
+                                                       // Forward setData on dataReady.\r
+                                                       editor.on( 'dataReady', function()\r
+                                                       {\r
+                                                               $element.trigger( 'setData' + '.ckeditor', [ editor ] );\r
+                                                       });\r
+\r
+                                                       // Forward getData.\r
+                                                       editor.on( 'getData', function( event ) {\r
+                                                               $element.trigger( 'getData' + '.ckeditor', [ editor, event.data ] );\r
+                                                       }, 999 );\r
+\r
+                                                       // Forward destroy event.\r
+                                                       editor.on( 'destroy', function()\r
+                                                       {\r
+                                                               $element.trigger( 'destroy.ckeditor', [ editor ] );\r
+                                                       });\r
+\r
+                                                       // Integrate with form submit.\r
+                                                       if ( editor.config.autoUpdateElementJquery && $element.is( 'textarea' ) && $element.parents( 'form' ).length )\r
+                                                       {\r
+                                                               var onSubmit = function()\r
+                                                               {\r
+                                                                       $element.ckeditor( function()\r
+                                                                       {\r
+                                                                               editor.updateElement();\r
+                                                                       });\r
+                                                               };\r
+\r
+                                                               // Bind to submit event.\r
+                                                               $element.parents( 'form' ).submit( onSubmit );\r
+\r
+                                                               // Unbind when editor destroyed.\r
+                                                               $element.bind( 'destroy.ckeditor', function()\r
+                                                               {\r
+                                                                       $element.parents( 'form' ).unbind( 'submit', onSubmit );\r
+                                                               });\r
+                                                       }\r
+\r
+                                                       // Garbage collect on destroy.\r
+                                                       editor.on( 'destroy', function()\r
+                                                       {\r
+                                                               $element.data( 'ckeditorInstance', null );\r
+                                                       });\r
+\r
+                                                       // Remove lock.\r
+                                                       $element.data( '_ckeditorInstanceLock', null );\r
+\r
+                                                       // Fire instanceReady event.\r
+                                                       $element.trigger( 'instanceReady.ckeditor', [ editor ] );\r
+\r
+                                                       // Run given (first) code.\r
+                                                       if ( callback )\r
+                                                               callback.apply( editor, [ element ] );\r
+                                               }, 0 );\r
+                                       }, null, null, 9999);\r
+                               }\r
+                               else\r
+                               {\r
+                                       // Editor is already during creation process, bind our code to the event.\r
+                                       CKEDITOR.on( 'instanceReady', function( event )\r
+                                       {\r
+                                               var editor = event.editor;\r
+                                               setTimeout( function()\r
+                                               {\r
+                                                       // Delay bit more if editor is still not ready.\r
+                                                       if ( !editor.element )\r
+                                                       {\r
+                                                               setTimeout( arguments.callee, 100 );\r
+                                                               return;\r
+                                                       }\r
+\r
+                                                       if ( editor.element.$ == element )\r
+                                                       {\r
+                                                               // Run given code.\r
+                                                               if ( callback )\r
+                                                                       callback.apply( editor, [ element ] );\r
+                                                       }\r
+                                               }, 0 );\r
+                                       }, null, null, 9999);\r
+                               }\r
+                       });\r
+                       return this;\r
+               }\r
+       });\r
+\r
+       // New val() method for objects.\r
+       if ( CKEDITOR.config.jqueryOverrideVal )\r
+       {\r
+               jQuery.fn.val = CKEDITOR.tools.override( jQuery.fn.val, function( oldValMethod )\r
+               {\r
+                       /**\r
+                        * CKEditor-aware val() method.\r
+                        *\r
+                        * Acts same as original jQuery val(), but for textareas which have CKEditor instances binded to them, method\r
+                        * returns editor's content. It also works for settings values.\r
+                        *\r
+                        * @param oldValMethod\r
+                        * @name jQuery.fn.val\r
+                        */\r
+                       return function( newValue, forceNative )\r
+                       {\r
+                               var isSetter = typeof newValue != 'undefined',\r
+                                       result;\r
+\r
+                               this.each( function()\r
+                               {\r
+                                       var $this = jQuery( this ),\r
+                                               editor = $this.data( 'ckeditorInstance' );\r
+\r
+                                       if ( !forceNative && $this.is( 'textarea' ) && editor )\r
+                                       {\r
+                                               if ( isSetter )\r
+                                                       editor.setData( newValue );\r
+                                               else\r
+                                               {\r
+                                                       result = editor.getData();\r
+                                                       // break;\r
+                                                       return null;\r
+                                               }\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               if ( isSetter )\r
+                                                       oldValMethod.call( $this, newValue );\r
+                                               else\r
+                                               {\r
+                                                       result = oldValMethod.call( $this );\r
+                                                       // break;\r
+                                                       return null;\r
+                                               }\r
+                                       }\r
+\r
+                                       return true;\r
+                               });\r
+                               return isSetter ? this : result;\r
+                       };\r
+               });\r
+       }\r
+})();\r