Importation initiale du code de CKEditor 3.6.1.
[ckeditor.git] / _source / plugins / adobeair / plugin.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 (function()
7 {
8 var eventNameList = [ 'click', 'keydown', 'mousedown', 'keypress', 'mouseover', 'mouseout' ];
9
10 // Inline event callbacks assigned via innerHTML/outerHTML, such as
11 // onclick/onmouseover, are ignored in AIR.
12 // Use DOM2 event listeners to substitue inline handlers instead.
13 function convertInlineHandlers( container )
14 {
15 // TODO: document.querySelectorAll is not supported in AIR.
16 var children = container.getElementsByTag( '*' ),
17 count = children.count(),
18 child;
19
20 for ( var i = 0; i < count; i++ )
21 {
22 child = children.getItem( i );
23
24 (function( node )
25 {
26 for ( var j = 0; j < eventNameList.length; j++ )
27 {
28 (function( eventName )
29 {
30 var inlineEventHandler = node.getAttribute( 'on' + eventName );
31 if ( node.hasAttribute( 'on' + eventName ) )
32 {
33 node.removeAttribute( 'on' + eventName );
34 node.on( eventName, function( evt )
35 {
36 var callFunc = /(return\s*)?CKEDITOR\.tools\.callFunction\(([^)]+)\)/.exec( inlineEventHandler ),
37 hasReturn = callFunc && callFunc[ 1 ],
38 callFuncArgs = callFunc && callFunc[ 2 ].split( ',' ),
39 preventDefault = /return false;/.test( inlineEventHandler );
40
41 if ( callFuncArgs )
42 {
43 var nums = callFuncArgs.length,
44 argName;
45
46 for ( var i = 0; i < nums; i++ )
47 {
48 // Trim spaces around param.
49 callFuncArgs[ i ] = argName = CKEDITOR.tools.trim( callFuncArgs[ i ] );
50
51 // String form param.
52 var strPattern = argName.match( /^(["'])([^"']*?)\1$/ );
53 if ( strPattern )
54 {
55 callFuncArgs[ i ] = strPattern[ 2 ];
56 continue;
57 }
58
59 // Integer form param.
60 if ( argName.match( /\d+/ ) )
61 {
62 callFuncArgs[ i ] = parseInt( argName, 10 );
63 continue;
64 }
65
66 // Speical variables.
67 switch( argName )
68 {
69 case 'this' :
70 callFuncArgs[ i ] = node.$;
71 break;
72 case 'event' :
73 callFuncArgs[ i ] = evt.data.$;
74 break;
75 case 'null' :
76 callFuncArgs [ i ] = null;
77 break;
78 }
79 }
80
81 var retval = CKEDITOR.tools.callFunction.apply( window, callFuncArgs );
82 if ( hasReturn && retval === false )
83 preventDefault = 1;
84 }
85
86 if ( preventDefault )
87 evt.data.preventDefault();
88 });
89 }
90 })( eventNameList[ j ] );
91 }
92 })( child );
93 }
94 }
95
96 CKEDITOR.plugins.add( 'adobeair',
97 {
98 init : function( editor )
99 {
100 if ( !CKEDITOR.env.air )
101 return;
102
103 // Body doesn't get default margin on AIR.
104 editor.addCss( 'body { padding: 8px }' );
105
106 editor.on( 'uiReady', function()
107 {
108 convertInlineHandlers( editor.container );
109
110 if ( editor.sharedSpaces )
111 {
112 for ( var space in editor.sharedSpaces )
113 convertInlineHandlers( editor.sharedSpaces[ space ] );
114 }
115
116 editor.on( 'elementsPathUpdate', function( evt ) { convertInlineHandlers( evt.data.space ); } );
117 });
118
119 editor.on( 'contentDom', function()
120 {
121 // Hyperlinks are enabled in editable documents in Adobe
122 // AIR. Prevent their click behavior.
123 editor.document.on( 'click', function( ev )
124 {
125 ev.data.preventDefault( true );
126 });
127 });
128 }
129 });
130
131 CKEDITOR.ui.on( 'ready', function( evt )
132 {
133 var ui = evt.data;
134 // richcombo, panelbutton and menu
135 if ( ui._.panel )
136 {
137 var panel = ui._.panel._.panel,
138 holder;
139
140 ( function()
141 {
142 // Adding dom event listeners off-line are not supported in AIR,
143 // waiting for panel iframe loaded.
144 if ( !panel.isLoaded )
145 {
146 setTimeout( arguments.callee, 30 );
147 return;
148 }
149 holder = panel._.holder;
150 convertInlineHandlers( holder );
151 })();
152 }
153 else if ( ui instanceof CKEDITOR.dialog )
154 convertInlineHandlers( ui._.element );
155 });
156 })();
157
158 CKEDITOR.dom.document.prototype.write = CKEDITOR.tools.override( CKEDITOR.dom.document.prototype.write,
159 function( original_write )
160 {
161 function appendElement( parent, tagName, fullTag, text )
162 {
163 var node = parent.append( tagName ),
164 attrs = CKEDITOR.htmlParser.fragment.fromHtml( fullTag ).children[ 0 ].attributes;
165 attrs && node.setAttributes( attrs );
166 text && node.append( parent.getDocument().createText( text ) );
167 }
168
169 return function( html, mode )
170 {
171 // document.write() or document.writeln() fail silently after
172 // the page load event in Adobe AIR.
173 // DOM manipulation could be used instead.
174 if ( this.getBody() )
175 {
176 // We're taking the below extra work only because innerHTML
177 // on <html> element doesn't work as expected.
178 var doc = this,
179 head = this.getHead();
180
181 // Create style nodes for inline css. ( <style> content doesn't applied when setting via innerHTML )
182 html = html.replace( /(<style[^>]*>)([\s\S]*?)<\/style>/gi,
183 function ( match, startTag, styleText )
184 {
185 appendElement( head, 'style', startTag, styleText );
186 return '';
187 });
188
189 html = html.replace( /<base\b[^>]*\/>/i,
190 function( match )
191 {
192 appendElement( head, 'base', match );
193 return '';
194 });
195
196 html = html.replace( /<title>([\s\S]*)<\/title>/i,
197 function( match, title )
198 {
199 doc.$.title = title;
200 return '';
201 });
202
203 // Move the rest of head stuff.
204 html = html.replace( /<head>([\s\S]*)<\/head>/i,
205 function( headHtml )
206 {
207 // Inject the <head> HTML inside a <div>.
208 // Do that before getDocumentHead because WebKit moves
209 // <link css> elements to the <head> at this point.
210 var div = new CKEDITOR.dom.element( 'div', doc );
211 div.setHtml( headHtml );
212 // Move the <div> nodes to <head>.
213 div.moveChildren( head );
214 return '';
215 });
216
217 html.replace( /(<body[^>]*>)([\s\S]*)(?=$|<\/body>)/i,
218 function( match, startTag, innerHTML )
219 {
220 doc.getBody().setHtml( innerHTML );
221 var attrs = CKEDITOR.htmlParser.fragment.fromHtml( startTag ).children[ 0 ].attributes;
222 attrs && doc.getBody().setAttributes( attrs );
223 });
224 }
225 else
226 original_write.apply( this, arguments );
227 };
228 });