PageRenderTime 49ms CodeModel.GetById 24ms app.highlight 20ms RepoModel.GetById 2ms 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
  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			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>' + value + '</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;
387		},
388
389		_getContent : function(ed, o) {
390			var self = this;
391
392			if (!o.source_view || !ed.getParam('fullpage_hide_in_source_view'))
393				o.content = tinymce.trim(self.head) + '\n' + tinymce.trim(o.content) + '\n' + tinymce.trim(self.foot);
394		}
395	});
396
397	// Register plugin
398	tinymce.PluginManager.add('fullpage', tinymce.plugins.FullPagePlugin);
399})();