//supporting form script for the application

//paging support function used by page links in query results
function pageToID(formID,page) {
    var currform=document.getElementById(formID);
    if(currform != null) {
        var ekpid=formID + '.UIFormContext.enterKeyPressed';
        var ekp=document.getElementById(ekpid);
        if(ekp) {
            var pageto='page to:' + page;
            ekp.setAttribute('value',pageto); }
        document.forms[formID].submit(); }
    return true;
}

// Remove the irrelevant due date fields when not needed.  We have to
// hide the span and set the display to none so the space does not show
// up in the form.  The relative due date plan reference wraps around 
// when listing which makes the form look wierd.
function dueTypeSelection()
{
    var tag = document.getElementById('DynamicDueType');
    var value = tag.value;
    var fdd = document.getElementById('FixedDueDate');
    var rdd = document.getElementById('RelativeDueDate');
    if(value == 'None') {
        fdd.style.visibility="hidden";
        fdd.style.display="none";
        rdd.style.visibility="hidden";
        rdd.style.display="none"; }
    else if(value == 'Fixed') {
        fdd.style.visibility="visible";
        fdd.style.display="";
        rdd.style.visibility="hidden";
        rdd.style.display="none"; }
    else if(value == 'Relative') {
        fdd.style.visibility="hidden";
        fdd.style.display="none";
        rdd.style.visibility="visible";
        rdd.style.display="";
        var relday = document.getElementById('RelativeRoundDay');
        var roundtag = document.getElementById('MyPlans.UIFormContext.ci.relRounding');
        var roundtype = roundtag.value;
        if(roundtype.indexOf("Exact")>=0) {
            relday.style.visibility="hidden";
            relday.style.display="none"; }
        else {
            relday.style.visibility="visible";
            relday.style.display=""; } }
}


var activeMenu = null;
//drag and drop support adapted from http://www.isocra.com/
//http://www.isocra.com/2007/07/dragging-and-dropping-table-rows-in-javascript/
var currenttable = null;

function mouseMove(ev) {
    if(currenttable && currenttable.dragObject) {
        ev = ev || window.event;   //normal param or IE style
        var mousePos = mouseCoords(ev);
        var y = mousePos.y - currenttable.mouseOffset.y;
        if(y != currenttable.oldY) {
            var movingDown = (y > currenttable.oldY);
            currenttable.oldY = y;
            //color change hangs around in IE.  Doing without.
            //currenttable.dragObject.style.backgroundColor = "#FFCCFF";
            var currentRow = currenttable.findDropTargetRow(y);
            if((currentRow)&&(currenttable.dragObject!=currentRow)) {
                currenttable.onDrag(currenttable.dragObject);
                if(movingDown) {
                    currenttable.dragObject.parentNode.insertBefore(
                        currenttable.dragObject,currentRow.nextSibling); }
                else {
                    currenttable.dragObject.parentNode.insertBefore(
                        currenttable.dragObject,currentRow); } } }
        return false; }
    if(activeMenu) {
        ev = ev || window.event;   //normal param or IE style
        var mousePos = mouseCoords(ev);
        var left=parseInt(activeMenu.style.left);  //e.g. "276px"
        var top=parseInt(activeMenu.style.top);
        var right=left + activeMenu.offsetWidth;
        var bottom=top + activeMenu.offsetHeight;
        if((mousePos.x < left)||(mousePos.x > right)||
           (mousePos.y < top)||(mousePos.y > bottom)) {
            activeMenu.style.display='none';
            activeMenu=null; } }
}


function mouseUp(ev) {
    if(currenttable && currenttable.dragObject) {
        var droppedRow = currenttable.dragObject;
        //droppedRow.style.backgroundColor = 'transparent';
        currenttable.dragObject = null;
        currenttable.onDrop(currenttable.table, droppedRow);
        currenttable = null; }
}


function getEventSource(evt) {
    if(window.event) {
        evt = window.event;  //IE
        return evt.srcElement; }
    else {
        return evt.target; } //standard browsers
}


/**
 * The table drag and drop functionality class.  Singleton reference used
 * to control scope.
 */
