/**
 * @author Jarno Elovirta (jarno.elovirta@nokia.com)
 * @version 11/08/01
 */

var is = new Is();                  // Get browser information.
var targetfile = new String("");
var isExpanded = false;             // Blocks are collapsed by default.
onload = openPage;                  // Set blocks collapsed when the page
                                    // is loaded.

// IE doesn't accept any other version than this: onload = OpenPage;
// Note that it is case sensitive! onload is not the same as onLoad.

// points right
// urn:mars:dn01157982:1:none:global:gif:data:data
var expandIcon      = "NED?action=retrieve&identifier=dn01157982&edition=1&language=none&coverage=global&encoding=gif&component=data&item=data"
// points down
// urn:mars:dn01157994:1:none:global:gif:data:data
var collapseIcon    = "NED?action=retrieve&identifier=dn01157994&edition=1&language=none&coverage=global&encoding=gif&component=data&item=data"

/*
 * Gets browser information and version.
 */
function Is () {
    // convert all characters to lowercase to simplify testing
    var agt=navigator.userAgent.toLowerCase();

    // detecting browser version
    this.major = parseInt(navigator.appVersion);

    this.nav  = ((agt.indexOf('mozilla')!=-1) && ((agt.indexOf('spoofer')==-1)
                        && (agt.indexOf('compatible') == -1)));
    this.nav4 = (this.nav && (this.major == 4));
    this.nav4up = this.nav && (this.major >= 4);

    // For Mozilla and Netscape version 6 or newer.
    this.nav6up = this.nav && (this.major >= 5);

    this.ie   = (agt.indexOf("msie") != -1);
    this.ie4  = (this.ie && (this.major == 4));
    this.ie4up  = this.ie  && (this.major >= 4);

    this.opera = (agt.indexOf("opera") != -1);
    this.opera6up = ((agt.indexOf("opera 6") != -1) || (agt.indexOf("opera/6") != -1 ));
}


/*
 * Sets all expand/collapse blocks to collapsed. 
 * The function is executed when page is loaded.
 *
 * THIS CURRENTLY DOESN'T WORK IN MOZILLA/NETSCAPE 6.
 */
function openPage() {
    var Collapse;           // Elements that will be collapsed.
    var i;                  // Loop counter.


    if(is.nav6up) {
        // This doesn't work correctly in Mozilla. This may be the bug 72058?
        // http://bugzilla.mozilla.org/show_bug.cgi?id=72058
        // getElementsByTagName returns empty nodelist for some unknown reason.

        // Get elements.
        Collapse = document.getElementsByTagName("DIV");
        // Collapse elements.
        for (i=0 ; i < Collapse.length ; i++) {
            // Collapse elements with class="text".
            // Use XML interface of DOM instead of HTML interface.
            if (Collapse[i].getAttribute("class") == "text") {
                Collapse[i].style.display = "none";
            }
        }

        // Change collapse state to make "expand/collapse all" work correctly.
        // This is due to the previously mentioned bug...
        if(Collapse.length <= 0) {
            isExpanded = true;
        }
    } else if (is.ie) {
        // This is for IE.
        Collapse = document.all.tags("DIV");
        for (i=0; i<Collapse.length; i++) {
            if (Collapse(i).className == "text") {
                Collapse(i).style.display = "none";
            }
        }
    }
}


/**
 * Opens a large pop-up window.
 *
 * @param event      the onclick event
 * @param targetfile URL of the file which will be opened to the new window
 */
function openLargePopup(event,targetfile)
{
    openPopup(event, targetfile, 500, 300);
}


/**
 * Opens a small pop-up window.
 *
 * @param event      the onclick event
 * @param targetfile URL of the file which will be opened to the new window
 */
function openSmallPopup(event,targetfile)
{
    openPopup(event, targetfile, 300, 150);
}


/**
 * Opens a pop-up window.
 *
 * NOTE! Opera will not open a new window unless
 *       File/Preferences.../Windows/Allow documents to create windows
 *       is checked
 *
 * @param event      the onclick event
 * @param targetfile URL of the file which will be opened to the new window
 * @param windowX    width of the new window in pixels
 * @param windowY    height of the new window in pixels
 */
