/*
 * =================================================================
 * Gossamer Forum - Advanced web community
 *
 *   Website  : http://gossamer-threads.com/
 *   Support  : http://gossamer-threads.com/scripts/support/
 *   Revision : $Id: utils.js,v 1.6 2007/11/15 02:04:06 brewt Exp $
 *  
 * Copyright (c) 2006 Gossamer Threads Inc.  All Rights Reserved.
 * Redistribution in part or in whole strictly prohibited. Please
 * see LICENSE file for full details.
 * =================================================================
 */

/*
Event Handler
=============
Description:
    A cross-browser event handler.
Usage:
    registerEvent(<html_object>, <event>, <handler>);
    unregisterEvent(<html_object>, <event>, <handler>);
Example:
    registerEvent(window, 'load', myhandler);
Notes:
    html_object is a html object that you wish to register the event on.
    event is a string containing the event you wish to register, eg. 'load'.
    handler is a function reference for the code you wish to run when the
        event is fired.
*/

function registerEvent(obj, evt, handler) {
    if (!(obj && evt && handler))
        return;

    if (obj.addEventListener)
        obj.addEventListener(evt, handler, false);
    else if (obj.attachEvent)
        obj.attachEvent('on' + evt, handler);
}

function unregisterEvent(obj, evt, handler) {
    if (!(obj && evt && handler))
        return;

    if (obj.removeEventListener) {
        try { obj.removeEventListener(evt, handler, false); } catch (e) {};
    }
    else if (obj.detachEvent) {
        try { obj.detachEvent('on' + evt, handler); } catch (e) {};
    }
}

function stopPropagation(evt) {
    if (!evt)
        return;

    if (evt.stopPropagation)
        evt.stopPropagation();
    else
        evt.cancelBubble = true;
}

function cancelEvent(evt) {
    if (!evt)
        return;

    if (evt.preventDefault && evt.cancelable)
        evt.preventDefault();
    else
        evt.returnValue = false;
}

/*
Check All Checkbox
==================
Description:
    Code to implement a check all checkbox.
Usage:
    checkAllInit(<checkbox_name>, <checkall_id>);
Example:
    registerEvent(window, 'onload', function () { checkAllInit('ID', 'checkall') });
*/
var _checkAllLastChecked = {};
function checkAllInit(checkBoxes, checkAllBox) {
    var oForm, oCheckBoxes, oCheckAllBox;
    if (!((oCheckAllBox = document.getElementById(checkAllBox)) &&
        (oForm = oCheckAllBox.form) &&
        (oCheckBoxes = oForm.elements[checkBoxes])))
        return;

    registerEvent(oCheckAllBox, 'click', function () { _checkAllBoxes(checkBoxes, checkAllBox) });
    if (!oCheckBoxes.length)
        oCheckBoxes = [oCheckBoxes];

    var allChecked = true;
    for (var i = 0; i < oCheckBoxes.length; i++) {
        // This weird next line is simply to provide localized scoping for i/boxPos:
        registerEvent(oCheckBoxes[i], 'click', function () { var boxPos = i; return function (ev) { _updateAllBoxes(checkBoxes, checkAllBox, boxPos, ev) } }());

        if (!oCheckBoxes[i].checked) allChecked = false;
    }
    oCheckAllBox.checked = allChecked;
}

function _checkAllBoxes(checkBoxes, checkAllBox) {
    checkAllBox = document.getElementById(checkAllBox);
    var form = checkAllBox.form;
    checkBoxes = form.elements[checkBoxes];
    if (!checkBoxes.length)
        checkBoxes = [checkBoxes];
    for (var i = 0; i < checkBoxes.length; ++i)
        checkBoxes[i].checked = checkAllBox.checked;
}

function _updateAllBoxes(checkBoxes, checkAllBox, boxPos, evnt) {
            
    checkAllBox = document.getElementById(checkAllBox);
    var form = checkAllBox.form;
    checkBoxes = form.elements[checkBoxes];
    if (!checkBoxes.length)
        checkBoxes = [checkBoxes];

    // Holding shift when clicking on a box selects everything from the previous box to the current one:
    var lastCheckedBox = _checkAllLastChecked[checkAllBox.id];
    if (evnt && evnt.shiftKey && lastCheckedBox && checkBoxes[boxPos].checked) {
        for (var i = boxPos; i != lastCheckedBox-1; i += lastCheckedBox-1 < i ? -1 : 1) {
            checkBoxes[i].checked = true;
        }
    }
    // boxPos+1 here and -1 above so that lastCheckedBox can be checked for truth, and 0 is false
    _checkAllLastChecked[checkAllBox.id] = checkBoxes[boxPos].checked ? boxPos+1 : false;

    var allChecked = true;
    for (var i = 0; i < checkBoxes.length; ++i)
        if (!checkBoxes[i].checked) {
            allChecked = false;
            break;
        }
    checkAllBox.checked = allChecked;
}

