/*
 * Copyright (c) 1997-2005 Day Management AG
 * Barfuesserplatz 6, 4001 Basel, Switzerland
 * All Rights Reserved.
 *
 * This software is the confidential and proprietary information of
 * Day Management AG, ("Confidential Information"). You shall not
 * disclose such Confidential Information and shall use it only in
 * accordance with the terms of the license agreement you entered into
 * with Day.
 */


/**
 * MVControl constructor.
 * @param name the name of the control
 * @param type the type of the control
 */
function MVControl(/* String */name, /* string*/ type, /* boolean*/ isMultiple) {
    this.name = name;
    this.type = type?type:"String";
    this.isMultiple = isMultiple;
    this.htmlType = "text";
    this.numValues=0;
    this.nodeTypes = new Array();
    this.textLimit=40;
    this.properties=new Object();
    this.customEvents=new Object();
    this.setEvent("onkeypress", "MVControl.onEditCtl(event);");
    this.setEvent("onchange", "MVControl.onEditCtl(event);");
    this.setEvent("onpaste", "MVControl.onEditCtl(event);");
    this.allowEmpty=isMultiple;
    this.flatNodeTypes = true;
    if (type=="Reference" || type=="Path" || type=="WeakReference") {
        this.getAdditionalHTML = MVControl.prototype.getNodeBrowseHTML;
    }
    if (type=="NodeType") {
        this.getControlHTML = MVControl.prototype.getNodeTypeHTML;
    }
    if (type=="Binary") {
        this.htmlType = "file";
    }
    if (type==("Date")) {
        this.getAdditionalHTML  = MVControl.prototype.getDateNowHTML;
    }
    MVControl.controls[name] = this;
}

/**
 * sets a property
 */
/* void */MVControl.prototype.setProperty = function(name, value) {
    this.properties[name]=value;
}

/* void */MVControl.prototype.setAllowEmpty = function(/* boolean */allow) {
    this.allowEmpty=allow;
}

/* void */MVControl.prototype.setEvent = function(name, value) {
    if (this.customEvents[name]) {
        this.customEvents[name]+=value;
    } else {
        this.customEvents[name]=value;
    }
}

/**
 * returns the HTML of the actual control
 */
/*String */MVControl.prototype.getControlHTML = function(value, id) {
    var events="";
    for (var e in this.customEvents) {
        events+=" " + e + '="' + this.customEvents[e] + '"';
    }
    if (!value) value="";
    var width = this.properties["css_width"];
    if (!width) width="250";
    if (value.length>this.textLimit) {
        return '<textarea id="'+id+'" style="width:'+width+'px" rows="3" wrap="auto" name="'+this.name+'"'+events+'>' + value + '</textarea>';
    } else {
        return '<input id="'+id+'" style="width:'+width+'px" value="'+value+'" type="' + this.htmlType + '" name="'+this.name+'"'+events+'>';
    }
}

/**
 * returns the HTML of the actual control
 */
/*String */MVControl.prototype.getDateNowHTML = function(id) {
    return '<input type="button" onClick="MVControl.setDateNow(\''+this.name+'\', \''+id+'\')" value="now...">';
}

/* int */ MVControl.nodeTypeComparator = function(nt1, nt2) {
    if (nt1.name == nt2.name) {
        return 0;
    } else if (nt1.name < nt2.name) {
        return -1;
    } else {
        return 1;
    }
}
/**
 * returns the HTML of the actual control
 */
