var ie = document.all;
var ns6 = document.getElementById && !document.all;
var Translations = {SAVE:"Save", CANCEL:"Cancel", EDIT:"Edit", OK:"OK", YES:"Yes", NO:"No"};

/* Temporary manual console for non-Firefox browsers */
var enable_debugger = false;
if (!console || !console.debug) {var console = {container:false,init:function(){if(console.container) return; console.container=$(document.createElement('div')); console.container.addClassName('console'); $$('body')[0].appendChild(console.container);}, debug:function(){if(!enable_debugger) return; console.init(); $A(arguments).each(function(arg){var div=$(document.createElement('div')); div.innerHTML=arg; console.container.appendChild(div)});}};}

// Helper functions
function _(id) {return(document.getElementById(id));}
function _s(id) {return(document.getElementById(id).style);}
function doJSON(endpoint, query, callback) {new Ajax.Request(endpoint, {parameters:query, onComplete:function(response){callback(eval('('+response.responseText+')'))}});}
function clearChildren(element) {while (element.firstChild) {element.removeChild(element.firstChild);}}
function replaceAll(str, replaceStr, replaceWith) {while (str.indexOf(replaceStr)>-1) str = str.replace(replaceStr,replaceWith);return(str);}
function enhancedToHtml(text) {var params = 'text=' + encodeURI(text); var retAjax = new Ajax.Request( '/23/ajax/enhanced-to-html', {method: 'post', postBody: params, asynchronous: false}); return(retAjax.transport.responseXML);}
function eventIsBubble(e) {if (!e) var e = window.event; var tg = (window.event) ? e.srcElement : e.target; if (tg.nodeName != 'DIV') return; var reltg = (e.relatedTarget) ? e.relatedTarget : e.toElement; while (reltg != tg && reltg.nodeName != 'BODY') reltg= reltg.parentNode; if (reltg==tg) return(true); else return(false);}
function SetCookie(sName, sValue) {document.cookie = sName + "=" + sValue + "; path=/; Max-Age=1200";}
function GetCookie(sName) {var aCookie = document.cookie.split("; ");  for (var i=0; i < aCookie.length; i++) {var aCrumb = aCookie[i].split("="); if (sName == aCrumb[0]) return unescape(aCrumb[1]);} return null;}
function getQueryVariable(variable) {var query = window.location.search.substring(1); var vars = query.split("&"); for (var i=0;i<vars.length;i++) {var pair = vars[i].split("="); if (pair[0] == variable) {return pair[1];}} return(0);}
function isDefined(variable) {return ((typeof(window[variable]) == "undefined") ? false : true);}


// Cookie object
var Cookie = {
    set: function(name, value, daysToExpire) {var expire = ''; if (daysToExpire != undefined) {var d = new Date();d.setTime(d.getTime() + (86400000 * parseFloat(daysToExpire)));expire = '; expires=' + d.toGMTString();} var path = '; path=/'; if (value.length) value=escape(value); else value='""'; return (document.cookie = escape(name) + '=' + value + expire + path);},
    get: function(name) {var cookie = document.cookie.match(new RegExp('(^|;)\\s*' + escape(name) + '=([^;\\s]*)')); return (cookie ? unescape(cookie[2]) : '');},
    erase: function(name) {var cookie = Cookie.get(name) || true; Cookie.set(name, '', -1); return cookie;},
    accept: function() {if (typeof(navigator.cookieEnabled)=='boolean') {return navigator.cookieEnabled;} Cookie.set('_test', '1'); return (Cookie.erase('_test')=='1');}
};

// Get positioning of mouse and object
function getAbsoluteX(e) {if (e.pageX) return(e.pageX); else return(e.clientX + document.body.scrollLeft);}
function getAbsoluteY(e) {if (e.pageY) return(e.pageY); else return(e.clientY + document.body.scrollLeft);}
function getAbsoluteX_obj(obj) {var x = obj.offsetLeft; while (obj.offsetParent) {obj = obj.offsetParent; x += obj.offsetLeft;} return(x);}
function getAbsoluteY_obj(obj) {var y = obj.offsetTop; while (obj.offsetParent) {obj = obj.offsetParent; y += obj.offsetTop;} return(y);}

// CSS photo grid
function resizeCssTable(id, className, force) {
    var o = document.getElementsByClassName(className);
    if (o.length==0) return;
    if (!o[0].offsetHeight) {$(id).style.visibility = 'hidden'; window.setTimeout("resizeCssTable('" + id + "','" + className + "', " + force + ");", 100); return;}
    //for (var i=0; i<o.length; i++) $(o[i]).removeClassName('margined-column');
    if (typeof(force)!=undefined && force) for (var i=0; i<o.length; i++) o[i].style.height = 'auto';
    var top = o[0].offsetTop; var cols = 1;
    while (o[cols] && o[cols].offsetTop==top) cols++;
    for (var rowStart=0; rowStart<(o.length-cols); rowStart+=cols) {var height = 0; for (var i=0; i<cols; i++) height = Math.max(height, o[rowStart+i].offsetHeight); for (var i=0; i<cols; i++) o[rowStart+i].style.height = height+'px';}
    //for (var rowStart=0; rowStart<o.length; rowStart+=cols) {for (var i=0; i<cols; i++) if(i<cols-1) $(o[rowStart+i]).addClassName('margined-column');}
    $(id).style.visibility = 'visible';
}

