ここの情報は古いです。ご理解頂いた上でお取り扱いください。

source: OpenPNE/trunk/public_html/js/tiny_mce/plugins/openpne/editor_plugin.js.src @ 7279

Last change on this file since 7279 was 7279, checked in by ebihara, 12 years ago

#2448:多重に装飾されている文字にカーソルをあわせた際に、すべての装飾ボタンがアクティブにならなかったのを修正

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