﻿//============================================================================
//  CwikContentEditor.js
//----------------------------------------------------------------------------
//  Copyright © 2009 Sovenix, Inc.  All rights reserved.
//   - Updated March 12, 2008
//============================================================================

var currentCwikEditor = null;

function CwikContentEditor (parms)
{
    this.constructor (parms);
}

CwikContentEditor.prototype.constructor = function (parms)
{
    this.offsetLeft       = 0;
    this.offsetTop        = 0;
    this.left             = null;
    this.top              = null;
    this.mouseDown        = false;
    this.globalBookmark   = null;
    
    this.elementMain      = document.getElementById (parms.mainClientID);
    this.elementDefault   = document.getElementById (parms.defectoClientID);
    this.elementValue     = document.getElementById (parms.valorClientID);
    this.elementKeywords  = document.getElementById (parms.keywordsClientID);
    
    this.iconPath         = parms.iconPath;
    this.popupPath        = parms.popupPath;
    this.styleList        = parms.styleList;
    this.postBackFunction = parms.postBackFunction;
    this.saveFunction     = parms.saveFunction;
    this.toolboxTitle     = parms.toolboxTitle;
    
    this.elementToolbox = this.createToolbox ();
    
    this.elementDefault.value = escape(this.elementMain.innerHTML);
    this.elementValue.value   = escape(this.elementMain.innerHTML);
    
    this.elementHTML                  = document.createElement ("TEXTAREA");
    this.elementHTML.style.height     = "200px";
    this.elementHTML.style.width      = "100%";
    this.elementHTML.style.padding    = "0";
    this.elementHTML.style.fontFamily = "Courier New";
    this.elementHTML.style.fontSize   = "9pt";
    this.elementHTML.style.border     = "solid white 1px";
    this.elementHTML.style.display    = "none";
    
    document.body.insertBefore(this.elementToolbox, document.body.firstChild);
    
    this.elementMain.parentElement.insertBefore(this.elementHTML, this.elementMain);
    
    this.elementMain.onkeyup        = CwikContentEditor_OnKeyUp;
    this.elementMain.onclick        = CwikContentEditor_MouseClick;
    this.elementMain.onclickCommand = "open";
    this.elementMain.contentEditor  = this;
}

CwikContentEditor.prototype.createToolbox = function ()
{
    var table = document.createElement ("TABLE");
    var tbody = document.createElement ("TBODY");
    
    table.cellSpacing           = "4"
    table.cellPadding           = "0"
    table.border                = "0"
    table.style.position        = "absolute";
    table.style.visibility      = "hidden";
    table.style.backgroundColor = "buttonface";
    table.style.zIndex          = "9999";
    table.style.border          = "outset 2px";
    
    table.onmouseup             = CwikContentEditor_MouseUp;
    table.onmousemove           = CwikContentEditor_MouseMove;
    
    table.onmouseupCommand      = "release";
    table.onmousemoveCommand    = "track";
    
    table.contentEditor         = this;

    table.appendChild (tbody);
    tbody.appendChild (this.createToolboxTitle());
    tbody.appendChild (this.createToolboxIcons());
    
    return table;
}