// Slideshow
function beginSlideshow(url) {var arrPage = getPageSize(); var w = arrPage[2]; var h = arrPage[3]; url = "max_width=" + Math.ceil(w*1.1) + "&max_height=" + Math.ceil(h*1.15) + "&" + url; lightbox('/23/slideshow', {params:url, top:0, left:0, width:w-20, height:h, overflow:'hidden'}); $('lightbox').style.padding = $('lightbox').style.borderBottom = $('lightbox').style.borderTop = $('lightbox').style.borderRight = $('lightbox').style.borderLeft = $('lightbox').style.margin = "0px"; $('lightbox').style.backgroundColor = "transparent";}
function beginSlideshowFromForm(formname) {beginSlideshow(Form.serialize(document.forms[formname]));}

// Tooltip
var objTooltip = false;
var moveWithMouse = false;
function ietruebody(){return (document.compatMode && document.compatMode!="BackCompat")? document.documentElement : document.body;}
function positionTooltip(e) {if (objTooltip) {objTooltip.style.position = 'absolute'; objTooltip.style.display = 'block'; var offsetxpoint = -60; var offsetypoint = 20; var curX = (ns6) ? e.pageX : event.x+ietruebody().scrollLeft; var curY = (ns6) ? e.pageY : event.y+ietruebody().scrollTop; var rightedge = ie&&!window.opera? ietruebody().clientWidth-event.clientX-offsetxpoint : window.innerWidth-e.clientX-offsetxpoint-20; var bottomedge = ie&&!window.opera? ietruebody().clientHeight-event.clientY-offsetypoint : window.innerHeight-e.clientY-offsetypoint-20; var leftedge = (offsetxpoint<0) ? offsetxpoint*(-1) : -1000; if (rightedge<objTooltip.offsetWidth) {objTooltip.style.left = ie ? ietruebody().scrollLeft+event.clientX-objTooltip.offsetWidth+"px" : window.pageXOffset+e.clientX-objTooltip.offsetWidth+"px";} else {if (curX<leftedge) {objTooltip.style.left = "5px";} else {objTooltip.style.left = curX+offsetxpoint+"px"; if (bottomedge<objTooltip.offsetHeight) {objTooltip.style.top = ie ? ietruebody().scrollTop+event.clientY-objTooltip.offsetHeight-offsetypoint+"px" : window.pageYOffset+e.clientY-objTooltip.offsetHeight-offsetypoint+"px";} else {objTooltip.style.top = curY+offsetypoint+"px"; objTooltip.style.visibility = "visible";}}}} if (!moveWithMouse) document.onmousemove = '';}
function showTooltip(id, mwm) {if ( mwm!="undefined" ) {moveWithMouse = mwm;} if (ns6||ie) {objTooltip = _(id);document.onmousemove=positionTooltip;}}
function hideTooltip() {if (objTooltip) {objTooltip.style.display = "none"; objTooltip = false; document.onmousemove = '';}}
function openTooltip(id) {window.open('/23/tip?tip='+id, 'tip', 'location=no,menubar=no,resizable=no,scrollbars=yes,status=no,titlebar=no,toolbar=no,width=400,height=320');}

// Favs & Private etc
function favoriteClick(obj, id, rel) {if (!isDefined(rel)) {if (obj.name=="off") {obj.name = 'on'; obj.src = '/resources/um-style/staron.gif'; rel = "on";} else {obj.name = 'off'; obj.src = '/resources/um-style/staroff.gif'; rel = "off";}} new Ajax.Request('/23/ajax/set-favorite', {parameters:'photo_id='+escape(id)+'&rel='+rel, asynchronous:true});}
function setFavorite(photo_id, fav) {doAction('set-favorite', 'photo_id='+photo_id+'&favorite_p='+(fav?'t':'f'));}
function togglePrivate(photo_id, containerName) {$(containerName).innerHTML = '<img id="imgIndicator" src="/resources/um-style/indicator.gif">'; var params = 'photo_id=' + encodeURI(photo_id) + '&container_name=' + encodeURI(containerName); new Ajax.Updater(containerName, '/23/ajax/toggle-private', {method: 'get', parameters: params});}

