HTMLtoolbar Classic
Originally by Oolong
1: // JS QuickTags version 1.3.1
2: //
3: // Copyright (c) 2002-2008 Alex King
4: // http://alexking.org/projects/js-quicktags
5: //
6: // Thanks to Greg Heo <greg@node79.com> for his changes
7: // to support multiple toolbars per page.
8: //
9: // Licensed under the LGPL license
10: // http://www.gnu.org/copyleft/lesser.html
11: //
12: // **********************************************************************
13: // This program is distributed in the hope that it will be useful, but
14: // WITHOUT ANY WARRANTY; without even the implied warranty of
15: // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16: // **********************************************************************
17: //
18: // This JavaScript will insert the tags below at the cursor position in IE and
19: // Gecko-based browsers (Mozilla, Camino, Firefox, Netscape). For browsers that
20: // do not support inserting at the cursor position (older versions of Safari,
21: // OmniWeb) it appends the tags to the end of the content.
22: //
23: // Pass the ID of the <textarea> element to the edToolbar and function.
24: //
25: // Example:
26: //
27: // <script type="text/javascript">edToolbar('canvas');</script>
28: // <textarea id="canvas" rows="20" cols="50"></textarea>
29: //
30:
31: var dictionaryUrl = 'http://www.ninjawords.com/';
32:
33: // other options include:
34: //
35: // var dictionaryUrl = 'http://www.answers.com/';
36: // var dictionaryUrl = 'http://www.dictionary.com/';
37:
38: var edButtons = new Array();
39: var edLinks = new Array();
40: var edOpenTags = new Array();
41:
42: function edButton(id, display, title, tagStart, tagEnd, access, open) {
43: this.id = id; // used to name the toolbar button
44: this.display = display; // label on button
45: this.title = title; // label on button
46: this.tagStart = tagStart; // open tag
47: this.tagEnd = tagEnd; // close tag
48: this.access = access; // set to -1 if tag does not need to be closed
49: this.open = open; // set to -1 if tag does not need to be closed
50: }
51:
52: edButtons.push(
53: new edButton(
54: 'ed_strong'
55: ,'b'
56: ,'Bold'
57: ,'<strong>'
58: ,'</strong>'
59: ,'b'
60: )
61: );
62:
63: edButtons.push(
64: new edButton(
65: 'ed_em'
66: ,'i'
67: ,'Italics (for emphasis)'
68: ,'<em>'
69: ,'</em>'
70: ,'i'
71: )
72: );
73:
74: edButtons.push(
75: new edButton(
76: 'ed_hardlink'
77: ,'link'
78: ,'Hard link'
79: ,'['
80: ,']'
81: ,'a'
82: )
83: ); // special case
84:
85: /*edButtons.push(
86: new edButton(
87: 'ed_link'
88: ,'link'
89: ,'Hard link'
90: ,''
91: ,']'
92: ,'a'
93: )
94: );*/ // special case (not used)
95:
96: edButtons.push(
97: new edButton(
98: 'ed_pipe_link'
99: ,'pipe link'
100: ,'Pipe link (show one thing, link another)'
101: ,''
102: ,']'
103: ,'e'
104: )
105: ); // special case
106:
107: /* edButtons.push(
108: new edButton(
109: 'ed_img'
110: ,'IMG'
111: ,''
112: ,''
113: ,'m'
114: ,-1
115: )
116: ); */ // special case - removed as long as we don't have images
117:
118: edButtons.push(
119: new edButton(
120: 'ed_ul'
121: ,'ul'
122: ,'Bulleted (unordered) list'
123: ,'<ul>\n'
124: ,'</ul>\n\n'
125: ,'u'
126: )
127: );
128:
129: edButtons.push(
130: new edButton(
131: 'ed_ol'
132: ,'ol'
133: ,'Numbered (ordered) list'
134: ,'<ol>\n'
135: ,'</ol>\n\n'
136: ,'o'
137: )
138: );
139:
140: edButtons.push(
141: new edButton(
142: 'ed_li'
143: ,'li'
144: ,'List item'
145: ,'\t<li>'
146: ,'</li>\n'
147: ,'l'
148: )
149: );
150:
151: edButtons.push(
152: new edButton(
153: 'ed_block'
154: ,'b-quote'
155: ,'Block quote'
156: ,'<blockquote>'
157: ,'</blockquote>'
158: ,'q'
159: )
160: );
161:
162: var extendedStart = edButtons.length;
163:
164: // below here are the extended buttons
165:
166: edButtons.push(
167: new edButton(
168: 'ed_h1'
169: ,'h1'
170: ,'Top-level heading'
171: ,'<h1>'
172: ,'</h1>\n\n'
173: ,'1'
174: )
175: );
176:
177: edButtons.push(
178: new edButton(
179: 'ed_h2'
180: ,'h2'
181: ,'Second-level heading'
182: ,'<h2>'
183: ,'</h2>\n\n'
184: ,'2'
185: )
186: );
187:
188: edButtons.push(
189: new edButton(
190: 'ed_h3'
191: ,'h3'
192: ,'Third-level heading'
193: ,'<h3>'
194: ,'</h3>\n\n'
195: ,'3'
196: )
197: );
198:
199: edButtons.push(
200: new edButton(
201: 'ed_h4'
202: ,'h4'
203: ,'Fourth-level heading'
204: ,'<h4>'
205: ,'</h4>\n\n'
206: ,'4'
207: )
208: );
209:
210: edButtons.push(
211: new edButton(
212: 'ed_p'
213: ,'p'
214: ,'Paragraph'
215: ,'<p>'
216: ,'</p>\n\n'
217: ,'p'
218: )
219: );
220:
221: edButtons.push(
222: new edButton(
223: 'ed_code'
224: ,'code'
225: ,'Code'
226: ,'<code>'
227: ,'</code>'
228: ,'c'
229: )
230: );
231:
232: edButtons.push(
233: new edButton(
234: 'ed_pre'
235: ,'pre'
236: ,'Pre-formatted text'
237: ,'<pre>'
238: ,'</pre>'
239: )
240: );
241:
242: edButtons.push(
243: new edButton(
244: 'ed_dl'
245: ,'dl'
246: ,'Definition list'
247: ,'<dl>\n'
248: ,'</dl>\n\n'
249: )
250: );
251:
252: edButtons.push(
253: new edButton(
254: 'ed_dt'
255: ,'dt'
256: ,'Definition title'
257: ,'\t<dt>'
258: ,'</dt>\n'
259: )
260: );
261:
262: edButtons.push(
263: new edButton(
264: 'ed_dd'
265: ,'dd'
266: ,'Definition description'
267: ,'\t<dd>'
268: ,'</dd>\n'
269: )
270: );
271:
272: /* edButtons.push(
273: new edButton(
274: 'ed_table'
275: ,'TABLE'
276: ,'<table>\n<tbody>'
277: ,'</tbody>\n</table>\n'
278: )
279: );
280:
281: edButtons.push(
282: new edButton(
283: 'ed_tr'
284: ,'TR'
285: ,'\t<tr>\n'
286: ,'\n\t</tr>\n'
287: )
288: );
289:
290: edButtons.push(
291: new edButton(
292: 'ed_td'
293: ,'TD'
294: ,'\t\t<td>'
295: ,'</td>\n'
296: )
297: ); */ // until such time as we allow tables...
298:
299: edButtons.push(
300: new edButton(
301: 'ed_ins'
302: ,'ins'
303: ,'Mark inserted text'
304: ,'<ins>'
305: ,'</ins>'
306: )
307: );
308:
309: edButtons.push(
310: new edButton(
311: 'ed_del'
312: ,'del'
313: ,'Mark deleted (struck out) text'
314: ,'<del>'
315: ,'</del>'
316: )
317: );
318:
319: /* edButtons.push(
320: new edButton(
321: 'ed_nobr'
322: ,'NOBR'
323: ,'<nobr>'
324: ,'</nobr>'
325: )
326: );
327:
328: edButtons.push(
329: new edButton(
330: 'ed_footnote'
331: ,'Footnote'
332: ,''
333: ,''
334: ,'f'
335: )
336: );
337:
338: edButtons.push(
339: new edButton(
340: 'ed_via'
341: ,'Via'
342: ,''
343: ,''
344: ,'v'
345: )
346: ); */
347:
348: function edLink(display, URL, newWin) {
349: this.display = display;
350: this.URL = URL;
351: if (!newWin) {
352: newWin = 0;
353: }
354: this.newWin = newWin;
355: }
356:
357:
358: edLinks[edLinks.length] = new edLink('alexking.org'
359: ,'http://www.alexking.org/'
360: );
361:
362: function edShowButton(which, button, i) {
363: if (button.access) {
364: var accesskey = ' accesskey = "' + button.access + '"'
365: }
366: else {
367: var accesskey = '';
368: }
369: switch (button.id) {
370: case 'ed_img':
371: document.write('<input type="button" id="' + button.id + '" ' + accesskey + ' class="ed_button" onclick="edInsertImage(\'' + which + '\');" value="' + button.display + '" title="' + button.title + '" />');
372: break;
373: case 'ed_link':
374: document.write('<input type="button" id="' + button.id + '" ' + accesskey + ' class="ed_button" onclick="edInsertLink(\'' + which + '\', ' + i + ');" value="' + button.display + '" title="' + button.title + '" />');
375: break;
376: case 'ed_pipe_link':
377: document.write('<input type="button" id="' + button.id + '" ' + accesskey + ' class="ed_button" onclick="edInsertExtLink(\'' + which + '\', ' + i + ');" value="' + button.display + '" title="' + button.title + '" />');
378: break;
379: case 'ed_footnote':
380: document.write('<input type="button" id="' + button.id + '" ' + accesskey + ' class="ed_button" onclick="edInsertFootnote(\'' + which + '\');" value="' + button.display + '" title="' + button.title + '" />');
381: break;
382: case 'ed_via':
383: document.write('<input type="button" id="' + button.id + '" ' + accesskey + ' class="ed_button" onclick="edInsertVia(\'' + which + '\');" value="' + button.display + '" title="' + button.title + '" />');
384: break;
385: default:
386: document.write('<input type="button" id="' + button.id + '" ' + accesskey + ' class="ed_button" onclick="edInsertTag(\'' + which + '\', ' + i + ');" value="' + button.display + '" title="' + button.title + '" />');
387: break;
388: }
389: }
390:
391: function edShowLinks() {
392: var tempStr = '<select onchange="edQuickLink(this.options[this.selectedIndex].value, this);"><option value="-1" selected>(Quick Links)</option>';
393: for (i = 0; i < edLinks.length; i++) {
394: tempStr += '<option value="' + i + '">' + edLinks[i].display + '</option>';
395: }
396: tempStr += '</select>';
397: document.write(tempStr);
398: }
399:
400: function edAddTag(which, button) {
401: if (edButtons[button].tagEnd != '') {
402: edOpenTags[which][edOpenTags[which].length] = button;
403: document.getElementById(edButtons[button].id + '_' + which).value = '/' + document.getElementById(edButtons[button].id + '_' + which).value;
404: }
405: }
406:
407: function edRemoveTag(which, button) {
408: for (i = 0; i < edOpenTags[which].length; i++) {
409: if (edOpenTags[which][i] == button) {
410: edOpenTags[which].splice(i, 1);
411: document.getElementById(edButtons[button].id + '_' + which).value = document.getElementById(edButtons[button].id + '_' + which).value.replace('/', '');
412: }
413: }
414: }
415:
416: function edCheckOpenTags(which, button) {
417: var tag = 0;
418: for (i = 0; i < edOpenTags[which].length; i++) {
419: if (edOpenTags[which][i] == button) {
420: tag++;
421: }
422: }
423: if (tag > 0) {
424: return true; // tag found
425: }
426: else {
427: return false; // tag not found
428: }
429: }
430:
431: function edCloseAllTags(which) {
432: var count = edOpenTags[which].length;
433: for (o = 0; o < count; o++) {
434: edInsertTag(which, edOpenTags[which][edOpenTags[which].length - 1]);
435: }
436: }
437:
438: function edQuickLink(i, thisSelect) {
439: if (i > -1) {
440: var newWin = '';
441: if (edLinks[i].newWin == 1) {
442: newWin = ' target="_blank"';
443: }
444: var tempStr = '<a href="' + edLinks[i].URL + '"' + newWin + '>'
445: + edLinks[i].display
446: + '</a>';
447: thisSelect.selectedIndex = 0;
448: edInsertContent(edCanvas, tempStr);
449: }
450: else {
451: thisSelect.selectedIndex = 0;
452: }
453: }
454:
455: function edSpell(which) {
456: myField = document.getElementById(which);
457: var word = '';
458: if (document.selection) {
459: myField.focus();
460: var sel = document.selection.createRange();
461: if (sel.text.length > 0) {
462: word = sel.text;
463: }
464: }
465: else if (myField.selectionStart || myField.selectionStart == '0') {
466: var startPos = myField.selectionStart;
467: var endPos = myField.selectionEnd;
468: if (startPos != endPos) {
469: word = myField.value.substring(startPos, endPos);
470: }
471: }
472: if (word == '') {
473: word = prompt('Enter a word to look up:', '');
474: }
475: if (word != '') {
476: window.open(dictionaryUrl + escape(word));
477: }
478: }
479:
480: function edToolbar(which) {
481: document.write('<div id="ed_toolbar_' + which + '"><span>');
482: for (i = 0; i < extendedStart; i++) {
483: edShowButton(which, edButtons[i], i);
484: }
485: if (edShowExtraCookie()) {
486: document.write(
487: '<input type="button" id="ed_close_' + which + '" class="ed_button" onclick="edCloseAllTags(\'' + which + '\');" value="Close Tags" />'
488: + '<input type="button" id="ed_autoformat_' + which + '" class="ed_button" onclick="autoFormat(\'' + which + '\');" value="Line Breaks" title="Insert paragraph and line-break tags based on line breaks in the source" />'
489: + '<input type="button" id="ed_spell_' + which + '" class="ed_button" onclick="edSpell(\'' + which + '\');" value="Dict" />'
490: + '<input type="button" id="ed_extra_show_' + which + '" class="ed_button" onclick="edShowExtra(\'' + which + '\')" value="»" style="visibility: hidden;" />'
491: + '</span><br />'
492: + '<span id="ed_extra_buttons_' + which + '">'
493: + '<input type="button" id="ed_extra_hide_' + which + '" class="ed_button" onclick="edHideExtra(\'' + which + '\');" value="«" />'
494: );
495: }
496: else {
497: document.write(
498: '<input type="button" id="ed_close_' + which + '" class="ed_button" onclick="edCloseAllTags(\'' + which + '\');" value="Close Tags" />'
499: + '<input type="button" id="ed_spell_' + which + '" class="ed_button" onclick="edSpell(\'' + which + '\');" value="Dict" />'
500: + '<input type="button" id="ed_extra_show_' + which + '" class="ed_button" onclick="edShowExtra(\'' + which + '\')" value="»" />'
501: + '</span><br />'
502: + '<span id="ed_extra_buttons_' + which + '" style="display: none;">'
503: + '<input type="button" id="ed_extra_hide_' + which + '" class="ed_button" onclick="edHideExtra(\'' + which + '\');" value="«" />'
504: );
505: }
506: for (i = extendedStart; i < edButtons.length; i++) {
507: edShowButton(which, edButtons[i], i);
508: }
509: document.write('</span>');
510: // edShowLinks();
511: document.write('</div>');
512: edOpenTags[which] = new Array();
513: }
514:
515: function edShowExtra(which) {
516: document.getElementById('ed_extra_show_' + which).style.visibility = 'hidden';
517: document.getElementById('ed_extra_buttons_' + which).style.display = 'block';
518: edSetCookie(
519: 'js_quicktags_extra'
520: , 'show'
521: , new Date("December 31, 2100")
522: );
523: }
524:
525: function edHideExtra(which) {
526: document.getElementById('ed_extra_buttons_' + which).style.display = 'none';
527: document.getElementById('ed_extra_show_' + which).style.visibility = 'visible';
528: edSetCookie(
529: 'js_quicktags_extra'
530: , 'hide'
531: , new Date("December 31, 2100")
532: );
533: }
534:
535: // insertion code
536:
537: function edInsertTag(which, i) {
538: myField = document.getElementById(which);
539: //IE support
540: if (document.selection) {
541: myField.focus();
542: sel = document.selection.createRange();
543: if (sel.text.length > 0) {
544: sel.text = edButtons[i].tagStart + sel.text + edButtons[i].tagEnd;
545: }
546: else {
547: if (!edCheckOpenTags(which, i) || edButtons[i].tagEnd == '') {
548: sel.text = edButtons[i].tagStart;
549: edAddTag(which, i);
550: }
551: else {
552: sel.text = edButtons[i].tagEnd;
553: edRemoveTag(which, i);
554: }
555: }
556: myField.focus();
557: }
558: //MOZILLA/NETSCAPE support
559: else if (myField.selectionStart || myField.selectionStart == '0') {
560: var startPos = myField.selectionStart;
561: var endPos = myField.selectionEnd;
562: var cursorPos = endPos;
563: var scrollTop = myField.scrollTop;
564: if (startPos != endPos) {
565: myField.value = myField.value.substring(0, startPos)
566: + edButtons[i].tagStart
567: + myField.value.substring(startPos, endPos)
568: + edButtons[i].tagEnd
569: + myField.value.substring(endPos, myField.value.length);
570: cursorPos += edButtons[i].tagStart.length + edButtons[i].tagEnd.length;
571: }
572: else {
573: if (!edCheckOpenTags(which, i) || edButtons[i].tagEnd == '') {
574: myField.value = myField.value.substring(0, startPos)
575: + edButtons[i].tagStart
576: + myField.value.substring(endPos, myField.value.length);
577: edAddTag(which, i);
578: cursorPos = startPos + edButtons[i].tagStart.length;
579: }
580: else {
581: myField.value = myField.value.substring(0, startPos)
582: + edButtons[i].tagEnd
583: + myField.value.substring(endPos, myField.value.length);
584: edRemoveTag(which, i);
585: cursorPos = startPos + edButtons[i].tagEnd.length;
586: }
587: }
588: myField.focus();
589: myField.selectionStart = cursorPos;
590: myField.selectionEnd = cursorPos;
591: myField.scrollTop = scrollTop;
592: }
593: else {
594: if (!edCheckOpenTags(which, i) || edButtons[i].tagEnd == '') {
595: myField.value += edButtons[i].tagStart;
596: edAddTag(which, i);
597: }
598: else {
599: myField.value += edButtons[i].tagEnd;
600: edRemoveTag(which, i);
601: }
602: myField.focus();
603: }
604: }
605:
606: function edInsertContent(which, myValue) {
607: myField = document.getElementById(which);
608: //IE support
609: if (document.selection) {
610: myField.focus();
611: sel = document.selection.createRange();
612: sel.text = myValue;
613: myField.focus();
614: }
615: //MOZILLA/NETSCAPE support
616: else if (myField.selectionStart || myField.selectionStart == '0') {
617: var startPos = myField.selectionStart;
618: var endPos = myField.selectionEnd;
619: var scrollTop = myField.scrollTop;
620: myField.value = myField.value.substring(0, startPos)
621: + myValue
622: + myField.value.substring(endPos, myField.value.length);
623: myField.focus();
624: myField.selectionStart = startPos + myValue.length;
625: myField.selectionEnd = startPos + myValue.length;
626: myField.scrollTop = scrollTop;
627: } else {
628: myField.value += myValue;
629: myField.focus();
630: }
631: }
632:
633: function edInsertLink(which, i, defaultValue) {
634: myField = document.getElementById(which);
635: if (!defaultValue) {
636: defaultValue = 'http://';
637: }
638: if (!edCheckOpenTags(which, i)) {
639: var URL = prompt('Enter the URL' ,defaultValue);
640: if (URL) {
641: edButtons[i].tagStart = '<a href="' + URL + '">';
642: edInsertTag(which, i);
643: }
644: }
645: else {
646: edInsertTag(which, i);
647: }
648: }
649:
650: function edInsertExtLink(which, i, defaultValue) {
651: myField = document.getElementById(which);
652: if (!defaultValue) {
653: defaultValue = '';
654: }
655: if (!edCheckOpenTags(which, i)) {
656: var target = prompt('Enter the target' ,defaultValue);
657: if (target) {
658: edButtons[i].tagStart = '[' + target + '|';
659: edInsertTag(which, i);
660: }
661: }
662: else {
663: edInsertTag(which, i);
664: }
665: }
666:
667: function edInsertImage(which) {
668: myField = document.getElementById(which);
669: var myValue = prompt('Enter the URL of the image', 'http://');
670: if (myValue) {
671: myValue = '<img src="'
672: + myValue
673: + '" alt="' + prompt('Enter a description of the image', '')
674: + '" />';
675: edInsertContent(which, myValue);
676: }
677: }
678:
679: function edInsertFootnote(which) {
680: myField = document.getElementById(which);
681: var note = prompt('Enter the footnote:', '');
682: if (!note || note == '') {
683: return false;
684: }
685: var now = new Date;
686: var fnId = 'fn' + now.getTime();
687: var fnStart = myField.value.indexOf('<ol class="footnotes">');
688: if (fnStart != -1) {
689: var fnStr1 = myField.value.substring(0, fnStart)
690: var fnStr2 = myField.value.substring(fnStart, myField.value.length)
691: var count = countInstances(fnStr2, '<li id="') + 1;
692: }
693: else {
694: var count = 1;
695: }
696: var count = '<sup><a href="#' + fnId + 'n" id="' + fnId + '" class="footnote">' + count + '</a></sup>';
697: edInsertContent(which, count);
698: if (fnStart != -1) {
699: fnStr1 = myField.value.substring(0, fnStart + count.length)
700: fnStr2 = myField.value.substring(fnStart + count.length, myField.value.length)
701: }
702: else {
703: var fnStr1 = myField.value;
704: var fnStr2 = "\n\n" + '<ol class="footnotes">' + "\n"
705: + '</ol>' + "\n";
706: }
707: var footnote = ' <li id="' + fnId + 'n">' + note + ' [<a href="#' + fnId + '">back</a>]</li>' + "\n"
708: + '</ol>';
709: myField.value = fnStr1 + fnStr2.replace('</ol>', footnote);
710: }
711:
712: function countInstances(string, substr) {
713: var count = string.split(substr);
714: return count.length - 1;
715: }
716:
717: function edInsertVia(which) {
718: myField = document.getElementById(which);
719: var myValue = prompt('Enter the URL of the source link', 'http://');
720: if (myValue) {
721: myValue = '(Thanks <a href="' + myValue + '" rel="external">'
722: + prompt('Enter the name of the source', '')
723: + '</a>)';
724: edInsertContent(which, myValue);
725: }
726: }
727:
728:
729: function edSetCookie(name, value, expires, path, domain) {
730: document.cookie= name + "=" + escape(value) +
731: ((expires) ? "; expires=" + expires.toGMTString() : "") +
732: ((path) ? "; path=" + path : "") +
733: ((domain) ? "; domain=" + domain : "");
734: }
735:
736: function edShowExtraCookie() {
737: var cookies = document.cookie.split(';');
738: for (var i=0;i < cookies.length; i++) {
739: var cookieData = cookies[i];
740: while (cookieData.charAt(0) ==' ') {
741: cookieData = cookieData.substring(1, cookieData.length);
742: }
743: if (cookieData.indexOf('js_quicktags_extra') == 0) {
744: if (cookieData.substring(19, cookieData.length) == 'show') {
745: return true;
746: }
747: else {
748: return false;
749: }
750: }
751: }
752: return false;
753: }