/*global window,ActiveXObject,tinymce */

var tinyMCE, tinyMCE_GZ;
var jQuery = window.jQuery || window.jQ;

/** ** Utility functions *** */
function $(el) {
    if (typeof el === 'string') {
        el = document.getElementById(el);
    }
    return el;
}

// Global namespace
var IA = {};

/* Current revision - do not edit */
IA.Revision = '1283791304';

IA.each = function(list, callback) {
    for ( var i = 0; i < list.length; i++) {
        callback(list[i], i);
    }
};

IA.each_list_item = function(container, callback) {
    container = $(container);
    var ul = container.getElementsByTagName('ul')[0];
    if (!ul) {
        return;
    }
    IA.each(IA.get_children(ul, 'li'), callback);
};

IA.extend =
    function() {
        var target = arguments[0] || {}, length = arguments.length, options, name, src, copy, i;

        for (i = 1; i < length; i++) {
            if ((options = arguments[i]) !== null) {
                for (name in options) {
                    if (options.hasOwnProperty(name)) {
                        src = target[name];
                        copy = options[name];
                        if (target === copy) {
                            continue;
                        }
                        if (copy !== undefined) {
                            target[name] = copy;
                        }
                    }
                }
            }
        }
        return target;
    };

/* UTILITY FUNCTIONS */
IA.add_event = function(el, event_name, action) {
    el = $(el);
    if (el.addEventListener) {
        el.addEventListener(event_name, action, false);
    } else {
        el.attachEvent('on' + event_name, action);
    }
};

IA.remove_event = function(el, event_name, listener) {
    el = $(el);
    if (el.removeEventListener) {
        el.removeEventListener(event_name, listener, false);
    } else {
        el.detachEvent('on' + event_name, listener);
    }
};

IA.add_script = function(url) {
    var scriptEl = document.createElement('script');
    scriptEl.type = 'text/javascript';
    scriptEl.src = url;
    document.body.appendChild(scriptEl);
};

IA.to_array = function(nodelist) {
    var array = [];
    for ( var i = 0; i < nodelist.length; i++) {
        array[i] = nodelist[i];
    }
    return array;
};

IA._node_matcher = function(tag, number) {
    return function(el) {
        if (el.nodeType === 1 && (!tag || el.nodeName.toLowerCase() === tag)) {
            if (number <= 1) {
                return true;
            }
            number = number - 1;
        }
        return false;
    };
};

IA.get_child = function(parent, tag, number) {
    var matches = IA._node_matcher(tag, number || 1);
    var child = parent.firstChild;
    while (child) {
        if (matches(child)) {
            return child;
        }
        child = child.nextSibling;
    }
    return;
};

IA.get_children = function(parent, tag) {
    var children = [];
    var matches = IA._node_matcher(tag, 0);
    var child = parent.firstChild;
    while (child) {
        if (matches(child)) {
            children.push(child);
        }
        child = child.nextSibling;
    }
    return children;
};

IA.get_parent = function(el, tag, number) {
    var parent = el.parentNode;
    var matches = IA._node_matcher(tag, number || 1);
    while (parent) {
        if (matches(parent)) {
            return parent;
        }
        parent = parent.parentNode;
    }
    return;
};

IA.get_siblings = function(child, tag) {
    var siblings = [];
    var matches = IA._node_matcher(tag, 0);
    var sibling = child.previousSibling;
    while (sibling) {
        if (matches(sibling)) {
            siblings.unshift(sibling);
        }
        sibling = sibling.previousSibling;
    }
    sibling = child.nextSibling;
    while (sibling) {
        if (matches(sibling)) {
            siblings.push(sibling);
        }
        sibling = sibling.nextSibling;
    }
    return siblings;
};

IA.previous_sibling = function(child, tag) {
    var matches = IA._node_matcher(tag, 0);
    var sibling = child.previousSibling;
    while (sibling) {
        if (matches(sibling)) {
            return sibling;
        }
        sibling = sibling.previousSibling;
    }
};

IA.next_sibling = function(child, tag) {
    var matches = IA._node_matcher(tag, 0);
    var sibling = child.nextSibling;
    while (sibling) {
        if (matches(sibling)) {
            return sibling;
        }
        sibling = sibling.nextSibling;
    }
};

IA.parent_offset = function(child, tag) {
    var offset = 0;
    var matches = IA._node_matcher(tag, 0);
    var sibling = child.previousSibling;
    while (sibling) {
        if (matches(sibling)) {
            offset++;
        }
        sibling = sibling.previousSibling;
    }
    return offset;
};

IA.add_class = function(el, name) {
    var className = el.className;
    if (className === null) {
        className = '';
    } else {
        var re = new RegExp("\\b" + name + "\\b");
        if (re.test(className)) {
            return;
        }
    }
    el.className = className + ' ' + name;
    return;
};

IA.remove_class = function(el, name) {
    var className = el.className;
    if (className !== null) {
        var re = new RegExp("\\s*\\b" + name + "\\b\\s*");
        el.className = className.replace(re, ' ');
    }
    return;
};

IA.toggle_class = function(el, name) {
    if (el.className && el.className.indexOf(name) !== -1) {
        return IA.remove_class(el, name);
    }
    return IA.add_class(el, name);
};

IA.solo_class = function(el, name) {
    IA.add_class(el, name);
    IA.each(IA.get_siblings(el), function(li) {
        IA.remove_class(li, name);
    });
};

IA.has_class = function(el, name) {
    var className = el.className;
    if (className === null) {
        return false;
    }

    var re = new RegExp("\\s*\\b" + name + "\\b\\s*");
    return re.test(className);
};

IA.set_attrs = function(el, attrs) {
    for ( var key in attrs) {
        if (attrs.hasOwnProperty(key)) {
            el[key] = attrs[key];
        }
    }
};

IA.ease =
    function(spec) {
        var current = spec.current || 0;
        var end = spec.end || 0;
        var rate = spec.rate || 2;
        var min = spec.min || 8;
        var set = spec.set;
        var delay = spec.delay || 50;
        var done = spec.done;

        var _ease =
            function _ease() {
                var change = end - current;
                var inc =
                    end > current ? Math.ceil(change / rate) : Math
                        .floor(change / rate);
                if (Math.abs(inc) < min) {
                    current = end;
                    change = 0;
                } else {
                    current = current + inc;
                }
                set(current);
                if (change === 0) {
                    if (done) {
                        done(end);
                    }
                } else {
                    setTimeout(function() {
                        _ease();
                    }, delay);
                }
            };
        return _ease;
    };

IA.get_css = function(elem, name) {
    /*
     * This function Adapted from jQuery JavaScript Library v1.3.2
     * http://jquery.com/
     *
     * Copyright (c) 2009 John Resig Dual licensed under the MIT and GPL
     * licenses. http://docs.jquery.com/License
     */

    var ret, cs, style = elem.style, defaultView = document.defaultView || {};

    if (defaultView.getComputedStyle) {
        name = name.replace(/([A-Z])/g, "-$1").toLowerCase();
        cs = defaultView.getComputedStyle(elem, null);
        return cs ? cs.getPropertyValue(name) : undefined;
    }

    cs = elem.currentStyle;
    if (!cs) {
        return undefined;
    }

    var camelCase = name.replace(/\-(\w)/g, function(all, letter) {
        return letter.toUpperCase();
    });

    ret = cs[name] || cs[camelCase];

    // From the awesome hack by Dean Edwards
    // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291

    // If we're not dealing with a regular pixel number
    // but a number that has a weird ending, we need to convert it
    // to pixels
    if (!/^\d+(px)?$/i.test(ret) && /^\d/.test(ret)) {
        var rs = elem.runtimeStyle;

        // Remember the original values
        var left = style.left, rsLeft = rs.left;

        // Put in the new values to get a computed value out
        rs.left = cs.left;
        style.left = ret || 0;
        ret = style.pixelLeft + "px";

        // Revert the changed values
        style.left = left;
        rs.left = rsLeft;
    }

    return ret;
};

IA.get_css_int = function(elem, name) {
    var ret = IA.get_css(elem, name);
    return parseInt(ret, 10) || 0;
};

IA.box = function(el, prop, vals) {
    var props = [];
    var i = 0;
    IA.each( [ 'Top', 'Right', 'Bottom', 'Left' ], function(dir) {
        var name = prop === 'border' ? 'border' + dir + 'Width' : prop + dir;
        if (vals) {
            el.style[name] = vals[i];
            i = i + 1;
        }
        props.push(IA.get_css_int(el, name));
    });
    return props;
};

IA.dim =
    function(el, include) {
        include = include || '';
        var props = {
            width : el.offsetWidth,
            height : el.offsetHeight
        };
        if (props.width === 0 && props.height === 0 &&
            IA.get_css(el, 'display') === 'none') {
            return props;
        }
        if (include === 'border') {
            return props;
        }
        function add(prop, pos) {
            var box = IA.box(el, prop);
            props.width = props.width + pos * (box[1] + box[3]);
            props.height = props.height + pos * (box[0] + box[2]);
        }

        if (include === 'margin') {
            add('margin', 1);
            return props;
        }
        add('border', -1);

        if (include !== 'padding') {
            add('padding', -1);
        }
        return props;

    };

/* WINDOW DIMENSION UTILITIES */
IA.window = {};
IA.window.dim = function() {
    if (document.documentElement) {
        return {
            width : document.documentElement.offsetWidth,
            height : document.documentElement.offsetHeight
        };
    }
    return {
        width : window.innerWidth,
        height : window.innerHeight
    };
};

IA.window.scroll_pos =
    function() {
        var X = 0;
        var Y = 0;
        if (typeof (window.pageYOffset) === 'number') {
            X = window.pageXOffset;
            Y = window.pageYOffset;
        } else if (document.body &&
            (document.body.scrollLeft || document.body.scrollTop)) {
            X = document.body.scrollLeft;
            Y = document.body.scrollTop;
        } else if (document.documentElement &&
            (document.documentElement.scrollLeft || document.documentElement.scrollTop)) {
            X = document.documentElement.scrollLeft;
            Y = document.documentElement.scrollTop;
        }
        return {
            top : Y,
            left : X
        };
    };

IA.window.scroll_to = function(el, spec) {
    el = $(el);
    if (!el) {
        return true;
    }
    var el_top = IA.window.offset(el).top;
    var scroll_pos = IA.window.scroll_pos();
    var top = scroll_pos.top;
    if (top === el_top) {
        return false;
    }
    var left = scroll_pos.left;
    spec = spec || {};
    var inc = parseInt((el_top - top) / 50, 10);
    if (inc > -20 && inc < 20) {
        inc = 20 * (el_top > top ? 1 : -1);
    }
    function _scroll() {
        top = top + inc;
        if (inc > 0 && top > el_top || inc < 0 && top < el_top) {
            top = el_top;
        }
        window.scrollTo(left, top);
        if (top === el_top) {
            return;
        }
        setTimeout(_scroll, 50);
    }
    _scroll();
    return false;
};

