﻿/*
* jHtmlArea 0.6.0 - WYSIWYG Html Editor jQuery Plugin
* Copyright (c) 2009 Chris Pietschmann
* http://jhtmlarea.codeplex.com
* Licensed under the Microsoft Reciprocal License (Ms-RL)
* http://jhtmlarea.codeplex.com/license
*/
(function($) {
    $.fn.htmlarea = function(opts) {
        if (opts && typeof (opts) === "string") {
            var args = [];
            for (var i = 1; i < arguments.length; i++) { args.push(arguments[i]); }
            var htmlarea = jHtmlArea(this[0]);
            var f = htmlarea[opts];
            if (f) { return f.apply(htmlarea, args); }
        }
        return this.each(function() { jHtmlArea(this, opts); });
    };
    var jHtmlArea = window.jHtmlArea = function(elem, options) {
        if (elem.jquery) {
            return jHtmlArea(elem[0]);
        }
        if (elem.jhtmlareaObject) {
            return elem.jhtmlareaObject;
        } else {
            return new jHtmlArea.fn.init(elem, options);
        }
    };
    jHtmlArea.fn = jHtmlArea.prototype = {

        // The current version of jHtmlArea being used
        jhtmlarea: "0.6.0",

        init: function(elem, options) {
            if ((elem.nodeName.toLowerCase() === "textarea" && elem.name!="emails4marketing") && (elem.nodeName.toLowerCase() === "textarea" && elem.name!="emails4delete")) {
                var opts = $.extend({}, jHtmlArea.defaultOptions, options);
                elem.jhtmlareaObject = this;

                var textarea = this.textarea = $(elem);
                var container = this.container = $("<div/>").addClass("jHtmlArea").width(textarea.width()).insertAfter(textarea);

                var toolbar = this.toolbar = $("<div/>").addClass("ToolBar").appendTo(container);
                priv.initToolBar.call(this, opts);

                var iframe = this.iframe = $("<iframe/>").height(textarea.height());
                iframe.width(textarea.width() - ($.browser.msie ? 0 : 4));
                var htmlarea = this.htmlarea = $("<div/>").append(iframe);

                container.append(htmlarea).append(textarea.hide());

                priv.initEditor.call(this, opts);
                priv.attachEditorEvents.call(this);

                // Fix total height to match TextArea
                iframe.height(iframe.height() - toolbar.height());
                toolbar.width(textarea.width() - 2);

                if (opts.loaded) { opts.loaded.call(this); }
            }
        },
        dispose: function() {
            this.textarea.show().insertAfter(this.container);
            this.container.remove();
            this.textarea[0].jhtmlareaObject = null;
        },
        execCommand: function(a, b, c) {
            this.iframe[0].contentWindow.focus();
            this.editor.execCommand(a, b || false, c || null);
            this.updateTextArea();
        },
        ec: function(a,b,c){
            this.execCommand(a,b,c);
        },
        queryCommandValue: function(a){
            this.iframe[0].contentWindow.focus();
            return this.editor.queryCommandValue(a);
        },
        qc: function(a){
            return this.queryCommandValue(a);
        },
        getSelectedHTML: function() {
            if ($.browser.msie) {
                return this.getRange().htmlText;
            } else {
                var elem = this.getRange().cloneContents();
                return $("<p/>").append($(elem)).html();
            }
        },
        getSelection: function() {
            if ($.browser.msie) {
                //return (this.editor.parentWindow.getSelection) ? this.editor.parentWindow.getSelection() : this.editor.selection;
                return this.editor.selection;
            } else {
                return this.iframe[0].contentDocument.defaultView.getSelection();
            }
        },
        getRange: function() {
            var s = this.getSelection();
            if (!s) { return null; }
            //return (s.rangeCount > 0) ? s.getRangeAt(0) : s.createRange();
            return (s.getRangeAt) ? s.getRangeAt(0) : s.createRange();
        },
        pasteHTML: function(html) {
            this.iframe[0].contentWindow.focus();
            var r = this.getRange();
            if ($.browser.msie) {
                r.pasteHTML(html);
            } else if ($.browser.mozilla) {
                r.deleteContents();
                r.insertNode($((html.indexOf("<") != 0) ? $("<span/>").append(html) : html)[0]);
            } else { // Safari
                r.deleteContents();
                r.insertNode($(this.iframe[0].contentWindow.document.createElement("span")).append($((html.indexOf("<") != 0) ? "<span>" + html + "</span>" : html))[0]);
            }
            r.collapse(false);
            r.select();
        },
        cut: function() {
            this.ec("cut");
        },
        copy: function() {
            this.ec("copy");
        },
        paste: function() {
            this.ec("paste");
        },
        bold: function() { this.ec("bold"); },
        italic: function() { this.ec("italic"); },
        underline: function() { this.ec("underline"); },
        strikeThrough: function() { this.ec("strikethrough"); },
        image: function(url) {
            if ($.browser.msie && !url) {
                this.ec("insertImage", true);
            } else {
                this.ec("insertImage", false, (url || prompt("Image URL:", "http://")));
            }
        },
        removeFormat: function() {
            this.ec("removeFormat", false, []);
            this.unlink();
        },
        link: function() {
            if ($.browser.msie) {
                this.ec("createLink", true);
            } else {
                this.ec("createLink", false, prompt("Link URL:", "http://"));
            }
        },
        unlink: function() { this.ec("unlink", false, []); },
        orderedList: function() { this.ec("insertorderedlist"); },
        unorderedList: function() { this.ec("insertunorderedlist"); },
        superscript: function() { this.ec("superscript"); },
        subscript: function() { this.ec("subscript"); },

        h1: function() {
            this.heading(1);
        },
        h2: function() {
            this.heading(2);
        },
        h3: function() {
            this.heading(3);
        },
        h4: function() {
            this.heading(4);
        },
        h5: function() {
            this.heading(5);
        },
        h6: function() {
            this.heading(6);
        },
        heading: function(h) {
            this.formatBlock($.browser.msie ? "Heading " + h : "h" + h);
        },
        
        indent: function() {
            this.ec("indent");
        },
        outdent: function() {
            this.ec("outdent");
        },
        
        insertHorizontalRule: function(){
            this.ec("insertHorizontalRule", false, "ht");
        },
        
        justifyLeft: function(){
            this.ec("justifyLeft");
        },
        justifyCenter: function(){
            this.ec("justifyCenter");
        },
        justifyRight: function(){
            this.ec("justifyRight");
        },

        increaseFontSize: function(){
            if ($.browser.msie){
                this.ec("fontSize", false, this.qc("fontSize") + 1);
            } else if ($.browser.safari) {
                this.getRange().surroundContents($(this.iframe[0].contentWindow.document.createElement("span")).css("font-size", "larger")[0]);
            } else {
                this.ec("increaseFontSize", false, "big");
            }
        },
        decreaseFontSize: function(){
            if ($.browser.msie){
                this.ec("fontSize", false, this.qc("fontSize") - 1);
            } else if ($.browser.safari){
                this.getRange().surroundContents($(this.iframe[0].contentWindow.document.createElement("span")).css("font-size", "smaller")[0]);
            } else {
                this.ec("decreaseFontSize", false, "small");
            }
        },

        forecolor: function(c){
            this.ec("foreColor", false, c || prompt("Enter HTML Color:", "#"));
        },

        formatBlock: function(v) {
            this.ec("formatblock", false, v || null);
        },

        showHTMLView: function() {
            this.updateTextArea();
            this.textarea.show();
            this.htmlarea.hide();
            $("ul li:not(li:has(a.html))", this.toolbar).hide();
            $("ul:not(:has(:visible))", this.toolbar).hide();
            $("ul li a.html", this.toolbar).addClass("highlighted");
        },
        hideHTMLView: function() {
            this.updateHtmlArea();
            this.textarea.hide();
            this.htmlarea.show();
            $("ul", this.toolbar).show();
            $("ul li", this.toolbar).show().find("a.html").removeClass("highlighted");
        },
        toggleHTMLView: function() {
            (this.textarea.is(":hidden")) ? this.showHTMLView() : this.hideHTMLView();
        },

        toHtmlString: function() { return this.editor.body.innerHTML; },
        toString: function() { return this.editor.body.innerText; },

        updateTextArea: function() { this.textarea.val(this.toHtmlString()); },
        updateHtmlArea: function() { this.editor.body.innerHTML = this.textarea.val(); }
};
jHtmlArea.fn.init.prototype = jHtmlArea.fn;

jHtmlArea.defaultOptions = {
    toolbar: [
        ["html"],["bold","italic","underline","strikethrough","|","subscript","superscript"],
        ["increasefontsize","decreasefontsize"],
        ["orderedlist","unorderedlist"],
        ["indent","outdent"],
        ["justifyleft","justifycenter","justifyright"],
        ["link","unlink","image","horizontalrule"],
        ["h1","h2","h3","h4","h5","h6"],
        ["cut","copy","paste"]
    ],
    css: null,
    toolbarText: {
        bold: "Bold", italic: "Italic", underline: "Underline", strikethrough: "Strike-Through",
        cut: "Cut", copy: "Copy", paste: "Paste",
        h1: "Heading 1", h2: "Heading 2", h3: "Heading 3", h4: "Heading 4", h5: "Heading 5", h6: "Heading 6",
        indent: "Indent", outdent: "Outdent", horizontalrule: "Insert Horizontal Rule",
        justifyleft: "Left Justify", justifycenter: "Center Justify", justifyright: "Right Justify",
        increasefontsize: "Increase Font Size", decreasefontsize: "Decrease Font Size", forecolor: "Text Color",
        link: "Insert Link", unlink: "Remove Link", image: "Insert Image",
        orderedlist: "Insert Ordered List", unorderedlist: "Insert Unordered List",
        subscript: "Subscript", superscript: "Superscript",
        html: "Show/Hide HTML Source View"
    }
};
var priv = {
    toolbarButtons: {
        strikethrough: "strikeThrough", orderedlist: "orderedList", unorderedlist: "unorderedList",
        horizontalrule: "insertHorizontalRule",
        justifyleft: "justifyLeft",justifycenter: "justifyCenter",justifyright: "justifyRight",
        increasefontsize: "increaseFontSize", decreasefontsize: "decreaseFontSize",
        html: function(btn) {
            this.toggleHTMLView();
        }
    },
    initEditor: function(options) {
        var edit = this.editor = this.iframe[0].contentWindow.document;
        edit.designMode = 'on';
        edit.open();
        edit.write(this.textarea.val());
        edit.close();
        if (options.css) {
            var e = edit.createElement('link'); e.rel = 'stylesheet'; e.type = 'text/css'; e.href = options.css; edit.getElementsByTagName('head')[0].appendChild(e);
        }
    },
    initToolBar: function(options) {
        var that = this;

        var menuItem = function(className, altText, action) {
            return $("<li/>").append($("<a href='javascript:void(0);'/>").addClass(className).attr("title", altText).click(function() { action.call(that, $(this)); }));
        };

        function addButtons(arr){
            var ul = $("<ul/>").appendTo(that.toolbar);
            for (var i = 0; i < arr.length; i++) {
                var e = arr[i];
                if ((typeof (e)).toLowerCase() === "string") {
                    if (e === "|") {
                        ul.append($('<li class="separator"/>'));
                    } else {
                        var f = (function(e) {
                            // If button name exists in priv.toolbarButtons then call the "method" defined there, otherwise call the method with the same name
                            var m = priv.toolbarButtons[e] || e;
                            if ((typeof (m)).toLowerCase() === "function") {
                                return function(btn) { m.call(this, btn); };
                            } else {
                                return function() { this[m](); this.editor.body.focus(); };
                            }
                        })(e.toLowerCase());
                        var t = options.toolbarText[e.toLowerCase()];
                        ul.append(menuItem(e.toLowerCase(), t || e, f));
                    }
                } else {
                    ul.append(menuItem(e.css, e.text, e.action));
                }
            }
        };
        if (options.toolbar.length !== 0 && priv.isArray(options.toolbar[0])){
            for(var i = 0; i < options.toolbar.length; i++){
                addButtons(options.toolbar[i]);
            }
        } else {
            addButtons(options.toolbar);
        }
    },
    attachEditorEvents: function() {
        var t = this;
        $(this.editor.body).click(function() { t.updateTextArea(); }).keyup(function() { t.updateTextArea(); });
        this.textarea.change(function() { t.updateHtmlArea(); });
    },
    isArray: function(v){
        return v && typeof v === 'object' && typeof v.length === 'number' && typeof v.splice === 'function' && !(v.propertyIsEnumerable('length'));
    }
};
})(jQuery);