// Some html/dom manipulation
//    (auto-expand textareas)
function expandTA(ta) {if (ta.scrollHeight) {if ($(ta).rel!='fixedWidth') $(ta).setStyle({width:ta.getWidth()+'px'});$(ta).rel='fixedWidth';$(ta).setStyle({height:(ta.scrollHeight>350 ? 350 : (ta.scrollHeight<80 ? 80 : ta.scrollHeight))+'px'});}}
//    (automatically insert indicators)
var arrDeindicate = new Object();
function indicate(obj, text) {if (!obj.innerHTML) obj = $(obj); if (text==undefined) text = ''; arrDeindicate[obj.id] = obj.innerHTML;obj.innerHTML = '<div class="indicator"><img src="/resources/um-style/indicator.gif"> &nbsp;' + text + '</div>';}
//    (inline delete confirmations)
function confirmDelete(obj, q, deleteAction, yesText, noText) {if (yesText==undefined) yesText = 'Yes'; if (noText==undefined) noText = 'No'; var cancelHTML = obj.innerHTML; obj.innerHTML = ''; var span = document.createElement('span'); span.className = 'private'; span.innerHTML = q + ' &nbsp;'; obj.appendChild(span); var a = document.createElement('a'); a.innerHTML = yesText; if (typeof(deleteAction)=='function') {a.href = 'javascript:void(0)'; a.onclick = deleteAction;} else {a.href = deleteAction;} obj.appendChild(a); var span = document.createElement('span'); span.innerHTML = ' / '; obj.appendChild(span); var a = document.createElement('a'); a.innerHTML = noText; a.href = 'javascript:void(0)'; Event.observe(a, 'click', function(){obj.innerHTML = cancelHTML;}); obj.appendChild(a);}

function handleInlineHelp() {$$('div.inlineHelp').each(function(item) {if(item.hasClassName('__inlineHelpDone')) return; item.addClassName('__inlineHelpDone'); var icon=document.createElement('img'); icon.src='/resources/um-style/question-mark.gif'; item.parentNode.insertBefore(icon, item); $$('body')[0].appendChild(item); Event.observe(icon, 'mouseover', function(){var pos=Position.cumulativeOffset(icon); item.addClassName('inlineHelpShow'); item.setStyle({left:pos[0]+'px',top:(25+pos[1])+'px'}); }); Event.observe(icon, 'mouseout', function(){item.removeClassName('inlineHelpShow');});});}
function indicateAutoformSubmit() {$A($$('.autoform')).each(function(f) {Event.observe(f, 'submit', function(){f.getElementsBySelector('input[type="submit"]').each(function(submit) {$(submit).disable(); $(submit).addClassName('disabled');}); var indicator = $(document.createElement('div')); f.appendChild(indicator); visual.indicate(indicator, 'Validating form, please wait...');});});}
//document.observe('dom:loaded', indicateAutoformSubmit);

// Tiny MCE
function mceEventHandler(e) {return;}
function mceInitHandler(inst) {return;}
function mceAllInitHandler(inst) {return;}
function createTinyMCE(name, buttons, css) {
    if (buttons==undefined) buttons = "fontsizeselect,separator,bold,italic,underline,strikethrough,separator,justifyleft,justifycenter,justifyright,separator,bullist,numlist,separator,link,unlink,separator,forecolor,backcolor";
    if (name==undefined) var mode = "textareas";
    else var mode = "exact";
    if (css==undefined) tinyMCE.init({theme:"advanced", mode:mode, elements:name, relative_urls:false, convert_urls:false, remove_script_host :false, theme_advanced_buttons1:buttons, theme_advanced_buttons2:"", theme_advanced_buttons3:"", theme_advanced_toolbar_align:'left', theme_advanced_toolbar_location:'top', handle_event_callback:"mceEventHandler", init_instance_callback :"mceInitHandler", oninit:"mceAllInitHandler"});
     else tinyMCE.init({theme:"advanced", mode:mode, elements:name, relative_urls:false, convert_urls:false, remove_script_host :false, theme_advanced_buttons1:buttons, theme_advanced_buttons2:"", theme_advanced_buttons3:"", theme_advanced_toolbar_align:'left', theme_advanced_toolbar_location:'top', handle_event_callback:"mceEventHandler", init_instance_callback :"mceInitHandler", oninit:"mceAllInitHandler", content_css:css});
}


function serializeObject(o) {var a = new Array(); for(i in o) a[a.length]=encodeURI(i)+'='+encodeURI(o[i]); return(a.join('&'));}
function doAction(action, params, opts) {if (typeof(opts)=='undefined' || opts.length==0) var opts = new Object();if (typeof(params)=='undefined' || params.length==0) {var params = 'action='+encodeURI(action);} else {params += '&action='+encodeURI(action);}var options = new Object();options.method = 'post';options.postBody = params;options.evalScripts=true;if (opts.onComplete) {options.onComplete=opts.onComplete;} else if (opts.indicator) {options.onComplete = function(){$(opts.indicator).hide();}}if (opts.onFailure) options.onComplete=opts.onFailure;if (opts.onSuccess) options.onComplete=opts.onSuccess;var url = '/global/ajax/actions';if (opts.container) {new Ajax.Updater(opts.container, url, options);} else {new Ajax.Request(url, options);}}
function setFirstAndLast(o, childNodeName) {if (!$(o)) return; var nodes = $A($(o).getElementsByTagName(childNodeName)); nodes.each(function(node) {nodes.each(function(refNode) {if($(node).descendantOf(refNode)) {nodes = nodes.without(node);return;}});}); if(!nodes.length) return; $(nodes[0]).addClassName('first'); $(nodes[nodes.length-1]).addClassName('last');}
function setOddsAndEvens(o, childNodeName) {var odd=true; $A($(o).getElementsByTagName(childNodeName)).each(function(item) {$(item).addClassName((odd ? 'odd' : 'even')); odd=!odd;});}
function yellowFade(c) {new Effect.Highlight(c, {startcolor: '#FFFFCC', restorecolor:true, duration:3});}