/*String */MVControl.prototype.getNodeTypeHTML= function(value, id) {
    var events="";
    for (var e in this.customEvents) {
        events+=" " + e + '="' + this.customEvents[e] + '"';
    }
    if (!value) value="";

    // if value, search style
    var defaultIcon=MVControl.docroot + "/imgs/0.gif";
    if (value) {
        for (var i=0; i<this.nodeTypes.length; i++) {
            if (value==this.nodeTypes[i].name) {
                defaultIcon= MVControl.docroot + this.nodeTypes[i].icon;
                break;
            }
        }
    } else if (!this.allowEmpty) {
        defaultIcon= MVControl.docroot + this.nodeTypes[0].icon;
    }
    var str="";
    var style="height:18px;";
    if (this.properties["HideNodeTypeIcon"]!="true") {
        if (this.flatNodeTypes) {
            // IE is not able to draw 'position:absolute' stuff above controls
            str+= '<span style="position:relative;top:3px; width:18px;"><img height="16" src="'+defaultIcon+'"></span>';
        } else {
            str+= '<span style="position:absolute;padding-left:2px;padding-top:3px;"><img src="'+defaultIcon+'"></span>';
        }
        style+="padding-left:17px;";
    }
    if (this.flatNodeTypes) {
        // sort nodetypes for IE that cannot display tree
        this.nodeTypes.sort(MVControl.nodeTypeComparator);
    }
    str+= '<select style="'+style+'" id="'+id+'" name="' + this.name +'"' + events + '>';
    if (this.allowEmpty) {
        style=" height: 18px;";
        style+=" background-image: url(" + MVControl.docroot + "/imgs/0.gif);";
        style+=" background-repeat: no-repeat;";
        str+= '<option style="'+style+'"></option>';
    }
    var drawnNodeTypes = new Object();
    for (var i=0; i<this.nodeTypes.length; i++) {
        var nt = this.nodeTypes[i];
        if (this.flatNodeTypes && drawnNodeTypes[nt.name]) {
            // skip duplicate nodetypes for IE
            continue;
        }
        var disabled="";
        if ((nt.isMixin && this.properties["DisableMixinTypes"]=="true") ||
            (!nt.isMixin && this.properties["DisablePrimaryTypes"]=="true")) {
            if (document.all) {
                // IE does not support disabled in <option> yet
                continue;
            }
            disabled=' disabled="yes"';
        }
        if (!this.flatNodeTypes) {
            style="margin-left: " + nt.indent*18 + "px;";
        }
        style+=" padding-left: 17px;";
        style+=" height: 18px;";
        style+=" background-image: url(" + MVControl.docroot + nt.icon + ");";
        style+=" background-repeat: no-repeat;";
        str+= '<option'+disabled+' style="'+style+'" value="'+nt.name+'"'+(value==nt.name?" selected":"")+'>' + nt.name + '</option>';
        drawnNodeTypes[nt.name] = true;
    }
    str+="</select>";
    return str;
}


/**
 * returns the HTML for the nodebrowse button
 */
/*String */MVControl.prototype.getNodeBrowseHTML = function(id) {
    return '<input type="button" onClick="MVControl.browseNode(\''+this.name+'\', \''+id+'\')" value="Browse...">';
}

/**
 * returns the HTML of the '+' / '-' buttons
 */
/*String*/MVControl.prototype.getButtonsHTML = function() {
    return '<img onClick="MVControl.onInsert(event)" src="' + MVControl.docroot + '/imgs/icons/small_plus.gif"><br><img onClick="MVControl.onDelete(event)" src="' + MVControl.docroot + '/imgs/icons/small_minus.gif">';
}

/**
 * creates a new control 'line'
 */
/*DHTMLObject */ MVControl.prototype.createTR = function(/*String*/ id) {
    var tr = document.createElement("tr");
    var td = document.createElement("td");
    tr.appendChild(td);
    td.innerHTML = this.getControlHTML("", id);

    if (this.getAdditionalHTML) {
        td = document.createElement("td");
        tr.appendChild(td);
        td.innerHTML = this.getAdditionalHTML(id);
    }
    if (this.isMultiple) {
        td = document.createElement("td");
        tr.appendChild(td);
        td.innerHTML = this.getButtonsHTML();
    }
    return tr;
}

/**
 * draws this control start
 */