function TableDnD() {
    this.dragObject = null;   //holds the current drag object
    this.mouseOffset = null;
    this.table = null;
    this.oldY = 0;

    this.init = function(table) {
        this.table = table;
        var rows = table.tBodies[0].rows;  //e.g. getElementsByTagName("tr")
        for(var i=0;i<rows.length;i++) {
            var nodrag = rows[i].getAttribute("NoDrag");
            if(nodrag == null || nodrag == "undefined") {
                this.makeDraggable(rows[i]); } }
    }


    //Clear the link on drag so we do not follow it during script processing.
    //The value is set to null on normal browsers, empty string on IE
    this.onDrag = function(dragRow) {
        var anchor = this.getAnchor(dragRow);
        anchor.removeAttribute('href');
    }


    this.onDrop = function(table, droppedRow) {
        var anchor = this.getAnchor(droppedRow);
        var href = anchor.getAttribute("href");
        //with IE, href will be the empty string
        if((href!=null)&&(href!="undefined")&&(href!="")) {
            return true; }  //not actually dragged anywhere, skip processing
        var compID = droppedRow.getAttribute("id");
        var parentID = "0";
        var childindex = "0";
        var rows = table.tBodies[0].rows;
        for(var i=0;i<rows.length;i++) {
            if(rows[i].getAttribute("id") == compID) {  //found the row
                if(i < 2) {   //head:0, blankrow:1, immediate:2
                    //alert("using above-table rule");
                    parentID=rows[2].getAttribute("id"); }  //child index 0
                else if(i == 2) {  //replaced immediate, so pushed down.
                    //alert("using immediate-parent rule");
                    parentID=rows[3].getAttribute("id"); }
                else if(((rows[i-1].getAttribute("parentID")) ==
                         (rows[i].getAttribute("parentID")))&&
                        (!this.isPlan(rows[i-1]))) {
                    //alert("using current-plan row before rule");
                    parentID=rows[i].getAttribute("parentID");
                    var prevIdxStr=rows[i-1].getAttribute("childIndex");
                    var prevIndex=parseInt(prevIdxStr);
                    var currIndex=prevIndex + 1;
                    childindex="" + currIndex; }
                else if((i<(rows.length-1))&&   //somewhere in the middle
                        (rows[i+1].getAttribute("parentID") != "0")) {
                    //alert("using row-after rule");
                    parentID=rows[i+1].getAttribute("parentID");
                    childindex=rows[i+1].getAttribute("childIndex"); }
                else {
                    //alert("using default row-before rule");
                    var prevRow = rows[i-1];
                    if(this.isPlan(prevRow)) {
                        parentID=prevRow.getAttribute("id"); } //child index 0
                    else {  //prev row is a sibling child row
                        parentID=prevRow.getAttribute("parentID");
                        var prevIdxStr=prevRow.getAttribute("childIndex");
                        var prevIndex=parseInt(prevIdxStr);
                        var currIndex=prevIndex + 1;
                        childindex="" + currIndex; } }
                break; } }
        var moveaction="move:" + compID + ":" + parentID + ":" + childindex;
        var ekp=
            document.getElementById('MyPlans.UIFormContext.enterKeyPressed');
        ekp.setAttribute('value',moveaction);
        document.forms['MyPlans'].submit();
        return true;
    }


    this.isPlan = function(row) {
        var anchor = this.getAnchor(row);
        var href = anchor.getAttribute("href");
        if((href!=null)&&(href!="undefined")&&(href.indexOf("class=Plan")>0)) {
            return true; }
        return false;
    }


    //return the main anchor link for a given row.
    this.getAnchor = function(row) {
        var tds = row.getElementsByTagName('td');
        var reftd = tds[2];  //td[0]:outlinepath, td[1]:actions
        var anchors = reftd.getElementsByTagName('a');
        anchor = anchors[anchors.length-1];  //skip +/-, use last
        return anchor;
    }        


    //walk the DOM tree and add up the offsets
    this.getPosition = function(e) {
        var left = 0;
        var top = 0;
        if(e.offsetHeight == 0) {
            e = e.firstChild; }  //a table cell
        while(e.offsetParent) {
            left += e.offsetLeft;
            top += e.offsetTop;
            e = e.offsetParent; }
        left += e.offsetLeft;
        top += e.offsetTop;
        return {x:left, y:top};
    }


    this.getMouseOffset = function(target, ev) {
        ev = ev || window.event;
        var docPos = this.getPosition(target);
        var mousePos = mouseCoords(ev);
        return {x:mousePos.x - docPos.x, y:mousePos.y - docPos.y};
    }


    this.makeDraggable = function(item) {
        if(!item) return;
        var self = this;  //Keep the context of the TableDnd inside the function
        item.onmousedown = function(ev) {
            var target = getEventSource(ev);
            if(target.tagName == 'INPUT' || target.tagName == 'SELECT') {
                return true; }  //do not process input controls
            currenttable = self;
            self.dragObject = this;
            self.mouseOffset = self.getMouseOffset(this, ev);
            return false; }
        //item.style.cursor = "move";
    }


    this.findDropTargetRow = function(y) {
        var rows = this.table.tBodies[0].rows;
        for(var i=0;i<rows.length;i++) {
            var row = rows[i];
            var nodrop = row.getAttribute("NoDrop");
            if(nodrop == null || nodrop == "undefined") {
                var rowY = this.getPosition(row).y;
                var rowHeight = parseInt(row.offsetHeight)/2;
                if(row.offsetHeight == 0) {
                    rowY = this.getPosition(row.firstChild).y;
                    rowHeight = parseInt(row.firstChild.offsetHeight)/2; }
                if((y > (rowY - rowHeight)) && (y < (rowY + rowHeight))) {
                    return row; } } }
        return null;
    }

}

//factored method to get the actual mouse coordinates
function mouseCoords(ev) {
    if(ev.pageX || ev.pageY) {
        return {x:ev.pageX, y:ev.pageY}; }
    return {
        x:ev.clientX + document.body.scrollLeft - document.body.clientLeft,
        y:ev.clientY + document.body.scrollTop - document.body.clientTop };
}