CwikContentEditor.prototype.createToolboxIcons = function ()
{
    var otr   = document.createElement ("TR");
    var otd   = document.createElement ("TD");
    var table = document.createElement ("TABLE");
    var tbody = document.createElement ("TBODY");
    var tr    = document.createElement ("TR");
    
    otr.appendChild (otd);
    otd.appendChild (table);
    
    tr.appendChild (this.createToolboxIcon ("save.gif",      "Save",           "save"));
    tr.appendChild (this.createToolboxIcon ("bold.gif",      "Bold",           "bold"));
    tr.appendChild (this.createToolboxIcon ("italic.gif",    "Italic",         "italic"));
    tr.appendChild (this.createToolboxIcon ("copy.gif",      "Copy",           "copy"));
    tr.appendChild (this.createToolboxIcon ("cut.gif",       "Cut",            "cut"));
    tr.appendChild (this.createToolboxIcon ("paste.gif",     "Paste",          "paste"));
    tr.appendChild (this.createToolboxIcon ("delete.gif",    "Delete",         "delete"));
    tr.appendChild (this.createToolboxIcon ("undo.gif",      "Undo",           "undo"));
    tr.appendChild (this.createToolboxIcon ("redo.gif",      "Redo",           "redo"));
    tr.appendChild (this.createToolboxIcon ("indent.gif",    "Indent",         "indent"));
    tr.appendChild (this.createToolboxIcon ("outdent.gif",   "Outdent",        "outdent"));
    tr.appendChild (this.createToolboxIcon ("ordered.gif",   "Ordered List",   "ordered"));
    tr.appendChild (this.createToolboxIcon ("unordered.gif", "Unordered List", "unordered"));
    tr.appendChild (this.createToolboxIcon ("color.gif",     "Foreground Color", "color"));
    tr.appendChild (this.createToolboxIcon ("background-color.gif", "Background Color", "background"));
    
    tr.appendChild (this.createToolboxIcon ("left.gif",      "Justify Left",   "justifyleft"));
    tr.appendChild (this.createToolboxIcon ("center.gif",    "Justify Center", "justifycenter"));
    tr.appendChild (this.createToolboxIcon ("right.gif",     "Justify Right",  "justifyright"));
    
    tr.appendChild (this.createToolboxIcon ("hr.gif",        "Horizontal Rule", "hr"));
    tr.appendChild (this.createToolboxIcon ("table.gif",     "Table",           "table"));
    tr.appendChild (this.createToolboxIcon ("image.gif",     "Image",           "image"));
    tr.appendChild (this.createToolboxIcon ("hyperlink.gif", "HyperLink",       "hyperlink"));
    tr.appendChild (this.createToolboxIcon ("keywords.gif",  "Keywords",        "keywords"));
    
    if (this.styleList != "")
    {
        tr.appendChild (this.createToolboxStyleControl ());
    }
    
    tr.appendChild (this.createToolboxIcon ("properties.gif", "Toggle HTML Mode", "html"));
    
    table.appendChild (tbody);
    tbody.appendChild (tr);
    
    return otr;
}

CwikContentEditor.prototype.createToolboxIcon = function (icon, text, command)
{
    var img   = document.createElement ("IMG");
    var td    = document.createElement ("TD");
    
    img.src   = this.iconPath + "/" + icon;
    img.title = text;
    
    td.style.border       = "solid buttonface 1px";
    
    td.onmousedown        = CwikContentEditor_MouseDown;
    td.onmouseup          = CwikContentEditor_MouseUp;
    td.onmouseover        = CwikContentEditor_MouseOver;
    td.onmouseout         = CwikContentEditor_MouseOut;
    
    td.onmousedownCommand = "flash";
    td.onmouseupCommand   = "flash";
    td.onmouseoverCommand = "flash";
    td.onmouseoutCommand  = "flash";
    
    td.onclick            = CwikContentEditor_MouseClick;
    td.onclickCommand     = command;
    
    td.contentEditor      = this;
    
    td.appendChild (img);
    
    return td;
}

CwikContentEditor.prototype.createToolboxTitle = function ()
{
    var otr       = document.createElement ("TR");
    var otd       = document.createElement ("TD");
    var table     = document.createElement ("TABLE");
    var tbody     = document.createElement ("TBODY");
    var tr        = document.createElement ("TR");
    
    var titlecell = document.createElement ("TD");
    var titlespan = document.createElement ("SPAN");
    
    var closecell = document.createElement ("TD");
    var closespan = document.createElement ("SPAN");
    
    titlecell.style.backgroundColor = "black";
    titlecell.style.fontFamily      = "tahoma";
    titlecell.style.fontSize        = "8pt";
    titlecell.style.fontWeight      = "bold";
    titlecell.style.color           = "white";
    titlecell.onmousedown           = CwikContentEditor_MouseDown;
    titlecell.onmousedownCommand    = "capture";
    titlecell.contentEditor         = this;
    titlecell.appendChild (titlespan);
    
    titlespan.style.cursor          = "default";
    titlespan.innerText             = "Editing Tools";
    
    if (this.toolboxTitle != "")
    {
        titlespan.innerText += " - " + this.toolboxTitle;
    }
    
    closecell.align                 = "right";
    closecell.style.backgroundColor = "black";
    closecell.style.fontFamily      = "tahoma";
    closecell.style.fontSize        = "8pt";
    closecell.style.fontWeight      = "bold";
    closecell.style.color           = "white";
    closecell.onmousedown           = CwikContentEditor_MouseDown;
    closecell.onmousedownCommand    = "capture";
    closecell.contentEditor         = this;
    closecell.appendChild (closespan);
    
    closespan.style.cursor          = "hand";
    closespan.innerText             = "X";
    closespan.onclick               = CwikContentEditor_MouseClick;
    closespan.onclickCommand        = "close"
    closespan.contentEditor         = this;
    
    otd.bgColor = "black";
    
    otr.appendChild (otd);
    otd.appendChild (table);
    
    table.width = "100%";
    
    table.appendChild (tbody);
    tbody.appendChild (tr);
    
    tr.appendChild (titlecell);
    tr.appendChild (closecell);
    
    return otr;
}

