Mercurial > hg > AnnotationManager
comparison WebContent/jscripts/tiny_mce/plugins/fullpage/editor_plugin_src.js @ 5:0be9d53a6967
editor for annotations
| author | dwinter |
|---|---|
| date | Tue, 13 Dec 2011 17:43:46 +0100 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 4:c32080f364c6 | 5:0be9d53a6967 |
|---|---|
| 1 /** | |
| 2 * editor_plugin_src.js | |
| 3 * | |
| 4 * Copyright 2009, Moxiecode Systems AB | |
| 5 * Released under LGPL License. | |
| 6 * | |
| 7 * License: http://tinymce.moxiecode.com/license | |
| 8 * Contributing: http://tinymce.moxiecode.com/contributing | |
| 9 */ | |
| 10 | |
| 11 (function() { | |
| 12 var each = tinymce.each, Node = tinymce.html.Node; | |
| 13 | |
| 14 tinymce.create('tinymce.plugins.FullPagePlugin', { | |
| 15 init : function(ed, url) { | |
| 16 var t = this; | |
| 17 | |
| 18 t.editor = ed; | |
| 19 | |
| 20 // Register commands | |
| 21 ed.addCommand('mceFullPageProperties', function() { | |
| 22 ed.windowManager.open({ | |
| 23 file : url + '/fullpage.htm', | |
| 24 width : 430 + parseInt(ed.getLang('fullpage.delta_width', 0)), | |
| 25 height : 495 + parseInt(ed.getLang('fullpage.delta_height', 0)), | |
| 26 inline : 1 | |
| 27 }, { | |
| 28 plugin_url : url, | |
| 29 data : t._htmlToData() | |
| 30 }); | |
| 31 }); | |
| 32 | |
| 33 // Register buttons | |
| 34 ed.addButton('fullpage', {title : 'fullpage.desc', cmd : 'mceFullPageProperties'}); | |
| 35 | |
| 36 ed.onBeforeSetContent.add(t._setContent, t); | |
| 37 ed.onGetContent.add(t._getContent, t); | |
| 38 }, | |
| 39 | |
| 40 getInfo : function() { | |
| 41 return { | |
| 42 longname : 'Fullpage', | |
| 43 author : 'Moxiecode Systems AB', | |
| 44 authorurl : 'http://tinymce.moxiecode.com', | |
| 45 infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/fullpage', | |
| 46 version : tinymce.majorVersion + "." + tinymce.minorVersion | |
| 47 }; | |
| 48 }, | |
| 49 | |
| 50 // Private plugin internal methods | |
| 51 | |
| 52 _htmlToData : function() { | |
| 53 var headerFragment = this._parseHeader(), data = {}, nodes, elm, matches, editor = this.editor; | |
| 54 | |
| 55 function getAttr(elm, name) { | |
| 56 var value = elm.attr(name); | |
| 57 | |
| 58 return value || ''; | |
| 59 }; | |
| 60 | |
| 61 // Default some values | |
| 62 data.fontface = editor.getParam("fullpage_default_fontface", ""); | |
| 63 data.fontsize = editor.getParam("fullpage_default_fontsize", ""); | |
| 64 | |
| 65 // Parse XML PI | |
| 66 elm = headerFragment.firstChild; | |
| 67 if (elm.type == 7) { | |
| 68 data.xml_pi = true; | |
| 69 matches = /encoding="([^"]+)"/.exec(elm.value); | |
| 70 if (matches) | |
| 71 data.docencoding = matches[1]; | |
| 72 } | |
| 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; | |
| 223 } | |
| 224 } | |
| 225 | |
| 226 if (value) { | |
| 227 elm = new Node('meta', 1); | |
| 228 elm.attr('name', name); | |
| 229 elm.attr('content', value); | |
| 230 elm.shortEnded = true; | |
| 231 | |
| 232 addHeadNode(elm); | |
| 233 } | |
| 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); | |
| 299 }, | |
| 300 | |
| 301 _setContent : function(ed, o) { | |
| 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 }; | |
| 309 | |
| 310 // Ignore raw updated if we already have a head, this will fix issues with undo/redo keeping the head/foot separate | |
| 311 if (o.format == 'raw' && self.head) | |
| 312 return; | |
| 313 | |
| 314 if (o.source_view && ed.getParam('fullpage_hide_in_source_view')) | |
| 315 return; | |
| 316 | |
| 317 // Parse out head, body and footer | |
| 318 content = content.replace(/<(\/?)BODY/gi, '<$1body'); | |
| 319 startPos = content.indexOf('<body'); | |
| 320 | |
| 321 if (startPos != -1) { | |
| 322 startPos = content.indexOf('>', startPos); | |
| 323 self.head = low(content.substring(0, startPos + 1)); | |
| 324 | |
| 325 endPos = content.indexOf('</body', startPos); | |
| 326 if (endPos == -1) | |
| 327 endPos = content.length; | |
| 328 | |
| 329 o.content = content.substring(startPos + 1, endPos); | |
| 330 self.foot = low(content.substring(endPos)); | |
| 331 } else { | |
| 332 self.head = this._getDefaultHeader(); | |
| 333 self.foot = '\n</body>\n</html>'; | |
| 334 } | |
| 335 | |
| 336 // Parse header and update iframe | |
| 337 headerFragment = self._parseHeader(); | |
| 338 each(headerFragment.getAll('style'), function(node) { | |
| 339 if (node.firstChild) | |
| 340 styles += node.firstChild.value; | |
| 341 }); | |
| 342 | |
| 343 elm = headerFragment.getAll('body')[0]; | |
| 344 if (elm) { | |
| 345 dom.setAttribs(self.editor.getBody(), { | |
| 346 style : elm.attr('style') || '', | |
| 347 dir : elm.attr('dir') || '', | |
| 348 vLink : elm.attr('vlink') || '', | |
| 349 link : elm.attr('link') || '', | |
| 350 aLink : elm.attr('alink') || '' | |
| 351 }); | |
| 352 } | |
| 353 | |
| 354 dom.remove('fullpage_styles'); | |
| 355 | |
| 356 if (styles) { | |
| 357 dom.add(self.editor.getDoc().getElementsByTagName('head')[0], 'style', {id : 'fullpage_styles'}, styles); | |
| 358 | |
| 359 // Needed for IE 6/7 | |
| 360 elm = dom.get('fullpage_styles'); | |
| 361 if (elm.styleSheet) | |
| 362 elm.styleSheet.cssText = styles; | |
| 363 } | |
| 364 }, | |
| 365 | |
| 366 _getDefaultHeader : function() { | |
| 367 var header = '', editor = this.editor, value, styles = ''; | |
| 368 | |
| 369 if (editor.getParam('fullpage_default_xml_pi')) | |
| 370 header += '<?xml version="1.0" encoding="' + editor.getParam('fullpage_default_encoding', 'ISO-8859-1') + '" ?>\n'; | |
| 371 | |
| 372 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">'); | |
| 373 header += '\n<html>\n<head>\n'; | |
| 374 | |
| 375 if (value = editor.getParam('fullpage_default_title')) | |
| 376 header += '<title>' + value + '</title>\n'; | |
| 377 | |
| 378 if (value = editor.getParam('fullpage_default_encoding')) | |
| 379 header += '<meta http-equiv="Content-Type" content="text/html; charset=' + value + '" />\n'; | |
| 380 | |
| 381 if (value = editor.getParam('fullpage_default_font_family')) | |
| 382 styles += 'font-family: ' + value + ';'; | |
| 383 | |
| 384 if (value = editor.getParam('fullpage_default_font_size')) | |
| 385 styles += 'font-size: ' + value + ';'; | |
| 386 | |
| 387 if (value = editor.getParam('fullpage_default_text_color')) | |
| 388 styles += 'color: ' + value + ';'; | |
| 389 | |
| 390 header += '</head>\n<body' + (styles ? ' style="' + styles + '"' : '') + '>\n'; | |
| 391 | |
| 392 return header; | |
| 393 }, | |
| 394 | |
| 395 _getContent : function(ed, o) { | |
| 396 var self = this; | |
| 397 | |
| 398 if (!o.source_view || !ed.getParam('fullpage_hide_in_source_view')) | |
| 399 o.content = tinymce.trim(self.head) + '\n' + tinymce.trim(o.content) + '\n' + tinymce.trim(self.foot); | |
| 400 } | |
| 401 }); | |
| 402 | |
| 403 // Register plugin | |
| 404 tinymce.PluginManager.add('fullpage', tinymce.plugins.FullPagePlugin); | |
| 405 })(); |