var visual = {
    indicate: function(c, text) {c=$(c); if(!c) return; clearChildren(c); var x=document.createElement('div'); x.className="jumptop center"; var d=document.createElement('div'); d.className='indicator'; d.style.display='inline'; d.innerHTML=text; x.appendChild(d); c.appendChild(x);},

    alert: function(message, onOK) {
        if (typeof(onOK)=='undefined') onOK = function(){};
        var container = $(document.createElement('div')); container.addClassName('visual-alert');
        var m = $(document.createElement('div')); m.addClassName('visual-alert-message'); m.appendChild(document.createTextNode(message));
        var buttons = $(document.createElement('div')); buttons.addClassName('visual-alert-buttons');
        var okButton = $(document.createElement('input')); okButton.setAttribute('type', 'button'); okButton.addClassName('button'); okButton.addClassName('visual-alert-ok-button'); okButton.setAttribute('value', Translation.OK);
        container.appendChild(m); buttons.appendChild(okButton); container.appendChild(buttons);
        var modal = new visual.modalDialog(container);
        Event.observe(okButton, 'click', function(){onOK(); modal.close();});
        this.modal = modal; this.onOK = onOK; return(this);
    },

    confirm: function(question, onYes, onNo) {
        var container = $(document.createElement('div')); container.addClassName('visual-confirm');
        var q = $(document.createElement('div')); q.addClassName('visual-confirm-question'); q.appendChild(document.createTextNode(question));
        var buttons = $(document.createElement('div')); buttons.addClassName('visual-confirm-buttons');
        var yesButton = $(document.createElement('input')); yesButton.setAttribute('type', 'button'); yesButton.addClassName('button'); yesButton.addClassName('visual-confirm-yes-button'); yesButton.setAttribute('value', Translation.YES);
        var noButton = $(document.createElement('input')); noButton.setAttribute('type', 'button'); noButton.addClassName('button'); noButton.addClassName('visual-confirm-no-button'); noButton.setAttribute('value', Translation.NO);
        container.appendChild(q); buttons.appendChild(yesButton); buttons.appendChild(noButton); container.appendChild(buttons);
        var modal = new visual.modalDialog(container);
        Event.observe(yesButton, 'click', function(){onYes(); modal.close();});
        Event.observe(noButton, 'click', function(){onNo(); modal.close();});
        this.modal = modal; this.onYes = onYes; this.onNo = onNo; return(this);
    },

    prompt: function(question, defaultValue, onOK, onCancel) {
        var container = $(document.createElement('div')); container.addClassName('visual-prompt');
        var q = $(document.createElement('div')); q.addClassName('visual-prompt-question'); q.appendChild(document.createTextNode(question));
        var text = $(document.createElement('div')); text.addClassName('visual-prompt-text');
        var input = $(document.createElement('input')); input.setAttribute('type', 'text'); input.addClassName('input'); input.addClassName('visual-prompt-text-input'); input.setAttribute('value', defaultValue);
        var buttons = $(document.createElement('div')); buttons.addClassName('visual-prompt-buttons');
        var okButton = $(document.createElement('input')); okButton.setAttribute('type', 'button'); okButton.addClassName('button'); okButton.addClassName('visual-prompt-ok-button'); okButton.setAttribute('value', Translations.OK);
        var cancelButton = $(document.createElement('input')); cancelButton.setAttribute('type', 'button'); cancelButton.addClassName('button'); cancelButton.addClassName('visual-prompt-cancel-button'); cancelButton.setAttribute('value', Translations.CANCEL);
        container.appendChild(q); text.appendChild(input); container.appendChild(text); buttons.appendChild(okButton); buttons.appendChild(cancelButton); container.appendChild(buttons);
        var modal = new visual.modalDialog(container);
        Event.observe(okButton, 'click', function(){onOK(input.value); modal.close();});
        Event.observe(cancelButton, 'click', function(){onCancel(); modal.close();});
        this.modal = modal; this.input = input; this.onOK = onOK; this.onCancel = onCancel; return(this);
    },

    modalDialog: function(contentDOMNode) {
        var body = $$('body')[0]; var bodyOffset=Position.realOffset(body); bodyDimensions=Element.getDimensions(body);
        // Overall dialog div
        var dialog = $(document.createElement('div')); dialog.setStyle({visibility:'hidden'}); dialog.addClassName('visual-modal-dialog'); dialog.appendChild(contentDOMNode);
        // Screen body from clicks
        var screen = $(document.createElement('div')); screen.addClassName('visual-modal-screen'); screen.setStyle({height:bodyDimensions.height+'px', width:bodyDimensions.width+'px'}); body.appendChild(screen);
        Event.observe(screen, 'click', Event.stop); Event.observe(dialog, 'click', Event.stop);
        // Place it & Calculate it
        body.appendChild(dialog); dialogDimensions=Element.getDimensions(dialog);
        dialog.setStyle({top:(bodyOffset[1]+50)+'px', left:((bodyDimensions.width-dialogDimensions.width)/2)+'px', visibility:'visible'});
        // Prepare return object
        this.dialog=dialog; this.screen=screen; this.close = function() {try {body.removeChild(screen); body.removeChild(dialog);} catch(e){};}
        return(this);
    },

    dialog: function(url, opts) {
        if (typeof(opts)=='undefined') opts = {};
        var body = document.getElementsByTagName('body')[0];

        // Body overlay?
        if(opts.overlay) {
            var fade = new Element('div', {id:'dialogFade'});
            fade.addClassName('visual-dialog-fade');
            var dim = Element.getDimensions(body);
            fade.setStyle({width:dim.width+'px', height:dim.height+'px'});
            body.appendChild(fade);
        }

        // Overall dialog div
        var dialog = $(document.createElement('div'));
        dialog.addClassName('visual-dialog');
        dialog.setStyle({visibility:'hidden'});
        if(opts.id) dialog.setAttribute("id", opts.id);
        if(opts.height) dialog.setStyle({height:opts.height+'px'});
        if(opts.width) dialog.setStyle({width:opts.width+'px'});

        // Container
        var dialogContainer = $(document.createElement('div'));
        dialogContainer.addClassName('visual-dialog-container');
        visual.indicate(dialogContainer, 'Loading...');
        dialog.appendChild(dialogContainer);
        body.appendChild(dialog);

        // Prepare return object
        this.dialog=dialog;
        this.dialogContainer=dialogContainer;
        this.close = function() {try {body.removeChild(dialog); body.removeChild(fade);} catch(e){};}

        // Position the dialog
        var bodyWidth = Element.getDimensions(body).width;
        var dialogWidth = Element.getDimensions(dialog).width;
        if (typeof(opts.top)=='undefined') opts.top=50;
        dialog.setStyle({top:(Position.realOffset(body)[1]+opts.top)+'px', left:((bodyWidth-dialogWidth)/2)+'px', visibility:'visible'});

        // Close when clicking on body
        Event.observe(dialog, 'click', function(event){Event.stop(event);});
        Event.observe(body, 'click', this.close);

        // And give it some content
        if (typeof(opts.method)=='undefined') opts.method = 'GET';
        if (typeof(opts.evalScripts)=='undefined') opts.evalScripts = true;
        var requestOptions = {method:opts.method, evalScripts:opts.evalScripts, parameters:opts.parameters, postBody:opts.postBody, onComplete:opts.onComplete};
        new Ajax.Updater(dialogContainer, url, requestOptions);

        return(this);
    },

    // Make div fields editable
    editableHelper: {has_replaced:false, has_clicked:false, replacedHTML:'', ta:null},
    makeEditable: function(o) {
        if (typeof(o.defaultText)=='undefined' || o.defaultText.length==0) o.defaultText='';
        if (typeof(o.parameterName)=='undefined' || o.parameterName.length==0) o.parameterName='text';
        if (typeof(o.extraParams)=='undefined' || o.extraParams.length==0) o.extraParams=new Object();
        if (typeof(o.message)=='undefined' || o.message.length==0) o.message = 'Click here to edit';
        if (typeof(o.widget)=='undefined' || o.widget.length==0) o.widget = 'textarea';
        if (typeof(o.persistent)=='undefined') o.persistent=false;

        var c = $(o.containerName);
        var h = visual.editableHelper;
        var f = null;
        if (c.empty()) {
            if (o.persistent) {c.addClassName('editablePersistent'); c.innerHTML = o.message;} else {if (c.getHeight()<10) {c.setStyle({height:'20px'});}}
        } else {
            if (!c.getElementsByClassName('editableEditLabel').length) {var editLabel = $(document.createElement('span')); editLabel.addClassName('editableEditLabel'); editLabel.appendChild(document.createTextNode(Translations.EDIT)); c.appendChild(editLabel, c.firstChild);}
        }
        var click = function(e){
            if (h.has_clicked) return; h.has_clicked = true;
            if (!h.has_replaced) {h.replacedHTML = c.innerHTML;} h.has_replaced = true; c.innerHTML=''; c.setStyle({height:''});
            f = document.createElement('form'); $(f).addClassName('editableForm');
            f.setAttribute('onsubmit', 'return(false);');
            Event.observe(f, 'submit', function(e){
                    o.defaultText = (h.ta ? h.ta.value : f[o.parameterName].value);
                    doAction(o.action, Form.serialize(f)+'&'+serializeObject(o.extraParams), {onSuccess:function(r){
                                c.innerHTML=r.responseText;
                                h.has_clicked=false; h.has_replaced=false; c.removeClassName('editable'); c.removeClassName('editableText'); c.removeClassName('editablePersistent');
                                Event.stopObserving(c, 'click', click); Event.stopObserving(c, 'mouseover', mouseover); Event.stopObserving(c, 'mouseout', mouseout);
                                visual.makeEditable(o); yellowFade(c);
                            }});
                    Event.stop(e);
                    return(false);
                });
            Event.observe(f, 'reset', function(e){
                    c.innerHTML=h.replacedHTML;
                    h.has_clicked=false; h.has_replaced=false; c.removeClassName('editable'); c.removeClassName('editableText');
                    Event.stopObserving(c, 'click', click); Event.stopObserving(c, 'mouseover', mouseover); Event.stopObserving(c, 'mouseout', mouseout);
                    visual.makeEditable(o);
                    return(false);
                });
            var d = document.createElement('div');
            if (o.widget=='text') {
                var ta = document.createElement('input'); ta.setAttribute('type', 'text'); ta.setAttribute('name', o.parameterName); ta.className = 'input'; ta.value=o.defaultText;
                if (typeof(o.maxlength)!='undefined') ta.setAttribute('maxlength', o.maxlength);
            } else if (o.widget=='select') {
                var ta = document.createElement('select'); ta.setAttribute('name', o.parameterName); ta.className = 'small discrete';
                for (i in o.selectOptions) {var option = document.createElement('option'); option.value=i; option.innerHTML=o.selectOptions[i]; if (o.defaultText==i) option.setAttribute('selected', 'selected'); ta.appendChild(option);}
            } else {
                var ta = document.createElement('textarea'); ta.setAttribute('name', o.parameterName); ta.setAttribute('rows', '4'); ta.value=o.defaultText;
                Event.observe(ta, 'keyup', function(e){expandTA(ta);}); Event.observe(ta, 'click', function(e){expandTA(ta);}); Event.observe(ta, 'focus', function(e){expandTA(ta);});
                if (typeof(o.maxlength)!='undefined') {ta.setAttribute('onkeyup', 'if(this.value.length>'+o.maxlength+') this.value=this.value.substring(0,'+o.maxlength+');');}
            }
            h.ta = ta; d.appendChild(ta); f.appendChild(d);
            var d = document.createElement('div');
            var submit = document.createElement('input'); submit.setAttribute('type', 'submit'); submit.setAttribute('value', Translations.SAVE); submit.className='button';  d.appendChild(submit);
            d.appendChild(document.createTextNode(' or '));
            var cancel = document.createElement('input'); cancel.setAttribute('type', 'reset'); cancel.setAttribute('value', Translations.CANCEL); cancel.className='discrete'; d.appendChild(cancel);
            // Opera didn't play nice with cancel from a link; had to do it with a form reset button. Don't know why.
            //var cancel = document.createElement('a'); cancel.setAttribute('href', '#'); cancel.setAttribute('onclick', 'return(false);'); cancel.appendChild(document.createTextNode('Cancel')); d.appendChild(cancel);
            //Event.observe(cancel, 'click', function(e){c.innerHTML=''; h.has_clicked=h.has_replaced=false; c.removeClassName('editable'); c.removeClassName('editableText');});
            f.appendChild(d); c.appendChild(f);  ta.focus();
        }
        var mouseover = function(e){
            if (h.has_clicked) return;
            h.replacedHTML = c.innerHTML;
            h.has_replaced = (o.defaultText.length==0);
            if (o.defaultText.length==0) {c.innerHTML=o.message; c.addClassName('editableText');}
            c.addClassName('editable');
        }
        var mouseout = function(e){
            if (h.has_clicked) return;
            if (h.has_replaced) c.innerHTML = h.replacedHTML;
            h.has_replaced = false;
            c.removeClassName('editable'); c.removeClassName('editableText');
        }
        Event.observe(c, 'click', click); Event.observe(c, 'mouseover', mouseover); Event.observe(c, 'mouseout', mouseout);
    },

    browse: {
        dialog:null,
        selection:[],
        begin: function(params, clear) {
            visual.browse.selection = (Cookie.get('browseSelection').length>0 ? $A(Cookie.get('browseSelection').split(',')).uniq() : []);
            //for(var i=0; i<visual.browse.selection.length; i++) visual.browse.selection[i]=new Number(visual.browse.selection[i]);
            if(typeof(params)=='undefined') params={};
            if(typeof(clear)!='undefined' && clear) visual.browse.clearSelection();
            if (!params.return_url) params.return_url=location.href;
            params = $H(params).toQueryString();
            visual.browse.dialog = new visual.dialog(USER_URL+'a/browse', {method:'POST', postBody:params, width:900, height:500, overlay:true});
        },
        search: function() {
            var f = $('browseForm');
            // IE 5.5 doesn't support $F() for selects, so we're doing it the hard way
            params = (typeof(f.params.selectedIndex)!='undefined' ? f.params[f.params.selectedIndex].value : f.params.value);
            //params = $F(f.params);
            params += '&search_string='+encodeURI($F(f.search_string));
            visual.indicate('browsePhotos', 'Fetching photos, please wait...');
            new Ajax.Updater('browsePhotos', USER_URL+'a/browse-include', {method:'post',postBody:params,evalScripts:true});
            if($('browseSelectAllLink')) $('browseSelectAllLink').hide();
            if($('browseUnselectAllLink')) $('browseUnselectAllLink').hide();
        },
        saving:function(){
            // Maybe the box has been closed?
            if (!$('browseCancel')) return;

            $('browseCancel').hide();
            $$('.highlightbackground').each(function(el) {$(el).removeClassName('highlightbackground');});
            $('browseSaving').addClassName('highlightbackground');
            visual.indicate('browseSaving', 'Performing actions, please wait...');
            $$('#browseActionButtons a').each(function(button) {$(button).addClassName('disabled');});
            $$('input').each(function(button) {$(button).disable(); $(button).addClassName('disabled');});
        },
        notSaving:function(){
            if (!$('browseCancel')) return;
            $('browseCancel').show(); $('browseSaving').hide();
            $$('.browse-action-button').each(function(button) {$(button).removeClassName('disabled');});
        },
        select: function(img, photo_id, doUnselect) {
            if(typeof(doUnselect)=='undefined') doUnselect=true;
            var img = $(img);
            img.addClassName('opaque');

            if (visual.browse.selection.indexOf(photo_id.toString())>=0 || visual.browse.selection.indexOf(photo_id)>=0) {if (doUnselect) visual.browse.unselect($('browseSelectedImg'+photo_id), photo_id); return;}
            visual.browse.selection[visual.browse.selection.length] = photo_id.toString();
            visual.browse.selection = visual.browse.selection.uniq();
            visual.browse.saveSelection();

            var newImg = $(document.createElement('img'));
            newImg.src = img.src;
            newImg.setAttribute('id', 'browseSelectedImg'+img.getAttribute('rel'));
            newImg.setAttribute('rel', img.getAttribute('rel'));
            newImg.setStyle({width:'50px', height:'50px', padding:'2px', margin:'0'});
            Event.observe(newImg, 'click', function(){visual.browse.unselect(newImg, photo_id);});
            $('browseSelection').appendChild(newImg);

            visual.browse.maintainUIState();
        },
        selectAll: function() {$$('#browsePhotos img').each(function(img) {var id = img.getAttribute('rel'); visual.browse.select(img, id, false);});},
        unselect: function(img, photo_id) {
            visual.browse.selection = visual.browse.selection.without(photo_id);
            visual.browse.saveSelection();
            if ($('browseImg'+photo_id)) $('browseImg'+photo_id).removeClassName('opaque');
            img.remove();

            visual.browse.maintainUIState();
        },
        unselectAll: function() {$$('#browseSelection img').each(function(img) {var id = img.getAttribute('rel'); visual.browse.unselect(img, id);});},
        saveSelection: function() {
            if(visual.browse.selection.length)
                Cookie.set('browseSelection', visual.browse.selection.join(','), 1);
            else
                Cookie.erase('browseSelection');
        },
        clearSelection: function() {
            Cookie.erase('browseSelection');
            visual.browse.selection = new Array();
            visual.browse.saveSelection();
            visual.browse.maintainUIState();
        },
        maintainUIState: function() {
            // Show, hide and disable based on state

            // Unselect all & Action buttons disabled?
            if ($('browseUnselectAllLink')) {
                if (visual.browse.selection.length) {
                    $$('.browse-action-button').each(function(button) {$(button).removeClassName('disabled');});
                    $('browseUnselectAllLink').show();
                } else {
                    $$('.browse-action-button').each(function(button) {$(button).addClassName('disabled');});
                    $('browseUnselectAllLink').hide();
                }
            }

            // Select all
            if ($('browseSelectAllLink')) {
                $('browseSelectAllLink').hide();
                $$('#browsePhotos img').each(function(img) {if (!img.hasClassName('opaque')) {$('browseSelectAllLink').show(); throw $break;}});
            }
        }
    }
}


