/**
 * Contains common functions for use on front-end
 * @version $Revision: 1.33.2.2.2.4 $
 */

/**
 * 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', 'yes');
    }
    return false;
}

/**
 * Opens a new popup window
 */
function popup(anchor, w, h, location, menubar, toolbar, status, scrollbars)
{
    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 + ',scrollbars=' + scrollbars;

    var win      = window.open(anchor, win, features);
    win.focus();

    return win;
}


/**
 * Sets a random banner on a given <a> node with child <img>
 * @param string DOMNode The <a> node to apply banner on
 * @param Array bannerPositionData An array holding banner data for the position
 * @return void
 */
function randomBanner(oldNode, bannerPositionData)
{
    // 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].urltitle;

    if (visualPosition in bannerPositionData[bannerPosition].visuals) {

        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 newNode;

        // create new visual node
        if (visualType == 'application/x-shockwave-flash') {

            // create flash object node
            var newNode = document.createElement('object');

            newNode.setAttribute('type', visualType);
            newNode.setAttribute('width', visualWidth);
            newNode.setAttribute('height', visualHeight);
            newNode.setAttribute('data', visualSrc);
            newNode.setAttribute('id', oldNode.getAttribute('id'));

            var params = Object();
            params['FlashVars'] = 'clickTAG=' + bannerUrl + '&external=' + ((bannerPositionData[bannerPosition].external == 1) ? 'true' : 'false');
            params['movie'] = visualSrc;
            params['wmode'] = bannerPositionData[bannerPosition].visuals[visualPosition].wmode;
            params['menu'] = bannerPositionData[bannerPosition].visuals[visualPosition].menu;

            var paramNode;

            for (e in params) {
                paramNode = document.createElement('param');
                paramNode.setAttribute('name', e);
                paramNode.setAttribute('value', params[e]);
                newNode.appendChild(paramNode);
            }

        } else {

            // create img node
            var newNode = document.createElement('a');

            newNode.setAttribute('href', bannerUrl);
            newNode.setAttribute('title', bannerTitle);
            newNode.setAttribute('id', oldNode.getAttribute('id'));
            if (bannerPositionData[bannerPosition].external == 1) {
                newNode.setAttribute('rel', 'external');
                newNode.setAttribute('target', '_blank');
            }

            var visualNode = document.createElement('img');
            visualNode.setAttribute('src', visualSrc);

            if (visualWidth > 0) visualNode.setAttribute('width', visualWidth);
            if (visualHeight > 0) visualNode.setAttribute('height', visualHeight);

            newNode.appendChild(visualNode);

        }
    }

    if (newNode) {
        // replace visual node
        oldNode.parentNode.insertBefore(newNode, oldNode);
        oldNode.parentNode.removeChild(oldNode);
    }
}


/**
 * 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;
    }
}

/* ----------------
 * HIKING FUNCTIONS
 * ---------------- */


/**
 * Changes background image of a node
 */
function swapBgImage(node, src)
{
    if (node != '' && src != '') node.style.backgroundImage = 'url(' + src + ')';
}

// applies hover event to element after rendering page. used for dynaamic content, such as dynamic menu images
function applyHoverEvent(id, mouseout, mouseover) {

  var e = document.getElementById(id);

  if (e && mouseout && mouseover) {

    e.over = mouseover;
    e.out = mouseout;
    e.el = e;

    if (window.addEventListener) {
      e.addEventListener('mouseover', over, false);
      e.addEventListener('mouseout', out, false);
    } else {
      e.attachEvent('onmouseover', over);
      e.attachEvent('onmouseout', out);
    }
  }
}

function over(e) {
  var target = e['target'] ? 'target' : 'srcElement'; // Gecko uses target to access element properties, IE uses srcElement
  swapBgImage(e[target]['el'], e[target]['over']);
}

function out(e) {
  var target = e['target'] ? 'target' : 'srcElement'; // Gecko uses target to access element properties, IE uses srcElement
  swapBgImage(e[target]['el'], e[target]['out']);
}


/**
 * Apply 'onload' events
 */
addLoadEvent(applyEvents);
addLoadEvent(eventLinks);
addLoadEvent(preloadImages);
addLoadEvent(backLink);
addUnloadEvent(EventCache.flush);