IA.window.offset = function(el) {
    el = $(el);
    var X = 0;
    var Y = 0;
    var body = document.body;
    while (el && el !== body && !isNaN(el.offsetLeft) && !isNaN(el.offsetTop)) {
        X += el.offsetLeft - el.scrollLeft;
        Y += el.offsetTop - el.scrollTop;
        el = el.offsetParent;
    }
    return {
        top : Y,
        left : X
    };
};

IA.window.center = function(el, el_dim) {
    el = $(el);
    if (!el) {
        return;
    }
    var es = el.style;
    el_dim = el_dim || IA.dim(el);

    es.width = el_dim.width + 'px';
    es.height = el_dim.height + 'px';
    es.top = 0;
    es.left = 0;

    var el_pos = IA.get_css(el, 'position');
    if (el_pos !== 'absolute' && el_pos !== 'relative') {
        es.position = 'relative';
    }

    var window_dim = IA.window.dim();
    var scroll = IA.window.scroll_pos();
    var offset = IA.window.offset(el);

    var centre_y = window_dim.height / 2 - (offset.top - scroll.top);
    var centre_x = window_dim.width / 2 - (offset.left - scroll.left);

    var new_top = parseInt(centre_y - el_dim.height / 2, 10);
    if (new_top < scroll.top) {
        new_top = scroll.top;
    }
    es.top = new_top + 'px';
    es.left = parseInt(centre_x - el_dim.width / 2, 10) + 'px';

};

/* ADD NEW CONTENT TO THE PAGE */
IA.create = function(tag, attrs) {
    var el = document.createElement(tag);
    attrs = attrs || {};
    var style = attrs.style;
    delete attrs.style;
    if (attrs) {
        IA.set_attrs(el, attrs);
    }
    if (style) {
        IA.set_attrs(el.style, style);
    }
    return el;
};

IA.replace = function(dest, source) {
    dest = $(dest);
    source = $(source);
    var parent = dest.parentNode;
    return parent.replaceChild(source, dest);
};

IA.append = function(dest, source, interval) {
    dest = $(dest);
    source = $(source);
    interval = interval || 0;
    (function _append() {
        var child = source.firstChild;
        if (child) {
            dest.appendChild(child);
            setTimeout(function() {
                _append();
            }, interval);
        }
    }());
};

IA.replace_contents = function(dest, source) {
    dest = $(dest);
    var child = dest.firstChild;
    while (child) {
        dest.removeChild(child);
        child = dest.firstChild;
    }
    dest.appendChild(source);
};

IA.replace_contents_with_contents = function(dest, source) {
    dest = $(dest);
    var child = dest.firstChild;
    while (child) {
        dest.removeChild(child);
        child = dest.firstChild;
    }
    child = source.firstChild;
    while (child) {
        dest.appendChild(child);
        child = source.firstChild;
    }
};

IA.replace_with_contents = function(dest, source) {
    dest = $(dest);
    source = $(source);

    var parent = dest.parentNode;

    if (!source.firstChild) {
        parent.removeChild(dest);
        return parent;
    }
    var child = source.firstChild;
    while (child) {
        parent.insertBefore(child, dest);
        child = source.firstChild;
    }
    parent.removeChild(dest);
    return parent;
};

IA.add_waiting = function(tag, spec) {
    spec = spec || {};
    spec.className = 'waiting';
    return IA.create(tag, spec);
};

IA.replace_with_waiting = function(dest, tag, set_dim) {
    dest = $(dest);
    if (!dest) {
        return;
    }
    var el = IA.add_waiting(tag);
    var es = el.style;

    if (set_dim) {
        IA.each( [ 'margin', 'border', 'padding' ], function(prop) {
            IA.box(el, prop, IA.box(dest, 'prop'));
        });
        var dim = IA.dim(dest);
        es.height = dim.height + 'px';
        es.width = dim.width + 'px';
    }

    var id = dest.id;
    IA.replace(dest, el);
    el.id = id;
    return el;
};

IA.add_close_link = function(parent, close) {
    var close_link = IA.create('a', {
        id : 'close_link'
    });
    close_link.innerHTML = '&nbsp;';
    close_link.onclick = close;
    parent.appendChild(close_link);
    return close_link;
};

IA.iframe = {
    vars : {
        width_from : 'inner',
        wrapper_class : 'iframe_wrapper',
        iframe_id : 'iframe_target',
        scroll_width : 18,
        min_height : 500,
        command_url : '/iframe_cmd'
    },
    current : undefined
};

IA.iframe.create = function(spec) {

    var vars = IA.iframe.vars;

    // get dimensions
    var window_dim = IA.window.dim();
    var scroll = IA.window.scroll_pos();
    var factor = spec.height_factor || 3 / 4;

    var width = IA.get_css_int($(vars.width_from), 'width') + vars.scroll_width;
    if (width >= window_dim.width - vars.scroll_width) {
        width = window_dim.width - vars.scroll_width;
    }

    var height = parseInt(window_dim.height * factor, 10);
    if (height < vars.min_height) {
        height = vars.min_height;
    }
    if (height >= window_dim.height) {
        height = window_dim.height - vars.scroll_width;
    }

    var top = scroll.top + parseInt((window_dim.height - height) / 2, 10);
    if (top < scroll.top) {
        top = scroll.top;
    }
    var left = parseInt(vars.scroll_width / 2, 10) * -1;
    if (left < 0) {
        left = 0;
    }

    var scroll_to = function() {
        window.scrollTo(scroll.left, scroll.top);
        return false;
    };

    // create wrapper which will contain the iframe plus the close link
    var wrapper = IA.create('div', {
        className : vars.wrapper_class,
        style : {
            position : 'absolute',
            width : width + 'px',
            height : height + 'px',
            top : top + 'px',
            left : left + 'px',
            overflow : 'hidden',
            visibility : 'hidden'
        }
    });

    IA.add_close_link(wrapper, function() {
        return IA.iframe.current.remove();
    });

    var src = spec.src || '';
    if (src) {
        src = src + (src.indexOf('?') >= 0 ? '&' : '?') + '_iframe=1';

        var protocol = window.location.protocol;
        if (src.indexOf('http:') === 0 && protocol === 'https:') {
            src = 'https:' + src.substr(5);
        }
    }

    // create iframe
    height = height - 26;
    var iframe;
    // IE6 won't set the name of an iframe with JS, so try this first
    try {
        iframe =
            document.createElement('<iframe name="' + vars.iframe_id + '">');
    } catch (e) {
        iframe = IA.create('iframe');
    }

    IA.set_attrs(iframe, {
        src : src,
        height : height,
        width : width,
        name : vars.iframe_id,
        id : vars.iframe_id
    });
    IA.set_attrs(iframe.style, {
        width : width + 'px',
        height : height + 'px',
        overflowX : 'auto',
        overflowY : 'auto'
    });
    wrapper.appendChild(iframe);

    // create lightbox and add wrapper
    var lightbox = IA.lightbox(function() {
        IA.remove_event(window, 'scroll', scroll_to);
        if (spec.close) {
            spec.close();
        }
    });

    lightbox.el.parentNode.appendChild(wrapper);

    IA.iframe.current = {
        iframe : iframe,
        show : function() {
            wrapper.style.visibility = 'visible';
            lightbox.show();
            IA.add_event(window, 'scroll', scroll_to);
            return false;
        },
        remove : function(timeout) {
            timeout = timeout || 25;
            setTimeout(lightbox.remove, timeout);
            delete IA.iframe.current;
            return false;
        }
    };
    if (spec.cmd) {
        for ( var key in spec.cmd) {
            if (spec.cmd.hasOwnProperty(key)) {
                IA.iframe.current[key] = spec.cmd[key];
            }
        }
    }
    return IA.iframe.current;
};

IA.iframe.open_link = function(link_el, spec) {
    spec = spec || {};
    spec.src = link_el.href;
    IA.iframe.create(spec).show();
    return false;
};

IA.iframe.command = function(cmd, args) {
    var current = IA.iframe.current;
    if (cmd === 'close') {
        return current.remove();
    }
    if (cmd === 'delayed_close') {
        return current.remove(2000);
    }
    if (cmd === 'show') {
        return current.show();
    }
    if (cmd === 'reload_list') {
        return IA.contribs.reload(args);
    }
    if (current[cmd]) {
        return current[cmd]();
    }
    return true;
};

IA.iframe.issue_command =
    function(cmd, args) {
        var top = window.top;
        if (top === window.self) {
            return;
        }
        try {
            top.IA.iframe.command(cmd, args);
        } catch (e) {

            /* Resend command to the same domain using iframe_cmd */
            var location = window.location;
            var protocol = location.protocol === 'http:' ? 'https:' : 'http:';
            var host = protocol + '//' + location.host;
            var qs =
                '?cmd=' + encodeURIComponent(cmd) + ';args=' +
                    encodeURIComponent(args);
            var url = host + IA.iframe.vars.command_url + qs;
            var iframe = IA.create('iframe', {
                width : 0,
                height : 0,
                src : url
            });
            document.body.appendChild(iframe);
            return;
        }
    };

IA.remove = function(el) {
    el = $(el);
    if (el) {
        var parent = el.parentNode;
        parent.removeChild(el);
    }
};

IA.toggle_show = function(el, state) {
    el = $(el);
    if (!el) {
        return false;
    }
    var es = el.style;
    el.old_height = el.old_height || IA.dim(el).height;
    if (state) {
        es.display = state === 'show' ? '' : 'none';
    } else {
        es.display = es.display === 'none' ? '' : 'none';
    }
    el.old_height = el.old_height || IA.dim(el).height;
    return false;
};

IA.show = function(el) {
    return IA.toggle_show(el, 'show');
};
IA.hide = function(el) {
    return IA.toggle_show(el, 'hide');
};

IA.roll = function(el, spec) {
    el = $(el);
    spec = spec || {};

    var es = el.style;
    var height = IA.dim(el).height;
    var delay = spec.delay || 0;

    if (el.old_height === undefined) {
        el.old_height = spec.max || height;
        if (spec.init_hide && height !== 0) {
            delay = 0;
        }
    }

    es.overflow = 'hidden';

    var end = height === 0 ? el.old_height : 0;
    if (end === 0 && delay === 0) {
        es.height = 0;
        es.display = 'none';
        return false;
    }

    es.height = height + 'px';
    es.display = 'block';

    (IA.ease( {
        current : height,
        end : end,

        set : function(height) {
            es.height = height + 'px';
        },
        done : function(end) {
            if (end === 0) {
                es.display = 'none';
            } else {
                es.overflow = '';
            }
            if (spec.done) {
                spec.done();
            }
        }
    })());
    return false;
};

