/**
 * Contains common functions for use on front-end
 * @version $Revision: 1.34.28.1 $
 */

/**
 * arrays for use later on
 */
var preloadimages = new Array();
var events = new Array();


/* ----------------
 * COMMON FUNCTIONS
 * ---------------- */

function is_array(array)
{
    return (array instanceof Array);
}


function in_array(needle, haystack)
{
    if ((needle != '') && (haystack.length > 0)) {
        for (var i = 0; i < haystack.length; i++) {
            if (haystack[i] == needle) return true;
        }
    }
    return false;
}

function isset(obj)
{
    return (typeof obj != 'undefined');
}

/* ----------------
 * MISCELLANEOUS FUNCTIONS
 * ---------------- */

/**
 * Enable scrolling for overflow:auto elements in Mozilla
 */
function scrollMe(e)
{
    var scrollTop = e.currentTarget.scrollTop + (e.detail * 12);
    e.currentTarget.scrollTop = scrollTop < 0 ? 0 : scrollTop;
    e.preventDefault();
}

function scroll(e)
{
    if (document.body.addEventListener) {
        try {
            document.getElementById(e).addEventListener('DOMMouseScroll', scrollMe, false);
        } catch (ex) {
        }
    }
}

/**
 * Adds image to preload stack
 * The stack is processed in preloadImages()
 * @param string src The image src
 * @return void
 */
function preparePreloadImage(src)
{
    for (i in window.preloadimages) if (window.preloadimages[i] == src) return;
    window.preloadimages.push(src);
}

/**
 * Preloads images set in window.preloadimages
 * @return void
 */
function preloadImages()
{
    if (preloadimages.length > 0) {
        for (var i = 0; i < preloadimages.length; i++) {
            preloadImg(preloadimages[i]);
        }
    }
}

/**
 * Adds image (invisible) to body so that it will be preloaded
 * @return void
 */
function preloadImg(src)
{
    var img = document.createElement('img');
    img.setAttribute('src', src);
    img.setAttribute('width', 0);
    img.setAttribute('height', 0);
    img.style.display = 'none';

    document.getElementsByTagName('body').item(0).appendChild(img);
}

/**
 * Prints current screen
 */
function printScreen(e)
{
    cancelEvent(e);
    window.print();
}

/**
 * Navigates browser window back 1 page in history
 */
function goBack(e)
{
    cancelEvent(e);
    history.back();
}

/**
 * Closes window
 */
function closeWindow(e)
{
    cancelEvent(e);
    window.close();
}

function onPopup(e)
{
    var target = getTarget(e);
    var node = document.getElementById(target.properties.targetid);

    cancelEvent(e);

    if (node.value != '') {
        popup(target,target.properties.targetwidth,target.properties.targetheight,target.properties.targethref, 'no', 'no', 'no');
    }
    return false;
}

/**
 * Opens a new popup window
 */
function popup(anchor, w, h, location, menubar, toolbar, status)
{
    var width    = w ? w : screen.width * 0.8;
    var height   = h ? h : screen.height * 0.8;
    var features = 'width=' + width + ',height=' + height + ',location=' + location + ',menubar=' + menubar + ',toolbar=' + toolbar + ',status=' + status;

    var win      = window.open(location, win, features);
    win.focus();

    return win;
}


/**
 * Sets a random banner on a given node
 * @param string id The node id to change banner for
 * @param Array bannerPositionData An array holding banner data for the position
 * @return void
 */
