﻿// JScript File
Type.registerNamespace("Winthusiasm");

Winthusiasm.HtmlEditor = function(element)
{
    Winthusiasm.HtmlEditor.initializeBase(this, [element]);
    
    this._htmlencodedTextID = "";
    this._htmlEditorID = "";
    this._designEditorID = "";
    this._htmlAreaID = "";
    this._designAreaID = "";
    this._htmlTabID = "";
    this._designTabID = "";
    this._dropdownToolbarID = "";
    this._buttonToolbarID = "";
    this._designModeCss = "";
    this._designModeBodyTagCssClass = "";
    this._baseUrl = "";
    this._backColor = "";
    this._editorForeColor = "";
    this._editorBackColor = "";
    this._toolbarColor = "";
    this._tabForeColor = "";
    this._tabBackColor = "";
    this._tabMouseOverColor = "";
    this._tabbarBackColor = "";
    this._buttonMouseOverColor = "";
    this._buttonMouseOverBorderColor = "";
    this._outputXHTML = "";
    this._convertDeprecatedSyntax = "";
    this._showModifiedAsterick = "";
    this._allowedTags = "";
    this._allowedAttributes = "";
    this._formatHtmlMode = false;
    this._newLine = "";
    this._modified = false;
    this.htmlEditor = null;
    this.designEditor = null;
    this.htmlArea = null;
    this.designArea = null;
    this.designModeDocument = null;
    this.htmlModeDocument = null;
    this.designFocusDocument = null;
    this.designModeFocusElement = null;
    this.htmlModeFocusElement = null;
    this.formElement = null;
    this.designMode = false;
    this.cssCommand = "";
    this.outputXHTML = false;
    this.convertDeprecatedSyntax = false;
    this.allowedTags = null;
    this.allowedAttributes = null;
    this.newLine = "";
    this.noEndTags = null;
    this.blockTags = null;
    this.listTags = null;
    this.conversionRules = null;
    this.fontSizes = "";
    this.onDesignEditorKeypressHandler = null;
    this.onDesignEditorKeydownHandler = null;
    this.onDesignEditorMousedownHandler = null;
    this.onDesignEditorBlurHandler = null;
    this.onHtmlEditorBlurHandler = null;
    this.onEditorFocusHandler = null;
    this.endRequestHandler = null;
    this.timer = null;
    this.recordedHtml = "";
    this.innerHtml = "";
    this.initialized = false;
    this.designModeInitialized = false;
    this.isIE = false;
    this.isFirefox = false;
}