MVControl.prototype.drawBegin = function() {
    var tableId = "mvc_" + this.name;
    document.write('<table border="0" cellpadding="0" cellspacing="0" id="' + tableId + '">');
}

MVControl.prototype.getId = function(num) {
    return "mvc_" + this.name + num;
}
/**
 * draws this control value
 */
MVControl.prototype.drawValue = function(/* String */value) {
    value = unescape(value);
    value = value.replace('"', "&quot;");
    value = value.replace('<', "&lt;");
    document.write('<tr><td>' + this.getControlHTML(value,  this.getId(this.numValues)) + '</td>');
    if (this.getAdditionalHTML) {
        document.write('<td>' + this.getAdditionalHTML(this.getId(this.numValues)) + '</td>');
    }
    if (this.isMultiple) {
        document.write('<td>' + this.getButtonsHTML() + '</td>');
    }
    document.write('</tr>');
    this.numValues++;
}

/**
 * draws this control end
 */
MVControl.prototype.drawEnd = function() {
    if (this.numValues==0 || this.isMultiple) {
        this.drawValue("");
    }
    document.write('</table>');
}

MVControl.prototype.addNodeType = function(/*String*/name, /*boolean*/ isMixin, /*String*/ icon, /*int*/ indent) {
    var nt = new Object();
    nt.name = name;
    nt.icon = icon;
    nt.indent = indent;
    nt.isMixin = isMixin;
    this.nodeTypes[this.nodeTypes.length] = nt;
}

function zeroPad(str, len) {
    var s = "" + str;
    while (s.length<len) {
        s = "0" + s;
    }
    return s;
}

MVControl.setDateNow = function(name, id) {
    var mvc  = MVControl.getCtl(name);
    var ctl = document.getElementById(id);
    var now = new Date();
    var str = now.getFullYear();
    str += "-" + zeroPad(now.getMonth()+1, 2);
    str += "-" + zeroPad(now.getDate(), 2);
    str += "T" + zeroPad(now.getHours(), 2);
    str += ":" + zeroPad(now.getMinutes(), 2);
    str += ":" + zeroPad(now.getSeconds(), 2);
    str += "." + zeroPad(now.valueOf() % 1000, 3);
    var tz = now.getTimezoneOffset();
    if (tz<0) {
        tz = -tz;
        str += "+";
    } else {
        str += "-";
    }
    str += zeroPad(tz/60, 2) + ":" + zeroPad(tz%60, 2);
    ctl.value=str;
}

/**
 * Creates a new NodeTree and puts it into the control registry
 * @param name     name of new node tree
 * @param provider the html provider
 * @param levelURI the location to fetch level data
 *
 * @return newly created node tree instance
 */
/*void*/ MVControl.browseNode = function(name, id) {
    var mvc = MVControl.getCtl(name);
    mvc.browseNode(id);
}

/*void*/ MVControl.prototype.browseNode = function(id) {
    var ctl = document.getElementById(id);
    var uri = MVControl.docroot + "/ui/nodebrowse.jsp";
    uri+= "?ck=" + new Date().valueOf();
    uri+= "&SelectedPath=" + encodeURIComponent(ctl.value);
    for (var p in this.properties) {
        uri+="&" + p + "=" + this.properties[p];
    }
    if (window.showModalDialog) {
    	// IE only
	var feat = "scroll:No; resizable:Yes; status:No; dialogHeight:450px; dialogWidth: 600px;";
    	var ret = window.showModalDialog(uri, "", feat);
	if (ret) {
	    ctl.value = ret;
	    MVControl.onEdit(ctl);
	}
    } else {
	//var feat = "scroll:no, resizable:yes, status:no, windowheight:250px, windowwidth: 600px,dialog";
	var feat = "scroll=no, height=450, width=600, dialog, resizable=yes, modal";
    	uri+="&TargetControlId=" + encodeURIComponent(id);
    	var w = window.open(uri, "nodebrowser", feat);
    }
}