IA.lightbox = function(close) {

    var close_func;
    var lightbox;
    var parent_el;
    (function init() {
        var outer = $('outer');
        parent_el = IA.create('div', {
            style : {
                position : 'relative',
                zIndex : 10000
            }
        });
        var lb_height = outer.offsetHeight + outer.offsetTop;
        var window_dim = IA.window.dim();
        if (lb_height < window_dim.height) {
            lb_height = window_dim.height - 15;
        }
        lightbox = IA.create('div', {
            className : 'lightbox',
            style : {
                position : 'absolute',
                height : lb_height + 'px',
                width : document.body.offsetWidth + 'px',
                left : '-' + outer.offsetLeft + 'px',
                top : '-' + outer.offsetTop + 'px',
                display : 'block',
                visibility : 'hidden'
            }
        });

        parent_el.appendChild(lightbox);
        var outer_child;
        var outer_children = IA.to_array(outer.childNodes);
        while (outer_children.length) {
            outer_child = outer_children.shift();
            if (outer_child.firstChild && IA.has_class(outer_child.firstChild,'lightbox')) {
                continue;
            }
            break;
        }
        outer.insertBefore(parent_el, outer_child);

        close_func = function() {
            if (close) {
                close();
            }
            IA.remove(parent_el);
            return false;
        };
        IA.add_event(lightbox, 'click', close_func);
    }());

    return {
        el : lightbox,
        parent : parent_el,
        show : function() {
            lightbox.style.visibility = 'visible';
            parent_el.style.display = '';
        },
        hide : function() {
            parent_el.style.display = 'none';
        },

        remove : close_func
    };

};

IA.thumbnails = {};
IA.thumbnails.init =
    function(spec) {
        var ul = $(spec.list);
        if (!ul) {
            return;
        }

        var items = IA.get_children(ul, 'li');
        var total = items.length;
        if (total === 0) {
            return;
        }

        var show_images = spec.show_images || 4;

        var dim = IA.dim(items[0], 'margin');
        var inner_dim = IA.dim(items[0]);

        /* Setup the wrapper, the prev, next links, */
        /* the viewport and the ul tag */
        var wrapper_s = {
            position : 'relative'
        }, viewport_s = {
            overflow : 'hidden'
        }, ul_s = {
            width : dim.width + 'px',
            height : dim.height + 'px',
            position : 'relative',
            top : 0,
            left : 0
        };

        IA.each( [ wrapper_s, viewport_s ],
            function(s /* horizontal vs vertical layout */) {
                IA.set_attrs(s, {
                    width : dim.width + 'px',
                    height : dim.height + 'px',
                    position : 'relative'
                });
            });

        /* horizontal vs vertical layout */
        var wh, prop;
        if (spec.aspect !== 'vertical') {
            wh = 'width';
            prop = 'left';
            viewport_s.margin = '0 ' + spec.pager_dim + 'px';
        } else {
            wh = 'height';
            prop = 'top';
            viewport_s.margin = spec.pager_dim + 'px 0';
        }

        var item_wh = dim[wh];
        var offset = show_images * item_wh - (item_wh - inner_dim[wh]);
        viewport_s[wh] = offset + 'px';
        wrapper_s[wh] = 2 * spec.pager_dim + offset + 'px';
        ul_s[wh] = total * item_wh + 'px';

        var wrapper = IA.create('div', {
            className : 'thumbnails',
            style : wrapper_s
        });

        var viewport = IA.create('div', {
            className : 'viewport',
            style : viewport_s
        });
        IA.set_attrs(ul.style, ul_s);

        var state = {
            wrapper : wrapper,
            ul : ul,
            i : 0,
            offset : 0,
            sliding : false,
            show_images : show_images,
            total : total,
            delta : item_wh,
            prop : prop
        };

        var a_prev = IA.create('a', {
            className : 'pager prev',
            href : '#',
            onclick : function(e) {
                return IA.thumbnails.move(e, state, -show_images);
            }
        });
        var a_next = IA.create('a', {
            className : 'pager next',
            href : '#',
            onclick : function(e) {
                return IA.thumbnails.move(e, state, show_images);
            }
        });

        IA.replace(ul, wrapper);
        wrapper.appendChild(a_prev);
        wrapper.appendChild(viewport);
        wrapper.appendChild(a_next);
        viewport.appendChild(ul);

        IA.thumbnails.set_pagers(state);
    };

IA.thumbnails.move =
    function(e, state, change) {
        if (state.sliding || state.i + change < 0 ||
            state.i + change >= state.total) {
            return false;
        }
        state.i = state.i + change;
        IA.thumbnails.set_pagers(state);

        state.sliding = true;
        (IA.ease( {
            current : state.offset,
            end : state.i * state.delta,
            rate : 4,
            min : 6,
            done : function() {
                state.sliding = false;
            },
            set : function(offset) {
                state.offset = offset;
                state.ul.style[state.prop] = -offset + 'px';
            }
        })());
        return false;
    };

IA.thumbnails.set_pagers = function set_pagers(state) {
    var wrapper = state.wrapper;
    if (state.i === 0) {
        IA.remove_class(wrapper, 'prev');
    } else {
        IA.add_class(wrapper, 'prev');
    }

    if (state.i >= state.total - state.show_images) {
        IA.remove_class(wrapper, 'next');
    } else {
        IA.add_class(wrapper, 'next');
    }

};

IA.gallery = function(spec) {
    var this_page = spec.this_page || 0;
    var last_page = spec.last_page || 0;
    var page_height = $(spec.page_height);
    var pager = $(spec.pager_id);
    var pages = $(spec.pages_id);

    /*
     * move the thumbnail list up or down to the correct position to display the
     * specified row in the viewport. Add/remove first and last classes to pager
     * container so we can switch on/off the previous/next buttons
     */

    function show_page(page) {

        pages.style.marginTop = '-' + page * page_height + 'px';

        if (page === 0) {
            IA.add_class(pager, 'first');
        } else {
            IA.remove_class(pager, 'first');
        }
        if (page === last_page) {
            IA.add_class(pager, 'last');
        } else {
            IA.remove_class(pager, 'last');
        }

    }

    // expose a globally accessible control to rewind gallery back to the
    // first page (used by slideshow picture selector)
    IA.gallery_rewind = function() {
        this_page = 0;
        show_page(this_page);
    };

    // bind handlers to prev/next page buttons that dec/inc the page
    IA.add_event($(spec.prev_page_id), 'click', function(e) {
        e = e || window.event;
        if (e.preventDefault) {
            e.preventDefault();
        }
        if (this_page > 0) {
            show_page(--this_page);
        }
        return false;
    });

    IA.add_event($(spec.next_page_id), 'click', function(e) {
        e = e || window.event;
        if (e.preventDefault) {
            e.preventDefault();
        }
        if (this_page < last_page) {
            show_page(++this_page);
        }
        return false;
    });

    // prime the current page and bind onclick function to prev/next page
    show_page(this_page);
};

IA.can_eval = function() {
    /* This function Adapted from jQuery JavaScript Library v1.3.2 */
    var root = document.documentElement;
    var id = "script" + (new Date()).getTime();
    var script = IA.create('script', {
        type : 'text/javascript'
    });

    try {
        script.appendChild(document.createTextNode("window." + id + "=1;"));
    } catch (e) {
    }

    root.insertBefore(script, root.firstChild);

    var supported = false;
    if (window[id]) {
        supported = true;
        delete window[id];
    }

    root.removeChild(script);
    IA.can_eval = function() {
        return supported;
    };
    return supported;
};

IA.can_exec_ajax =
    (function() {
        IA.can_exec_ajax = function() {
            return false;
        };
        var head =
            document.getElementsByTagName("head")[0] ||
                document.documentElement;
        var div = IA.create('div');
        div.innerHTML =
            '<script type="text/javascript">' + "\n" +
                "IA.can_exec_ajax = function() { return true; };" +
                "\n</script>";
        head.appendChild(div);
        head.removeChild(div);
        return IA.can_exec_ajax();
    }());

IA.exec_scripts =
    function(el) {
        if (IA.can_exec_ajax) {
            return;
        }
        el = $(el);
        if (!el) {
            return;
        }
        var scripts =
            el.nodeName.toLowerCase() === 'script' ? [ el ] : IA.to_array(el
                .getElementsByTagName('script'));
        var head =
            document.getElementsByTagName("head")[0] ||
                document.documentElement;
        var can_eval = IA.can_eval();
        while (scripts.length) {
            var sc = scripts.shift();
            var text = sc.text || sc.textContent || sc.innerHTML || '';
            text = text.replace('<!--', '').replace('-->', '');
            var script = document.createElement("script");
            script.type = "text/javascript";
            if (can_eval) {
                script.appendChild(document.createTextNode(text));
            } else {
                script.text = text;
            }
            head.insertBefore(script, head.firstChild);
            head.removeChild(script);
        }
    };

IA.escaped_params = function(args) {
    var values = [];
    function encode_pair(key, val) {
        return encodeURIComponent(key) + '=' + encodeURIComponent(val);
    }
    function _add_multi(key) {
        return function(val) {
            values.push(encode_pair(key, val));
        };
    }
    for ( var key in args) {
        if (args.hasOwnProperty(key)) {
            var value = args[key];

            if (typeof value === 'object') {
                IA.each(value, _add_multi(key));
            } else {
                values.push(encode_pair(key, value));
            }
        }
    }

    return values.join('&');
};

/* **************** AJAX *************************** */
/*
 * var ajax = IA.AJAX({ url: '/', form: 'form_id', args: {key: value}, block:
 * true/false, # sync / async success: callback, replace: 'node_to_replace',
 * replace_contents: 'node_whose_contents_to_replace', append:
 * 'node_to_append_to', fail: callback, fail_url: 'url_to_redirect_to_if_fail' })
 * ajax.get(); or ajax.post();
 *
 * In case of success, it checks for: - success callback (passes a created <div>
 * element containing the result) - replace (replaces the node with all of
 * node(s) in the result) - replace_contents (replaces the content of the node
 * with all the result) - append (appends the contents of the result to the
 * node)
 *
 * In case of failure, it checks for: - fail callback - fail URL - otherwise it
 * returns silently
 *
 * If 'url' is undefined, but 'form' is then it uses the form action
 */

