initial commit
[namibia] / public / scripts / ckeditor / _source / adapters / jquery.js
1 /*
2 Copyright (c) 2003-2011, CKSource - Frederico Knabben. All rights reserved.
3 For licensing, see LICENSE.html or http://ckeditor.com/license
4 */
5
6 /**
7  * @fileOverview jQuery adapter provides easy use of basic CKEditor functions
8  *   and access to internal API. It also integrates some aspects of CKEditor with
9  *   jQuery framework.
10  *
11  * Every TEXTAREA, DIV and P elements can be converted to working editor.
12  *
13  * Plugin exposes some of editor's event to jQuery event system. All of those are namespaces inside
14  * ".ckeditor" namespace and can be binded/listened on supported textarea, div and p nodes.
15  *
16  * Available jQuery events:
17  * - instanceReady.ckeditor( editor, rootNode )
18  *   Triggered when new instance is ready.
19  * - destroy.ckeditor( editor )
20  *   Triggered when instance is destroyed.
21  * - getData.ckeditor( editor, eventData )
22  *   Triggered when getData event is fired inside editor. It can change returned data using eventData reference.
23  * - setData.ckeditor( editor )
24  *   Triggered when getData event is fired inside editor.
25  *
26  * @example
27  * <script src="jquery.js"></script>
28  * <script src="ckeditor.js"></script>
29  * <script src="adapters/jquery/adapter.js"></script>
30  */
31
32 (function()
33 {
34         /**
35          * Allows CKEditor to override jQuery.fn.val(), making it possible to use the val()
36          * function on textareas, as usual, having it synchronized with CKEditor.<br>
37          * <br>
38          * This configuration option is global and executed during the jQuery Adapter loading.
39          * It can't be customized across editor instances.
40          * @type Boolean
41          * @example
42          * &lt;script&gt;
43          * CKEDITOR.config.jqueryOverrideVal = true;
44          * &lt;/script&gt;
45          * &lt;!-- Important: The JQuery adapter is loaded *after* setting jqueryOverrideVal --&gt;
46          * &lt;script src="/ckeditor/adapters/jquery.js"&gt;&lt;/script&gt;
47          * @example
48          * // ... then later in the code ...
49          *
50          * $( 'textarea' ).ckeditor();
51          * // ...
52          * $( 'textarea' ).val( 'New content' );
53          */
54         CKEDITOR.config.jqueryOverrideVal = typeof CKEDITOR.config.jqueryOverrideVal == 'undefined'
55                 ? true : CKEDITOR.config.jqueryOverrideVal;
56
57         var jQuery = window.jQuery;
58
59         if ( typeof jQuery == 'undefined' )
60                 return;
61
62         // jQuery object methods.
63         jQuery.extend( jQuery.fn,
64         /** @lends jQuery.fn */
65         {
66                 /**
67                  * Return existing CKEditor instance for first matched element.
68                  * Allows to easily use internal API. Doesn't return jQuery object.
69                  *
70                  * Raised exception if editor doesn't exist or isn't ready yet.
71                  *
72                  * @name jQuery.ckeditorGet
73                  * @return CKEDITOR.editor
74                  * @see CKEDITOR.editor
75                  */
76                 ckeditorGet: function()
77                 {
78                         var instance = this.eq( 0 ).data( 'ckeditorInstance' );
79                         if ( !instance )
80                                 throw "CKEditor not yet initialized, use ckeditor() with callback.";
81                         return instance;
82                 },
83                 /**
84                  * Triggers creation of CKEditor in all matched elements (reduced to DIV, P and TEXTAREAs).
85                  * Binds callback to instanceReady event of all instances. If editor is already created, than
86                  * callback is fired right away.
87                  *
88                  * Mixed parameter order allowed.
89                  *
90                  * @param callback Function to be run on editor instance. Passed parameters: [ textarea ].
91                  * Callback is fiered in "this" scope being ckeditor instance and having source textarea as first param.
92                  *
93                  * @param config Configuration options for new instance(s) if not already created.
94                  * See URL
95                  *
96                  * @example
97                  * $( 'textarea' ).ckeditor( function( textarea ) {
98                  *   $( textarea ).val( this.getData() )
99                  * } );
100                  *
101                  * @name jQuery.fn.ckeditor
102                  * @return jQuery.fn
103                  */
104                 ckeditor: function( callback, config )
105                 {
106                         if ( !CKEDITOR.env.isCompatible )
107                                 return this;
108
109                         if ( !jQuery.isFunction( callback ))
110                         {
111                                 var tmp = config;
112                                 config = callback;
113                                 callback = tmp;
114                         }
115                         config = config || {};
116
117                         this.filter( 'textarea, div, p' ).each( function()
118                         {
119                                 var $element = jQuery( this ),
120                                         editor = $element.data( 'ckeditorInstance' ),
121                                         instanceLock = $element.data( '_ckeditorInstanceLock' ),
122                                         element = this;
123
124                                 if ( editor && !instanceLock )
125                                 {
126                                         if ( callback )
127                                                 callback.apply( editor, [ this ] );
128                                 }
129                                 else if ( !instanceLock )
130                                 {
131                                         // CREATE NEW INSTANCE
132
133                                         // Handle config.autoUpdateElement inside this plugin if desired.
134                                         if ( config.autoUpdateElement
135                                                 || ( typeof config.autoUpdateElement == 'undefined' && CKEDITOR.config.autoUpdateElement ) )
136                                         {
137                                                 config.autoUpdateElementJquery = true;
138                                         }
139
140                                         // Always disable config.autoUpdateElement.
141                                         config.autoUpdateElement = false;
142                                         $element.data( '_ckeditorInstanceLock', true );
143
144                                         // Set instance reference in element's data.
145                                         editor = CKEDITOR.replace( element, config );
146                                         $element.data( 'ckeditorInstance', editor );
147
148                                         // Register callback.
149                                         editor.on( 'instanceReady', function( event )
150                                         {
151                                                 var editor = event.editor;
152                                                 setTimeout( function()
153                                                 {
154                                                         // Delay bit more if editor is still not ready.
155                                                         if ( !editor.element )
156                                                         {
157                                                                 setTimeout( arguments.callee, 100 );
158                                                                 return;
159                                                         }
160
161                                                         // Remove this listener.
162                                                         event.removeListener( 'instanceReady', this.callee );
163
164                                                         // Forward setData on dataReady.
165                                                         editor.on( 'dataReady', function()
166                                                         {
167                                                                 $element.trigger( 'setData' + '.ckeditor', [ editor ] );
168                                                         });
169
170                                                         // Forward getData.
171                                                         editor.on( 'getData', function( event ) {
172                                                                 $element.trigger( 'getData' + '.ckeditor', [ editor, event.data ] );
173                                                         }, 999 );
174
175                                                         // Forward destroy event.
176                                                         editor.on( 'destroy', function()
177                                                         {
178                                                                 $element.trigger( 'destroy.ckeditor', [ editor ] );
179                                                         });
180
181                                                         // Integrate with form submit.
182                                                         if ( editor.config.autoUpdateElementJquery && $element.is( 'textarea' ) && $element.parents( 'form' ).length )
183                                                         {
184                                                                 var onSubmit = function()
185                                                                 {
186                                                                         $element.ckeditor( function()
187                                                                         {
188                                                                                 editor.updateElement();
189                                                                         });
190                                                                 };
191
192                                                                 // Bind to submit event.
193                                                                 $element.parents( 'form' ).submit( onSubmit );
194
195                                                                 // Bind to form-pre-serialize from jQuery Forms plugin.
196                                                                 $element.parents( 'form' ).bind( 'form-pre-serialize', onSubmit );
197
198                                                                 // Unbind when editor destroyed.
199                                                                 $element.bind( 'destroy.ckeditor', function()
200                                                                 {
201                                                                         $element.parents( 'form' ).unbind( 'submit', onSubmit );
202                                                                         $element.parents( 'form' ).unbind( 'form-pre-serialize', onSubmit );
203                                                                 });
204                                                         }
205
206                                                         // Garbage collect on destroy.
207                                                         editor.on( 'destroy', function()
208                                                         {
209                                                                 $element.data( 'ckeditorInstance', null );
210                                                         });
211
212                                                         // Remove lock.
213                                                         $element.data( '_ckeditorInstanceLock', null );
214
215                                                         // Fire instanceReady event.
216                                                         $element.trigger( 'instanceReady.ckeditor', [ editor ] );
217
218                                                         // Run given (first) code.
219                                                         if ( callback )
220                                                                 callback.apply( editor, [ element ] );
221                                                 }, 0 );
222                                         }, null, null, 9999);
223                                 }
224                                 else
225                                 {
226                                         // Editor is already during creation process, bind our code to the event.
227                                         CKEDITOR.on( 'instanceReady', function( event )
228                                         {
229                                                 var editor = event.editor;
230                                                 setTimeout( function()
231                                                 {
232                                                         // Delay bit more if editor is still not ready.
233                                                         if ( !editor.element )
234                                                         {
235                                                                 setTimeout( arguments.callee, 100 );
236                                                                 return;
237                                                         }
238
239                                                         if ( editor.element.$ == element )
240                                                         {
241                                                                 // Run given code.
242                                                                 if ( callback )
243                                                                         callback.apply( editor, [ element ] );
244                                                         }
245                                                 }, 0 );
246                                         }, null, null, 9999);
247                                 }
248                         });
249                         return this;
250                 }
251         });
252
253         // New val() method for objects.
254         if ( CKEDITOR.config.jqueryOverrideVal )
255         {
256                 jQuery.fn.val = CKEDITOR.tools.override( jQuery.fn.val, function( oldValMethod )
257                 {
258                         /**
259                          * CKEditor-aware val() method.
260                          *
261                          * Acts same as original jQuery val(), but for textareas which have CKEditor instances binded to them, method
262                          * returns editor's content. It also works for settings values.
263                          *
264                          * @param oldValMethod
265                          * @name jQuery.fn.val
266                          */
267                         return function( newValue, forceNative )
268                         {
269                                 var isSetter = typeof newValue != 'undefined',
270                                         result;
271
272                                 this.each( function()
273                                 {
274                                         var $this = jQuery( this ),
275                                                 editor = $this.data( 'ckeditorInstance' );
276
277                                         if ( !forceNative && $this.is( 'textarea' ) && editor )
278                                         {
279                                                 if ( isSetter )
280                                                         editor.setData( newValue );
281                                                 else
282                                                 {
283                                                         result = editor.getData();
284                                                         // break;
285                                                         return null;
286                                                 }
287                                         }
288                                         else
289                                         {
290                                                 if ( isSetter )
291                                                         oldValMethod.call( $this, newValue );
292                                                 else
293                                                 {
294                                                         result = oldValMethod.call( $this );
295                                                         // break;
296                                                         return null;
297                                                 }
298                                         }
299
300                                         return true;
301                                 });
302                                 return isSetter ? this : result;
303                         };
304                 });
305         }
306 })();