1 | /** |
---|
2 | * TinyMCE Plugin for OpenPNE |
---|
3 | * |
---|
4 | * @author Kousuke Ebihara |
---|
5 | */ |
---|
6 | |
---|
7 | (function() { |
---|
8 | |
---|
9 | tinymce.create('tinymce.ui.OpenPNEColorButton:tinymce.ui.ColorSplitButton', { |
---|
10 | renderHTML : function() { |
---|
11 | var s = this.settings, h = '<a id="' + this.id + '" href="javascript:;" class="mceButton mceButtonEnabled ' + s['class'] |
---|
12 | + '" onmousedown="return false;" onclick="return false;" title="' + tinymce.DOM.encode(s.title) + '">'; |
---|
13 | |
---|
14 | if (s.image) { |
---|
15 | h += '<img class="mceIcon" src="' + s.image + '" /></a>'; |
---|
16 | } else { |
---|
17 | h += '<span class="mceIcon ' + s['class'] + '"></span></a>'; |
---|
18 | } |
---|
19 | |
---|
20 | return h; |
---|
21 | }, |
---|
22 | |
---|
23 | postRender : function() { |
---|
24 | tinymce.dom.Event.add(this.id, 'click', this.showMenu, this); |
---|
25 | }, |
---|
26 | |
---|
27 | setColor : function(c) { |
---|
28 | this.value = c; |
---|
29 | this.hideMenu(); |
---|
30 | this.settings.onselect(c); |
---|
31 | } |
---|
32 | }); |
---|
33 | |
---|
34 | tinymce.create('tinymce.ui.OpenPNEEmojiButton:tinymce.ui.ColorSplitButton', { |
---|
35 | OpenPNEEmojiButton : function(id, s) { |
---|
36 | var t = this; |
---|
37 | |
---|
38 | t.parent(id, s); |
---|
39 | |
---|
40 | t.settings = s; |
---|
41 | }, |
---|
42 | |
---|
43 | renderMenu : function() { |
---|
44 | var t = this, m, i = 0, s = t.settings, n, tb, tr, w; |
---|
45 | var DOM = tinymce.DOM, Event = tinymce.dom.Event, is = tinymce.is, each = tinymce.each; |
---|
46 | w = DOM.add(s.menu_container, 'div', {id : t.id + '_menu', dir : 'ltr', 'class' : s['menu_class'] + ' ' + s['class'], |
---|
47 | style : 'position:absolute;left:0;top:-1000px;'}); |
---|
48 | m = DOM.add(w, 'div', {'class' : s['class'] + ' mceSplitButtonMenu'}); |
---|
49 | DOM.add(m, 'span', {'class' : 'mceMenuLine'}); |
---|
50 | |
---|
51 | n = DOM.add(m, 'table', {'class' : 'mceEmojiSplitMenu'}); |
---|
52 | tb = DOM.add(n, 'tbody'); |
---|
53 | |
---|
54 | for (var num in s.emoji) { |
---|
55 | var emoji = s.emoji[num]; |
---|
56 | for (var i = emoji.start; i <= emoji.end; i++) { |
---|
57 | if (i == emoji.start || i % 25 == 0) { |
---|
58 | tr = DOM.add(tb, 'tr'); |
---|
59 | } |
---|
60 | n = DOM.add(tr, 'td'); |
---|
61 | |
---|
62 | n = DOM.add(n, 'img', { |
---|
63 | src : "./skin/default/img/emoji/" + s.carrier +"/" + s.carrier + i + ".gif", |
---|
64 | alt : "[" + s.carrier + ":" + i + "]" |
---|
65 | }); |
---|
66 | |
---|
67 | Event.add(n, 'mousedown', function(e) { |
---|
68 | tinyMCE.execCommand("mceInsertContent", false, e.element().getAttribute("alt")); |
---|
69 | }); |
---|
70 | } |
---|
71 | } |
---|
72 | |
---|
73 | DOM.addClass(m, 'mceColorSplitMenu'); |
---|
74 | |
---|
75 | return w; |
---|
76 | }, |
---|
77 | |
---|
78 | renderHTML : function() { |
---|
79 | var s = this.settings, h = '<a id="' + this.id + '" href="javascript:;" class="mceButton mceButtonEnabled ' + s['class'] |
---|
80 | + '" onmousedown="return false;" onclick="return false;" title="' + tinymce.DOM.encode(s.title) + '">'; |
---|
81 | |
---|
82 | if (s.image) { |
---|
83 | h += '<img class="mceIcon" src="' + s.image + '" /></a>'; |
---|
84 | } else { |
---|
85 | h += '<span class="mceIcon ' + s['class'] + '"></span></a>'; |
---|
86 | } |
---|
87 | |
---|
88 | return h; |
---|
89 | }, |
---|
90 | |
---|
91 | postRender : function() { |
---|
92 | tinymce.dom.Event.add(this.id, 'click', this.showMenu, this); |
---|
93 | } |
---|
94 | }); |
---|
95 | |
---|
96 | tinymce.create('tinymce.ui.OpenPNECmdButton:tinymce.ui.Button', { |
---|
97 | renderHTML : function() { |
---|
98 | var s = this.settings; |
---|
99 | var h = '<a id="' + this.id + '" href="javascript:;" class="mceButton mceButtonEnabled ' + s['class'] + '" style="width:40px;" onmousedown="return false;" onclick="return false;" title="' + tinymce.DOM.encode(s.title) + '"><img class="mceIcon" style="width:40px;" src="' + s.image + '" /></a>'; |
---|
100 | |
---|
101 | return h; |
---|
102 | } |
---|
103 | }); |
---|
104 | |
---|
105 | tinymce.PluginManager.requireLangPack('openpne'); |
---|
106 | |
---|
107 | var config = pne_mce_editor_get_config(); |
---|
108 | |
---|
109 | tinymce.create('tinymce.plugins.OpenPNEPlugin', { |
---|
110 | init : function(ed, url) { |
---|
111 | var t = this; |
---|
112 | |
---|
113 | // change the editor setting |
---|
114 | ed.settings.content_css = url + "/css/editor.css"; |
---|
115 | |
---|
116 | // command |
---|
117 | ed.addCommand('mceOpenPNE_op_b', function() { |
---|
118 | tinyMCE.execCommand("Bold"); |
---|
119 | }); |
---|
120 | ed.addCommand('mceOpenPNE_op_u', function() { |
---|
121 | tinyMCE.execCommand("Underline"); |
---|
122 | }); |
---|
123 | ed.addCommand('mceOpenPNE_op_s', function() { |
---|
124 | tinyMCE.execCommand("Strikethrough"); |
---|
125 | }); |
---|
126 | ed.addCommand('mceOpenPNE_op_i', function() { |
---|
127 | tinyMCE.execCommand("Italic"); |
---|
128 | }); |
---|
129 | ed.addCommand('mceOpenPNE_op_large', function() { |
---|
130 | tinyMCE.execCommand("Fontsize", false, 5); |
---|
131 | }); |
---|
132 | ed.addCommand('mceOpenPNE_op_small', function() { |
---|
133 | tinyMCE.execCommand("Fontsize", false, 1); |
---|
134 | }); |
---|
135 | ed.addCommand('mceOpenPNE_op_image', function() { |
---|
136 | window.open(config.op_image.contentURL, '', 'width=600,height=550,toolbar=no,scrollbars=yes,left=10,top=10'); |
---|
137 | }); |
---|
138 | ed.addCommand('mceOpenPNE_op_cmd', function() { |
---|
139 | window.open('http://www.openpne.jp/cmd/'); |
---|
140 | }); |
---|
141 | |
---|
142 | // button |
---|
143 | for (var key in config) { |
---|
144 | var value = config[key]; |
---|
145 | if (value.isEnabled && key != "op_color") { |
---|
146 | ed.addButton(key, {title : '{#openpne.' + key + '}', image: value.imageURL, cmd : 'mceOpenPNE_' + key}); |
---|
147 | } |
---|
148 | } |
---|
149 | |
---|
150 | // event |
---|
151 | ed.onBeforeSetContent.add(function(ed, o) { // To preview mode |
---|
152 | o.content = t._textToPreview(o.content); |
---|
153 | }); |
---|
154 | ed.onPostProcess.add(function(ed, o) { // To text mode |
---|
155 | if (o.save) { |
---|
156 | if (ed.isHidden()) { |
---|
157 | o.content = ed.getElement().value; |
---|
158 | } else { |
---|
159 | o.content = t._previewToText(o.content, ed); |
---|
160 | } |
---|
161 | } |
---|
162 | }); |
---|
163 | ed.onNodeChange.add(function(ed, cm, n) { |
---|
164 | cm.setActive('mce_editor_textarea_op_b', n.nodeName.toLowerCase() == 'b'); |
---|
165 | cm.setActive('mce_editor_textarea_op_u', n.nodeName.toLowerCase() == 'u'); |
---|
166 | cm.setActive('mce_editor_textarea_op_s', n.nodeName.toLowerCase() == 's'); |
---|
167 | cm.setActive('mce_editor_textarea_op_i', n.nodeName.toLowerCase() == 'i'); |
---|
168 | }); |
---|
169 | }, |
---|
170 | |
---|
171 | createControl: function(n, cm) { |
---|
172 | var c = null; |
---|
173 | if (n == "op_color" && config["op_color"].isEnabled) { |
---|
174 | c = this._createOpenPNEColorButton("op_color", { title : "{#openpne.op_color}", image: config["op_color"].imageURL, cmd : "ForeColor"}, cm); |
---|
175 | } |
---|
176 | |
---|
177 | if (n == "op_emoji_docomo" || n == "op_emoji_au" && config["op_emoji_au"].isEnabled || n == "op_emoji_softbank" && config["op_emoji_softbank"].isEnabled) { |
---|
178 | var emoji_config = { |
---|
179 | op_emoji_docomo : { |
---|
180 | carrier : "i", |
---|
181 | emoji : [ {start : 1, end : 252} ], |
---|
182 | title : "{#openpne." + n + "}", |
---|
183 | image: config[n].imageURL |
---|
184 | }, |
---|
185 | op_emoji_au : { |
---|
186 | carrier : "e", |
---|
187 | emoji : [ {start : 1, end : 518}, {start : 700, end : 822} ], |
---|
188 | title : "{#openpne." + n + "}", |
---|
189 | image: config[n].imageURL |
---|
190 | }, |
---|
191 | op_emoji_softbank : { |
---|
192 | carrier : "s", |
---|
193 | emoji : [ {start : 1, end : 485} ], |
---|
194 | title : "{#openpne." + n + "}", |
---|
195 | image: config[n].imageURL |
---|
196 | } |
---|
197 | } |
---|
198 | c = this._createOpenPNEEmojiButton(n, emoji_config[n], cm); |
---|
199 | } |
---|
200 | |
---|
201 | if (n == "op_cmd") { |
---|
202 | c = this._createOpenPNECmdButton(n, {title: "{#openpne.op_cmd}", image: config["op_cmd"].imageURL, cmd: "mceOpenPNE_op_cmd"}, cm); |
---|
203 | } |
---|
204 | |
---|
205 | return c; |
---|
206 | }, |
---|
207 | |
---|
208 | getInfo : function() { |
---|
209 | return { |
---|
210 | longname : 'OpenPNE plugin', |
---|
211 | author : 'Kousuke Ebihara', |
---|
212 | version : "1.0" |
---|
213 | } |
---|
214 | }, |
---|
215 | |
---|
216 | _createOpenPNEColorButton : function(id, s, cm) { |
---|
217 | var t = cm, ed = t.editor, cmd, c; |
---|
218 | |
---|
219 | if (t.get(id)) { |
---|
220 | return null; |
---|
221 | } |
---|
222 | |
---|
223 | s.title = ed.translate(s.title); |
---|
224 | s.scope = s.scope || ed; |
---|
225 | |
---|
226 | if (!s.onclick) { |
---|
227 | s.onclick = function(v) { ed.execCommand(s.cmd, s.ui || false, v || s.value); }; |
---|
228 | } |
---|
229 | |
---|
230 | if (!s.onselect) { |
---|
231 | s.onselect = function(v) { ed.execCommand(s.cmd, s.ui || false, v || s.value); }; |
---|
232 | } |
---|
233 | |
---|
234 | id = t.prefix + id; |
---|
235 | |
---|
236 | s = tinymce.extend({ title : s.title, 'class' : 'mce_' + id, 'menu_class' : ed.getParam('skin') + 'Skin', scope : s.scope, more_colors_title : ed.getLang('more_colors') }, s); |
---|
237 | |
---|
238 | c = new tinymce.ui.OpenPNEColorButton(id, s); |
---|
239 | ed.onMouseDown.add(c.hideMenu, c); |
---|
240 | |
---|
241 | ed.onRemove.add(function() { |
---|
242 | c.destroy(); |
---|
243 | }); |
---|
244 | |
---|
245 | return t.add(c); |
---|
246 | }, |
---|
247 | |
---|
248 | _createOpenPNEEmojiButton : function(id, s, cm) { |
---|
249 | var t = cm, ed = t.editor, cmd, c; |
---|
250 | |
---|
251 | if (t.get(id)) { |
---|
252 | return null; |
---|
253 | } |
---|
254 | |
---|
255 | s.title = ed.translate(s.title); |
---|
256 | s.scope = s.scope || ed; |
---|
257 | |
---|
258 | if (!s.onclick) { |
---|
259 | s.onclick = function(v) { ed.execCommand(s.cmd, s.ui || false, v || s.value); }; |
---|
260 | } |
---|
261 | |
---|
262 | if (!s.onselect) { |
---|
263 | s.onselect = function(v) { ed.execCommand(s.cmd, s.ui || false, v || s.value); }; |
---|
264 | } |
---|
265 | |
---|
266 | id = t.prefix + id; |
---|
267 | |
---|
268 | s = tinymce.extend({ title : s.title, 'class' : 'mce_' + id, 'menu_class' : ed.getParam('skin') + 'Skin', scope : s.scope}, s); |
---|
269 | |
---|
270 | c = new tinymce.ui.OpenPNEEmojiButton(id, s); |
---|
271 | ed.onMouseDown.add(c.hideMenu, c); |
---|
272 | |
---|
273 | ed.onRemove.add(function() { |
---|
274 | c.destroy(); |
---|
275 | }); |
---|
276 | |
---|
277 | return t.add(c); |
---|
278 | }, |
---|
279 | |
---|
280 | _createOpenPNECmdButton : function(id, s, cm) { |
---|
281 | var t = cm, ed = t.editor, cmd, c; |
---|
282 | |
---|
283 | if (t.get(id)) { |
---|
284 | return null; |
---|
285 | } |
---|
286 | |
---|
287 | s.title = ed.translate(s.title); |
---|
288 | s.scope = s.scope || ed; |
---|
289 | |
---|
290 | if (!s.onclick) { |
---|
291 | s.onclick = function(v) { ed.execCommand(s.cmd, s.ui || false, v || s.value); }; |
---|
292 | } |
---|
293 | |
---|
294 | if (!s.onselect) { |
---|
295 | s.onselect = function(v) { ed.execCommand(s.cmd, s.ui || false, v || s.value); }; |
---|
296 | } |
---|
297 | |
---|
298 | id = t.prefix + id; |
---|
299 | |
---|
300 | s = tinymce.extend({ title : s.title, 'class' : 'mce_' + id, 'menu_class' : ed.getParam('skin') + 'Skin', scope : s.scope}, s); |
---|
301 | |
---|
302 | c = new tinymce.ui.OpenPNECmdButton(id, s); |
---|
303 | |
---|
304 | ed.onPostRender.add(function() { |
---|
305 | var parentContainer = document.getElementById(c.id).parentNode; |
---|
306 | parentContainer.style.width = "45px"; |
---|
307 | }); |
---|
308 | |
---|
309 | ed.onRemove.add(function() { |
---|
310 | c.destroy(); |
---|
311 | }); |
---|
312 | |
---|
313 | return t.add(c); |
---|
314 | }, |
---|
315 | |
---|
316 | _previewToText : function(s, editor) { |
---|
317 | var editorDoc = editor.getBody(); |
---|
318 | |
---|
319 | function rep(re, str) { |
---|
320 | s = s.replace(re, str); |
---|
321 | }; |
---|
322 | |
---|
323 | if (!tinymce.isWebKit) { // not safari |
---|
324 | s = tinymce.trim(s); |
---|
325 | rep('/<(\/?)strong>/gi', '<\1b>'); |
---|
326 | rep('/<(\/?)strike>/gi', '<\1s>'); |
---|
327 | rep('/<(\/?)em>/gi', '<\1i>'); |
---|
328 | editor.dom.setHTML(editor.getBody(), s); |
---|
329 | } |
---|
330 | |
---|
331 | function convertHtmlTagToDecoTag(doc, tagname) |
---|
332 | { |
---|
333 | var tagList = doc.getElementsByTagName(tagname); |
---|
334 | var org_tagname = tagname; |
---|
335 | var args = {}; |
---|
336 | |
---|
337 | while (tagList.length) { |
---|
338 | targetObj = tagList[0]; |
---|
339 | |
---|
340 | if (org_tagname == "font") { |
---|
341 | var size = targetObj.getAttribute("size"); |
---|
342 | var color = targetObj.getAttribute("color"); |
---|
343 | |
---|
344 | if (size && color) { |
---|
345 | if (tinymce.isIE) { |
---|
346 | targetObj.removeAttribute("color"); |
---|
347 | targetObj.innerHTML = '<font color="' + color + '">' + targetObj.innerHTML + "</font>"; |
---|
348 | } else { |
---|
349 | var fontSize = document.createElement("font"); |
---|
350 | fontSize.setAttribute("size", size); |
---|
351 | fontSize.removeAttribute("color"); |
---|
352 | |
---|
353 | var clone = targetObj.cloneNode(true); |
---|
354 | clone.removeAttribute("size"); |
---|
355 | |
---|
356 | fontSize.appendChild(clone); |
---|
357 | targetObj.parentNode.replaceChild(fontSize, targetObj); |
---|
358 | } |
---|
359 | |
---|
360 | // initialize |
---|
361 | tagList = doc.getElementsByTagName(org_tagname); |
---|
362 | args = {}; |
---|
363 | |
---|
364 | continue; |
---|
365 | } |
---|
366 | |
---|
367 | if (size == '5') { |
---|
368 | tagname = 'op:large'; |
---|
369 | } else if (size == '1') { |
---|
370 | tagname = 'op:small'; |
---|
371 | } |
---|
372 | |
---|
373 | if (color) { |
---|
374 | tagname = 'op:color'; |
---|
375 | args = { |
---|
376 | code: color |
---|
377 | }; |
---|
378 | } |
---|
379 | } else if (org_tagname == 'span') { // for safari |
---|
380 | if (targetObj.style.fontWeight == 'bold') { |
---|
381 | tagname = 'op:b'; |
---|
382 | } else if (targetObj.style.textDecoration == 'underline') { |
---|
383 | tagname = 'op:u'; |
---|
384 | } else if (targetObj.style.textDecoration == 'line-through') { |
---|
385 | tagname = 'op:s'; |
---|
386 | } else if (targetObj.style.fontStyle == 'italic') { |
---|
387 | tagname = 'op:i'; |
---|
388 | } else if (targetObj.style.color) { |
---|
389 | var color = tinyMCE.activeEditor.dom.toHex(targetObj.style.color); |
---|
390 | tagname = 'op:color'; |
---|
391 | args = { |
---|
392 | code: color |
---|
393 | }; |
---|
394 | } else if (targetObj.style.fontSize == 'x-large') { |
---|
395 | tagname = 'op:large'; |
---|
396 | } else if (targetObj.style.fontSize == 'x-small') { |
---|
397 | tagname = 'op:small'; |
---|
398 | } else { |
---|
399 | editor.dom.remove(targetObj, true); |
---|
400 | continue; |
---|
401 | } |
---|
402 | } else { |
---|
403 | tagname = 'op:' + org_tagname; |
---|
404 | } |
---|
405 | |
---|
406 | if (tinymce.isIE) { |
---|
407 | tagname = tagname.replace("op:", "op"); |
---|
408 | } |
---|
409 | |
---|
410 | var newObj = editor.dom.create(tagname); |
---|
411 | editor.dom.setAttribs(newObj, args); |
---|
412 | |
---|
413 | if (tinymce.isIE) { |
---|
414 | newObj.innerHTML = targetObj.innerHTML; |
---|
415 | targetObj.parentNode.replaceChild(newObj, targetObj); |
---|
416 | } else { |
---|
417 | editor.dom.replace(newObj, targetObj, true); |
---|
418 | } |
---|
419 | tagList = doc.getElementsByTagName(org_tagname); |
---|
420 | } |
---|
421 | s = editorDoc.innerHTML; |
---|
422 | } |
---|
423 | |
---|
424 | var convertList = new Array('span', 'b', 'u', 's', 'i', 'font'); |
---|
425 | for (var i = 0; i < convertList.length; i++) { |
---|
426 | convertHtmlTagToDecoTag(editor.getBody(), convertList[i]); |
---|
427 | } |
---|
428 | |
---|
429 | rep(/<\/?div>/gi,""); // for Safari |
---|
430 | |
---|
431 | if (tinymce.isIE) { |
---|
432 | rep(/<op/gi, "<op:"); |
---|
433 | rep(/<\/op/gi, "</op:"); |
---|
434 | } |
---|
435 | |
---|
436 | rep(/<br\s?\/?[^>]*>/gi,"\n\n"); |
---|
437 | rep(/ /gi," "); |
---|
438 | rep(/"/gi,"\""); |
---|
439 | rep(/</gi,"<"); |
---|
440 | rep(/>/gi,">"); |
---|
441 | rep(/&/gi,"&"); |
---|
442 | |
---|
443 | return s; |
---|
444 | }, |
---|
445 | |
---|
446 | _textToPreview : function(s) { |
---|
447 | s = tinymce.trim(s); |
---|
448 | var rule = /<op:(b|u|s|i|large|small|color)( code="(#[0-9a-f]{3,6})"|)>(.*?)<\/op:\1>/i; |
---|
449 | |
---|
450 | function rep(re, str) { |
---|
451 | s = s.replace(re, str); |
---|
452 | }; |
---|
453 | |
---|
454 | function convertDecoTagToHtmlTag(matches) |
---|
455 | { |
---|
456 | var tagname = matches[1]; |
---|
457 | var color = matches[3]; |
---|
458 | var value = matches[4].gsub(rule, convertDecoTagToHtmlTag); |
---|
459 | var opt = ''; |
---|
460 | |
---|
461 | if (tagname == 'color' && color) { |
---|
462 | tagname = 'font'; |
---|
463 | opt = ' color="' + color + '"'; |
---|
464 | } |
---|
465 | |
---|
466 | if (tagname == 'large') { |
---|
467 | tagname = 'font'; |
---|
468 | opt = ' size="5"'; |
---|
469 | } |
---|
470 | |
---|
471 | if (tagname == 'small') { |
---|
472 | tagname = 'font'; |
---|
473 | opt = ' size="1"'; |
---|
474 | } |
---|
475 | |
---|
476 | var converted = "<" + tagname + opt + ">" + value + "</" + tagname + ">"; |
---|
477 | return converted; |
---|
478 | }; |
---|
479 | |
---|
480 | rep(/</gi,"<"); |
---|
481 | rep(/>/gi,">"); |
---|
482 | rep(/\n/gi,"<br />"); |
---|
483 | s = s.gsub(rule, convertDecoTagToHtmlTag); |
---|
484 | |
---|
485 | return s; |
---|
486 | } |
---|
487 | }); |
---|
488 | |
---|
489 | // Register plugin |
---|
490 | tinymce.PluginManager.add('openpne', tinymce.plugins.OpenPNEPlugin); |
---|
491 | })(); |
---|