//write quick edit link menu
document.write('<div id="outlineLinkMenu" class="userlink" style="position:absolute;display:none;background:#FFCC66;border:1px solid black;padding: 0 3 3 3">');
document.write('<a id="olmnotes" href="?">Notes and Status</a><br/>');
document.write('<a id="olmview" href="?">View Details</a></br/>');
document.write('<a id="olmedit" href="?">Edit Component</a><br/>');
document.write('<a id="olmAddTask" href="?">Add Task</a><br/>');
document.write('<a id="olmAddPlan" href="?">Add Plan</a><br/>');
document.write('</div>');
//outline link menu to quickly select what you want to do
function olmenu(ev) {
    ev = ev || window.event;
    var sourcenode=getEventSource(ev);
    while((sourcenode!=null)&&(sourcenode.nodeName!='A')) {
        sourcenode=sourcenode.parentNode; }
    var link=sourcenode.getAttribute("href");
    if(!link) {  //dragdrop release triggers a click response, ignore it.
        return false; }
    var isPlan=link.indexOf('class=Plan')>=0;
    var linkmenu=document.getElementById('outlineLinkMenu');
    var coords=mouseCoords(ev);
    linkmenu.style.left=coords.x-10;
    linkmenu.style.top=coords.y-5;
    linkmenu.style.display='';  //make visible
    var menuitems=linkmenu.childNodes;
    for(var i=0;i<menuitems.length;i++) {
        var menulink=menuitems[i];
        if(menulink.getAttribute("id")=='olmnotes') {
            menulink.setAttribute('href',olmlink('ComponentSummary',link)); }
        else if(menulink.getAttribute("id")=='olmview') {
            menulink.setAttribute('href',olmlink('',link)); }
        else if(menulink.getAttribute("id")=='olmedit') {
            menulink.setAttribute('href',olmlink('edit',link)); }
        else if(menulink.getAttribute("id")=='olmAddTask') {
            if(isPlan) {
                displayMenuItem(menuitems,i,true);
                menulink.setAttribute('href',olmlink('AddTaskButton',link)); }
            else {
                displayMenuItem(menuitems,i,false); } }
        else if(menulink.getAttribute("id")=='olmAddPlan') {
            if(isPlan) {
                displayMenuItem(menuitems,i,true);
                menulink.setAttribute('href',olmlink('AddPlanButton',link)); }
            else {
                displayMenuItem(menuitems,i,false); } } }
    activeMenu=linkmenu;  //set var so we can hide if mouseout
    return false;
}

//factored method to hide a menu item ref/br pair
function displayMenuItem(items,index,show) {
    var menuitem=items[index];
    var britem=items[index+1];
    if(show) {
        menuitem.style.visibility='visible';
        menuitem.style.display='';
        britem.style.visibility='visible';
        britem.style.display=''; }
    else {
        menuitem.style.visibility='hidden';
        menuitem.style.display='none'
        britem.style.visibility='hidden';
        britem.style.display='none'; }
}

//replace the button in the given linktext with the one given.
//this method assumes a "?button=blah&scr=Heap&class=blah&id=blah" format.
function olmlink(buttonName,linktext) {
    var retval='?button=' + buttonName + '&';
    if(buttonName=='') {
        retval='?'; }
    retval=retval + linktext.substring(linktext.indexOf('&')+1);
    return retval;
}


//any additional functions go here

    function verifySubscribed() {
        var haveAds=false;
        var haveSub=true;
        var headArea=document.getElementById('headerAdArea');
        var divcont=headArea.childNodes[0].childNodes;
        for(var i=0;i<divcont.length;i++) {
            if(divcont[i].nodeName.toUpperCase() == 'A') {
                haveSub=false;
                break; } }
        var adArea=document.getElementById('adArea');
        var children=adArea.childNodes;
        for(var i=0;i<children.length;i++) {
            //alert("children[" + i + "]: " + children[i].nodeName);
            //var subkids=children[i].childNodes;
            //for(var j=0;j<subkids.length;j++) {
            //    alert("children[" + i + "][" + j + "]: " + 
            //          subkids[j].nodeName); }
            //IFRAME used to be the indicator, now HTMLInsElement seems to be
            //This is not infallible, so don't nag badly if it breaks.
            if((children[i].nodeName.toUpperCase() == 'IFRAME')||
               (children[i].nodeName.toUpperCase() == 'INS')) {
                haveAds=true;
                break; } }
        if(!haveAds && !haveSub) {
            var guiltmsg=document.createTextNode('TaskHeap is supported by advertising or subscription.');
            var guiltpara=document.createElement('P');
            guiltpara.appendChild(guiltmsg);
            adArea.appendChild(guiltpara); }
    }

    

//document function hooks
window.onload=function() {
    document.onmousemove = mouseMove;
    document.onmouseup = mouseUp;
    //initialize all the outline links to call the olmenu function onclick
    var cites=document.getElementsByTagName("cite");
    for(var i=0;i<cites.length;i++) {
        //className accessor property works in all browsers, even IE
        if(cites[i].className=='treelink') {
            cites[i].parentNode.onclick=olmenu; } }
}