IA.AJAX =
    function(spec) {

        var request;

        function success() {

            var temp_el = document.createElement('div');
            temp_el.innerHTML = request.responseText;
            if (spec.success) {
                spec.success(temp_el);
                return;
            }

            if (spec.replace) {
                IA.replace_with_contents(spec.replace, temp_el);
            } else if (spec.replace_contents) {
                IA.replace_contents(spec.replace_contents, temp_el);
            } else if (spec.append) {
                IA.append(spec.append, temp_el);
            }

            return;
        }

        function fail() {
            if (spec.fail) {
                spec.fail();
            } else if (spec.fail_url) {
                document.location = spec.fail_url;
            }
            return;
        }

        function stateChange() {
            if (request.readyState === 4) {
                if (request.status === 200) {
                    success.apply(this);
                } else {
                    fail.apply(this);
                }
            }
        }

        function send_request(method, url, body) {
            request.open(method, url, spec.block ? false : true);

            method = method || 'GET';
            url = url || '';

            if (method === 'POST') {
                request.setRequestHeader("Content-Type",
                    "application/x-www-form-urlencoded; charset=UTF-8");
            } else {
                body = null;
            }
            request.setRequestHeader("X-iAnnounce-AJAX", "1");

            if (!spec.block) {
                var that = this;
                request.onreadystatechange = function() {
                    stateChange.apply(that);
                };
                request.send(body);
                return false;
            }

            request.send(body);
            if (request.status !== 200) {
                return fail.apply(this);
            }
            return success.apply(this);
        }

        function get_url() {
            var url = spec.url;
            if (url === undefined) {
                if (spec.form) {
                    url = $(spec.form).action;
                } else {
                    url = '';
                }
            }
            var protocol = window.location.protocol;
            if (url.indexOf('http:') === 0 && protocol === 'https:') {
                return 'https:' + url.substr(5);
            } else if (url.indexOf('https:') === 0 && protocol === 'http:') {
                return 'http:' + url.substr(6);
            }
            return url;
        }

        // PUBLIC
        function get() {
            var url = get_url();
            var args = spec.args || {};
            if (spec.form) {
                args = IA.form.get_values(spec.form, args);
            }
            var qs = IA.escaped_params(args);

            if (qs.length) {
                url = url + (url.indexOf('?') >= 0 ? '&' : '?') + qs;
            }
            return send_request.apply(this, [ 'GET', url ]);
        }

        // PUBLIC
        function post() {
            var url = get_url();
            var args = spec.args || {};
            if (spec.form) {
                args = IA.form.get_values(spec.form, args);
            }
            var body = IA.escaped_params(args);
            return send_request.apply(this, [ 'POST', url, body ]);
        }

        try {
            request = new XMLHttpRequest();
        } catch (trymicrosoft) {
            try {
                request = new ActiveXObject("Msxml2.XMLHTTP");
            } catch (othermicrosoft) {
                try {
                    request = new ActiveXObject("Microsoft.XMLHTTP");
                } catch (failed) {
                    request = false;
                }
            }
        }

        if (!request) {
            fail.apply(this);
        }

        return {
            request : function() {
                return request;
            },
            get : get,
            post : post
        };

    };

/** * FORM UTILITIES** */
IA.form = {};
IA.form.init =
    function(form) {
        function _init_field(field) {
            if (!(field.nodeName.toLowerCase() === 'textarea' || field.nodeName
                .toLowerCase() === 'input' &&
                field.type !== 'hidden')) {
                return;
            }

            var parent = field.parentNode;
            IA.add_event(field, 'focus', function() {
                IA.add_class(parent, 'focussed');
            });
            IA.add_event(field, 'blur', function() {
                IA.remove_class(parent, 'focussed');
            });

        }

        form = $(form);
        if (!form || form.nodeName.toLowerCase() !== 'form') {
            return false;
        }
        IA.each(form.elements, _init_field);
        return true;
    };

IA.form.set_hint = function(field) {
    if (field.value === '' || field.value === field.alt) {
        field.value = field.alt;
        IA.add_class(field, 'hint');
    }
};

IA.form.clear_hint = function(field) {
    if (field && field.value === field.alt) {
        field.value = '';
        IA.remove_class(field, 'hint');
    }
};

IA.form.setup_hints = function(form, field_ids) {
    form = $(form);
    if (!form) {
        return;
    }

    // stash the list of hint fields within the form so that we can manually
    // clear them when submitting a form via form.submit() (e.g. when the
    // slideshow 'preview' tab is clicked).
    var fields = form.hint_fields = form.hint_fields || [];

    function _init_field(field) {
        field = $(field);
        if (!field) {
            return;
        }
        fields.push(field);
        IA.add_event(field, 'focus', function() {
            IA.form.clear_hint(field);
        });
        IA.add_event(field, 'blur', function() {
            IA.form.set_hint(field);
        });
        IA.form.set_hint(field);
    }
    IA.each(field_ids, _init_field);
    IA.add_event(form, 'submit', function() {
        IA.each(fields, function(field) {
            IA.form.clear_hint(field);
        });
    });
};

IA.form.get_values =
    function(form, extra) {
        var values = {};
        form = $(form);

        function _get_value(field) {
            var option;
            if (!field.name) {
                return;
            }
            if (field.tagName === 'INPUT') {
                if ((field.type === 'radio' || field.type === 'checkbox') &&
                    !field.checked) {
                    return;
                }
                if (field.type === 'file') {
                    return;
                }
                values[field.name] = field.value;
            } else if (field.tagName === 'SELECT') {
                if (field.multiple) {
                    values[field.name] = [];
                    var options = field.options;
                    IA.each(options, function(option) {
                        if (option.selected) {
                            values[field.name].push(field.value);
                        }
                    });
                } else if (field.selectedIndex >= 0) {
                    option = field.options[field.selectedIndex];
                    values[field.name] = option.value;
                }
            } else if (field.tagName === 'TEXTAREA') {
                if (tinyMCE) {
                    var editor = tinyMCE.get(field.id);
                    if (editor) {
                        editor.save();
                    }
                }
                values[field.name] = field.value;
            }

        }
        if (form) {
            IA.each(form.elements, _get_value);
        }

        if (extra) {
            for ( var key in extra) {
                if (extra.hasOwnProperty(key)) {
                    values[key] = extra[key];
                }
            }

        }
        return values;
    };

IA.form.file = {
    vars : {
        uploader_url : '/uploader',
        max_size : '5MB',
        callbacks : {}
    },
    fields : {}
};

IA.form.file.init = function(args) {
    var id = args.field_id;
    var fields = IA.form.file.fields;
    fields[id] = args;
    var field = $(id);
    if (field && field.type === 'file') {
        IA.add_event(id, 'change', function() {
            IA.form.file.upload(id, args);
        });
    }
};

IA.form.file.remove = function(button, field_id) {
    var args = IA.form.file.fields[field_id];
    var new_input = IA.create('input', {
        type : 'file',
        size : '28',
        className : 'file',
        name : args.fieldname
    });
    var field = $(field_id);
    if (field && field.value) {
        IA.AJAX( {
            url : IA.form.file.vars.uploader_url,
            args : {
                prev_id : field.value
            },
            success : function() {
            },
            fail : function() {
            }
        }).post();
    }
    IA.remove(button.parentNode);
    IA.replace(field_id, new_input);
    new_input.id = field_id;
    IA.form.file.init(args);
    return false;
};

IA.form.file.update = function(field_id) {
    var field = $(field_id);
    var args  = IA.form.file.fields[field_id];
    if (field && field.value) {
        args[args.fieldname] = field.value;
        args._fstatus = 'uploader';
        IA.AJAX({
            url:     IA.form.file.vars.uploader_url,
            args:    args,
            replace: field.parentNode
        }).post();
        delete args[args.fieldname];
    }
    return false;
};

IA.form.file.add_callback = function(field, callback) {
    field = $(field);
    if (!field) {
        return;
    }
    IA.form.file.vars.callbacks[field.id] = callback;
};

/* FILE UPLOADS */
IA.form.file.upload =
    function(field, args) {
        var id = new Date().getTime();
        var vars = IA.form.file.vars;
        var wrapper, original, waiting, iframe, form, original_form;

        function _create_iframe() {
            try {
                iframe = document.createElement('<iframe name="' + id + '">');
            } catch (e) {
                iframe = IA.create('iframe');
            }
            var dummy = ':false';
            IA.set_attrs(iframe, {
                src : 'javascript' + dummy,
                className : 'uploader',
                name : id,
                id : id
            });
            document.body.appendChild(iframe);
        }

        function _create_form() {
            form = IA.create('form', {
                action : vars.uploader_url,
                method : 'post',
                enctype : 'multipart/form-data',
                encoding : 'multipart/form-data',
                target : id,
                className : 'uploader'
            });

            args._fstatus = 'uploader';

            for ( var key in args) {
                if (args.hasOwnProperty(key)) {
                    var el = IA.create('input', {
                        type : 'hidden',
                        name : key,
                        value : args[key]
                    });
                    form.appendChild(el);
                }
            }
            form.appendChild(field);
            document.body.appendChild(form);
        }

        function _postpone_submit(e) {
            if (e.preventDefault) {
                e.preventDefault();
            }
            alert(vars.label.please_wait);
            return false;
        }

        function _do_callback() {
            var callback = vars.callbacks[field.id];
            if (callback) {
                callback(field, wrapper, original);
            }
        }

        function _cancel_upload() {
            wrapper.innerHTML = original;
            try {
                IA.remove(iframe);
                IA.replace(waiting, wrapper);
            } catch (e) {
            }
            IA.remove_event(original_form, 'submit', _postpone_submit);
            IA.form.file.init(args);
            _do_callback();
        }

        function _upload_callback() {
            var iframe_window = iframe.contentWindow || iframe.contentDocument;
            var div = iframe_window.document.getElementById(waiting.id);
            if (div) {
                if (IA.form.file.upload_success) {
                    /*
                     * temporary hack for slideshow - restore the upload field
                     * and call the callback, passing the content div
                     */
                    wrapper.innerHTML = original;
                    IA.replace(waiting, wrapper);
                    IA.form.file.upload_success(div);
                } else {
                    try {
                        IA.replace(waiting, div);
                    } catch (e) {
                        var new_div = IA.create('div', {
                            innerHTML : div.innerHTML
                        });
                        IA.replace(waiting, new_div);
                        new_div.id = waiting.id;
                        new_div.className = waiting.className;
                    }
                }
                IA.form.file.init(args);
                IA.remove(iframe);
                _do_callback();
                IA.remove_event(original_form, 'submit', _postpone_submit);
            } else {
                var msg;
                if (iframe_window.document.getElementById('msg_upload')) {
                    msg =
                        vars.label.upload_max +
                            (args.max_size || vars.upload_max);
                } else {
                    msg = vars.label.unknown_error;
                }
                _cancel_upload();

                IA.each(IA.get_children(wrapper, 'p'), function(p) {
                    if (p.className === 'error') {
                        IA.remove(p);
                    }
                });
                wrapper.appendChild(IA.create('p', {
                    className : 'error',
                    innerHTML : msg
                }));
            }
        }

        function _create_waiting() {
            waiting = IA.replace_with_waiting(wrapper, 'div');
            waiting.id = wrapper.id;
            IA.add_class(waiting, 'uploading');

            var cancel;
            try {
                cancel = IA.create('button', {
                    type : 'button',
                    title : vars.label.cancel,
                    className : 'cancel_upload'
                });
            } catch (e) {
                cancel =
                    document
                        .createElement('<button type="button" class="cancel_upload" title="' + vars.label.cancel + '"></button>');
            }
            IA.add_event(cancel, 'click', function() {
                _cancel_upload();
            });
            var msg = IA.create('div', {
                innerHTML : vars.label.uploading + ' '
            });
            msg.appendChild(cancel);
            waiting.appendChild(msg);
        }

        function _form_submit() {
            _create_form();
            _create_waiting();

            form.submit();
            IA.add_event(iframe, 'load', _upload_callback);
            IA.add_event(original_form, 'submit', _postpone_submit);
        }

        field = $(field);
        if (!field.value) {
            return;
        }

        original_form = field.form;

        wrapper = field.parentNode;
        original = wrapper.innerHTML;
        _create_iframe();
        setTimeout(_form_submit, 500);
        return false;

    };

