From 9caf635dfc82ce4ef10f482a8208ccd4a7d39374 Mon Sep 17 00:00:00 2001 From: Viktor Klang Date: Tue, 13 Oct 2009 22:22:38 +0200 Subject: [PATCH] Added webroot --- config/jndi.properties | 1 + deploy/root/images/body-background.png | Bin 0 -> 2381 bytes deploy/root/images/header-background.png | Bin 0 -> 20847 bytes deploy/root/images/main-background.png | Bin 0 -> 8026 bytes deploy/root/index.html | 45 + deploy/root/javascripts/application.js | 90 ++ deploy/root/javascripts/behaviour.js | 254 +++ deploy/root/javascripts/moo.fx.js | 136 ++ deploy/root/javascripts/moo.fx.pack.js | 83 + deploy/root/javascripts/prototype.js | 1781 ++++++++++++++++++++++ deploy/root/stylesheets/default.css | 54 + 11 files changed, 2444 insertions(+) create mode 100644 config/jndi.properties create mode 100644 deploy/root/images/body-background.png create mode 100644 deploy/root/images/header-background.png create mode 100644 deploy/root/images/main-background.png create mode 100644 deploy/root/index.html create mode 100644 deploy/root/javascripts/application.js create mode 100644 deploy/root/javascripts/behaviour.js create mode 100644 deploy/root/javascripts/moo.fx.js create mode 100644 deploy/root/javascripts/moo.fx.pack.js create mode 100644 deploy/root/javascripts/prototype.js create mode 100644 deploy/root/stylesheets/default.css diff --git a/config/jndi.properties b/config/jndi.properties new file mode 100644 index 0000000000..c4151420d6 --- /dev/null +++ b/config/jndi.properties @@ -0,0 +1 @@ +java.naming.factory.initial=com.sun.jndi.fscontext.RefFSContextFactory \ No newline at end of file diff --git a/deploy/root/images/body-background.png b/deploy/root/images/body-background.png new file mode 100644 index 0000000000000000000000000000000000000000..ece11eb20ac9dea8dbda6dfebbc134c78fd3b096 GIT binary patch literal 2381 zcmeAS@N?(olHy`uVBq!ia0y~yVBlh4U{>H@VqjpH+MlA%z`(#+;1OBOz`!jG!i)^F z=14FwaQydlaSW-r^)~wUrpFc>E+YT`AD=ysJ+foZ#@b<6FXn9iab`g;Wx{8u+fS4vxC8XzVC{AoxYd|Uc4~zW%JGN9p}}*9o~}v zY0gB0aEtKRah$i;&%D#*t(4KKlilHdLAw7{^!e_|JSXwA11cVclfs2Ct{re z|Bw9i{$nKJ{%(k$N zy!#^F8&sXlOR-%Labf3^Y)5JLW4BZ@j{ki#=^xj-Z^yq#Iqq+Mv?jG<(x+=xZQ9~@ z{MCCWCs|K!N}E^r^1-E_l?5rRhL&#_1(w`xSW>+vTAw-Qo^po71)UffHc{mh@Bhc# zFa4V?t@UYYzcMq2;!%h5yOeet%YQqN?)XV$fw7Es9@7NNXAcXDj~F~xK6=k3(Mirf z_WjP;Zzb>CIJfZEgg8ZoGYXmEQP)El7B%vEuz0iGsM=u~QN*xlVgmnx30qFRduUwn z^3r9VkfUms7Jf)u-xMU;9eDEhkMf0<-R1j|&awq_`gT2E zp(fk)T(T>E!=9yGE*uXQa?3citIW6-Ei8ECv&~YQ^B=e`Y?0d#7qDIsIQ~$3M->e@@)lIb}~ny5{_?GT*rL z9#4+G;Jjwii+}$bcoW2ShkRN0RQCz%lPN1Z{xKfZxtx>!Y;g`>{&N}Ab!Rt-JPLMX zTkWab*YQ|zO7g5{ldUWbo*WGhRx)#P3%w9{xi<@bnAp$u6MyjOy_;KSIWJ^0FuJnh>y zbn0Qf17SX!+V(jb3oow8H_3W)E5YK?taZC&dzSpRvRpI8#Yg0f(S*tO`5Zq<-a4Ic zqdR@CkIqe>3syGnO+CxzBz0#WlZHlRt4sX=d0}Mc2%(?hpKRqiXiHgHd4$nkgoarb{SxvQ-{z>!{dwamyj2 zzsuJoOidH5T{KPllO*dp%jaPVO;ct0Z(ED9F$qreOD^N74$w95=)8LGys$!IphM>B zaP7W@&aY=wgzTH9ZhY<8ri6uCcRuJ)v^b$yp*;B@!~G(S>CmG5#w%Hmv$QY3H=3^>-Yv9bYihGmd9t z*9At~qpNzOEN(LWv=HM968UmhLdN_-!M#({rqBLazpuqO;-+zEUcxDk{A;tF4bSyO zzji78e#&6Svl8J@#l_0)v48YuaqS6sR9U=N{no5R_KDup@`|2%Y&hHeQsIro z6JO2t7ak3m7g>yk5=jsefnx zrfJfr7T;+-9&b8v%7$G}X9&r~^>f{Q;Snw5$jWnhzOCR^(b=JHPJzj%&NS~jCll4n zve4j_gYn(#-b%~1i6(Q-itV{@{HlR(Z|_3~lVx@@xu=OYJ3QDda)kHUL67>U*%3)W zUy4i`wXX7>I&sfSDeaqgr}UMpI!P1G_-p4s9FpZCO<*tnBWB`LxYWtUEtt)<&lERj1NruXg*gE_MF%bWZe7i}h=sL>-(y^XPIH6A}Ga@4}v+ zNG;#4CVnTVoTVtBv}s@Tdl`whjO{}1783%l@}JJH%n~@?lQcxBaoYdduo3EV-(`aL3)$B9kP`CoZjVsPIV?OxA@oZlW3ubNyqX*xfO z{r#=W{IN=&U&`x7b-a`ofY8oWZH z#xm!moO;HWYm2;9xH&HAJm0YS8r$k9!O&fGS^2+zNA7->y^nPCZ{|<_<()3l>{EAp RGB7YOc)I$ztaD0e0sw=8iI@NY literal 0 HcmV?d00001 diff --git a/deploy/root/images/header-background.png b/deploy/root/images/header-background.png new file mode 100644 index 0000000000000000000000000000000000000000..93e4a49c3795da40ddee63af280a4a0fadffbb45 GIT binary patch literal 20847 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 Q0|Nttr>mdKI;Vst0K + + + + + Atmosphere Scala REST Chat + + + + + + + + +
+
+ +
+
+
+
+
Please input your name:
+
+ +
+ +
+ +
+
+
+
+ + + diff --git a/deploy/root/javascripts/application.js b/deploy/root/javascripts/application.js new file mode 100644 index 0000000000..f8361babea --- /dev/null +++ b/deploy/root/javascripts/application.js @@ -0,0 +1,90 @@ +var count = 0; +var app = { + url: '/chat', + initialize: function() { + $('login-name').focus(); + app.listen(); + }, + listen: function() { + $('comet-frame').src = app.url + '?' + count; + count ++; + }, + login: function() { + var name = $F('login-name'); + if(! name.length > 0) { + $('system-message').style.color = 'red'; + $('login-name').focus(); + return; + } + $('system-message').style.color = '#2d2b3d'; + $('system-message').innerHTML = name + ':'; + + $('login-button').disabled = true; + $('login-form').style.display = 'none'; + $('message-form').style.display = ''; + + var query = + 'action=login' + + '&name=' + encodeURI($F('login-name')); + new Ajax.Request(app.url, { + postBody: query, + onSuccess: function() { + $('message').focus(); + } + }); + }, + post: function() { + var message = $F('message'); + if(!message > 0) { + return; + } + $('message').disabled = true; + $('post-button').disabled = true; + + var query = + 'action=post' + + '&name=' + encodeURI($F('login-name')) + + '&message=' + encodeURI(message); + new Ajax.Request(app.url, { + postBody: query, + onComplete: function() { + $('message').disabled = false; + $('post-button').disabled = false; + $('message').focus(); + $('message').value = ''; + } + }); + }, + update: function(data) { + var p = document.createElement('p'); + p.innerHTML = data.name + ':
' + data.message; + + $('display').appendChild(p); + + new Fx.Scroll('display').down(); + } +}; +var rules = { + '#login-name': function(elem) { + Event.observe(elem, 'keydown', function(e) { + if(e.keyCode == 13) { + $('login-button').focus(); + } + }); + }, + '#login-button': function(elem) { + elem.onclick = app.login; + }, + '#message': function(elem) { + Event.observe(elem, 'keydown', function(e) { + if(e.shiftKey && e.keyCode == 13) { + $('post-button').focus(); + } + }); + }, + '#post-button': function(elem) { + elem.onclick = app.post; + } +}; +Behaviour.addLoadEvent(app.initialize); +Behaviour.register(rules); diff --git a/deploy/root/javascripts/behaviour.js b/deploy/root/javascripts/behaviour.js new file mode 100644 index 0000000000..fdde861bba --- /dev/null +++ b/deploy/root/javascripts/behaviour.js @@ -0,0 +1,254 @@ +/* + Behaviour v1.1 by Ben Nolan, June 2005. Based largely on the work + of Simon Willison (see comments by Simon below). + + Description: + + Uses css selectors to apply javascript behaviours to enable + unobtrusive javascript in html documents. + + Usage: + + var myrules = { + 'b.someclass' : function(element){ + element.onclick = function(){ + alert(this.innerHTML); + } + }, + '#someid u' : function(element){ + element.onmouseover = function(){ + this.innerHTML = "BLAH!"; + } + } + }; + + Behaviour.register(myrules); + + // Call Behaviour.apply() to re-apply the rules (if you + // update the dom, etc). + + License: + + This file is entirely BSD licensed. + + More information: + + http://ripcord.co.nz/behaviour/ + +*/ + +var Behaviour = { + list : new Array, + + register : function(sheet){ + Behaviour.list.push(sheet); + }, + + start : function(){ + Behaviour.addLoadEvent(function(){ + Behaviour.apply(); + }); + }, + + apply : function(){ + for (h=0;sheet=Behaviour.list[h];h++){ + for (selector in sheet){ + list = document.getElementsBySelector(selector); + + if (!list){ + continue; + } + + for (i=0;element=list[i];i++){ + sheet[selector](element); + } + } + } + }, + + addLoadEvent : function(func){ + var oldonload = window.onload; + + if (typeof window.onload != 'function') { + window.onload = func; + } else { + window.onload = function() { + oldonload(); + func(); + } + } + } +} + +Behaviour.start(); + +/* + The following code is Copyright (C) Simon Willison 2004. + + document.getElementsBySelector(selector) + - returns an array of element objects from the current document + matching the CSS selector. Selectors can contain element names, + class names and ids and can be nested. For example: + + elements = document.getElementsBySelect('div#main p a.external') + + Will return an array of all 'a' elements with 'external' in their + class attribute that are contained inside 'p' elements that are + contained inside the 'div' element which has id="main" + + New in version 0.4: Support for CSS2 and CSS3 attribute selectors: + See http://www.w3.org/TR/css3-selectors/#attribute-selectors + + Version 0.4 - Simon Willison, March 25th 2003 + -- Works in Phoenix 0.5, Mozilla 1.3, Opera 7, Internet Explorer 6, Internet Explorer 5 on Windows + -- Opera 7 fails +*/ + +function getAllChildren(e) { + // Returns all children of element. Workaround required for IE5/Windows. Ugh. + return e.all ? e.all : e.getElementsByTagName('*'); +} + +document.getElementsBySelector = function(selector) { + // Attempt to fail gracefully in lesser browsers + if (!document.getElementsByTagName) { + return new Array(); + } + // Split selector in to tokens + var tokens = selector.split(' '); + var currentContext = new Array(document); + for (var i = 0; i < tokens.length; i++) { + token = tokens[i].replace(/^\s+/,'').replace(/\s+$/,'');; + if (token.indexOf('#') > -1) { + // Token is an ID selector + var bits = token.split('#'); + var tagName = bits[0]; + var id = bits[1]; + var element = document.getElementById(id); + if (tagName && element.nodeName.toLowerCase() != tagName) { + // tag with that ID not found, return false + return new Array(); + } + // Set currentContext to contain just this element + currentContext = new Array(element); + continue; // Skip to next token + } + if (token.indexOf('.') > -1) { + // Token contains a class selector + var bits = token.split('.'); + var tagName = bits[0]; + var className = bits[1]; + if (!tagName) { + tagName = '*'; + } + // Get elements matching tag, filter them for class selector + var found = new Array; + var foundCount = 0; + for (var h = 0; h < currentContext.length; h++) { + var elements; + if (tagName == '*') { + elements = getAllChildren(currentContext[h]); + } else { + elements = currentContext[h].getElementsByTagName(tagName); + } + for (var j = 0; j < elements.length; j++) { + found[foundCount++] = elements[j]; + } + } + currentContext = new Array; + var currentContextIndex = 0; + for (var k = 0; k < found.length; k++) { + if (found[k].className && found[k].className.match(new RegExp('\\b'+className+'\\b'))) { + currentContext[currentContextIndex++] = found[k]; + } + } + continue; // Skip to next token + } + // Code to deal with attribute selectors + if (token.match(/^(\w*)\[(\w+)([=~\|\^\$\*]?)=?"?([^\]"]*)"?\]$/)) { + var tagName = RegExp.$1; + var attrName = RegExp.$2; + var attrOperator = RegExp.$3; + var attrValue = RegExp.$4; + if (!tagName) { + tagName = '*'; + } + // Grab all of the tagName elements within current context + var found = new Array; + var foundCount = 0; + for (var h = 0; h < currentContext.length; h++) { + var elements; + if (tagName == '*') { + elements = getAllChildren(currentContext[h]); + } else { + elements = currentContext[h].getElementsByTagName(tagName); + } + for (var j = 0; j < elements.length; j++) { + found[foundCount++] = elements[j]; + } + } + currentContext = new Array; + var currentContextIndex = 0; + var checkFunction; // This function will be used to filter the elements + switch (attrOperator) { + case '=': // Equality + checkFunction = function(e) { return (e.getAttribute(attrName) == attrValue); }; + break; + case '~': // Match one of space seperated words + checkFunction = function(e) { return (e.getAttribute(attrName).match(new RegExp('\\b'+attrValue+'\\b'))); }; + break; + case '|': // Match start with value followed by optional hyphen + checkFunction = function(e) { return (e.getAttribute(attrName).match(new RegExp('^'+attrValue+'-?'))); }; + break; + case '^': // Match starts with value + checkFunction = function(e) { return (e.getAttribute(attrName).indexOf(attrValue) == 0); }; + break; + case '$': // Match ends with value - fails with "Warning" in Opera 7 + checkFunction = function(e) { return (e.getAttribute(attrName).lastIndexOf(attrValue) == e.getAttribute(attrName).length - attrValue.length); }; + break; + case '*': // Match ends with value + checkFunction = function(e) { return (e.getAttribute(attrName).indexOf(attrValue) > -1); }; + break; + default : + // Just test for existence of attribute + checkFunction = function(e) { return e.getAttribute(attrName); }; + } + currentContext = new Array; + var currentContextIndex = 0; + for (var k = 0; k < found.length; k++) { + if (checkFunction(found[k])) { + currentContext[currentContextIndex++] = found[k]; + } + } + // alert('Attribute Selector: '+tagName+' '+attrName+' '+attrOperator+' '+attrValue); + continue; // Skip to next token + } + + if (!currentContext[0]){ + return; + } + + // If we get here, token is JUST an element (not a class or ID selector) + tagName = token; + var found = new Array; + var foundCount = 0; + for (var h = 0; h < currentContext.length; h++) { + var elements = currentContext[h].getElementsByTagName(tagName); + for (var j = 0; j < elements.length; j++) { + found[foundCount++] = elements[j]; + } + } + currentContext = found; + } + return currentContext; +} + +/* That revolting regular expression explained +/^(\w+)\[(\w+)([=~\|\^\$\*]?)=?"?([^\]"]*)"?\]$/ + \---/ \---/\-------------/ \-------/ + | | | | + | | | The value + | | ~,|,^,$,* or = + | Attribute + Tag +*/ diff --git a/deploy/root/javascripts/moo.fx.js b/deploy/root/javascripts/moo.fx.js new file mode 100644 index 0000000000..95c01f819a --- /dev/null +++ b/deploy/root/javascripts/moo.fx.js @@ -0,0 +1,136 @@ +//(c) 2006 Valerio Proietti (http://mad4milk.net). MIT-style license. +//moo.fx.js - depends on prototype.js OR prototype.lite.js +//version 2.0 + +var Fx = fx = {}; + +Fx.Base = function(){}; +Fx.Base.prototype = { + + setOptions: function(options){ + this.options = Object.extend({ + onStart: function(){}, + onComplete: function(){}, + transition: Fx.Transitions.sineInOut, + duration: 500, + unit: 'px', + wait: true, + fps: 50 + }, options || {}); + }, + + step: function(){ + var time = new Date().getTime(); + if (time < this.time + this.options.duration){ + this.cTime = time - this.time; + this.setNow(); + } else { + setTimeout(this.options.onComplete.bind(this, this.element), 10); + this.clearTimer(); + this.now = this.to; + } + this.increase(); + }, + + setNow: function(){ + this.now = this.compute(this.from, this.to); + }, + + compute: function(from, to){ + var change = to - from; + return this.options.transition(this.cTime, from, change, this.options.duration); + }, + + clearTimer: function(){ + clearInterval(this.timer); + this.timer = null; + return this; + }, + + _start: function(from, to){ + if (!this.options.wait) this.clearTimer(); + if (this.timer) return; + setTimeout(this.options.onStart.bind(this, this.element), 10); + this.from = from; + this.to = to; + this.time = new Date().getTime(); + this.timer = setInterval(this.step.bind(this), Math.round(1000/this.options.fps)); + return this; + }, + + custom: function(from, to){ + return this._start(from, to); + }, + + set: function(to){ + this.now = to; + this.increase(); + return this; + }, + + hide: function(){ + return this.set(0); + }, + + setStyle: function(e, p, v){ + if (p == 'opacity'){ + if (v == 0 && e.style.visibility != "hidden") e.style.visibility = "hidden"; + else if (e.style.visibility != "visible") e.style.visibility = "visible"; + if (window.ActiveXObject) e.style.filter = "alpha(opacity=" + v*100 + ")"; + e.style.opacity = v; + } else e.style[p] = v+this.options.unit; + } + +}; + +Fx.Style = Class.create(); +Fx.Style.prototype = Object.extend(new Fx.Base(), { + + initialize: function(el, property, options){ + this.element = $(el); + this.setOptions(options); + this.property = property.camelize(); + }, + + increase: function(){ + this.setStyle(this.element, this.property, this.now); + } + +}); + +Fx.Styles = Class.create(); +Fx.Styles.prototype = Object.extend(new Fx.Base(), { + + initialize: function(el, options){ + this.element = $(el); + this.setOptions(options); + this.now = {}; + }, + + setNow: function(){ + for (p in this.from) this.now[p] = this.compute(this.from[p], this.to[p]); + }, + + custom: function(obj){ + if (this.timer && this.options.wait) return; + var from = {}; + var to = {}; + for (p in obj){ + from[p] = obj[p][0]; + to[p] = obj[p][1]; + } + return this._start(from, to); + }, + + increase: function(){ + for (var p in this.now) this.setStyle(this.element, p, this.now[p]); + } + +}); + +//Transitions (c) 2003 Robert Penner (http://www.robertpenner.com/easing/), BSD License. + +Fx.Transitions = { + linear: function(t, b, c, d) { return c*t/d + b; }, + sineInOut: function(t, b, c, d) { return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b; } +}; \ No newline at end of file diff --git a/deploy/root/javascripts/moo.fx.pack.js b/deploy/root/javascripts/moo.fx.pack.js new file mode 100644 index 0000000000..a06656fb44 --- /dev/null +++ b/deploy/root/javascripts/moo.fx.pack.js @@ -0,0 +1,83 @@ +//by Valerio Proietti (http://mad4milk.net). MIT-style license. +//moo.fx.pack.js - depends on prototype.js or prototype.lite.js + moo.fx.js +//version 2.0 + +Fx.Scroll = Class.create(); +Fx.Scroll.prototype = Object.extend(new Fx.Base(), { + + initialize: function(el, options) { + this.element = $(el); + this.setOptions(options); + this.element.style.overflow = 'hidden'; + }, + + down: function(){ + return this.custom(this.element.scrollTop, this.element.scrollHeight-this.element.offsetHeight); + }, + + up: function(){ + return this.custom(this.element.scrollTop, 0); + }, + + increase: function(){ + this.element.scrollTop = this.now; + } + +}); + +//fx.Color, originally by Tom Jensen (http://neuemusic.com) MIT-style LICENSE. + +Fx.Color = Class.create(); +Fx.Color.prototype = Object.extend(new Fx.Base(), { + + initialize: function(el, property, options){ + this.element = $(el); + this.setOptions(options); + this.property = property.camelize(); + this.now = []; + }, + + custom: function(from, to){ + return this._start(from.hexToRgb(true), to.hexToRgb(true)); + }, + + setNow: function(){ + [0,1,2].each(function(i){ + this.now[i] = Math.round(this.compute(this.from[i], this.to[i])); + }.bind(this)); + }, + + increase: function(){ + this.element.style[this.property] = "rgb("+this.now[0]+","+this.now[1]+","+this.now[2]+")"; + } + +}); + +Object.extend(String.prototype, { + + rgbToHex: function(array){ + var rgb = this.match(new RegExp('([\\d]{1,3})', 'g')); + if (rgb[3] == 0) return 'transparent'; + var hex = []; + for (var i = 0; i < 3; i++){ + var bit = (rgb[i]-0).toString(16); + hex.push(bit.length == 1 ? '0'+bit : bit); + } + var hexText = '#'+hex.join(''); + if (array) return hex; + else return hexText; + }, + + hexToRgb: function(array){ + var hex = this.match(new RegExp('^[#]{0,1}([\\w]{1,2})([\\w]{1,2})([\\w]{1,2})$')); + var rgb = []; + for (var i = 1; i < hex.length; i++){ + if (hex[i].length == 1) hex[i] += hex[i]; + rgb.push(parseInt(hex[i], 16)); + } + var rgbText = 'rgb('+rgb.join(',')+')'; + if (array) return rgb; + else return rgbText; + } + +}); \ No newline at end of file diff --git a/deploy/root/javascripts/prototype.js b/deploy/root/javascripts/prototype.js new file mode 100644 index 0000000000..0e85338bab --- /dev/null +++ b/deploy/root/javascripts/prototype.js @@ -0,0 +1,1781 @@ +/* Prototype JavaScript framework, version 1.4.0 + * (c) 2005 Sam Stephenson + * + * Prototype is freely distributable under the terms of an MIT-style license. + * For details, see the Prototype web site: http://prototype.conio.net/ + * +/*--------------------------------------------------------------------------*/ + +var Prototype = { + Version: '1.4.0', + ScriptFragment: '(?:)((\n|\r|.)*?)(?:<\/script>)', + + emptyFunction: function() {}, + K: function(x) {return x} +} + +var Class = { + create: function() { + return function() { + this.initialize.apply(this, arguments); + } + } +} + +var Abstract = new Object(); + +Object.extend = function(destination, source) { + for (property in source) { + destination[property] = source[property]; + } + return destination; +} + +Object.inspect = function(object) { + try { + if (object == undefined) return 'undefined'; + if (object == null) return 'null'; + return object.inspect ? object.inspect() : object.toString(); + } catch (e) { + if (e instanceof RangeError) return '...'; + throw e; + } +} + +Function.prototype.bind = function() { + var __method = this, args = $A(arguments), object = args.shift(); + return function() { + return __method.apply(object, args.concat($A(arguments))); + } +} + +Function.prototype.bindAsEventListener = function(object) { + var __method = this; + return function(event) { + return __method.call(object, event || window.event); + } +} + +Object.extend(Number.prototype, { + toColorPart: function() { + var digits = this.toString(16); + if (this < 16) return '0' + digits; + return digits; + }, + + succ: function() { + return this + 1; + }, + + times: function(iterator) { + $R(0, this, true).each(iterator); + return this; + } +}); + +var Try = { + these: function() { + var returnValue; + + for (var i = 0; i < arguments.length; i++) { + var lambda = arguments[i]; + try { + returnValue = lambda(); + break; + } catch (e) {} + } + + return returnValue; + } +} + +/*--------------------------------------------------------------------------*/ + +var PeriodicalExecuter = Class.create(); +PeriodicalExecuter.prototype = { + initialize: function(callback, frequency) { + this.callback = callback; + this.frequency = frequency; + this.currentlyExecuting = false; + + this.registerCallback(); + }, + + registerCallback: function() { + setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); + }, + + onTimerEvent: function() { + if (!this.currentlyExecuting) { + try { + this.currentlyExecuting = true; + this.callback(); + } finally { + this.currentlyExecuting = false; + } + } + } +} + +/*--------------------------------------------------------------------------*/ + +function $() { + var elements = new Array(); + + for (var i = 0; i < arguments.length; i++) { + var element = arguments[i]; + if (typeof element == 'string') + element = document.getElementById(element); + + if (arguments.length == 1) + return element; + + elements.push(element); + } + + return elements; +} +Object.extend(String.prototype, { + stripTags: function() { + return this.replace(/<\/?[^>]+>/gi, ''); + }, + + stripScripts: function() { + return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), ''); + }, + + extractScripts: function() { + var matchAll = new RegExp(Prototype.ScriptFragment, 'img'); + var matchOne = new RegExp(Prototype.ScriptFragment, 'im'); + return (this.match(matchAll) || []).map(function(scriptTag) { + return (scriptTag.match(matchOne) || ['', ''])[1]; + }); + }, + + evalScripts: function() { + return this.extractScripts().map(eval); + }, + + escapeHTML: function() { + var div = document.createElement('div'); + var text = document.createTextNode(this); + div.appendChild(text); + return div.innerHTML; + }, + + unescapeHTML: function() { + var div = document.createElement('div'); + div.innerHTML = this.stripTags(); + return div.childNodes[0] ? div.childNodes[0].nodeValue : ''; + }, + + toQueryParams: function() { + var pairs = this.match(/^\??(.*)$/)[1].split('&'); + return pairs.inject({}, function(params, pairString) { + var pair = pairString.split('='); + params[pair[0]] = pair[1]; + return params; + }); + }, + + toArray: function() { + return this.split(''); + }, + + camelize: function() { + var oStringList = this.split('-'); + if (oStringList.length == 1) return oStringList[0]; + + var camelizedString = this.indexOf('-') == 0 + ? oStringList[0].charAt(0).toUpperCase() + oStringList[0].substring(1) + : oStringList[0]; + + for (var i = 1, len = oStringList.length; i < len; i++) { + var s = oStringList[i]; + camelizedString += s.charAt(0).toUpperCase() + s.substring(1); + } + + return camelizedString; + }, + + inspect: function() { + return "'" + this.replace('\\', '\\\\').replace("'", '\\\'') + "'"; + } +}); + +String.prototype.parseQuery = String.prototype.toQueryParams; + +var $break = new Object(); +var $continue = new Object(); + +var Enumerable = { + each: function(iterator) { + var index = 0; + try { + this._each(function(value) { + try { + iterator(value, index++); + } catch (e) { + if (e != $continue) throw e; + } + }); + } catch (e) { + if (e != $break) throw e; + } + }, + + all: function(iterator) { + var result = true; + this.each(function(value, index) { + result = result && !!(iterator || Prototype.K)(value, index); + if (!result) throw $break; + }); + return result; + }, + + any: function(iterator) { + var result = true; + this.each(function(value, index) { + if (result = !!(iterator || Prototype.K)(value, index)) + throw $break; + }); + return result; + }, + + collect: function(iterator) { + var results = []; + this.each(function(value, index) { + results.push(iterator(value, index)); + }); + return results; + }, + + detect: function (iterator) { + var result; + this.each(function(value, index) { + if (iterator(value, index)) { + result = value; + throw $break; + } + }); + return result; + }, + + findAll: function(iterator) { + var results = []; + this.each(function(value, index) { + if (iterator(value, index)) + results.push(value); + }); + return results; + }, + + grep: function(pattern, iterator) { + var results = []; + this.each(function(value, index) { + var stringValue = value.toString(); + if (stringValue.match(pattern)) + results.push((iterator || Prototype.K)(value, index)); + }) + return results; + }, + + include: function(object) { + var found = false; + this.each(function(value) { + if (value == object) { + found = true; + throw $break; + } + }); + return found; + }, + + inject: function(memo, iterator) { + this.each(function(value, index) { + memo = iterator(memo, value, index); + }); + return memo; + }, + + invoke: function(method) { + var args = $A(arguments).slice(1); + return this.collect(function(value) { + return value[method].apply(value, args); + }); + }, + + max: function(iterator) { + var result; + this.each(function(value, index) { + value = (iterator || Prototype.K)(value, index); + if (value >= (result || value)) + result = value; + }); + return result; + }, + + min: function(iterator) { + var result; + this.each(function(value, index) { + value = (iterator || Prototype.K)(value, index); + if (value <= (result || value)) + result = value; + }); + return result; + }, + + partition: function(iterator) { + var trues = [], falses = []; + this.each(function(value, index) { + ((iterator || Prototype.K)(value, index) ? + trues : falses).push(value); + }); + return [trues, falses]; + }, + + pluck: function(property) { + var results = []; + this.each(function(value, index) { + results.push(value[property]); + }); + return results; + }, + + reject: function(iterator) { + var results = []; + this.each(function(value, index) { + if (!iterator(value, index)) + results.push(value); + }); + return results; + }, + + sortBy: function(iterator) { + return this.collect(function(value, index) { + return {value: value, criteria: iterator(value, index)}; + }).sort(function(left, right) { + var a = left.criteria, b = right.criteria; + return a < b ? -1 : a > b ? 1 : 0; + }).pluck('value'); + }, + + toArray: function() { + return this.collect(Prototype.K); + }, + + zip: function() { + var iterator = Prototype.K, args = $A(arguments); + if (typeof args.last() == 'function') + iterator = args.pop(); + + var collections = [this].concat(args).map($A); + return this.map(function(value, index) { + iterator(value = collections.pluck(index)); + return value; + }); + }, + + inspect: function() { + return '#'; + } +} + +Object.extend(Enumerable, { + map: Enumerable.collect, + find: Enumerable.detect, + select: Enumerable.findAll, + member: Enumerable.include, + entries: Enumerable.toArray +}); +var $A = Array.from = function(iterable) { + if (!iterable) return []; + if (iterable.toArray) { + return iterable.toArray(); + } else { + var results = []; + for (var i = 0; i < iterable.length; i++) + results.push(iterable[i]); + return results; + } +} + +Object.extend(Array.prototype, Enumerable); + +Array.prototype._reverse = Array.prototype.reverse; + +Object.extend(Array.prototype, { + _each: function(iterator) { + for (var i = 0; i < this.length; i++) + iterator(this[i]); + }, + + clear: function() { + this.length = 0; + return this; + }, + + first: function() { + return this[0]; + }, + + last: function() { + return this[this.length - 1]; + }, + + compact: function() { + return this.select(function(value) { + return value != undefined || value != null; + }); + }, + + flatten: function() { + return this.inject([], function(array, value) { + return array.concat(value.constructor == Array ? + value.flatten() : [value]); + }); + }, + + without: function() { + var values = $A(arguments); + return this.select(function(value) { + return !values.include(value); + }); + }, + + indexOf: function(object) { + for (var i = 0; i < this.length; i++) + if (this[i] == object) return i; + return -1; + }, + + reverse: function(inline) { + return (inline !== false ? this : this.toArray())._reverse(); + }, + + shift: function() { + var result = this[0]; + for (var i = 0; i < this.length - 1; i++) + this[i] = this[i + 1]; + this.length--; + return result; + }, + + inspect: function() { + return '[' + this.map(Object.inspect).join(', ') + ']'; + } +}); +var Hash = { + _each: function(iterator) { + for (key in this) { + var value = this[key]; + if (typeof value == 'function') continue; + + var pair = [key, value]; + pair.key = key; + pair.value = value; + iterator(pair); + } + }, + + keys: function() { + return this.pluck('key'); + }, + + values: function() { + return this.pluck('value'); + }, + + merge: function(hash) { + return $H(hash).inject($H(this), function(mergedHash, pair) { + mergedHash[pair.key] = pair.value; + return mergedHash; + }); + }, + + toQueryString: function() { + return this.map(function(pair) { + return pair.map(encodeURIComponent).join('='); + }).join('&'); + }, + + inspect: function() { + return '#'; + } +} + +function $H(object) { + var hash = Object.extend({}, object || {}); + Object.extend(hash, Enumerable); + Object.extend(hash, Hash); + return hash; +} +ObjectRange = Class.create(); +Object.extend(ObjectRange.prototype, Enumerable); +Object.extend(ObjectRange.prototype, { + initialize: function(start, end, exclusive) { + this.start = start; + this.end = end; + this.exclusive = exclusive; + }, + + _each: function(iterator) { + var value = this.start; + do { + iterator(value); + value = value.succ(); + } while (this.include(value)); + }, + + include: function(value) { + if (value < this.start) + return false; + if (this.exclusive) + return value < this.end; + return value <= this.end; + } +}); + +var $R = function(start, end, exclusive) { + return new ObjectRange(start, end, exclusive); +} + +var Ajax = { + getTransport: function() { + return Try.these( + function() {return new ActiveXObject('Msxml2.XMLHTTP')}, + function() {return new ActiveXObject('Microsoft.XMLHTTP')}, + function() {return new XMLHttpRequest()} + ) || false; + }, + + activeRequestCount: 0 +} + +Ajax.Responders = { + responders: [], + + _each: function(iterator) { + this.responders._each(iterator); + }, + + register: function(responderToAdd) { + if (!this.include(responderToAdd)) + this.responders.push(responderToAdd); + }, + + unregister: function(responderToRemove) { + this.responders = this.responders.without(responderToRemove); + }, + + dispatch: function(callback, request, transport, json) { + this.each(function(responder) { + if (responder[callback] && typeof responder[callback] == 'function') { + try { + responder[callback].apply(responder, [request, transport, json]); + } catch (e) {} + } + }); + } +}; + +Object.extend(Ajax.Responders, Enumerable); + +Ajax.Responders.register({ + onCreate: function() { + Ajax.activeRequestCount++; + }, + + onComplete: function() { + Ajax.activeRequestCount--; + } +}); + +Ajax.Base = function() {}; +Ajax.Base.prototype = { + setOptions: function(options) { + this.options = { + method: 'post', + asynchronous: true, + parameters: '' + } + Object.extend(this.options, options || {}); + }, + + responseIsSuccess: function() { + return this.transport.status == undefined + || this.transport.status == 0 + || (this.transport.status >= 200 && this.transport.status < 300); + }, + + responseIsFailure: function() { + return !this.responseIsSuccess(); + } +} + +Ajax.Request = Class.create(); +Ajax.Request.Events = + ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']; + +Ajax.Request.prototype = Object.extend(new Ajax.Base(), { + initialize: function(url, options) { + this.transport = Ajax.getTransport(); + this.setOptions(options); + this.request(url); + }, + + request: function(url) { + var parameters = this.options.parameters || ''; + if (parameters.length > 0) parameters += '&_='; + + try { + this.url = url; + if (this.options.method == 'get' && parameters.length > 0) + this.url += (this.url.match(/\?/) ? '&' : '?') + parameters; + + Ajax.Responders.dispatch('onCreate', this, this.transport); + + this.transport.open(this.options.method, this.url, + this.options.asynchronous); + + if (this.options.asynchronous) { + this.transport.onreadystatechange = this.onStateChange.bind(this); + setTimeout((function() {this.respondToReadyState(1)}).bind(this), 10); + } + + this.setRequestHeaders(); + + var body = this.options.postBody ? this.options.postBody : parameters; + this.transport.send(this.options.method == 'post' ? body : null); + + } catch (e) { + this.dispatchException(e); + } + }, + + setRequestHeaders: function() { + var requestHeaders = + ['X-Requested-With', 'XMLHttpRequest', + 'X-Prototype-Version', Prototype.Version]; + + if (this.options.method == 'post') { + requestHeaders.push('Content-type', + 'application/x-www-form-urlencoded'); + + /* Force "Connection: close" for Mozilla browsers to work around + * a bug where XMLHttpReqeuest sends an incorrect Content-length + * header. See Mozilla Bugzilla #246651. + */ + if (this.transport.overrideMimeType) + requestHeaders.push('Connection', 'close'); + } + + if (this.options.requestHeaders) + requestHeaders.push.apply(requestHeaders, this.options.requestHeaders); + + for (var i = 0; i < requestHeaders.length; i += 2) + this.transport.setRequestHeader(requestHeaders[i], requestHeaders[i+1]); + }, + + onStateChange: function() { + var readyState = this.transport.readyState; + if (readyState != 1) + this.respondToReadyState(this.transport.readyState); + }, + + header: function(name) { + try { + return this.transport.getResponseHeader(name); + } catch (e) {} + }, + + evalJSON: function() { + try { + return eval(this.header('X-JSON')); + } catch (e) {} + }, + + evalResponse: function() { + try { + return eval(this.transport.responseText); + } catch (e) { + this.dispatchException(e); + } + }, + + respondToReadyState: function(readyState) { + var event = Ajax.Request.Events[readyState]; + var transport = this.transport, json = this.evalJSON(); + + if (event == 'Complete') { + try { + (this.options['on' + this.transport.status] + || this.options['on' + (this.responseIsSuccess() ? 'Success' : 'Failure')] + || Prototype.emptyFunction)(transport, json); + } catch (e) { + this.dispatchException(e); + } + + if ((this.header('Content-type') || '').match(/^text\/javascript/i)) + this.evalResponse(); + } + + try { + (this.options['on' + event] || Prototype.emptyFunction)(transport, json); + Ajax.Responders.dispatch('on' + event, this, transport, json); + } catch (e) { + this.dispatchException(e); + } + + /* Avoid memory leak in MSIE: clean up the oncomplete event handler */ + if (event == 'Complete') + this.transport.onreadystatechange = Prototype.emptyFunction; + }, + + dispatchException: function(exception) { + (this.options.onException || Prototype.emptyFunction)(this, exception); + Ajax.Responders.dispatch('onException', this, exception); + } +}); + +Ajax.Updater = Class.create(); + +Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), { + initialize: function(container, url, options) { + this.containers = { + success: container.success ? $(container.success) : $(container), + failure: container.failure ? $(container.failure) : + (container.success ? null : $(container)) + } + + this.transport = Ajax.getTransport(); + this.setOptions(options); + + var onComplete = this.options.onComplete || Prototype.emptyFunction; + this.options.onComplete = (function(transport, object) { + this.updateContent(); + onComplete(transport, object); + }).bind(this); + + this.request(url); + }, + + updateContent: function() { + var receiver = this.responseIsSuccess() ? + this.containers.success : this.containers.failure; + var response = this.transport.responseText; + + if (!this.options.evalScripts) + response = response.stripScripts(); + + if (receiver) { + if (this.options.insertion) { + new this.options.insertion(receiver, response); + } else { + Element.update(receiver, response); + } + } + + if (this.responseIsSuccess()) { + if (this.onComplete) + setTimeout(this.onComplete.bind(this), 10); + } + } +}); + +Ajax.PeriodicalUpdater = Class.create(); +Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), { + initialize: function(container, url, options) { + this.setOptions(options); + this.onComplete = this.options.onComplete; + + this.frequency = (this.options.frequency || 2); + this.decay = (this.options.decay || 1); + + this.updater = {}; + this.container = container; + this.url = url; + + this.start(); + }, + + start: function() { + this.options.onComplete = this.updateComplete.bind(this); + this.onTimerEvent(); + }, + + stop: function() { + this.updater.onComplete = undefined; + clearTimeout(this.timer); + (this.onComplete || Prototype.emptyFunction).apply(this, arguments); + }, + + updateComplete: function(request) { + if (this.options.decay) { + this.decay = (request.responseText == this.lastText ? + this.decay * this.options.decay : 1); + + this.lastText = request.responseText; + } + this.timer = setTimeout(this.onTimerEvent.bind(this), + this.decay * this.frequency * 1000); + }, + + onTimerEvent: function() { + this.updater = new Ajax.Updater(this.container, this.url, this.options); + } +}); +document.getElementsByClassName = function(className, parentElement) { + var children = ($(parentElement) || document.body).getElementsByTagName('*'); + return $A(children).inject([], function(elements, child) { + if (child.className.match(new RegExp("(^|\\s)" + className + "(\\s|$)"))) + elements.push(child); + return elements; + }); +} + +/*--------------------------------------------------------------------------*/ + +if (!window.Element) { + var Element = new Object(); +} + +Object.extend(Element, { + visible: function(element) { + return $(element).style.display != 'none'; + }, + + toggle: function() { + for (var i = 0; i < arguments.length; i++) { + var element = $(arguments[i]); + Element[Element.visible(element) ? 'hide' : 'show'](element); + } + }, + + hide: function() { + for (var i = 0; i < arguments.length; i++) { + var element = $(arguments[i]); + element.style.display = 'none'; + } + }, + + show: function() { + for (var i = 0; i < arguments.length; i++) { + var element = $(arguments[i]); + element.style.display = ''; + } + }, + + remove: function(element) { + element = $(element); + element.parentNode.removeChild(element); + }, + + update: function(element, html) { + $(element).innerHTML = html.stripScripts(); + setTimeout(function() {html.evalScripts()}, 10); + }, + + getHeight: function(element) { + element = $(element); + return element.offsetHeight; + }, + + classNames: function(element) { + return new Element.ClassNames(element); + }, + + hasClassName: function(element, className) { + if (!(element = $(element))) return; + return Element.classNames(element).include(className); + }, + + addClassName: function(element, className) { + if (!(element = $(element))) return; + return Element.classNames(element).add(className); + }, + + removeClassName: function(element, className) { + if (!(element = $(element))) return; + return Element.classNames(element).remove(className); + }, + + // removes whitespace-only text node children + cleanWhitespace: function(element) { + element = $(element); + for (var i = 0; i < element.childNodes.length; i++) { + var node = element.childNodes[i]; + if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) + Element.remove(node); + } + }, + + empty: function(element) { + return $(element).innerHTML.match(/^\s*$/); + }, + + scrollTo: function(element) { + element = $(element); + var x = element.x ? element.x : element.offsetLeft, + y = element.y ? element.y : element.offsetTop; + window.scrollTo(x, y); + }, + + getStyle: function(element, style) { + element = $(element); + var value = element.style[style.camelize()]; + if (!value) { + if (document.defaultView && document.defaultView.getComputedStyle) { + var css = document.defaultView.getComputedStyle(element, null); + value = css ? css.getPropertyValue(style) : null; + } else if (element.currentStyle) { + value = element.currentStyle[style.camelize()]; + } + } + + if (window.opera && ['left', 'top', 'right', 'bottom'].include(style)) + if (Element.getStyle(element, 'position') == 'static') value = 'auto'; + + return value == 'auto' ? null : value; + }, + + setStyle: function(element, style) { + element = $(element); + for (name in style) + element.style[name.camelize()] = style[name]; + }, + + getDimensions: function(element) { + element = $(element); + if (Element.getStyle(element, 'display') != 'none') + return {width: element.offsetWidth, height: element.offsetHeight}; + + // All *Width and *Height properties give 0 on elements with display none, + // so enable the element temporarily + var els = element.style; + var originalVisibility = els.visibility; + var originalPosition = els.position; + els.visibility = 'hidden'; + els.position = 'absolute'; + els.display = ''; + var originalWidth = element.clientWidth; + var originalHeight = element.clientHeight; + els.display = 'none'; + els.position = originalPosition; + els.visibility = originalVisibility; + return {width: originalWidth, height: originalHeight}; + }, + + makePositioned: function(element) { + element = $(element); + var pos = Element.getStyle(element, 'position'); + if (pos == 'static' || !pos) { + element._madePositioned = true; + element.style.position = 'relative'; + // Opera returns the offset relative to the positioning context, when an + // element is position relative but top and left have not been defined + if (window.opera) { + element.style.top = 0; + element.style.left = 0; + } + } + }, + + undoPositioned: function(element) { + element = $(element); + if (element._madePositioned) { + element._madePositioned = undefined; + element.style.position = + element.style.top = + element.style.left = + element.style.bottom = + element.style.right = ''; + } + }, + + makeClipping: function(element) { + element = $(element); + if (element._overflow) return; + element._overflow = element.style.overflow; + if ((Element.getStyle(element, 'overflow') || 'visible') != 'hidden') + element.style.overflow = 'hidden'; + }, + + undoClipping: function(element) { + element = $(element); + if (element._overflow) return; + element.style.overflow = element._overflow; + element._overflow = undefined; + } +}); + +var Toggle = new Object(); +Toggle.display = Element.toggle; + +/*--------------------------------------------------------------------------*/ + +Abstract.Insertion = function(adjacency) { + this.adjacency = adjacency; +} + +Abstract.Insertion.prototype = { + initialize: function(element, content) { + this.element = $(element); + this.content = content.stripScripts(); + + if (this.adjacency && this.element.insertAdjacentHTML) { + try { + this.element.insertAdjacentHTML(this.adjacency, this.content); + } catch (e) { + if (this.element.tagName.toLowerCase() == 'tbody') { + this.insertContent(this.contentFromAnonymousTable()); + } else { + throw e; + } + } + } else { + this.range = this.element.ownerDocument.createRange(); + if (this.initializeRange) this.initializeRange(); + this.insertContent([this.range.createContextualFragment(this.content)]); + } + + setTimeout(function() {content.evalScripts()}, 10); + }, + + contentFromAnonymousTable: function() { + var div = document.createElement('div'); + div.innerHTML = '' + this.content + '
'; + return $A(div.childNodes[0].childNodes[0].childNodes); + } +} + +var Insertion = new Object(); + +Insertion.Before = Class.create(); +Insertion.Before.prototype = Object.extend(new Abstract.Insertion('beforeBegin'), { + initializeRange: function() { + this.range.setStartBefore(this.element); + }, + + insertContent: function(fragments) { + fragments.each((function(fragment) { + this.element.parentNode.insertBefore(fragment, this.element); + }).bind(this)); + } +}); + +Insertion.Top = Class.create(); +Insertion.Top.prototype = Object.extend(new Abstract.Insertion('afterBegin'), { + initializeRange: function() { + this.range.selectNodeContents(this.element); + this.range.collapse(true); + }, + + insertContent: function(fragments) { + fragments.reverse(false).each((function(fragment) { + this.element.insertBefore(fragment, this.element.firstChild); + }).bind(this)); + } +}); + +Insertion.Bottom = Class.create(); +Insertion.Bottom.prototype = Object.extend(new Abstract.Insertion('beforeEnd'), { + initializeRange: function() { + this.range.selectNodeContents(this.element); + this.range.collapse(this.element); + }, + + insertContent: function(fragments) { + fragments.each((function(fragment) { + this.element.appendChild(fragment); + }).bind(this)); + } +}); + +Insertion.After = Class.create(); +Insertion.After.prototype = Object.extend(new Abstract.Insertion('afterEnd'), { + initializeRange: function() { + this.range.setStartAfter(this.element); + }, + + insertContent: function(fragments) { + fragments.each((function(fragment) { + this.element.parentNode.insertBefore(fragment, + this.element.nextSibling); + }).bind(this)); + } +}); + +/*--------------------------------------------------------------------------*/ + +Element.ClassNames = Class.create(); +Element.ClassNames.prototype = { + initialize: function(element) { + this.element = $(element); + }, + + _each: function(iterator) { + this.element.className.split(/\s+/).select(function(name) { + return name.length > 0; + })._each(iterator); + }, + + set: function(className) { + this.element.className = className; + }, + + add: function(classNameToAdd) { + if (this.include(classNameToAdd)) return; + this.set(this.toArray().concat(classNameToAdd).join(' ')); + }, + + remove: function(classNameToRemove) { + if (!this.include(classNameToRemove)) return; + this.set(this.select(function(className) { + return className != classNameToRemove; + }).join(' ')); + }, + + toString: function() { + return this.toArray().join(' '); + } +} + +Object.extend(Element.ClassNames.prototype, Enumerable); +var Field = { + clear: function() { + for (var i = 0; i < arguments.length; i++) + $(arguments[i]).value = ''; + }, + + focus: function(element) { + $(element).focus(); + }, + + present: function() { + for (var i = 0; i < arguments.length; i++) + if ($(arguments[i]).value == '') return false; + return true; + }, + + select: function(element) { + $(element).select(); + }, + + activate: function(element) { + element = $(element); + element.focus(); + if (element.select) + element.select(); + } +} + +/*--------------------------------------------------------------------------*/ + +var Form = { + serialize: function(form) { + var elements = Form.getElements($(form)); + var queryComponents = new Array(); + + for (var i = 0; i < elements.length; i++) { + var queryComponent = Form.Element.serialize(elements[i]); + if (queryComponent) + queryComponents.push(queryComponent); + } + + return queryComponents.join('&'); + }, + + getElements: function(form) { + form = $(form); + var elements = new Array(); + + for (tagName in Form.Element.Serializers) { + var tagElements = form.getElementsByTagName(tagName); + for (var j = 0; j < tagElements.length; j++) + elements.push(tagElements[j]); + } + return elements; + }, + + getInputs: function(form, typeName, name) { + form = $(form); + var inputs = form.getElementsByTagName('input'); + + if (!typeName && !name) + return inputs; + + var matchingInputs = new Array(); + for (var i = 0; i < inputs.length; i++) { + var input = inputs[i]; + if ((typeName && input.type != typeName) || + (name && input.name != name)) + continue; + matchingInputs.push(input); + } + + return matchingInputs; + }, + + disable: function(form) { + var elements = Form.getElements(form); + for (var i = 0; i < elements.length; i++) { + var element = elements[i]; + element.blur(); + element.disabled = 'true'; + } + }, + + enable: function(form) { + var elements = Form.getElements(form); + for (var i = 0; i < elements.length; i++) { + var element = elements[i]; + element.disabled = ''; + } + }, + + findFirstElement: function(form) { + return Form.getElements(form).find(function(element) { + return element.type != 'hidden' && !element.disabled && + ['input', 'select', 'textarea'].include(element.tagName.toLowerCase()); + }); + }, + + focusFirstElement: function(form) { + Field.activate(Form.findFirstElement(form)); + }, + + reset: function(form) { + $(form).reset(); + } +} + +Form.Element = { + serialize: function(element) { + element = $(element); + var method = element.tagName.toLowerCase(); + var parameter = Form.Element.Serializers[method](element); + + if (parameter) { + var key = encodeURIComponent(parameter[0]); + if (key.length == 0) return; + + if (parameter[1].constructor != Array) + parameter[1] = [parameter[1]]; + + return parameter[1].map(function(value) { + return key + '=' + encodeURIComponent(value); + }).join('&'); + } + }, + + getValue: function(element) { + element = $(element); + var method = element.tagName.toLowerCase(); + var parameter = Form.Element.Serializers[method](element); + + if (parameter) + return parameter[1]; + } +} + +Form.Element.Serializers = { + input: function(element) { + switch (element.type.toLowerCase()) { + case 'submit': + case 'hidden': + case 'password': + case 'text': + return Form.Element.Serializers.textarea(element); + case 'checkbox': + case 'radio': + return Form.Element.Serializers.inputSelector(element); + } + return false; + }, + + inputSelector: function(element) { + if (element.checked) + return [element.name, element.value]; + }, + + textarea: function(element) { + return [element.name, element.value]; + }, + + select: function(element) { + return Form.Element.Serializers[element.type == 'select-one' ? + 'selectOne' : 'selectMany'](element); + }, + + selectOne: function(element) { + var value = '', opt, index = element.selectedIndex; + if (index >= 0) { + opt = element.options[index]; + value = opt.value; + if (!value && !('value' in opt)) + value = opt.text; + } + return [element.name, value]; + }, + + selectMany: function(element) { + var value = new Array(); + for (var i = 0; i < element.length; i++) { + var opt = element.options[i]; + if (opt.selected) { + var optValue = opt.value; + if (!optValue && !('value' in opt)) + optValue = opt.text; + value.push(optValue); + } + } + return [element.name, value]; + } +} + +/*--------------------------------------------------------------------------*/ + +var $F = Form.Element.getValue; + +/*--------------------------------------------------------------------------*/ + +Abstract.TimedObserver = function() {} +Abstract.TimedObserver.prototype = { + initialize: function(element, frequency, callback) { + this.frequency = frequency; + this.element = $(element); + this.callback = callback; + + this.lastValue = this.getValue(); + this.registerCallback(); + }, + + registerCallback: function() { + setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); + }, + + onTimerEvent: function() { + var value = this.getValue(); + if (this.lastValue != value) { + this.callback(this.element, value); + this.lastValue = value; + } + } +} + +Form.Element.Observer = Class.create(); +Form.Element.Observer.prototype = Object.extend(new Abstract.TimedObserver(), { + getValue: function() { + return Form.Element.getValue(this.element); + } +}); + +Form.Observer = Class.create(); +Form.Observer.prototype = Object.extend(new Abstract.TimedObserver(), { + getValue: function() { + return Form.serialize(this.element); + } +}); + +/*--------------------------------------------------------------------------*/ + +Abstract.EventObserver = function() {} +Abstract.EventObserver.prototype = { + initialize: function(element, callback) { + this.element = $(element); + this.callback = callback; + + this.lastValue = this.getValue(); + if (this.element.tagName.toLowerCase() == 'form') + this.registerFormCallbacks(); + else + this.registerCallback(this.element); + }, + + onElementEvent: function() { + var value = this.getValue(); + if (this.lastValue != value) { + this.callback(this.element, value); + this.lastValue = value; + } + }, + + registerFormCallbacks: function() { + var elements = Form.getElements(this.element); + for (var i = 0; i < elements.length; i++) + this.registerCallback(elements[i]); + }, + + registerCallback: function(element) { + if (element.type) { + switch (element.type.toLowerCase()) { + case 'checkbox': + case 'radio': + Event.observe(element, 'click', this.onElementEvent.bind(this)); + break; + case 'password': + case 'text': + case 'textarea': + case 'select-one': + case 'select-multiple': + Event.observe(element, 'change', this.onElementEvent.bind(this)); + break; + } + } + } +} + +Form.Element.EventObserver = Class.create(); +Form.Element.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), { + getValue: function() { + return Form.Element.getValue(this.element); + } +}); + +Form.EventObserver = Class.create(); +Form.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), { + getValue: function() { + return Form.serialize(this.element); + } +}); +if (!window.Event) { + var Event = new Object(); +} + +Object.extend(Event, { + KEY_BACKSPACE: 8, + KEY_TAB: 9, + KEY_RETURN: 13, + KEY_ESC: 27, + KEY_LEFT: 37, + KEY_UP: 38, + KEY_RIGHT: 39, + KEY_DOWN: 40, + KEY_DELETE: 46, + + element: function(event) { + return event.target || event.srcElement; + }, + + isLeftClick: function(event) { + return (((event.which) && (event.which == 1)) || + ((event.button) && (event.button == 1))); + }, + + pointerX: function(event) { + return event.pageX || (event.clientX + + (document.documentElement.scrollLeft || document.body.scrollLeft)); + }, + + pointerY: function(event) { + return event.pageY || (event.clientY + + (document.documentElement.scrollTop || document.body.scrollTop)); + }, + + stop: function(event) { + if (event.preventDefault) { + event.preventDefault(); + event.stopPropagation(); + } else { + event.returnValue = false; + event.cancelBubble = true; + } + }, + + // find the first node with the given tagName, starting from the + // node the event was triggered on; traverses the DOM upwards + findElement: function(event, tagName) { + var element = Event.element(event); + while (element.parentNode && (!element.tagName || + (element.tagName.toUpperCase() != tagName.toUpperCase()))) + element = element.parentNode; + return element; + }, + + observers: false, + + _observeAndCache: function(element, name, observer, useCapture) { + if (!this.observers) this.observers = []; + if (element.addEventListener) { + this.observers.push([element, name, observer, useCapture]); + element.addEventListener(name, observer, useCapture); + } else if (element.attachEvent) { + this.observers.push([element, name, observer, useCapture]); + element.attachEvent('on' + name, observer); + } + }, + + unloadCache: function() { + if (!Event.observers) return; + for (var i = 0; i < Event.observers.length; i++) { + Event.stopObserving.apply(this, Event.observers[i]); + Event.observers[i][0] = null; + } + Event.observers = false; + }, + + observe: function(element, name, observer, useCapture) { + var element = $(element); + useCapture = useCapture || false; + + if (name == 'keypress' && + (navigator.appVersion.match(/Konqueror|Safari|KHTML/) + || element.attachEvent)) + name = 'keydown'; + + this._observeAndCache(element, name, observer, useCapture); + }, + + stopObserving: function(element, name, observer, useCapture) { + var element = $(element); + useCapture = useCapture || false; + + if (name == 'keypress' && + (navigator.appVersion.match(/Konqueror|Safari|KHTML/) + || element.detachEvent)) + name = 'keydown'; + + if (element.removeEventListener) { + element.removeEventListener(name, observer, useCapture); + } else if (element.detachEvent) { + element.detachEvent('on' + name, observer); + } + } +}); + +/* prevent memory leaks in IE */ +Event.observe(window, 'unload', Event.unloadCache, false); +var Position = { + // set to true if needed, warning: firefox performance problems + // NOT neeeded for page scrolling, only if draggable contained in + // scrollable elements + includeScrollOffsets: false, + + // must be called before calling withinIncludingScrolloffset, every time the + // page is scrolled + prepare: function() { + this.deltaX = window.pageXOffset + || document.documentElement.scrollLeft + || document.body.scrollLeft + || 0; + this.deltaY = window.pageYOffset + || document.documentElement.scrollTop + || document.body.scrollTop + || 0; + }, + + realOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.scrollTop || 0; + valueL += element.scrollLeft || 0; + element = element.parentNode; + } while (element); + return [valueL, valueT]; + }, + + cumulativeOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + element = element.offsetParent; + } while (element); + return [valueL, valueT]; + }, + + positionedOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + element = element.offsetParent; + if (element) { + p = Element.getStyle(element, 'position'); + if (p == 'relative' || p == 'absolute') break; + } + } while (element); + return [valueL, valueT]; + }, + + offsetParent: function(element) { + if (element.offsetParent) return element.offsetParent; + if (element == document.body) return element; + + while ((element = element.parentNode) && element != document.body) + if (Element.getStyle(element, 'position') != 'static') + return element; + + return document.body; + }, + + // caches x/y coordinate pair to use with overlap + within: function(element, x, y) { + if (this.includeScrollOffsets) + return this.withinIncludingScrolloffsets(element, x, y); + this.xcomp = x; + this.ycomp = y; + this.offset = this.cumulativeOffset(element); + + return (y >= this.offset[1] && + y < this.offset[1] + element.offsetHeight && + x >= this.offset[0] && + x < this.offset[0] + element.offsetWidth); + }, + + withinIncludingScrolloffsets: function(element, x, y) { + var offsetcache = this.realOffset(element); + + this.xcomp = x + offsetcache[0] - this.deltaX; + this.ycomp = y + offsetcache[1] - this.deltaY; + this.offset = this.cumulativeOffset(element); + + return (this.ycomp >= this.offset[1] && + this.ycomp < this.offset[1] + element.offsetHeight && + this.xcomp >= this.offset[0] && + this.xcomp < this.offset[0] + element.offsetWidth); + }, + + // within must be called directly before + overlap: function(mode, element) { + if (!mode) return 0; + if (mode == 'vertical') + return ((this.offset[1] + element.offsetHeight) - this.ycomp) / + element.offsetHeight; + if (mode == 'horizontal') + return ((this.offset[0] + element.offsetWidth) - this.xcomp) / + element.offsetWidth; + }, + + clone: function(source, target) { + source = $(source); + target = $(target); + target.style.position = 'absolute'; + var offsets = this.cumulativeOffset(source); + target.style.top = offsets[1] + 'px'; + target.style.left = offsets[0] + 'px'; + target.style.width = source.offsetWidth + 'px'; + target.style.height = source.offsetHeight + 'px'; + }, + + page: function(forElement) { + var valueT = 0, valueL = 0; + + var element = forElement; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + + // Safari fix + if (element.offsetParent==document.body) + if (Element.getStyle(element,'position')=='absolute') break; + + } while (element = element.offsetParent); + + element = forElement; + do { + valueT -= element.scrollTop || 0; + valueL -= element.scrollLeft || 0; + } while (element = element.parentNode); + + return [valueL, valueT]; + }, + + clone: function(source, target) { + var options = Object.extend({ + setLeft: true, + setTop: true, + setWidth: true, + setHeight: true, + offsetTop: 0, + offsetLeft: 0 + }, arguments[2] || {}) + + // find page position of source + source = $(source); + var p = Position.page(source); + + // find coordinate system to use + target = $(target); + var delta = [0, 0]; + var parent = null; + // delta [0,0] will do fine with position: fixed elements, + // position:absolute needs offsetParent deltas + if (Element.getStyle(target,'position') == 'absolute') { + parent = Position.offsetParent(target); + delta = Position.page(parent); + } + + // correct by body offsets (fixes Safari) + if (parent == document.body) { + delta[0] -= document.body.offsetLeft; + delta[1] -= document.body.offsetTop; + } + + // set position + if(options.setLeft) target.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px'; + if(options.setTop) target.style.top = (p[1] - delta[1] + options.offsetTop) + 'px'; + if(options.setWidth) target.style.width = source.offsetWidth + 'px'; + if(options.setHeight) target.style.height = source.offsetHeight + 'px'; + }, + + absolutize: function(element) { + element = $(element); + if (element.style.position == 'absolute') return; + Position.prepare(); + + var offsets = Position.positionedOffset(element); + var top = offsets[1]; + var left = offsets[0]; + var width = element.clientWidth; + var height = element.clientHeight; + + element._originalLeft = left - parseFloat(element.style.left || 0); + element._originalTop = top - parseFloat(element.style.top || 0); + element._originalWidth = element.style.width; + element._originalHeight = element.style.height; + + element.style.position = 'absolute'; + element.style.top = top + 'px';; + element.style.left = left + 'px';; + element.style.width = width + 'px';; + element.style.height = height + 'px';; + }, + + relativize: function(element) { + element = $(element); + if (element.style.position == 'relative') return; + Position.prepare(); + + element.style.position = 'relative'; + var top = parseFloat(element.style.top || 0) - (element._originalTop || 0); + var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0); + + element.style.top = top + 'px'; + element.style.left = left + 'px'; + element.style.height = element._originalHeight; + element.style.width = element._originalWidth; + } +} + +// Safari returns margins on body which is incorrect if the child is absolutely +// positioned. For performance reasons, redefine Position.cumulativeOffset for +// KHTML/WebKit only. +if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) { + Position.cumulativeOffset = function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + if (element.offsetParent == document.body) + if (Element.getStyle(element, 'position') == 'absolute') break; + + element = element.offsetParent; + } while (element); + + return [valueL, valueT]; + } +} \ No newline at end of file diff --git a/deploy/root/stylesheets/default.css b/deploy/root/stylesheets/default.css new file mode 100644 index 0000000000..716fc7ab59 --- /dev/null +++ b/deploy/root/stylesheets/default.css @@ -0,0 +1,54 @@ +body { + background-image: url(../images/body-background.png); + background-repeat: repeat-x; + background-color: #5c8098; +} +html, body, h1, h2 { + margin: 0px; + padding: 0px; +} +body, textarea, input { + font-size: 12px; + font-family: Verdana, Helvetica, Arial, sans-serif; + color: #2d2b3d; +} +#container { + text-align:center; +} +#container-inner { + margin-left: auto; + margin-right: auto; + text-align: justify; + width: 820px; +} +#header { + width: 820px; + height: 100px; + background-image: url(../images/header-background.png); + background-repeat: no-repeat; +} +#header h1 { + display: none; +} +#main { + height: 610px; + background-image: url(../images/main-background.png); + background-repeat: no-repeat; + text-align: left; + width: 740px; + padding: 30px 40px 20px 40px; +} +#display { + border: 1px solid #5c8098; + width: 740px; + height: 400px; + margin-bottom: 10px; + overflow-y: scroll; +} +#login-name { + width: 200px; +} +#message { + width: 740px; + height: 50px; +}