if (!visual) var visual={};

Position.getWindowSize = function(w) {
    var width, height;
    w = w ? w : window;
    width = w.innerWidth || (w.document.documentElement.clientWidth || w.document.body.clientWidth);
    height = w.innerHeight || (w.document.documentElement.clientHeight || w.document.body.clientHeight);
    return {width:width, height:height};
}

function showSlideshow(src) {
    // Destroy old slideshow...
    if ($('__slideshow_iframe')) {var d = $('__slideshow_iframe'); d.parentNode.removeChild(d);}

    var ifrm = $(document.createElement('iframe'));
    var body = $$('body')[0];
    ifrm.setAttribute('id', '__slideshow_iframe'); ifrm.setAttribute('src', src); ifrm.setAttribute('frameborder', '0'); ifrm.setAttribute('border', '0');  ifrm.setAttribute('scrolling', 'no');

    windowSize = Position.getWindowSize();
    ifrm.setAttribute('width', windowSize.width-90); ifrm.setAttribute('height', windowSize.height-70);
    ifrm.setStyle({position:'absolute', top:(Position.realOffset(body)[1]+30)+'px', left:'30px', border:'8px solid #eee'});
    body.appendChild(ifrm);
}

function formatRating(rating,blockID) {return('(' + Math.floor(rating*10.0)/10.0 + ')');}
function rate(id,rating,numunits,blockID) {
    $$('#block'+blockID+' .object-rating-user-average').each(function(el){$(el).removeClassName('object-rating-user-average');});
    $$('#block'+blockID+' .object-rating-'+rating).each(function(el){$(el).addClassName('object-rating-user-average');});
    $$('#block'+blockID+' .object-rating').each(function(el){
            $(el).removeClassName('object-rating-no-user');
            $(el).addClassName('object-rating-user');
        });
    doAction('photo-rate', 'photo_id='+encodeURIComponent(id)+'&num_units='+encodeURIComponent(numunits)+'&rating='+encodeURIComponent(rating), {onSuccess:function(r){
                var avg_rating = r.responseText;
                if (!avg_rating.length) return;
                $$('#block'+blockID+' .object-rating-average-value').each(function(el){el.innerHTML = formatRating(avg_rating,blockID);});
                $$('#block'+blockID+' .object-rating-average').each(function(el){$(el).removeClassName('object-rating-average');});
                var int_rating = Math.floor(Math.round(avg_rating));
                $$('#block'+blockID+' .object-rating-'+int_rating).each(function(el){$(el).addClassName('object-rating-average');});
            }});

}