visual.addHoverClass = function(cssIdentifier, hoverClassName) {$A($$(cssIdentifier)).each(function(element) {Event.observe(element, 'mouseover', function(){$(element).addClassName(hoverClassName);}); Event.observe(element, 'mouseout', function(){$(element).removeClassName(hoverClassName);});});}
document.observe('dom:loaded', function(){
                     visual.addHoverClass('#tabs li', 'hover');
                 });


var MoreMenus = {
    build:function(container) {
        var body = $$('body')[0];
        $(container).getElementsBySelector('li').each(function(li) {
                li = $(li); var moreMenus = li.getElementsByClassName('more-menu-popup')
                if (moreMenus.length) {
                    li.addClassName('more-menu-container');
                    $A(li.getElementsByTagName('a')).each(function(a) {Event.observe(a, 'click', function(e){location.href=a.getAttribute('href'); Event.stop(e);});});
                    var menu = moreMenus[0];
                    body.appendChild(menu);
                    Event.observe(li, 'click', function(e){MoreMenus.click(e, li, menu);});
                }
            });
        Event.observe(body, 'click', MoreMenus.destroy);
    },
    click:function(event, container, menu) {
        if (!menu) return;
        if(menu.style.display=='block') MoreMenus.destroy(); else MoreMenus.show(event, container, menu);
        var body = $$('body')[0];
        Event.stop(event);
    },
    destroy: function() {$$('.more-menu-popup').each(function(popup) {popup.style.display='none';}); $$('.more-menu-container').each(function(container) {container.removeClassName('more-menu-container-selected')});},
    show: function(event, container, menu) {
        MoreMenus.destroy();
        container.addClassName('more-menu-container-active');
        var offset=Position.cumulativeOffset(container);  var dimensions=$(container).getDimensions();
        menu.setStyle({left:offset[0]+'px',top:(4+offset[1]+dimensions.height)+'px'}); menu.style.display='block';
    }
}