/** DATE PICKER **/
IA.form.date_vars = {
    lang_url: '/scripts/jquery/i18n/jquery.ui.datepicker-',
    loaded: {}
};

IA.form.date_picker = function(args) {
    var lang = args.lang;
    var vars = IA.form.date_vars;

    if (! vars.loaded[lang]++) {
        IA.add_script(vars.lang_url + lang + '.js');
    }

    function _to_date(val) {
        return new Date(val[0],val[1]-1,val[2]);
    }

    var excluded = args.excluded;
    var weekdays = args.weekdays;

    var date_checker = function(date) {
        if (weekdays) {
            var day = date.getDay() || 7;
            if (! weekdays[day]) {
                return [false];
            }
        }
        var y = date.getFullYear();
        var m = date.getMonth() + 1;
        var d = date.getDate();

        for (var i= excluded.length ; i > 0; i--) {
            var check = excluded[i - 1];
            if (check[0] && check[0] !== y) { continue; }
            if (check[1] && check[1] !== m) { continue; }
            if (check[2] && check[2] !== d) { continue; }
            return [false];
        }

        return [true];
    };

    var opts = {
        dateFormat:         'd MM yy',
        defaultDate:        _to_date(args['default']),
        beforeShowDay:      date_checker,
        firstDay:           1,
        duration:           'fast'
    };
    if (args.min) {opts.minDate = _to_date(args.min);}
    if (args.max) {opts.maxDate = _to_date(args.max);}
    jQ('#'+args.id).datepicker(opts);
    return false;
};

/** FLASH * */
var swfobject;

IA.flash = {
    vars : {
        swf_express : '/scripts/swfobject/expressInstall.swf',
        min_version : '9.0.0'
    }
};

IA.flash.enabled = function() {
    var enabled = swfobject.hasFlashPlayerVersion(IA.flash.vars.min_version);
    if (enabled) {
        IA.flash.enabled = function() {
            return true;
        };
    }
    return enabled;
};

IA.flash.get_movie = function(name) {
    if (window.document[name]) {
        return window.document[name];
    }
    if (navigator.appName.indexOf("Microsoft Internet") === -1) {
        if (document.embeds && document.embeds[name]) {
            return document.embeds[name];
        }
    }
    return $(name);
};

IA.flash.add_movie =
    function(spec) {
        var attr = spec.attr || {};
        attr.id = spec.id;
        attr.name = spec.id;

        var flash_vars = spec.flash_vars || {};
        var params = spec.params || {};
        params.allowscriptaccess = params.allowscriptaccess || 'sameDomain';

        swfobject.embedSWF(spec.url, spec.id, spec.width, spec.height,
            IA.flash.vars.min_version, IA.flash.vars.swf_express, flash_vars,
            params, attr);
    };

IA.flash.hide_required = function(el_id) {
    if (IA.flash.enabled()) {
        var required_el = $(el_id + '_required');
        if (required_el && required_el.tagName.toLowerCase() === 'div') {
            required_el.style.display = 'none';
        }
        var content_el = $(el_id + '_content');
        if (content_el && content_el.tagName.toLowerCase() === 'div') {
            content_el.style.display = '';
        }
    }
};

/** * HOME PAGE ** */
/* Search form */
IA.search = {};
IA.search.init_form = function(spec) {
    var date_limit = $(spec.date_limit);
    var date = $(spec.date);

    var _update_display = function() {
        if (date_limit.value === 'custom') {
            IA.add_class(date_limit, 'custom');
            IA.show(date);
            IA.form.set_hint(date);
        } else {
            IA.hide(date);
            IA.remove_class(date_limit, 'custom');
            date.value = '';
        }
    };
    IA.add_event(date_limit, 'change', _update_display);
    IA.add_event(date_limit, 'keypress', _update_display);
    _update_display();
};

/* Browse tabs */
IA.browse = {};

IA.browse.init_tabs = function(container) {
    container = $(container);
    if (!container) {
        return;
    }

    var state = {
        current : ''
    };

    IA.each_list_item(container, function(li) {
        var a = IA.get_child(li, 'a');
        var type = a.id.replace('tab_', '');
        var href = a.href;
        if (IA.has_class(li, 'selected')) {
            state.current = type;
        }
        IA.add_event(a, 'click', function(e) {
            if (e.preventDefault) {
                e.preventDefault();
            }
            return IA.browse.load_tab(type, href, state);
        });
    });
};

IA.browse.load_tab = function(type, url, state) {
    var current = state.current;
    if (current === type) {
        return false;
    }
    IA.remove_class($('tab_' + current).parentNode, 'selected');
    IA.add_class($('tab_' + type).parentNode, 'selected');

    var current_browse = $('browse_' + current);
    IA.hide(current_browse);
    var new_browse = $('browse_' + type);
    if (new_browse) {
        IA.show(new_browse);
    } else {
        var waiting = IA.add_waiting('div');
        IA.add_class(waiting, current_browse.className);
        waiting.style.height = current_browse.old_height + 'px';
        current_browse.parentNode.appendChild(waiting);
        IA.AJAX( {
            url : url,
            success : function(source) {
                var div = IA.get_child(source, 'div');
                IA.replace_with_contents(waiting, source);
                IA.exec_scripts(div);
            }
        }).get();
    }
    state.current = type;
    return false;
};

/* Latest activity */
IA.activity_carousel = function(spec) {
    var list = $(spec.container).getElementsByTagName('ul')[0];
    if (!list) {
        return;
    }

    var mouse_over = false;
    IA.add_event(list, 'mouseover', function() {
        mouse_over = true;
    });
    IA.add_event(list, 'mouseout', function() {
        mouse_over = false;
    });
    function _scroll() {
        var first = IA.get_child(list, 'li');
        if (first && !mouse_over) {
            IA.roll(first, {
                delay : spec.hide_delay,
                max : 0,
                done : function() {
                    list.appendChild(first);
                    IA.show(first);
                    IA.roll(first, {
                        delay : 0
                    });
                }
            });
        }
        setTimeout(_scroll, spec.scroll_delay);
    }
    setTimeout(_scroll, spec.scroll_delay);
};

/** * CONTRIBUTIONS ** */

IA.contribs = {
    vars : {},
    form_types : {},
    form_vars : {}
};

IA.contribs.admin_hover = function() {
    if (!IA.is_ie6()) { return };

    var ul = $('contribs_list');
    if (! ul || ! IA.has_class(ul,'moderate')) { return; }

    function _callback(li) {
        var lis = IA.to_array(li.getElementsByTagName('li'));
        if (lis.length) {
            IA.each(lis, _callback);
        }
        else {
            li.onmouseover = function() { IA.add_class(li,'hover') };
            li.onmouseout = function() { IA.remove_class(li,'hover') };
        }
    };

    IA.each(IA.get_children(ul,'li'),_callback);
};

IA.contribs.more = function(args) {
    var vars = IA.contribs.vars;
    var waiting = IA.add_waiting('li');

    args.success = function(source) {
        var list, pager;
        try {
            list = source.getElementsByTagName('ul')[0];
            IA.replace_with_contents(waiting, list);
            var divs = source.getElementsByTagName('div');
            pager = divs[divs.length - 1];
            IA.replace_contents(vars.pager, pager);
            IA.contribs.admin_hover();
        } catch (e) {
        }
    };
    args.url = vars.reload_url;
    args.form = vars.filter;
    args.args.append = 1;

    $(vars.contribs_list).appendChild(waiting);
    $(vars.pager).innerHTML = '';
    return IA.AJAX(args).post();
};

IA.contribs.reload = function(list_name) {
    var vars = IA.contribs.vars;
    list_name = list_name || 'contribs';

    var container = $(list_name);
    if (!container) {
        return false;
    }
    var reload_args;
    if (list_name === 'contribs') {
        reload_args = IA.form.get_values(vars.filter);
    } else {
        reload_args = {
            show_list : list_name
        };
    }
    var waiting = IA.replace_with_waiting(container, 'div', 'set-height');
    var args = {
        success : function(source) {
            IA.replace_with_contents(waiting, source);
            IA.exec_scripts(list_name);
            IA.contribs.admin_hover();
        },
        url : vars.reload_url,
        args : reload_args
    };

    return IA.AJAX(args).post();
};

IA.contribs.filter = function(type) {
    var vars = IA.contribs.vars;
    var filter = $(vars.filter);
    if (!filter) {
        return true;
    }
    var field = filter.getElementsByTagName('select')[0];
    field.value = type;
    IA.contribs.reload('contribs');
    window.location.hash = '#' + vars.contribs_header;
    $(vars.contribs_header).scrollIntoView(true);
    return false;
};

IA.contribs.reload_single = function(li, url) {
    var list = IA.get_parent(li, 'ul');
    var waiting = IA.replace_with_waiting(li, 'li', 'set_dim');
    var args = {
        url : url,
        success : function(source) {
            var children = IA.to_array(IA.get_children(source));
            IA.replace_with_contents(waiting, source);
            IA.each(children, function(child) {
                IA.exec_scripts(child);
            });
            IA.contribs.check_empty(list);
            IA.contribs.admin_hover();
        }
    };
    IA.AJAX(args).post();
};