CwikContentEditor.prototype.createToolboxStyleControl = function ()
{
    var values = this.styleList.split(",");
    var x;
    
    var td     = document.createElement ("TD");
    var select = document.createElement ("SELECT");
    
    var option;
    
    select.style.fontFamily = "tahoma";
    select.style.fontSize   = "8pt";
    //select.style.height     = "20px";
    select.style.color      = "maroon";
    
    select.onchange         = CwikContentEditor_StyleSelect;
    select.contentEditor    = this;
    
    option = document.createElement ("OPTION");
    option.innerText = "Apply Style ";
    
    select.appendChild (option);
    
    for (x in values)
    {
        option = document.createElement("OPTION");
        option.innerText = values[x];
        
        select.appendChild (option);
    } 
   
    td.appendChild (select);
    
    return td;
}

CwikContentEditor.prototype.toggleHTML = function ()
{
    if (this.elementHTML.style.display == "inline")
    {
        this.elementMain.innerHTML = this.elementHTML.value;
        this.elementMain.style.display = "inline";
        this.elementHTML.style.display = "none";
    }
    
    else
    {
        this.elementHTML.value = this.elementMain.innerHTML;
        this.elementHTML.style.display = "inline";
        this.elementMain.style.display = "none";
    }
}

CwikContentEditor.prototype.max = function (a, b)
{
    return (a > b) ? a : b;
}

CwikContentEditor.prototype.trueTop = function (element)
{
    if (element.offsetParent.tagName.toLowerCase() == "body")
        return element.offsetTop;
    else
        return element.offsetTop + this.trueTop (element.offsetParent);
}

CwikContentEditor.prototype.trueLeft = function (element)
{
    if (element.offsetParent.tagName.toLowerCase() == "body")
        return element.offsetLeft;
    else
        return element.offsetLeft + this.trueLeft(element.offsetParent);
}

CwikContentEditor.prototype.purgeSuperfluousSpans = function (element, text)
{
    var e;

    if (element == null)
        return;
    if (element.tagName.toLowerCase() == "body")
        return;
    if (element.innerText.replace (/(^\s*)|(\s*$)/g, "") != text)
        return;
    
    e = element.parentElement;
    
    if (element.tagName.toLowerCase() == "span")
        element.outerHTML = element.innerHTML;
        
    this.purgeSuperfluousSpans (e, text);
}

CwikContentEditor.prototype.close = function ()
{
    if (this.elementHTML.style.display == "inline")
    {
        this.toggleHTML ();
    }
    
    if (this.elementDefault.value != escape (this.elementMain.innerHTML))
    {
        if (confirm ("Abandon changes to this content area?") == false)
            return;
        else
            this.elementMain.innerHTML = unescape(this.elementDefault.value);
    }
    
    this.elementMain.contentEditable = false;
    this.elementToolbox.style.visibility = "hidden";
    
    currentCwikEditor = null;
}

