Mercurial > public > sg101
comparison static/js/tiny_mce/plugins/fullpage/editor_plugin_src.js @ 442:6c182ceb7147
Fixing #217; upgrade TinyMCE to 3.4.2 and enable the paste plugin.
author | Brian Neal <bgneal@gmail.com> |
---|---|
date | Thu, 26 May 2011 00:43:49 +0000 |
parents | 88b2b9cb8c1f |
children |
comparison
equal
deleted
inserted
replaced
441:33d0c55e57a9 | 442:6c182ceb7147 |
---|---|
7 * License: http://tinymce.moxiecode.com/license | 7 * License: http://tinymce.moxiecode.com/license |
8 * Contributing: http://tinymce.moxiecode.com/contributing | 8 * Contributing: http://tinymce.moxiecode.com/contributing |
9 */ | 9 */ |
10 | 10 |
11 (function() { | 11 (function() { |
12 var each = tinymce.each, Node = tinymce.html.Node; | |
13 | |
12 tinymce.create('tinymce.plugins.FullPagePlugin', { | 14 tinymce.create('tinymce.plugins.FullPagePlugin', { |
13 init : function(ed, url) { | 15 init : function(ed, url) { |
14 var t = this; | 16 var t = this; |
15 | 17 |
16 t.editor = ed; | 18 t.editor = ed; |
22 width : 430 + parseInt(ed.getLang('fullpage.delta_width', 0)), | 24 width : 430 + parseInt(ed.getLang('fullpage.delta_width', 0)), |
23 height : 495 + parseInt(ed.getLang('fullpage.delta_height', 0)), | 25 height : 495 + parseInt(ed.getLang('fullpage.delta_height', 0)), |
24 inline : 1 | 26 inline : 1 |
25 }, { | 27 }, { |
26 plugin_url : url, | 28 plugin_url : url, |
27 head_html : t.head | 29 data : t._htmlToData() |
28 }); | 30 }); |
29 }); | 31 }); |
30 | 32 |
31 // Register buttons | 33 // Register buttons |
32 ed.addButton('fullpage', {title : 'fullpage.desc', cmd : 'mceFullPageProperties'}); | 34 ed.addButton('fullpage', {title : 'fullpage.desc', cmd : 'mceFullPageProperties'}); |
33 | 35 |
34 ed.onBeforeSetContent.add(t._setContent, t); | 36 ed.onBeforeSetContent.add(t._setContent, t); |
35 ed.onSetContent.add(t._setBodyAttribs, t); | |
36 ed.onGetContent.add(t._getContent, t); | 37 ed.onGetContent.add(t._getContent, t); |
37 }, | 38 }, |
38 | 39 |
39 getInfo : function() { | 40 getInfo : function() { |
40 return { | 41 return { |
46 }; | 47 }; |
47 }, | 48 }, |
48 | 49 |
49 // Private plugin internal methods | 50 // Private plugin internal methods |
50 | 51 |
51 _setBodyAttribs : function(ed, o) { | 52 _htmlToData : function() { |
52 var bdattr, i, len, kv, k, v, t, attr = this.head.match(/body(.*?)>/i); | 53 var headerFragment = this._parseHeader(), data = {}, nodes, elm, matches, editor = this.editor; |
53 | 54 |
54 if (attr && attr[1]) { | 55 function getAttr(elm, name) { |
55 bdattr = attr[1].match(/\s*(\w+\s*=\s*".*?"|\w+\s*=\s*'.*?'|\w+\s*=\s*\w+|\w+)\s*/g); | 56 var value = elm.attr(name); |
56 | 57 |
57 if (bdattr) { | 58 return value || ''; |
58 for(i = 0, len = bdattr.length; i < len; i++) { | 59 }; |
59 kv = bdattr[i].split('='); | 60 |
60 k = kv[0].replace(/\s/,''); | 61 // Default some values |
61 v = kv[1]; | 62 data.fontface = editor.getParam("fullpage_default_fontface", ""); |
62 | 63 data.fontsize = editor.getParam("fullpage_default_fontsize", ""); |
63 if (v) { | 64 |
64 v = v.replace(/^\s+/,'').replace(/\s+$/,''); | 65 // Parse XML PI |
65 t = v.match(/^["'](.*)["']$/); | 66 elm = headerFragment.firstChild; |
66 | 67 if (elm.type == 7) { |
67 if (t) | 68 data.xml_pi = true; |
68 v = t[1]; | 69 matches = /encoding="([^"]+)"/.exec(elm.value); |
69 } else | 70 if (matches) |
70 v = k; | 71 data.docencoding = matches[1]; |
71 | 72 } |
72 ed.dom.setAttrib(ed.getBody(), 'style', v); | 73 |
74 // Parse doctype | |
75 elm = headerFragment.getAll('#doctype')[0]; | |
76 if (elm) | |
77 data.doctype = '<!DOCTYPE' + elm.value + ">"; | |
78 | |
79 // Parse title element | |
80 elm = headerFragment.getAll('title')[0]; | |
81 if (elm && elm.firstChild) { | |
82 data.metatitle = elm.firstChild.value; | |
83 } | |
84 | |
85 // Parse meta elements | |
86 each(headerFragment.getAll('meta'), function(meta) { | |
87 var name = meta.attr('name'), httpEquiv = meta.attr('http-equiv'), matches; | |
88 | |
89 if (name) | |
90 data['meta' + name.toLowerCase()] = meta.attr('content'); | |
91 else if (httpEquiv == "Content-Type") { | |
92 matches = /charset\s*=\s*(.*)\s*/gi.exec(meta.attr('content')); | |
93 | |
94 if (matches) | |
95 data.docencoding = matches[1]; | |
96 } | |
97 }); | |
98 | |
99 // Parse html attribs | |
100 elm = headerFragment.getAll('html')[0]; | |
101 if (elm) | |
102 data.langcode = getAttr(elm, 'lang') || getAttr(elm, 'xml:lang'); | |
103 | |
104 // Parse stylesheet | |
105 elm = headerFragment.getAll('link')[0]; | |
106 if (elm && elm.attr('rel') == 'stylesheet') | |
107 data.stylesheet = elm.attr('href'); | |
108 | |
109 // Parse body parts | |
110 elm = headerFragment.getAll('body')[0]; | |
111 if (elm) { | |
112 data.langdir = getAttr(elm, 'dir'); | |
113 data.style = getAttr(elm, 'style'); | |
114 data.visited_color = getAttr(elm, 'vlink'); | |
115 data.link_color = getAttr(elm, 'link'); | |
116 data.active_color = getAttr(elm, 'alink'); | |
117 } | |
118 | |
119 return data; | |
120 }, | |
121 | |
122 _dataToHtml : function(data) { | |
123 var headerFragment, headElement, html, elm, value, dom = this.editor.dom; | |
124 | |
125 function setAttr(elm, name, value) { | |
126 elm.attr(name, value ? value : undefined); | |
127 }; | |
128 | |
129 function addHeadNode(node) { | |
130 if (headElement.firstChild) | |
131 headElement.insert(node, headElement.firstChild); | |
132 else | |
133 headElement.append(node); | |
134 }; | |
135 | |
136 headerFragment = this._parseHeader(); | |
137 headElement = headerFragment.getAll('head')[0]; | |
138 if (!headElement) { | |
139 elm = headerFragment.getAll('html')[0]; | |
140 headElement = new Node('head', 1); | |
141 | |
142 if (elm.firstChild) | |
143 elm.insert(headElement, elm.firstChild, true); | |
144 else | |
145 elm.append(headElement); | |
146 } | |
147 | |
148 // Add/update/remove XML-PI | |
149 elm = headerFragment.firstChild; | |
150 if (data.xml_pi) { | |
151 value = 'version="1.0"'; | |
152 | |
153 if (data.docencoding) | |
154 value += ' encoding="' + data.docencoding + '"'; | |
155 | |
156 if (elm.type != 7) { | |
157 elm = new Node('xml', 7); | |
158 headerFragment.insert(elm, headerFragment.firstChild, true); | |
159 } | |
160 | |
161 elm.value = value; | |
162 } else if (elm && elm.type == 7) | |
163 elm.remove(); | |
164 | |
165 // Add/update/remove doctype | |
166 elm = headerFragment.getAll('#doctype')[0]; | |
167 if (data.doctype) { | |
168 if (!elm) { | |
169 elm = new Node('#doctype', 10); | |
170 | |
171 if (data.xml_pi) | |
172 headerFragment.insert(elm, headerFragment.firstChild); | |
173 else | |
174 addHeadNode(elm); | |
175 } | |
176 | |
177 elm.value = data.doctype.substring(9, data.doctype.length - 1); | |
178 } else if (elm) | |
179 elm.remove(); | |
180 | |
181 // Add/update/remove title | |
182 elm = headerFragment.getAll('title')[0]; | |
183 if (data.metatitle) { | |
184 if (!elm) { | |
185 elm = new Node('title', 1); | |
186 elm.append(new Node('#text', 3)).value = data.metatitle; | |
187 addHeadNode(elm); | |
188 } | |
189 } | |
190 | |
191 // Add meta encoding | |
192 if (data.docencoding) { | |
193 elm = null; | |
194 each(headerFragment.getAll('meta'), function(meta) { | |
195 if (meta.attr('http-equiv') == 'Content-Type') | |
196 elm = meta; | |
197 }); | |
198 | |
199 if (!elm) { | |
200 elm = new Node('meta', 1); | |
201 elm.attr('http-equiv', 'Content-Type'); | |
202 elm.shortEnded = true; | |
203 addHeadNode(elm); | |
204 } | |
205 | |
206 elm.attr('content', 'text/html; charset=' + data.docencoding); | |
207 } | |
208 | |
209 // Add/update/remove meta | |
210 each('keywords,description,author,copyright,robots'.split(','), function(name) { | |
211 var nodes = headerFragment.getAll('meta'), i, meta, value = data['meta' + name]; | |
212 | |
213 for (i = 0; i < nodes.length; i++) { | |
214 meta = nodes[i]; | |
215 | |
216 if (meta.attr('name') == name) { | |
217 if (value) | |
218 meta.attr('content', value); | |
219 else | |
220 meta.remove(); | |
221 | |
222 return; | |
73 } | 223 } |
74 } | 224 } |
75 } | 225 |
76 }, | 226 if (value) { |
77 | 227 elm = new Node('meta', 1); |
78 _createSerializer : function() { | 228 elm.attr('name', name); |
79 return new tinymce.dom.Serializer({ | 229 elm.attr('content', value); |
80 dom : this.editor.dom, | 230 elm.shortEnded = true; |
81 apply_source_formatting : true | 231 |
232 addHeadNode(elm); | |
233 } | |
82 }); | 234 }); |
235 | |
236 // Add/update/delete link | |
237 elm = headerFragment.getAll('link')[0]; | |
238 if (elm && elm.attr('rel') == 'stylesheet') { | |
239 if (data.stylesheet) | |
240 elm.attr('href', data.stylesheet); | |
241 else | |
242 elm.remove(); | |
243 } else if (data.stylesheet) { | |
244 elm = new Node('link', 1); | |
245 elm.attr({ | |
246 rel : 'stylesheet', | |
247 text : 'text/css', | |
248 href : data.stylesheet | |
249 }); | |
250 elm.shortEnded = true; | |
251 | |
252 addHeadNode(elm); | |
253 } | |
254 | |
255 // Update body attributes | |
256 elm = headerFragment.getAll('body')[0]; | |
257 if (elm) { | |
258 setAttr(elm, 'dir', data.langdir); | |
259 setAttr(elm, 'style', data.style); | |
260 setAttr(elm, 'vlink', data.visited_color); | |
261 setAttr(elm, 'link', data.link_color); | |
262 setAttr(elm, 'alink', data.active_color); | |
263 | |
264 // Update iframe body as well | |
265 dom.setAttribs(this.editor.getBody(), { | |
266 style : data.style, | |
267 dir : data.dir, | |
268 vLink : data.visited_color, | |
269 link : data.link_color, | |
270 aLink : data.active_color | |
271 }); | |
272 } | |
273 | |
274 // Set html attributes | |
275 elm = headerFragment.getAll('html')[0]; | |
276 if (elm) { | |
277 setAttr(elm, 'lang', data.langcode); | |
278 setAttr(elm, 'xml:lang', data.langcode); | |
279 } | |
280 | |
281 // Serialize header fragment and crop away body part | |
282 html = new tinymce.html.Serializer({ | |
283 validate: false, | |
284 indent: true, | |
285 apply_source_formatting : true, | |
286 indent_before: 'head,html,body,meta,title,script,link,style', | |
287 indent_after: 'head,html,body,meta,title,script,link,style' | |
288 }).serialize(headerFragment); | |
289 | |
290 this.head = html.substring(0, html.indexOf('</body>')); | |
291 }, | |
292 | |
293 _parseHeader : function() { | |
294 // Parse the contents with a DOM parser | |
295 return new tinymce.html.DomParser({ | |
296 validate: false, | |
297 root_name: '#document' | |
298 }).parse(this.head); | |
83 }, | 299 }, |
84 | 300 |
85 _setContent : function(ed, o) { | 301 _setContent : function(ed, o) { |
86 var t = this, sp, ep, c = o.content, v, st = ''; | 302 var self = this, startPos, endPos, content = o.content, headerFragment, styles = '', dom = self.editor.dom, elm; |
303 | |
304 function low(s) { | |
305 return s.replace(/<\/?[A-Z]+/g, function(a) { | |
306 return a.toLowerCase(); | |
307 }) | |
308 }; | |
87 | 309 |
88 // Ignore raw updated if we already have a head, this will fix issues with undo/redo keeping the head/foot separate | 310 // Ignore raw updated if we already have a head, this will fix issues with undo/redo keeping the head/foot separate |
89 if (o.format == 'raw' && t.head) | 311 if (o.format == 'raw' && self.head) |
90 return; | 312 return; |
91 | 313 |
92 if (o.source_view && ed.getParam('fullpage_hide_in_source_view')) | 314 if (o.source_view && ed.getParam('fullpage_hide_in_source_view')) |
93 return; | 315 return; |
94 | 316 |
95 // Parse out head, body and footer | 317 // Parse out head, body and footer |
96 c = c.replace(/<(\/?)BODY/gi, '<$1body'); | 318 content = content.replace(/<(\/?)BODY/gi, '<$1body'); |
97 sp = c.indexOf('<body'); | 319 startPos = content.indexOf('<body'); |
98 | 320 |
99 if (sp != -1) { | 321 if (startPos != -1) { |
100 sp = c.indexOf('>', sp); | 322 startPos = content.indexOf('>', startPos); |
101 t.head = c.substring(0, sp + 1); | 323 self.head = low(content.substring(0, startPos + 1)); |
102 | 324 |
103 ep = c.indexOf('</body', sp); | 325 endPos = content.indexOf('</body', startPos); |
104 if (ep == -1) | 326 if (endPos == -1) |
105 ep = c.indexOf('</body', ep); | 327 endPos = content.length; |
106 | 328 |
107 o.content = c.substring(sp + 1, ep); | 329 o.content = content.substring(startPos + 1, endPos); |
108 t.foot = c.substring(ep); | 330 self.foot = low(content.substring(endPos)); |
109 | |
110 function low(s) { | |
111 return s.replace(/<\/?[A-Z]+/g, function(a) { | |
112 return a.toLowerCase(); | |
113 }) | |
114 }; | |
115 | |
116 t.head = low(t.head); | |
117 t.foot = low(t.foot); | |
118 } else { | 331 } else { |
119 t.head = ''; | 332 self.head = this._getDefaultHeader(); |
120 if (ed.getParam('fullpage_default_xml_pi')) | 333 self.foot = '\n</body>\n</html>'; |
121 t.head += '<?xml version="1.0" encoding="' + ed.getParam('fullpage_default_encoding', 'ISO-8859-1') + '" ?>\n'; | 334 } |
122 | 335 |
123 t.head += ed.getParam('fullpage_default_doctype', '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">'); | 336 // Parse header and update iframe |
124 t.head += '\n<html>\n<head>\n<title>' + ed.getParam('fullpage_default_title', 'Untitled document') + '</title>\n'; | 337 headerFragment = self._parseHeader(); |
125 | 338 each(headerFragment.getAll('style'), function(node) { |
126 if (v = ed.getParam('fullpage_default_encoding')) | 339 if (node.firstChild) |
127 t.head += '<meta http-equiv="Content-Type" content="' + v + '" />\n'; | 340 styles += node.firstChild.value; |
128 | 341 }); |
129 if (v = ed.getParam('fullpage_default_font_family')) | 342 |
130 st += 'font-family: ' + v + ';'; | 343 elm = headerFragment.getAll('body')[0]; |
131 | 344 if (elm) { |
132 if (v = ed.getParam('fullpage_default_font_size')) | 345 dom.setAttribs(self.editor.getBody(), { |
133 st += 'font-size: ' + v + ';'; | 346 style : elm.attr('style') || '', |
134 | 347 dir : elm.attr('dir') || '', |
135 if (v = ed.getParam('fullpage_default_text_color')) | 348 vLink : elm.attr('vlink') || '', |
136 st += 'color: ' + v + ';'; | 349 link : elm.attr('link') || '', |
137 | 350 aLink : elm.attr('alink') || '' |
138 t.head += '</head>\n<body' + (st ? ' style="' + st + '"' : '') + '>\n'; | 351 }); |
139 t.foot = '\n</body>\n</html>'; | 352 } |
140 } | 353 |
354 if (styles) | |
355 dom.add(self.editor.getDoc().getElementsByTagName('head')[0], 'style', {id : 'fullpage_styles'}, styles); | |
356 else | |
357 dom.remove('fullpage_styles'); | |
358 }, | |
359 | |
360 _getDefaultHeader : function() { | |
361 var header = '', editor = this.editor, value, styles = ''; | |
362 | |
363 if (editor.getParam('fullpage_default_xml_pi')) | |
364 header += '<?xml version="1.0" encoding="' + editor.getParam('fullpage_default_encoding', 'ISO-8859-1') + '" ?>\n'; | |
365 | |
366 header += editor.getParam('fullpage_default_doctype', '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">'); | |
367 header += '\n<html>\n<head>\n'; | |
368 | |
369 if (value = editor.getParam('fullpage_default_title')) | |
370 header += '<title>' + v + '</title>\n'; | |
371 | |
372 if (value = editor.getParam('fullpage_default_encoding')) | |
373 header += '<meta http-equiv="Content-Type" content="text/html; charset=' + value + '" />\n'; | |
374 | |
375 if (value = editor.getParam('fullpage_default_font_family')) | |
376 styles += 'font-family: ' + value + ';'; | |
377 | |
378 if (value = editor.getParam('fullpage_default_font_size')) | |
379 styles += 'font-size: ' + value + ';'; | |
380 | |
381 if (value = editor.getParam('fullpage_default_text_color')) | |
382 styles += 'color: ' + value + ';'; | |
383 | |
384 header += '</head>\n<body' + (styles ? ' style="' + styles + '"' : '') + '>\n'; | |
385 | |
386 return header; | |
141 }, | 387 }, |
142 | 388 |
143 _getContent : function(ed, o) { | 389 _getContent : function(ed, o) { |
144 var t = this; | 390 var self = this; |
145 | 391 |
146 if (!o.source_view || !ed.getParam('fullpage_hide_in_source_view')) | 392 if (!o.source_view || !ed.getParam('fullpage_hide_in_source_view')) |
147 o.content = tinymce.trim(t.head) + '\n' + tinymce.trim(o.content) + '\n' + tinymce.trim(t.foot); | 393 o.content = tinymce.trim(self.head) + '\n' + tinymce.trim(o.content) + '\n' + tinymce.trim(self.foot); |
148 } | 394 } |
149 }); | 395 }); |
150 | 396 |
151 // Register plugin | 397 // Register plugin |
152 tinymce.PluginManager.add('fullpage', tinymce.plugins.FullPagePlugin); | 398 tinymce.PluginManager.add('fullpage', tinymce.plugins.FullPagePlugin); |