IA.contribs.check_empty = function(list) {
    var curr = list;
    var rows = [];
    var exclude_link_rows = function(row) {
        if (!IA.has_class(row, 'links_row')) {
            rows.push(row);
        }
    };

    IA.each(curr.getElementsByTagName('li'), exclude_link_rows);

    if (rows.length > 0) {
        return;
    }
    if (IA.has_class(curr, 'contribs')) {
        while (curr) {
            curr = IA.get_parent(curr, 'div');
            if (curr.id && IA.has_class(curr, 'contribs')) {
                IA.contribs.reload(curr.id);
                return;
            }
            return;
        }
    } else {
        list = IA.get_parent(list, 'ul');
        if (IA.has_class(list, 'questions')) {
            /* special case for memory box */
            IA.add_class(list, 'empty');
        } else {
            IA.remove(IA.get_parent(curr, 'li'));
            IA.contribs.check_empty(list);
        }
    }
};

IA.contribs.del = function(link_el, list_name, done) {
    var parent = IA.get_parent(link_el, 'li');
    if (!parent) {
        return true;
    }
    var url = link_el.href;
    var list = IA.get_parent(parent, 'ul');
    var waiting = IA.replace_with_waiting(parent, 'li', 'setdims');
    var args = {
        url : url,
        args : {
            confirm : 1
        },
        success : function(source) {
            waiting.className = '';
            IA.roll(waiting, {
                delay : 50,
                done : function() {
                    IA.remove(waiting);
                    IA.contribs.check_empty(list);
                    if (done) {
                        done();
                    }
                    if (list_name === 'memories' && IA.memory_box.lightbox) {
                        IA.contribs.reload(list_name);
                    }
                }
            });
        }
    };
    return IA.AJAX(args).post();
};

IA.contribs.approve = function(link_el, list_name, dest_list) {
    IA.contribs.del(link_el, list_name, function() {
        IA.contribs.reload(dest_list);
    });

    return false;
};

IA.contribs.edit = function(link_el, list_id, reload_url) {
    var lightbox;
    if (list_id === 'memories') {
        lightbox = IA.memory_box.lightbox;
    }
    if (lightbox) {
        lightbox.hide();
    }
    var vars = IA.contribs.vars;
    var li = IA.get_parent(link_el, 'li');
    var close = function() {
        if (lightbox) {
            lightbox.show();
            IA.contribs.reload(list_id);
        }
        IA.contribs.reload_single(li, reload_url);
    };

    IA.iframe.create( {
        src : link_el.href,
        close : close
    }).show();
    return false;
};

IA.contribs.form_vars = {};

IA.contribs.init_name_fields = function(full_name) {
    var short_name = $(IA.contribs.vars.short_name);
    full_name = $(full_name);
    if (short_name && full_name) {
        short_name.maxLength = full_name.maxLength;

        var short_to_full = function() {
            full_name.value = short_name.value;
            if (full_name.value === '') {
                full_name.value = full_name.alt;
            }
            if (full_name.value !== full_name.alt) {
                IA.remove_class(full_name, 'hint');
            } else {
                IA.add_class(full_name, 'hint');
            }
        };
        var full_to_short = function() {
            short_name.value = full_name.value;
            if (short_name.value === '') {
                short_name.value = short_name.alt;
            }
            if (short_name.value !== short_name.alt) {
                IA.remove_class(short_name, 'hint');
            } else {
                IA.add_class(short_name, 'hint');
            }
        };
        full_to_short();
        short_name.onkeyup = short_to_full;
        short_name.onchange = short_to_full;
        full_name.onkeyup = full_to_short;
        full_name.onchange = full_to_short;
    }
};

IA.contribs.init_form_tabs = function(spec) {
    var vars = IA.contribs.vars;
    var container = $(spec.container);
    var form = $(spec.form);
    if (!vars.no_iframe[spec.tab]) {
        IA.add_event(form, 'submit', function() {
            return IA.contribs.add(form, spec.type);
        });
    }

    IA.set_attrs(IA.contribs.form_vars, {
        selected : spec.type,
        container : container,
        loaded : {},
        selected_tab : $(spec.tab)
    });
    IA.contribs.form_vars.loaded[spec.type] = form;
};

IA.contribs.load_form = function(type, reload) {
    var vars = IA.contribs.form_vars;
    var types = IA.contribs.form_types;
    if (vars.selected === type) {
        return false;
    }

    IA.remove_class(vars.selected_tab, 'selected');
    vars.selected_tab = $(types[type].tab);
    IA.add_class(vars.selected_tab, 'selected');

    if (vars.loaded[type]) {
        vars.loaded[type].style.display = '';
    } else {
        var waiting = IA.add_waiting('div');
        IA.set_attrs(waiting.style, {
            height : '250px'
        });
        vars.container.appendChild(waiting);
        IA.AJAX( {
            url : types[type].url,
            fail_url : types[type].url,
            success : function(source) {
                IA.replace(waiting, source);
                vars.loaded[type] = source;
                IA.exec_scripts(source);
                IA.each(source.getElementsByTagName('form'), function(form) {
                    if (form) {
                        if (!IA.contribs.vars.no_iframe[type]) {
                            IA.add_event(form, 'submit', function() {
                                return IA.contribs.add(form, type);
                            });
                        }
                    } else if (reload) {
                        IA.contribs.load_form('comment');
                    }
                });
            }
        }).post();
    }
    /* hide currently selected */
    if (vars.selected) {
        vars.loaded[vars.selected].style.display = 'none';
    }

    vars.selected = type;
    return false;
};

IA.contribs.reload_form = function(type) {
    var vars = IA.contribs.form_vars;
    IA.tinymce.disable(vars.loaded[type]);
    IA.remove(vars.loaded[type]);
    delete vars.loaded[type];
    if (vars.selected === type) {
        vars.selected = '';
    }
    IA.contribs.load_form(type, true);
};

IA.contribs.add = function(form, type) {
    var original = $(IA.contribs.vars.short_name);
    var name_field;

    if (original) {
        var has_name = false;
        IA.each(form.elements, function(input) {
            if (input.name === 'name') {
                has_name = 1;
            }
        });

        if (!has_name) {
            name_field = form.appendChild(IA.create('input', {
                type : 'hidden',
                name : original.name,
                value : original.value
            }));
        }
    }

    // include _iframe target
    var iframe_field = form.appendChild(IA.create('input', {
        type : 'hidden',
        name : '_iframe',
        value : "1"
    }));

    var popup = IA.contribs.form_vars.lightbox;
    if (popup) {
        popup.remove();
        delete IA.contribs.form_vars.lightbox;
    }

    var iframe = IA.iframe.create( {
        src : '',
        close : function() {
            if (name_field) {
                IA.remove(name_field);
            }
            IA.remove(iframe_field);
        },
        cmd : {
            reload_form : function() {
                IA.contribs.reload_form(type);
            }
        }
    }).show();
    form.target = IA.iframe.vars.iframe_id;
    return true;
};

IA.contribs.popup_form = function() {
    var waiting = IA.add_waiting('div');
    var form_container = IA.contribs.form_vars.container;

    var editors = IA.tinymce.disable();

    var close = function() {
        var editors = IA.tinymce.disable();
        IA.replace(waiting, form_container);
        IA.tinymce.enable(editors);
        delete IA.contribs.form_vars.lightbox;
    };

    var lightbox = IA.lightbox(close);
    var form_wrapper = IA.create('div', {
        id : 'contrib_form_wrapper'
    });

    lightbox.parent.appendChild(form_wrapper);
    var dim = IA.dim(form_container);
    form_container.style.width = dim.width + 'px';
    waiting.style.height = dim.height + 'px';

    IA.replace(form_container, waiting);
    IA.add_close_link(form_wrapper, function() {
        lightbox.remove();
    });
    form_wrapper.appendChild(form_container);
    lightbox.show();
    IA.window.center(form_wrapper);
    form_wrapper.style.height = '';
    IA.tinymce.enable(editors);

    IA.contribs.form_vars.lightbox = lightbox;
    return false;
};

/** MEMORY BOX * */

IA.memory_box = {
    vars : {
        question_form_id : 'add_question',
        container_id : 'mb_input',
        question_url : ''
    },
    reloaders : []
};

IA.memory_box.question_selected = function(target) {
    var vars = IA.memory_box.vars;
    var container = $(target || vars.container_id);
    if (!container) {
        return false;
    }

    var form_id = vars.question_form_id;
    var form_args = IA.form.get_values(form_id);
    var waiting = IA.replace_with_waiting(container, 'div');
    var args = {
        url : vars.question_url,
        args : form_args,
        success : function(source) {
            IA.replace_with_contents(waiting, source);
        }
    };

    return IA.AJAX(args).post();
};

IA.memory_box.display = function(target) {
    var url = target ? target.href : IA.memory_box.reload_url;
    var lightbox = IA.memory_box.lightbox;
    var waiting = IA.add_waiting('div');

    var wrapper;
    if (lightbox) {
        IA.replace_contents($('memory_lightbox'), waiting);
    } else {
        lightbox = IA.lightbox(function() {
            delete IA.memory_box.lightbox;
            // IA.contribs.reload('memories');
        });
        wrapper = IA.create('div', {
            id : 'memory_lightbox'
        });
        var height = IA.window.dim().height - 50;
        var scroll = IA.window.scroll_pos().top + 20;
        wrapper.style.height = height + 'px';
        wrapper.style.top = scroll + 'px';
        lightbox.parent.appendChild(wrapper);
        IA.window.center(wrapper);

        wrapper.appendChild(waiting);
        IA.add_close_link(wrapper, function() {
            lightbox.remove();
        });
        IA.memory_box.lightbox = lightbox;
    }
    IA.memory_box.reload_url = url;

    lightbox.show();

    IA.AJAX( {
        url : url,
        replace : waiting
    }).get();

    return false;
};

IA.memory_box.edit = function(target) {
    var lightbox = IA.memory_box.lightbox;
    if (lightbox) {
        lightbox.remove();
    }
    IA.iframe.create( {
        src : target.href,
        close : function() {
            if (lightbox) {
                IA.memory_box.display();
            }
        }
    }).show();

    return false;
};

IA.queue = {};
IA.queue.gift_del = function(link_el) {
    var parent = IA.get_parent(link_el, 'tr');
    if (!parent) {
        return true;
    }
    var url = link_el.href;
    var waiting = IA.replace_with_waiting(parent, 'tr', 'setdims');
    var args = {
        url : url,
        args : {
            confirm : 1
        },
        success : function(source) {
            IA.remove(waiting);
        }
    };
    return IA.AJAX(args).post();
};