CwikContentEditor.prototype.open = function (px, py)
{
    var tr = document.selection.createRange();
   
    if (tr.getBookmark)
    {
        this.globalBookmark = tr.getBookmark();
    }
    
    if (this.elementToolbox.style.visibility == "hidden")
    {
        if (currentCwikEditor != null)
        {
            currentCwikEditor.close();
            
            if (currentCwikEditor != null)
            {
                return;
            }
        }
        
        currentCwikEditor = this;
        
        this.elementMain.contentEditable = true;
        this.elementDefault.value = escape (this.elementMain.innerHTML);
        this.elementToolbox.style.visibility = "visible";
        
        if (this.left == null)
        {
            this.left = this.trueLeft(this.elementMain);
            this.elementToolbox.style.left = this.max(this.left, 0);
        }
        
        if (this.top == null)
        {
            //this.top = this.trueTop(this.elementMain);
            this.top = py;
            
            if ((this.top - this.elementToolbox.offsetHeight - 14) > 0)
                this.elementToolbox.style.top = this.max((this.top - this.elementToolbox.offsetHeight - 14), 0)
            else
                this.elementToolbox.style.top = this.max((this.top + 24), 0);
        }
        
        tr.moveToBookmark(this.globalBookmark);
        tr.select();
    }
}

CwikContentEditor.prototype.save = function ()
{
    var x;
    var raw;
    
    if (this.elementHTML.style.display == "inline")
    {
        this.toggleHTML();
    }
    
    raw = this.elementMain.innerHTML;
    raw = this.reparseSaving(raw);
    
    // this.elementValue.value = escape(this.elementMain.innerHTML);
    this.elementValue.value = escape(raw);
    
    this.elementMain.contentEditable = false;
    this.elementToolbox.style.visibility = "hidden";
    
    currentCwikEditor = null;
    
    if ((x = this.saveFunction.replace (/(^\s*)|(\s*$)/g, "")) != "")
    {
        if (typeof (window[x]) == "function")
        {
            var fn = window[x];
            
            fn();
        }
    }
    
    this.postBackFunction ();
}

            CwikContentEditor.prototype.reparseSaving = function (HTML)
            {
                var u = "http://" + document.location.host;
                var s = "https://" + document.location.host;
                
                HTML = HTML.split (s).join ("");
                HTML = HTML.split (u).join ("");
                
                return HTML;
            }

CwikContentEditor.prototype.doImage = function ()
{
    var tr = document.selection.createRange();
    
    if (tr.getBookmark)
        this.doImageAsTextRange (tr);
    else if (tr.length == 1)
        this.doImageAsObject (tr.item(0));
    else
        alert ("Cannot operate on more than one object at a time.");    
}

        CwikContentEditor.prototype.doImageAsTextRange = function (tr)
        {
            var result;
            var bm;
            
            if (document.selection.type.toLowerCase() != "none")
            {
                if (confirm ("Inserting an image now will delete the highlighted text.  Continue?") == false)
                {
                    return;
                }
            }
            
            else
            {
                tr.moveToBookmark (this.globalBookmark);    
            }
            
            bm = tr.getBookmark();
            
            result = showModalDialog (this.popupPath + "/ContentEditorImage.aspx", "", "center: yes; dialogHeight: 358px; dialogWidth: 660px;");
            
            if (! ((typeof (result) == "undefined") || (result == "[Cancel]")))
            {
                tr.moveToBookmark (bm);
                tr.pasteHTML (result);
            }
        }
        
        CwikContentEditor.prototype.doImageAsObject = function (image)
        {
            var result;
            
            result = showModalDialog (this.popupPath + "/ContentEditorImage.aspx", image, "center: yes; dialogHeight: 358px; dialogWidth: 660px;");
            
            if (! ((typeof (result) == "undefined") || (result == "[Cancel]")))
            {
                image.outerHTML = result;
            }
        }

