Make WordPress Core

Ticket #16695: 16695.5.diff

File 16695.5.diff, 29.1 KB (added by garyc40, 13 years ago)

backward compatibility with edButtons and edButton

  • wp-admin/js/editor.dev.js

    diff --git wp-admin/js/editor.dev.js wp-admin/js/editor.dev.js
    index cf58279..75ef5dc 100644
    var switchEditors = { 
    103103
    104104                        P.className = 'active';
    105105                        H.className = '';
    106                         edCloseAllTags(); // :-(
     106                        QTags.getInstance(id).closeAllTags(); // :-(
    107107                        qt.style.display = 'none';
    108108
    109109                        ta.style.color = '#FFF';
  • wp-includes/general-template.php

    diff --git wp-includes/general-template.php wp-includes/general-template.php
    index 19194f2..af610c6 100644
    function the_editor($content, $id = 'content', $prev_id = 'title', $media_button 
    18271827?>
    18281828        <div id="quicktags"><?php
    18291829        wp_print_scripts( 'quicktags' ); ?>
    1830         <script type="text/javascript">edToolbar()</script>
     1830        <script type="text/javascript">QTags.init('<?php echo esc_js($id); ?>');</script>
    18311831        </div>
    18321832
    18331833<?php
  • wp-includes/js/quicktags.dev.js

    diff --git wp-includes/js/quicktags.dev.js wp-includes/js/quicktags.dev.js
    index 48b7b6a..8da4582 100644
     
     1/*globals quicktagsL10n */
     2
    13// new edit toolbar used with permission
    24// by Alex King
    35// http://www.alexking.org/
    46
    5 var edButtons = new Array(), edLinks = new Array(), edOpenTags = new Array(), now = new Date(), datetime;
    6 
    7 function edButton(id, display, tagStart, tagEnd, access, open) {
    8         this.id = id;                           // used to name the toolbar button
    9         this.display = display;         // label on button
    10         this.tagStart = tagStart;       // open tag
    11         this.tagEnd = tagEnd;           // close tag
    12         this.access = access;           // access key
    13         this.open = open;                       // set to -1 if tag does not need to be closed
    14 }
    15 
    16 function zeroise(number, threshold) {
    17         // FIXME: or we could use an implementation of printf in js here
    18         var str = number.toString();
    19         if (number < 0) { str = str.substr(1, str.length) }
    20         while (str.length < threshold) { str = "0" + str }
    21         if (number < 0) { str = '-' + str }
    22         return str;
    23 }
    24 
    25 datetime = now.getUTCFullYear() + '-' +
    26 zeroise(now.getUTCMonth() + 1, 2) + '-' +
    27 zeroise(now.getUTCDate(), 2) + 'T' +
    28 zeroise(now.getUTCHours(), 2) + ':' +
    29 zeroise(now.getUTCMinutes(), 2) + ':' +
    30 zeroise(now.getUTCSeconds() ,2) +
    31 '+00:00';
    32 
    33 edButtons[edButtons.length] =
    34 new edButton('ed_strong'
    35 ,'b'
    36 ,'<strong>'
    37 ,'</strong>'
    38 ,'b'
    39 );
    40 
    41 edButtons[edButtons.length] =
    42 new edButton('ed_em'
    43 ,'i'
    44 ,'<em>'
    45 ,'</em>'
    46 ,'i'
    47 );
    48 
    49 edButtons[edButtons.length] =
    50 new edButton('ed_link'
    51 ,'link'
    52 ,''
    53 ,'</a>'
    54 ,'a'
    55 ); // special case
    56 
    57 edButtons[edButtons.length] =
    58 new edButton('ed_block'
    59 ,'b-quote'
    60 ,'\n\n<blockquote>'
    61 ,'</blockquote>\n\n'
    62 ,'q'
    63 );
    64 
    65 
    66 edButtons[edButtons.length] =
    67 new edButton('ed_del'
    68 ,'del'
    69 ,'<del datetime="' + datetime + '">'
    70 ,'</del>'
    71 ,'d'
    72 );
    73 
    74 edButtons[edButtons.length] =
    75 new edButton('ed_ins'
    76 ,'ins'
    77 ,'<ins datetime="' + datetime + '">'
    78 ,'</ins>'
    79 ,'s'
    80 );
    81 
    82 edButtons[edButtons.length] =
    83 new edButton('ed_img'
    84 ,'img'
    85 ,''
    86 ,''
    87 ,'m'
    88 ,-1
    89 ); // special case
    90 
    91 edButtons[edButtons.length] =
    92 new edButton('ed_ul'
    93 ,'ul'
    94 ,'<ul>\n'
    95 ,'</ul>\n\n'
    96 ,'u'
    97 );
    98 
    99 edButtons[edButtons.length] =
    100 new edButton('ed_ol'
    101 ,'ol'
    102 ,'<ol>\n'
    103 ,'</ol>\n\n'
    104 ,'o'
    105 );
     7var QTags, edButtons, edButton;
    1068
    107 edButtons[edButtons.length] =
    108 new edButton('ed_li'
    109 ,'li'
    110 ,'\t<li>'
    111 ,'</li>\n'
    112 ,'l'
    113 );
    114 
    115 edButtons[edButtons.length] =
    116 new edButton('ed_code'
    117 ,'code'
    118 ,'<code>'
    119 ,'</code>'
    120 ,'c'
    121 );
    122 
    123 edButtons[edButtons.length] =
    124 new edButton('ed_more'
    125 ,'more'
    126 ,'<!--more-->'
    127 ,''
    128 ,'t'
    129 ,-1
    130 );
    131 /*
    132 edButtons[edButtons.length] =
    133 new edButton('ed_next'
    134 ,'page'
    135 ,'<!--nextpage-->'
    136 ,''
    137 ,'p'
    138 ,-1
    139 );
    140 */
    141 function edLink() {
    142         this.display = '';
    143         this.URL = '';
    144         this.newWin = 0;
    145 }
    146 
    147 edLinks[edLinks.length] = new edLink('WordPress'
    148                                     ,'http://wordpress.org/'
    149                                     );
    150 
    151 edLinks[edLinks.length] = new edLink('alexking.org'
    152                                     ,'http://www.alexking.org/'
    153                                     );
    154 
    155 function edShowButton(button, i) {
    156         if (button.id == 'ed_img') {
    157                 document.write('<input type="button" id="' + button.id + '" accesskey="' + button.access + '" class="ed_button" onclick="edInsertImage(edCanvas);" value="' + button.display + '" />');
    158         }
    159         else if (button.id == 'ed_link') {
    160                 document.write('<input type="button" id="' + button.id + '" accesskey="' + button.access + '" class="ed_button" onclick="edInsertLink(edCanvas, ' + i + ');" value="' + button.display + '" />');
    161         }
    162         else {
    163                 document.write('<input type="button" id="' + button.id + '" accesskey="' + button.access + '" class="ed_button" onclick="edInsertTag(edCanvas, ' + i + ');" value="' + button.display + '"  />');
    164         }
    165 }
    166 
    167 function edShowLinks() {
    168         var tempStr = '<select onchange="edQuickLink(this.options[this.selectedIndex].value, this);"><option value="-1" selected>' + quicktagsL10n.quickLinks + '</option>', i;
    169         for (i = 0; i < edLinks.length; i++) {
    170                 tempStr += '<option value="' + i + '">' + edLinks[i].display + '</option>';
    171         }
    172         tempStr += '</select>';
    173         document.write(tempStr);
    174 }
    175 
    176 function edAddTag(button) {
    177         if (edButtons[button].tagEnd != '') {
    178                 edOpenTags[edOpenTags.length] = button;
    179                 document.getElementById(edButtons[button].id).value = '/' + document.getElementById(edButtons[button].id).value;
    180         }
    181 }
    182 
    183 function edRemoveTag(button) {
    184         for (var i = 0; i < edOpenTags.length; i++) {
    185                 if (edOpenTags[i] == button) {
    186                         edOpenTags.splice(i, 1);
    187                         document.getElementById(edButtons[button].id).value =           document.getElementById(edButtons[button].id).value.replace('/', '');
    188                 }
    189         }
    190 }
     9(function(){
     10        // private stuff is prefixed with an underscore
     11        var _domReady = function(func) {
     12                if (typeof jQuery != 'undefined') {
     13                        jQuery(document).ready(func);
     14                } else {
     15                        var t = _domReady, DOMContentLoaded, top;
     16                                t.funcs = [];
     17
     18                        t.ready = function() {
     19                                if (! t.isReady) {
     20                                        t.isReady = true;
     21                                        for (var i=0; i < t.funcs.length; i++) {
     22                                                t.funcs[i]();
     23                                        }
     24                                }
     25                        };
    19126
    192 function edCheckOpenTags(button) {
    193         var tag = 0, i;
    194         for (i = 0; i < edOpenTags.length; i++) {
    195                 if (edOpenTags[i] == button) {
    196                         tag++;
    197                 }
    198         }
    199         if (tag > 0) {
    200                 return true; // tag found
    201         }
    202         else {
    203                 return false; // tag not found
    204         }
    205 }
     27                        if (t.isReady) {
     28                                func();
     29                        } else {
     30                                t.funcs.push(func);
     31                        }
    20632
    207 function edCloseAllTags() {
    208         var count = edOpenTags.length, o;
    209         for (o = 0; o < count; o++) {
    210                 edInsertTag(edCanvas, edOpenTags[edOpenTags.length - 1]);
    211         }
    212 }
     33                        if ( ! t.eventAttached ) {
     34                                if (document.addEventListener) {
     35                                        DOMContentLoaded = function(){document.removeEventListener('DOMContentLoaded', DOMContentLoaded, false);t.ready();};
     36                                        document.addEventListener('DOMContentLoaded', DOMContentLoaded, false);
     37                                        window.addEventListener('load', t.ready, false);
     38                                } else if (document.attachEvent) {
     39                                        DOMContentLoaded = function(){if (document.readyState === 'complete'){ document.detachEvent('onreadystatechange', DOMContentLoaded);t.ready();}};
     40                                        document.attachEvent('onreadystatechange', DOMContentLoaded);
     41                                        window.attachEvent('onload', t.ready);
     42
     43                                        (function(){
     44                                                try {
     45                                                        document.documentElement.doScroll("left");
     46                                                } catch(e) {
     47                                                        setTimeout(arguments.callee, 50);
     48                                                        return;
     49                                                }
     50
     51                                                t.ready();
     52                                        })();
     53                                }
    21354
    214 function edQuickLink(i, thisSelect) {
    215         if (i > -1) {
    216                 var newWin = '', tempStr;
    217                 if (edLinks[i].newWin == 1) {
    218                         newWin = ' target="_blank"';
     55                                t.eventAttached = true;
     56                        }
    21957                }
    220                 tempStr = '<a href="' + edLinks[i].URL + '"' + newWin + '>'
    221                             + edLinks[i].display
    222                             + '</a>';
    223                 thisSelect.selectedIndex = 0;
    224                 edInsertContent(edCanvas, tempStr);
    225         }
    226         else {
    227                 thisSelect.selectedIndex = 0;
    228         }
    229 }
    230 
    231 function edSpell(myField) {
    232         var word = '', sel, startPos, endPos;
    233         if (document.selection) {
    234                 myField.focus();
    235             sel = document.selection.createRange();
    236                 if (sel.text.length > 0) {
    237                         word = sel.text;
     58        };
     59       
     60        var _zeroise = function(number, threshold) {
     61                // FIXME: or we could use an implementation of printf in js here
     62                var str = number.toString();
     63                if (! threshold) {
     64                        threshold = 2;
    23865                }
    239         }
    240         else if (myField.selectionStart || myField.selectionStart == '0') {
    241                 startPos = myField.selectionStart;
    242                 endPos = myField.selectionEnd;
    243                 if (startPos != endPos) {
    244                         word = myField.value.substring(startPos, endPos);
     66                if (number < 0) { str = str.substr(1, str.length); }
     67                while (str.length < threshold) { str = "0" + str; }
     68                if (number < 0) { str = '-' + str; }
     69                return str;
     70        };
     71       
     72        var _dateToString = function(d) {
     73                return '' +
     74                        d.getUTCFullYear() + '-' +
     75                        _zeroise(d.getUTCMonth() + 1, 2) + '-' +
     76                        _zeroise(d.getUTCDate(), 2) + 'T' +
     77                        _zeroise(d.getUTCHours(), 2) + ':' +
     78                        _zeroise(d.getUTCMinutes(), 2) + ':' +
     79                        _zeroise(d.getUTCSeconds() ,2) +
     80                        '+00:00';
     81        };
     82       
     83        var _instances = [],
     84                _now = new Date(),
     85                _datetime = _dateToString(_now),               
     86                _customButtons = {}, qt;
     87       
     88        qt = QTags = function(name, id, container, disabled) {
     89                var t = this,
     90                        cont = document.getElementById(container),
     91                        buttons = {},
     92                        links = [],
     93                        openTags = [],
     94                        i, c, p, tb, html, canvas;
     95                       
     96                t.name = name;
     97                t.id = id;
     98
     99                disabled = (typeof disabled == 'undefined') ? '' : ',' + disabled + ',';
     100               
     101                // default buttons
     102               
     103                for (i in edButtons) {
     104                        buttons[edButtons[i].id] = edButtons[i];
    245105                }
    246         }
    247         if (word == '') {
    248                 word = prompt(quicktagsL10n.wordLookup, '');
    249         }
    250         if (word !== null && /^\w[\w ]*$/.test(word)) {
    251                 window.open('http://www.answers.com/' + escape(word));
    252         }
    253 }
    254 
    255 function edToolbar() {
    256         document.write('<div id="ed_toolbar">');
    257         for (var i = 0; i < edButtons.length; i++) {
    258                 edShowButton(edButtons[i], i);
    259         }
    260         document.write('<input type="button" id="ed_spell" class="ed_button" onclick="edSpell(edCanvas);" title="' + quicktagsL10n.dictionaryLookup + '" value="' + quicktagsL10n.lookup + '" />');
    261         document.write('<input type="button" id="ed_close" class="ed_button" onclick="edCloseAllTags();" title="' + quicktagsL10n.closeAllOpenTags + '" value="' + quicktagsL10n.closeTags + '" />');
    262 //      edShowLinks(); // disabled by default
    263         document.write('</div>');
    264 }
    265 
    266 // insertion code
    267 
    268 function edInsertTag(myField, i) {
    269         //IE support
    270         if (document.selection) {
    271                 myField.focus();
    272             var sel = document.selection.createRange();
    273                 if (sel.text.length > 0) {
    274                         sel.text = edButtons[i].tagStart + sel.text + edButtons[i].tagEnd;
     106               
     107                // add custom buttons
     108                for (i in _customButtons) {
     109                        buttons[i] = new _customButtons[i]();
    275110                }
    276                 else {
    277                         if (!edCheckOpenTags(i) || edButtons[i].tagEnd == '') {
    278                                 sel.text = edButtons[i].tagStart;
    279                                 edAddTag(i);
    280                         }
    281                         else {
    282                                 sel.text = edButtons[i].tagEnd;
    283                                 edRemoveTag(i);
     111               
     112                html = '<div id="' + name + '_toolbar">';
     113                for (i in buttons) {
     114                        if (disabled && (disabled.indexOf(',' + buttons[i].id + ',') != -1)) {
     115                                continue;
    284116                        }
     117                        html += buttons[i].html(name + '_');
    285118                }
    286                 myField.focus();
    287         }
    288         //MOZILLA/NETSCAPE support
    289         else if (myField.selectionStart || myField.selectionStart == '0') {
    290                 var startPos = myField.selectionStart, endPos = myField.selectionEnd, cursorPos = endPos, scrollTop = myField.scrollTop;
    291 
    292                 if (startPos != endPos) {
    293                         myField.value = myField.value.substring(0, startPos)
    294                                       + edButtons[i].tagStart
    295                                       + myField.value.substring(startPos, endPos)
    296                                       + edButtons[i].tagEnd
    297                                       + myField.value.substring(endPos, myField.value.length);
    298                         cursorPos += edButtons[i].tagStart.length + edButtons[i].tagEnd.length;
    299                 }
    300                 else {
    301                         if (!edCheckOpenTags(i) || edButtons[i].tagEnd == '') {
    302                                 myField.value = myField.value.substring(0, startPos)
    303                                               + edButtons[i].tagStart
    304                                               + myField.value.substring(endPos, myField.value.length);
    305                                 edAddTag(i);
    306                                 cursorPos = startPos + edButtons[i].tagStart.length;
    307                         }
    308                         else {
    309                                 myField.value = myField.value.substring(0, startPos)
    310                                               + edButtons[i].tagEnd
    311                                               + myField.value.substring(endPos, myField.value.length);
    312                                 edRemoveTag(i);
    313                                 cursorPos = startPos + edButtons[i].tagEnd.length;
     119                html += "</div>";
     120                cont.innerHTML = html + cont.innerHTML;
     121               
     122                // listen for click events
     123                this.toolbar = tb = document.getElementById(name + '_toolbar');
     124               
     125               
     126                var onclick = function(e) {
     127                        e = e || window.event;
     128                        var target = e.target || e.srcElement, i;
     129
     130                        // as long as it has the class ed_button, execute the callback
     131                        if (/\s+ed_button\s+/.test(' ' + target.className + ' ')) {
     132                                // we have to reassign canvas here
     133                                t.canvas = canvas = document.getElementById(id);
     134                                i = target.id.replace(name + '_', '');
     135                                if (buttons[i]) {
     136                                        buttons[i].callback.call(buttons[i], target, canvas, t);
     137                                }
    314138                        }
     139                };
     140               
     141                if (tb.addEventListener) {
     142                        tb.addEventListener('click', onclick, false);
     143                } else if (tb.attachEvent) {
     144                        tb.attachEvent('onclick', onclick);
    315145                }
    316                 myField.focus();
    317                 myField.selectionStart = cursorPos;
    318                 myField.selectionEnd = cursorPos;
    319                 myField.scrollTop = scrollTop;
    320         }
    321         else {
    322                 if (!edCheckOpenTags(i) || edButtons[i].tagEnd == '') {
    323                         myField.value += edButtons[i].tagStart;
    324                         edAddTag(i);
    325                 }
    326                 else {
    327                         myField.value += edButtons[i].tagEnd;
    328                         edRemoveTag(i);
    329                 }
    330                 myField.focus();
    331         }
    332 }
    333 
    334 function edInsertContent(myField, myValue) {
    335         var sel, startPos, endPos, scrollTop;
    336 
    337         //IE support
    338         if (document.selection) {
    339                 myField.focus();
    340                 sel = document.selection.createRange();
    341                 sel.text = myValue;
    342                 myField.focus();
    343         }
    344         //MOZILLA/NETSCAPE support
    345         else if (myField.selectionStart || myField.selectionStart == '0') {
    346                 startPos = myField.selectionStart;
    347                 endPos = myField.selectionEnd;
    348                 scrollTop = myField.scrollTop;
    349                 myField.value = myField.value.substring(0, startPos)
    350                               + myValue
    351                       + myField.value.substring(endPos, myField.value.length);
    352                 myField.focus();
    353                 myField.selectionStart = startPos + myValue.length;
    354                 myField.selectionEnd = startPos + myValue.length;
    355                 myField.scrollTop = scrollTop;
    356         } else {
    357                 myField.value += myValue;
    358                 myField.focus();
    359         }
    360 }
    361 
    362 function edInsertLink(myField, i, defaultValue) {
    363         if (!defaultValue) {
    364                 defaultValue = 'http://';
    365         }
    366         if (!edCheckOpenTags(i)) {
    367                 var URL = prompt(quicktagsL10n.enterURL, defaultValue);
    368                 if (URL) {
    369                         edButtons[i].tagStart = '<a href="' + URL + '">';
    370                         edInsertTag(myField, i);
    371                 }
    372         }
    373         else {
    374                 edInsertTag(myField, i);
    375         }
    376 }
    377 
    378 function edInsertImage(myField) {
    379         var myValue = prompt(quicktagsL10n.enterImageURL, 'http://');
    380         if (myValue) {
    381                 myValue = '<img src="'
    382                                 + myValue
    383                                 + '" alt="' + prompt(quicktagsL10n.enterImageDescription, '')
    384                                 + '" />';
    385                 edInsertContent(myField, myValue);
    386         }
    387 }
    388 
    389 
    390 // Allow multiple instances.
    391 // Name = unique value, id = textarea id, container = container div.
    392 // Can disable some buttons by passing comma delimited string as 4th param.
    393 var QTags = function(name, id, container, disabled) {
    394         var t = this, cont = document.getElementById(container), i, tag, tb, html, sel;
    395 
    396         t.Buttons = [];
    397         t.Links = [];
    398         t.OpenTags = [];
    399         t.Canvas = document.getElementById(id);
    400 
    401         if ( ! t.Canvas || ! cont )
    402                 return;
    403 
    404         disabled = ( typeof disabled != 'undefined' ) ? ','+disabled+',' : '';
    405 
    406         t.edShowButton = function(button, i) {
    407                 if ( disabled && (disabled.indexOf(','+button.display+',') != -1) )
    408                         return '';
    409                 else if ( button.id == name+'_img' )
    410                         return '<input type="button" id="' + button.id + '" accesskey="' + button.access + '" class="ed_button" onclick="edInsertImage('+name+'.Canvas);" value="' + button.display + '" />';
    411                 else if (button.id == name+'_link')
    412                         return '<input type="button" id="' + button.id + '" accesskey="' + button.access + '" class="ed_button" onclick="'+name+'.edInsertLink('+i+');" value="'+button.display+'" />';
    413                 else
    414                         return '<input type="button" id="' + button.id + '" accesskey="'+button.access+'" class="ed_button" onclick="'+name+'.edInsertTag('+i+');" value="'+button.display+'" />';
     146               
     147                t.getButton = function(id){
     148                        return buttons[id];
     149                };
     150               
     151                _instances[id] = t;
    415152        };
    416 
    417         t.edAddTag = function(button) {
    418                 if ( t.Buttons[button].tagEnd != '' ) {
    419                         t.OpenTags[t.OpenTags.length] = button;
    420                         document.getElementById(t.Buttons[button].id).value = '/' + document.getElementById(t.Buttons[button].id).value;
    421                 }
     153       
     154        qt.registerButton = function(id, btnClass) {
     155                _customButtons[id] = btnClass;
    422156        };
    423 
    424         t.edRemoveTag = function(button) {
    425                 for ( i = 0; i < t.OpenTags.length; i++ ) {
    426                         if ( t.OpenTags[i] == button ) {
    427                                 t.OpenTags.splice(i, 1);
    428                                 document.getElementById(t.Buttons[button].id).value = document.getElementById(t.Buttons[button].id).value.replace('/', '');
    429                         }
    430                 }
     157       
     158        qt.getInstance = function(id) {
     159                return _instances[id];
    431160        };
    432 
    433         t.edCheckOpenTags = function(button) {
    434                 tag = 0;
    435                 for ( var i = 0; i < t.OpenTags.length; i++ ) {
    436                         if ( t.OpenTags[i] == button )
    437                                 tag++;
     161       
     162        // when used with the_editor()
     163        qt.init = function(id){
     164                _domReady(function(){
     165                        var instance = new QTags('ed', id, 'quicktags');
     166                });
     167        };
     168       
     169        // a plain, dumb button
     170        qt.Button = function(id, display, access) {
     171                var t = this;
     172                t.id = id;
     173                t.display = display;
     174                t.access = access;
     175        };
     176        qt.Button.prototype.html = function(idPrefix) {
     177                var access = this.access ? ' accesskey="' + this.access + '"' : '';
     178                return '<input type="button" id="' + idPrefix + this.id + '"' + access + ' class="ed_button" value="' + this.display + '" />';
     179        };
     180        qt.Button.prototype.callback = function(canvas) {};
     181       
     182        // a button that inserts HTML tag
     183        qt.TagButton = function(id, display, tagStart, tagEnd, access, open) {
     184                var t = this;
     185                qt.Button.call(t, id, display, access);
     186                t.tagStart = tagStart;
     187                t.tagEnd = tagEnd;
     188                t.open = open;         
     189        };
     190        qt.TagButton.prototype = new qt.Button();
     191        qt.TagButton.prototype.openTag = function(e, tb) {
     192                var t = this;
     193                if (! tb.openTags) {
     194                        tb.openTags = [];
     195                }
     196                if (t.tagEnd) {
     197                        tb.openTags.push(t.id);
     198                        e.value = '/' + e.value;
    438199                }
    439                 if ( tag > 0 ) return true; // tag found
    440                 else return false; // tag not found
    441200        };
    442 
    443         this.edCloseAllTags = function() {
    444                 var count = t.OpenTags.length;
    445                 for ( var o = 0; o < count; o++ )
    446                         t.edInsertTag(t.OpenTags[t.OpenTags.length - 1]);
     201        qt.TagButton.prototype.closeTag = function(e, tb) {
     202                var t = this,
     203                        i = t.isOpen(tb);
     204               
     205                if (i !== false) {
     206                        tb.openTags.splice(i, 1);
     207                }
     208               
     209                e.value = t.display;
    447210        };
    448 
    449         this.edQuickLink = function(i, thisSelect) {
    450                 if ( i > -1 ) {
    451                         var newWin = '', tempStr;
    452                         if ( Links[i].newWin == 1 ) {
    453                                 newWin = ' target="_blank"';
     211        // whether a tag is open or not. Returns false if not open, or current open depth of the tag
     212        qt.TagButton.prototype.isOpen = function (tb) {
     213                var t = this, i = 0, ret = false;
     214                if (tb.openTags) {
     215                        while (ret === false && i < tb.openTags.length) {
     216                                ret = tb.openTags[i] == t.id ? i : false;
     217                                i ++;
    454218                        }
    455                         tempStr = '<a href="' + Links[i].URL + '"' + newWin + '>'
    456                                     + Links[i].display
    457                                     + '</a>';
    458                         thisSelect.selectedIndex = 0;
    459                         edInsertContent(t.Canvas, tempStr);
    460219                } else {
    461                         thisSelect.selectedIndex = 0;
     220                        ret = false;
    462221                }
     222                return ret;
    463223        };
     224        qt.TagButton.prototype.callback = function(element, canvas, toolbar) {
     225                var t = this, startPos, endPos, cursorPos, scrollTop, v, l, r, i, sel;
     226
     227                v = canvas.value;
    464228
    465         // insertion code
    466         t.edInsertTag = function(i) {
    467                 //IE support
    468                 if ( document.selection ) {
    469                         t.Canvas.focus();
    470                     sel = document.selection.createRange();
    471                         if ( sel.text.length > 0 ) {
    472                                 sel.text = t.Buttons[i].tagStart + sel.text + t.Buttons[i].tagEnd;
     229                // IE support
     230                if (document.selection) {
     231                        canvas.focus();
     232                        sel = document.selection.createRange();
     233                        if (sel.text.length > 0) {
     234                                sel.text = t.tagStart + sel.text + t.tagEnd;
    473235                        } else {
    474                                 if ( ! t.edCheckOpenTags(i) || t.Buttons[i].tagEnd == '' ) {
    475                                         sel.text = t.Buttons[i].tagStart;
    476                                         t.edAddTag(i);
     236                                if (t.isOpen(toolbar) === false || t.tagEnd === '') {
     237                                        sel.text = t.tagStart;
     238                                        t.openTag(element, toolbar);
    477239                                } else {
    478                                         sel.text = t.Buttons[i].tagEnd;
    479                                         t.edRemoveTag(i);
     240                                        sel.text = t.tagEnd;
     241                                        t.closeTag(element, toolbar);
    480242                                }
    481243                        }
    482                         t.Canvas.focus();
    483                 } else if ( t.Canvas.selectionStart || t.Canvas.selectionStart == '0' ) { //MOZILLA/NETSCAPE support
    484                         var startPos = t.Canvas.selectionStart, endPos = t.Canvas.selectionEnd, cursorPos = endPos, scrollTop = t.Canvas.scrollTop;
    485 
    486                         if ( startPos != endPos ) {
    487                                 t.Canvas.value = t.Canvas.value.substring(0, startPos)
    488                                               + t.Buttons[i].tagStart
    489                                               + t.Canvas.value.substring(startPos, endPos)
    490                                               + t.Buttons[i].tagEnd
    491                                               + t.Canvas.value.substring(endPos, t.Canvas.value.length);
    492                                 cursorPos += t.Buttons[i].tagStart.length + t.Buttons[i].tagEnd.length;
     244                        canvas.focus();
     245                }
     246                // moz, webkit, opera
     247                else if (canvas.selectionStart || canvas.selectionStart == '0') {
     248                        startPos = canvas.selectionStart;
     249                        endPos = canvas.selectionEnd;
     250                        cursorPos = endPos;
     251                        scrollTop = canvas.scrollTop;
     252                        l = v.substring(0, startPos); // left of the selection
     253                        r = v.substring(endPos, v.length); // right of the selection
     254                        i = v.substring(startPos, endPos); // inside the selection
     255                        if (startPos != endPos) {
     256                                canvas.value = l + t.tagStart + i + t.tagEnd + r;
     257                                if (t.tagEnd === '') {
     258                                        cursorPos = startPos;
     259                                }
     260                                cursorPos += t.tagStart.length + t.tagEnd.length;
    493261                        } else {
    494                                 if ( !t.edCheckOpenTags(i) || t.Buttons[i].tagEnd == '' ) {
    495                                         t.Canvas.value = t.Canvas.value.substring(0, startPos)
    496                                                       + t.Buttons[i].tagStart
    497                                                       + t.Canvas.value.substring(endPos, t.Canvas.value.length);
    498                                         t.edAddTag(i);
    499                                         cursorPos = startPos + t.Buttons[i].tagStart.length;
     262                                if (t.isOpen(toolbar) === false || t.tagEnd === '') {
     263                                        canvas.value = l + t.tagStart + r;
     264                                        t.openTag(element, toolbar);
     265                                        cursorPos = startPos + t.tagStart.length;
    500266                                } else {
    501                                         t.Canvas.value = t.Canvas.value.substring(0, startPos)
    502                                                       + t.Buttons[i].tagEnd
    503                                                       + t.Canvas.value.substring(endPos, t.Canvas.value.length);
    504                                         t.edRemoveTag(i);
    505                                         cursorPos = startPos + t.Buttons[i].tagEnd.length;
     267                                        canvas.value = l + t.tagEnd + r;
     268                                        cursorPos = startPos + t.tagEnd.length;
     269                                        t.closeTag(element, toolbar);
    506270                                }
    507271                        }
    508                         t.Canvas.focus();
    509                         t.Canvas.selectionStart = cursorPos;
    510                         t.Canvas.selectionEnd = cursorPos;
    511                         t.Canvas.scrollTop = scrollTop;
    512                 } else {
    513                         if ( ! t.edCheckOpenTags(i) || t.Buttons[i].tagEnd == '' ) {
    514                                 t.Canvas.value += Buttons[i].tagStart;
    515                                 t.edAddTag(i);
     272
     273                        canvas.focus();
     274                        canvas.selectionStart = cursorPos;
     275                        canvas.selectionEnd = cursorPos;
     276                        canvas.scrollTop = scrollTop;
     277                }
     278                // other browsers
     279                else {
     280                        if (t.isOpen(toolbar) !== false || t.tagEnd === '') {
     281                                canvas.value += t.tagStart;
     282                                t.openTag(element, toolbar);
    516283                        } else {
    517                                 t.Canvas.value += Buttons[i].tagEnd;
    518                                 t.edRemoveTag(i);
     284                                canvas.value += t.tagEnd;
     285                                t.closeTag(element, toolbar);
    519286                        }
    520                         t.Canvas.focus();
     287                        canvas.focus();
    521288                }
    522289        };
    523 
    524         this.edInsertLink = function(i, defaultValue) {
    525                 if ( ! defaultValue )
     290       
     291        // the spell button
     292        qt.SpellButton = function() {
     293                qt.Button.call(this, 'spell', quicktagsL10n.lookup, '');
     294        };
     295        qt.SpellButton.prototype = new qt.Button();
     296        qt.SpellButton.prototype.callback = function(element, canvas, toolbar) {
     297                var word = '', sel, startPos, endPos;
     298               
     299                if (document.selection) {
     300                        canvas.focus();
     301                        sel = document.selection.createRange();
     302                        if (sel.text.length > 0) {
     303                                word = sel.text;
     304                        }
     305                }
     306                else if (canvas.selectionStart || canvas.selectionStart == '0') {
     307                        startPos = canvas.selectionStart;
     308                        endPos = canvas.selectionEnd;
     309                        if (startPos != endPos) {
     310                                word = canvas.value.substring(startPos, endPos);
     311                        }
     312                }
     313               
     314                if (word === '') {
     315                        word = prompt(quicktagsL10n.wordLookup, '');
     316                }
     317               
     318                if (word !== null && /^\w[\w ]*$/.test(word)) {
     319                        window.open('http://www.answers.com/' + encodeURIComponent(word));
     320                }
     321        };
     322       
     323        // the close button
     324        qt.CloseButton = function() {
     325                qt.Button.call(this, 'close', quicktagsL10n.closeAllOpenTags, '');
     326        };
     327        qt.CloseButton.prototype = new qt.Button();
     328        qt.CloseButton.prototype.callback = function(e, c, tb) {
     329                var button, i, element, tbo = tb.openTags;
     330                if (tbo) {
     331                        while (tbo.length > 0) {
     332                                button = tb.getButton(tbo[tbo.length - 1]);
     333                                element = document.getElementById(tb.name + '_' + button.id);
     334                                button.callback.call(button, element, c, tb);
     335                        }
     336                }
     337        };
     338        qt.prototype.closeAllTags = function() {
     339                var btn = this.getButton('close');
     340                btn.callback.call(btn, '', this.canvas, this.toolbar);
     341        };
     342       
     343        // the link button
     344        qt.LinkButton = function() {
     345                qt.TagButton.call(this, 'link', 'link', '', '</a>', 'a');
     346        };
     347        qt.LinkButton.prototype = new qt.TagButton();
     348        qt.LinkButton.prototype.callback = function(e, c, tb, defaultValue) {
     349                var URL, t = this;
     350               
     351                if (! defaultValue) {
    526352                        defaultValue = 'http://';
    527 
    528                 if ( ! t.edCheckOpenTags(i) ) {
    529                         var URL = prompt(quicktagsL10n.enterURL, defaultValue);
    530                         if ( URL ) {
    531                                 t.Buttons[i].tagStart = '<a href="' + URL + '">';
    532                                 t.edInsertTag(i);
     353                }
     354               
     355                if (t.isOpen(tb) === false) {
     356                        URL = prompt(quicktagsL10n.enterURL, defaultValue);
     357                        if (URL) {
     358                                t.tagStart = '<a href="' + URL + '">';
     359                                qt.TagButton.prototype.callback.call(t, e, c, tb);
    533360                        }
    534361                } else {
    535                         t.edInsertTag(i);
     362                        qt.TagButton.prototype.callback.call(t, e, c, tb);
    536363                }
    537364        };
    538 
    539         this.edInsertImage = function() {
    540                 var myValue = prompt(quicktagsL10n.enterImageURL, 'http://');
    541                 if ( myValue ) {
    542                         myValue = '<img src="'
    543                                         + myValue
    544                                         + '" alt="' + prompt(quicktagsL10n.enterImageDescription, '')
    545                                         + '" />';
    546                         edInsertContent(t.Canvas, myValue);
     365       
     366        // the img button
     367        qt.ImgButton = function() {
     368                qt.TagButton.call(this, 'img', 'img', '', '', 'm', -1);
     369        };
     370        qt.ImgButton.prototype = new qt.TagButton();
     371        qt.ImgButton.prototype.callback = function(e, c, tb, defaultValue) {
     372                if (! defaultValue) {
     373                        defaultValue = 'http://';
     374                }
     375                var src = prompt(quicktagsL10n.enterImageURL, defaultValue), alt;
     376                if (src) {
     377                        alt = prompt(quicktagsL10n.enterImageDescription, '');
     378                        this.tagStart = '<img src="' + src + '" alt="' + alt + '" />';
     379                        qt.TagButton.prototype.callback.call(this, e, c, tb);
    547380                }
    548381        };
    549382
    550         t.Buttons[t.Buttons.length] = new edButton(name+'_strong','b','<strong>','</strong>','b');
    551         t.Buttons[t.Buttons.length] = new edButton(name+'_em','i','<em>','</em>','i');
    552         t.Buttons[t.Buttons.length] = new edButton(name+'_link','link','','</a>','a'); // special case
    553         t.Buttons[t.Buttons.length] = new edButton(name+'_block','b-quote','\n\n<blockquote>','</blockquote>\n\n','q');
    554         t.Buttons[t.Buttons.length] = new edButton(name+'_del','del','<del datetime="' + datetime + '">','</del>','d');
    555         t.Buttons[t.Buttons.length] = new edButton(name+'_ins','ins','<ins datetime="' + datetime + '">','</ins>','s');
    556         t.Buttons[t.Buttons.length] = new edButton(name+'_img','img','','','m',-1); // special case
    557         t.Buttons[t.Buttons.length] = new edButton(name+'_ul','ul','<ul>\n','</ul>\n\n','u');
    558         t.Buttons[t.Buttons.length] = new edButton(name+'_ol','ol','<ol>\n','</ol>\n\n','o');
    559         t.Buttons[t.Buttons.length] = new edButton(name+'_li','li','\t<li>','</li>\n','l');
    560         t.Buttons[t.Buttons.length] = new edButton(name+'_code','code','<code>','</code>','c');
    561         t.Buttons[t.Buttons.length] = new edButton(name+'_more','more','<!--more-->','','t',-1);
    562 //      t.Buttons[t.Buttons.length] = new edButton(name+'_next','page','<!--nextpage-->','','p',-1);
    563 
    564         tb = document.createElement('div');
    565         tb.id = name+'_qtags';
    566 
    567         html = '<div id="'+name+'_toolbar">';
    568         for (i = 0; i < t.Buttons.length; i++)
    569                 html += t.edShowButton(t.Buttons[i], i);
    570 
    571         html += '<input type="button" id="'+name+'_ed_spell" class="ed_button" onclick="edSpell('+name+'.Canvas);" title="' + quicktagsL10n.dictionaryLookup + '" value="' + quicktagsL10n.lookup + '" />';
    572         html += '<input type="button" id="'+name+'_ed_close" class="ed_button" onclick="'+name+'.edCloseAllTags();" title="' + quicktagsL10n.closeAllOpenTags + '" value="' + quicktagsL10n.closeTags + '" /></div>';
    573 
    574         tb.innerHTML = html;
    575         cont.parentNode.insertBefore(tb, cont);
    576 
    577 };
     383        // ensure backward compatibility
     384        edButtons = [
     385                new qt.TagButton('strong','b','<strong>','</strong>','b'),
     386                new qt.TagButton('em','i','<em>','</em>','i'),
     387                new qt.LinkButton(), // special case
     388                new qt.TagButton('block','b-quote','\n\n<blockquote>','</blockquote>\n\n','q'),
     389                new qt.TagButton('del','del','<del datetime="' + _datetime + '">','</del>','d'),
     390                new qt.TagButton('ins','ins','<ins datetime="' + _datetime + '">','</ins>','s'),
     391                new qt.ImgButton(), // special case
     392                new qt.TagButton('ul','ul','<ul>\n','</ul>\n\n','u'),
     393                new qt.TagButton('ol','ol','<ol>\n','</ol>\n\n','o'),
     394                new qt.TagButton('li','li','\t<li>','</li>\n','l'),
     395                new qt.TagButton('code','code','<code>','</code>','c'),
     396                new qt.TagButton('more','more','<!--more-->','','t',-1),
     397                new qt.SpellButton(),
     398                new qt.CloseButton()
     399        ];
     400       
     401        edButton = qt.TagButton;
     402})();
     403 No newline at end of file