Вход Регистрация
Файл: public/js/ips.editor.js
Строк: 2878
<?php

/************************************************/
/* IPB3 Javascript                                */
/* -------------------------------------------- */
/* ips.editor.js - Editor class                    */
/* (c) IPS, Inc 2008                            */
/* -------------------------------------------- */
/* Author: Rikki Tissier (based on Matt's code)    */
/************************************************/

var _editor window.IPBoard;

var 
isRTL = ( isRTL ) ? isRTL false;

/* ===================================================================================================== */
/* Values for the IPB text editor */

IPBoard.prototype.editor_values $H({
    
'templates':         $A(),
    
'colors_perrow':     8,
    
'colors': [         '000000' 'A0522D' '556B2F' '006400' '483D8B' '000080' '4B0082' '2F4F4F' ,
                        
'8B0000' 'FF8C00' '808000' '008000' ,    '008080' '0000FF' '708090' '696969' ,
                        
'FF0000' 'F4A460' '9ACD32' '2E8B57' '48D1CC' '4169E1' '800080' '808080' ,
                        
'FF00FF' 'FFA500' 'FFFF00' '00FF00' ,    '00FFFF' '00BFFF' '9932CC' 'C0C0C0' ,
                        
'FFC0CB' 'F5DEB3' 'FFFACD' '98FB98' ,    'AFEEEE' 'ADD8E6' 'DDA0DD' 'FFFFFF'
                    
],
    
    
// You can add new fonts here if you wish, HOWEVER, if you use
    // non-standard fonts, users without those fonts on their computer
    // will not see them. The default list below has the generally accepted
    // safe fonts; add others at your own risk! 
    
'primary_fonts'$H({     arial:                    "Arial",
                            
arialblack:                "Arial Black",
                            
arialnarrow:            "Arial Narrow",
                            
bookantiqua:            "Book Antiqua",
                            
centurygothic:            "Century Gothic",
                            
comicsansms:            "Comic Sans MS",
                            
couriernew:                "Courier New",
                            
franklingothicmedium:    "Franklin Gothic Medium",
                            
garamond:                "Garamond",
                            
georgia:                "Georgia",
                            
impact:                    "Impact",
                            
lucidaconsole:            "Lucida Console",
                            
lucidasansunicode:        "Lucida Sans Unicode",
                            
microsoftsansserif:        "Microsoft Sans Serif",
                            
palatinolinotype:        "Palatino Linotype",
                            
tahoma:                    "Tahoma",
                            
timesnewroman:            "Times New Roman",
                            
trebuchetms:            "Trebuchet MS",
                            
verdana:                "Verdana"
                    
}),
    
'font_sizes'$A([ 123456])
                
});

// =============================================================================================================//
// Class for RTE EDITOR which is inherited by main Editor class
_editor_rte = Class.create({
    
_identifyType: function()
    {
        
Debug.write"(Editor " this.id ") This is the RTE class" );
    },
    
togglesource_pre_show_html: function()
    {
    },
    
togglesource_post_show_html: function()
    {
    },
    
editor_write_contents: function( textdo_init )
    { 
        
        if ( ( 
Object.isUndefined(text) || text === false || text.blank() ) && Prototype.Browser.Gecko )
        {
            
text '<br />';
        }
        else if ( 
Object.isUndefined(text) || text === false )
        {
            
text '';
        }
        
        if ( 
this.editor_document && this.editor_document.initialized )
        {
            
this.editor_document.body.innerHTML text;
        }
        else
        {
            if ( 
do_init )
            {
                
this.editor_document.designMode 'on';
            }

            
this.editor_document this.editor_window.document;
            
this.editor_document.open'text/html''replace' );
            
this.editor_document.writethis.ips_frame_html.replace'{:content:}'text ) );
            
this.editor_document.close();
            
            if ( 
do_init )
            {
                
this.editor_document.body.contentEditable true;
                
this.editor_document.initialized          true;
            }
        }
    },
    
removeformat: function(e)
    {
        
this.apply_formatting'unlink'      falsefalse );
        
this.apply_formatting'removeformat'falsefalse );
        
/*this.apply_formatting( 'killword', false, false );*/
        
        
var text this.get_selection();

        if ( 
text )
        {
            
text this.strip_htmltext );
            
text this.strip_empty_htmltext );
            
text text.replace( /r/g"" );
            
text text.replace( /n/g"<br />" );
            
text text.replace( /<!--(.*?)-->/g"" );
            
text text.replace( /&lt;!--(.*?)--&gt;/g"" );

            
this.insert_texttext );
        }
    },
    
editor_get_contents: function()
    {
        return 
this.editor_document.body.innerHTML;
    },
    
editor_set_content: function( init_text )
    { 
        if( $( 
this.id '_iframe' ) )
        {
            
this.editor_box = $( this.id '_iframe' );
        }
        else
        {
            
// Create iframe
            
var iframe = new Element('iframe', { 'id'this.id '_iframe''tabindex'} );
            
            if( 
Prototype.Browser.IE && window.location.protocol == 'https:' )
            {
                
iframe.writeAttribute'src'this.options.file_path '/index.html' );
            }
            
            
// Insert into DOM
            
this.items['text_obj'].up().insertiframe );
            
this.editor_box iframe;
        }
        
        if( !
Prototype.Browser.IE )
        {
            
this.editor_box.setStyle'border: 1px inset' );
        }
        else
        {
            
// Bug #17772
            
if( !Object.isUndefinedinit_text ) && init_text != false )
            {
                
init_text init_text.replace( /&sect/g"&amp;sect");
            }
        }
        
        
//-----------------------------------------
        // Is there a height in the cookies?
        //-----------------------------------------
        
        
var test_height ipb.Cookie.get'ips_rte_height' );
        
        
/*Debug.write( "Height is " + test_height );*/
        
        
if ( Object.isNumbertest_height ) && test_height 50 )
        {
            
this.items['text_obj'].setStyle( { heighttest_height 'px' } );
            
Debug.write"Set text_obj height to " test_height );
        }
        
        
// Set up
        
var tobj_dims this.items['text_obj'].getDimensions();
        
        if( 
Object.isUndefinedtobj_dims ) || tobj_dims['height'] == )
        {
            
tobj_dims['height'] = 250;
        }
        
        
//Debug.write( tobj_dims );
        
        /*Debug.write( this.items['text_obj'].getDimensions()['height'] );*/
        
        
this.editor_box.setStyle( { width:         '100%',
                                    
height:     tobj_dims.height 'px',
                                    
className:     this.items['text_obj'].className
                                 
});
                                
        
this.items['text_obj'].hide();
        
        
//---------
        
        
this.editor_window   this.editor_box.contentWindow;
        
this.editor_document this.editor_window.document;
        
        if ( ! 
this.items['text_obj'].value && ( init_text === false || Object.isUndefinedinit_text ) ) )
        {
            
/* Wipe editor */
            
this.editor_write_contents(falsetrue);
        }
        else
        {
            
this.editor_write_contents( (Object.isUndefinedinit_text ) || ! init_text ?  this.items['text_obj'].value init_text), true );
        }
    
        
this.editor_document.editor_id this.editor_id;
        
this.editor_window.editor_id   this.editor_id;
        
this.editor_window.has_focus   false;
        
        
// Go on.. cursor, flash you bastard        
        
try
        {
            
Debug.write"Attempt to get focus" );
            
this.editor_check_focus();
            
            
// Sometimes moves the focus to the RTE
            
this.editor_document.execCommand("InsertHorizontalRule"falsenull);
            
this.editor_document.execCommand("undo"      falsenull);
        }
        catch(
error)
        {
            
Debug.write"#011 " error );
        }
        
        
//-----------------------------------------
        // Kill tags
        //-----------------------------------------
        
        //document.getElementById( this.editor_id + '_cmd_justifyfull' ).style.display  = 'none';
    
},
    
apply_formatting: function(cmddialogargument)
    {
        
dialog   = ( Object.isUndefineddialog ) ? false dialog);
        
argument = ( Object.isUndefinedargument ) ? true  argument);
        
        if ( 
Prototype.Browser.IE && this.forum_fix_ie_newlines )
        {
            if ( 
cmd == 'justifyleft' || cmd == 'justifycenter' || cmd == 'justifyright' )
            {
                var 
_a  cmd.replace"justify""" );

                
this.wrap_tags_lite"[" _a "]""[/" _a "]" );
                return 
true;
            }
            else if ( 
cmd == 'outdent' || cmd == 'indent' || cmd == 'insertorderedlist' || cmd == 'insertunorderedlist' 
            {
                
this.editor_check_focus();

                var 
sel this.editor_document.selection;
                var 
ts  this.editor_document.selection.createRange();

                var 
t   ts.htmlText.replace(/<p([^>]*)>(.*)</p>/i'$2');

                if ( (
sel.type == "Text" || sel.type == "None") )
                {
                    
ts.pasteHTML"<p />n" );
                }
                else
                {
                    
this.editor_document.body.innerHTML += "<p />";
                }
            }
        }

        
//alert( "Here" );
        /*Debug.write( "Apply formatting selection is: " + this.get_selection() + ", cmd is " + cmd );*/
        
        
if( Prototype.Browser.IE && this._ie_cache != null )
        {
            
this.editor_check_focus();
            
this._ie_cache.select();
        }
        
        
this.editor_document.execCommandcmddialogargument );
        
        
this._ie_cache null;
        return 
false;
    },
    
/* ! get_selection */
    
get_selection: function()
    {
        var 
rng this._ie_cache this._ie_cache this.editor_document.selection.createRange();
        
        
//Debug.write( 'get selection: ie_cache:' + this._ie_cache.htmlText + '.' );
        
        
if ( rng.htmlText )
        {
            
Debug.write'htmlTest:' rng.htmlText '.' );
            return 
rng.htmlText;
        }
        else
        {
            var 
rtn '';
            
            for (var 
0rng.lengthi++)
            {
                
rtn += rng.item(i).outerHTML;
            }
        }
        
        return 
rtn;
    },
    
editor_set_functions: function()
    {
        
//Debug.write( this.editor_document );
        
Event.observethis.editor_document'mouseup'this.events.editor_document_onmouseup.bindAsEventListenerthis ) );
        
Event.observethis.editor_document'keyup'this.events.editor_document_onkeyup.bindAsEventListenerthis ) );
        
Event.observethis.editor_document'keydown'this.events.editor_document_onkeydown.bindAsEventListenerthis ) );
        
        
        
Event.observethis.editor_window'blur'this.events.editor_window_onblur.bindAsEventListenerthis ) );
        
Event.observethis.editor_window'focus'this.events.editor_window_onfocus.bindAsEventListenerthis ) );
    },
    
set_context: function( cmd )
    {
        
// Showing HTML?
        
if ( this._showing_html )
        {
            return 
false;
        }
        
        
this.button_update.each( function(item)
        {
            
//Debug.write( this.id + '_cmd_' + item );
            
var obj = $( this.id '_cmd_' item );
            
            if( 
obj != null )
            {
                try {
                    var 
state = new Stringthis.editor_document.queryCommandStateitem ) );
                    
                    if( 
obj.readAttribute('state') != state )
                    {
                        
obj.writeAttribute'state', new Stringstate ) );
                        
this.set_button_contextobj, ( obj.readAttribute('cmd') == cmd 'mouseover' 'mouseout' ) );
                    }
                }
                catch( 
error )
                {
                    
Debug.write"#1 " error );
                }
            }
        }.
bind(this) );
        
        
//-----------------------------------------
        // Check and set font context
        //-----------------------------------------
        
        
this.button_set_font_context();
        
        
//-----------------------------------------
        // Check and set size context
        //-----------------------------------------
        
        
this.button_set_size_context();
    },
    
button_set_font_context: function( font_state )
    {    
        
changeto '';
        
        
// Showing HTML?
        
if ( this._showing_html )
        {
            return 
false;
        }
        
        if( 
this.items['buttons']['fontname'] )
        {
            if( 
Object.isUndefinedfont_state ) ){
                
font_state this.editor_document.queryCommandValue('fontname') || '';
            }
            
            if( 
font_state.blank() ){
                if ( !
Prototype.Browser.IE && window.getComputedStyle )
                {
                    
font_state this.editor_document.body.style.fontFamily;
                }
            } else if( 
font_state == null ){
                
font_state '';
            }
            
            if( 
font_state != this.font_state )
            {
                
this.font_state    font_state;
                var 
fontword    font_state;
                var 
commapos     fontword.indexOf(",");

                if( 
commapos != -){
                    
fontword fontword.substr(0commapos);
                }
                
                
fontword fontword.toLowerCase();
                
changeto '';
                
                
ipb.editor_values.get('primary_fonts').any( function(font){
                    if( 
font.value.toLowerCase() == fontword ){
                        
changeto font.value;
                        return 
true;
                    } else {
                        return 
false;
                    }                    
                });
                
                
changeto = ( changeto == '' ) ? this.fontoptions['_default'] : changeto;
                
                
this.items['buttons']['fontname'].updatechangeto );
            }
        }
    },        
    
    