Winthusiasm.HtmlEditor.prototype = 
{
    Save: function()
    {
        var html = this.GetInnerHtml();
        if (this.outputXHTML) html = this.ConvertHTML(html, true);

        var encodedhtml = this.ClientEncode(html);
        var htmlencodedText = $get(this.get_htmlencodedTextID());
        htmlencodedText.value = encodedhtml;
        
        this.RecordHtml();
    },
    
    IsModified: function()
    {
        return this.get_modified();
    },
    
    GetText: function()
    {
        var html = this.GetDecodedText();
        if (this.outputXHTML) html = this.ConvertHTML(html, true);
        
        return html;
    },
    
    SetText: function(html)
    {
        var encodedHtml = this.ClientEncode(html);

        var htmlencodedText = $get(this.get_htmlencodedTextID());
        htmlencodedText.value = encodedHtml; 
        
        this.UpdateHtml();
    },
    
    get_htmlencodedTextID: function()
    {
        return this._htmlencodedTextID;
    },
    
    set_htmlencodedTextID: function(value)
    {
        this._htmlencodedTextID = value;
    },
    
    get_htmlEditorID: function()
    {
        return this._htmlEditorID;
    },
    
    set_htmlEditorID: function(value)
    {
        this._htmlEditorID = value;
    },
    
    get_designEditorID: function()
    {
        return this._designEditorID;
    },
    
    set_designEditorID: function(value)
    {
        this._designEditorID = value;
    },
    
    get_htmlAreaID: function()
    {
        return this._htmlAreaID;
    },
    
    set_htmlAreaID: function(value)
    {
        this._htmlAreaID = value;
    },
    
    get_designAreaID: function()
    {
        return this._designAreaID;
    },
    
    set_designAreaID: function(value)
    {
        this._designAreaID = value;
    },
    
    get_htmlTabID: function()
    {
        return this._htmlTabID;
    },
    
    set_htmlTabID: function(value)
    {
        this._htmlTabID = value;
    },
    
    get_designTabID: function()
    {
        return this._designTabID;
    },
    
    set_designTabID: function(value)
    {
        this._designTabID = value;
    },
    
    get_dropdownToolbarID: function()
    {
        return this._dropdownToolbarID;
    },
    
    set_dropdownToolbarID: function(value)
    {
        this._dropdownToolbarID = value;
    },
    
    get_buttonToolbarID: function()
    {
        return this._buttonToolbarID;
    },
    
    set_buttonToolbarID: function(value)
    {
        this._buttonToolbarID = value;
    },
    
    get_designModeCss: function()
    {
        return this._designModeCss;
    },
    
    set_designModeCss: function(value)
    {
        this._designModeCss = value;
    },
    
    get_designModeBodyTagCssClass: function()
    {
        return this._designModeBodyTagCssClass;
    },
    
    set_designModeBodyTagCssClass: function(value)
    {
        this._designModeBodyTagCssClass = value;
    },
    
    get_baseUrl: function()
    {
        return this._baseUrl;
    },
    
    set_baseUrl: function(value)
    {
        this._baseUrl = value;
    },
    
    get_backColor: function()
    {
        return this._backColor;
    },
    
    set_backColor: function(value)
    {
        this._backColor = value;
    },
    
    get_editorForeColor: function()
    {
        return this._editorForeColor;
    },
    
    set_editorForeColor: function(value)
    {
        this._editorForeColor = value;
    },
    
    get_editorBackColor: function()
    {
        return this._editorBackColor;
    },
    
    set_editorBackColor: function(value)
    {
        this._editorBackColor = value;
    },
    
    get_toolbarColor: function()
    {
        return this._toolbarColor;
    },
    
    set_toolbarColor: function(value)
    {
        this._toolbarColor = value;
    },
    
    get_tabForeColor: function()
    {
        return this._tabForeColor;
    },
    
    set_tabForeColor: function(value)
    {
        this._tabForeColor = value;
    },
    
    get_tabBackColor: function()
    {
        return this._tabBackColor;
    },
    
    set_tabBackColor: function(value)
    {
        this._tabBackColor = value;
    },
    
    get_tabMouseOverColor: function()
    {
        return this._tabMouseOverColor;
    },
    
    set_tabMouseOverColor: function(value)
    {
        this._tabMouseOverColor = value;
    },
    
    get_tabbarBackColor: function()
    {
        return this._tabbarBackColor;
    },
    
    set_tabbarBackColor: function(value)
    {
        this._tabbarBackColor = value;
    },
    
    get_buttonMouseOverColor: function()
    {
        return this._buttonMouseOverColor;
    },
    
    set_buttonMouseOverColor: function(value)
    {
        this._buttonMouseOverColor = value;
    },
    
    get_buttonMouseOverBorderColor: function()
    {
        return this._buttonMouseOverBorderColor;
    },
    
    set_buttonMouseOverBorderColor: function(value)
    {
        this._buttonMouseOverBorderColor = value;
    },
    
    get_outputXHTML: function()
    {
        return this._outputXHTML;
    },
    
    set_outputXHTML: function(value)
    {
        this._outputXHTML = value;
    },
    
    get_convertDeprecatedSyntax: function()
    {
        return this._convertDeprecatedSyntax;
    },
    
    set_convertDeprecatedSyntax: function(value)
    {
        this._convertDeprecatedSyntax = value;
    },
    
    get_showModifiedAsterick: function()
    {
        return this._showModifiedAsterick;
    },
    
    set_showModifiedAsterick: function(value)
    {
        this._showModifiedAsterick = value;
    },
    
    get_allowedTags: function()
    {
        return this._allowedTags;
    },
    
    set_allowedTags: function(value)
    {
        this._allowedTags = value;
    },
    
    get_allowedAttributes: function()
    {
        return this._allowedAttributes;
    },
    
    set_allowedAttributes: function(value)
    {
        this._allowedAttributes = value;
    },
    
    get_formatHtmlMode: function()
    {
        return this._formatHtmlMode;
    },
    
    set_formatHtmlMode: function(value)
    {
        this._formatHtmlMode = value;
    },
    
    get_newLine: function()
    {
        return this._newLine;
    },
    
    set_newLine: function(value)
    {
        this._newLine = value;
    },
    
    get_modified: function()
    {
        return this._modified;
    },
    
    set_modified: function(value)
    {
        if (this._modified == value) return;
        if (value == false) this.StopTimer();

        this._modified = value;

        if (this.initialized) 
            this.SetTabLabels();
        
        this.raisePropertyChanged('modified');
    },
    
    IsCommandSupported: function(commandName)
    {
        try
        {
            this.designModeDocument.queryCommandEnabled(commandName);
            return true;
        }
        catch(e)
        {
            return false;
        }
    },
    
    IsDesignModeSet: function()
    {
        return this.designModeDocument.designMode.toLowerCase() == "on";
    },
    
    ExecuteCommand: function(commandName, commandValue)
    {
        if (!this.designMode) return;
        if (!this.designModeInitialized) return;
        if (!this.IsDesignModeSet()) return;
        
        this.designFocusDocument.focus();
        this.designModeDocument.execCommand(commandName, false, commandValue);
        this.StoreDesignEditor();
    },

    DialogBox: function(query, value)
    {
        return this.designMode ? prompt(query, value) : null;
    },

    DoBold: function()
    {
        this.ExecuteCommand('bold', null);
    },

    DoItalic: function()
    {
        this.ExecuteCommand('italic', null);
    },

    DoUnderline: function()
    {
        this.ExecuteCommand('underline', null);
    },

    DoLeft: function()
    {
        this.ExecuteCommand('justifyleft', null);
    },

    DoCenter: function()
    {
        this.ExecuteCommand('justifycenter', null);
    },

    DoRight: function()
    {
        this.ExecuteCommand('justifyright', null);
    },

    DoJustify: function()
    {
        this.ExecuteCommand('justifyfull', null);
    },

    DoOrdList: function()
    {
        this.ExecuteCommand('insertorderedlist', null);
    },

    DoBulList: function()
    {
        this.ExecuteCommand('insertunorderedlist', null);
    },

    DoIndent: function()
    {
        this.ExecuteCommand('indent', null);
    },

    DoOutdent: function()
    {
        this.ExecuteCommand('outdent', null);
    },

    DoForeCol: function()
    {
        var fCol = this.DialogBox('Enter foreground color:', '');
        if (fCol != null)
            this.ExecuteCommand('forecolor', fCol);
    },

    DoBgCol: function()
    {
        var bCol = this.DialogBox('Enter background color:', '');
        if (bCol != null)
        {
	        var commandName = this.isIE ? 'backcolor' : 'hilitecolor';
            this.ExecuteCommand(commandName, bCol);
        }
    },

    DoLink: function()
    {
        if (this.isFirefox)
        {
            var href = this.DialogBox('Enter the URL:', 'http://');
            if (href != null)
                this.ExecuteCommand('createlink', href);
        }
        else
        {
            this.ExecuteCommand('createlink');
        }
    },

    DoImage: function()
    {
        var imgSrc = this.DialogBox('Enter image location:', '');
        if (imgSrc != null)    
            this.ExecuteCommand('insertimage', imgSrc);
    },

    DoRule: function()
    {
        this.ExecuteCommand('inserthorizontalrule', null);
    },

    DoSubscript: function()
    {
        this.ExecuteCommand('subscript', null);
    },

    DoSuperscript: function()
    {
        this.ExecuteCommand('superscript', null);
    },

    DoFont: function(fontName)
    {
        if (fontName != '')
            this.ExecuteCommand('fontname', fontName);
    },

    DoSize: function(fontSize)
    {
        if (fontSize != '')
            this.ExecuteCommand('fontsize', fontSize);
    },

    DoFormat: function(formatType)
    {
        if (formatType != '')
            this.ExecuteCommand('formatblock', '<' + formatType + '>');  
    },
    
    GetHtmlTextEditor: function()
    {
        return this.htmlModeDocument.getElementById('htmlTextEditor');
    },
    
    GetInnerHtml: function()
    {
        if (this.designMode)
            return this.designModeDocument.body.innerHTML;
        else
            return this.GetHtmlTextEditor().value;
    },
    
    RecordHtml: function()
    {
        this.recordedHtml = this.GetInnerHtml();
        this.set_modified(false);
    },
    
    MouseOver: function(ctrl)
    {
        ctrl.style.borderColor = this.get_buttonMouseOverBorderColor();
        ctrl.style.backgroundColor = this.get_buttonMouseOverColor();
        ctrl.style.cursor = 'pointer';	
    },

    MouseOut: function(ctrl)
    {
        var bgColor = this.get_toolbarColor();

        ctrl.style.borderColor = bgColor;  
        ctrl.style.backgroundColor = bgColor;
    },

    SelectTab: function(designMode)
    {
        var designTab = $get(this.get_designTabID());
        var htmlTab = $get(this.get_htmlTabID());
        var selectedTab = designMode ? designTab : htmlTab;
        var unselectedTab = designMode ? htmlTab : designTab;

        selectedTab.style.fontWeight = "bold";        
        unselectedTab.style.fontWeight = "normal";        
        
        selectedTab.style.backgroundColor = this.get_toolbarColor();;        
        unselectedTab.style.backgroundColor = this.get_tabBackColor();;        
    },
    
    IsTabSelected: function(ctrl)
    {
        var designTab = this.get_designTabID() == ctrl.id;
        var htmlTab = !designTab;
        
        if (designTab && this.designMode) return true;
        if (htmlTab && !this.designMode) return true;
        
        return false;
    },
    
    TabOver: function(ctrl)
    {
        if (!this.IsTabSelected(ctrl))
            ctrl.style.backgroundColor = this.get_tabMouseOverColor();;        
    },

    TabOut: function(ctrl)
    {
        if (!this.IsTabSelected(ctrl))
            ctrl.style.backgroundColor = this.get_tabBackColor();;        
    },

    SetTabLabel: function(tab, isModified, selected)
    {
        var e = tab.getElementsByTagName("span")[0];
        var text = e.innerHTML;
        var hasAsterick = text.endsWith('*');
        var showAsterick = this.get_showModifiedAsterick();
        var addAsterick = selected == true && isModified == true;
        var removeAsterick = selected == false || isModified == false;

        if (hasAsterick && removeAsterick) e.innerHTML = text.slice(0,-1);
        if (addAsterick && showAsterick && !hasAsterick) e.innerHTML = text + '*';
    },
    
    SetTabLabels: function()
    {
        var isModified = this.get_modified();
        var designTab = $get(this.get_designTabID());
        var htmlTab = $get(this.get_htmlTabID());
        var selectedTab = this.designMode ? designTab : htmlTab;
        var unselectedTab = this.designMode ? htmlTab : designTab;

        this.SetTabLabel(selectedTab, isModified, true);
        this.SetTabLabel(unselectedTab, isModified, false);
    },
    
    ClientEncode: function(html)
    {
        html = html.replace(/&quot;/g,'&quotx;');
        html = html.replace(/"/g,'&quot;');
        html = html.replace(/&amp;/g,'&ampx;');
        html = html.replace(/&/g,'&amp;');
        html = html.replace(/&lt;/g,'&ltx;');
        html = html.replace(/</g,'&lt;');
        html = html.replace(/&gt;/g,'&gtx;');
        html = html.replace(/>/g,'&gt;');
        
        return html;
    },
    
    ClientDecode: function(html)
    {
        html = html.replace(/&gt;/g,'>');
        html = html.replace(/&gtx;/g,'&gt;');
        html = html.replace(/&lt;/g,'<');
        html = html.replace(/&ltx;/g,'&lt;');
        html = html.replace(/&amp;/g,'&');
        html = html.replace(/&ampx;/g,'&amp;');
        html = html.replace(/&quot;/g,'"');
        html = html.replace(/&quotx;/g,'&quot;');
        
        return html;
    },
    
    HtmlEncode: function(html)
    {
        var div = document.createElement('div');
        var text = document.createTextNode(html);
        div.appendChild(text);

        return div.innerHTML;
    },
    
    ParseRule: function(rule)
    {
        var cc = rule.split(':');
        var conditionList = cc[0].split(',');
        var conversionList = cc[1].split(',');
        
        var r = new Object();
        r.conditions = new Object();
        r.conversion = new Object();
        
        for (var i = 0; i < conditionList.length; i++)
        {
            var pv = conditionList[i].split('=');
            switch (pv[0])
            {
                case ("unique") :
                    r.conditions.unique = pv[1];
                    break;
                case ("direction") :
                    r.conditions.direction = pv[1];
                    break;
                case ("browser") :
                    r.conditions.browser = pv[1];
                    break;
                case ("tag") :
                    r.conditions.tag = pv[1];
                    break;
                case ("attribute") :
                    r.conditions.attribute = pv[1];
                    break;
                case ("attributeValue") :
                    r.conditions.attributeValue = pv[1];
                    break;
                case ("style") :
                    r.conditions.style = pv[1];
                    break;
                case ("styleValue") :
                    r.conditions.styleValue = pv[1];
                    break;
                default :
                    break;
            }
        }
        
        for (i = 0; i < conversionList.length; i++)
        {
            pv = conversionList[i].split('=');
            switch (pv[0])
            {
                case ("tag") :
                    r.conversion.tag = pv[1];
                    break;
                case ("attribute") :
                    r.conversion.attribute = pv[1];
                    break;
                case ("attributeValue") :
                    r.conversion.attributeValue = pv[1];
                    break;
                case ("style") :
                    r.conversion.style = pv[1];
                    break;
                case ("styleValue") :
                    r.conversion.styleValue = pv[1];
                    break;
                case ("conversionType") :
                    r.conversion.conversionType = pv[1];
                    break;
                default :
                    break;
            }
        }
        
        return r;
    },

    InitializeRules: function()
    {
        var rules = [
        "direction=to,tag=font,attribute=size:tag=span,style=font-size,conversionType=fontsize",
        "direction=to,tag=font,attribute=face:tag=span,style=font-family",
        "direction=to,tag=font,attribute=color:tag=span,style=color",
        "direction=from,browser=ie,tag=span,style=font-size:tag=font,attribute=size,conversionType=fontsize",
        "direction=from,browser=ie,tag=span,style=font-family:tag=font,attribute=face",
        "direction=from,browser=ie,tag=span,style=color:tag=font,style=color",
        "direction=from,browser=ff,tag=span,style=font-size:tag=font,attribute=size,conversionType=fontsize",
        "direction=to,tag=u:tag=span,style=text-decoration,styleValue=underline",
        "unique=true,browser=ie,direction=from,tag=span,style=text-decoration,styleValue=underline:tag=u",
        "browser=ie,direction=to,tag=blockquote,style=margin-right,styleValue=0px:tag=div,style=margin-left,styleValue=40px",
        "direction=to,tag=blockquote:tag=div",
        "browser=ie,direction=from,tag=div,style=margin-left,styleValue=40px:tag=blockquote,style=margin-right,styleValue=0px",
        "unique=true,browser=ie,direction=to,tag=p,attribute=align:tag=p,style=text-align",
        "direction=to,attribute=align:style=text-align",
        "unique=true,browser=ie,direction=from,tag=p,style=text-align:tag=p,attribute=align"
        ];
        
        this.conversionRules = new Array();
        
        for (var i = 0; i < rules.length; i++)
        {
            Array.add(this.conversionRules, this.ParseRule(rules[i]));
        }
    },
    
    InitializeLists: function()
    {
        this.noEndTags = "img,br,hr".split(',');
        this.blockTags = "p,div,blockquote,pre,br,hr,ul,ol,li,h1,h2,h3,h4,h5,h6,dd,dt,address".split(',');
        this.listTags = "ul,ol,dd".split(',');
        this.fontSizes = "1:xx-small;2:x-small;3:small;4:medium;5:large;6:x-large;7:xx-large".split(';');
        this.scriptableAttributes = "href,src".split(',');
    },
    
    IsNoEndTag: function(node)
    {
        return Array.contains(this.noEndTags, node.tagName.toLowerCase());
    },
    
    IsBlockTag: function(node)
    {
        return Array.contains(this.blockTags, node.tagName.toLowerCase());
    },
    
    IsListTag: function(node)
    {
        return Array.contains(this.listTags, node.tagName.toLowerCase());
    },
    
    IsScriptableAttribute: function(attributeName)
    {
        return Array.contains(this.scriptableAttributes, attributeName.toLowerCase());
    },

    IsAllowedTag: function(node)
    {
        return Array.contains(this.allowedTags, node.tagName.toLowerCase());
    },
    
    IsAllowedAttribute: function(attributeName)
    {
        return Array.contains(this.allowedAttributes, attributeName.toLowerCase());
    },
    
    IsParentTag: function(node, name)
    {
        node = node.parentNode;
        
        while (node)
        {
            if (node.nodeName.toLowerCase() == name)
                return true;
            
            node = node.parentNode;
        }
        
        return false;
    },

    RemoveAttributeScript: function(attributeValue)
    {
        var value = attributeValue.toLowerCase().trim();
        var j = value.indexOf("javascript");
        if (j < 0) return attributeValue;
        if (value.substr(j).indexOf(':') < 0) return attributeValue;
        if (this.isIE) value = decodeURIComponent(value);
        
        var valueParts = value.split(':');
        var len = valueParts.length - 1;
        for (var i = 0; i < len; i++)
        {
            if (valueParts[i].trim().endsWith("javascript"))
                return "javascript: void(0)";
        }

        return attributeValue;
    },
    
    FormatCssText: function(node)
    {
        var cssText = "";
        var rules = node.style.cssText.split(';');
        for (var i = 0; i < rules.length; i++)
        {
            var pv = rules[i].split(':')
            if (pv.length != 2) continue;
                
            if (cssText.length > 0) cssText += "; ";
            cssText += pv[0].trim().toLowerCase() + ": " + pv[1].trim();
        }
        
        return cssText;
    },
    
    LookUp: function(list, key, isKey)
    {
        var index = isKey ? 0 : 1;
        for (var i = 0; i < list.length; i++)
        {
            var kv = list[i].split(':');
            if (kv[index] == key) return kv[isKey ? 1 : 0];
        }
                
        return "";    
    },
    
    RuleDelimiter: function(cssText)
    {
        return cssText.length > 0 ? "; " : "";
    },    

    EncodeDoubleQuotes: function(s)
    {
        return s.replace(/"/g, '&#34;');
    },
    
    ReplaceEntityReferences: function(text)
    {
        text = text.replace(/\u0026/g,'&amp;');
        text = text.replace(/\u00A0/g,'&nbsp;');
        text = text.replace(/\u003C/g,'&lt;');
        text = text.replace(/\u003E/g,'&gt;');
        
        return text;
    },
    
    GetStyle: function(styles, index)
    {
        var pv = styles[index].split(':');
        if (pv.length != 2) return null;
        
        pv[0] = pv[0].trim();
        pv[1] = pv[1].trim();
        
        return pv;
    },
    
    FindStyle: function(cssText, property)
    {
        if (cssText.length == 0) return "";
        var styles = cssText.split(';');
        
        for (var i = 0; i < styles.length; i++)
        {
            var pv = this.GetStyle(styles, i);
            if (pv == null) continue;

            if (pv[0] == property) return pv[1];
        }
        
        return "";
    },
    
    HasStyle: function(cssText, property)
    {
        return this.FindStyle(cssText, property).length > 0 ? true : false;
    },

    AddStyle: function(cssText, addStyle)
    {
        if (addStyle.length == 0) return cssText;
        
        var pv = addStyle.split(':');
        if (this.HasStyle(cssText, pv[0])) return cssText;

        return cssText + this.RuleDelimiter(cssText) + addStyle;
    },
    
    AddStyles: function(cssText, list)
    {
        for (var i = 0; i < list.length; i++)
            cssText = this.AddStyle(cssText, list[i]);

        return cssText;
    },
    
    RemoveStyles: function(cssText, list)
    {
        var rules = cssText.split(';');
        var cssText = "";
        for (var i = 0; i < rules.length; i++)
        {
            var pv = rules[i].split(':')
            if (Array.contains(list, pv[0])) continue;
             
            if (cssText.length > 0) cssText += "; ";
            cssText += rules[i].trim();
        }
        
        return cssText;
    },
    
    AddAttributes: function(list)
    {
        var attributes = "";
        for (var i = 0; i < list.length; i++) attributes += " " + list[i];    
        
        return attributes;
    },
    
    AttributeCount: function(attributes)
    {
        var count = 0;
        for (var i = 0; i < attributes.length; i++)
        {
            if (attributes[i].specified) count++;
        }
        
        return count;
    },
    
    FindAttribute: function(attributes, name)
    {
        for (var i = 0; i < attributes.length; i++)
        {
            var attribute = attributes[i];
            if (attribute.specified && attribute.name.toLowerCase() == name)
                return attribute;
        }
        
        return null;
    },
    
    ConvertValue: function(conversionType, value, isKey)
    {
        switch (conversionType)
        {
            case "fontsize" :
                return this.LookUp(this.fontSizes, value, isKey);
                break;
            default :
                break;
        }
        
        return value;
    },
    
    AddConversionItem: function(conversions, type, value)
    {
        if (!conversions)
            conversions = new Object();
            
        switch (type)
        {
            case ("changeTagName") :
                if (!conversions.changeTagName) conversions.changeTagName = new Object();
                conversions.changeTagName = value;
                break;
            case ("addAttribute") :
                if (!conversions.addAttributes) conversions.addAttributes = new Array();
                if (!Array.contains(conversions.addAttributes, value))
                    Array.add(conversions.addAttributes, value);
                break;
            case ("removeAttribute") :
                if (!conversions.removeAttributes) conversions.removeAttributes = new Array();
                if (!Array.contains(conversions.removeAttributes, value))
                    Array.add(conversions.removeAttributes, value);
                break;
            case ("addStyle") :
                if (!conversions.addStyles) conversions.addStyles = new Array();
                if (!Array.contains(conversions.addStyles, value))
                    Array.add(conversions.addStyles, value);
                break;
            case ("removeStyle") :
                if (!conversions.removeStyles) conversions.removeStyles = new Array();
                if (!Array.contains(conversions.removeStyles, value))
                    Array.add(conversions.removeStyles, value);
                break;
            default :
                break;
        }

        return conversions;
    },
    
    AddConversionItems: function(conversions, rule, tagName, attributeValue, styleValue)
    {
        if (rule.conversion.tag && tagName != rule.conversion.tag)
            conversions = this.AddConversionItem(conversions, "changeTagName", rule.conversion.tag);
        
        if (rule.conversion.attribute && rule.conditions.style && styleValue.length > 0)
        {
            attributeValue = rule.conversion.attributeValue ? rule.conversion.attributeValue : styleValue;
            if (rule.conversion.conversionType) attributeValue = this.ConvertValue(rule.conversion.conversionType, attributeValue, false);

            conversions = this.AddConversionItem(conversions, "addAttribute", rule.conversion.attribute + '="' + this.EncodeDoubleQuotes(attributeValue) + '"');
            
            if (rule.conditions.attribute)
                conversions = this.AddConversionItem(conversions, "removeAttribute", rule.conditions.attribute);

            if (rule.conditions.style)
                conversions = this.AddConversionItem(conversions, "removeStyle", rule.conditions.style);
        }
        
        if (rule.conversion.style)
        {
            styleValue = rule.conversion.styleValue ? rule.conversion.styleValue : attributeValue;
            if (rule.conversion.conversionType) styleValue = this.ConvertValue(rule.conversion.conversionType, styleValue, true);

            conversions = this.AddConversionItem(conversions, "addStyle", rule.conversion.style + ": " + this.EncodeDoubleQuotes(styleValue));
            
            if (rule.conditions.style)
                conversions = this.AddConversionItem(conversions, "removeStyle", rule.conditions.style);

            if (rule.conditions.attribute)
                conversions = this.AddConversionItem(conversions, "removeAttribute", rule.conditions.attribute);
        }
        
        return conversions;
    },
    
    GetConversions: function(tagName, attributes, cssText, toXHTML)
    {
        var conversions = null;
        
        var direction = toXHTML ? "to" : "from";
        var browser = this.isIE ? "ie" : "ff";
        var attribute = null;
        var attributeValue = null;
        var style = null;
        var styleValue = null;
        var unique = false;

        for (var i = 0; i < this.conversionRules.length; i++)
        {
            var rule = this.conversionRules[i];
            if (rule.conditions.tag && rule.conditions.tag != tagName) continue;
            if (rule.conditions.direction != direction) continue;
            if (rule.conditions.browser && rule.conditions.browser != browser) continue;
            
            attributeValue = "";
            styleValue = "";
            unique = rule.conditions.unique && rule.conditions.unique == "true" ? true : false;
            
            if (rule.conditions.attribute)
            {
                attribute = this.FindAttribute(attributes, rule.conditions.attribute);
                if (!attribute) continue;
                
                attributeValue = attribute.value.trim();
                if (rule.conditions.attributeValue && rule.conditions.attributeValue != attributeValue.toLowerCase()) continue;
                if (unique && this.AttributeCount(attributes) != 1) continue;
                if (unique && cssText.length > 0) continue;
            }
            
            if (rule.conditions.style)
            {
                styleValue = this.FindStyle(cssText, rule.conditions.style).trim();
                if (styleValue.length == 0) continue;
                if (rule.conditions.styleValue && rule.conditions.styleValue != styleValue.toLowerCase()) continue;
                if (unique && cssText.split(';').length != 1) continue;
                if (unique && this.AttributeCount(attributes) != 1) continue;
            }
            
            conversions = this.AddConversionItems(conversions, rule, tagName, attributeValue, styleValue);
        }
        
        return conversions;
    },
    
    WriteHTMLAttributes: function(attributes, cssText, conversions)
    {
        var html = "";
        
        for (var i = 0; i < attributes.length; i++)
        {
            var attribute = attributes[i];
            if (attribute.specified)
            {
                var name = attribute.name.toLowerCase();
                if (!this.IsAllowedAttribute(name)) continue;
                if (name == 'style') continue;
                if (conversions && conversions.removeAttributes && Array.contains(conversions.removeAttributes, name)) continue;
                
                var value = this.EncodeDoubleQuotes(attribute.value);
                if (this.IsScriptableAttribute(name)) value = this.RemoveAttributeScript(value);
                
                html += " " + name + '="' + value + '"';
            }
        }
        
        if (conversions)
        {
            if (conversions.addStyles)
                cssText = this.AddStyles(cssText, conversions.addStyles);

            if (conversions.removeStyles)
                cssText = this.RemoveStyles(cssText, conversions.removeStyles);
            
            if (conversions.addAttributes)
                html += this.AddAttributes(conversions.addAttributes);
        }
                
        if (cssText.length > 0)
        {
            html += ' style="' + this.EncodeDoubleQuotes(cssText) + '"';
        }
        
        return html;
    },
    
    WriteHTMLTag: function(node, toXHTML)
    {
        var tagName = node.tagName.toLowerCase();
        var attributes = node.attributes;
        var cssText = this.FormatCssText(node);
        
        var conversions =  this.convertDeprecatedSyntax ? this.GetConversions(tagName, attributes, cssText, toXHTML) : null;
        if (conversions && conversions.changeTagName) tagName = conversions.changeTagName;
         
        var html = "<" + tagName;
        
        html += this.WriteHTMLAttributes(attributes, cssText, conversions);
            
        var innerHTML = this.WriteInnerHTML(node.childNodes, toXHTML);
        if ((innerHTML.length == 0) && (this.IsNoEndTag(node)))
        {
            html += " />";
        }
        else
        {
            var format = this.formatHtmlMode && toXHTML && this.IsListTag(node);
            html += ">" + (format ? this.newLine : "") + innerHTML + "</" + tagName + ">";
        }
        
        if (this.formatHtmlMode && toXHTML && this.IsBlockTag(node)) html += this.newLine;
        
        return html;
    },
    
    WriteInnerHTML: function(childNodes, toXHTML)
    {
        var html = "";
        var inPre = -1;
        
        for (var i = 0; i < childNodes.length; i++)
        {
            var node = childNodes[i];
            if ((node.nodeType == 1) && (this.IsAllowedTag(node)))
                html += this.WriteHTMLTag(node, toXHTML);
            else if (node.nodeType == 3)
            {
                if (inPre == -1) inPre = this.IsParentTag(node, "pre") ? 1 : 0;
                html += inPre == 1 ? this.ReplaceEntityReferences(node.nodeValue) : this.HtmlEncode(node.nodeValue);
            }
        }
        
        return html;
    },
    
    ReplaceDefaultTags: function(html, toXHTML)
    {
        if (this.formatHtmlMode)
        {
            while (html.endsWith(this.newLine))
                html = html.slice(0, -this.newLine.length);
        }

        var defaultTags = this.isIE ? "<p>&nbsp;</p>" : "<br />";
        var hasDefaultTags = html.endsWith(defaultTags);

        if (!toXHTML)
        {
            if (!hasDefaultTags && !this.isIE) html += defaultTags;
        }
        else
        {
            if (hasDefaultTags) html = html.slice(0, -defaultTags.length);
        }
            
        return html;
    },
    
    ConvertHTML: function(html, toXHTML)
    {
        var div = document.createElement('div');
        div.innerHTML = html;
        
        html = this.WriteInnerHTML(div.childNodes, toXHTML);
        html = this.ReplaceDefaultTags(html, toXHTML);
        
        return html;
    },
    
    GetDecodedHtml: function()
    {
        var htmlencodedText = $get(this.get_htmlencodedTextID());
        return this.ClientDecode(htmlencodedText.value);
    },

    CheckModified: function()
    {
        var html = this.GetInnerHtml();
        if (html != this.recordedHtml) this.set_modified(true);
    },
    
    StoreHtml: function(html)
    {
        this.innerHTML = html;
        if (this._modified == false && html != this.recordedHtml) this.set_modified(true);
    },
    
    CopyHtmlToDesign: function()
    {
        var html = this.innerHTML;
        if (this.outputXHTML) html = this.ConvertHTML(html, false);
        if (html.length == 0 && this.isFirefox) html = "<br />";

        this.designModeDocument.body.innerHTML = html;
    },

    CopyDesignToHtml: function()
    {
        this.StoreHtml(this.designModeDocument.body.innerHTML);
    },
    
    CopyHtmlEditorToHtml: function()
    {
        this.StoreHtml(this.GetHtmlTextEditor().value);
    },
    
    CopyHtmlToHtmlEditor: function()
    {
        this.GetHtmlTextEditor().value = this.outputXHTML ? this.ConvertHTML(this.innerHTML, true) : this.innerHTML;
    },

    SetCursor: function(wait)
    {
        var switchMode = this.designMode ? "Html" : "Design";
        var tab = null;
        
        switch (switchMode)
        {
            case "Html" :
                tab = $get(this.get_htmlTabID());
                break;
            case "Design" :
                tab = $get(this.get_designTabID());
                break;
            default :
                return;
        }

        tab.style.cursor = wait ? "wait" : "pointer"; 
    },
    
    DisplayWait: function(wait)
    {
        this.SetCursor(wait);
    },

    ShowToolbar: function(toolbar, show)
    {
        var imgList = toolbar.getElementsByTagName('img');
        var selectList = toolbar.getElementsByTagName('select');
        
        var opacity = show ? "1.0" : ".40";
        var opacityIE = "alpha(opacity=" + (show ? "100" : "40") + ")";
        
        for (var i = 0; i < imgList.length; i++)
        {
            if (imgList[i].alt.length == 0) continue;
            
            if (this.isIE)
                imgList[i].style.filter = opacityIE;
            else
                imgList[i].style.opacity = opacity;

            imgList[i].disabled = show ? false : true;
        }
        
        for (var i = 0; i < selectList.length; i++)
        {
            if (this.isIE)
                selectList[i].style.filter = opacityIE;
            else
                selectList[i].style.opacity = opacity;
            
            selectList[i].disabled = show ? false : true;
        }
    },

    ShowToolbars: function(show)
    {
        var dropdownToolbar = $get(this.get_dropdownToolbarID());
        var buttonToolbar = $get(this.get_buttonToolbarID());
        
        this.ShowToolbar(dropdownToolbar, show);
        this.ShowToolbar(buttonToolbar, show);
    },

    SwitchMode: function(mode)
    {
        if (mode == "Design" && this.designMode) return;
        if (mode == "Html" && !this.designMode) return;

        var f = null;

        switch (mode)
        {
            case "Html" :
                f = this.GoToHtmlMode;
                break;
            case "Design" :
                f = this.GoToDesignMode;
                break;
            default :
                return;
        }

        this.DisplayWait(true);
        this.TimeoutInvoke(f);
    },
    
    GoToHtmlMode: function()
    {
        if (!this.designMode) return;
        
        var isModified = this._modified;
        this.CopyHtmlToHtmlEditor();
        
    	if (this.isFirefox && this.designModeInitialized)
	    	this.SetDesignMode(false);
	    	
	    this.ShowHtmlEditor(true);
	    this.ShowDesignEditor(false);
	    this.SelectTab(false);
	    this.ShowToolbars(false);
        this.DisplayWait(false);

	    this.designMode = false;

	    if (!isModified) this.RecordHtml();
	    this.SetTabLabels();
    },
    
    GoToDesignMode: function()
    {
        if (this.designMode) return;
        
        var isModified = this._modified;
        this.CopyHtmlToDesign();
    	
	    this.ShowDesignEditor(true);
	    this.ShowHtmlEditor(false);
	    this.SelectTab(true);
	    this.ShowToolbars(true);
        this.DisplayWait(false);
	    
        if (this.isFirefox && this.designModeInitialized)
    	{
	    	if (this.SetDesignMode(true))
    	        this.designModeDocument.execCommand(this.cssCommand, false, true);
    	}
    	
    	this.designMode = true;

	    if (!isModified) this.RecordHtml();
	    this.SetTabLabels();
    },
    
    ShowDesignEditor: function(show)
    {
        this.ShowElement(this.designArea, show, false);
    },

    ShowHtmlEditor: function(show)
    {
        this.ShowElement(this.htmlArea, show, false);
    },

    ShowElement: function(e, show, inline)
    {
        e.style.display = show == false ? "none" : inline ? "inline" : "block";
    },
    
    TimeoutInvoke: function(f)
    {
        f = Function.createDelegate(this, f);
        window.setTimeout(f, 100);
    },
        
    InitializeHTML: function()
    {
        this.outputXHTML = this.get_outputXHTML();
        this.convertDeprecatedSyntax = this.get_convertDeprecatedSyntax();
        this.allowedTags = this.get_allowedTags().split(',');
        this.allowedAttributes = this.get_allowedAttributes().split(',');
        this.formatHtmlMode = this.isIE && this.get_formatHtmlMode();
        this.newLine = this.get_newLine();
        this.InitializeLists();
        this.InitializeRules();
        
        var html = this.ClientDecode($get(this.get_htmlencodedTextID()).value);
        this.StoreHtml(this.outputXHTML ? this.ConvertHTML(html, false) : html); 
    },
    
    GetInitialHtmlEditorOuterHTML: function()
    {
        var designFrame = $get(this.get_designEditorID());
        var h = designFrame.height - 20;
        var w = designFrame.width - 20;
        var rows = "";
        var cols = "";
        
        var outerHTML = 
            "<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Transitional//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'>" +
            "<html xmlns='http://www.w3.org/1999/xhtml'>" + 
            "<head>" + 
            "<style type='text/css'>" + 
            "body {margin:0; padding:0;}" +
            "</style>" + 
            "</head>" + 
            "<body>" + 
            "<form>" + 
            "<textarea id='htmlTextEditor' style='overflow:auto; font-family:Courier New; font-size:10pt; border:0; margin:0; position: absolute; left: 10px; top:10px; width:" + w + "px; " + "height:" + h + "px;" + "' rows='" +
            rows + "' cols='" + cols + "'>" +
            "</textarea>" +
            "</form>" + 
            "</body>" + 
            "</html>";
            
        return outerHTML;
    },

    GetInitialDesignEditorInnerHTML: function()
    {
        var html = this.innerHTML;
        if (html.length == 0 && this.isFirefox) html = "<br />";
        
        return html;
    },
    
    SetInitialDesignEditorInnerHtml: function()
    {
        this.designModeDocument.body.innerHTML = this.GetInitialDesignEditorInnerHTML();
    },
    
    GetInitialDesignEditorOuterHTML: function()
    {
        var outerHTML = 
            "<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Transitional//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'>" +
            "<html xmlns='http://www.w3.org/1999/xhtml'>" +
            "<head>" + 
            "<title>Design Editor Frame</title>" + 
            ((this.designModeCss) ? "<link rel='stylesheet' href='" + this.designModeCss + "' type='text/css' />" : "") + 
            ((this.baseUrl) ? "<base href='" + this.baseUrl + "' />" : "") + 
            "</head>" + 
            "<body" + ((this.designModeBodyTagCssClass) ? " class='" + this.designModeBodyTagCssClass + "'" : "") + ">" + 
                "" +
            "</body>" + 
            "</html>";
            
        return outerHTML;
    },
    
    SetDesignMode: function(on)
    {
        var setting = on ? "On" : "Off";

        try
        {
            this.designModeDocument.designMode = setting;
            this.designModeInitialized = true;
        }
        catch(e)
        {
            this.designModeInitialized = false;
        }
        
        return this.designModeInitialized;
    },
    
    InitializeDesignMode: function()
    {
        if (!this.SetDesignMode(true)) return;
        
        if (this.isFirefox)
        {
            this.cssCommand = "useCSS";
            if (this.IsCommandSupported("styleWithCSS")) this.cssCommand = "styleWithCSS";
            this.designModeDocument.execCommand(this.cssCommand, false, true);
        }
    },

    InitializeEditor: function()
    {
        this.isIE = Sys.Browser.agent == Sys.Browser.InternetExplorer;
        this.isFirefox = !this.isIE;
        this.designMode = true;
        this.htmlEditor = this.isIE ? $get(this.get_htmlEditorID()) :
                                      $get(this.get_htmlEditorID()).contentWindow;
        this.designEditor = this.isIE ? $get(this.get_designEditorID()) :
                                        $get(this.get_designEditorID()).contentWindow;

        this.htmlArea = $get(this.get_htmlAreaID());
        this.designArea = $get(this.get_designAreaID());
        
        if (this.isFirefox)
        {  
            this.htmlModeDocument = this.htmlEditor.document;
            this.designModeDocument = this.designEditor.document;
        } 
        else
        {
            this.htmlModeDocument = this.htmlEditor.contentWindow.document;
            this.designModeDocument = this.designEditor.contentWindow.document;
        }
        
        this.designFocusDocument = this.isIE ? this.designModeDocument :
                                               this.designEditor;
        
        this.InitializeHTML();
        
        this.designModeDocument.open("text/html", "replace");
        this.designModeDocument.write(this.GetInitialDesignEditorOuterHTML());
        this.designModeDocument.close();

        this.htmlModeDocument.open("text/html", "replace");
        this.htmlModeDocument.write(this.GetInitialHtmlEditorOuterHTML());
        this.htmlModeDocument.close();
        
        this.InitializeDesignMode();
        
        this.TimeoutInvoke(this.PostDesignModeDocumentCreate);

        this.endRequestHandler = Function.createDelegate(this, this.OnUpdateHtml);
        Sys.WebForms.PageRequestManager.getInstance().add_endRequest(this.endRequestHandler);
    },
    
    DisposeEditor: function()
    {
        Sys.WebForms.PageRequestManager.getInstance().remove_endRequest(this.endRequestHandler);
        this.endRequestHandler = null;

        this.ClearEventHandlers();
    },
    
    initialize: function()
    {
        Winthusiasm.HtmlEditor.callBaseMethod(this, 'initialize');
        
        this.InitializeEditor();
        this.initialized = true;
    },
    
    dispose: function()
    {
        this.StopTimer();
        this.DisposeEditor();

        Winthusiasm.HtmlEditor.callBaseMethod(this, 'dispose');
    },
    
    PostDesignModeDocumentCreate: function()
    {
        this.SetInitialDesignEditorInnerHtml();
        this.RecordHtml();
        this.InitializeEventHandlers();
    },
    
    InitializeEventHandlers: function()
    {
        this.designModeFocusElement = this.isIE ? this.designEditor : this.designModeDocument;
        this.htmlModeFocusElement = this.isIE ? this.htmlEditor : this.htmlModeDocument;
        
        this.onDesignEditorBlurHandler = Function.createDelegate(this, this.StoreDesignEditor);
        this.onHtmlEditorBlurHandler = Function.createDelegate(this, this.StoreHtmlEditor);

        $addHandler(this.designModeFocusElement, 'blur', this.onDesignEditorBlurHandler);
        $addHandler(this.htmlModeFocusElement, 'blur', this.onHtmlEditorBlurHandler);

        this.onEditorFocusHandler = Function.createDelegate(this, this.OnEditorFocus);
        $addHandler(this.designModeFocusElement, 'focus', this.onEditorFocusHandler);
        $addHandler(this.htmlModeFocusElement, 'focus', this.onEditorFocusHandler);
        
        if (this.isFirefox)
        {
            this.onDesignEditorKeypressHandler = Function.createDelegate(this, this.OnDesignEditorKeyEvent);
            $addHandler(this.designModeFocusElement, 'keypress', this.onDesignEditorKeypressHandler);

            this.onDesignEditorMousedownHandler = Function.createDelegate(this, this.OnDesignEditorMouseEvent);
            $addHandler(this.designModeFocusElement, 'mousedown', this.onDesignEditorMousedownHandler);
        }
        else if (this.isIE)
        {
            this.onDesignEditorKeydownHandler = Function.createDelegate(this, this.OnDesignEditorKeyEvent);
            this.designModeDocument.body.attachEvent("onkeydown", this.onDesignEditorKeydownHandler);
        }
    },

    ClearEventHandlers: function()
    {
        if (this.isIE)
        {
            this.designModeDocument.body.detachEvent('onkeydown', this.onDesignEditorKeydownHandler);
            this.onDesignEditorKeydownHandler = null;
        }
        else if (this.isFirefox)
        {
            $removeHandler(this.designModeFocusElement, 'mousedown', this.onDesignEditorMousedownHandler);
            this.onDesignEditorMousedownHandler = null;

            $removeHandler(this.designModeFocusElement, 'keypress', this.onDesignEditorKeypressHandler);
            this.onDesignEditorKeypressHandler = null;
        }

        $removeHandler(this.htmlModeFocusElement, 'focus', this.onEditorFocusHandler);
        $removeHandler(this.designModeFocusElement, 'focus', this.onEditorFocusHandler);
        this.onEditorFocusHandler = null;
        
        $removeHandler(this.designModeFocusElement, 'blur', this.onDesignEditorBlurHandler);
        this.onDesignEditorBlurHandler = null;
        
        $removeHandler(this.htmlModeFocusElement, 'blur', this.onHtmlEditorBlurHandler);
        this.onHtmlEditorBlurHandler = null;
    },

    OnTimerTick: function()
    {
        if (!this._modified) this.CheckModified();
    },
    
    StartTimer: function()
    {
        if (this.timer == null)
        {
            var interval = 2000;
            this.timer = window.setInterval(Function.createDelegate(this, this.OnTimerTick), interval);
        }
    },
    
    StopTimer: function()
    {
        if (this.timer != null)
        {
            window.clearInterval(this.timer);
            this.timer = null;
        }
    },
        
    PreventDefault: function(event)
    {
        if (this.isIE)
            event.returnValue = false;
        else
            event.preventDefault();
    },
    
    StopPropagation: function(event)
    {
        if (this.isIE)
            event.cancelBubble = true;
        else
            event.stopPropagation();
    },
    
    OnDesignEditorKeyEvent: function(event)
    {
        var e = event || window.event;
        var code = e.charCode || e.keyCode;
        
        if (event.ctrlKey && !event.altKey && !event.shiftKey)
        {
            var commandName = "";
            switch (String.fromCharCode(code).toLowerCase())
            {
                case 'b' :
                    commandName = "bold";
                    break;
                case 'i' :
                    commandName = "italic";
                    break;
                case 'u' :
                    commandName = "underline";
                    break;
                default :
                    return;
            }
            
            this.PreventDefault(e);
            this.StopPropagation(e);
            
            this.ExecuteCommand(commandName, null);
        }
    },
    
    OnDesignEditorMouseEvent: function(event)
    {
        if (this.initialized && !this.designModeInitialized)
        {
            this.InitializeDesignMode();
        }
    },
        
    OnEditorFocus: function()
    {
        if (this.designMode &&  !this.designModeInitialized)
            this.InitializeDesignMode();

        if (this._modified == false && this.timer == null) this.StartTimer();
    },
    
    StoreDesignEditor: function()
    {
        this.StopTimer();
        this.CopyDesignToHtml();
    },

    StoreHtmlEditor: function()
    {
        this.StopTimer();
        this.CopyHtmlEditorToHtml();
    },
    
    UpdateHtml: function()
    {
        var html = this.ClientDecode($get(this.get_htmlencodedTextID()).value); 
        this.StoreHtml(html); 

        if (this.designMode)
            this.CopyHtmlToDesign();
        else
            this.CopyHtmlToHtmlEditor();
            
        this.RecordHtml();
    },
    
    IsDocumentLoaded: function()
    {
        if (this.designMode)
            return this.designModeDocument.body != null;
        else
            return this.htmlModeDocument.body != null;
    },
    
    OnUpdateHtml: function(sender, args)
    {
        var dataItem = args.get_dataItems()[this.get_htmlencodedTextID()];
        if (dataItem && this.initialized)
        {
            if (this.IsDocumentLoaded())
                this.UpdateHtml();
        }
    }
}

Winthusiasm.HtmlEditor.descriptor = 
{
    properties: [ {name: 'htmlencodedTextID', type: String },
                  {name: 'htmlEditorID', type: String },
                  {name: 'designEditorID', type: String },
                  {name: 'htmlAreaID', type: String },
                  {name: 'designAreaID', type: String },
                  {name: 'htmlTabID', type: String },
                  {name: 'designTabID', type: String },
                  {name: 'dropdownToolbarID', type: String },
                  {name: 'buttonToolbarID', type: String },
                  {name: 'designModeCss', type: String },
                  {name: 'designModeBodyTagCssClass', type: String },
                  {name: 'baseUrl', type: String },
                  {name: 'backColor', type: String },
                  {name: 'editorForeColor', type: String },
                  {name: 'editorBackColor', type: String },
                  {name: 'toolbarColor', type: String },
                  {name: 'tabForeColor', type: String },
                  {name: 'tabBackColor', type: String },
                  {name: 'tabMouseOverColor', type: String },
                  {name: 'tabbarBackColor', type: String },
                  {name: 'buttonMouseOverColor', type: String },
                  {name: 'buttonMouseOverBorderColor', type: String },
                  {name: 'outputXHTML', type: Boolean },
                  {name: 'convertDeprecatedSyntax', type: Boolean },
                  {name: 'showModifiedAsterick', type: Boolean },
                  {name: 'allowedTags', type: String },
                  {name: 'allowedAttributes', type: String },
                  {name: 'formatHtmlMode', type: Boolean },
                  {name: 'newLine', type: String } ]
}

Winthusiasm.HtmlEditor.registerClass("Winthusiasm.HtmlEditor", Sys.UI.Control);

if(typeof(Sys)!=='undefined')Sys.Application.notifyScriptLoaded();