function openPopup(event, targetfile, windowX, windowY) {
    var x = event.screenX;
    var y = event.screenY;
    var width = screen.width;
    var height = screen.height;

    // If the window will not fit into the screen area, adjust the entry coordinates.
    // The extra pixels facilitate the window header and scrollbars. They are just
    // approximations and can be adjusted as needed.
    if (x + windowX > width) {
        x = width - (windowX + 20);
    }
    if (y + windowY > height) {
        y = height - (windowY + 40);
    }

    var windowName = Math.round(Math.random() * 100000);
    var openstring = "resizable=yes,scrollbars=yes,height=" + windowY
                     + ",width=" + windowX + ",left=" + x + ",top=" + y;
    msg = window.open(targetfile, windowName, openstring);
    msg.focus();
}


/*
 * Expands or collapses an one block in the document.
 *
 * block: First part of the block ID. Something like "block1" when the whole
 *        ID is "block1Text"
 */
function expandBlock(block) {

    if(is.nav6up) {
        var node;               // Block to be expanded/collapsed.
        var allImages;          // All images in the document.
        var image;              // Image which is associated with the block.
        var i;                  // Loop counter.


        // Get the block node.
        node = document.getElementById(block + 'Text');

        // images attribute from HTML interface of DOM could be used to 
        // do the same as the following loop. 
        // I just don't like the HTML interface...

        // Get all images.
        allImages = document.getElementsByTagName("IMG");
        // Get the image associated with the block.
        for (i=0 ; i < allImages.length ; i++) {
            if(allImages[i].getAttribute("name") == block + "Title") {
                // Image found.
                image = allImages[i];
                break;
            }
        }

        // Set expand/collapse and the correct image.
        if(node.style.display == "none") {
            // Block is collapsed, so expand it.
            node.style.display = "block";
            // Show correct image.
            if(image != null) {
                image.setAttribute("src", collapseIcon);
                image.style.display = "inline";
            }
        } else {
            // Block expanded, so collapse it.
            node.style.display = "none";
            // Show correct image.
            if(image != null) {
                image.setAttribute("src", expandIcon);
                image.style.display = "inline";
            }
        }
    } else {
        // IE version.

        whichBlock = eval(block + "Text");

        whichImage = document.images.item(block + "title");
        if (whichBlock.style.display == "none") {
            whichBlock.style.display = "block";
            whichImage.src = collapseIcon;
        }
        else {
            whichBlock.style.display = "none";
            whichImage.src = expandIcon;
        }
    }
}


/*
 * Expands or collapses all blocks in the document.
 */
function ExpCollAll()
{
    var DivCollapse;                // All nodes to be expanded/collapsed.
    var ImageCollapse;              // All image elements associated with the
                                    // nodes. 
    var NewImage;                   // Image which will be set in the operation.
    var i;                          // Loop counter.


    // Select correct image.
    NewImage = (isExpanded)
                ? expandIcon
                : collapseIcon;

    if(is.nav6up) {
        // Get the nodes and expand/collapse them.
        DivCollapse = document.getElementsByTagName("DIV");
        for (i=0 ; i < DivCollapse.length ; i++) {
            if (DivCollapse[i].getAttribute("class") == "text") {
                DivCollapse[i].style.display = (isExpanded) ? "none" : "block";
            }
        }

        // Change the images associated with the nodes.
        ImageCollapse = document.getElementsByTagName("IMG");
        for (i=0 ; i < ImageCollapse.length ; i++) {
            if (ImageCollapse[i].getAttribute("class") == "ExpColl") {
                ImageCollapse[i].setAttribute("src", NewImage);
                ImageCollapse[i].style.display = "inline";
            }
        }
    } else {
        DivCollapse = document.all.tags("DIV");
        for (i=0; i<DivCollapse.length; i++) {
            if (DivCollapse(i).className == "text") {
                DivCollapse(i).style.display = (isExpanded) ? "none" : "block";
            }
        }

        ImageCollapse = document.all.tags("IMG");
        for (i=0; i<ImageCollapse.length; i++) {
            if (ImageCollapse(i).className == "ExpColl") {
                ImageCollapse(i).src = NewImage;
            }
        }

    }

    // Change the expand/collapse status.
    isExpanded = !isExpanded;
}