function randomBanner(id, bannerPositionData)
{
    // get banner div
    var bannerDiv = document.getElementById(id);

    // get a random bannerposition
    var bannerWeights = new Array();
    for (var i in bannerPositionData) {
        bannerWeights[i] = bannerPositionData[i].weight;
    }
    var bannerPosition = arrayFactorRand(bannerWeights);

    // get a random bannervisual within the chosen bannerposition
    var visualWeights = new Array();
    for (var j in bannerPositionData[bannerPosition].visuals) {
        visualWeights[j] = bannerPositionData[bannerPosition].visuals[j].weight;
    }
    var visualPosition = arrayFactorRand(visualWeights);

    // get the other variables
    var bannerUrl = bannerPositionData[bannerPosition].url;
    var bannerTitle = bannerPositionData[bannerPosition].title;
    var urlTitle = bannerPositionData[bannerPosition].urltitle;

    if (!(bannerPositionData[bannerPosition] && bannerPositionData[bannerPosition].visuals[visualPosition])) return;

    var visualSrc = bannerPositionData[bannerPosition].visuals[visualPosition].filename;
    var visualTitle = bannerPositionData[bannerPosition].visuals[visualPosition].title;
    var visualWidth = bannerPositionData[bannerPosition].visuals[visualPosition].width;
    var visualHeight = bannerPositionData[bannerPosition].visuals[visualPosition].height;
    var visualType = bannerPositionData[bannerPosition].visuals[visualPosition].type;

    var bannerVisualDiv = document.createElement('div');
    bannerVisualDiv.className = 'bannervisual';

    // create new visual node
    if (visualType == 'application/x-shockwave-flash') {

        // create flash object node
        var html;

        // Flash banner
        html = '<object type="' + visualType + '" width="' + visualWidth + '" height="' + visualHeight + '" data="' + visualSrc + '">';

        // params
        html += '<param name="FlashVars" value="' + 'clickTag=' + bannerUrl + '&external=' + ((bannerPositionData[bannerPosition].external == 1) ? 'true' : 'false') + '">';
        html += '<param name="movie" value="' + visualSrc + '">';
        html += '<param name="wmode" value="' + (bannerPositionData[bannerPosition].visuals[visualPosition].wmode || 'transparent') + '">';
        html += '<param name="menu" value="' + (bannerPositionData[bannerPosition].visuals[visualPosition].menu || 'false') + '">';
        html += '</object>';

        bannerVisualDiv.innerHTML = html;

    } else {
        var anchor = document.createElement('a');
        anchor.setAttribute('href', bannerUrl);

        if (bannerPositionData[bannerPosition].external == 1) {
            anchor.setAttribute('rel', 'external');
            anchor.setAttribute('target', '_blank');
        }

        var img = document.createElement('img');
        img.setAttribute('src', visualSrc);
        img.setAttribute('alt', visualTitle);
        img.setAttribute('width', visualWidth);
        img.setAttribute('height', visualHeight);

        anchor.appendChild(img);

        bannerVisualDiv.appendChild(anchor);
    }

    // append visual div
    bannerDiv.appendChild(bannerVisualDiv);

}

/**
 * Redirects browser to event target's value (target should be input box)
 */
function redirect(e)
{
    var target = getTarget(e);
    var node = document.getElementById(target.redir_id);

    cancelEvent(e);

    if (node.value != '') {
        window.location.href = node.value + ( (node.value.indexOf('?') > 0) ? '&redir=1' : '?redir=1');
    }
    return false;
}

/**
 * Returns random element from array using weight factors as values
 * @param Array factors The array holding the factors (integers)
 * @return mixed The 'lucky' key
 */
function arrayFactorRand(factors)
{
    var factorTotals = 0;
    var factorEnds = new Array();
    var luckyKey = false;

    for (i in factors) {
        factorTotals += factors[i];
        factorEnds[i] = factorTotals;
    }

    var luckyNumber = Math.random() * factorTotals;

    for (i in factors) {
        if (factorEnds[i] > luckyNumber) {
            luckyKey = i;
            break;
        }
    }

    return luckyKey;
}

/**
 * Returns url fragment parameters as associative array
 * If the url looks like this: http://www.example.org/path/#a=1;b=2 then this
 * function returns an object holding a => 1, b => 2
 * @return Object|void An object holding key => value pairs or void if url fragment not found
 */
function getFragmentParams()
{
    var res = null;
    var fragment = getFragment(window.location.toString());

    if (fragment != '') {
        var parts = fragment.substr(1, fragment.length).split(';');

        if (parts.length > 1) {
            res = new Object();
            for (var i = 0; i < parts.length; i++) {
                part = parts[i];
                pos = part.search('=')
                if (pos) {
                    key = part.substr(0,pos);
                    value = part.substr(pos + 1, part.length - pos - 1);
                    res[key] = value;
                }
            }
        }
    }

    return res;
}

/**
 * Returns the 'fragment' part of a url (including the '#')
 * @param String url The url to parse
 * @return String The 'fragment' part of the url
 */
