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