button_set_size_context: function( size_state )
    {        
        if( 
this.items['buttons']['fontsize'] )
        {
            if( 
Object.isUndefinedsize_state ) ){
                
size_state this.editor_document.queryCommandValue('fontsize');
            }
            
            if( 
size_state == null || size_state == ''  )
            {
                if ( 
Prototype.Browser.Gecko )
                {
                    
size_state this.convert_sizethis.editor_document.body.style.fontSize);
                    
                    if ( ! 
size_state )
                    {
                        
size_state '2';
                    }
                }
            }
            
            
changeto '';
            if ( 
size_state != this.size_state )
            {
                
this.size_state size_state;
                
                
ipb.editor_values.get('font_sizes').any( function(size){
                    if( 
parseIntsize ) == parseIntthis.size_state ) ){
                        
changeto size;
                        return 
true;
                    } else {
                        return 
false;
                    }
                }.
bind(this));
                
                
changeto = ( changeto == '' ) ? this.sizeoptions['_default'] : changeto;
                
                
this.items['buttons']['fontsize'].updatechangeto );
            }
        }
    },
    
/* ! insert_text */
    
insert_text: function(text)
    {
        
Debug.write"Inserting " text "." );
        
this.editor_check_focus();

        if ( 
typeofthis.editor_document.selection )    != 'undefined'
                  
&& this.editor_document.selection.type != 'Text'
                  
&& this.editor_document.selection.type != 'None' )
        {
            
this.editor_document.selection.clear();
        }
        
        var 
sel this._ie_cache this._ie_cache this.editor_document.selection.createRange();
        
sel.pasteHTML(text);
        
sel.select();        
        
this._ie_cache null;
    },
    
/* ! insert_emoticon */
    
insert_emoticon: function( emo_idemo_imageemo_codeevent )
    {
        
Debug.write"Adding emoticon " emo_code );
        
        try
        {
            
//this._ie_cache = null;
            // INIT
            
var _emo_url  ipb.vars['emoticon_url'] + "/" emo_image;
            var 
_emo_html ' <img src="' _emo_url '" class="bbc_emoticon" alt="' this.unhtmlspecialcharsemo_code ) + '" />';
            
            
this.wrap_tags_lite" " _emo_html" "false);
        }
        catch( 
error )
        {
            
Debug.write"#2 " error );
            
//alert( error );
        
}
        
        
/*if ( this.emoticon_window_id != '' && typeof( this.emoticon_window_id ) != 'undefined' )
        {
            this.emoticon_window_id.focus();
        }*/
    
},
    
    
togglesource: function( eupdate )
    {
        
Event.stop(e);
        
        
// Already showing?
        
if( this._showing_html )
        {
            if( 
update )
            {
                
this.editor_document.initialized false;
                
this.editor_write_contents( $( this.id '_htmlsource' ).valuetrue );
                
//this.editor_document.body.innerHTML = $( this.id + '_htmlsource' ).value;
            
}
            
            $( 
this.editor_box ).show();
            $( 
this.items['controls'] ).show();
            
            
// Remove source editor
            
$( this.id '_htmlsource' ).remove();
            $( 
this.id '_ts_controls' ).remove();
            
            
// Post process
            //this.togglesource_post_show_html();
            
this._showing_html false;    
            
// Set context
            
this.editor_check_focus();
            
//this.set_context();
        
}
        else
        {
            
this._showing_html true;
            
this.togglesource_pre_show_html();
            
            
// Create a new textarea
            
var textarea = new Element'textarea', { idthis.id '_htmlsource'tabindex} );
            
textarea.className this.items['text_obj'].className;
            var 
dims this.items['text_obj'].getDimensions();
            
            
/*textarea.setStyle('width: ' + dims.width + 'px; height: ' + dims.height + 'px;');*/
            
            
textarea.value this.clean_htmlthis.editor_get_contents() );
            
            
// Build controls
            
var controlbar ipb.editor_values.get('templates')['togglesource'].evaluate( { idthis.id } );
            
            
// Insert into page
            
$( this.items['text_obj'] ).insert( { aftertextarea } );
            $( 
textarea ).insert( { aftercontrolbar } );
            
            
// Hook up events
            
$( this.id '_ts_update' ).writeAttribute('cmd''togglesource').writeAttribute('editor_id'this.id).observe('click'this.togglesource.bindAsEventListenerthis) );
            $( 
this.id '_ts_cancel' ).writeAttribute('cmd''togglesource').writeAttribute('editor_id'this.id).observe('click'this.togglesource.bindAsEventListenerthis) );
            
            
// Hide editor
            
$( this.items['controls'] ).hide();
            $( 
this.editor_box ).hide();
            
            
// Set context
            
this.editor_check_focus();
            
//this.set_context();
        
}    
        
    },
    
    
update_for_form_submit: function()
    {
        
Debug.write("Updating for submit");
        
this.items['text_obj'].value this.editor_get_contents();
        
Debug.write"Before: " this.items['text_obj'].value );
        
// IE does crappy things. </3
        
if ( Prototype.Browser.IE )
        {
            
this.items['text_obj'].value this.items['text_obj'].value.replace( /&nbsp;/g' ' );
            
this.items['text_obj'].value this.items['text_obj'].value.replace( /s+?$/, '' );
        }
        
        
// http://trac.webkit.org/changeset/47640
        // Safari bug with execcommand and underline + strikethrough
        
if( Prototype.Browser.WebKit )
        {
            
this.items['text_obj'].value    this.items['text_obj'].value.replace( /<span class="Apple-style-span" style="text-decoration: underline;">([^>]*)</span>/gi"<u>$1</u>" );
            
this.items['text_obj'].value    this.items['text_obj'].value.replace( /<span class="Apple-style-span" style="text-decoration: line-through;">([^>]*)</span>/gi"<strike>$1</strike>" );
        }
        
Debug.write"After: " this.items['text_obj'].value );
        return 
true;
    }
});


// =============================================================================================================//
// Class for STANDARD EDITOR which is inherited by main Editor class
_editor_std = Class.create({
    
_identifyType: function()
    {
        
Debug.write"(Editor " this.id ") This is the STD class" );
    },
    
editor_set_content: function( init_text )
    {
        var 
iframe this.items['text_obj'].up().down('iframe'0);
        
        if ( !
Object.isUndefinediframe ) )
        {
            var 
iframeDims iframe.getDimensions();
            $( 
this.items['text_obj'] ).setStyle( { 'width'iframeDims.width'height'iframeDims.height } ).show();
            $( 
iframe ).setStyle'width: 0px; height: 0px; border: none;' );
        }

        
this.editor_window   this.items['text_obj'];
        
this.editor_document this.items['text_obj'];
        
this.editor_box      this.items['text_obj'];
        
        if( !
Object.isUndefinedinit_text ) && init_text !== false )
        {
            
this.editor_write_contentsinit_text );
        }

        
this.editor_document.editor_id this.id;
        
this.editor_window.editor_id   this.id;
        
        
// Hide those pesky buttons we dont need
        
if( !Prototype.Browser.IE && $( this.id '_cmd_spellcheck' ) ){
            $( 
this.id '_cmd_spellcheck').hide();
        }
        
        if( $(
this.id '_cmd_removeformat') ){
            $( 
this.id '_cmd_removeformat' ).hide();
        }
        
        if( $(
this.id '_cmd_togglesource' ) ){
            $( 
this.id '_cmd_togglesource' ).hide();
        }
        
        if( $(
this.id '_cmd_justifyfull' ) ){
            $( 
this.id '_cmd_justifyfull' ).hide();
        }
        
        if( $(
this.id '_cmd_outdent' ) ){
            $( 
this.id '_cmd_outdent' ).hide();
        }
        
        if( $(
this.id '_cmd_switcheditor' ) ){
            $( 
this.id '_cmd_switcheditor' ).hide();
        }
    },
    
editor_write_contents: function(text)
    {
        if ( 
text !== false )
        {
            
this.items['text_obj'].value text;
        }
    },
    
editor_get_contents: function()
    {
        return 
this.editor_document.value;
    },
    
apply_formatting: function(cmddialogargument)
    {
        
/*Debug.write("Click");*/
        
switch (cmd)
        {
            case 
'bold':
            case 
'italic':
            case 
'underline':
            {
                
this.wrap_tags(cmd.substr(01), false);
                return;
            }
            case 
'justifyleft':
            case 
'justifycenter':
            case 
'justifyright':
            {
                
this.wrap_tags(cmd.substr(7), false);
                return;
            }
            case 
'indent':
            {
                
this.wrap_tags(cmdfalse);
                return;
            }
            case 
'createlink':
            {
                var 
sel this.get_selection();
                
                if (
sel)
                {
                    
this.wrap_tags('url'argument);
                }
                else
                {
                    
this.wrap_tags('url'argumentargument);
                }
                return;
            }
            case 
'fontname':
            {
                
this.wrap_tags('font'argument);
                return;
            }
            case 
'fontsize':
            {
                
this.wrap_tags('size'argument);
                return;
            }
            case 
'forecolor':
            {
                
this.wrap_tags('color'argument);
                return;
            }            
            case 
'backcolor':
            {
                
this.wrap_tags('background'argument);
                return;
            }
            case 
'insertimage':
            {
                
this.wrap_tags('img'falseargument);
                return;
            }            
            case 
'strikethrough':
            {
                
this.wrap_tags('s'false);
                return;
            }            
            case 
'superscript':
            {
                
this.wrap_tags('sup'false);
                return;
            }            
            case 
'subscript':
            {
                
this.wrap_tags('sub'false);
                return;
            }
            case 
'removeformat':
            return;
        }
    },
    
editor_set_functions: function()
    {
        
Event.observethis.editor_document'keypress'this.events.editor_document_onkeypress.bindAsEventListener(this) );
        
Event.observethis.editor_window'focus'this.events.editor_window_onfocus.bindAsEventListenerthis ) );
        
Event.observethis.editor_window'blur'this.events.editor_window_onblur.bindAsEventListenerthis ) );
    },
    
set_context: function()
    {
        
//Debug.write('Set context');
    
},
    
get_selection: function()
    { 
         if ( !
Object.isUndefinedthis.editor_document.selectionStart ) )
        {
            return 
this.editor_document.value.substr(this.editor_document.selectionStartthis.editor_document.selectionEnd this.editor_document.selectionStart);
        }
        else if ( ( 
document.selection && document.selection.createRange ) || this._ie_cache )
        {
            return ( ! 
document.selection.createRange().text && this._ie_cache ) ? this._ie_cache.text document.selection.createRange().text;
        }
        else if ( 
window.getSelection )
        {
            return 
window.getSelection() + '';
        }
        else
        {
            return 
false;
        }
    },
    
insert_text: function(text)
    {
        
this.editor_check_focus();

        if ( !
Object.isUndefinedthis.editor_document.selectionStart ) )
        {
            var 
open this.editor_document.selectionStart 0;
            var 
st   this.editor_document.scrollTop;
            var 
end  open text.length;
            
            
/* Opera doesn't count the linebreaks properly for some reason */
            
if( Prototype.Browser.Opera )
            {
                var 
opera_len text.match( /n/);

                try
                {
                    
end += parseInt(opera_len.length);
                }
                catch(
e)
                {
                    
Debug.write"#3 " );
                }
            }
            
            
this.editor_document.value this.editor_document.value.substr(0this.editor_document.selectionStart) + text this.editor_document.value.substr(this.editor_document.selectionEnd);

            
// Don't adjust selection if we're simply adding <b></b>, etc
            