function getFragment(url)
{
    var fragmentRe = (/\#(.*)/).exec(url);
    var fragmentStr = '';

    if ((fragmentRe != null) && (fragmentRe.index > 1)) {
        fragmentStr = url.substr(fragmentRe.index, url.length);
    }
    return fragmentStr;
}

/* ----------------
 * EVENT FUNCTIONS
 * ---------------- */

/**
 * Parses anchors and span tags in page.
 * Applies event handlers to nodes with attributes for 'back', 'external' or 'print' links
 */
function eventLinks()
{
    if (!document.getElementsByTagName) return;

    var anchor, span, div, regexp, rel, className;
    var anchors = document.getElementsByTagName('a');
    var spans = document.getElementsByTagName('span');
    var divs = document.getElementsByTagName('div');
    var onclick = 'popup(this); return false;';

    for (var i = 0; i < anchors.length; i++) {
        anchor = anchors[i];
        rel = anchor.getAttribute('rel');

        if (rel != '') {
            regexp = new RegExp('\\bexternal\\b', 'i');
            if (regexp.test(rel)) {
                anchor.setAttribute('target', '_blank');
                var img = document.createElement('img');
                img.setAttribute('width', 16);
                img.setAttribute('height', 16);
                img.setAttribute('src', '/images/i_exlink.gif');
//                anchor.appendChild(img);
            }

            regexp = new RegExp('\\bback\\b', 'i');
            if (regexp.test(rel)) {
                applyEvent(anchor, 'click', goBack);
            }
        }
    }

    for (var i = 0; i < spans.length; i++) {
        span = spans.item(i);
        className = span.getAttribute('class') || span.getAttribute('className');

        if (className != '') {
            regexp = new RegExp('\\bprint\\b', 'i');
            if (regexp.test(className)) {
                var txtnode = document.createTextNode(span.getAttribute('title'));
                span.appendChild(txtnode);
                applyEvent(span, 'click', printScreen);
                span.style.display = 'block';
            }
        }
    }

    for (var i = 0; i < divs.length; i++) {
        div = divs.item(i);
        className = div.getAttribute('class') || div.getAttribute('className');

        if (className != '') {
            regexp = new RegExp('\\bclose\\b', 'i');
            if (regexp.test(className)) {
                var txtnode = document.createTextNode(div.getAttribute('title'));
                div.appendChild(txtnode);
                applyEvent(div, 'click', closeWindow);
            }
        }
    }
}

/**
 * Applies event to element with id 'back', when referrer is set
 */
function backLink()
{
    var back = document.getElementById('back');

    if (back) {
        if (document.referrer != '') {
            // create link
            var anchor = document.createElement('a');
            anchor.className = 'back';
            anchor.setAttribute('rel', 'back');
            anchor.setAttribute('href', document.referrer);
            anchor.appendChild(document.createTextNode(getText('Back')));

            applyEvent(anchor, 'click', goBack);

            back.appendChild(anchor);
        }
    }
}

/**
 * Adds event to stack
 * The stack will be processed in .onload()
 * @param string id The element id
 * @param string eventname The name of the event
 * @param string callback Function to callback to
 * @param array properties Array containing properties to apply to element
 * @return void
 */
function prepareEvent(id, eventname, callback, properties)
{
    var event = new Object();
    event.id = id;
    event.eventname = eventname;
    event.callback = callback;
    event.properties = new Array();

    if (properties instanceof Array) {
        for (var i = 0; i < properties.length; i++) {
            event.properties.push(properties[i]);
        }
    }
    window.events.push(event);
}

/**
 * Process events
 * This is done in body.onload()
 * @return void
 */
function applyEvents()
{
    var event;
    for (var i = 0; i < window.events.length; i++) {
        event = window.events[i];
        applyEvent(document.getElementById(event.id), event.eventname, event.callback, event.properties);
    }
}

/**
 * Attaches event to element, with given callback function and properties
 * @param DOMNode node The node to attach the event to
 * @param string event The event name
 * @param string callback The function to callback to
 * @param array properties The properties to be assigned to the node
 */
function applyEvent(node, event, callback, properties)
{
    if (node.attachEvent || node.addEventListener) {

        // get properties passed to this event
        if (properties) {
            node.properties = new Object();
            for (var i = 0; i < properties.length; i++) {
                for (var a in properties[i]) {
                    node.properties[a] = properties[i][a];
                }
            }
        }

        // add the event listener (respects IE's proprietary attachEvent function)
        if (node.addEventListener) {
            node.addEventListener(event, callback, false);
        } else if (node.attachEvent) {
            node.attachEvent('on'+event, callback);
        }

        // cache the event, to make sure it's unloaded
        EventCache.add(node, event, callback, false);
    }
}

/**
 * Add onload() event to the stack
 * @param callback func The callback (function name or inline function) to add
 * @return void
 * @author Simon Willison
 * @see http://simon.incutio.com/archive/2004/05/26/addLoadEvent
 */
function addLoadEvent(func)
{
    var oldonload = window.onload;
    if (typeof window.onload != 'function') {
        window.onload = func;
    } else {
        window.onload = function() {
            if (oldonload) {
              oldonload();
            }
            func();
        }
    }
}

/**
 * Add onunload() event to the stack (based on addLoadEvent)
 * @param callback func The callback (function name or inline function) to add
 * @return void
 * @author Simon Willison
 * @author Peter Kruithof
 */
function addUnloadEvent(func)
{
    var oldOnUnload = window.onunload;
    if (typeof window.onunload != 'function') {
        window.onunload = func;
    } else {
        window.onunload = function() {
            if (oldOnUnload) {
              oldOnUnload();
            }
            func();
        }
    }
}

/**
 * Returns event target.
 */
function getTarget(e)
{
    return e.target || e.srcElement;
}

/**
 * Cancels further event execution, stops bubbling
 */
function cancelEvent(e)
{
    if (isset(e.cancelable)) {
        if (e.cancelable) e.preventDefault();
        e.stopPropagation();
    } else {
        e.returnValue = false;
        e.cancelBubble = true;
    }
}

/**
 * Apply 'onload' events
 */
addLoadEvent(applyEvents);
addLoadEvent(eventLinks);
addLoadEvent(preloadImages);
addLoadEvent(backLink);

addUnloadEvent(EventCache.flush);

