Object.extend(Position, { // // getPageScroll() // Returns array with x,y page scroll values. // Core code from - quirksmode.org // pageScroll: function (){ var yScroll; if (self.pageYOffset) { yScroll = self.pageYOffset; } else if (document.documentElement && document.documentElement.scrollTop){ // Explorer 6 Strict yScroll = document.documentElement.scrollTop; } else if (document.body) {// all other Explorers yScroll = document.body.scrollTop; } arrayPageScroll = new Array('',yScroll) return arrayPageScroll; }, // // getPageSize() // Returns array with page width, height and window width, height // Core code from - quirksmode.org // Edit for Firefox by pHaez // pageSize: function (){ var xScroll, yScroll; if (window.innerHeight && window.scrollMaxY) { xScroll = document.body.scrollWidth; yScroll = window.innerHeight + window.scrollMaxY; } else if (document.body.scrollHeight > document.body.offsetHeight){ // all but Explorer Mac xScroll = document.body.scrollWidth; yScroll = document.body.scrollHeight; } else { // Explorer Mac...would also work in Explorer 6 Strict, Mozilla and Safari xScroll = document.body.offsetWidth; yScroll = document.body.offsetHeight; } var windowWidth, windowHeight; if (self.innerHeight) { // all except Explorer windowWidth = self.innerWidth; windowHeight = self.innerHeight; } else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode windowWidth = document.documentElement.clientWidth; windowHeight = document.documentElement.clientHeight; } else if (document.body) { // other Explorers windowWidth = document.body.clientWidth; windowHeight = document.body.clientHeight; } // for small pages with total height less then height of the viewport if(yScroll < windowHeight){ pageHeight = windowHeight; } else { pageHeight = yScroll; } // for small pages with total width less then width of the viewport if(xScroll < windowWidth){ pageWidth = windowWidth; } else { pageWidth = xScroll; } return {"pageWidth": pageWidth, "pageHeight": pageHeight, "windowWidth": windowWidth, "windowHeight": windowHeight}; } }); Object.extend(Element, { stringValue: function(element) { var str_value = ''; var iterator = function(e) { if (e.nodeType == 3) str_value += e.nodeValue; else if (e.nodeType == 1) $A(e.childNodes).each(iterator); }; $A($(element).childNodes).each(iterator); return str_value; } }); oAvalonRPC = new AvalonRPC(); var Avalon = {} Avalon.Browser = { name: false, version: false, initialize: function() { var match = false; if (match = (/MSIE (\d+)\.(\d+)/.exec(navigator.userAgent))) { this.name = 'MSIE'; this.version = match[1]; } else if (match = (/Gecko\/(\d+)/.exec(navigator.userAgent))) { this.name = 'GECKO'; this.version = match[1]; } else if (match = (/KHTML/.exec(navigator.userAgent))) { this.version = 1; if (match = (/KDE/.exec(navigator.vendor))) this.name = 'Konqueror'; else this.name = 'KHTML'; } else if (match = (/Opera(\/)?(\d+)/.exec(navigator.userAgent))) { this.name = 'OPERA'; this.version = match[2]; } else { this.name = 'Unknown'; this.version = 0; } } } $B = function(spec) { if (!Avalon.Browser.name) Avalon.Browser.initialize(); var match; if (match = /(\w+)\s*((=|>|<|>=|<=|!=)\s*\d+)/.exec(spec)) { var ver_check = false; var version = Avalon.Browser.version; switch (match[3]) { case '=': ver_check = (version == match[3]); break; case '>': ver_check = (version > match[3]); break; case '>=': ver_check = (version >= match[3]); break; case '<': ver_check = (version < match[3]); break; case '>=': ver_check = (version >= match[3]); break; case '!=': ver_check = (version != match[3]); break; default: ver_check = true; break; } return (match[1].toUpperCase() == Avalon.Browser.name) && ver_check; } else { return spec.toUpperCase() == Avalon.Browser.name; } return false; } $MSG = function(id) { var elem = $('_msg_' + id); if (elem) return elem.innerHTML; else return '#ERR: unknown message id'; } Avalon.Ajax = { ping_interval: 1000 * 60 * 5, last_activity: 0, server_config: {}, activityListener: function() { this.last_activity = (new Date()).getTime(); }, connect: function() { if (!this.serverPing()) throw 'RPC not supported'; if (!oAvalonRPC.checkCookie()) throw 'No cookies'; this.last_activity = (new Date()).getTime(); this.server_config = oAvalonRPC.getServerConfig(); if (this.server_config.session_timeout) { Event.observe(document.body, 'mouseover', this.activityListener.bind(this)); setInterval(this.serverKeepAlive.bind(this), this.ping_interval); } }, disconnect: function() { oAvalonRPC.terminateSession(); if (this.server_config.urls.disconnect) document.location.href = this.server_config.urls.disconnect; else document.location.pathname = "/"; }, panic: function() { if (this.server_config.urls.error) document.location.href = this.server_config.urls.error; else document.location.pathname = "/"; }, serverPing: function() { return ('ping' == oAvalonRPC.test('ping')); }, serverKeepAlive: function() { var do_ping = ((new Date()).getTime() - this.last_activity) < this.server_config.session_timeout * 1000; if (do_ping) this.serverPing(); else this.disconnect(); } }; Avalon.Ajax.Overlay = Class.create(); Avalon.Ajax.Overlay.prototype = { overlay: false, initialize: function(element) { var options = Object.extend({ onclickRemove: false, overlay: 'loading', pageRelative: false }, arguments[1] || {}) element = $(element); var overlay_container = $("__avalon_ajax_overlay_" + options.overlay); if (!overlay_container) { overlay_container = document.createElement('table'); var tbody = document.createElement('tbody'); var tr = document.createElement('tr'); var td = document.createElement('td'); tr.appendChild(td); tbody.appendChild(tr); overlay_container.appendChild(tbody); overlay_container.id = '__avalon_ajax_overlay_' + options.overlay; Element.hide(overlay_container); Element.addClassName(overlay_container, 'ajax-loading'); if (options.overlay != 'plain') Element.update( td, oAvalonRPC.remoteRender('controls/overlays/' + options.overlay) ); document.body.appendChild(overlay_container); } if (element.__avalon_overlay && element.__avalon_overlay[options.overlay]) this.overlay = element.__avalon_overlay[options.overlay]; else { this.overlay = overlay_container.cloneNode(true); this.overlay.id = null; document.body.appendChild(this.overlay); if (!element['__avalon_overlay']) element['__avalon_overlay'] = {}; element['__avalon_overlay'][options.overlay] = this.overlay; } if (options.onclickRemove) this.overlay.onclick = this.remove.bind(this); else this.overlay.onclick = null; Position.clone(element, this.overlay); }, show: function() { this.overlay.show(); }, remove: function() { this.overlay.hide(); } } Object.extend(Avalon.Ajax.Overlay, { removeFrom: function(element) { if (arguments.length == 1) $H(($(element)['__avalon_overlay'])).each( function(pair){pair.value.hide();} ); else if ($(element)['__avalon_overlay'][arguments[1]]) $(element)['__avalon_overlay'][arguments[1]].hide(); } }); Avalon.Ajax.Renderer = { bindUpdater: function(element, block, params) { var __method = this.updateElement, __args = $A(arguments); if (!arguments[3]) __args.push({}); return function() { return __method.apply(this, __args.concat($A(arguments))); } }, updateElement: function(element, block, params) { var options = Object.extend({ overlay: 'loading', oncomplete: false, waitfor: false, globalOverlay: false }, arguments[3] || {}); if (options.overlay) { var overlay = new Avalon.Ajax.Overlay( options.globalOverlay ? document.body : element, {"overlay":options.overlay}); } var updater = function(transport, result) { if (result) Element.update(element, result); if (options.overlay) overlay.remove(); if (options.oncomplete) options.oncomplete(); } var responder = function(transport, result) { oAvalonRPC.remoteRender_async( updater, block, params ); } if (options.overlay) { overlay.show(); } if (options.waitfor) { options.waitfor(responder); } else { responder(null, null); } } } Avalon.Ajax.MessageBox = Class.create(); Avalon.Ajax.MessageBox.prototype = { box: false, overlay: false, initialize: function(message, title, buttons) { var container = $("__avalon_ajax_msgbox"); if (!container) { container = document.createElement('div'); var content = document.createElement('div'); var button_container = document.createElement('div'); var title_container = document.createElement('div'); container.id = '__avalon_ajax_msgbox'; container.appendChild(title_container); container.appendChild(content); container.appendChild(button_container); Element.hide(container); Element.addClassName(container, 'message-box'); Element.addClassName(content, 'message-box-content'); Element.addClassName(button_container, 'message-box-buttons'); Element.addClassName(title_container, 'message-box-title'); document.body.appendChild(container); } this.box = container.cloneNode(true); this.box.id = ''; var title_container = this.box.firstChild; var text_container = title_container.nextSibling; var buttons_container = text_container.nextSibling; title_container.appendChild(document.createTextNode(title)); text_container.innerHTML = message; document.body.appendChild(this.box); this.overlay = new Avalon.Ajax.Overlay( document.body, {'overlay':'plain'}); var b_size = Element.getDimensions(this.box); var w_size = Position.pageSize(); var w_scroll = Position.pageScroll(); var top = ((w_size.windowHeight - b_size.height) + ($B('msie < 7') ? w_scroll[1] * 2 : 0)) / 2; this.box.style.top = ((top > 0) ? top : 0) + 'px'; var left = (w_size.windowWidth - b_size.width) / 2; this.box.style.left = ((left > 0) ? left : 0) + 'px'; this.box.style.position = $B('msie < 7') ? 'absolute' : 'fixed'; var box = this; var callbacks = (arguments[3] || {}); $A(buttons).each( function(element) { var button = document.createElement('img'); var button_name = element.toLowerCase().replace(' ', '_'); button.src = $('avalon_ajax_messagebox_button_' + button_name).value; button.alt = button_name; buttons_container.appendChild(button); var callback = (callbacks[element] || box['on_' + button_name] || Prototype.emptyFunction ).bind(box, box, element); var destructor = box.destroy.bind(box); button.onclick = function() { callback(); destructor(); }; }); if ($B('msie')) $A(document.getElementsByTagName('select')).each( function(element){Element.toggle(element)}); this.overlay.show(); this.box.show(); }, destroy: function() { this.overlay.remove(); if ($B('msie')) $A(document.getElementsByTagName('select')).each( function(element){Element.toggle(element)}); this.box.remove(); }, onButton: function(button) { this.destroy(); } } Avalon.Ajax.Image = { load: function(imageurl) { var overlay = new Avalon.Ajax.Overlay( document.body, {onclickRemove: true, overlay: 'image'}); var div = document.getElementsByClassName('ajax-image-outer', overlay.overlay)[0]; var divInner = document.getElementsByClassName('ajax-image-inner', overlay.overlay)[0]; var img = document.getElementsByClassName('ajax-image', overlay.overlay)[0]; div.style.top = Position.pageScroll()[1] + 20 + 'px'; overlay.show(); preloaded = new Image(); preloaded.onload = function() { var width = preloaded.width + 20; if (width < 200) { width = 200; } divInner.style.width = width + 'px'; var height = preloaded.height + 60; if (height < 200) { height = 200; } divInner.style.height = height + 'px'; img.src = imageurl; } preloaded.src = imageurl; } }; Avalon.Ajax.Exception = { handler: function(object, exception) { if (exception instanceof Ajax.ServerException) { var etype = /\[(\w+)\](.*)/.exec(exception.toString()); if (etype) { if (this.handle(etype[1], etype[2])) return true; } } if (Avalon.Ajax.server_config.enable_debug) alert(exception.toString()); else Avalon.Ajax.panic(); }, addHandler: function(etype, handler) { if (this.handlers[etype] && !this.handlers[etype].include(handler)) this.handlers[etype].push(handler); else this.handlers[etype] = [handler]; }, removeHandler: function(etype, handler) { if (this.handlers[etype]) this.handlers[etype] = this.handlers[etype].without(handler); }, handle: function(etype, message) { if (this.handlers[etype]) { this.handlers[etype].each(function(e){e();}); return true; } else { return false; } }, handlers: {} } Avalon.Ajax.TransportFailure = { handler: function(request, transport, result) { this.failures.push({'request':request, 'transport':transport}); if (!this.message_active) { this.message_active = true; var failures = this.failures.clone(); this.failures.clear(); new Avalon.Ajax.MessageBox( 'There has been a problem communicating with the server.', 'SecureFood', ['Try Again', 'Cancel'], {'Try Again': this.retry.bind(this, failures), 'Cancel': this.hide.bind(this)} ); } }, retry: function(failures) { failures.each(function(failure){failure.request.send();}); this.message_active = false; }, hide: function() { this.message_active = false; }, message_active: false, failures: $A([]) } Ajax.Responders.register({ onException: Avalon.Ajax.Exception.handler.bind( Avalon.Ajax.Exception), onFailure: Avalon.Ajax.TransportFailure.handler.bind( Avalon.Ajax.TransportFailure) }); Function.prototype.bindAsRPCMethod = function() { var __method = this, args = $A(arguments), object = args.shift(); return function(callback) { return __method.apply(object, $A([callback]).concat(args)); } } Array.prototype.clone = function() { var arr = $A([]); this.each(function(elem){arr.push(elem)}); return arr; } Object.extend(Element, { append: function(element, html) { $(element).innerHTML += html.stripScripts(); setTimeout(function() {html.evalScripts()}, 10); } });