///////////////////////// TOC ////////////////////////////

/*
 * Generates a query which contains enough information to synchronize 
 * TOC page with the referred document and updates toc_content frame.
 *
 * Side effects: toc frame is updated.
 *
 * Tested with: Mozilla 2002030604, NN4.75, IE4, IE5.5, Opera 6.01
 *
 * @param element A element which contains link to the referred document.
 */
function sync(element) {
	if(parent.toc != null) {
		if((parent.toc.toc_content != null) && (element.href.indexOf("NED?") != -1)) {
			// Get NED and TOC requests.
			var documentQuery = getNEDQuery(element.href);
			var tocQuery = getTargetToCRequest(getTOCQuery(), documentQuery);
			// Split TOC request.
			var queryStart = tocQuery.substr(0, (tocQuery.indexOf("?") + 1));
			var queryEnd = tocQuery.substr(tocQuery.indexOf("?") + 1);
			// Add default pointer if pointer doesn't exist.
			if(queryEnd.indexOf("#") == -1) {
				queryEnd = queryEnd + "#target";
			}
			// All done, open ToC.
			window.open(queryStart + documentQuery + "&" + queryEnd, "toc_content");
		}
	}
}

/*
 * Changes ToC request so that the correct ToC is opened to the 
 * ToC frame. Note that the given ToC request is not modified
 * but a completely new request is generated.
 *
 * Tested with: Mozilla 2002030604, NN4.75, IE4, IE5.5, Opera 6.01
 *
 * @param tocRequest Request currently in the ToC frame.
 * @param documentRequest NED request used to synchronize the ToC.
 *
 * @return ToC request.
 */
function getTargetToCRequest(tocRequest, documentRequest) {

	var result = tocRequest;	// Resulting ToC request.
	// Change ToC request to open Glossary if the document request is 
	// a glossary reference.
	if((documentRequest.indexOf("identifier=dn9763965") != -1) 
		|| (documentRequest.indexOf("identifier=general_glossary") != -1)) {
		if(tocRequest.indexOf("encoding=ned_glossary_1_0") == -1) {
			result = getToCRequestFromHeader("ned_glossary_1_0");
		}
		return result;
	}
	// Open PDF List ToC.
	if((documentRequest.indexOf("encoding=pdf") != -1) || 
		(documentRequest.indexOf("encoding=oem_pdf") != -1)) {
		if(tocRequest.indexOf("encoding=ned_pdf_toc_1_0") == -1) {
			result = getToCRequestFromHeader("ned_pdf_toc_1_0");
		}
		return result;
	}
	// Open normal ToC if NED Help ToC is open.
	if(tocRequest.indexOf("identifier=dn01175013") != -1) {
		result = getToCRequestFromHeader("ned_toc_1_0");
		return result;
	}
	// Change ToC request to open NED ToC.
	if(tocRequest.indexOf("encoding=ned_toc_1_0") == -1) {
		result = getToCRequestFromHeader("ned_toc_1_0");
	}
	// No matches, return the given request.
	return result;
}

/*
 * Reads the Home request from the header frame and modifies it 
 * to be a correct ToC request.
 *
 * Tested with: Mozilla 2002030604, NN4.75, IE4, IE5.5, Opera 6.01
 *
 * @param encoding Encoding in the resulting request.
 *
 * @return ToC request or an empty string if input request is not found.
 */
function getToCRequestFromHeader(encoding) {

	var headerLinks = parent.header.document.links;

	for(i = 0 ; i < headerLinks.length ; i++) {
		var url = new String(headerLinks[i].href);
		if(url.indexOf("fragment") != -1) {
			// This should be the correct request.
			// Remove invalid parameters and 
			// add correct encoding parameter.
			var result = removeQueryParameter(url, "encoding=");
			result = removeQueryParameter(result, "action=");
			result = "encoding=" + encoding + "&" + result.substr(result.indexOf("?") + 1);
			result = "TOC?" + result;
			return result;
		}
	}
	return "";
}

/*
 * Modifies the address of the page in toc_content frame.
 * The only modification is that action parameter is removed.
 *
 * Tested with: Mozilla 2001092703, NN4.75, IE4, IE5.5
 *
 * @return Modified TOC query.
 */