/*
Find Element Position
=====================
Description:
    Find the position of an element.
    http://www.quirksmode.org/js/findpos.html
Usage:
    findPosX(<element>);
    findPosY(<element>);
*/

function findPosX(obj) {
    var curleft = 0;
    if (obj.offsetParent)
        while (obj.offsetParent) {
            curleft += obj.offsetLeft
            obj = obj.offsetParent;
        }
    else if (obj.x)
        curleft += obj.x;
    return curleft;
}

function findPosY(obj) {
    var curtop = 0;
    if (obj.offsetParent)
        while (obj.offsetParent) {
            curtop += obj.offsetTop
            obj = obj.offsetParent;
        }
    else if (obj.y)
        curtop += obj.y;
    return curtop;
}

function getStyle(obj, property) {
    if (document.defaultView && document.defaultView.getComputedStyle) {
// Safari can return undefined if the element is display: none
        var style = document.defaultView.getComputedStyle(obj, null);
        if (style)
            return style.getPropertyValue(property);
    }
    else if (obj.currentStyle) {
        property = property.replace(/-(.)/g, function (str, p1) { return p1.toUpperCase() });
        return obj.currentStyle[property];
    }
}

// Note that this will only return pixel lengths.  Only Mozilla and Opera always return pixel units for lengths.
function getStyleLength(obj, property) {
    var length = getStyle(obj, property);
    if (length.match(/^\d+(?:\.\d+)?px$/))
        return parseFloat(length);
    return 0;
}

function calcCSSWidth(obj, width) {
    if (isIE && ieVersion <= 5.5)
        return width + 'px';
    return width -
        getStyleLength(obj, 'padding-left') -
        getStyleLength(obj, 'padding-right') -
        getStyleLength(obj, 'border-left-width') -
        getStyleLength(obj, 'border-right-width') + 'px';
}

function calcCSSHeight(obj, height) {
    if (isIE && ieVersion <= 5.5)
        return height + 'px';
    return height -
        getStyleLength(obj, 'padding-top') -
        getStyleLength(obj, 'padding-bottom') -
        getStyleLength(obj, 'border-bottom-width') -
        getStyleLength(obj, 'border-bottom-width') + 'px';
}

/*
HTML Escape/Unescape
====================
*/ 

function htmlEscape(text) {
    return text.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
}

function htmlUnEscape(text) {
    return text.replace(/&quot;/gi, '"').replace(/&gt;/gi, '>').replace(/&lt;/gi, '<').replace(/&amp;/gi, '&');
}

var isOpera = false;
var operaVersion;
var isIE = false;
var ieVersion;
var isMozilla = false;
var mozillaVersion;
var isWebkit = false;
var webkitVersion;

var ua = navigator.userAgent;
// http://opera.com/support/search/supsearch.dml?index=570
if (ua.match(/Opera(?:\s+|\/)([0-9.]+)/i)) {
    isOpera = true;
    operaVersion = RegExp.$1;
}
else if (ua.match(/MSIE\s+([0-9.]+)/i)) {
    isIE = true;
    ieVersion = RegExp.$1;
}
else if (ua.match(/Mozilla\/([0-9.]+)\s+\([^)]+rv:([0-9.]+)/i)) {
    isMozilla = true;
    mozillaVersion = RegExp.$2;
}
// http://developer.apple.com/internet/safari/uamatrix.html
else if (ua.match(/AppleWebKit\/([0-9.]+)/i)) {
    isWebkit = true;
    webkitVersion = RegExp.$1;
}

/* Appends various hidden values to and submits a form.  Takes the form element
 * and an array of param => value pairs, and submits the form.
 */