var Selectbox = {
    prepare: function(o, onSelect) {     // make the custom html snippet into a selectbox
        // Add a <ul> for the selection
        o.appendChild(new Element('ul').addClassName('selection'));

        // Expand and fold on click
        o.observe('click', function(e){Selectbox.toggle(o); e.stop();});
        $$('body')[0].observe('click', function(e){Selectbox.toggle(o, true);});

        // Append 'option' classname to all option items, and make them clickable
        o.select('.options li').each(function(option) {
                if (!option.hasClassName('group')) {
                    option.addClassName('option');
                    option.observe('click', function(){Selectbox.select(o,option,onSelect);});
                }
            });

        // Add 'hover' on mouse over (and remove on mouse out) to all <li> items
        o.select('ul, li').each(function(item) {
                item.observe('mouseover', function(){item.addClassName('hover')});
                item.observe('mouseout', function(){item.removeClassName('hover')});
            });

        // Keep the selection current
        Selectbox.updateSelection(o);
    },
    toggle:function(o, remove) {     // Toggle selectbox expansion by adding or removing the 'expanded' class name
        if(o.hasClassName('expanded') || (typeof(remove)!='undefined' && remove)) {
            o.removeClassName('expanded');
        } else {
            // Place options list
            var optionsElement = o.select('ul.options')[0];
            optionsElement.setStyle({display:'', visibility:'hidden'});
            var optionsDims = optionsElement.getDimensions();
            // TODO: display below or over?
            //var top = o.cumulativeOffset().top + o.getDimensions().height - 1;
            var top = o.cumulativeOffset().top - optionsDims.height - 1;
            var left = o.cumulativeOffset().left;
            o.select('ul.options')[0].setStyle({top:top+'px', left:left+'px'});
            // show options
            o.addClassName('expanded');
            optionsElement.setStyle({visibility:'visible'});
        }
    },
    updateSelection: function(o) {    // Update the 'selection' list according to selected item on the options list
        var selectionElement = o.select('ul.selection')[0];
        // Remove all current children on the selection element
        selectionElement.childElements().each(Element.remove);
        // Look for a selected item
        var sel = o.select('.options li.selected');
        var selectboxRel = o.getAttribute('rel');
        if(sel.length) {
            // There is at least one selected item
            var content = $(sel[0].cloneNode(true));
            content.classNames().each(function(className){content.addClassName(className);});
            content.update(selectboxRel.length ? selectboxRel : '&nbsp;')
        } else {
            // No selection
            var content = new Element('li').update(selectboxRel.length ? selectboxRel : '&nbsp;')
        }
        selectionElement.appendChild(content);
        content.observe('click', function(e){Selectbox.toggle(o); e.stop();});
    },
    select: function(o,i,onSelect) {    //select a given item...
        if(i.hasClassName('selected')) return;
        // Deselect other items
        o.select('li.option').each(function(option){option.removeClassName('selected');});
        i.addClassName('selected');
        Selectbox.updateSelection(o);
        // Invoke onSelect()
        if(onSelect) onSelect(i.getAttribute('rel'));
    }
}



