|
1 /** |
|
2 * $Id: editor_plugin_src.js 162 2007-01-03 16:16:52Z spocke $ |
|
3 * |
|
4 * @author Moxiecode |
|
5 * @copyright Copyright © 2004-2007, Moxiecode Systems AB, All rights reserved. |
|
6 */ |
|
7 |
|
8 tinyMCE.importPluginLanguagePack('template'); |
|
9 |
|
10 var TinyMCE_TemplatePlugin = { |
|
11 getInfo : function() { |
|
12 return { |
|
13 longname : 'Template plugin', |
|
14 author : 'Moxiecode Systems AB', |
|
15 authorurl : 'http://www.moxiecode.com', |
|
16 infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/template', |
|
17 version : tinyMCE.majorVersion + "." + tinyMCE.minorVersion |
|
18 }; |
|
19 }, |
|
20 |
|
21 initInstance : function(inst) { |
|
22 var cdate, mdate, content, x = 0, key, value, rvals, ds = inst.getData('template'); |
|
23 |
|
24 // ensure the required elements and sttributes are added |
|
25 //inst.cleanup.addRuleStr('*[' + TinyMCE_TemplatePlugin.TMPL_DATE_SRC_ATTR + '],div[title,tsrc]'); |
|
26 |
|
27 //setup template content functions |
|
28 // creation date and modified date classes |
|
29 cdate = tinyMCE.getParam("template_cdate_classes", '').split(/\s+/); |
|
30 mdate = tinyMCE.getParam("template_mdate_classes", '').split(/\s+/); |
|
31 |
|
32 // classes that specify where selected content should go |
|
33 content = tinyMCE.getParam("template_selected_content_classes", '').split(/\s+/); |
|
34 |
|
35 for (x = 0; x < cdate.length; x++) |
|
36 TinyMCE_TemplatePlugin.functions[cdate[x]] = TinyMCE_TemplatePlugin.functions['cdate']; |
|
37 |
|
38 for (x = 0; x < mdate.length; x++) |
|
39 TinyMCE_TemplatePlugin.functions[mdate[x]] = TinyMCE_TemplatePlugin.functions['mdate']; |
|
40 |
|
41 for (x = 0; x < content.length; x++) |
|
42 TinyMCE_TemplatePlugin.functions[content[x]] = TinyMCE_TemplatePlugin.functions['selectedContent']; |
|
43 |
|
44 // special template functions for replacing template content |
|
45 rvals = tinyMCE.getParam("template_replace_values", false); |
|
46 for (key in rvals) { |
|
47 value = rvals[key]; |
|
48 |
|
49 if (typeof value == "function") |
|
50 TinyMCE_TemplatePlugin.functions[key] = value; |
|
51 else |
|
52 TinyMCE_TemplatePlugin.functions[key] = TinyMCE_TemplatePlugin.functions['generateReplacer'](value); |
|
53 } |
|
54 |
|
55 // Setup replace_items |
|
56 rvals = tinyMCE.getParam("template_replace_values", false); |
|
57 ds.replace_items = {}; |
|
58 |
|
59 for (key in rvals) |
|
60 ds.replace_items[key] = rvals[key]; |
|
61 |
|
62 inst.addShortcut('ctrl', 't', 'lang_template_desc', 'mceTemplate'); |
|
63 |
|
64 // Setup data storage |
|
65 ds.currentAction = "insert"; |
|
66 ds.currentTmplNode = null; |
|
67 }, |
|
68 |
|
69 getControlHTML : function(cn) { |
|
70 switch (cn) { |
|
71 case "template": |
|
72 return tinyMCE.getButtonHTML(cn, 'lang_template_desc', '{$pluginurl}/images/template.gif', 'mceTemplate', true); |
|
73 } |
|
74 |
|
75 return ""; |
|
76 }, |
|
77 |
|
78 execCommand : function(editor_id, element, command, user_interface, value) { |
|
79 var nodeArray, current, newTmpl, x, inst = tinyMCE.getInstanceById(editor_id), ds = inst.getData('template'), telm; |
|
80 |
|
81 switch (command) { |
|
82 case "mceTemplate": |
|
83 if (user_interface) { |
|
84 // called from toolbar button - show the popup |
|
85 tinyMCE.openWindow({ |
|
86 file : '../../plugins/template/template.htm', // Relative to theme |
|
87 width : tinyMCE.getParam('template_popup_width', 750), |
|
88 height : tinyMCE.getParam('template_popup_height', 600) |
|
89 }, {editor_id : editor_id, resizable : "yes", scrollbars : "no", pluginObj : TinyMCE_TemplatePlugin}); |
|
90 } else { |
|
91 // internal command do the template stuff |
|
92 |
|
93 // get the returned HTML string from the pop-up and appened it to a DIV element |
|
94 telm = TinyMCE_TemplatePlugin._convertToNode(value.body); |
|
95 |
|
96 // Find template body |
|
97 nodeArray = tinyMCE.selectElements(telm, 'div', function(n) { |
|
98 return tinyMCE.hasCSSClass(n, TinyMCE_TemplatePlugin.TMPL); |
|
99 }); |
|
100 |
|
101 telm = nodeArray.length > 0 ? nodeArray[0] : null; |
|
102 nodeArray = []; |
|
103 |
|
104 if (ds.currentAction == "insert") { |
|
105 //insert new template after applying all the template content functions |
|
106 |
|
107 // Is it a template or snippet |
|
108 if (telm) { |
|
109 tinyMCE.execCommand('mceBeginUndoLevel'); |
|
110 ds.currentAction = "insert-new"; |
|
111 TinyMCE_TemplatePlugin._insertTemplate(editor_id, telm, value.title, value.tsrc, true); |
|
112 ds.currentAction == "insert"; |
|
113 tinyMCE.execCommand('mceEndUndoLevel'); |
|
114 tinyMCE.execInstanceCommand(editor_id, 'mceCleanup', false); |
|
115 } else |
|
116 tinyMCE.execCommand('mceInsertContent', false, this._replaceValues(value.body)); |
|
117 } else { |
|
118 // First collect the selected template in the editor |
|
119 nodeArray = TinyMCE_TemplatePlugin._collectTemplateElements(ds.currentTmplNode); |
|
120 current = []; |
|
121 newTmpl = []; |
|
122 tinyMCE.getNodeTree(telm, newTmpl); |
|
123 |
|
124 for (x=0; x<nodeArray.length; x++) |
|
125 tinyMCE.getNodeTree(nodeArray[x], current); |
|
126 |
|
127 /** |
|
128 * inner function used in the loop below. |
|
129 * compares the supplied HTML element to the new template to: |
|
130 * - find a match with the new template and copy the element's content over |
|
131 * - find no match and indicate content will be lost |
|
132 */ |
|
133 var _test = function(elm) { |
|
134 var replaced = true; |
|
135 |
|
136 if (elm.className) { |
|
137 var names = elm.className.split(/\s+/), c, n; |
|
138 |
|
139 for (c = 0; c<names.length; c++) { |
|
140 if (names[c].match(/^mce/i)) |
|
141 continue; // ignore all internal class names |
|
142 |
|
143 for (n=0; n<newTmpl.length; n++){ |
|
144 replaced = false; |
|
145 |
|
146 if (newTmpl[n].className && newTmpl[n].className.match(new RegExp(names[c], "gi"))) { |
|
147 newTmpl[n].innerHTML = elm.innerHTML; |
|
148 //if(tinyMCE.getAttrib(elm,TinyMCE_TemplatePlugin.TMPL_DATE_SRC_ATTR,"") != "") { |
|
149 // tinyMCE.setAttrib(newTmpl[n], TinyMCE_TemplatePlugin.TMPL_DATE_SRC_ATTR, tinyMCE.getAttrib(elm,TinyMCE_TemplatePlugin.TMPL_DATE_SRC_ATTR)); |
|
150 //} |
|
151 replaced = true; |
|
152 break; |
|
153 } |
|
154 |
|
155 } |
|
156 } |
|
157 } |
|
158 |
|
159 return replaced; |
|
160 }; |
|
161 |
|
162 // comparison loop - first mis-match alerts user for confirmation. |
|
163 var cont = true; |
|
164 var asked = false; |
|
165 |
|
166 for (x = 0; x < current.length; x++) { |
|
167 if(!_test(current[x])) { |
|
168 cont = (asked || confirm("The new template has less elements than the currently selected content.\nIf you proceed you will loose content.\nAre you sure you want to proceed?", "Proceed?")); |
|
169 asked = true; |
|
170 |
|
171 if (!cont) |
|
172 break; |
|
173 } |
|
174 }; |
|
175 |
|
176 // apply replacement if allowed to |
|
177 if (cont) { |
|
178 tinyMCE.execCommand('mceBeginUndoLevel'); |
|
179 TinyMCE_TemplatePlugin._replaceTemplateContent(current[0], editor_id, telm, value.title, value.tsrc); |
|
180 tinyMCE.execCommand('mceEndUndoLevel'); |
|
181 tinyMCE.execInstanceCommand(editor_id, 'mceCleanup', false); |
|
182 } |
|
183 } |
|
184 |
|
185 tinyMCE.triggerNodeChange(true); |
|
186 } |
|
187 |
|
188 return true; |
|
189 } |
|
190 |
|
191 return false; |
|
192 }, |
|
193 |
|
194 handleNodeChange : function(editor_id, node, undo_index, undo_levels, visual_aid, any_selection) { |
|
195 var inst = tinyMCE.getInstanceById(editor_id), ds = inst.getData('template'); |
|
196 |
|
197 if (tinyMCE.hasCSSClass(node, TinyMCE_TemplatePlugin.TMPL_ELEMENT) || tinyMCE.hasCSSClass(node.parentNode, TinyMCE_TemplatePlugin.TMPL_ELEMENT)) { |
|
198 tinyMCE.switchClass(editor_id + '_template', 'mceButtonSelected'); |
|
199 ds.currentAction = "update"; |
|
200 ds.currentTmplNode = node; |
|
201 |
|
202 return true; |
|
203 } |
|
204 |
|
205 ds.currentAction = "insert"; |
|
206 ds.currentTmplNode = null; |
|
207 tinyMCE.switchClass(editor_id + '_template', 'mceButtonNormal'); |
|
208 |
|
209 return false; |
|
210 }, |
|
211 |
|
212 cleanup : function(type, content, inst) { |
|
213 var nodes = []; |
|
214 |
|
215 switch (type) { |
|
216 case "get_from_editor": |
|
217 // replace the opening wrapper div tag with a HTML comment |
|
218 content = content.replace( |
|
219 new RegExp('<div class="' + TinyMCE_TemplatePlugin.TMPL + '">', 'gi'), |
|
220 '<!-- ' + TinyMCE_TemplatePlugin.TMPL_BEGINS + ' -->' |
|
221 ); |
|
222 |
|
223 // delete any empty template wrappers |
|
224 content = content.replace( |
|
225 new RegExp('<div class="' + TinyMCE_TemplatePlugin.TMPL + '">(\s| | )?(<!-- ' + TinyMCE_TemplatePlugin.TMPL_ENDS + ' -->|\s)?</div>', 'gi'), |
|
226 '' |
|
227 ); |
|
228 |
|
229 // replace the closing wrapper tag |
|
230 content = content.replace( |
|
231 new RegExp('<!-- ' + TinyMCE_TemplatePlugin.TMPL_ENDS + ' --></div>', 'gi'), |
|
232 '<!-- ' + TinyMCE_TemplatePlugin.TMPL_ENDS + ' -->' |
|
233 ); |
|
234 |
|
235 break; |
|
236 |
|
237 case "insert_to_editor": |
|
238 // replace HTML comment with DIV wrapper |
|
239 content = content.replace( |
|
240 new RegExp('<!-- ' + TinyMCE_TemplatePlugin.TMPL_BEGINS + ' -->', 'gi'), |
|
241 '<div class="' + TinyMCE_TemplatePlugin.TMPL + '">' |
|
242 ); |
|
243 |
|
244 content = content.replace( |
|
245 new RegExp('<!-- ' + TinyMCE_TemplatePlugin.TMPL_ENDS + ' -->', 'gi'), |
|
246 '<!-- ' + TinyMCE_TemplatePlugin.TMPL_ENDS + ' --></div>' |
|
247 ); |
|
248 |
|
249 break; |
|
250 |
|
251 case "get_from_editor_dom": |
|
252 // apply template content replacement functions |
|
253 nodes = tinyMCE.selectNodes(content, function(n) { |
|
254 return tinyMCE.hasCSSClass(n, TinyMCE_TemplatePlugin.TMPL_ELEMENT); |
|
255 } |
|
256 ); |
|
257 |
|
258 TinyMCE_TemplatePlugin._applyFunctions(nodes, type); |
|
259 |
|
260 break; |
|
261 |
|
262 case "insert_to_editor_dom": |
|
263 // apply template content replacement functions |
|
264 nodes = tinyMCE.selectNodes(content, function(n) { |
|
265 return tinyMCE.hasCSSClass(n, TinyMCE_TemplatePlugin.TMPL_ELEMENT); |
|
266 } |
|
267 ); |
|
268 |
|
269 TinyMCE_TemplatePlugin._applyFunctions(nodes, type); |
|
270 |
|
271 break; |
|
272 } |
|
273 |
|
274 return content; |
|
275 }, |
|
276 |
|
277 // Private plugin internal methods |
|
278 |
|
279 /** |
|
280 * Creates a HTML DIV element and sets the innerHTML to equal the temlate innerHTML so that the template can be manipulated as DOM nodes. |
|
281 * |
|
282 * @param {string} Template innerHTML |
|
283 * @return a HTML Element |
|
284 * @type HTMLElement |
|
285 */ |
|
286 _convertToNode : function(html) { |
|
287 var elm = document.createElement('div'); |
|
288 |
|
289 elm.innerHTML = html; |
|
290 |
|
291 return elm; |
|
292 }, |
|
293 |
|
294 /** |
|
295 * pass an array of template html elements and they will have the template class name added and any template functions applied |
|
296 * |
|
297 * @param {array} template HTML elements |
|
298 * @return array of template HTML elements |
|
299 * @type array |
|
300 */ |
|
301 _prepareTemplateContent : function(elms) { |
|
302 var x, n, nodes = []; |
|
303 |
|
304 if (!elms) |
|
305 return {}; |
|
306 |
|
307 if (!elms.length) |
|
308 elms = [elms]; |
|
309 |
|
310 for (x = 0; x<elms.length; x++) |
|
311 tinyMCE.getNodeTree(elms[x], nodes, 1); |
|
312 |
|
313 for (n = 0; n<nodes.length; n++) { |
|
314 tinyMCE.addCSSClass(nodes[n], TinyMCE_TemplatePlugin.TMPL_ELEMENT); |
|
315 TinyMCE_TemplatePlugin._applyFunctions(nodes[n], TinyMCE_TemplatePlugin.TMPL_TEMPLATE_EVENT); |
|
316 } |
|
317 |
|
318 return elms; |
|
319 }, |
|
320 |
|
321 _replaceValues : function(s) { |
|
322 var t = this, ds = tinyMCE.selectedInstance.getData('template'); |
|
323 |
|
324 return s.replace(/\{\$([^\}]+)\}/g, function(a, b) { |
|
325 var it = ds.replace_items[b]; |
|
326 |
|
327 if (it) { |
|
328 // Only supports text for now |
|
329 if (typeof(it) != 'function') |
|
330 return it; |
|
331 } |
|
332 |
|
333 return b; |
|
334 }); |
|
335 }, |
|
336 |
|
337 /** |
|
338 * Applies any special functions to the template elements |
|
339 * |
|
340 * @param {array} template HTML elements |
|
341 * @return array of template HTML elements |
|
342 * @type array |
|
343 */ |
|
344 _applyFunctions : function(elms, editor_event) { |
|
345 var x, elm, names, c, f; |
|
346 |
|
347 if (!elms) |
|
348 return {}; |
|
349 |
|
350 if (!elms.length) |
|
351 elms = [elms]; |
|
352 |
|
353 for(x = 0; x < elms.length; x++) { |
|
354 elm = elms[x]; |
|
355 |
|
356 if (elm.className){ |
|
357 names = elm.className.split(/\s+/); |
|
358 |
|
359 for (c = 0; c < names.length; c++){ |
|
360 if (names[c] == TinyMCE_TemplatePlugin.TMPL_ELEMENT) |
|
361 continue; |
|
362 |
|
363 f = (TinyMCE_TemplatePlugin.functions[names[c]] ? TinyMCE_TemplatePlugin.functions[names[c]] : TinyMCE_TemplatePlugin.functions['blank']); |
|
364 f(elm, editor_event); |
|
365 } |
|
366 } |
|
367 } |
|
368 |
|
369 return elms; |
|
370 }, |
|
371 |
|
372 /** |
|
373 * Given one node reference this function will collect all the nodes of the template to which it belongs. |
|
374 * It does this by finding the parent template wrapper DIV and returning all child nodes. |
|
375 * |
|
376 * @param {HTMLElement} a HTMLElement which is part of a template |
|
377 * @return array of template HTML elements |
|
378 * @type array |
|
379 */ |
|
380 _collectTemplateElements : function(node) { |
|
381 var nodeArray = [], p; |
|
382 |
|
383 p = tinyMCE.getParentElement(node, 'DIV', function(n) { |
|
384 return tinyMCE.hasCSSClass(n, TinyMCE_TemplatePlugin.TMPL); |
|
385 }); |
|
386 |
|
387 if (p) |
|
388 tinyMCE.getNodeTree(p, nodeArray); |
|
389 |
|
390 return nodeArray; |
|
391 }, |
|
392 |
|
393 /** |
|
394 * Simply calls TinyMCE_TemplatePlugin._deleteTemplateContent and then TinyMCE_TemplatePlugin._insertTemplate |
|
395 * |
|
396 * @param {HTMLElement} currently selected template node in editor |
|
397 * @param {string} id of editor instance |
|
398 * @param {HTMLElement} template contents as a HTMLElement (the parent DIV wrapper) |
|
399 * @param {string} title of template (unused as yet) |
|
400 * @param {string} source URI of the template file (unused as yet) |
|
401 * @return array of template HTML elements |
|
402 * @type array |
|
403 */ |
|
404 _replaceTemplateContent : function(currentNode, editor_id, newTemplate, title, tsrc) { |
|
405 TinyMCE_TemplatePlugin._deleteTemplateContent(currentNode); |
|
406 TinyMCE_TemplatePlugin._insertTemplate(editor_id, newTemplate, title, tsrc, false); |
|
407 }, |
|
408 |
|
409 /** |
|
410 * Deletes a template from the editor content |
|
411 * Finds the parent DIV wrapper and deletes it and all children |
|
412 * @param {HTMLElement} currently selected template node in editor |
|
413 */ |
|
414 _deleteTemplateContent : function(node) { |
|
415 var p = tinyMCE.getParentElement(node, 'DIV', function(n) { |
|
416 return tinyMCE.hasCSSClass(n, TinyMCE_TemplatePlugin.TMPL); |
|
417 }); |
|
418 |
|
419 if (p) |
|
420 p.parentNode.removeChild(p, true); |
|
421 }, |
|
422 |
|
423 /** |
|
424 * Inserts a template into the specified editor |
|
425 * |
|
426 * @param {string} id of editor instance |
|
427 * @param {HTMLElement} template contents as a HTMLElement (the parent DIV wrapper) |
|
428 * @param {string} title of template (unused as yet) |
|
429 * @param {string} source URI of the template file (unused as yet) |
|
430 */ |
|
431 _insertTemplate : function(editor_id, elm, title, tsrc, incComments) { |
|
432 var html; |
|
433 |
|
434 TinyMCE_TemplatePlugin._prepareTemplateContent(elm); |
|
435 |
|
436 html = '<div class="' + TinyMCE_TemplatePlugin.TMPL + '">'; |
|
437 html += elm.innerHTML; |
|
438 html += '<!-- ' + TinyMCE_TemplatePlugin.TMPL_ENDS + ' --></div>'; |
|
439 |
|
440 tinyMCE.execInstanceCommand(editor_id, 'mceInsertContent', false, html); |
|
441 }, |
|
442 |
|
443 /** |
|
444 * template functions - functions for modifying template content |
|
445 */ |
|
446 functions : { |
|
447 blank : function(elm, editor_event) {}, |
|
448 |
|
449 cdate : function(elm, editor_event) { |
|
450 var d, dsrc; |
|
451 |
|
452 if (editor_event != TinyMCE_TemplatePlugin.TMPL_TEMPLATE_EVENT) |
|
453 return; |
|
454 |
|
455 d = new Date(); |
|
456 // find out if the creation date was previously stored |
|
457 dsrc = elm.innerHTML.match(new RegExp("<!-- " + TinyMCE_TemplatePlugin.TMPL_DATE_SRC_ATTR + ":(.*) -->", "gi")); |
|
458 |
|
459 if (dsrc) |
|
460 d = new Date(RegExp.$1); |
|
461 |
|
462 elm.innerHTML = TinyMCE_TemplatePlugin._getDateTime(d, tinyMCE.getParam("template_cdate_format", tinyMCE.getLang("lang_template_def_date_format"))); |
|
463 //now we have to store the date value in a format easily read again, in case a future template change changes the date format... |
|
464 elm.innerHTML += "<!-- " + TinyMCE_TemplatePlugin.TMPL_DATE_SRC_ATTR + ":" + d.toUTCString() + " -->"; |
|
465 }, |
|
466 |
|
467 mdate : function(elm, editor_event) { |
|
468 var d = new Date(); |
|
469 elm.innerHTML = TinyMCE_TemplatePlugin._getDateTime(d, tinyMCE.getParam("template_mdate_format", tinyMCE.getLang("lang_template_def_date_format"))); |
|
470 }, |
|
471 |
|
472 /** |
|
473 * This will insert the currently selected editor content into the template element. |
|
474 * It only does this if the template inserted is a new one and if the element does not have the special class. |
|
475 * The special class name prevents this from happening more than once. |
|
476 */ |
|
477 selectedContent : function(elm, editor_event) { |
|
478 var ds = tinyMCE.selectedInstance.getData('template'); |
|
479 |
|
480 if (editor_event != TinyMCE_TemplatePlugin.TMPL_TEMPLATE_EVENT) |
|
481 return; |
|
482 |
|
483 if (ds.currentAction == "insert-new" && !tinyMCE.hasCSSClass(elm, TinyMCE_TemplatePlugin.TMPL_SEL_HTML_DONE)) { |
|
484 elm.innerHTML = tinyMCE.selectedInstance.selection.getSelectedHTML(); |
|
485 tinyMCE.addCSSClass(elm, TinyMCE_TemplatePlugin.TMPL_SEL_HTML_DONE); |
|
486 } |
|
487 }, |
|
488 |
|
489 /** |
|
490 * When the plugin is initialised this generates the functions that insert configured strings into template elements. |
|
491 */ |
|
492 generateReplacer : function(s) { |
|
493 return function(elm, editor_event) {elm.innerHTML = "" + s;}; |
|
494 } |
|
495 }, |
|
496 |
|
497 /** |
|
498 * formats a date according to the format string - straight from the 'insert date/time' plugin |
|
499 * |
|
500 * @param {Date} date object |
|
501 * @param {string} format string |
|
502 * @return formatted date |
|
503 * @type string |
|
504 */ |
|
505 _getDateTime : function(d,fmt) { |
|
506 if (!fmt) |
|
507 return ""; |
|
508 |
|
509 function addZeros(value, len) { |
|
510 var i; |
|
511 |
|
512 value = "" + value; |
|
513 |
|
514 if (value.length < len) { |
|
515 for (i=0; i<(len-value.length); i++) |
|
516 value = "0" + value; |
|
517 } |
|
518 |
|
519 return value; |
|
520 } |
|
521 |
|
522 fmt = fmt.replace("%D", "%m/%d/%y"); |
|
523 fmt = fmt.replace("%r", "%I:%M:%S %p"); |
|
524 fmt = fmt.replace("%Y", "" + d.getFullYear()); |
|
525 fmt = fmt.replace("%y", "" + d.getYear()); |
|
526 fmt = fmt.replace("%m", addZeros(d.getMonth()+1, 2)); |
|
527 fmt = fmt.replace("%d", addZeros(d.getDate(), 2)); |
|
528 fmt = fmt.replace("%H", "" + addZeros(d.getHours(), 2)); |
|
529 fmt = fmt.replace("%M", "" + addZeros(d.getMinutes(), 2)); |
|
530 fmt = fmt.replace("%S", "" + addZeros(d.getSeconds(), 2)); |
|
531 fmt = fmt.replace("%I", "" + ((d.getHours() + 11) % 12 + 1)); |
|
532 fmt = fmt.replace("%p", "" + (d.getHours() < 12 ? "AM" : "PM")); |
|
533 fmt = fmt.replace("%B", "" + tinyMCE.getLang("lang_template_months_long")[d.getMonth()]); |
|
534 fmt = fmt.replace("%b", "" + tinyMCE.getLang("lang_template_months_short")[d.getMonth()]); |
|
535 fmt = fmt.replace("%A", "" + tinyMCE.getLang("lang_template_day_long")[d.getDay()]); |
|
536 fmt = fmt.replace("%a", "" + tinyMCE.getLang("lang_template_day_short")[d.getDay()]); |
|
537 fmt = fmt.replace("%%", "%"); |
|
538 |
|
539 return fmt; |
|
540 }, |
|
541 |
|
542 TMPL_ELEMENT : 'mceTmplElm', |
|
543 TMPL : 'mceTmpl', |
|
544 TMPL_BEGINS : 'mceTmplBegins', |
|
545 TMPL_SEL_HTML_DONE : 'mceSelHTMLDone', |
|
546 TMPL_ENDS : 'mceTmplEnds', |
|
547 TMPL_DATE_SRC_ATTR : 'mcetmpldtesrc', |
|
548 TMPL_TEMPLATE_EVENT : 'prepare_template' |
|
549 }; |
|
550 |
|
551 tinyMCE.addPlugin("template", TinyMCE_TemplatePlugin); |