//-----------------------------------------------------------------------------
// static members

/** list of all controls in this form */
MVControl.controls = new Object();
MVControl.docroot = "";


//-----------------------------------------------------------------------------
// static methods

/**
 * returns the control with the given name
 */
/* MVControl */ MVControl.getCtl = function(/* String */ name) {
    return MVControl.controls[name];
}

/*void*/ MVControl.setDocroot = function(/*String*/ docroot) {
    this.docroot = docroot;
}

MVControl.refresh = function(ctlId) {
    MVControl.onEdit(document.getElementById(ctlId));
}

/**
 * called when key pressed
 */
MVControl.onEditCtl = function(evt) {
    if (window.event) e=window.event;
    var ctl = evt.srcElement? evt.srcElement : evt.target;
    MVControl.onEdit(ctl);
}
/**
 * called when key pressed
 */
MVControl.onEdit = function(ctl) {
    var mvc = MVControl.getCtl(ctl.name);
    var td = ctl.parentNode;

    // check size
    if (mvc.type=="String" || mvc.type=="undefined") {
      if ((ctl.value.length>mvc.textLimit && ctl.tagName.toLowerCase()=="input")
            || (ctl.value.length<mvc.textLimit && ctl.tagName.toLowerCase()=="textarea")) {
            var newTD= document.createElement("td");
            newTD.innerHTML = mvc.getControlHTML(ctl.value, ctl.id);
            td.parentNode.replaceChild(newTD, td);
            td=newTD;
            td.firstChild.value=ctl.value;
            if (td.firstChild.setActive) {
                td.firstChild.setActive();
            }
            td.firstChild.focus();
        }
    }
    if (mvc.type=="NodeType") {
        var srcStyle = ctl.options[ctl.selectedIndex].style;
        var url = srcStyle.backgroundImage;
        // the backgroundimage style has the form: url(src)
        ctl.parentNode.firstChild.firstChild.src = url.substring(4, url.length-1);
    }

    // check if not last
    if (!mvc.isMultiple || td.parentNode.nextSibling || ctl.value=="") {
        return;
    }

    var table = td.parentNode.parentNode;
    var tr = mvc.createTR(mvc.getId(mvc.numValues++));
    table.appendChild(tr);
}

/**
 * called when '+' butten is clicked
 */
MVControl.onInsert = function(e) {
    if (window.event) e=window.event;
    var img = e.srcElement? e.srcElement : e.target;
    var tr = img.parentNode.parentNode;
    var table = tr.parentNode;
    var ctl = tr.firstChild.firstChild;
    // hack for 'nodetype select'
    if (ctl.tagName.toLowerCase()=="span") {
        ctl = ctl.nextSibling;
    }
    var mvc = MVControl.getCtl(ctl.name);
    var newTR = mvc.createTR(mvc.getId(mvc.numValues++));
    table.insertBefore(newTR, tr);
    MVControl.adjustImages(table);
}

/**
 * called when '-' button is clicked
 */
MVControl.onDelete = function(e) {
    if (window.event) e=window.event;
    var ctl = e.srcElement? e.srcElement : e.target;
    var tr = ctl.parentNode.parentNode;
    var table = tr.parentNode;

    // if only child, ignore
    if (table.firstChild.nextSibling) {
        table.removeChild(tr);
    }
    MVControl.adjustImages(table);
}

MVControl.adjustImages = function(table) {
    // need to adjust images for 'nodetype select'
    var tr = table.firstChild;
    var y = 0;
    while (table) {
        y+=table.offsetTop;
        table=table.offsetParent;
    }
    while (tr) {
        var td = tr.firstChild;
        var span = td.firstChild;
        if (span.style.position=="absolute") {
            span.style.top=y+tr.offsetTop;
        }
        tr = tr.nextSibling;
    }
}