// 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');}
};

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'});}}
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(o[rowStart+i]) $(o[rowStart+i]).addClassName(i<cols-1 ? 'margined-column' : 'non-margined-column');
    }
    $(id).style.visibility = 'visible';
}

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;if (typeof(opts.asynchronous)!=undefined) options.asynchronous=opts.asynchronous;var url = '/actions';if (opts.container) {new Ajax.Updater(opts.container, url, options);} else {new Ajax.Request(url, options);}}
function rev(s) {var r=''; for (var i=s.length-1; i>=0; i--) r+=s.charAt(i); return r;}
function revmailto(e) {location.href = 'mailto:' + rev(e);}
function multiEdit() {if (visual && visual.page && visual.page.view_params.length) {var params = visual.page.view_params;} else {if (visual && visual.photos && visual.photos.length) {var a = []; for (var i=0; i<visual.photos.length; i++) a[a.length]='photos='+visual.photos[i].photo_id; var params = a.join('&');}} if (params.length) location.href='/organize?return_url='+encodeURI(visual.page.return_url)+'&show_search_form_p=f&'+params;}
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 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 indicate(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);}
function yellowFade(c) {new Effect.Highlight(c, {startcolor: '#FFFFCC', restorecolor:true, duration:3});}
/* Show inline help for all <div class="inlineHelp">...</div> */
function handleInlineHelp() {$$('div.inlineHelp').each(function(item) {if(item.hasClassName('__inlineHelpDone')) return; item.addClassName('__inlineHelpDone'); var icon=document.createElement('img'); icon.src='/resources/um/graphics/icons/info-icon.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 preloadImage(src) {var img = new Image(); img.src=src;};

function str_repeat(i,m){for(var o=[];m>0;o[--m]=i);return(o.join(''));}
function sprintf(){var i=0,a,f=arguments[i++],o=[],m,p,c,x;while(f){if(m=/^[^\x25]+/.exec(f))o.push(m[0]);else if(m=/^\x25{2}/.exec(f))o.push('%');else if(m=/^\x25(?:(\d+)\$)?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(f)){if(((a=arguments[m[1]||i++])==null)||(a==undefined))throw("Too few arguments.");if(/[^s]/.test(m[7])&&(typeof(a)!='number'))
throw("Expecting number but found "+typeof(a));switch(m[7]){case'b':a=a.toString(2);break;case'c':a=String.fromCharCode(a);break;case'd':a=parseInt(a);break;case'e':a=m[6]?a.toExponential(m[6]):a.toExponential();break;case'f':a=m[6]?parseFloat(a).toFixed(m[6]):parseFloat(a);break;case'o':a=a.toString(8);break;case's':a=((a=String(a))&&m[6]?a.substring(0,m[6]):a);break;case'u':a=Math.abs(a);break;case'x':a=a.toString(16);break;case'X':a=a.toString(16).toUpperCase();break;}
a=(/[def]/.test(m[7])&&m[2]&&a>0?'+'+a:a);c=m[3]?m[3]=='0'?'0':m[3].charAt(1):' ';x=m[5]-String(a).length;p=m[5]?str_repeat(c,x):'';o.push(m[4]?a+p:p+a);}
else throw("Huh ?!");f=f.substring(m[0].length);}
return o.join('');}


visual.removeNodes = function(cssIdentifier) {if ($$(cssIdentifier)) $A($$(cssIdentifier)).each(function(node) {node.parentNode.removeChild(node);});}
visual.setText = function(cssIdentifier, text) {$A($$(cssIdentifier)).each(function(item) {item.innerHTML = text;});}
visual.contain = function(cssIdentifier, containerId) {var o = $$(cssIdentifier); if (o.length) {var e = o[0]; var c = document.createElement('div'); c.setAttribute('id', containerId); e.parentNode.insertBefore(c, e); c.appendChild(e);}}
visual.insert = function(actionElement, toElement, location, force) {
    actionElement=$(actionElement);toElement=$(toElement);
    if (!actionElement || !toElement) return;
    if (location!='top') location='bottom';
    if (!actionElement||!toElement) {return;}
    if(location=='bottom') toElement.appendChild(actionElement);
    else toElement.insertBefore(actionElement, toElement.firstChild);
}

visual.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', '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);
}
visual.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', 'Yes');
    var noButton = $(document.createElement('input')); noButton.setAttribute('type', 'button'); noButton.addClassName('button'); noButton.addClassName('visual-confirm-no-button'); noButton.setAttribute('value', '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);
}
visual.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', 'Ok');
    var cancelButton = $(document.createElement('input')); cancelButton.setAttribute('type', 'button'); cancelButton.addClassName('button'); cancelButton.addClassName('visual-prompt-cancel-button'); cancelButton.setAttribute('value', '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);
}

visual.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);
}