var _submitForm_Div;
function submitForm (form, params) {
    if (_submitForm_Div)
        _submitForm_Div.parentNode.removeChild(_submitForm_Div);
    _submitForm_Div = document.createElement('div');
    _submitForm_Div.id = '_submitForm_Div';
    _submitForm_Div.style.display = 'none';
    form.appendChild(_submitForm_Div);
    var i, hidden;
    for (i = 0; i < params.length; i += 2) {
        hidden = document.createElement('input');
        hidden.type = 'hidden';
        hidden.name = params[i];
        hidden.value = params[i+1];
        _submitForm_Div.appendChild(hidden);
    }
    var submit = document.createElement('input');
    submit.type = 'submit';
    _submitForm_Div.appendChild(submit);
    submit.click();
    return false;
}


/* Takes an element, goes through its childNodes, and removes them all.
 * Returns the element itself, to allow chaining. */
function killChildren (e) {
    while (e.childNodes.length) e.removeChild(e.childNodes[0]);
    return e;
}


/* XMLHttpRequest wrapper - takes a url, method (e.g. 'GET'), body (i.e. for a
 * POST request), success function and failure function.  The functions will be
 * called with the XMLHttpRequest object as argument.
 */

function xmlReqSend (url, method, content, onsuccess, onfailure) {
    var req;
    if (!method) method = "GET";
    else method = method.toUpperCase();
    if (method != "GET" && method != "POST" && method != "HEAD") method = "GET";

    if (window.XMLHttpRequest)
        req = new XMLHttpRequest();
    else if (window.ActiveXObject) {
        try {
            req = new ActiveXObject('Msxml2.XMLHTTP');
        }
        catch (e) {
            try {
                req = new ActiveXObject("Microsoft.XMLHTTP");
            }
            catch (e) {
                req = false;
            }
        }
    }

    if (req) {
        req.onreadystatechange = function () { _xmlReqChange(req, onsuccess, onfailure); };
        url = url.replace(/^https?:\/\/[^\/]+\//, '/');
        req.open(method, url, true);
        req.send(content);
    }
}

function _xmlReqChange (req, success, failure) {
    if (req.readyState == 4) {
        if (req.status == 200) {
            if (success) success(req);
        }
        else {
            if (failure) failure(req);
        }
    }
}

function insertText(element, text) {
    if (element.setSelectionRange) {
        var start = element.selectionStart;
        var end = element.selectionEnd;
        element.value = element.value.substr(0, start) + text + element.value.substr(end, element.value.length);
// Set the caret to be right after the text that was just inserted.
        start += text.length;
        setSelectionRange(element, start, start);
    }
    else if (document.selection) {
        element.focus();
        var range = document.selection.createRange();
        if (range.parentElement() != element)
            return;
        range.text = text;
    }
    else {
        element.value += text;
    }
}

function wrapText(element, pre_text, post_text) {
    if (element.setSelectionRange) {
        var start = element.selectionStart;
        var end = element.selectionEnd;
        element.value = element.value.substr(0, start) + pre_text + element.value.substr(start, end - start) + post_text + element.value.substr(end, element.value.length);
        setSelectionRange(element, start + pre_text.length, end + pre_text.length);
    }
    else if (document.selection) {
        element.focus();
        var range = document.selection.createRange();
        if (range.parentElement() != element)
            return;
        var len = range.text.length;
        range.text = pre_text + range.text + post_text;
        range.moveEnd('character', -post_text.length);
        range.moveStart('character', -len);
        range.select();
    }
    else {
        element.value += pre_text + post_text;
    }
}

function setSelectionRange(element, start, end) {
    if (element.setSelectionRange) {
        element.focus();
        element.setSelectionRange(start, end);
    }
    else if (element.createTextRange) {
        var range = element.createTextRange();
        range.collapse(true);
        range.moveEnd('character', end);
        range.moveStart('character', start);
        range.select();
    }
}

var max_x;
var max_y;
function resizeImage(img, x, y) {
    x = x ? x : max_x;
    y = y ? y : max_y;
    var width = 0;
    var height = 0;
    if (x && x < img.width)
        width = x;
    if (y && y < img.height)
        height = y;
    if (width && height) {
        if ((img.width > width && img.height <= height) || (img.width > width && img.height > height && width < height))
            height = 0;
        else
            width = 0;
    }
    if (width > 0)
        img.width = width;
    if (height > 0)
        img.height = height;
    if (width > 0 || height > 0) {
        var link = document.createElement('a');
        link.title = "Click to view full sized image";
        link.href = img.src;
        link.target = '_blank';
        img.parentNode.replaceChild(link, img);
        link.appendChild(img);
    }
}