CwikContentEditor.prototype.doHyperLink = function ()
{
    var tr, tt, bm, len, x;
    var parent;
    var alternate;
    var child;
    var html;
    var args;
    var result;
    var none;
    
    tr = document.selection.createRange();
    tt = document.selection.createRange();
    
    if (! tr.getBookmark)
    {
        // this is a control range, not a text range;
        alert ("Not yet supported.");
    }
    
    if (document.selection.type.toLowerCase() == "none")
    {
        none = true;
        
        tr.moveToBookmark (this.globalBookmark);
        tt.moveToBookmark (this.globalBookmark);
    }
    
    if (tr.htmlText.length == 0)
    {
        tr.moveEnd("character", 1);
        tt.moveEnd("character", 1);
    }

    parent = this.getHyperLinkElement (tr.parentElement ());
    
    if (! parent)
    {
        if (none == true)
        {
            alert ("You must select some text in order to create a hyperlink."); return;
        }
        
        for (x = 0, len = tt.text.length, tt.collapse(-1); x < len; x++, tt.collapse(0))
        {
            tt.moveEnd("character", 1);
           
            alternate = this.getHyperLinkElement (tt.parentElement ());
            
            if (alternate != null)
            {
                if (! child)
                {
                    child = alternate;
                }
                
                else if (child != alternate)
                {
                    alert ("Cannot select overlapping hyperlinks."); return;
                }
            }
        }
        
        if (! child)
            args = "none::" + tr.htmlText + "::::::" + this.styleList;
        else
            args = "child::" + tr.text + "::" + child.target + "::" + child.href + "::" + this.styleList;
    }

    else
    {
        tr.moveToElementText (parent);
        tr.select();
        
        args = "parent::" + parent.innerHTML + "::" + parent.target + "::" + parent.href + "::" + this.styleList;
    }
    
    bm = tr.getBookmark();
    
    result = showModalDialog (this.popupPath + "/ContentEditorHyperLink.aspx", args, "center: yes; dialogHeight: 215px; dialogWidth: 440px;");

    if (! ((typeof (result) == "undefined") || (result == "[Cancel]")))
    {
        if (parent != null)
        {
            parent.outerHTML = result;
        }
        
        else
        {
            tr.moveToBookmark (bm);
            tr.pasteHTML (result);
        }
    }
    
    tr.moveToBookmark (bm);
    tr.select();
}

    CwikContentEditor.prototype.getHyperLinkElement = function (element)
    {
        if (element.tagName.toLowerCase() == "body")
            return null;
        else if (element.tagName.toLowerCase() == "a")
            return element;
        else
            return this.getHyperLinkElement(element.parentElement);
    }

CwikContentEditor.prototype.doKeywords = function ()
{
    var tr;
    var bm;
    var result;
    
    tr = document.selection.createRange();
    
    if (tr.getBookmark)
    {
        bm = tr.getBookmark();
    }
    
    result = showModalDialog (this.popupPath + "/ContentEditorKeywords.aspx", this.elementKeywords.value, "center: yes; dialogHeight: 125px; dialogWidth: 458px;");

    if (! ((typeof (result) == "undefined") || (result == "[Cancel]")))
    {
        this.elementKeywords.value = result;
    }
    
    if (bm)
    {
        tr.moveToBookmark (bm);
    }
    
    tr.select();
}

CwikContentEditor.prototype.onMouseDown = function (element, px, py)
{
    if (element.onmousedownCommand == "flash")
    {
        element.style.backgroundColor = "white";
    }
    
    if (element.onmousedownCommand == "capture")
    {
        this.elementToolbox.setCapture();
        
        this.offsetLeft = px - parseInt(this.elementToolbox.style.left);
        this.offsetTop  = py - parseInt(this.elementToolbox.style.top);
        this.mouseDown  = true;
    }
}

CwikContentEditor.prototype.onMouseMove = function (element, px, py)
{
    if (element.onmousemoveCommand == "track")
    {
        if (this.mouseDown == false) return;
        
        this.elementToolbox.style.left = this.max (px - this.offsetLeft, 0);
        this.elementToolbox.style.top  = this.max (py - this.offsetTop,  0);
    }
}

CwikContentEditor.prototype.onMouseUp = function (element, px, py)
{
    if (element.onmouseupCommand == "flash")
    {
        element.style.backgroundColor = "buttonface";
    }
    
    if (element.onmouseupCommand == "release")
    {
        this.elementToolbox.releaseCapture();
        this.mouseDown = false;
    }
}