if (document.observe) {
    document.observe('dom:loaded', function(){
            try {Slideshow.possiblyStartSlideshow();} catch(e) {}
        });
}


var _xhrid = 0;
var _xhruploadloaded = {};
var _xhruploadtotal = {};
var _xhrstatus = false;
function _xhr_updateProgress() {
    var loaded = 0;
    $H(_xhruploadloaded).each(function(k){loaded+=k.value;});
    var total = 0;
    $H(_xhruploadtotal).each(function(k){total+=k.value;});
    if(loaded==total) {
        _xhrstatus.innerHTML = 'Done uploading';
    } else {
        _xhrstatus.innerHTML = 'Uploaded ' + Math.floor(loaded/total*100.0) + '%';
    }
}
function _xhr_uploadFile(file) {
    if(typeof(upload_context)=='undefined') upload_context='';
    if(!_xhrstatus) {
        _xhrstatus = new Element('div').setStyle({position:'absolute', top:'10px', right:'10px', fontWeight:'bold'});
        $$('body')[0].appendChild(_xhrstatus);
    }
    var reader = new FileReader();
    var i = _xhrid++;
    reader.onload = function(e) {
        var bin = e.target.result;
        var xhr = new XMLHttpRequest();

        _xhruploadtotal[i]=file.size;
        xhr.upload.addEventListener('progress', function(e) {_xhruploadloaded[i]=e.loaded; _xhr_updateProgress();}, false);
        xhr.upload.addEventListener('load', function(e) {_xhruploadloaded[i]=file.size; _xhr_updateProgress();}, false);
        _xhr_updateProgress();
          
        xhr.open("POST", "/23/ajax/xhr-upload?_original_filename="+encodeURIComponent(file.name)+"&upload_context="+encodeURIComponent(upload_context));
        xhr.overrideMimeType('text/plain; charset=x-user-defined-binary');
        xhr.sendAsBinary(bin);
    };
    reader.readAsBinaryString(file);
}

try {
    document.addEventListener("dragover", function(event) {
            try {event.preventDefault();} catch(e){}
        }, true);
    document.addEventListener("drop", function(event) {            
            try {event.preventDefault(); $A(event.dataTransfer.files).each(_xhr_uploadFile);} catch(e){}
        }, true);
} catch(e){}