if ( ! text.match( new RegExp"\" + this.open_brace + "(\S+?)" + "\" + this.close_brace + "\" + this.open_brace + "/(\S+?)" + "\" + this.close_brace ) ) )
            {
                this.editor_document.selectionStart = open;
                this.editor_document.selectionEnd   = end;
                this.editor_document.scrollTop      = st;
                Debug.write("
Insert 0");
            }
            else
            { 
                // Only firefox seems to need this...
                if( Prototype.Browser.Gecko ){
                    this.editor_document.scrollTop      = st;
                }
            }
            
            this.editor_document.setSelectionRange( open, end );
            Debug.write("
Insert 1");
        }
        else if ( ( document.selection && document.selection.createRange ) || this._ie_cache )
        {
            var sel  = this._ie_cache ? this._ie_cache : document.selection.createRange();
            sel.text = text.replace(/r?n/g, 'rn');
            sel.select();
            Debug.write("
Insert 2");
        }
        else
        {
            this.editor_document.value += text;
            Debug.write("
Insert 3");
        }
        
        this._ie_cache = null;
    },
    insert_emoticon: function( emo_id, emo_image, emo_code, event )
    {
        this.editor_check_focus();
        
        emo_code = this.unhtmlspecialchars( emo_code );
        
        this.wrap_tags_lite( " " + emo_code, " ");        
        
        /*if ( Prototype.Browser.IE )
        {
            if ( this.emoticon_window_id != '' && !Object.isUndefined( this.emoticon_window_id ) )
            {
                this.emoticon_window_id.focus();
            }
        }*/
    },
    insertorderedlist: function(e)
    {
        this.insertlist( 'ol');
    },
    insertunorderedlist: function(e)
    {
        this.insertlist( 'ul');
    },
    insertlist: function( list_type )
    {
        var open_tag;
        var close_tag;
        var item_open_tag  = '<li>';
        var item_close_tag = '</li>';
        var regex          = '';
        var all_add        = '';
        
        if ( this.use_bbcode )
        {
            regex          = new RegExp('([rn]+|^[rn]*)(?!\[\*\]|\[\/?list)(?=[^rn])', 'gi');
            open_tag       = list_type == 'ol' ? '[list=1]n' : '[list]n';
            close_tag      = '[/list]';
            item_open_tag  = '[*]';
            item_close_tag = '';
        }
        else
        {
            regex     = new RegExp('([rn]+|^[rn]*)(?!<li>|<\/?ol|ul)(?=[^rn])', 'gi');
            open_tag  = list_type == 'ol'  ? '<ol>n'  : '<ul>n';
            close_tag = list_type == 'ol'  ? '</ol>n' : '</ul>n';
        }
        
        if ( text = this.get_selection() )
        {
            text = open_tag + text.replace( regex, "
n" + item_open_tag + '$1' + item_close_tag ) + 'n' + close_tag;
            
            if ( this.use_bbcode )
            {
                text = text.replace( new RegExp( '\[\*\][rn]+', 'gi' ), item_open_tag );
            }
            
            this.insert_text( text );
        }
        else
        {
            // http://community.invisionpower.com/tracker/issue-19347-insert-list/
            // Commenting this out fixes the above bug report
            
            //if ( Prototype.Browser.Gecko )
            //{
            //    //this.insert_text( open_tag + close_tag );
            //    this.insert_text( open_tag  );
            //    
            //    /* SKINNOTE: use proper lang for these */
            //    while ( val = prompt( ipb.lang['editor_enter_list'], '') )
            //    {
            //        this.insert_text( item_open_tag + val + item_close_tag + 'n' );
            //        //all_add += item_open_tag + val + item_close_tag + 'n';
            //    }
            //    this.insert_text( close_tag );
            //}
            //else
            //{
                var to_insert    = open_tag;
                var listitems    = '';

                while ( val = prompt( ipb.lang['editor_enter_list'], '') )
                {
                    listitems += item_open_tag + val + item_close_tag + 'n';
                }

                //this.insert_text( close_tag );
                
                if( listitems )
                {
                    to_insert    += listitems;
                    to_insert    += close_tag;
                    this.insert_text( to_insert );
                }
            //}
        }
    },
    removeformat: function()
    {
        var text = this.get_selection();
        
        if ( text )
        {
            text = this.strip_html( text );
            this.insert_text( text );
        }
    },
    unlink: function()
    {
        var text       = this.get_selection();
        var link_regex = '';
        var link_text  = '';
        
        if ( text !== false )
        {
            if ( text.match( link_regex ) )
            { 
                text = ( this.use_bbcode ) ? text.replace( /[url=([^]]+?)]([^[]+?)[/url]/ig, "
$2" )
                                           : text.replace( /<a href=['"
]([^"']+?)['"]([^>]+?)?>(.+?)</a>/ig, "$3" );
            }
            this.insert_text( text );
        }
    },
    undo: function()
    {
        this.history_record_state( this.editor_get_contents() );
        
        this.history_time_shift( -1 );
        
        if ( ( text = this.history_fetch_recording() ) !== false )
        {
            this.editor_document.value = text;
        }
    },
    redo: function()
    {
        this.history_time_shift( 1 );
        
        if ( ( text = this.history_fetch_recording() ) !== false )
        {
            this.editor_document.value = text;
        }
    },
    update_for_form_submit: function(subjecttext, minchars)
    {
        return true;
    }    
});


//==============================================================================================================//
// MAIN EDITOR CODE

if( USE_RTE ){//&& !Prototype.Browser.WebKit ){ // Dont support safari
    Debug.write("Extending with RTE");
    _type = _editor_rte;
} else {
    Debug.write("Extending with STD");
    _type = _editor_std;
}

_editor.prototype.editor = Class.create(_type, {

    initialize: function( editor_id, mode, initial_content, options )
    {
        this.id                 = editor_id; 
        this.is_rte             = mode;      
        this.use_bbcode         = !mode;
        this.events             = null;
        this.options            = [];        
        this.items                = [];        
        this.settings            = {};        
        this.open_brace         = '';        
        this.close_brace        = '';        
        this.allow_advanced     = 0;
        this.initialized         = 0;
        this.ips_frame_html        = '';
        this.forum_fix_ie_newlines    = 1;
        this.has_focus            = null;
        this.history_recordings    = [];
        this.history_pointer    = -1;
        this._ie_cache            = null;
        this._showing_html        = false;
        this._loading            = false;
        this.original            = $H();
        this.hidden_objects        = [];
        this.fontoptions        = $A();
        this.sizeoptions        = $A();
        this.font_state            = null;
        this.size_state            = null;
        this.palettes            = {};
        this.defaults            = {};
        this.key_handlers        = [];
        this.showing_sidebar    = false;
        this.emoticons_loaded    = false;
        this.emoClick            = false;
        
        this.options = Object.extend({
            file_path:                     '',
            forum_fix_ie_newlines:         1,
            char_set:                     'UTF-8',
            ignore_controls:             [],
            button_update:                 []
        }, arguments[3] || {});
        
        this.button_update = $A( [ "bold", "italic", "underline", "justifyleft", "justifycenter",
                                "justifyright",    "insertorderedlist", "insertunorderedlist", "superscript", "subscript", "strikethrough" ].concat( this.options.button_update ) );
        
        this.values = ipb.editor_values; // The values for things like font list, colors etc.
        
        this.items['text_obj'] = $( this.id + "_textarea" );
        this.items['buttons'] = $A();
        this.items['controls'] = $( this.id + '_controls' );
        
        //Other configuration
        this.open_brace            = this.use_bbcode ? '[' : '<';
        this.close_brace           = this.use_bbcode ? ']' : '>';
        this.allow_advanced        = this.use_bbcode ?  0  :  1;
        this.doc_body               = $$('body')[0];
        
        //Object.extend( this._history, _editor_history );
        this.events = new _editor_events();                
        this._identifyType();
        
        // Any custom BBCodes to build?
        if( this.values.get('bbcodes') && $( this.id + '_cmd_otherstyles' ) ) // check for existence of other styles menu
        {
            this.buildCustomStyles();
        }
        
        // Lets try and find the form this belongs to, and add a submit
        // event to convert the text properly
        if( this.items['text_obj'].up('form') ){
            this.items['text_obj'].up('form').observe( 'submit', function(e){
                this.update_for_form_submit();
            }.bindAsEventListener(this) );
        }
        
        this.init( initial_content );
        
        Debug.write("All editor initialization complete");
    },

    /* ------------------------------ */
    /**
     * Initialization
    */
    init: function( initial_text )
    {
        try {
            if ( this.initialized ){
                return;
            }
        
            // Set WYSIWYG flag
            if( $( this.id + '_wysiwyg_used' ) ){
                $( this.id + '_wysiwyg_used' ).value = parseInt( this.is_rte );
            }

            if( ipb.Cookie.get('emoticon_sidebar') == '1' && $( this.id + '_sidebar' ) )
            {
                this.buildEmoticons();
                $( this.id + '_sidebar' ).show();
                $( 'editor_' + this.id ).addClassName('with_sidebar');
                ipb.Cookie.set( 'emoticon_sidebar', 1, 1 );
                this.showing_sidebar = true;
            }
            
            // Get default frame HTML
            this.ips_frame_html = this.get_frame_html();
            
            // Set editor up
            this.editor_set_content( initial_text );
                    
            // Set mouse events
            this.editor_set_functions();
            // Set controls up
            this.editor_set_controls();            
            
            // Having this here forces the page to jump down to the editor when it loads
            // which is highly undesirable.  Tested STD and RTE in FF and IE8, and Safari with STd
            // with this commented out and seems fine... Bug 15476
            //this.editor_check_focus();
        
            this.initialized = true;
        }
        catch(err){ Debug.error( "#4 " + err ); }
    },
    
    /* ------------------------------ */
    /**
     * Builds custom styles menu & toolbars
     */
    buildCustomStyles: function()
    {
        var buttons = false;
        var other_styles = false;
        
        // Create the toolbar to start with
        var toolbar = ipb.editor_values.get('templates')['toolbar'].evaluate( { 'id': this.id, 'toolbarid': '3' } );
        $( this.id + '_toolbar_2' ).insert( { after: toolbar } );
        
        // And init the other styles menu
        this.init_editor_menu( $( this.id + '_cmd_otherstyles' ) );
        
        this.values.get('bbcodes').each( function( bbcode ){
            
            if( !bbcode.value['image'].blank() )
            {
                $( this.id + '_toolbar_3' ).insert( ipb.editor_values.get('templates')['button'].evaluate( { 'id': this.id, 'cmd': bbcode.key, 'title': bbcode.value['title'], 'img': bbcode.value['image'] } ) );
                buttons = true;
            }
            else
            {
                $( this.id + '_popup_otherstyles_menu' ).insert( ipb.editor_values.get('templates')['menu_item'].evaluate( { 'id': this.id, 'cmd': bbcode.key, 'title': bbcode.value['title'] } ) );
                other_styles = true;
            }
            
            if( !( bbcode.value['useoption'] == '0' && bbcode.value['single_tag'] == '1' ) )
            {
                var item_wrap = new Element('div', { id: this.id + '_palette_otherstyles_' + bbcode.key } );
                item_wrap.addClassName('ipb_palette').addClassName('extended');
                item_wrap.writeAttribute("styleid", bbcode.key);

                var _content = this.values.get('templates')['generic'].evaluate( {
                    id: this.id + '_' + bbcode.key,
                    title: bbcode.value['title'],
                    example: bbcode.value['example'],
                    option_text: bbcode.value['menu_option_text'] || '',
                    value_text: bbcode.value['menu_content_text'] || ''
                } );

                item_wrap.update( _content );
                this.doc_body.insert( { top: item_wrap } );

                // Figure out what needs to be shown
                if( bbcode.value['useoption'] == '0' ){
                    item_wrap.select('.optional').invoke('remove');
                }
                
                if( bbcode.value['single_tag'] == '1' ){
                    item_wrap.select('.tagcontent').invoke('remove');
                }
                
                this.palettes[ 'otherstyles_' + bbcode.key ] = new ipb.Menu( $( this.id + '_cmd_custom_' + bbcode.key ), item_wrap, { stopClose: true, offsetX: 0, offsetY: 42, positionSource: $( this.id + '_cmd_otherstyles' ) } );
                item_wrap.down('input[type="submit"]').observe('click', this.events.handle_custom_onclick.bindAsEventListener( this ) );
            }
            
            // Set up events
            $( this.id + '_cmd_custom_' + bbcode.key ).observe('click', this.events.handle_custom_command.bindAsEventListener( this, bbcode.key ));
        
        }.bind(this));
        
        if( buttons ){
            $( this.id + '_toolbar_3' ).show();
        }
        
        if( other_styles ){
            $( this.id + '_cmd_otherstyles' ).show();
        }
        
    },

    /* ------------------------------ */
    /**
     * Resizes the content area
    */
    resize_to: function( size )
    {
        var afterFinish = function(){};
        
        // Bug #17799
        // Opera 10 wouldn't resize the emoticon pane when the editor resize buttons were used
        // Have to manually recalculate height, resize editor, then remove height
        if( Prototype.Browser.Opera && $( this.id + '_emoticon_holder' ) )
        {    
            var height = $( this.id + '_emoticon_holder' ).getHeight();
            var currentSize = ( this.is_rte ) ? $( this.editor_box ).getHeight() : $( this.items['text_obj'] ).getHeight();
            var diff = currentSize - size;
            var newSize = height - diff;
            
            $( this.id + '_emoticon_holder' ).setStyle('height: ' + newSize + 'px');
            
            var afterFinish = function(e){
                $( this.id + '_emoticon_holder' ).setStyle('height: auto;');
            }.bind( this );
                        
            //window.opera.postError("Height: " + height + "; diff: " + diff + "; newSize: " + newSize);
        }
            
        try {
            if( this.is_rte )
            {
                new Effect.Morph( $( this.editor_box ), { style: 'height: ' + size + 'px', duration: 0.3, afterFinish: afterFinish } );
                $( this.items['text_obj'] ).setStyle( 'height: ' + size + 'px' );
            }
            else
            {
                new Effect.Morph( $( this.items['text_obj'] ), { style: 'height: ' + size + 'px', duration: 0.3, afterFinish: afterFinish } );
                if( $( this.editor_box ) ){ $( this.editor_box ).setStyle( 'height: ' + size + 'px' ); }
            }
            
        } catch(err) { Debug.write( "#5 " + err ); }        
    },
    
    /* ------------------------------ */
    /**
     * Returns HTML for the RTE frame
    */
    get_frame_html: function()
    {
        var ips_frame_html = "";
        ips_frame_html += "<html id=""+this.id+"_html">n";
        ips_frame_html += "<head>n";
        ips_frame_html += "<meta http-equiv="content-type" content="text/html; charset=" + this.options.char_set + "" />";
        ips_frame_html += "<style type='text/css' media='all'>n";
        ips_frame_html += "body {n";
        ips_frame_html += "    background: #FFFFFF;n";
        ips_frame_html += "    margin: 0px;n";
        ips_frame_html += "    padding: 4px;n";
        ips_frame_html += "    font-family: arial, verdana, tahoma, sans-serif;n";
        ips_frame_html += "    font-size: 9pt;n";
        ips_frame_html += "}n";
        ips_frame_html += "font[size="1"] {n";
        ips_frame_html += "    font-size: 9px;n";
        ips_frame_html += "}n";
        ips_frame_html += "font[size="2"] {n";
        ips_frame_html += "    font-size: 13px;n";
        ips_frame_html += "}n";
        ips_frame_html += "font[size="3"] {n";
        ips_frame_html += "    font-size: 15px;n";
        ips_frame_html += "}n";
        ips_frame_html += "font[size="4"] {n";
        ips_frame_html += "    font-size: 17px;n";
        ips_frame_html += "}n";
        ips_frame_html += "font[size="5"] {n";
        ips_frame_html += "    font-size: 21px;n";
        ips_frame_html += "}n";
        ips_frame_html += "font[size="6"] {n";
        ips_frame_html += "    font-size: 26px;n";
        ips_frame_html += "}n";
        ips_frame_html += "font[size="7"] {n";
        ips_frame_html += "    font-size: 36px;n";
        ips_frame_html += "}n";
        ips_frame_html += "</style>n";
        
        if( isRTL && rtlFull )
        {
            ips_frame_html += "<link rel='stylesheet' type='text/css' media='screen' href='" + rtlFull + "' />n";
            
            if( rtlIe && Prototype.Browser.IE )
            {
                ips_frame_html += "<!--[if lte IE 7]>n";
                ips_frame_html += "<link rel='stylesheet' type='text/css' media='screen' href='" + rtlIe + "' />n";
                ips_frame_html += "<![endif]-->n";
            }
        }
        ips_frame_html += "</head>n";
        ips_frame_html += "<body class='withRTL'>n";
        ips_frame_html += "{:content:}n";
        ips_frame_html += "</body>n";
        ips_frame_html += "</html>";

        return ips_frame_html;
    },
    editor_check_focus: function()
    {
        if( this.is_rte )
        {
            Debug.write( "Focussing RTE" );
            
            try {
                this.editor_window.focus();
            } catch(err) { Debug.write( "Could not focus editor window" ); }
        }
        else
        {
            Debug.write( "Focussing STD Textarea" );
            
            if( !this._ie_cache )
            {
                this.items['text_obj'].focus();
            }
        }
        /*if ( ! this.editor_window.has_focus ){
            this.editor_window.focus();
        }*/
    },
    editor_set_controls: function()
    {
        //Debug.write( $( this.id + '_controls' ).select('span') );
        controls = $( this.id + '_controls' ).select('.rte_control').each( function(elem)
        {
            if( !elem.id ){ return; }
            if( this.options.ignore_controls.include( elem.id.toLowerCase() ) ){ return; }
            
            if( elem.hasClassName('rte_button') ){
                this.init_editor_button( elem );
            } else if ( elem.hasClassName( 'rte_menu' ) && !elem.hasClassName( 'rte_special') ){
                this.init_editor_menu( elem ); // SKINNOTE: IE error on this line
            } else if ( elem.hasClassName( 'rte_palette' ) ){
                this.init_editor_palette( elem );
            } else {
                return;
            }
            this.set_control_unselectable( elem );
        }.bind(this));
        
        if( $( this.id + '_resizer' ) ){
            this.init_editor_button( $( this.id + '_cmd_r_small' ) );
            this.set_control_unselectable( $( this.id + '_cmd_r_small' ) );
            this.init_editor_button( $( this.id + '_cmd_r_big' ) );
            this.set_control_unselectable( $( this.id + '_cmd_r_big' ) );
        }
            
    },
    set_button_context: function(obj, state, type)
    {
        //-----------------------------------------
        // Showing HTML?
        //-----------------------------------------
        if ( this._showing_html ){
            return false;
        }
        
        if ( Object.isUndefined( type ) ){
            type = 'button';
        }
        
        if ( state == 'mousedown' && ( obj.readAttribute('cmd') == 'undo' || obj.readAttribute('cmd') == 'redo' ) ){
            return false;
        }
        
        switch ( obj.readAttribute('state') )
        {
            case 'true':
            {
                switch (state)
                {
                    case 'mouseout':
                        this.editor_set_ctl_style(obj, 'button', 'selected');
                        break;
                    case 'mouseover':
                    case 'mousedown':
                    case 'mouseup':
                        this.editor_set_ctl_style(obj, type, 'down');
                        break;
                }
                break;
            }
            default:
            {
                switch (state)
                {
                    case 'mouseout':
                        this.editor_set_ctl_style(obj, type, 'normal');
                        break;
                    case 'mousedown':
                        this.editor_set_ctl_style(obj, type, 'down');
                        break;
                    case 'mouseover':
                    case 'mouseup':
                        this.editor_set_ctl_style(obj, type, 'hover');
                        break;
                }
                break;
            }
        }
    },
    editor_set_ctl_style: function( obj, type, mode )
    {
        if ( obj.readAttribute('mode') == mode ){ return; }
    
        // Add in -menu class
        var extra = '';
        
        if ( type == 'menu' ){
            extra = '_menu';
        } else if ( type == 'menubutton' ) {
            extra = '_menubutton';
        }
        
        // Add in -color if it's a color box
        extra     += obj.readAttribute('colorname') ? '_color' : '';
        
        // Add in -emo if it's an emo        
        extra     += obj.readAttribute('emo_id') ? '_emo' : '';
        
        // Set mode...
        obj.writeAttribute('mode', mode);
        
        try
        {
            switch ( mode )
            {
                case "normal":
                    obj.addClassName('rte_normal' + extra).removeClassName('rte_hover').removeClassName('rte_selected');
                    break;
                case "hover":
                    obj.addClassName('rte_hover' + extra ).removeClassName('rte_normal').removeClassName('rte_selected');
                    break;
                case "selected":
                case "down":
                    obj.addClassName('rte_selected' + extra ).removeClassName('rte_normal').removeClassName('rte_hover');
                    break;
            }
        }
        catch (err)
        {
            Debug.write( "#6 " + err );
        }
    },
    set_control_unselectable: function(elem)
    {
        if( !$(elem) ){ return; }
        $( elem ).descendants().each( function(dec){
            dec.writeAttribute( 'unselectable', 'on' );
        });
        
        $(elem).writeAttribute( 'unselectable', 'on' );
    },
    init_editor_button: function( elem )
    {
        // What command are we running?
        elem.writeAttribute( 'cmd',         elem.id.replace( this.id + '_cmd_', '' ) );
        elem.writeAttribute( 'editor_id',    this.id );

        // Add to buttons array
        this.items['buttons'][ elem.readAttribute('cmd') ] = elem;

        // Set up defaults
        elem.writeAttribute('state',        false);
        elem.writeAttribute('mode',            'normal');
        elem.writeAttribute('real_type',    'button');
        
        elem.observe( 'click',            this.events.button_onmouse_event.bindAsEventListener( this ) );
        elem.observe( 'mousedown',        this.events.button_onmouse_event.bindAsEventListener( this ) );
        elem.observe( 'mouseover',        this.events.button_onmouse_event.bindAsEventListener( this ) );
        elem.observe( 'mouseout',        this.events.button_onmouse_event.bindAsEventListener( this ) );
    },
    
    /* ------------------------------ */
    /**
     * Builds a simple menu
     * 
     * @var        {element}    elem    The relevant element
    */
    init_editor_menu: function( elem )
    {        
        // Build the details
        elem.writeAttribute( 'cmd',         elem.id.replace( this.id + '_cmd_', '' ) );
        elem.writeAttribute( 'editor_id',     this.id );
        
        this.items['buttons'][ elem.readAttribute('cmd') ] = elem;
        
        // Build wrapper
        var wrap = new Element('ul', { id: this.id + '_popup_' + elem.readAttribute('cmd') + '_menu' } );
        wrap.writeAttribute( 'cmd', elem.readAttribute('cmd' ) ).addClassName('ipbmenu_content');
        wrap.hide();
        
        if( elem.hasClassName('rte_font') )
        {
            this.fontoptions[ '_default' ] = elem.innerHTML;
            
            ipb.editor_values.get('primary_fonts').each( function(font){
                var item = new Element( 'li', { 'id': this.id + '_fontoption_' + font.key } );
                item.setStyle( 'font-family: "' + font.value + '"; cursor: pointer' ).addClassName('fontitem');
                item.update( font.value );
                $( item ).observe( 'click', this.events.font_format_option_onclick.bindAsEventListener( this ) );
                wrap.insert( item );
                
                this.fontoptions[ font.key ] = item;
            }.bind(this));
            
            elem.insert( { after: wrap } );
        }
        else if( elem.hasClassName('rte_fontsize') )
        {
            this.sizeoptions[ '_default' ] = elem.innerHTML;
            
            ipb.editor_values.get('font_sizes').each( function( size ){
                var item = new Element( 'li', { id: this.id + '_sizeoption_' + size } );
                item.setStyle( 'font-size: ' + this.convert_size( size, 1 ) + 'px; cursor: pointer' ).addClassName('fontitem');
                item.update( size );
                $( item ).observe( 'click', this.events.font_format_option_onclick.bindAsEventListener( this ) );
                wrap.insert( item );
                wrap.addClassName("fontsizes");
                
                this.sizeoptions.push( size );
            }.bind(this));
            
            elem.insert( { after: wrap } );
        }
        else if( elem.hasClassName('rte_special') )
        {
            /*ipb.editor_values.get('other_styles').each( function(style){
                var item = new Element( 'li', { id: this.id + '_otherstyle_' + style.key } ).setStyle('cursor: pointer;').addClassName('specialitem');
                item.update( style.value[0] );
                //$( item ).observe( 'click', this.events.other_styles_onclick.bindAsEventListener( this ) );
                wrap.insert( item );
                
                // Set up palette
                var item_wrap = new Element('div', {id: this.id + '_palette_other_' + style.key } );
                item_wrap.hide().addClassName('ipb_palette').addClassName('extended');
                item_wrap.writeAttribute("styleid", style.key);
                
                var _content = ipb.editor_values.get('templates')['generic'].evaluate( {
                    id: this.id + '_' + style.key,
                    title: style.value[0],
                    example: style.value[3],
                    option_text: style.value[5] || '',
                    value_text: style.value[4] || ''
                } );
                
                item_wrap.update( _content );
                item_wrap.down('input[type="submit"]').observe('click', this.events.other_styles_onclick.bindAsEventListener( this ) );
                
                $( this.id + '_controls').insert( { bottom: item_wrap } );
                
                if( !style.value[2] )
                {
                    item_wrap.select('.optional').invoke('remove');
                }
                
                this.palettes[ 'otherstyles_' + style.key ] = new ipb.Menu( $( item ), item_wrap, { stopClose: true, offsetX: 50, offsetY: 50 } );
                $( item ).observe('click', this.events.other_styles_preshow_onclick.bindAsEventListener( this, style.key ) );
            }.bind(this));
            */
            
            elem.insert( { after: wrap } );
        }

        // Init function for IE
        var beforeOpen = function( menu ){
            this.editor_check_focus();
            this.preserve_ie_range();
            Debug.write("Preserved IE Range");
        }.bind(this);
        
        // Create new menu
        new ipb.Menu( $( elem ), wrap, {}, { beforeOpen: beforeOpen } );                 
    },
    
    /* ------------------------------ */
    /**
     * Builds a palette
     * 
     * @var        {element}    elem    The relevant element
    */
    init_editor_palette: function( elem )
    {
        elem.writeAttribute( 'cmd',         elem.id.replace( this.id + '_cmd_', '' ) );
        elem.writeAttribute( 'editor_id',     this.id );
        
        this.items['buttons'][ elem.readAttribute('cmd') ] = elem;
        
        wrap = new Element('div', { id: this.id + '_palette_' + elem.readAttribute('cmd') } );
        wrap.writeAttribute( 'cmd', elem.readAttribute('cmd') ).addClassName('ipb_palette');
        wrap.hide();
        opt = {};
        var handleReturn = false;
        
        switch( elem.readAttribute('cmd') )
        {
            case 'forecolor':
            case 'backcolor':
                var table = new Element('table', { id: this.id + '_' + elem.readAttribute('cmd') + '_palette' }).addClassName('rte_colors');
                
                // At this point IE would quite like you to have a tbody too
                var tbody = new Element('tbody');
                table.insert( tbody );
                
                var tr = null;
                var td = null;
                var color = '';
                
                for( i=0; i < ipb.editor_values.get('colors').length; i++ )
                {
                    color = ipb.editor_values.get('colors')[i];
                    
                    if( i % ipb.editor_values.get('colors_perrow') == 0 ){
                        tr = new Element('tr');
                        tbody.insert( tr );
                    }
                    
                    td = new Element('td', { id: this.id + '_' + elem.readAttribute('cmd') + '_color_' + color } );
                    td.setStyle('background-color: #' + color).setStyle('background-image: none').writeAttribute('colorname', color);
                    
                    tr.insert( td );
                    
                    // Events
                    $( td ).observe('click', this.events.color_cell_onclick.bindAsEventListener( this ) );
                }
                
                wrap.insert( table ).addClassName('color_palette');
                elem.insert( { after: wrap } );
            break;
            /*case 'emoticons':
                if( Object.isUndefined( ipb.editor_values.get('emoticons') ) )
                {
                    elem.hide();
                    return;
                }
                
                /*var table = new Element( 'ul', { id: this.id + '_emoticons_palette' } ).addClassName('rte_emoticons');
                var perrow = 10;
                var row = null;
                var i = 0;
                
                ipb.editor_values.get('emoticons').each( function(emote){
                        
                    var _tmp = emote.value.split(',');
                    var img = new Element('img', { id: 'smid_' + _tmp[0], src: ipb.vars['emoticon_url'] + '/' + _tmp[1] } );
                    var li = new Element('li', { id: this.id + '_emoticons_emote_' + _tmp[0] } ).setStyle('').addClassName('emote');
                    
                    li.writeAttribute('emo_id', _tmp[0] );
                    li.writeAttribute('emo_img', _tmp[1] );
                    li.writeAttribute('emo_code', emote.key);
                    
                    table.insert( li.insert( img ) );
                    $( li ).observe('click', this.events.emoticon_onclick.bindAsEventListener( this ) );
                    
                
                }.bind(this));
                
                //-------------
                var table = new Element( 'table', { id: this.id + '_emoticons_palette' } ).addClassName('rte_emoticons');
                
                // Same as before, tbody please, says IE
                var tbody = new Element('tbody');
                table.insert( tbody );
                
                var tr = null;
                var td = null;
                
                var perrow = 10;
                var i = 0;
                
                //Debug.write( ipb.editor_values.get('emoticons') );
                ipb.editor_values.get('emoticons').each( function(emote){
                    
                    if( i % perrow == 0 )
                    {
                        tr = new Element( 'tr' );
                        tbody.insert( tr );
                    }
                    
                    i++;
                    
                    var _tmp = emote.value.split(',');
                    var img = new Element('img', { id: 'smid_' + _tmp[0], src: ipb.vars['emoticon_url'] + '/' + _tmp[1] } );
                    
                    td = new Element('td', { id: this.id + '_emoticons_emote_' + _tmp[0] } ).setStyle('cursor: pointer; text-align: center').addClassName('emote');
                    td.writeAttribute('emo_id', _tmp[0] );
                    td.writeAttribute('emo_img', _tmp[1] );
                    td.writeAttribute('emo_code', emote.key);
                    
                    td.insert( img );
                    tr.insert( td );
                    $( td ).observe('click', this.events.emoticon_onclick.bindAsEventListener( this ) );
                }.bind(this));
                        
                
                // IE sucks
                if( Prototype.Browser.IE )
                {
                    var tmpdiv = new Element( 'div' ).setStyle('overflow-x: scroll');
                    wrap.insert( tmpdiv.insert( table ) ).addClassName('emoticons_palette');
                    elem.insert( { after: wrap } );
                }
                else
                {
                    wrap.insert( table ).addClassName('emoticons_palette');
                    elem.insert( { after: wrap } );
                }
                
                if( this.values.get('show_emoticon_link') )
                {
                    var emote_link = this.values.get('templates')['emoticons_showall'].evaluate( { id: this.id } );
                    wrap.insert( { bottom: emote_link } );
                    
                    $( this.id + '_all_emoticons' ).observe( 'click', this.events.show_emoticon_sidebar.bindAsEventListener( this ) );
                }            
                
            break;*/
            case 'link':
            case 'image':
            case 'email':
            case 'media':
                if( Object.isUndefined( ipb.editor_values.get('templates')[ elem.readAttribute('cmd') ] ) )
                {
                    elem.hide();
                    return;
                }
                try {
                    wrap.update( ipb.editor_values.get('templates')[ elem.readAttribute('cmd') ].evaluate( { id: this.id } ) );
                    wrap.down('input[type="submit"]').observe('click', this.events.palette_submit.bindAsEventListener( this ) );
                } catch( err ) { Debug.write("#7 " + err); }
                    
                this.doc_body.insert( { top: wrap } );
                
                if( elem.readAttribute('cmd') == 'link' )
                {
                    try {
                        this.defaults['link_text'] = $F( this.id + '_urltext' );
                        this.defaults['link_url'] = $F( this.id + '_url' );
                    } catch( err ){ Debug.write( "#8 " + err ); }
                    $( elem ).observe('click', this.events.link_onclick.bindAsEventListener( this ) );
                }
                
                if( elem.readAttribute('cmd') == 'image' )
                {
                    try {
                        this.defaults['img'] = $F( this.id + '_img' );
                    } catch( err ){ Debug.write( "#15 " + err ); }
                    $( elem ).observe('click', this.events.image_onclick.bindAsEventListener( this ) );
                }
                
                if( elem.readAttribute('cmd') == 'email' )
                {
                    try {
                        this.defaults['email_text'] = $F( this.id + '_emailtext' );
                        this.defaults['email'] = $F( this.id + '_email' );
                    } catch( err ){ Debug.write( "#8 " + err ); }
                    $( elem ).observe('click', this.events.email_onclick.bindAsEventListener( this ) );
                }
                
                if( elem.readAttribute('cmd') == 'media' )
                {
                    try {
                        this.defaults['media'] = $F( this.id + '_media' );
                    } catch( err ){ Debug.write( "#17 " + err ); }
                    $( elem ).observe('click', this.events.media_onclick.bindAsEventListener( this ) );
                }
                
                this.key_handlers[ elem.readAttribute('cmd') ] = false;
            break;
            default:
                this.items['buttons'][ elem.readAttribute( 'cmd' ) ] = null;
                elem.hide(); // Hide since we dont know what to do with it
                wrap.remove();
            break;
        }
        
        // Insert title
        if( elem.readAttribute('title' ) )
        {
            title = new Element( 'div' );
            title.update( elem.readAttribute('title') ).addClassName('rte_title');
            wrap.insert( { top: title } );
        }
        
        if( !elem.readAttribute('cmd').endsWith('color') ){
            opt = { stopClose: true };
        }
         
        $( elem ).observe('mouseover', this.events.palette_button_onmouseover.bindAsEventListener( this ) );
        $( elem ).observe('mouseover', this.events.palette_onmouse_event.bindAsEventListener( this ) );
        $( elem ).observe('mouseout',  this.events.palette_onmouse_event.bindAsEventListener( this ) );
    
        // Init function for IE
        var beforeOpen = function( menu ){
            this.editor_check_focus();
            this.preserve_ie_range();
            Debug.write("Preserved IE Range");
        }.bind(this);

        
        //this.doc_body.insert( wrap.setStyle('position: absolute; top:0px; left:0px;') );
        this.palettes[ elem.readAttribute('cmd') ] = new ipb.Menu( $( elem ), wrap, opt, { beforeOpen: beforeOpen } );
    },
    
    convert_size: function( size, type )
    {            
        if( type == 1 )
        {
            switch( size )
            {
                case 1:
                    return 9;
                    break;
                case 2:
                    return 13;
                    break;
                case 3:
                    return 15;
                    break;
                case 4:
                    return 17;
                    break;
                case 5:
                    return 21;
                    break;
                case 6:
                    return 26;
                    break;
                case 7:
                    return 36;
                    break;
                default:
                    return 13;
            }
        } else {
            switch( size )
            {
                case '7.5pt':
                case '9px': return 1;
                case '13px': return 2;
                case '15px': return 3;
                case '17px': return 4;
                case '21px': return 5;
                case '26px': return 6;
                case '36px': return 7;
                default:     return '';
            }
        }
    },
    
    format_text: function( e, command, arg )
    {        
        
        // Check for special commands
        if( command.startsWith( 'resize_' ) ){
            //
        }
        
        if( command == 'switcheditor' ){
            try {
                ipb.switchEditor( this.id );
            } catch(err) {
                Debug.error( "#9 " + err );
            }
        }
        
        // Recording state?
        if ( ! this.is_rte && command != 'redo' ){
            this.history_record_state( this.editor_get_contents() );
        }
        
        this.editor_check_focus();
        
        // Execute command
        if ( this[ command ] )
        {
            var return_val = this[ command ](e);
        }
        else
        {
            try
            {
                /*Debug.write( "In format text, selection is: " + this.get_selection() );*/
                var return_val = this.apply_formatting( command, false, (typeof arg == 'undefined' ? true : arg) );
            }
            catch(e)
            {
                Debug.warn( "#10 " + e );
                var return_val = false;
            }
        }
        
        // Recording state
        if ( ! this.is_rte && command != 'undo' ){
            this.history_record_state( this.editor_get_contents() );
        }
        
        // Set context
        this.set_context(command);
        
        // Check focus        
        this.editor_check_focus();

        return return_val;
    },
    
    spellcheck: function()
    {
        // Only IE can use this
        if( !Prototype.Browser.IE ){ return; }
        
        try    {
            if ( this.rte_mode ){
                var tmpis = new ActiveXObject("ieSpell.ieSpellExtension").CheckDocumentNode( this.editor_document );
            } else {
                var tmpis = new ActiveXObject("ieSpell.ieSpellExtension").CheckAllLinkedDocuments( this.editor_document );
            }
        } catch( exception ) {
            if ( exception.number == -2146827859 ) {
                if ( confirm( ipb.lang['js_rte_erroriespell'] ? ipb.lang['js_rte_erroriespell'] : "ieSpell необнаружен. Нажмите Ок для сохранения страницы." ) )
                {
                    window.open("http://www.iespell.com/download.php", "Download");
                }
            }
            else
            {
                alert( ipb.lang['js_rte_errorloadingiespell'] ? ipb.lang['js_rte_errorloadingiespell'] : "Ошибка загрузки ieSpell: номер ошибки " + exception.number);
            }
        }
        
    },
    
    wrap_tags: function(tag_name, has_option, selected_text)
    {
        //-----------------------------------------
        // Fix up for HTML use
        //-----------------------------------------
        
        var tag_close = tag_name;
        
        if ( ! this.use_bbcode )
        {
            switch( tag_name )
            {
                case 'url':
                    tag_name  = 'a href';
                    tag_close = 'a';
                    break;
                 case'email':
                    tag_name   = 'a href';
                    tag_close  = 'a';
                    has_option = 'mailto:' + has_option;
                    break;
                case 'img':
                    tag_name  = 'img src';
                    tag_close = '';
                    break;
                case 'font':
                    tag_name  = 'font face';
                    tag_close = 'font';
                    break;
                case 'size':
                    tag_name  = 'font size';
                    tag_close = 'font';
                    break;
                case 'color':
                    tag_name  = 'font color';
                    tag_close = 'font';
                    break;
                case 'background':
                    tag_name  = 'font bgcolor';
                    tag_close = 'font';
                    break;
                case 'indent':
                    tag_name = tag_close = 'blockquote';
                    break;
                case 'left':
                case 'right':
                case 'center':
                    has_option = tag_name;
                    tag_name   = 'div align';
                    tag_close  = 'div';
                    break;
            }
        }
        
        //-----------------------------------------
        // Got selected text?
        //-----------------------------------------
        
        if ( Object.isUndefined( selected_text ) )
        {
            selected_text = this.get_selection();
            selected_text = (selected_text === false) ? '' : new String(selected_text);
        }
        
        //-----------------------------------------
        // Using option?
        //-----------------------------------------
        
        if ( has_option === true )
        {
            var option = prompt( ips_language_arrayp['js_rte_optionals'] ? ips_language_arrayp['js_rte_optionals'] : "Введите аттрибуты для данного тега", '');
            
            if ( option )
            {
                var opentag = this.open_brace + tag_name + '="' + option + '"' + this.close_brace;
            }
            else
            {
                return false;
            }
        }
        else if ( has_option !== false )
        {
            var opentag = this.open_brace + tag_name + '="' + has_option + '"' + this.close_brace;
        }
        else
        {
            var opentag = this.open_brace + tag_name + this.close_brace;
        }

        var closetag = ( tag_close != '' ) ? this.open_brace + '/' + tag_close + this.close_brace : '';
        var text     = opentag + selected_text + closetag;
        //Debug.write( text );
        
        /*Debug.write("Wrap tags selection is: " + this.get_selection() );*/
        this.insert_text( text );
        
        return false;
    },
    /* ! wrap_tags_lite */
    wrap_tags_lite: function( start_text, close_text, replace_selection )
    {
        selected_text = '';
        
        if( Object.isUndefined( replace_selection ) || replace_selection == 0 )
        {
            // Got selected text?
            selected_text = this.get_selection();
            selected_text = (selected_text === false) ? '' : new String(selected_text);
        }
        
        this.insert_text( start_text + selected_text + close_text );
        
        return false;
    },
    /* ! preserve_ie_range */
    preserve_ie_range: function()
    { 
        if ( Prototype.Browser.IE && document.selection && ! this.emoClick )
        {
            /* Don't preserve range for emoticon click. It buggers things up epically */
            this._ie_cache = this.is_rte ? ( this.editor_document.selection.createRange ) ? this.editor_document.selection.createRange() : null : document.selection.createRange();
            Debug.write( "Preserved IE Range: ");
            this.emoClick = false;
        }
    },
    clean_html: function( t )
    {
        if ( t.blank() || Object.isUndefined(t) )
        {
            return t;
        }
        
        // Sort out BR tags
        t = t.replace( /<br>/ig, "<br />");

        // Remove empty <p> tags
        t = t.replace( /<p>(s+?)?</p>/ig, "");

        // HR issues
        t = t.replace( /<p><hr /></p>/ig                    , "<hr />"); 
        t = t.replace( /<p>&nbsp;</p><hr /><p>&nbsp;</p>/ig, "<hr />");

        // Attempt to fix some formatting issues...
        t = t.replace( /<(p|div)([^&]*)>/ig     , "n<$1$2>n" );
        t = t.replace( /</(p|div)([^&]*)>/ig   , "n</$1$2>n");
        t = t.replace( /<br />(?!</td)/ig     , "<br />n"   );

        // And some table issues...
        t = t.replace( /</(td|tr|tbody|table)>/ig  , "</$1>n");
        t = t.replace( /<(tr|tbody|table(.+?)?)>/ig , "<$1>n" );
        t = t.replace( /<(td(.+?)?)>/ig             , "t<$1>" );
        
        // Newlines
        t = t.replace( /<p>&nbsp;</p>/ig     , "<br />");
        t = t.replace( /<br />/ig            , "<br />n");
        t = t.replace( /<br>/ig               , "<br />n");
        
        t = t.replace( /<td><br />n</td>/ig  , "<td><br /></td>" );
        
        // Script tags
        t = t.replace( /<script/g , "&lt;script" );
        t = t.replace( /</script>/g , "&lt;/script&gt;" );
        
        t = t.replace( /^[snt]+/g, '' );
        t = t.replace( /[snt]+$/g, '' );
        t = t.replace( /<br />$/g, '' );
        
        return t;
    },
    strip_empty_html: function( html )
    {
        html = html.replace( '<([^>]+?)></([^>]+?)>', "");
        return html;
    },
    strip_html: function( html )
    {
        html = html.replace( /</?([^>]+?)>/ig, "");
        return html;
    },
    history_record_state: function( content )
    {
        // Make sure we're not recording twice        
        if ( this.history_recordings[ this.history_pointer ] != content )
        {
            this.history_pointer++;
            this.history_recordings[ this.history_pointer ] = content;
            
            // Make sure we've not gone back in time            
            if ( !Object.isUndefined( this.history_recordings[this.history_pointer + 1] ) )
            {
                this.history_recordings[this.history_pointer + 1] = null;
            }
        }
    },
    unhtmlspecialchars: function( html )
    {
        html = html.replace( /&quot;/g, '"' );
        html = html.replace( /&lt;/g  , '<' );
        html = html.replace( /&gt;/g  , '>' );
        html = html.replace( /&amp;/g , '&' );
        
        return html;
    },
    htmlspecialchars: function( html )
    {
        html = html.replace(/&/g, "&amp;");
        html = html.replace(/"/g, "&quot;");
        html = html.replace(/</g, "&lt;");
        html = html.replace(/>/g, "&gt;");
        
        return html;
    },
    history_time_shift: function( inc )
    {
        var i = this.history_pointer + inc;
        
        if ( i >= 0 && this.history_recordings[ i ] != null && typeof this.history_recordings[ i ] != 'undefined' )
        {
            this.history_pointer += inc;
        }
    },
    history_fetch_recording: function()
    {
        if (     !Object.isUndefined( this.history_recordings[ this.history_pointer ]  ) &&
                 this.history_recordings[ this.history_pointer ] != null
            )
        {
            return this.history_recordings[ this.history_pointer ];
        }
        else
        {
            return false;
        }
    },
    ipb_quote: function()
    {
        this.wrap_tags_lite(  '[quote]', '[/quote]', 0);
    },
    
    ipb_code: function()
    {
        this.wrap_tags_lite( '[code]', '[/code]', 0);
    },
    
    toggleEmoticons: function( e )
    {
        if( this.showing_sidebar )
        {
            $( this.id + '_sidebar').hide();
            $( 'editor_' + this.id ).removeClassName('with_sidebar'); 
            ipb.Cookie.set( 'emoticon_sidebar', 0, 0 );
            this.showing_sidebar = false;
        }
        else
        {
            if( this.emoticons_loaded )
            {
                $( this.id + '_emoticon_holder' ).show();
            }
            else
            {                
                this.buildEmoticons();
            }
            
            
            $( this.id + '_sidebar' ).show();
            $( 'editor_' + this.id ).addClassName('with_sidebar');
            ipb.Cookie.set( 'emoticon_sidebar', 1, 1 );
            this.showing_sidebar = true;
        }
        
    },
    
    buildEmoticons: function()
    {
        var table = new Element( 'table', { id: this.id + '_emoticons_palette' } ).addClassName('rte_emoticons');
        var tbody = new Element('tbody'); // IE needs a tbody
        table.insert( tbody );
        var perrow = 2;
        var classname = '1';
        var i = 0;
        
        //Cycle through emoticons list to build
        ipb.editor_values.get('emoticons').each( function(emote){
            
            if( i % perrow == 0 )
            {
                tr = new Element( 'tr' ).addClassName('row' + classname);
                tbody.insert( tr );
                classname = ( classname == '1' ) ? '2' : '1';
            }
            
            i++;
            
            var _tmp = emote.value.split(',');
            var img = new Element('img', { id: 'smid_' + _tmp[0], src: ipb.vars['emoticon_url'] + '/' + _tmp[1] } );
            
            td = new Element('td', { id: this.id + '_emoticons_emote_' + _tmp[0] } ).setStyle('cursor: pointer; text-align: center').addClassName('emote');
            td.writeAttribute('emo_id', _tmp[0] );
            td.writeAttribute('emo_img', _tmp[1] );
            td.writeAttribute('emo_code', emote.key);
            
            td.insert( img );
            tr.insert( td );
            $( td ).observe('click', this.events.emoticon_onclick.bindAsEventListener( this ) );
        }.bind(this));
        
        $( this.id + '_emoticon_holder' ).update( table ).show();
        this.emoticons_loaded = true;
        
        if( $( this.id + '_showall_emoticons' ) ){
            $( this.id + '_showall_emoticons' ).observe('click', this.showAllEmoticons.bindAsEventListener( this ));
        }
        
        if( $( this.id + '_close_sidebar' ) ){
            $( this.id + '_close_sidebar' ).observe('click', this.toggleEmoticons.bindAsEventListener( this ) );
        }
    },
    
    showAllEmoticons: function( e )
    {
        // Get the emoticons
        if( Object.isUndefined( inACP ) || inACP == false ){
            var url = ipb.vars['base_url'];
        } else {
            var url = ipb.vars['front_url'];
        }

        url += "app=forums&amp;module=ajax&amp;section=emoticons&amp;editor_id=" + this.id + "&amp;secure_key=" + ipb.vars['secure_hash'];

        new Ajax.Request( url.replace(/&amp;/g, '&'),
                        {
                            method: 'get',
                            onSuccess: function(t)
                            {
                                $( this.id + '_emoticon_holder').update( t.responseText );
                                if( $( this.id + '_showall_bar' ) ){
                                    $( this.id + '_showall_bar' ).hide();
                                    $( this.id + '_emoticon_holder').addClassName('no_bar');
                                }
                            }.bind(this)
                        });
        
    }
    
});

//==============================================================================================================//
// MOZ SPECIFIC CODE
if( ( Prototype.Browser.Gecko || Prototype.Browser.WebKit ) && USE_RTE ){
    _editor.prototype.editor.prototype.ORIGINAL_editor_set_content = _editor.prototype.editor.prototype.editor_set_content;
    _editor.prototype.editor.prototype.ORIGINAL_apply_formatting = _editor.prototype.editor.prototype.apply_formatting;
    
    Debug.write( "Adding mozilla-specific methods" );
    
    _editor.prototype.editor.addMethods({
        _moz_test: function()
        {
            return "Test: " + this.id;
        },
        togglesource_pre_show_html: function()
        {
            this.editor_document.designMode = 'off';
        },
        togglesource_post_show_html: function()
        {
            this.editor_document.designMode = 'on';
        },
        editor_set_content: function( initial_text )
        {
            this.ORIGINAL_editor_set_content( initial_text );
            
            Event.observe( this.editor_document, 'keypress', this.events.editor_document_onkeypress.bindAsEventListener(this) );

            // Remove spellcheck button
            if( $( this.id + '_cmd_spellcheck' ) ){ 
                $( this.id + '_cmd_spellcheck' ).hide();
                this.hidden_objects[ this.id + '_cmd_spellcheck' ] = 1;
            }

            // Kill tags
            if ( this.use_bbcode && $( this.id + '_cmd_justifyfull' ) )
            {
                $( this.id + '_cmd_justifyfull' ).hide();
                this.hidden_objects[ this.id + '_cmd_justifyfull' ] = 1;
            }

            // Go on.. cursor, flash you bastard        
            try
            {
                var _y = parseInt( window.pageYOffset );

                // Sometimes moves the focus to the RTE
                this.editor_document.execCommand("inserthtml", false, " ");
                this.editor_document.execCommand("undo"      , false, null);

                // Restore Y
                scroll( 0, _y );
            }
            catch(error)
            {
                Debug.write( "#11 " + error );
            }
        },
        
        editor_set_functions: function()
        {
            Event.observe( this.editor_document,     'mouseup',     this.events.editor_document_onmouseup.bindAsEventListener(this) );
            Event.observe( this.editor_document,     'keyup',     this.events.editor_document_onkeyup.bindAsEventListener(this) );
            Event.observe( this.editor_document,     'keydown',     this.events.editor_document_onkeydown.bindAsEventListener(this) );
        
            Event.observe( this.editor_window,         'focus',     this.events.editor_window_onfocus.bindAsEventListener( this ) );
            Event.observe( this.editor_window,         'blur',     this.events.editor_window_onblur.bindAsEventListener( this ) );            
        },
        apply_formatting: function(cmd, dialog, arg)
        {
            // Moz fix to allow list button click before clicking in RTE
            if ( cmd != 'redo' )
            {
                this.editor_document.execCommand("inserthtml", false, " ");
                this.editor_document.execCommand("undo"      , false, null);
            }
        
            this.editor_document.execCommand( 'useCSS', false, true );
            this.editor_document.execCommand( 'styleWithCSS', false, false );
            
            return this.ORIGINAL_apply_formatting(cmd, dialog, arg);
        },
        get_selection: function()
        {
            var selection = this.editor_window.getSelection();
        
            this.editor_check_focus();
            var range     = selection ? selection.getRangeAt(0) : this.editor_document.createRange();
        
            return this.moz_read_nodes( range.cloneContents(), false );
        },
        moz_add_range: function(node, text_length)
        {
            /*Debug.write( "In moz_add_range" );*/
            this.editor_check_focus();

            var sel   = this.editor_window.getSelection();
            var range = this.editor_document.createRange();
        
            range.selectNodeContents(node);
        
            if ( text_length )
            {
                range.setEnd(  node, text_length);
                range.setStart(node, text_length);
            }
        
            sel.removeAllRanges();
            sel.addRange(range);
        },
        moz_read_nodes: function(root, toptag)
        {
            var html      = "";
            var moz_check = /_moz/i;

            switch (root.nodeType)
            {
                case Node.ELEMENT_NODE:
                case Node.DOCUMENT_FRAGMENT_NODE:
                {
                    var closed;
                    if (toptag)
                    {
                        closed   = ! root.hasChildNodes();
                        html     = '<' + root.tagName.toLowerCase();
                        var attr = root.attributes;
                        for (var i = 0; i < attr.length; ++i)
                        {
                            var a = attr.item(i);
                            if (!a.specified || a.name.match(moz_check) || a.value.match(moz_check))
                            {
                                continue;
                            }

                            html += " " + a.name.toLowerCase() + '="' + a.value + '"';
                        }
                        html += closed ? " />" : ">";
                    }
                    for (var i = root.firstChild; i; i = i.nextSibling)
                    {
                        html += this.moz_read_nodes(i, true);
                    }
                    if (toptag && !closed)
                    {
                        html += "</" + root.tagName.toLowerCase() + ">";
                    }
                }
                break;

                case Node.TEXT_NODE:
                {
                    html = this.htmlspecialchars(root.data);
            
                }
                break;
            }

            return html;
        },
        moz_goto_parent_then_body: function( n )
        {
            var o = n;

            while (n.parentNode != null && n.parentNode.nodeName == 'HTML')
            {
                n = n.parentNode;
            }

            if (n)
            {
                for ( var c = 0; c < n.childNodes.length; c++ )
                {
                    if ( n.childNodes[c].nodeName == 'BODY' )
                    {
                        return n.childNodes[c];
                    }
                }
            }

            return o;
        },
        moz_insert_node_at_selection: function(text, text_length)
        {
            this.editor_check_focus();

            var sel   = this.editor_window.getSelection();
            var range = sel ? sel.getRangeAt(0) : this.editor_document.createRange();
        
            sel.removeAllRanges();
            range.deleteContents();

            var node = range.startContainer;
            var pos  = range.startOffset;
        
            text_length = text_length ? text_length : 0;
        
            if ( node.nodeName == 'HTML' )
            {
                node = this.moz_goto_parent_then_body( node );
            }
        
            switch (node.nodeType)
            {
                case Node.ELEMENT_NODE:
                { 
                    if (text.nodeType == Node.DOCUMENT_FRAGMENT_NODE)
                    {
                        selNode = text.firstChild;
                    }
                    else
                    {
                        selNode = text;
                    }
                    node.insertBefore(text, node.childNodes[pos]);
                    this.moz_add_range(selNode, text_length);
                }
                break;

                case Node.TEXT_NODE:
                {
                    if (text.nodeType == Node.TEXT_NODE)
                    {
                        var text_length = pos + text.length;
                        node.insertData(pos, text.data);
                        range = this.editor_document.createRange();
                        range.setEnd(node, text_length);
                        range.setStart(node, text_length);
                        sel.addRange(range);
                    }
                    else
                    {
                        node = node.splitText(pos);
                        var selNode;
                        if (text.nodeType == Node.DOCUMENT_FRAGMENT_NODE)
                        {
                            selNode = text.firstChild;
                        }
                        else
                        {
                            selNode = text;
                        }
                        node.parentNode.insertBefore(text, node);
                        this.moz_add_range(selNode, text_length);
                    }
                }
                break;
            }
            
            sel.removeAllRanges();
        },
        insert_text: function(str, len)
        {
            fragment = this.editor_document.createDocumentFragment();
            holder   = this.editor_document.createElement('span');
        
            holder.innerHTML = str;

            while (holder.firstChild){
                fragment.appendChild( holder.firstChild );
            }
        
            var my_length = parseInt( len ) > 0 ? len : 0;

            this.moz_insert_node_at_selection( fragment, my_length );
            
        },
        insert_emoticon: function( emo_id, emo_image, emo_code, event )
        {
            this.editor_check_focus();
            try
            {
                // INIT
                var _emo_url  = ipb.vars['emoticon_url'] + "/" + emo_image;
            
                this.editor_document.execCommand('InsertImage', false, _emo_url);
            
                var images = this.editor_document.getElementsByTagName('img');

                //----------------------------------
                // Sort through and fix emo
                //----------------------------------
            
                if ( images.length > 0 )
                {
                    for ( var i = 0 ; i <= images.length ; i++ )
                    {
                        if ( !Object.isUndefined( images[i] ) && images[i].src.match( new RegExp( _emo_url + "$" ) ) )
                        {
                            if ( ! images[i].getAttribute('alt') )
                            {
                                images[i].setAttribute( 'alt', this.unhtmlspecialchars( emo_code ) );
                                images[i].setAttribute( 'class', 'bbc_emoticon' );
                            }
                        }
                    }
                }
            }
            catch(error)
            {
                Debug.write( "#12 " + error );
                //alert( error );
            }
        
            if ( this.emoticon_window_id != '' && typeof( this.emoticon_window_id ) != 'undefined' )
            {
                this.emoticon_window_id.focus();
            }
        }
    });
};

//==============================================================================================================//
// OPERA SPECIFIC CODE

if( Prototype.Browser.Opera && USE_RTE ){
    _editor.prototype.editor.prototype.ORIGINAL_editor_set_content = _editor.prototype.editor.prototype.editor_set_content;
    
    _editor.prototype.editor.addMethods({
        editor_set_content: function(initial_text)
        {
            this.ORIGINAL_editor_set_content(initial_text);
        
        
            // Opera doesn't auto 100% the height, so
            // lets force the body to be 100% high        
            this.editor_document.body.style.height = '95%';
        
            Event.observe( this.editor_document, 'keypress', this.events.editor_document_onkeypress.bindAsEventListener( this ) );
        
            // Remove spellcheck button
            if ( $( this.id + '_cmd_spellcheck' ) )
            {
                $( this.id + '_cmd_spellcheck' ).hide();
                this.hidden_objects[ this.id + '_cmd_spellcheck' ] = 1;
            }
            
            // Kill tags
            if ( this.use_bbcode )
            {
                $( this.id + '_cmd_justifyfull' ).hide();            
                this.hidden_objects[ this.id + '_cmd_justifyfull' ] = 1;
            }
        
            // Go on.. cursor, flash you bastard
            try
            {
                var _y = parseInt( window.pageYOffset );
            
                // Sometimes moves the focus to the RTE
                this.editor_document.execCommand("inserthtml", false, "-");
                this.editor_document.execCommand("undo"      , false, null);
            
                // Restore Y
                scroll( 0, _y );
            }
            catch(error)
            {
                Debug.write( "#13 " + error );
            }
        },
        insert_text: function(str)
        {
            this.editor_document.execCommand('insertHTML', false, str);
        },
        get_selection: function()
        {
            var selection = this.editor_window.getSelection();
        
            this.editor_check_focus();
        
            var range = selection ? selection.getRangeAt(0) : this.editor_document.createRange();
            var lsserializer = document.implementation.createLSSerializer();
        
            return lsserializer.writeToString(range.cloneContents());
        },
        editor_set_functions: function()
        {
            Event.observe( this.editor_document,     'mouseup',     this.events.editor_document_onmouseup.bindAsEventListener( this ) );
            Event.observe( this.editor_document,     'keyup',     this.events.editor_document_onkeyup.bindAsEventListener( this ) );
            Event.observe( this.editor_window,         'focus',     this.events.editor_window_onfocus.bindAsEventListener( this ) );
            Event.observe( this.editor_window,         'blur',     this.events.editor_window_onblur.bindAsEventListener( this ) );
        }
    });
}


//==============================================================================================================//
// EVENTS
_editor_events = Class.create({
    handle_custom_command: function( e, cmd )
    {
        Event.stop(e);
        
        //Debug.write( Event.element(e) );
        
        var elem = ( $( Event.element(e) ).hasClassName('specialitem') ) ? $( Event.element(e) ) : $( Event.element( e ) ).up('.specialitem');
        if( !$( elem ) ){ return; }
        
        var cmd = $( elem ).id.replace( this.id + '_cmd_custom_', '' );
        var info = this.values.get('bbcodes').get( cmd );
        
        Debug.write( cmd );
        
        if( info['single_tag'] == '1' && info['useoption'] == '0' )
        {
            this.wrap_tags_lite( '[' + info['tag'] + ']', '', 1);
            ipb.menus.registered.get( this.id + '_cmd_otherstyles' ).doClose();
            return;
        }
        else
        {
            var selection = this.get_selection();

            try {            
                window.setTimeout( function()
                    { 
                        if( info['useoption'] == '1' && info['single_tag'] == '1' )
                        {
                            if( $( this.id + '_' + cmd + '_option') ){
                                $( this.id + '_' + cmd + '_option' ).focus();
                            }
                        }
                        else
                        {        
                            if( selection )
                            {
                                $( this.id + '_' + cmd + '_text' ).value = selection;
                            }

                            if( $( this.id + '_' + cmd + '_option') ){
                                $( this.id + '_' + cmd + '_option' ).focus();
                            } else {
                                $( this.id + '_' + cmd + '_text' ).activate();
                            }
                        }
                    }.bind(this), 200
                );
            } catch( err ){
                Debug.write( err );
            }
        }
    },
    handle_custom_onclick: function(e)
    {
        Debug.write("Here 5");
        var elem = Event.element(e);
        if( !elem.hasClassName('ipb_palette') ){
            elem = Event.findElement(e, '.ipb_palette');
        }
        
        var styleid = elem.readAttribute("styleid");
        if( !styleid || Object.isUndefined( this.values.get('bbcodes').get( styleid ) ) ) { return; }
        var info = this.values.get('bbcodes').get( styleid );
        Debug.write("Here 4");
        // Check for required option
        if( info['useoption'] == '1' && info['optional_option'] == '0' && $F( this.id + '_' + styleid + '_option' ).blank() )
        {
            alert( ipb.lang['option_is_empty'] );
            try {
                $( this.id + '_' + styleid + '_option' ).focus();
            } catch( err ){ }
            
            return;
        }
        Debug.write("Here 3");
        // Now work out what kind of tag to build...
        if( info['useoption'] == '1' && info['single_tag'] == '1' )
        {
            var option = $F( this.id + '_' + styleid + '_option' );
            
            if( info['optional_option'] == '1' && option.blank() ){
                this.wrap_tags_lite( '[' + info['tag'] + ']', '', 1 );
            } else {
                this.wrap_tags_lite( '[' + info['tag'] + "='" + option + "']", '', 1 );
            }
        }
        else
        {
            Debug.write("Here 1");
            var value = $F( this.id + '_' + styleid + '_text' );
            Debug.write("Here 2");
            var option = ( $(this.id + '_' + styleid + '_option') ) ? $F( this.id + '_' + styleid + '_option' ) : '';
            
            // If this is RTE, change newlines to br tags.
            // @link    http://community.invisionpower.com/tracker/issue-21173-line-breaks-arent-converted-to-%26lt%3Bbr%26gt%3B-in-code-popup-in-rte/
            if( USE_RTE )
            {
                value    = value.replace( /n/g, '<br />' );
            }
            
            if( ( info['optional_option'] == '1' && option.blank() ) || info['useoption'] == '0' ){
                this.wrap_tags_lite( '[' + info['tag'] + ']' + value, '[/' + info['tag'] + ']', 1 );
            } else {
                this.wrap_tags_lite( '[' + info['tag'] + "='" + option + "']" + value, '[/' + info['tag'] + ']', 1 );
            }
        }
        /*var value = $F( this.id + '_' + styleid + '_text' );
        
        if( style[2] ){
            var option = $F( this.id + '_' + styleid + '_option' );
            this.wrap_tags_lite( '[' + style[1] + "='" + option + "']" + value, '[/' + style[1] + ']' );
        }
        else
        {
            this.wrap_tags_lite( '[' + style[1] + ']' + value, '[/' + style[1] + ']' );
        }*/
        
        this.palettes[ 'otherstyles_' + styleid ].doClose();
    },
    /* ! editor_document_onmouseup */
    editor_document_onmouseup: function(e)
    {
        Debug.write("Mouse up");
        ipb.menus.closeAll(); // Close menus
        this.set_context();

        if ( Prototype.Browser.IE )
        {
            //this.preserve_ie_range();
        }
    },
    editor_document_onkeyup: function(e)
    {
        this.set_context();
    },
    editor_document_onkeydown: function(e)
    {
        //alert( this.forum_fix_ie_newlines + "   " + Prototype.Browser.IE + "    " + e.keyCode );
        
        if (    this.forum_fix_ie_newlines &&
                 Prototype.Browser.IE &&
                 e.keyCode == Event.KEY_RETURN ) // Enter key 
        {
            var _test = ['Indent', 'Outdent', 'JustifyLeft', 'JustifyCenter', 'JustifyRight', 'InsertOrderedList', 'InsertUnorderedList'];
            
            for ( i=0; i< _test.length; i++ )
            {
                if ( this.editor_document.queryCommandState( _test[ i ] ) )
                {
                    return true;
                }
            }
            
            var sel   = this.editor_document.selection; 
            var ts    = this.editor_document.selection.createRange();
            var t     = ts.htmlText.replace(/<p([^>]*)>(.*)</p>/i, '$2');
            
            if ( (sel.type == "Text" || sel.type == "None") ) 
            { 
                 ts.pasteHTML( "<br />" + t + "n" ); 
            } 
            else 
            { 
                 this.editor_document.innerHTML += "<br />n"; 
            } 

            this.editor_window.event.returnValue = false; 
            ts.select(); 
            this.editor_check_focus();
        }
    },
    editor_document_onkeypress: function(e)
    {
        if ( e.ctrlKey )
        {
            switch (String.fromCharCode(e.charCode).toLowerCase())
            {
                case 'b': cmd = 'bold';      break;
                case 'i': cmd = 'italic';    break;
                case 'u': cmd = 'underline'; break;
                default: return;
            }

            //e.preventDefault();
            Event.stop(e);

            this.apply_formatting(cmd, false, null);
            return false;
        }
    },
    editor_window_onfocus: function(e)
    {
        this.has_focus = true;
    },
    editor_window_onblur: function(e)
    {
        this.has_focus = false;
    },
    button_onmouse_event: function(e)
    {
        if( !Event.element(e).hasClassName( 'rte_control' ) ){
            elem = $( Event.element(e) ).up('.rte_control');
        } else {
            elem = Event.element(e);
        }
        
        Debug.write( elem.readAttribute('cmd') );
        
        if ( e.type == 'click' )
        {
            if( elem.readAttribute('cmd').startsWith('custom_') )
            {
                // Return so that the custom styles code can run interruptedb
                return;
            }
            else if( elem.readAttribute('cmd') == 'help' )
            {
                //Event.stop(e);
                if( inACP )
                {
                    window.open( ipb.vars['front_url'] + "&app=forums&module=extras&section=legends&do=bbcode", "bbcode", "status=0,toolbar=0,width=1024,height=800,scrollbars=1");
                }
                else
                {
                    window.open( ipb.vars['base_url'] + "&app=forums&module=extras&section=legends&do=bbcode", "bbcode", "status=0,toolbar=0,width=1024,height=800,scrollbars=1");
                }
                Event.stop(e);
                return false;
            }
            else if( elem.readAttribute('cmd').startsWith('r_') )
            {
                // Resize commands
                var editorSize = $( this.id + '_textarea' ).getHeight();
                
                if( elem.readAttribute('cmd') == 'r_small' ){
                    this.resize_to( editorSize - 100 );
                } else {
                    this.resize_to( editorSize + 100 );
                }
            }
            else if( elem.readAttribute('cmd') == 'emoticons' )
            {
                this.toggleEmoticons( e );
            }
            else
            {
                this.format_text( e, elem.readAttribute('cmd'), false, true);
            }
        }
        
        Event.stop(e); // Removed if(IE) check

        this.set_button_context(elem, e.type);
    },
    font_format_option_onclick: function(e)
    {        
        if( !Event.element(e).hasClassName('fontitem') ){
            elem = Event.element(e).up('.fontitem');
        } else {
            elem = Event.element(e);
        }
        
        cmd = $( elem ).up('.ipbmenu_content').readAttribute('cmd');
        
        //this.editor_check_focus();
        //this.preserve_ie_range();
        /*Debug.write( "Selection: " + this.get_selection() );
        Debug.write( "Format text option: " + elem.innerHTML );*/
        
        this.format_text(e, cmd, elem.innerHTML);
    },
    color_cell_onclick: function(e)
    {
        elem = Event.element(e);
        cmd = $( elem ).up('.ipb_palette').readAttribute('cmd');
        
        this.format_text(e, cmd, '#' + elem.readAttribute('colorname'));
        this.palettes[ cmd ].doClose();
    },
    
    palette_button_onmouseover: function(e)
    {
        if( !Event.element(e).hasClassName( 'rte_palette' ) ){
            elem = $( Event.element(e) ).up('.rte_palette');
        } else {
            elem = Event.element(e);
        }
        
        elem.setStyle('cursor: pointer;');
    },
    palette_onmouse_event: function(e)
    {
        if( !Event.element(e).hasClassName( 'rte_control' ) ){
            elem = $( Event.element(e) ).up('.rte_control');
        } else {
            elem = Event.element(e);
        }
        
        if( e.type == 'mouseover' ){
            $( elem ).addClassName('rte_hover');
        } else {
            $( elem ).removeClassName('rte_hover');
        }
    },
    
    palette_return_key: function(e)
    {    
        /*elem = Event.element(e);
        palette = elem.up('.ipb_palette');
        if( !palette ){ return; }
        cmd = palette.readAttribute('cmd');
            
        if( e.keyCode == Event.KEY_RETURN )
        {
            Debug.write( cmd );
            
            var test = this.events.palette_submit.bind( this, e );
            test();
            test = null;
            Event.stop(e);
        }*/
    },
    
    palette_submit: function(e)
    {
        elem = Event.element(e);
        palette = elem.up('.ipb_palette');
        if( !palette ){ return; }
        cmd = palette.readAttribute('cmd');
        
        Debug.write( $( elem ).id + " " + $( palette ).id + " " + cmd  );
        // What are we doing?
        switch( cmd )
        {
            case 'link':
                var url = $F( this.id + '_url' );
                var text = $F( this.id + '_urltext' );
                
                if( url == 'http://' || url.blank() ){ return; };
                if( text.blank() ){
                    text = url;
                }
                
                this.wrap_tags( 'url', url, text );
            break;
            case 'image':
                var img = $F( this.id + '_img' );
                
                if( img == 'http://' || img.blank() ){ return; };
                
                if ( ! this.is_rte ){
                    this.wrap_tags( 'img', false, img );
                } else {
                    this.wrap_tags( 'img', img, '' );
                }
            break;
            case 'email':
                var email = $F( this.id + '_email' );
                var text = $F( this.id + '_emailtext' );
                
                if( email.blank() || email.indexOf('@') == -1 ){ return; }
                if( text.blank() ){
                    text = email;
                }
                
                this.wrap_tags( 'email', email, text );
            break;
            case 'media':
                var url = $F( this.id + '_media' );
                
                if( url.blank() ){ return; }

                if( ! this.is_rte ){
                    this.wrap_tags( 'media', false, url );
                } else {
                    this.wrap_tags_lite( '[media]' + url, '[/media]' );
                }
            break;
        }
        
        this.palettes[ cmd ].doClose();
    },
    emoticon_onclick: function(e)
    {
        Event.stop(e);
        var elem = Event.element(e);
        var emo = elem.up('.emote');
        
        if( !emo )
        {
            return false;
        }
            
        this.insert_emoticon( emo.readAttribute('emo_id'), emo.readAttribute('emo_img'), emo.readAttribute('emo_code'), e );
    },
    link_onclick: function(e)
    {
        // Any selected text?
        var selection = this.get_selection();
        var _active = null;
        
        try {
            if( selection )
            {
                Debug.write( "**selection: " + selection );
                
                /* Got an image? */
                if( selection.match( /<img/ ) || selection.match( /[img]/ ) )
                {
                    /* Make sure it's valid BBcode */
                    if ( ! this.is_rte )
                    {
                        selection = selection.gsub( /<img src=['"]([^'"]+?)['"]s+?/>/, function( match ) { return "[img]" + match[1] + "[/img]"; } );
                    }
                    
                    $( this.id + '_url' ).value     = this.defaults['link_url'];
                    $( this.id + '_urltext' ).value = selection;
                }
                else if( selection.match(/<a/) )
                {
                    if ( res = selection.match( /href="([^"]+?)"([^>]+?)?>([^<]+?)</a>/i ) )
                    {
                        Debug.write( res );
                        if ( res.length )
                        {
                            $( this.id + '_url' ).value = res[1];
                            $( this.id + '_urltext' ).value = res[3];
                        }
                        else
                        {
                            $( this.id + '_url' ).value = selection.strip();
                            $( this.id + '_urltext' ).value = this.defaults['link_text'];
                        }
                        _active = $( this.id + '_urltext' );
                    }
                }
                else if( selection.match(/[A-Za-z]+://[A-Za-z0-9.-]{3,}.[A-Za-z]{3}/) ){
                    $( this.id + '_url' ).value = selection.strip();
                    $( this.id + '_urltext' ).value = this.defaults['link_text'];
                    _active = $( this.id + '_urltext' );
                } else {
                    $( this.id + '_urltext' ).value = selection.strip();
                    $( this.id + '_url' ).value = this.defaults['link_url'];
                    _active = $( this.id + '_url' );
                }
            }
            else
            {
                $( this.id + '_urltext' ).value = this.defaults['link_text'];
                $( this.id + '_url' ).value = this.defaults['link_url'];
                _active = $( this.id + '_url' );
            }
        
            if( !this.key_handlers[ 'url' ] )
            {
                $( this.id + '_url' ).observe('keypress', this.events.palette_return_key.bindAsEventListener( this ));
                $( this.id + '_urltext' ).observe('keypress', this.events.palette_return_key.bindAsEventListener( this ));
                this.key_handlers[ 'url' ] = true;
            }
            
            window.setTimeout( function()
                { 
                    $( _active ).activate();
                }.bind(this), 200
            );
                
        } catch(err){ Debug.write( "#13 " + err ); }
    },
    image_onclick: function(e)
    {        
        var selection = this.get_selection();
        var msg = ( selection && !selection.startsWith('<IMG') ) ? selection : this.defaults['img'];
        
        try {
            $( this.id + '_img' ).value = msg;
            
            if( !this.key_handlers[ 'image' ] )
            {
                $( this.id + '_img' ).observe('keypress', this.events.palette_return_key.bindAsEventListener( this ));
                this.key_handlers[ 'image' ] = true;
            }
            
            window.setTimeout( function()
                { 
                    $( this.id + '_img' ).activate();
                }.bind(this), 200
            );
        } catch(err){ Debug.write( "#14 " + err ); }
    },
    media_onclick: function(e)
    {        
        var selection = this.get_selection();
        var msg = ( selection ) ? selection : this.defaults['media'];
        
        try {
            $( this.id + '_media' ).value = msg;
            
            if( !this.key_handlers[ 'media' ] )
            {
                $( this.id + '_media' ).observe('keypress', this.events.palette_return_key.bindAsEventListener( this ));
                this.key_handlers[ 'media' ] = true;
            }
            
            window.setTimeout( function()
                { 
                    $( this.id + '_media' ).activate();
                }.bind(this), 200
            );
        } catch(err){ Debug.write( "#18 " + err ); }
    },
    email_onclick: function(e)
    {
        var selection = this.get_selection();
        var _active = $( this.id + '_email' );
        
        try {
            if( selection )
            {
                if( selection.match(/([a-zA-Z0-9_.-])+@(([a-zA-Z0-9-])+.)+([a-zA-Z0-9]{2,4})+/) )
                {
                    $( this.id + '_email' ).value = selection.strip();
                    $( this.id + '_emailtext' ).value = this.defaults['email_text'];
                    _active = $( this.id + '_emailtext' );
                }
                else
                {
                    $( this.id + '_emailtext' ).value = selection.strip();
                    $( this.id + '_email' ).value = this.defaults['email'];
                }
            }
            else
            {
                $( this.id + '_emailtext' ).value = this.defaults['email_text'];
                $( this.id + '_email' ).value = this.defaults['email'];
            }
            
            if( !this.key_handlers[ 'email' ] )
            {
                $( this.id + '_email' ).observe('keypress', this.events.palette_return_key.bindAsEventListener( this ));
                $( this.id + '_emailtext' ).observe('keypress', this.events.palette_return_key.bindAsEventListener( this ));
                this.key_handlers[ 'email' ] = true;
            }
            
            window.setTimeout( function()
                { 
                    $( _active ).activate();
                }.bind(this), 200
            );
        } catch( err ){ Debug.write( "#16 " + err ); }
    },
    
    show_emoticon_sidebar: function( e )
    {
        // Get the emoticons
        if( Object.isUndefined( inACP ) || inACP == false ){
            var url = ipb.vars['base_url'];
        } else {
            var url = ipb.vars['front_url'];
        }
        
        url += "app=forums&amp;module=ajax&amp;section=emoticons&amp;editor_id=" + this.id;
        
        new Ajax.Request( url.replace(/&amp;/g, '&'),
                        {
                            method: 'get',
                            onSuccess: function(t)
                            {
                                // Add the sidebar
                                $('editor_' + this.id).addClassName('with_sidebar');
                                var div = $('editor_' + this.id).down('.sidebar');
                                
                                div.update( this.values.get('templates')['emoticon_wrapper'].evaluate( { id: this.id } ) );
                                $( this.id + '_emoticon_holder').update( t.responseText );
                                div.show();
                                
                                this.palettes[ 'emoticons' ].doClose();
                            }.bind(this)
                        });
    },
    
    //called statically
    addEmoticon: function( code, id, img, editorid )
    {
        try {
            this.insert_emoticon( '', img, code, '' );
        }
        catch(err)
        {
            Debug.error( err );
        }
    }
});

var x_expanded = new Array();

function editorMinimize( key )
{
    Debug.write( 'shrinking: ' + key );
    x_expanded[key] = 0;
    
    $(key + '_textarea').setStyle( { height: '70px' } );
    
    $('editor_' + key).removeClassName('ips_editor');
    $(key + '_controls').hide();
    
    /* is there value? */
    if ( $(key + '_textarea').value )
    {
        editorExpand( key );
    }
    
    $(key + '_textarea').observe( 'focus', function(e) {
        editorExpand( key );
    } );
}

function editorExpand( key )
{
    $H(x_expanded).each( function(i)
    {
        /* Shrink set up editors */
        if ( i.key != key )
        {
            editorCollapse( i.key );
        }
    } );
    
    if ( !x_expanded[key] || x_expanded[key] == 0 )
    {
        Debug.write(" expanding: " + key);
        $(key + '_controls').appear();
        $('editor_' + key).addClassName('ips_editor');
        
        ipb.editors[key] = new ipb.editor( key, USE_RTE );
        $( ipb.editors[key ] ).resize_to( 250 );
        x_expanded[ key ] = 1;
        
        try
        {    
            ipb.editors[key].editor_window.focus();
        } catch(err) { Debug.write( err ); }

    }    
}

function editorCollapse(key)
{
    
}

/*_editor.prototype.switchEditor = function( editorID )
{
    if( !ipb.editors[ editorID ] ){ Debug.error( "No editor found for ID " + editorID ); }
    
    var editor = ipb.editors[ editorID ];
    var url = ipb.vars['base_url'] + "app=";
    var newmode = !ipb.editors[ editorID ].is_rte;
    
    if( editor._loading ){
        Debug.info("Editor is already loading")
        return false;
    } else {
        editor._loading = true;
    }
}*/
?>
Онлайн: 1
Реклама