CwikContentEditor.prototype.onClick = function (element, px, py)
{
    if (element.onclickCommand == "open")
        this.open(px, py);
    if (element.onclickCommand == "close")
        this.close();
    if (element.onclickCommand == "save")
        this.save();
    if (element.onclickCommand == "bold")
        this.doBasicCommand ("bold");
    if (element.onclickCommand == "italic")
        this.doBasicCommand ("italic");
    if (element.onclickCommand == "copy")
        this.doBasicCommand ("copy");
    if (element.onclickCommand == "cut")
        this.doBasicCommand ("cut");
    if (element.onclickCommand == "paste")
        this.doBasicCommand ("paste");
    if (element.onclickCommand == "delete")
        this.doBasicCommand ("delete");
    if (element.onclickCommand == "indent")
        this.doBasicCommand ("indent");
    if (element.onclickCommand == "outdent")
        this.doBasicCommand ("outdent");
    if (element.onclickCommand == "redo")
        this.doBasicCommand ("redo");
    if (element.onclickCommand == "undo")
        this.doBasicCommand ("undo");
    if (element.onclickCommand == "justifyleft")
        this.doBasicCommand ("justifyleft");
    if (element.onclickCommand == "justifycenter")
        this.doBasicCommand ("justifycenter");
    if (element.onclickCommand == "justifyright")
        this.doBasicCommand ("justifyright");
    if (element.onclickCommand == "image")
        this.doImage();
    if (element.onclickCommand == "hyperlink")
        this.doHyperLink();
    if (element.onclickCommand == "keywords")
        this.doKeywords();
    if (element.onclickCommand == "html")
        this.toggleHTML ();
}
        
        CwikContentEditor.prototype.doBasicCommand = function (command)
        {
            var tr = document.selection.createRange();
    
            if (this.globalBookmark)
            {
                if (tr.moveToBookmark)
                {
                    tr.moveToBookmark (this.globalBookmark);
                    tr.select();
                }
               
                document.execCommand (command);
            }
        }

CwikContentEditor.prototype.onMouseOver = function (element)
{
    if (element.onmouseoverCommand == "flash")
    {
        element.style.border = "solid gray 1px";
    }
}

CwikContentEditor.prototype.onMouseOut = function (element)
{
    if (element.onmouseoutCommand == "flash")
    {
        element.style.border = "solid buttonface 1px";
    }
}

CwikContentEditor.prototype.onKeyUp = function (element)
{    
    var tr = document.selection.createRange();
   
    if (tr.getBookmark)
        this.globalBookmark = tr.getBookmark ();
    else
        this.globalBookmark = null;
}

CwikContentEditor.prototype.onStyleSelect = function (element)
{
    var tr, tx, st, bm, el;
    
    if (element.selectedIndex < 1)
    {
        return;
    }
    
    st = element.options[element.selectedIndex].text;
    
    tr = document.selection.createRange();
    el = tr.parentElement();
    bm = tr.getBookmark();
    tx = tr.text;
    
    this.purgeSuperfluousSpans (el, tx.replace (/(^\s*)|(\s*$)/g, ""));
    
    tr.moveToBookmark(bm);
    tr.select()
    
    tr = document.selection.createRange()
    bm = tr.getBookmark();
    tx = tr.text;
    
    tr.pasteHTML("<SPAN CLASS='" + st + "'>" + tx + "</SPAN>");
    tr.moveToBookmark(bm);
    tr.select();
    
    element.selectedIndex = 0;
}

function CwikContentEditor_MouseDown ()
{
    if (this.contentEditor)
    {
        this.contentEditor.onMouseDown (this, event.clientX, event.clientY);
    }
}

function CwikContentEditor_MouseMove ()
{
    if (this.contentEditor)
    {
        this.contentEditor.onMouseMove (this, event.clientX, event.clientY);
    }
}

function CwikContentEditor_MouseUp ()
{
    if (this.contentEditor)
    {
        this.contentEditor.onMouseUp (this, event.clientX, event.clientY);
    }
}

function CwikContentEditor_MouseClick ()
{
    if (this.contentEditor)
    {
        this.contentEditor.onClick (this, event.clientX, event.clientY);
    }
}

function CwikContentEditor_MouseOver ()
{
    if (this.contentEditor)
    {
        this.contentEditor.onMouseOver (this);
    }
}

function CwikContentEditor_MouseOut ()
{
    if (this.contentEditor)
    {
        this.contentEditor.onMouseOut (this);
    }
}

function CwikContentEditor_OnKeyUp ()
{
    if (this.contentEditor)
    {
        this.contentEditor.onKeyUp (this);
    }
}

function CwikContentEditor_StyleSelect ()
{
    if (this.contentEditor)
    {
        this.contentEditor.onStyleSelect (this);
    }
}