/** LOGIN - REGISTER * */
IA.login = {
    vars : {},
    show : function(type) {
        var vars = IA.login.vars;
        for ( var key in vars) {
            if (vars.hasOwnProperty(key)) {
                if (key === type) {
                    IA.show(vars[key]);
                } else {
                    IA.hide(vars[key]);
                }
            }
        }
        return false;
    },
    init : function(type, focus) {
        IA.login.show(type);
        focus = $(focus);
        IA.add_event(window, 'load', function() {
            focus.blur();
            focus.focus();
        });

    }
};

/** * SHARE ** */
IA.share = {
    share_id : ''
};

IA.share.show = function(args) {
    var share, ss, waiting;
    if (IA.share.share_id) {
        ss = $(IA.share.share_id).style;
        ss.display = ss.display !== 'none' ? 'none' : 'block';
        return false;
    }

    IA.share.share_id = args.share_id;
    share = $(args.share_id);
    share.style.display = 'block';

    waiting = IA.replace_with_waiting(share, 'div');
    args.replace = waiting;
    return IA.AJAX(args).post();
};

IA.share.hide = function() {
    return IA.share.show();
};

/** SUGGESTED MESSAGES * */
IA.messages = {
    vars : {
        suggested : '',
        view_link : '',
        field : ''
    }
};

IA.messages.toggle = function(display) {
    var suggested = $(IA.messages.vars.suggested);
    var view_link = $(IA.messages.vars.view_link);
    view_link.style.display = display ? 'none' : '';
    IA.roll(suggested, {
        delay : 50,
        max : 150
    });
    return false;
};

IA.messages.add = function(msg) {
    var text = msg.textContent || msg.innerHTML;
    var editor = tinyMCE.getInstanceById(IA.messages.vars.field);
    editor.contentWindow.focus();
    editor.setContent('<p>' + text + '<\/p>');
    editor.execCommand('selectall', false, null);
    return IA.messages.toggle(false);
};

/* CLIPART */

IA.clipart = {
    vars : {}
};

IA.clipart.init = function(spec) {
    var container = $(spec.container);
    if (!container) {
        return;
    }

    var timeouts = {};
    var selected = 0;

    function resize(el, start, end) {
        if (!spec.hover_zoom) {
            return;
        }
        el = $(el);
        if (timeouts[el.id]) {
            window.clearTimeout(timeouts[el.id]);
        }
        var growing = end > start;
        var inc = growing ? 5 : -5;
        var es = el.style;
        var displace = growing ? 0 : (end - start) / 2;

        es.zIndex = 1000;
        if (el.offsetParent) {
            el.offsetParent.style.zIndex = 1001;
        }
        (function _resize() {
            start = start + (2 * inc);
            displace = displace - inc;
            es.width = start + 'px';
            es.height = start + 'px';
            es.top = displace + 'px';
            es.left = displace + 'px';
            if (start !== end) {
                setTimeout(function() {
                    _resize();
                }, 1);
            } else {
                timeouts[el.id] = '';
                if (!growing) {
                    es.zIndex = '';
                    if (el.offsetParent) {
                        el.offsetParent.style.zIndex = '';
                    }
                }
            }
        }());
    }

    function toggle_select(img_id) {
        var old_id = selected;
        var radio;

        selected = img_id;

        if (old_id && old_id !== selected) {
            IA.remove_class($(old_id), 'selected');
        }

        if (selected) {
            radio = $(selected.substr(4));
            radio.checked = 1;

            IA.add_class($(selected), 'selected');
            if (spec.selected_image) {
                var thumb = $(img_id);
                thumb.style.cursor = 'auto';
                resize(thumb, 100, 60);
                var image = $(spec.selected_image);
                image.src = thumb.src;
                IA.roll(container, {
                    delay : 50,
                    init_hide : true
                });
            }
            if (spec.onselect) {
                spec.onselect(old_id, selected, radio.value);
            }
        }
    }

    function _init_image(image) {
        var is = image.style;
        if (spec.hover_zoom) {
            is.width = '60px';
            is.height = '60px';
            is.position = 'absolute';
            is.top = 0;
            is.left = 0;
            is.zIndex = 100;
            image.parentNode.parentNode.style.width = '60px';
        }
        IA.add_event(image, 'mouseover', function() {
            image.style.cursor = 'pointer';
            resize(image, 60, 100);
        });
        IA.add_event(image, 'mouseout', function() {
            image.style.cursor = 'auto';
            resize(image, 100, 60);
        });
        IA.add_event(image, 'click', function() {
            toggle_select(image.id);
        });
    }

    function _init_radio(radio) {
        radio.style.display = 'none';
        var checked = radio.defaultChecked;
        radio.checked = checked;
        if (checked) {
            selected = 'img_' + radio.id;
        }
    }
    IA.each(container.getElementsByTagName('input'), _init_radio);
    IA.each(container.getElementsByTagName('img'), _init_image);

    IA.add_class($(spec.outer), 'js_enabled');
    if (spec.selected_image) {
        $(spec.selected_image).style.display = '';
        if (spec.show_more) {
            $(spec.show_more).style.display = '';
        }
    }

    toggle_select(selected);
};

/** * GREETINGS ** */
IA.greetings = {
    vars : {}
};

IA.greetings.select = function(old_id, current_id, value) {
    if (!IA.flash.enabled()) {
        return;
    }

    var vars = IA.greetings.vars;
    if (old_id && old_id !== current_id) {
        var parent = swfobject.getObjectById(vars.preview).parentNode;
        swfobject.removeSWF(vars.preview);
        parent.appendChild(IA.create('div', {
            id : vars.preview
        }));
    }

    var url = vars.greeting_url + value + '/flash.swf';

    IA.flash.add_movie( {
        id : vars.preview,
        url : url,
        width : vars.width,
        height : vars.height,
        params : {
            wmode : 'opaque'
        }
    });
};

/* VIDEO */

IA.video = {
    vars : {}
};

IA.video.play = function(url,youtube) {
    var vars = IA.video.vars;

    var loaded_timer;
    function play_when_loaded() {
        var player = $(vars.id);
        if (player && player.loadVideo) {
            player.loadVideo(url, true);
            return;
        }
        loaded_timer = setTimeout(play_when_loaded, 100);
    }

    var unload = function() {
        swfobject.removeSWF(vars.id);
        if (loaded_timer) {
            clearTimeout(loaded_timer);
        }
        IA.video.vars.lightbox = undefined;
    };

    var lightbox = IA.lightbox(unload);
    IA.video.vars.lightbox = lightbox;
    var wrapper = IA.create('div', {
        style : {
            position : 'absolute',
            width : vars.wrapper.width + 'px',
            height : vars.wrapper.height + 'px'
        }
    });
    var waiting = IA.add_waiting('div', {
        style : {
            width : '100%',
            height : '100%'
        }
    });
    wrapper.appendChild(waiting);
    lightbox.parent.appendChild(wrapper);
    lightbox.show();
    IA.window.center(wrapper);

    if (youtube) {
        url = url + '?rel=0;autoplay=1;fs=1';
        IA.AJAX( {
            url : vars.wrapper.url,
            success : function(source) {
                IA.replace_with_contents(waiting, source);
                IA.flash.add_movie( {
                    id : vars.id,
                    url : url,
                    width : 425,
                    height : 344,
                    params: {
                        allowscriptaccess: "always",
                        movie: url,
                        allowfullscreen: "true"
                    }
                });
                play_when_loaded();
            }
        }).get();
    }
    else {
        IA.AJAX( {
            url : vars.wrapper.url,
            success : function(source) {
                IA.replace_with_contents(waiting, source);
                IA.flash.add_movie( {
                    id : vars.id,
                    url : vars.url,
                    width : vars.width,
                    height : vars.height,
                    flash_vars : vars.args
                });
                play_when_loaded();
            }
        }).get();
    }
    return false;

};


IA.video.close = function() {
    if (IA.video.vars.lightbox) {
        IA.video.vars.lightbox.remove();
    }
    return false;
};

/** Book online print preview * */
IA.print_preview = function(spec) {
    var form = $(spec.form);
    var url = spec.url;
    var preview = $(spec.preview);
    var old_qs = '';
    var interval = spec.interval || 5000;

    var updating = false;

    function update_preview() {
        if (updating) {
            return;
        }
        var curr_vals = IA.form.get_values(form, {
            preview : 1
        });
        /*
         * preview_id should not be counted as a changed value because it
         * changes for every new preview
         */
        var preview_id = curr_vals.preview_id;
        delete curr_vals.preview_id;
        if (!curr_vals.image_file) {
            delete curr_vals.image_file;
        }
        var curr_qs = IA.escaped_params(curr_vals);
        if (curr_qs === old_qs) {
            return;
        }

        updating = true;
        curr_vals.preview_id = preview_id;
        /* Show the "waiting" div */
        var divs = IA.get_children(preview, 'div');
        var waiting;
        for ( var i = 0; i < divs.length; i++) {
            if (divs[i].className === 'waiting') {
                waiting = divs[i];
                break;
            }
        }

        if (waiting) {
            waiting.style.display = 'block';
        }
        IA.AJAX( {
            url : url,
            args : curr_vals,
            success : function(source) {
                IA.replace_contents_with_contents(preview, source);
                delete curr_vals.preview_id;
                old_qs = IA.escaped_params(curr_vals);
                updating = false;

            },
            fail : function() {
                updating = false;
            }
        }).post();
    }

    var max_top = IA.window.offset(preview).top;
    IA.set_attrs(preview.style, ( {
        position : 'absolute',
        top : max_top + 'px',
        right : '0px'
    }));

    function slide_preview() {
        var scroll_top = IA.window.scroll_pos().top + 50;
        var top = scroll_top < max_top ? max_top : scroll_top;
        preview.style.top = top + 'px';
        return true;
    }

    update_preview();
    setInterval(update_preview, interval);

    IA.add_event(window, 'scroll', slide_preview);

};

/* TinyMCE loader */
IA.tinymce = {
    host : window.location.protocol + '//' + window.location.host,
    elements : []
};

IA.tinymce.init = function(el_id) {
    var el = $(el_id);
    var es = el.style;
    es.width = IA.get_css(el, 'width');
    es.height = IA.get_css(el, 'height');

    var elements = IA.tinymce.elements;
    function delayed_add() {
        while (elements.length) {
            tinyMCE.execCommand('mceAddControl', false, elements.shift());
        }
        delete IA.tinymce.elements;
    }

    if (!IA.tinymce.loaded) {
        IA.tinymce.loaded = true;
        var config = IA.tinymce.config;
        config.onpageload = function() {
            delayed_add();
        };
        if (tinyMCE) {
            tinyMCE.init(config);
        } else {
            IA.add_event(window, 'load', function() {
                tinyMCE.init(config);
            });
        }
    }

    if (IA.tinymce.elements) {
        elements.push(el_id);
    } else {
        tinyMCE.execCommand('mceAddControl', false, el_id);
    }
};