visual.dialog = function(url, opts) {
    if (typeof(opts)=='undefined') opts = {};
    var body = document.getElementsByTagName('body')[0];

    // Body overlay?
    if(opts.overlay) {
        var dim = Element.getDimensions(body);
        var fade = new Element('div', {id:'dialogFade'}).addClassName('visual-dialog-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'});


    if(opts.noscroll) {
        dialog.setStyle({overflow:'hidden'});
    }

    // Container
    var dialogContainer = $(document.createElement('div'));
    dialogContainer.addClassName('visual-dialog-container');
    indicate(dialogContainer, 'Loading...');
    dialog.appendChild(dialogContainer);
    body.appendChild(dialog);

    // Prepare return object
    var closebox = $(document.createElement('div'));
    this.dialog=dialog;
    this.dialogContainer=dialogContainer;
    this.close = function() {try {body.removeChild(dialog); body.removeChild(closebox); 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 button
    closebox.addClassName('visual-close');
    closebox.setStyle({top:(dialog.cumulativeOffset().top-15)+'px', left:(dialog.cumulativeOffset().left+dialog.getWidth()-15)+'px'});
    Event.observe(closebox, 'click', function(){this.close();}.bind(this));
    body.appendChild(closebox);

    // Close when clicking on body
    Event.observe(dialog, 'click', function(event){Event.stop(event);});
    if(opts.overlay) {Event.observe(fade, '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
visual.editableHelper = {has_replaced:false, has_clicked:false, replacedHTML:'', ta:null};
function makeEditable(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('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);
                            makeEditable(o);
                        }});
                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);
                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', 'Save'); submit.className='button';  d.appendChild(submit);
        d.appendChild(document.createTextNode(' or '));
        var cancel = document.createElement('input'); cancel.setAttribute('type', 'reset'); cancel.setAttribute('value', '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);
}

visual.browse = {
    dialog:null,
    selection:[],
    begin: function(params, clear) {
	visual.browse.selection = (Cookie.get('browseSelection').length>0 ? $A(Cookie.get('browseSelection').split(',')).uniq() : []);
	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('/photos/browse', {method:'POST',postBody:params,width:910,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));
	indicate('browsePhotos', 'Fetching photos, please wait...');
	new Ajax.Updater('browsePhotos', '/photos/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();
	indicate('browseSaving', 'Performing actions, please wait...');
	$$('.browse-action-button').each(function(button) {$(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:'30px', height:'30px', padding:'1px'});
	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.handleSectionSelector = function() {
    $$('.section-selector').each(function(selector){
            selector.select('.section-menu a').each(function(a){
                    a.observe('click', function(e){
                            selector.select('.section-menu li').invoke('removeClassName', 'selected');
                            $(e.target).up().addClassName('selected');
                            var x = e.target.href.split('?');
                            var params = (x.length>1 ? 'inline_p=1&'+x[1] : 'inline_p=1')
                            var c = selector.select('.section-content')[0];
                            c.childElements().each(Element.remove);
                            new Ajax.Updater(c, x[0], {evalScripts:true, parameters:params, onSuccess:function(){window.setTimeout(function(){$(c).scrollTo();}, 500);}});
                            Event.stop(e);
                        });
                });
            if (typeof(sectionSelectorMode)=='undefined') sectionSelectorMode = '';
            if (typeof(sectionSelectorInline)=='undefined') sectionSelectorInline = false;
            var rule = (sectionSelectorMode.length  ? '.section-menu a[rel='+sectionSelectorMode+']' : '.section-menu a');
            var def = selector.select(rule)[0];
            def.up().addClassName('selected');
            if (sectionSelectorInline==false && !sectionSelectorMode.length) {
                var x = def.href.split('?');
                var params = (x.length>1 ? 'inline_p=1&'+x[1] : 'inline_p=1');
                new Ajax.Updater(selector.select('.section-content')[0], x[0], {evalScripts:true, parameters:params});
            }
        });
}
visual.setSelectValue = function(select, value) {for(var i=0; i<select.options.length; i++) {if(select.options[i].value==value) {select.options[i].selected=true; return;}}}
visual.handlePreview=function(){
    $A($$('input.preview')).each(function(element) {
            Event.observe(element, 'focus', function(){if(element.hasClassName('preview')) {element.removeClassName('preview'); element.value='';}});
            element.up('form').observe('submit', function(e){if(element.hasClassName('preview')) {element.removeClassName('preview'); element.value='';}});
        });
}
visual.handleEmbed=function(){
    $A($$('input.embed,textarea.embed')).each(function(element) {
            Event.observe(element, 'click', function(){element.select(); element.focus();});
        });
}
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);});
	});
    }
visual.addSingleHoverClass = function(cssIdentifier, hoverClassName) {
    $A($$(cssIdentifier)).each(function(element) {
	    Event.observe(element, 'mouseover', function(e){$(element).addClassName(hoverClassName); Event.stop(e);});
	    Event.observe(element, 'mouseout', function(){$(element).removeClassName(hoverClassName);});
	});
    }
document.observe('dom:loaded', function(){
        visual.handlePreview();
        visual.handleSectionSelector();
        visual.handleEmbed();
        visual.addHoverClass('#admintabs li, #adminsubtabs li', 'hover');
        visual.addHoverClass('#contextnav li', 'hover');
        visual.addHoverClass('.context-links a.iconbutton', 'hover');
        visual.addHoverClass('.view-item div, .view-item img', 'hover');
        visual.addHoverClass('.hoverable', 'hover');
        visual.addSingleHoverClass('.object-rating-hoverable', 'object-rating-hover');
    });


function fbs_click() {u=location.href;t=document.title;window.open('http://www.facebook.com/sharer.php?u='+encodeURIComponent(u)+'&t='+encodeURIComponent(t),'sharer','toolbar=0,status=0,width=626,height=436');return false;}


function getFlexApp(appName) {return(document[appName] ? document[appName] : window[appName]);}
Event.observe(window, 'beforeunload', function(){
        try {$$('object').each(function(o){o.unloadVideoPlayer();});} catch(e){}
    });


document.observe('dom:loaded', function(){
  if(typeof(Calendar)!=='undefined'&&Calendar&&Calendar.setup) {
      $$('form.autoform input[name$=_date]').each(function(el){
          Calendar.setup({dateField: el});
        });
    }
  });

document.observe('dom:loaded', function(){
    var translatorGrid = {};
    $$('.translator-mode-translated, .translator-mode-untranslated').each(function(el){
        el.absolutize();
        var o = el.cumulativeOffset();
        while ( translatorGrid[index = [Math.floor(o.left/10), Math.floor(o.top/10)].join(',')] ) {
          o.left += 10;
          el.setStyle({left:o.left+'px'});
        }
        translatorGrid[index] = true;
        el.addClassName('translator-mode-absolutized');
        el.observe('click', function(e){
            location.href = '/manage/translate/batch?message_key='+el.getAttribute('rel')+'&return_url='+encodeURIComponent(location.href);
            e.stop();
          }.bind(el));
      });
  });