function getTOCQuery() {
	// Remove old NED parameters, otherwise URL blows up.
	var truncatedHref = removeQueryParameter(parent.toc.toc_content.location.href, "NED");
	truncatedHref = removeQueryParameter(truncatedHref, "move=");
	truncatedHref = removeQueryParameter(truncatedHref, "title=");
	truncatedHref = removeQueryParameter(truncatedHref, "relevance=");
	truncatedHref = removeQueryParameter(truncatedHref, "description=");
	return removeQueryParameter(truncatedHref, "action=");
}

/*
 * Modifies NED query to contain unique parameter names and changes action
 * parameter to contain "ned" value.
 *
 * All parameters except action are prefixed with "NED" string. The values 
 * of those parameters stay the same.
 *
 * Tested with: Mozilla 2002030604, NN4.75, IE4, IE5.5, Opera 6.01
 *
 * @param q NED query.
 *
 * @return  Modified ND query.
 */
function getNEDQuery(q) {

    // Query without useless parameters.
    var nedQuery = removeQueryParameter(q, "action=");
	nedQuery = removeQueryParameter(nedQuery, "title=");
	nedQuery = removeQueryParameter(nedQuery, "relevance=");
	nedQuery = removeQueryParameter(nedQuery, "description=");

    // Remove query mark and everything before it.
    if(nedQuery.indexOf("?") >= 0) {
        nedQuery = nedQuery.substr(nedQuery.indexOf("?")+1);
    }
    // Add new action parameter.
    nedQuery = "action=ned" + (nedQuery != "" ? "&" : "") + nedQuery;

    // Rename existing parameters.
    var property = new RegExp("identifier=");
    nedQuery = nedQuery.replace(property, "NEDidentifier=");
    property = new RegExp("edition=");
    nedQuery = nedQuery.replace(property, "NEDedition=");
    property = new RegExp("language=");
    nedQuery = nedQuery.replace(property, "NEDlanguage=");
    property = new RegExp("coverage=");
    nedQuery = nedQuery.replace(property, "NEDcoverage=");
    property = new RegExp("encoding=");
    nedQuery = nedQuery.replace(property, "NEDencoding=");
    property = new RegExp("fragment=");
    nedQuery = nedQuery.replace(property, "NEDfragment=");
    property = new RegExp("pointer=");
    nedQuery = nedQuery.replace(property, "NEDpointer=");
    property = new RegExp("component=");
    nedQuery = nedQuery.replace(property, "NEDcomponent=");
    property = new RegExp("item=");
    nedQuery = nedQuery.replace(property, "NEDitem=");
    property = new RegExp("product_release=");
    nedQuery = nedQuery.replace(property, "NEDproduct_release=");
	// Finally, remove pointer mark. Otherwise browser doesn't send it.
    property = new RegExp("#");
    nedQuery = nedQuery.replace(property, "_");
	if(is.opera) {
		// Add missing pointer information to the request.
		if(nedQuery.indexOf("pointer=") != -1) {
			nedQuery = nedQuery + "_" + nedQuery.substr(nedQuery.indexOf("pointer=") + 8);
		}
	}

    return nedQuery;
}

/*
 * Removes the defined parameter and its value from the request.
 *
 * Tested with: Mozilla 2002030604, NN4.75, IE4, IE5.5, Opera 6.01
 *
 * @return Query without the defined parameter.
 */
function removeQueryParameter(q, parameter) {

	var result = "";
	var queryStart = q.substr(0, (q.indexOf("?") + 1));
	var parameters = q.substr(q.indexOf("?") + 1);
	var splitQ = parameters.split("&");  // Query as an array of tokens.

	// Generate the result query by concatenating all tokens except the one
	// given in the parameters.
	for(var i = 0 ; i < splitQ.length ; i++) {
		if(splitQ[i].indexOf(parameter) < 0) {
			result = result + (result != "" ? "&" : "") + splitQ[i];
		} else {
			// Add pointer back to query if it exists.
			if(((i+1) == splitQ.length) && (splitQ[i].indexOf("#") != -1)) {
				result = result + splitQ[i].substr(splitQ[i].indexOf("#"));
			}
		}
	}

	return (queryStart + result);
}
