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

}

function hashHandler(f){
  $$('*[href]').each(function(el){
      var m = el.getAttribute('href').match(/#(.+)/)
      if(m) {
        el.setAttribute('rel', m[1]);
        el.setAttribute('href', "");
        el.observe('click', function(e){
            try {
              Event.stop(e);
              f(el.getAttribute('rel')).bind(el);
            }catch(e){}
          });
      }
    });
}

// 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.showDialog = function(url, opts) {
    if (typeof(opts)=='undefined') opts = {};
    var body = document.getElementsByTagName('body')[0];

    // Body 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(!$(url)) {
      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);
    } else {
      dialogContainer.childElements().each(Element.remove);
      dialogContainer.appendChild($(url));
    }

    return(this);
}

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 {getFlexApp('videoplayer').unload();} catch(e) {}
    });


document.observe('dom:loaded', function(){
        $$('.videodemo').each(function(el){
                el.observe('click', function(e){
                        new visual.dialog(el.href, {width:640,height:400,overlay:true,noscroll:true}); 
                        Event.stop(e);
                    });
            });
    });


function textToStub(text) {
    return(text.toLowerCase().replace(new RegExp(' ', 'img'), '-').replace(new RegExp('[^a-z\-]', 'img'), ''));
}
function createIndex(headline, cssSelector) {
  container = $$('.sidebar-links')[0];
    var ul = document.createElement('ul');
    $A($('realstuff').select(cssSelector)).each(function(item) {
            var anchorName = textToStub(item.innerHTML);
            var link = document.createElement('a');
            link.setAttribute('name', anchorName);
            item.parentNode.insertBefore(link, item);

            var li = document.createElement('li');
            var a = document.createElement('a');
            a.setAttribute('href', '#'+anchorName);
            a.innerHTML = item.innerHTML;
            li.appendChild(a);
            ul.appendChild(li);
        });
    $$('body')[0].addClassName('has-sidebar');
    $$('.sidebar')[0].addClassName('has-index');
    var div = new Element('div').addClassName('jumpbottom');
  //if(headline.length>0) div.appendChild(new Element('a',{href:'#top'}).appendChild(new Element('h3').update(headline)));
    div.appendChild(ul);

    if(container.childElements().length) div.addClassName('small').addClassName('bigjumptop');
    container.appendChild(div);
    $$('.sidebar')[0].setStyle({display:'block'});
}




