PageRenderTime 48ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/BlogEngine/BlogEngine.NET/editors/tiny_mce_3_4_3_1/plugins/fullpage/editor_plugin_src.js

#
JavaScript | 399 lines | 361 code | 23 blank | 15 comment | 10 complexity | 9ffc1b1dd312a248179801e4191cb8c2 MD5 | raw file
Possible License(s): LGPL-2.1, Apache-2.0, BSD-3-Clause
  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. (function() {
  11. var each = tinymce.each, Node = tinymce.html.Node;
  12. tinymce.create('tinymce.plugins.FullPagePlugin', {
  13. init : function(ed, url) {
  14. var t = this;
  15. t.editor = ed;
  16. // Register commands
  17. ed.addCommand('mceFullPageProperties', function() {
  18. ed.windowManager.open({
  19. file : url + '/fullpage.htm',
  20. width : 430 + parseInt(ed.getLang('fullpage.delta_width', 0)),
  21. height : 495 + parseInt(ed.getLang('fullpage.delta_height', 0)),
  22. inline : 1
  23. }, {
  24. plugin_url : url,
  25. data : t._htmlToData()
  26. });
  27. });
  28. // Register buttons
  29. ed.addButton('fullpage', {title : 'fullpage.desc', cmd : 'mceFullPageProperties'});
  30. ed.onBeforeSetContent.add(t._setContent, t);
  31. ed.onGetContent.add(t._getContent, t);
  32. },
  33. getInfo : function() {
  34. return {
  35. longname : 'Fullpage',
  36. author : 'Moxiecode Systems AB',
  37. authorurl : 'http://tinymce.moxiecode.com',
  38. infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/fullpage',
  39. version : tinymce.majorVersion + "." + tinymce.minorVersion
  40. };
  41. },
  42. // Private plugin internal methods
  43. _htmlToData : function() {
  44. var headerFragment = this._parseHeader(), data = {}, nodes, elm, matches, editor = this.editor;
  45. function getAttr(elm, name) {
  46. var value = elm.attr(name);
  47. return value || '';
  48. };
  49. // Default some values
  50. data.fontface = editor.getParam("fullpage_default_fontface", "");
  51. data.fontsize = editor.getParam("fullpage_default_fontsize", "");
  52. // Parse XML PI
  53. elm = headerFragment.firstChild;
  54. if (elm.type == 7) {
  55. data.xml_pi = true;
  56. matches = /encoding="([^"]+)"/.exec(elm.value);
  57. if (matches)
  58. data.docencoding = matches[1];
  59. }
  60. // Parse doctype
  61. elm = headerFragment.getAll('#doctype')[0];
  62. if (elm)
  63. data.doctype = '<!DOCTYPE' + elm.value + ">";
  64. // Parse title element
  65. elm = headerFragment.getAll('title')[0];
  66. if (elm && elm.firstChild) {
  67. data.metatitle = elm.firstChild.value;
  68. }
  69. // Parse meta elements
  70. each(headerFragment.getAll('meta'), function(meta) {
  71. var name = meta.attr('name'), httpEquiv = meta.attr('http-equiv'), matches;
  72. if (name)
  73. data['meta' + name.toLowerCase()] = meta.attr('content');
  74. else if (httpEquiv == "Content-Type") {
  75. matches = /charset\s*=\s*(.*)\s*/gi.exec(meta.attr('content'));
  76. if (matches)
  77. data.docencoding = matches[1];
  78. }
  79. });
  80. // Parse html attribs
  81. elm = headerFragment.getAll('html')[0];
  82. if (elm)
  83. data.langcode = getAttr(elm, 'lang') || getAttr(elm, 'xml:lang');
  84. // Parse stylesheet
  85. elm = headerFragment.getAll('link')[0];
  86. if (elm && elm.attr('rel') == 'stylesheet')
  87. data.stylesheet = elm.attr('href');
  88. // Parse body parts
  89. elm = headerFragment.getAll('body')[0];
  90. if (elm) {
  91. data.langdir = getAttr(elm, 'dir');
  92. data.style = getAttr(elm, 'style');
  93. data.visited_color = getAttr(elm, 'vlink');
  94. data.link_color = getAttr(elm, 'link');
  95. data.active_color = getAttr(elm, 'alink');
  96. }
  97. return data;
  98. },
  99. _dataToHtml : function(data) {
  100. var headerFragment, headElement, html, elm, value, dom = this.editor.dom;
  101. function setAttr(elm, name, value) {
  102. elm.attr(name, value ? value : undefined);
  103. };
  104. function addHeadNode(node) {
  105. if (headElement.firstChild)
  106. headElement.insert(node, headElement.firstChild);
  107. else
  108. headElement.append(node);
  109. };
  110. headerFragment = this._parseHeader();
  111. headElement = headerFragment.getAll('head')[0];
  112. if (!headElement) {
  113. elm = headerFragment.getAll('html')[0];
  114. headElement = new Node('head', 1);
  115. if (elm.firstChild)
  116. elm.insert(headElement, elm.firstChild, true);
  117. else
  118. elm.append(headElement);
  119. }
  120. // Add/update/remove XML-PI
  121. elm = headerFragment.firstChild;
  122. if (data.xml_pi) {
  123. value = 'version="1.0"';
  124. if (data.docencoding)
  125. value += ' encoding="' + data.docencoding + '"';
  126. if (elm.type != 7) {
  127. elm = new Node('xml', 7);
  128. headerFragment.insert(elm, headerFragment.firstChild, true);
  129. }
  130. elm.value = value;
  131. } else if (elm && elm.type == 7)
  132. elm.remove();
  133. // Add/update/remove doctype
  134. elm = headerFragment.getAll('#doctype')[0];
  135. if (data.doctype) {
  136. if (!elm) {
  137. elm = new Node('#doctype', 10);
  138. if (data.xml_pi)
  139. headerFragment.insert(elm, headerFragment.firstChild);
  140. else
  141. addHeadNode(elm);
  142. }
  143. elm.value = data.doctype.substring(9, data.doctype.length - 1);
  144. } else if (elm)
  145. elm.remove();
  146. // Add/update/remove title
  147. elm = headerFragment.getAll('title')[0];
  148. if (data.metatitle) {
  149. if (!elm) {
  150. elm = new Node('title', 1);
  151. elm.append(new Node('#text', 3)).value = data.metatitle;
  152. addHeadNode(elm);
  153. }
  154. }
  155. // Add meta encoding
  156. if (data.docencoding) {
  157. elm = null;
  158. each(headerFragment.getAll('meta'), function(meta) {
  159. if (meta.attr('http-equiv') == 'Content-Type')
  160. elm = meta;
  161. });
  162. if (!elm) {
  163. elm = new Node('meta', 1);
  164. elm.attr('http-equiv', 'Content-Type');
  165. elm.shortEnded = true;
  166. addHeadNode(elm);
  167. }
  168. elm.attr('content', 'text/html; charset=' + data.docencoding);
  169. }
  170. // Add/update/remove meta
  171. each('keywords,description,author,copyright,robots'.split(','), function(name) {
  172. var nodes = headerFragment.getAll('meta'), i, meta, value = data['meta' + name];
  173. for (i = 0; i < nodes.length; i++) {
  174. meta = nodes[i];
  175. if (meta.attr('name') == name) {
  176. if (value)
  177. meta.attr('content', value);
  178. else
  179. meta.remove();
  180. return;
  181. }
  182. }
  183. if (value) {
  184. elm = new Node('meta', 1);
  185. elm.attr('name', name);
  186. elm.attr('content', value);
  187. elm.shortEnded = true;
  188. addHeadNode(elm);
  189. }
  190. });
  191. // Add/update/delete link
  192. elm = headerFragment.getAll('link')[0];
  193. if (elm && elm.attr('rel') == 'stylesheet') {
  194. if (data.stylesheet)
  195. elm.attr('href', data.stylesheet);
  196. else
  197. elm.remove();
  198. } else if (data.stylesheet) {
  199. elm = new Node('link', 1);
  200. elm.attr({
  201. rel : 'stylesheet',
  202. text : 'text/css',
  203. href : data.stylesheet
  204. });
  205. elm.shortEnded = true;
  206. addHeadNode(elm);
  207. }
  208. // Update body attributes
  209. elm = headerFragment.getAll('body')[0];
  210. if (elm) {
  211. setAttr(elm, 'dir', data.langdir);
  212. setAttr(elm, 'style', data.style);
  213. setAttr(elm, 'vlink', data.visited_color);
  214. setAttr(elm, 'link', data.link_color);
  215. setAttr(elm, 'alink', data.active_color);
  216. // Update iframe body as well
  217. dom.setAttribs(this.editor.getBody(), {
  218. style : data.style,
  219. dir : data.dir,
  220. vLink : data.visited_color,
  221. link : data.link_color,
  222. aLink : data.active_color
  223. });
  224. }
  225. // Set html attributes
  226. elm = headerFragment.getAll('html')[0];
  227. if (elm) {
  228. setAttr(elm, 'lang', data.langcode);
  229. setAttr(elm, 'xml:lang', data.langcode);
  230. }
  231. // Serialize header fragment and crop away body part
  232. html = new tinymce.html.Serializer({
  233. validate: false,
  234. indent: true,
  235. apply_source_formatting : true,
  236. indent_before: 'head,html,body,meta,title,script,link,style',
  237. indent_after: 'head,html,body,meta,title,script,link,style'
  238. }).serialize(headerFragment);
  239. this.head = html.substring(0, html.indexOf('</body>'));
  240. },
  241. _parseHeader : function() {
  242. // Parse the contents with a DOM parser
  243. return new tinymce.html.DomParser({
  244. validate: false,
  245. root_name: '#document'
  246. }).parse(this.head);
  247. },
  248. _setContent : function(ed, o) {
  249. var self = this, startPos, endPos, content = o.content, headerFragment, styles = '', dom = self.editor.dom, elm;
  250. function low(s) {
  251. return s.replace(/<\/?[A-Z]+/g, function(a) {
  252. return a.toLowerCase();
  253. })
  254. };
  255. // Ignore raw updated if we already have a head, this will fix issues with undo/redo keeping the head/foot separate
  256. if (o.format == 'raw' && self.head)
  257. return;
  258. if (o.source_view && ed.getParam('fullpage_hide_in_source_view'))
  259. return;
  260. // Parse out head, body and footer
  261. content = content.replace(/<(\/?)BODY/gi, '<$1body');
  262. startPos = content.indexOf('<body');
  263. if (startPos != -1) {
  264. startPos = content.indexOf('>', startPos);
  265. self.head = low(content.substring(0, startPos + 1));
  266. endPos = content.indexOf('</body', startPos);
  267. if (endPos == -1)
  268. endPos = content.length;
  269. o.content = content.substring(startPos + 1, endPos);
  270. self.foot = low(content.substring(endPos));
  271. } else {
  272. self.head = this._getDefaultHeader();
  273. self.foot = '\n</body>\n</html>';
  274. }
  275. // Parse header and update iframe
  276. headerFragment = self._parseHeader();
  277. each(headerFragment.getAll('style'), function(node) {
  278. if (node.firstChild)
  279. styles += node.firstChild.value;
  280. });
  281. elm = headerFragment.getAll('body')[0];
  282. if (elm) {
  283. dom.setAttribs(self.editor.getBody(), {
  284. style : elm.attr('style') || '',
  285. dir : elm.attr('dir') || '',
  286. vLink : elm.attr('vlink') || '',
  287. link : elm.attr('link') || '',
  288. aLink : elm.attr('alink') || ''
  289. });
  290. }
  291. if (styles)
  292. dom.add(self.editor.getDoc().getElementsByTagName('head')[0], 'style', {id : 'fullpage_styles'}, styles);
  293. else
  294. dom.remove('fullpage_styles');
  295. },
  296. _getDefaultHeader : function() {
  297. var header = '', editor = this.editor, value, styles = '';
  298. if (editor.getParam('fullpage_default_xml_pi'))
  299. header += '<?xml version="1.0" encoding="' + editor.getParam('fullpage_default_encoding', 'ISO-8859-1') + '" ?>\n';
  300. 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">');
  301. header += '\n<html>\n<head>\n';
  302. if (value = editor.getParam('fullpage_default_title'))
  303. header += '<title>' + value + '</title>\n';
  304. if (value = editor.getParam('fullpage_default_encoding'))
  305. header += '<meta http-equiv="Content-Type" content="text/html; charset=' + value + '" />\n';
  306. if (value = editor.getParam('fullpage_default_font_family'))
  307. styles += 'font-family: ' + value + ';';
  308. if (value = editor.getParam('fullpage_default_font_size'))
  309. styles += 'font-size: ' + value + ';';
  310. if (value = editor.getParam('fullpage_default_text_color'))
  311. styles += 'color: ' + value + ';';
  312. header += '</head>\n<body' + (styles ? ' style="' + styles + '"' : '') + '>\n';
  313. return header;
  314. },
  315. _getContent : function(ed, o) {
  316. var self = this;
  317. if (!o.source_view || !ed.getParam('fullpage_hide_in_source_view'))
  318. o.content = tinymce.trim(self.head) + '\n' + tinymce.trim(o.content) + '\n' + tinymce.trim(self.foot);
  319. }
  320. });
  321. // Register plugin
  322. tinymce.PluginManager.add('fullpage', tinymce.plugins.FullPagePlugin);
  323. })();