IA.tinymce.setup_default_content = function(editor_id, body) {
    if (body.innerHTML === '') {
        body.innerHTML = '<p><br /><\/p>';
    }
};

IA.tinymce.cleanup_urls = function(url, node, on_save) {
    var host = IA.tinymce.host;
    var trimmed = 0;
    if (url.substring(0, host.length) === host) {
        url = url.substring(host.length);
    }
    while (url.substring(0, 3) === '../') {
        url = url.substring(3);
        trimmed = 1;
    }
    if (trimmed) {
        url = '/' + url;
    }
    return url;
};

IA.tinymce.disable = function(parent) {
    var editors = {};
    var active = tinymce.EditorManager.editors;
    if (parent) {
        IA.each(parent.getElementsByTagName('textarea'), function(el) {
            if (active[el.id]) {
                editors[el.id] = active[el.id];
            }
        });
    } else {
        editors = active;
    }

    var disabled = [];
    for ( var id in editors) {
        if (editors.hasOwnProperty(id)) {
            tinyMCE.execCommand('mceRemoveControl', false, id);
            disabled.push(id);
        }
    }
    return disabled;
};

IA.tinymce.enable = function(editors) {
    while (editors.length) {
        var id = editors.shift();
        tinyMCE.execCommand('mceAddControl', false, id);
    }
    return;
};

IA.tinymce.config =
    {
        mode : "exact",
        elements : "",
        theme : "advanced",
        plugins : "paste,emotions,inlinepopups",
        doctype : '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" ' + '"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">',
        language : "en",
        auto_focus : 0,
        button_tile_map : true,
        content_css : '/stylesheets/tinymce.css?' + IA.Revision,
        dialog_type : "modal",
        inline_styles : true,
        gecko_spellcheck : true,
        verify_css_classes : true,
        paste_middot_lists : true,
        entity_encoding : 'raw',
        fix_list_elements : true,
        remove_trailing_nbsp : true,
        setupcontent_callback : IA.tinymce.setup_default_content,
        theme_advanced_buttons1 : "bold,italic,separator,indent,outdent,justifyleft,justifycenter,justifyright,justifyfull,removeformat,code",
        theme_advanced_buttons2 : "formatselect,undo,redo,pastetext,pasteword,cut,copy,selectall,emotions",
        theme_advanced_buttons3 : "",
        theme_advanced_toolbar_location : "top",
        theme_advanced_toolbar_align : "left",
        theme_advanced_path_location : "bottom",
        theme_advanced_blockformats : "p,h4,h5,h6",
        relative_urls : false,
        remove_script_host : true,
        strict_loading_mode : true,
        urlconverter_callback : IA.tinymce.cleanup_urls,
        valid_elements : "a[href|style],blockquote[style],br[],p/div[align|style],em/i[style],h1/h4[align|style],h2/h5[align|style],h3/h6[align|style],img[src|alt=],span[align|style],strong/b,u,"
    };

IA.diary = {
    vars : {}
};

IA.diary.show_details = function(details) {
    var vars = IA.diary.vars;
    details = $(details);
    vars.details = details;
    var form = IA.get_parent(details, 'form');
    var fields = IA.get_child(form, 'div');
    vars.fields = fields;
    details.style.display = '';
    fields.style.display = 'none';
};

IA.diary.show_fields = function() {
    var vars = IA.diary.vars;
    vars.fields.style.display = '';
    vars.details.style.display = 'none';
};

IA.tabset = function(container) {
    IA.each_list_item(container, function(li) {
        var a = IA.get_child(li, 'a');
        var href = a.href.replace(/^.*?#/, '');
        var panel = $(href);
        IA.add_event(a, 'click', function(e) {
            if (e.preventDefault) {
                e.preventDefault();
            }
            IA.solo_class(li, 'selected');
            IA.solo_class(panel, 'selected');
            return false;
        });
    });
};
/* IMAGE EDITOR */
IA.image_editor = {
    script: {
        jcrop: '/scripts/jquery/jquery.Jcrop.ia.js?'+IA.Revision,
        iedit: '/scripts/image_editor.js?'+IA.Revision
    },
    vars : {}
};

IA.image_editor.edit_upload = function(field_id) {
    IA.image_editor.bootstrap({
        field_id: field_id,
        on_save: function(editor) {
            IA.form.file.update(field_id);
        }
    });
};

IA.image_editor.bootstrap = function(args) {
    var self  = IA.image_editor;

    if (self.loaded) {
        self.init(args);
    }
    else {
        // TODO: merge jcrop/image_edit.js - there is a potential (if unlikely)
        // race condition here that could make FAIL if jcrop hasn't finished
        // loading before init() is called, the image is loaded and cropper
        // initialised.
        jQuery.getScript(self.script.jcrop)
        jQuery.getScript(
            self.script.iedit,
            function() {
                self.loaded = true;
                self.init(args);
            }
        );
    }

    return false;
};

/* DEBUG FUNCTIONS */
IA.do_nothing = function() {
    return false;
};

/* send debugging output to firebug console, if avilable */
IA.debug = (window.console && window.console.log)
    ? function() { window.console.log.apply(console, arguments); }
    : IA.do_nothing;


IA.is_ie6 = function() {
    if (navigator.appName == 'Microsoft Internet Explorer') {
        var ua = navigator.userAgent;
        var re = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})");
        if (re.exec(ua) != null)
            rv = parseFloat(RegExp.$1);
        if (rv < 7) {
            IA.is_ie6 = function() {return 1};
            return 1;
        }
        ;
    }
    IA.is_ie6 = function() {return 0};
    return 0;
};


/* SURVEY POPUP */
function move_popup(el, close_text) {
    /* IE6 has problems with z-index */

    if (IA.is_ie6()) {return};

    el = $(el);

    var windowDim = getWindowDim();
    var scrollXY = getWindowScrollXY();
    var current_pos = getOffset(el);

    var window_x = scrollXY.left + Math.ceil(windowDim.width / 2);
    var window_y = scrollXY.top + Math.ceil(windowDim.height / 2);
    var centre_x = window_x - current_pos.left - Math.ceil(el.offsetWidth / 2);
    var centre_y = window_y - current_pos.top - Math.ceil(el.offsetHeight / 2);

    var bg_offset = getOffset(el.offsetParent);

    var timeout;

    /* Create a background to go behind the popup */
    var bg = document.createElement('a');
    var border = 30;
    var bgs = bg.style;
    bgs.display = 'none';
    bgs.position = 'absolute';
    bgs.width = (el.offsetWidth + border) + 'px';
    bgs.height = border + 'px';
    bgs.left =
        (window_x - bg_offset.left - Math.ceil(el.offsetWidth / 2) - border) + 'px';
    bgs.top =
        (window_y - bg_offset.top - Math.ceil(el.offsetHeight / 2) - border) + 'px';
    bgs.paddingTop = (el.offsetHeight + border * 2) + 'px';
    bgs.paddingRight = border + 'px';
    bgs.border = '3px solid silver';
    bgs.textAlign = 'right';
    bgs.zIndex = 999;
    bgs.background = '#EEE';
    bg.innerHTML = close_text;

    el.parentNode.insertBefore(bg, el);

    var s = el.style;
    var close_popup = function() {
        s.top = 0;
        s.left = 0;
        bg.style.display = 'none';
        if (timeout) {
            window.clearTimeout(timeout)
        }
    };

    IA.add_event(bg, 'click', close_popup);

    var x_sign = centre_x > 0 ? 1 : -1;
    var y_sign = centre_y > 0 ? 1 : -1;

    centre_x = Math.abs(centre_x);
    centre_y = Math.abs(centre_y);

    var x_incr = 10;
    var y_incr = 10;
    if (centre_x > centre_y) {
        y_incr = Math.ceil(x_incr * centre_y / centre_x);
    } else {
        x_incr = Math.ceil(y_incr * centre_x / centre_y);
    }

    var do_move = function(curr_x, curr_y) {
        curr_x += x_incr;
        if (curr_x > centre_x) {
            curr_x = centre_x;
        }
        curr_y += y_incr;
        if (curr_y > centre_y) {
            curr_y = centre_y;
        }
        s.left = (x_sign * curr_x) + 'px';
        s.top = (y_sign * curr_y) + 'px';

        if (curr_x != centre_x || curr_y != centre_y) {
            timeout = window.setTimeout(function() {
                do_move(curr_x, curr_y)
            }, 5);
        } else {
            bgs.display = 'block';
        }
    }

    do_move(0, 0);
    s.zIndex = 10000;

}

function getWindowDim() {
    var W = 0;
    var H = 0;
    if (typeof (window.innerWidth) == 'number') {
        W = window.innerWidth;
        H = window.innerHeight;
    } else if (document.documentElement &&
        (document.documentElement.clientWidth || document.documentElement.clientHeight)) {
        W = document.documentElement.clientWidth;
        H = document.documentElement.clientHeight;
    } else if (document.body &&
        (document.body.clientWidth || document.body.clientHeight)) {
        W = document.body.clientWidth;
        H = document.body.clientHeight;
    }
    return {
        width : W,
        height : H
    };
}

function getWindowScrollXY() {
    var X = 0;
    var Y = 0;
    if (typeof (window.pageYOffset) == 'number') {
        X = window.pageXOffset;
        Y = window.pageYOffset;
    } else if (document.body &&
        (document.body.scrollLeft || document.body.scrollTop)) {
        X = document.body.scrollLeft;
        Y = document.body.scrollTop;
    } else if (document.documentElement &&
        (document.documentElement.scrollLeft || document.documentElement.scrollTop)) {
        X = document.documentElement.scrollLeft;
        Y = document.documentElement.scrollTop;
    }
    return {
        top : Y,
        left : X
    };
}

function getOffset(el) {
    el = $(el);
    var X = 0;
    var Y = 0;
    while (el && !isNaN(el.offsetLeft) && !isNaN(el.offsetTop)) {
        X += el.offsetLeft - el.scrollLeft;
        Y += el.offsetTop - el.scrollTop;
        el = el.offsetParent;
    }
    return {
        top : Y,
        left : X
    };
}


/* jQuery extensions */
if (jQuery) {
    jQuery.fn.extend({
        // jQuery(spec).iAJAX() binds an ajaxSend event handler to each element in
        // spec that automatically adds the X-iAnnounce-AJAX header to the request
        // object when the element is reloaded via AJAX
        iAJAX: function() {
            return this.ajaxSend(
                function (event, request, options) {
                    request.setRequestHeader("X-iAnnounce-AJAX", "1");
                }
            );
        }
    });
}