AUTOMAKE_OPTIONS = gnu
-SUBDIRS = antiscrollbar
-# movietagger webinterface
+SUBDIRS = antiscrollbar movietagger webinterface
movietagger/etc/Makefile
movietagger/src/Makefile
+webinterface/Makefile
+webinterface/src/Makefile
+webinterface/src/web-data/Makefile
+webinterface/src/web-data/gfx/Makefile
+webinterface/src/web/Makefile
+webinterface/src/Components/Makefile
+webinterface/src/Components/Converter/Makefile
+webinterface/src/Components/Sources/Makefile
+
])
--- /dev/null
+SUBDIRS = src
--- /dev/null
+installdir = /usr/lib/enigma2/python/Plugins/Extensions/WebInterface/
+
+install_PYTHON = __init__.py plugin.py webif.py
+
+SUBDIRS = web web-data Components
--- /dev/null
+installdir = /usr/lib/enigma2/python/Plugins/Extensions/WebInterface/Components/Converter/
+
+install_PYTHON = __init__.py VolumeToText.py
--- /dev/null
+from Converter import Converter
+from Components.config import *
+from enigma import eDVBVolumecontrol #this is not nice
+class VolumeToText(Converter, object):
+
+ def __init__(self, type):
+ Converter.__init__(self, type)
+ self.volctrl = eDVBVolumecontrol.getInstance() # this is not nice
+
+ def getHTML(self, id):
+ return self.getText() # encode & etc. here!
+ def getText(self):
+ r = "%s\n"%config.audio.volume.value
+ if self.volctrl.isMuted():
+ r+="muted"
+ else:
+ r+="notmuted"
+ return r
+
+
+ text = property(getText)
--- /dev/null
+installdir = /usr/lib/enigma2/python/Plugins/Extensions/WebInterface/Components/
+
+install_PYTHON = __init__.py
+
+SUBDIRS = Converter Sources
--- /dev/null
+from enigma import *
+
+from Source import Source
+from ServiceReference import ServiceReference
+
+class EPG( Source):
+ NOWNEXT=0
+ SERVICE=1
+ TITLE=2
+
+ def __init__(self, navcore,func=NOWNEXT):
+ self.func = func
+ Source.__init__(self)
+ self.navcore = navcore
+ self.epgcache = eEPGCache.getInstance()
+
+ def handleCommand(self,cmd):
+ self.command = cmd
+
+ def do_func(self):
+ if self.func is self.TITLE:
+ func = self.searchEvent
+ elif self.func is self.SERVICE:
+ func = self.getEPGofService
+ else:
+ func = self.getEPGNowNext
+
+ return func(self.command)
+
+ def getEPGNowNext(self,cmd):
+ print "getting EPG NOWNEXT", cmd
+ events = self.epgcache.lookupEvent(['IBDTSERN',(cmd,0,0,-1)]);
+ if events:
+ return self.convert(events)
+ else:
+ return []
+
+ def getEPGofService(self,cmd):
+ print "getting EPG of Service", cmd
+ events = self.epgcache.lookupEvent(['IBDTSERN',(cmd,0,-1,-1)]);
+ if events:
+ return self.convert(events)
+ else:
+ return []
+
+ def searchEvent(self,cmd):
+ print "getting EPG by title",cmd
+ events = self.epgcache.search(('IBDTSERN',1024,eEPGCache.PARTIAL_TITLE_SEARCH,cmd,1));
+ if events:
+
+ return self.convert(events)
+ else:
+ return []
+
+ def convert(self,input):
+ #this is not nice, but ",',<,> and & are controlchars in xml and must be replaced
+ output = []
+ for i in input:
+ o = []
+ for key in i:
+ o.append(str(key).replace("<","<").replace(">",">").replace("&","&").replace("\"",""").replace("'","'"))
+ output.append(o)
+
+ return output
+
+ list = property(do_func)
+ lut = {"EventID": 0, "TimeStart": 1,"Duration": 2, "Title": 3, "Description": 4, "DescriptionExtended": 5, "ServiceReference": 6, "ServiceName": 7}
+
+
\ No newline at end of file
--- /dev/null
+installdir = /usr/lib/enigma2/python/Plugins/Extensions/WebInterface/Components/Sources/
+
+install_PYTHON = __init__.py EPG.py Timer.py Volume.py
--- /dev/null
+from enigma import *
+
+from Source import Source
+from ServiceReference import ServiceReference
+from enigma import eServiceReference
+class Timer( Source):
+
+ def __init__(self, session):
+ #self.func = func
+ Source.__init__(self)
+ self.session = session
+ self.recordtimer = session.nav.RecordTimer
+
+# def handleCommand(self,cmd):
+# self.command = cmd
+
+
+ def command(self):
+ timerlist = []
+ for item in self.recordtimer.timer_list+self.recordtimer.processed_timers:
+ timer = []
+ timer.append(item.service_ref)
+ timer.append(item.service_ref.getServiceName())
+ timer.append(item.eit)
+ timer.append(self.convert(item.name))
+ timer.append(self.convert(item.description))
+ timer.append(item.disabled)
+ timer.append(item.begin)
+ timer.append(item.end)
+ timer.append(item.end-item.begin)
+ timer.append(item.start_prepare)
+ timer.append(item.justplay)
+ timer.append(item.afterEvent)
+ timer.append(item.log_entries)
+ try:
+ timer.append(item.Filename)
+ except AttributeError:
+ timer.append("")
+
+ timer.append(item.backoff)
+ try:
+ timer.append(item.next_activation)
+ except AttributeError:
+ timer.append("")
+ timer.append(item.first_try_prepare)
+ timer.append(item.state)
+ timer.append(item.repeated)
+ timer.append(item.dontSave)
+ timer.append(item.cancelled)
+ timerlist.append(timer)
+
+ return timerlist
+
+ def convert(self,input):
+ #this is not nice, but ",',<,> and & are controlchars in xml and must be replaced
+ return input.replace("<","<").replace(">",">").replace("&","&").replace("\"",""").replace("'","'")
+
+ list = property(command)
+ lut = {"ServiceReference": 0
+ ,"ServiceName": 1
+ ,"EIT":2
+ ,"Name":3
+ ,"Description":4
+ ,"Disabled":5
+ ,"TimeBegin":6
+ ,"TimeEnd":7
+ ,"Duration":8
+ ,"startPrepare":9
+ ,"justPlay":10
+ ,"afterEvent":11
+ ,"LogEntries":12
+ ,"Filename":13
+ ,"Backoff":14
+ ,"nextActivation":15
+ ,"firstTryPrepare":16
+ ,"State":17
+ ,"Repeated":18
+ ,"dontSave":19
+ ,"Cancled":20
+ }
+
--- /dev/null
+from Source import Source
+from GlobalActions import globalActionMap
+
+from time import time
+
+class Volume( Source):
+ def __init__(self, navcore):
+ Source.__init__(self)
+
+
+ def handleCommand(self, cmd):
+ global globalActionMap
+ if cmd == "up":
+ globalActionMap.actions["volumeUp"]()
+ elif cmd == "down":
+ globalActionMap.actions["volumeDown"]()
+ elif cmd == "mute":
+ globalActionMap.actions["volumeMute"]()
+ elif cmd == "value":
+ pass
+ else:
+ print "unknow Volume handle command",cmd
+
\ No newline at end of file
--- /dev/null
+from Plugins.Plugin import PluginDescriptor
+
+sessions = [ ]
+
+def startWebserver():
+ from twisted.internet import reactor
+ from twisted.web2 import server, channel, static, resource, stream, http_headers, responsecode, http
+ from twisted.python import util
+ import webif
+
+ class ScreenPage(resource.Resource):
+ def __init__(self, path):
+ self.path = path
+
+ def render(self, req):
+ global sessions
+ if sessions == [ ]:
+ return http.Response(200, stream="please wait until enigma has booted")
+
+ class myProducerStream(stream.ProducerStream):
+ closed_callback = None
+
+ def close(self):
+ if self.closed_callback:
+ self.closed_callback()
+ stream.ProducerStream.close(self)
+
+ s = myProducerStream()
+ webif.renderPage(s, self.path, req, sessions[0]) # login?
+
+ return http.Response(stream=s)
+
+ def locateChild(self, request, segments):
+ path = '/'.join(["web"] + segments)
+ if path[-1:] == "/":
+ path += "index.html"
+
+ path += ".xml"
+ return ScreenPage(path), ()
+
+ class Toplevel(resource.Resource):
+ addSlash = True
+
+ def render(self, req):
+ return http.Response(responsecode.OK, {'Content-type': http_headers.MimeType('text', 'html')},
+ stream='Hello! You want go to <a href="/web/">OSD</a> instead.')
+
+ child_web = ScreenPage("/") # "/web"
+ child_hdd = static.File("/hdd")
+ child_webdata = static.File(util.sibpath(__file__, "web-data")) # FIXME: web-data appears as webdata
+
+ site = server.Site(Toplevel())
+
+ reactor.listenTCP(80, channel.HTTPFactory(site))
+
+def autostart(reason, **kwargs):
+ if "session" in kwargs:
+ global sessions
+ sessions.append(kwargs["session"])
+ return
+
+ if reason == 0:
+ try:
+ startWebserver()
+ except ImportError:
+ print "twisted not available, not starting web services"
+
+def Plugins(**kwargs):
+ return PluginDescriptor(where = [PluginDescriptor.WHERE_SESSIONSTART, PluginDescriptor.WHERE_AUTOSTART], fnc = autostart)
+++ /dev/null
-*.pyc
-*.pyo
+++ /dev/null
-from Converter import Converter
-from Components.config import *
-from enigma import eDVBVolumecontrol #this is not nice
-class VolumeToText(Converter, object):
-
- def __init__(self, type):
- Converter.__init__(self, type)
- self.volctrl = eDVBVolumecontrol.getInstance() # this is not nice
-
- def getHTML(self, id):
- return self.getText() # encode & etc. here!
- def getText(self):
- r = "%s\n"%config.audio.volume.value
- if self.volctrl.isMuted():
- r+="muted"
- else:
- r+="notmuted"
- return r
-
-
- text = property(getText)
+++ /dev/null
-*.pyc
-*.pyo
+++ /dev/null
-*.pyc
-*.pyo
+++ /dev/null
-from enigma import *
-
-from Source import Source
-from ServiceReference import ServiceReference
-
-class EPG( Source):
- NOWNEXT=0
- SERVICE=1
- TITLE=2
-
- def __init__(self, navcore,func=NOWNEXT):
- self.func = func
- Source.__init__(self)
- self.navcore = navcore
- self.epgcache = eEPGCache.getInstance()
-
- def handleCommand(self,cmd):
- self.command = cmd
-
- def do_func(self):
- if self.func is self.TITLE:
- func = self.searchEvent
- elif self.func is self.SERVICE:
- func = self.getEPGofService
- else:
- func = self.getEPGNowNext
-
- return func(self.command)
-
- def getEPGNowNext(self,cmd):
- print "getting EPG NOWNEXT", cmd
- events = self.epgcache.lookupEvent(['IBDTSERN',(cmd,0,0,-1)]);
- if events:
- return self.convert(events)
- else:
- return []
-
- def getEPGofService(self,cmd):
- print "getting EPG of Service", cmd
- events = self.epgcache.lookupEvent(['IBDTSERN',(cmd,0,-1,-1)]);
- if events:
- return self.convert(events)
- else:
- return []
-
- def searchEvent(self,cmd):
- print "getting EPG by title",cmd
- events = self.epgcache.search(('IBDTSERN',1024,eEPGCache.PARTIAL_TITLE_SEARCH,cmd,1));
- if events:
-
- return self.convert(events)
- else:
- return []
-
- def convert(self,input):
- #this is not nice, but ",',<,> and & are controlchars in xml and must be replaced
- output = []
- for i in input:
- o = []
- for key in i:
- o.append(str(key).replace("<","<").replace(">",">").replace("&","&").replace("\"",""").replace("'","'"))
- output.append(o)
-
- return output
-
- list = property(do_func)
- lut = {"EventID": 0, "TimeStart": 1,"Duration": 2, "Title": 3, "Description": 4, "DescriptionExtended": 5, "ServiceReference": 6, "ServiceName": 7}
-
-
\ No newline at end of file
+++ /dev/null
-from enigma import *
-
-from Source import Source
-from ServiceReference import ServiceReference
-from enigma import eServiceReference
-class Timer( Source):
-
- def __init__(self, session):
- #self.func = func
- Source.__init__(self)
- self.session = session
- self.recordtimer = session.nav.RecordTimer
-
-# def handleCommand(self,cmd):
-# self.command = cmd
-
-
- def command(self):
- timerlist = []
- for item in self.recordtimer.timer_list+self.recordtimer.processed_timers:
- timer = []
- timer.append(item.service_ref)
- timer.append(item.service_ref.getServiceName())
- timer.append(item.eit)
- timer.append(self.convert(item.name))
- timer.append(self.convert(item.description))
- timer.append(item.disabled)
- timer.append(item.begin)
- timer.append(item.end)
- timer.append(item.end-item.begin)
- timer.append(item.start_prepare)
- timer.append(item.justplay)
- timer.append(item.afterEvent)
- timer.append(item.log_entries)
- try:
- timer.append(item.Filename)
- except AttributeError:
- timer.append("")
-
- timer.append(item.backoff)
- try:
- timer.append(item.next_activation)
- except AttributeError:
- timer.append("")
- timer.append(item.first_try_prepare)
- timer.append(item.state)
- timer.append(item.repeated)
- timer.append(item.dontSave)
- timer.append(item.cancelled)
- timerlist.append(timer)
-
- return timerlist
-
- def convert(self,input):
- #this is not nice, but ",',<,> and & are controlchars in xml and must be replaced
- return input.replace("<","<").replace(">",">").replace("&","&").replace("\"",""").replace("'","'")
-
- list = property(command)
- lut = {"ServiceReference": 0
- ,"ServiceName": 1
- ,"EIT":2
- ,"Name":3
- ,"Description":4
- ,"Disabled":5
- ,"TimeBegin":6
- ,"TimeEnd":7
- ,"Duration":8
- ,"startPrepare":9
- ,"justPlay":10
- ,"afterEvent":11
- ,"LogEntries":12
- ,"Filename":13
- ,"Backoff":14
- ,"nextActivation":15
- ,"firstTryPrepare":16
- ,"State":17
- ,"Repeated":18
- ,"dontSave":19
- ,"Cancled":20
- }
-
+++ /dev/null
-from Source import Source
-from GlobalActions import globalActionMap
-
-from time import time
-
-class Volume( Source):
- def __init__(self, navcore):
- Source.__init__(self)
-
-
- def handleCommand(self, cmd):
- global globalActionMap
- if cmd == "up":
- globalActionMap.actions["volumeUp"]()
- elif cmd == "down":
- globalActionMap.actions["volumeDown"]()
- elif cmd == "mute":
- globalActionMap.actions["volumeMute"]()
- elif cmd == "value":
- pass
- else:
- print "unknow Volume handle command",cmd
-
\ No newline at end of file
+++ /dev/null
-*.pyc
-*.pyo
+++ /dev/null
-from Plugins.Plugin import PluginDescriptor
-
-sessions = [ ]
-
-def startWebserver():
- from twisted.internet import reactor
- from twisted.web2 import server, channel, static, resource, stream, http_headers, responsecode, http
- from twisted.python import util
- import webif
-
- class ScreenPage(resource.Resource):
- def __init__(self, path):
- self.path = path
-
- def render(self, req):
- global sessions
- if sessions == [ ]:
- return http.Response(200, stream="please wait until enigma has booted")
-
- class myProducerStream(stream.ProducerStream):
- closed_callback = None
-
- def close(self):
- if self.closed_callback:
- self.closed_callback()
- stream.ProducerStream.close(self)
-
- s = myProducerStream()
- webif.renderPage(s, self.path, req, sessions[0]) # login?
-
- return http.Response(stream=s)
-
- def locateChild(self, request, segments):
- path = '/'.join(["web"] + segments)
- if path[-1:] == "/":
- path += "index.html"
-
- path += ".xml"
- return ScreenPage(path), ()
-
- class Toplevel(resource.Resource):
- addSlash = True
-
- def render(self, req):
- return http.Response(responsecode.OK, {'Content-type': http_headers.MimeType('text', 'html')},
- stream='Hello! You want go to <a href="/web/">OSD</a> instead.')
-
- child_web = ScreenPage("/") # "/web"
- child_hdd = static.File("/hdd")
- child_webdata = static.File(util.sibpath(__file__, "web-data")) # FIXME: web-data appears as webdata
-
- site = server.Site(Toplevel())
-
- reactor.listenTCP(80, channel.HTTPFactory(site))
-
-def autostart(reason, **kwargs):
- if "session" in kwargs:
- global sessions
- sessions.append(kwargs["session"])
- return
-
- if reason == 0:
- try:
- startWebserver()
- except ImportError:
- print "twisted not available, not starting web services"
-
-def Plugins(**kwargs):
- return PluginDescriptor(where = [PluginDescriptor.WHERE_SESSIONSTART, PluginDescriptor.WHERE_AUTOSTART], fnc = autostart)
+++ /dev/null
-/* Prototype JavaScript framework, version 1.4.0
- * (c) 2005 Sam Stephenson <sam@conio.net>
- *
- * 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: '(?:<script.*?>)((\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 '#<Enumerable:' + this.toArray().inspect() + '>';
- }
-}
-
-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 '#<Hash:{' + this.map(function(pair) {
- return pair.map(Object.inspect).join(': ');
- }).join(', ') + '}>';
- }
-}
-
-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 = '<table><tbody>' + this.content + '</tbody></table>';
- 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
+++ /dev/null
-/**
- *
- * Copyright 2005 Sabre Airline Solutions
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
- * file except in compliance with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the
- * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
- * either express or implied. See the License for the specific language governing permissions
- * and limitations under the License.
- **/
-
-
-//-------------------- rico.js
-var Rico = {
- Version: '1.1.2',
- prototypeVersion: parseFloat(Prototype.Version.split(".")[0] + "." + Prototype.Version.split(".")[1])
-}
-
-if((typeof Prototype=='undefined') || Rico.prototypeVersion < 1.3)
- throw("Rico requires the Prototype JavaScript framework >= 1.3");
-
-Rico.ArrayExtensions = new Array();
-
-if (Object.prototype.extend) {
- Rico.ArrayExtensions[ Rico.ArrayExtensions.length ] = Object.prototype.extend;
-}else{
- Object.prototype.extend = function(object) {
- return Object.extend.apply(this, [this, object]);
- }
- Rico.ArrayExtensions[ Rico.ArrayExtensions.length ] = Object.prototype.extend;
-}
-
-if (Array.prototype.push) {
- Rico.ArrayExtensions[ Rico.ArrayExtensions.length ] = Array.prototype.push;
-}
-
-if (!Array.prototype.remove) {
- Array.prototype.remove = function(dx) {
- if( isNaN(dx) || dx > this.length )
- return false;
- for( var i=0,n=0; i<this.length; i++ )
- if( i != dx )
- this[n++]=this[i];
- this.length-=1;
- };
- Rico.ArrayExtensions[ Rico.ArrayExtensions.length ] = Array.prototype.remove;
-}
-
-if (!Array.prototype.removeItem) {
- Array.prototype.removeItem = function(item) {
- for ( var i = 0 ; i < this.length ; i++ )
- if ( this[i] == item ) {
- this.remove(i);
- break;
- }
- };
- Rico.ArrayExtensions[ Rico.ArrayExtensions.length ] = Array.prototype.removeItem;
-}
-
-if (!Array.prototype.indices) {
- Array.prototype.indices = function() {
- var indexArray = new Array();
- for ( index in this ) {
- var ignoreThis = false;
- for ( var i = 0 ; i < Rico.ArrayExtensions.length ; i++ ) {
- if ( this[index] == Rico.ArrayExtensions[i] ) {
- ignoreThis = true;
- break;
- }
- }
- if ( !ignoreThis )
- indexArray[ indexArray.length ] = index;
- }
- return indexArray;
- }
- Rico.ArrayExtensions[ Rico.ArrayExtensions.length ] = Array.prototype.indices;
-}
-
-// Create the loadXML method and xml getter for Mozilla
-if ( window.DOMParser &&
- window.XMLSerializer &&
- window.Node && Node.prototype && Node.prototype.__defineGetter__ ) {
-
- if (!Document.prototype.loadXML) {
- Document.prototype.loadXML = function (s) {
- var doc2 = (new DOMParser()).parseFromString(s, "text/xml");
- while (this.hasChildNodes())
- this.removeChild(this.lastChild);
-
- for (var i = 0; i < doc2.childNodes.length; i++) {
- this.appendChild(this.importNode(doc2.childNodes[i], true));
- }
- };
- }
-
- Document.prototype.__defineGetter__( "xml",
- function () {
- return (new XMLSerializer()).serializeToString(this);
- }
- );
-}
-
-document.getElementsByTagAndClassName = function(tagName, className) {
- if ( tagName == null )
- tagName = '*';
-
- var children = document.getElementsByTagName(tagName) || document.all;
- var elements = new Array();
-
- if ( className == null )
- return children;
-
- for (var i = 0; i < children.length; i++) {
- var child = children[i];
- var classNames = child.className.split(' ');
- for (var j = 0; j < classNames.length; j++) {
- if (classNames[j] == className) {
- elements.push(child);
- break;
- }
- }
- }
-
- return elements;
-}
-
-
-//-------------------- ricoAccordion.js
-Rico.Accordion = Class.create();
-
-Rico.Accordion.prototype = {
-
- initialize: function(container, options) {
- this.container = $(container);
- this.lastExpandedTab = null;
- this.accordionTabs = new Array();
- this.setOptions(options);
- this._attachBehaviors();
- if(!container) return;
-
- this.container.style.borderBottom = '1px solid ' + this.options.borderColor;
- // validate onloadShowTab
- if (this.options.onLoadShowTab >= this.accordionTabs.length)
- this.options.onLoadShowTab = 0;
-
- // set the initial visual state...
- for ( var i=0 ; i < this.accordionTabs.length ; i++ )
- {
- if (i != this.options.onLoadShowTab){
- this.accordionTabs[i].collapse();
- this.accordionTabs[i].content.style.display = 'none';
- }
- }
- this.lastExpandedTab = this.accordionTabs[this.options.onLoadShowTab];
- if (this.options.panelHeight == 'auto'){
- var tabToCheck = (this.options.onloadShowTab === 0)? 1 : 0;
- var titleBarSize = parseInt(RicoUtil.getElementsComputedStyle(this.accordionTabs[tabToCheck].titleBar, 'height'));
- if (isNaN(titleBarSize))
- titleBarSize = this.accordionTabs[tabToCheck].titleBar.offsetHeight;
-
- var totalTitleBarSize = this.accordionTabs.length * titleBarSize;
- var parentHeight = parseInt(RicoUtil.getElementsComputedStyle(this.container.parentNode, 'height'));
- if (isNaN(parentHeight))
- parentHeight = this.container.parentNode.offsetHeight;
-
- this.options.panelHeight = parentHeight - totalTitleBarSize-2;
- }
-
- this.lastExpandedTab.content.style.height = this.options.panelHeight + "px";
- this.lastExpandedTab.showExpanded();
- this.lastExpandedTab.titleBar.style.fontWeight = this.options.expandedFontWeight;
-
- },
-
- setOptions: function(options) {
- this.options = {
- expandedBg : '#63699c',
- hoverBg : '#63699c',
- collapsedBg : '#6b79a5',
- expandedTextColor : '#ffffff',
- expandedFontWeight : 'bold',
- hoverTextColor : '#ffffff',
- collapsedTextColor : '#ced7ef',
- collapsedFontWeight : 'normal',
- hoverTextColor : '#ffffff',
- borderColor : '#1f669b',
- panelHeight : 200,
- onHideTab : null,
- onShowTab : null,
- onLoadShowTab : 0
- }
- Object.extend(this.options, options || {});
- },
-
- showTabByIndex: function( anIndex, animate ) {
- var doAnimate = arguments.length == 1 ? true : animate;
- this.showTab( this.accordionTabs[anIndex], doAnimate );
- },
-
- showTab: function( accordionTab, animate ) {
- if ( this.lastExpandedTab == accordionTab )
- return;
-
- var doAnimate = arguments.length == 1 ? true : animate;
-
- if ( this.options.onHideTab )
- this.options.onHideTab(this.lastExpandedTab);
-
- this.lastExpandedTab.showCollapsed();
- var accordion = this;
- var lastExpandedTab = this.lastExpandedTab;
-
- this.lastExpandedTab.content.style.height = (this.options.panelHeight - 1) + 'px';
- accordionTab.content.style.display = '';
-
- accordionTab.titleBar.style.fontWeight = this.options.expandedFontWeight;
-
- if ( doAnimate ) {
- new Rico.Effect.AccordionSize( this.lastExpandedTab.content,
- accordionTab.content,
- 1,
- this.options.panelHeight,
- 100, 10,
- { complete: function() {accordion.showTabDone(lastExpandedTab)} } );
- this.lastExpandedTab = accordionTab;
- }
- else {
- this.lastExpandedTab.content.style.height = "1px";
- accordionTab.content.style.height = this.options.panelHeight + "px";
- this.lastExpandedTab = accordionTab;
- this.showTabDone(lastExpandedTab);
- }
- },
-
- showTabDone: function(collapsedTab) {
- collapsedTab.content.style.display = 'none';
- this.lastExpandedTab.showExpanded();
- if ( this.options.onShowTab )
- this.options.onShowTab(this.lastExpandedTab);
- },
-
- _attachBehaviors: function() {
- var panels = this._getDirectChildrenByTag(this.container, 'DIV');
- for ( var i = 0 ; i < panels.length ; i++ ) {
-
- var tabChildren = this._getDirectChildrenByTag(panels[i],'DIV');
- if ( tabChildren.length != 2 )
- continue; // unexpected
-
- var tabTitleBar = tabChildren[0];
- var tabContentBox = tabChildren[1];
- this.accordionTabs.push( new Rico.Accordion.Tab(this,tabTitleBar,tabContentBox) );
- }
- },
-
- _getDirectChildrenByTag: function(e, tagName) {
- var kids = new Array();
- var allKids = e.childNodes;
- for( var i = 0 ; i < allKids.length ; i++ )
- if ( allKids[i] && allKids[i].tagName && allKids[i].tagName == tagName )
- kids.push(allKids[i]);
- return kids;
- }
-
-};
-
-Rico.Accordion.Tab = Class.create();
-
-Rico.Accordion.Tab.prototype = {
-
- initialize: function(accordion, titleBar, content) {
- this.accordion = accordion;
- this.titleBar = titleBar;
- this.content = content;
- this._attachBehaviors();
- },
-
- collapse: function() {
- this.showCollapsed();
- this.content.style.height = "1px";
- },
-
- showCollapsed: function() {
- this.expanded = false;
- this.titleBar.style.backgroundColor = this.accordion.options.collapsedBg;
- this.titleBar.style.color = this.accordion.options.collapsedTextColor;
- this.titleBar.style.fontWeight = this.accordion.options.collapsedFontWeight;
- this.content.style.overflow = "hidden";
- },
-
- showExpanded: function() {
- this.expanded = true;
- this.titleBar.style.backgroundColor = this.accordion.options.expandedBg;
- this.titleBar.style.color = this.accordion.options.expandedTextColor;
- this.content.style.overflow = "auto";
- },
-
- titleBarClicked: function(e) {
- if ( this.accordion.lastExpandedTab == this )
- return;
- this.accordion.showTab(this);
- },
-
- hover: function(e) {
- this.titleBar.style.backgroundColor = this.accordion.options.hoverBg;
- this.titleBar.style.color = this.accordion.options.hoverTextColor;
- },
-
- unhover: function(e) {
- if ( this.expanded ) {
- this.titleBar.style.backgroundColor = this.accordion.options.expandedBg;
- this.titleBar.style.color = this.accordion.options.expandedTextColor;
- }
- else {
- this.titleBar.style.backgroundColor = this.accordion.options.collapsedBg;
- this.titleBar.style.color = this.accordion.options.collapsedTextColor;
- }
- },
-
- _attachBehaviors: function() {
- this.content.style.border = "1px solid " + this.accordion.options.borderColor;
- this.content.style.borderTopWidth = "0px";
- this.content.style.borderBottomWidth = "0px";
- this.content.style.margin = "0px";
-
- this.titleBar.onclick = this.titleBarClicked.bindAsEventListener(this);
- this.titleBar.onmouseover = this.hover.bindAsEventListener(this);
- this.titleBar.onmouseout = this.unhover.bindAsEventListener(this);
- }
-
-};
-
-
-//-------------------- ricoAjaxEngine.js
-Rico.AjaxEngine = Class.create();
-
-Rico.AjaxEngine.prototype = {
-
- initialize: function() {
- this.ajaxElements = new Array();
- this.ajaxObjects = new Array();
- this.requestURLS = new Array();
- this.options = {};
- },
-
- registerAjaxElement: function( anId, anElement ) {
- if ( !anElement )
- anElement = $(anId);
- this.ajaxElements[anId] = anElement;
- },
-
- registerAjaxObject: function( anId, anObject ) {
- this.ajaxObjects[anId] = anObject;
- },
-
- registerRequest: function (requestLogicalName, requestURL) {
- this.requestURLS[requestLogicalName] = requestURL;
- },
-
- sendRequest: function(requestName, options) {
- // Allow for backwards Compatibility
- if ( arguments.length >= 2 )
- if (typeof arguments[1] == 'string')
- options = {parameters: this._createQueryString(arguments, 1)};
- this.sendRequestWithData(requestName, null, options);
- },
-
- sendRequestWithData: function(requestName, xmlDocument, options) {
- var requestURL = this.requestURLS[requestName];
- if ( requestURL == null )
- return;
-
- // Allow for backwards Compatibility
- if ( arguments.length >= 3 )
- if (typeof arguments[2] == 'string')
- options.parameters = this._createQueryString(arguments, 2);
-
- new Ajax.Request(requestURL, this._requestOptions(options,xmlDocument));
- },
-
- sendRequestAndUpdate: function(requestName,container,options) {
- // Allow for backwards Compatibility
- if ( arguments.length >= 3 )
- if (typeof arguments[2] == 'string')
- options.parameters = this._createQueryString(arguments, 2);
-
- this.sendRequestWithDataAndUpdate(requestName, null, container, options);
- },
-
- sendRequestWithDataAndUpdate: function(requestName,xmlDocument,container,options) {
- var requestURL = this.requestURLS[requestName];
- if ( requestURL == null )
- return;
-
- // Allow for backwards Compatibility
- if ( arguments.length >= 4 )
- if (typeof arguments[3] == 'string')
- options.parameters = this._createQueryString(arguments, 3);
-
- var updaterOptions = this._requestOptions(options,xmlDocument);
-
- new Ajax.Updater(container, requestURL, updaterOptions);
- },
-
- // Private -- not part of intended engine API --------------------------------------------------------------------
-
- _requestOptions: function(options,xmlDoc) {
- var requestHeaders = ['X-Rico-Version', Rico.Version ];
- var sendMethod = 'post';
- if ( xmlDoc == null )
- if (Rico.prototypeVersion < 1.4)
- requestHeaders.push( 'Content-type', 'text/xml' );
- else
- sendMethod = 'get';
- (!options) ? options = {} : '';
-
- if (!options._RicoOptionsProcessed){
- // Check and keep any user onComplete functions
- if (options.onComplete)
- options.onRicoComplete = options.onComplete;
- // Fix onComplete
- if (options.overrideOnComplete)
- options.onComplete = options.overrideOnComplete;
- else
- options.onComplete = this._onRequestComplete.bind(this);
- options._RicoOptionsProcessed = true;
- }
-
- // Set the default options and extend with any user options
- this.options = {
- requestHeaders: requestHeaders,
- parameters: options.parameters,
- postBody: xmlDoc,
- method: sendMethod,
- onComplete: options.onComplete
- };
- // Set any user options:
- Object.extend(this.options, options);
- return this.options;
- },
-
- _createQueryString: function( theArgs, offset ) {
- var queryString = ""
- for ( var i = offset ; i < theArgs.length ; i++ ) {
- if ( i != offset )
- queryString += "&";
-
- var anArg = theArgs[i];
-
- if ( anArg.name != undefined && anArg.value != undefined ) {
- queryString += anArg.name + "=" + escape(anArg.value);
- }
- else {
- var ePos = anArg.indexOf('=');
- var argName = anArg.substring( 0, ePos );
- var argValue = anArg.substring( ePos + 1 );
- queryString += argName + "=" + escape(argValue);
- }
- }
- return queryString;
- },
-
- _onRequestComplete : function(request) {
- if(!request)
- return;
- // User can set an onFailure option - which will be called by prototype
- if (request.status != 200)
- return;
-
- var response = request.responseXML.getElementsByTagName("ajax-response");
- if (response == null || response.length != 1)
- return;
- this._processAjaxResponse( response[0].childNodes );
-
- // Check if user has set a onComplete function
- var onRicoComplete = this.options.onRicoComplete;
- if (onRicoComplete != null)
- onRicoComplete();
- },
-
- _processAjaxResponse: function( xmlResponseElements ) {
- for ( var i = 0 ; i < xmlResponseElements.length ; i++ ) {
- var responseElement = xmlResponseElements[i];
-
- // only process nodes of type element.....
- if ( responseElement.nodeType != 1 )
- continue;
-
- var responseType = responseElement.getAttribute("type");
- var responseId = responseElement.getAttribute("id");
-
- if ( responseType == "object" )
- this._processAjaxObjectUpdate( this.ajaxObjects[ responseId ], responseElement );
- else if ( responseType == "element" )
- this._processAjaxElementUpdate( this.ajaxElements[ responseId ], responseElement );
- else
- alert('unrecognized AjaxResponse type : ' + responseType );
- }
- },
-
- _processAjaxObjectUpdate: function( ajaxObject, responseElement ) {
- ajaxObject.ajaxUpdate( responseElement );
- },
-
- _processAjaxElementUpdate: function( ajaxElement, responseElement ) {
- ajaxElement.innerHTML = RicoUtil.getContentAsString(responseElement);
- }
-
-}
-
-var ajaxEngine = new Rico.AjaxEngine();
-
-
-//-------------------- ricoColor.js
-Rico.Color = Class.create();
-
-Rico.Color.prototype = {
-
- initialize: function(red, green, blue) {
- this.rgb = { r: red, g : green, b : blue };
- },
-
- setRed: function(r) {
- this.rgb.r = r;
- },
-
- setGreen: function(g) {
- this.rgb.g = g;
- },
-
- setBlue: function(b) {
- this.rgb.b = b;
- },
-
- setHue: function(h) {
-
- // get an HSB model, and set the new hue...
- var hsb = this.asHSB();
- hsb.h = h;
-
- // convert back to RGB...
- this.rgb = Rico.Color.HSBtoRGB(hsb.h, hsb.s, hsb.b);
- },
-
- setSaturation: function(s) {
- // get an HSB model, and set the new hue...
- var hsb = this.asHSB();
- hsb.s = s;
-
- // convert back to RGB and set values...
- this.rgb = Rico.Color.HSBtoRGB(hsb.h, hsb.s, hsb.b);
- },
-
- setBrightness: function(b) {
- // get an HSB model, and set the new hue...
- var hsb = this.asHSB();
- hsb.b = b;
-
- // convert back to RGB and set values...
- this.rgb = Rico.Color.HSBtoRGB( hsb.h, hsb.s, hsb.b );
- },
-
- darken: function(percent) {
- var hsb = this.asHSB();
- this.rgb = Rico.Color.HSBtoRGB(hsb.h, hsb.s, Math.max(hsb.b - percent,0));
- },
-
- brighten: function(percent) {
- var hsb = this.asHSB();
- this.rgb = Rico.Color.HSBtoRGB(hsb.h, hsb.s, Math.min(hsb.b + percent,1));
- },
-
- blend: function(other) {
- this.rgb.r = Math.floor((this.rgb.r + other.rgb.r)/2);
- this.rgb.g = Math.floor((this.rgb.g + other.rgb.g)/2);
- this.rgb.b = Math.floor((this.rgb.b + other.rgb.b)/2);
- },
-
- isBright: function() {
- var hsb = this.asHSB();
- return this.asHSB().b > 0.5;
- },
-
- isDark: function() {
- return ! this.isBright();
- },
-
- asRGB: function() {
- return "rgb(" + this.rgb.r + "," + this.rgb.g + "," + this.rgb.b + ")";
- },
-
- asHex: function() {
- return "#" + this.rgb.r.toColorPart() + this.rgb.g.toColorPart() + this.rgb.b.toColorPart();
- },
-
- asHSB: function() {
- return Rico.Color.RGBtoHSB(this.rgb.r, this.rgb.g, this.rgb.b);
- },
-
- toString: function() {
- return this.asHex();
- }
-
-};
-
-Rico.Color.createFromHex = function(hexCode) {
- if(hexCode.length==4) {
- var shortHexCode = hexCode;
- var hexCode = '#';
- for(var i=1;i<4;i++) hexCode += (shortHexCode.charAt(i) +
-shortHexCode.charAt(i));
- }
- if ( hexCode.indexOf('#') == 0 )
- hexCode = hexCode.substring(1);
- var red = hexCode.substring(0,2);
- var green = hexCode.substring(2,4);
- var blue = hexCode.substring(4,6);
- return new Rico.Color( parseInt(red,16), parseInt(green,16), parseInt(blue,16) );
-}
-
-/**
- * Factory method for creating a color from the background of
- * an HTML element.
- */
-Rico.Color.createColorFromBackground = function(elem) {
-
- var actualColor = RicoUtil.getElementsComputedStyle($(elem), "backgroundColor", "background-color");
-
- if ( actualColor == "transparent" && elem.parentNode )
- return Rico.Color.createColorFromBackground(elem.parentNode);
-
- if ( actualColor == null )
- return new Rico.Color(255,255,255);
-
- if ( actualColor.indexOf("rgb(") == 0 ) {
- var colors = actualColor.substring(4, actualColor.length - 1 );
- var colorArray = colors.split(",");
- return new Rico.Color( parseInt( colorArray[0] ),
- parseInt( colorArray[1] ),
- parseInt( colorArray[2] ) );
-
- }
- else if ( actualColor.indexOf("#") == 0 ) {
- return Rico.Color.createFromHex(actualColor);
- }
- else
- return new Rico.Color(255,255,255);
-}
-
-Rico.Color.HSBtoRGB = function(hue, saturation, brightness) {
-
- var red = 0;
- var green = 0;
- var blue = 0;
-
- if (saturation == 0) {
- red = parseInt(brightness * 255.0 + 0.5);
- green = red;
- blue = red;
- }
- else {
- var h = (hue - Math.floor(hue)) * 6.0;
- var f = h - Math.floor(h);
- var p = brightness * (1.0 - saturation);
- var q = brightness * (1.0 - saturation * f);
- var t = brightness * (1.0 - (saturation * (1.0 - f)));
-
- switch (parseInt(h)) {
- case 0:
- red = (brightness * 255.0 + 0.5);
- green = (t * 255.0 + 0.5);
- blue = (p * 255.0 + 0.5);
- break;
- case 1:
- red = (q * 255.0 + 0.5);
- green = (brightness * 255.0 + 0.5);
- blue = (p * 255.0 + 0.5);
- break;
- case 2:
- red = (p * 255.0 + 0.5);
- green = (brightness * 255.0 + 0.5);
- blue = (t * 255.0 + 0.5);
- break;
- case 3:
- red = (p * 255.0 + 0.5);
- green = (q * 255.0 + 0.5);
- blue = (brightness * 255.0 + 0.5);
- break;
- case 4:
- red = (t * 255.0 + 0.5);
- green = (p * 255.0 + 0.5);
- blue = (brightness * 255.0 + 0.5);
- break;
- case 5:
- red = (brightness * 255.0 + 0.5);
- green = (p * 255.0 + 0.5);
- blue = (q * 255.0 + 0.5);
- break;
- }
- }
-
- return { r : parseInt(red), g : parseInt(green) , b : parseInt(blue) };
-}
-
-Rico.Color.RGBtoHSB = function(r, g, b) {
-
- var hue;
- var saturation;
- var brightness;
-
- var cmax = (r > g) ? r : g;
- if (b > cmax)
- cmax = b;
-
- var cmin = (r < g) ? r : g;
- if (b < cmin)
- cmin = b;
-
- brightness = cmax / 255.0;
- if (cmax != 0)
- saturation = (cmax - cmin)/cmax;
- else
- saturation = 0;
-
- if (saturation == 0)
- hue = 0;
- else {
- var redc = (cmax - r)/(cmax - cmin);
- var greenc = (cmax - g)/(cmax - cmin);
- var bluec = (cmax - b)/(cmax - cmin);
-
- if (r == cmax)
- hue = bluec - greenc;
- else if (g == cmax)
- hue = 2.0 + redc - bluec;
- else
- hue = 4.0 + greenc - redc;
-
- hue = hue / 6.0;
- if (hue < 0)
- hue = hue + 1.0;
- }
-
- return { h : hue, s : saturation, b : brightness };
-}
-
-
-//-------------------- ricoCorner.js
-Rico.Corner = {
-
- round: function(e, options) {
- var e = $(e);
- this._setOptions(options);
-
- var color = this.options.color;
- if ( this.options.color == "fromElement" )
- color = this._background(e);
-
- var bgColor = this.options.bgColor;
- if ( this.options.bgColor == "fromParent" )
- bgColor = this._background(e.offsetParent);
-
- this._roundCornersImpl(e, color, bgColor);
- },
-
- _roundCornersImpl: function(e, color, bgColor) {
- if(this.options.border)
- this._renderBorder(e,bgColor);
- if(this._isTopRounded())
- this._roundTopCorners(e,color,bgColor);
- if(this._isBottomRounded())
- this._roundBottomCorners(e,color,bgColor);
- },
-
- _renderBorder: function(el,bgColor) {
- var borderValue = "1px solid " + this._borderColor(bgColor);
- var borderL = "border-left: " + borderValue;
- var borderR = "border-right: " + borderValue;
- var style = "style='" + borderL + ";" + borderR + "'";
- el.innerHTML = "<div " + style + ">" + el.innerHTML + "</div>"
- },
-
- _roundTopCorners: function(el, color, bgColor) {
- var corner = this._createCorner(bgColor);
- for(var i=0 ; i < this.options.numSlices ; i++ )
- corner.appendChild(this._createCornerSlice(color,bgColor,i,"top"));
- el.style.paddingTop = 0;
- el.insertBefore(corner,el.firstChild);
- },
-
- _roundBottomCorners: function(el, color, bgColor) {
- var corner = this._createCorner(bgColor);
- for(var i=(this.options.numSlices-1) ; i >= 0 ; i-- )
- corner.appendChild(this._createCornerSlice(color,bgColor,i,"bottom"));
- el.style.paddingBottom = 0;
- el.appendChild(corner);
- },
-
- _createCorner: function(bgColor) {
- var corner = document.createElement("div");
- corner.style.backgroundColor = (this._isTransparent() ? "transparent" : bgColor);
- return corner;
- },
-
- _createCornerSlice: function(color,bgColor, n, position) {
- var slice = document.createElement("span");
-
- var inStyle = slice.style;
- inStyle.backgroundColor = color;
- inStyle.display = "block";
- inStyle.height = "1px";
- inStyle.overflow = "hidden";
- inStyle.fontSize = "1px";
-
- var borderColor = this._borderColor(color,bgColor);
- if ( this.options.border && n == 0 ) {
- inStyle.borderTopStyle = "solid";
- inStyle.borderTopWidth = "1px";
- inStyle.borderLeftWidth = "0px";
- inStyle.borderRightWidth = "0px";
- inStyle.borderBottomWidth = "0px";
- inStyle.height = "0px"; // assumes css compliant box model
- inStyle.borderColor = borderColor;
- }
- else if(borderColor) {
- inStyle.borderColor = borderColor;
- inStyle.borderStyle = "solid";
- inStyle.borderWidth = "0px 1px";
- }
-
- if ( !this.options.compact && (n == (this.options.numSlices-1)) )
- inStyle.height = "2px";
-
- this._setMargin(slice, n, position);
- this._setBorder(slice, n, position);
- return slice;
- },
-
- _setOptions: function(options) {
- this.options = {
- corners : "all",
- color : "fromElement",
- bgColor : "fromParent",
- blend : true,
- border : false,
- compact : false
- }
- Object.extend(this.options, options || {});
-
- this.options.numSlices = this.options.compact ? 2 : 4;
- if ( this._isTransparent() )
- this.options.blend = false;
- },
-
- _whichSideTop: function() {
- if ( this._hasString(this.options.corners, "all", "top") )
- return "";
-
- if ( this.options.corners.indexOf("tl") >= 0 && this.options.corners.indexOf("tr") >= 0 )
- return "";
-
- if (this.options.corners.indexOf("tl") >= 0)
- return "left";
- else if (this.options.corners.indexOf("tr") >= 0)
- return "right";
- return "";
- },
-
- _whichSideBottom: function() {
- if ( this._hasString(this.options.corners, "all", "bottom") )
- return "";
-
- if ( this.options.corners.indexOf("bl")>=0 && this.options.corners.indexOf("br")>=0 )
- return "";
-
- if(this.options.corners.indexOf("bl") >=0)
- return "left";
- else if(this.options.corners.indexOf("br")>=0)
- return "right";
- return "";
- },
-
- _borderColor : function(color,bgColor) {
- if ( color == "transparent" )
- return bgColor;
- else if ( this.options.border )
- return this.options.border;
- else if ( this.options.blend )
- return this._blend( bgColor, color );
- else
- return "";
- },
-
-
- _setMargin: function(el, n, corners) {
- var marginSize = this._marginSize(n);
- var whichSide = corners == "top" ? this._whichSideTop() : this._whichSideBottom();
-
- if ( whichSide == "left" ) {
- el.style.marginLeft = marginSize + "px"; el.style.marginRight = "0px";
- }
- else if ( whichSide == "right" ) {
- el.style.marginRight = marginSize + "px"; el.style.marginLeft = "0px";
- }
- else {
- el.style.marginLeft = marginSize + "px"; el.style.marginRight = marginSize + "px";
- }
- },
-
- _setBorder: function(el,n,corners) {
- var borderSize = this._borderSize(n);
- var whichSide = corners == "top" ? this._whichSideTop() : this._whichSideBottom();
- if ( whichSide == "left" ) {
- el.style.borderLeftWidth = borderSize + "px"; el.style.borderRightWidth = "0px";
- }
- else if ( whichSide == "right" ) {
- el.style.borderRightWidth = borderSize + "px"; el.style.borderLeftWidth = "0px";
- }
- else {
- el.style.borderLeftWidth = borderSize + "px"; el.style.borderRightWidth = borderSize + "px";
- }
- if (this.options.border != false)
- el.style.borderLeftWidth = borderSize + "px"; el.style.borderRightWidth = borderSize + "px";
- },
-
- _marginSize: function(n) {
- if ( this._isTransparent() )
- return 0;
-
- var marginSizes = [ 5, 3, 2, 1 ];
- var blendedMarginSizes = [ 3, 2, 1, 0 ];
- var compactMarginSizes = [ 2, 1 ];
- var smBlendedMarginSizes = [ 1, 0 ];
-
- if ( this.options.compact && this.options.blend )
- return smBlendedMarginSizes[n];
- else if ( this.options.compact )
- return compactMarginSizes[n];
- else if ( this.options.blend )
- return blendedMarginSizes[n];
- else
- return marginSizes[n];
- },
-
- _borderSize: function(n) {
- var transparentBorderSizes = [ 5, 3, 2, 1 ];
- var blendedBorderSizes = [ 2, 1, 1, 1 ];
- var compactBorderSizes = [ 1, 0 ];
- var actualBorderSizes = [ 0, 2, 0, 0 ];
-
- if ( this.options.compact && (this.options.blend || this._isTransparent()) )
- return 1;
- else if ( this.options.compact )
- return compactBorderSizes[n];
- else if ( this.options.blend )
- return blendedBorderSizes[n];
- else if ( this.options.border )
- return actualBorderSizes[n];
- else if ( this._isTransparent() )
- return transparentBorderSizes[n];
- return 0;
- },
-
- _hasString: function(str) { for(var i=1 ; i<arguments.length ; i++) if (str.indexOf(arguments[i]) >= 0) return true; return false; },
- _blend: function(c1, c2) { var cc1 = Rico.Color.createFromHex(c1); cc1.blend(Rico.Color.createFromHex(c2)); return cc1; },
- _background: function(el) { try { return Rico.Color.createColorFromBackground(el).asHex(); } catch(err) { return "#ffffff"; } },
- _isTransparent: function() { return this.options.color == "transparent"; },
- _isTopRounded: function() { return this._hasString(this.options.corners, "all", "top", "tl", "tr"); },
- _isBottomRounded: function() { return this._hasString(this.options.corners, "all", "bottom", "bl", "br"); },
- _hasSingleTextChild: function(el) { return el.childNodes.length == 1 && el.childNodes[0].nodeType == 3; }
-}
-
-
-//-------------------- ricoDragAndDrop.js
-Rico.DragAndDrop = Class.create();
-
-Rico.DragAndDrop.prototype = {
-
- initialize: function() {
- this.dropZones = new Array();
- this.draggables = new Array();
- this.currentDragObjects = new Array();
- this.dragElement = null;
- this.lastSelectedDraggable = null;
- this.currentDragObjectVisible = false;
- this.interestedInMotionEvents = false;
- this._mouseDown = this._mouseDownHandler.bindAsEventListener(this);
- this._mouseMove = this._mouseMoveHandler.bindAsEventListener(this);
- this._mouseUp = this._mouseUpHandler.bindAsEventListener(this);
- },
-
- registerDropZone: function(aDropZone) {
- this.dropZones[ this.dropZones.length ] = aDropZone;
- },
-
- deregisterDropZone: function(aDropZone) {
- var newDropZones = new Array();
- var j = 0;
- for ( var i = 0 ; i < this.dropZones.length ; i++ ) {
- if ( this.dropZones[i] != aDropZone )
- newDropZones[j++] = this.dropZones[i];
- }
-
- this.dropZones = newDropZones;
- },
-
- clearDropZones: function() {
- this.dropZones = new Array();
- },
-
- registerDraggable: function( aDraggable ) {
- this.draggables[ this.draggables.length ] = aDraggable;
- this._addMouseDownHandler( aDraggable );
- },
-
- clearSelection: function() {
- for ( var i = 0 ; i < this.currentDragObjects.length ; i++ )
- this.currentDragObjects[i].deselect();
- this.currentDragObjects = new Array();
- this.lastSelectedDraggable = null;
- },
-
- hasSelection: function() {
- return this.currentDragObjects.length > 0;
- },
-
- setStartDragFromElement: function( e, mouseDownElement ) {
- this.origPos = RicoUtil.toDocumentPosition(mouseDownElement);
- this.startx = e.screenX - this.origPos.x
- this.starty = e.screenY - this.origPos.y
- //this.startComponentX = e.layerX ? e.layerX : e.offsetX;
- //this.startComponentY = e.layerY ? e.layerY : e.offsetY;
- //this.adjustedForDraggableSize = false;
-
- this.interestedInMotionEvents = this.hasSelection();
- this._terminateEvent(e);
- },
-
- updateSelection: function( draggable, extendSelection ) {
- if ( ! extendSelection )
- this.clearSelection();
-
- if ( draggable.isSelected() ) {
- this.currentDragObjects.removeItem(draggable);
- draggable.deselect();
- if ( draggable == this.lastSelectedDraggable )
- this.lastSelectedDraggable = null;
- }
- else {
- this.currentDragObjects[ this.currentDragObjects.length ] = draggable;
- draggable.select();
- this.lastSelectedDraggable = draggable;
- }
- },
-
- _mouseDownHandler: function(e) {
- if ( arguments.length == 0 )
- e = event;
-
- // if not button 1 ignore it...
- var nsEvent = e.which != undefined;
- if ( (nsEvent && e.which != 1) || (!nsEvent && e.button != 1))
- return;
-
- var eventTarget = e.target ? e.target : e.srcElement;
- var draggableObject = eventTarget.draggable;
-
- var candidate = eventTarget;
- while (draggableObject == null && candidate.parentNode) {
- candidate = candidate.parentNode;
- draggableObject = candidate.draggable;
- }
-
- if ( draggableObject == null )
- return;
-
- this.updateSelection( draggableObject, e.ctrlKey );
-
- // clear the drop zones postion cache...
- if ( this.hasSelection() )
- for ( var i = 0 ; i < this.dropZones.length ; i++ )
- this.dropZones[i].clearPositionCache();
-
- this.setStartDragFromElement( e, draggableObject.getMouseDownHTMLElement() );
- },
-
-
- _mouseMoveHandler: function(e) {
- var nsEvent = e.which != undefined;
- if ( !this.interestedInMotionEvents ) {
- //this._terminateEvent(e);
- return;
- }
-
- if ( ! this.hasSelection() )
- return;
-
- if ( ! this.currentDragObjectVisible )
- this._startDrag(e);
-
- if ( !this.activatedDropZones )
- this._activateRegisteredDropZones();
-
- //if ( !this.adjustedForDraggableSize )
- // this._adjustForDraggableSize(e);
-
- this._updateDraggableLocation(e);
- this._updateDropZonesHover(e);
-
- this._terminateEvent(e);
- },
-
- _makeDraggableObjectVisible: function(e)
- {
- if ( !this.hasSelection() )
- return;
-
- var dragElement;
- if ( this.currentDragObjects.length > 1 )
- dragElement = this.currentDragObjects[0].getMultiObjectDragGUI(this.currentDragObjects);
- else
- dragElement = this.currentDragObjects[0].getSingleObjectDragGUI();
-
- // go ahead and absolute position it...
- if ( RicoUtil.getElementsComputedStyle(dragElement, "position") != "absolute" )
- dragElement.style.position = "absolute";
-
- // need to parent him into the document...
- if ( dragElement.parentNode == null || dragElement.parentNode.nodeType == 11 )
- document.body.appendChild(dragElement);
-
- this.dragElement = dragElement;
- this._updateDraggableLocation(e);
-
- this.currentDragObjectVisible = true;
- },
-
- /**
- _adjustForDraggableSize: function(e) {
- var dragElementWidth = this.dragElement.offsetWidth;
- var dragElementHeight = this.dragElement.offsetHeight;
- if ( this.startComponentX > dragElementWidth )
- this.startx -= this.startComponentX - dragElementWidth + 2;
- if ( e.offsetY ) {
- if ( this.startComponentY > dragElementHeight )
- this.starty -= this.startComponentY - dragElementHeight + 2;
- }
- this.adjustedForDraggableSize = true;
- },
- **/
-
- _leftOffset: function(e) {
- return e.offsetX ? document.body.scrollLeft : 0
- },
-
- _topOffset: function(e) {
- return e.offsetY ? document.body.scrollTop:0
- },
-
-
- _updateDraggableLocation: function(e) {
- var dragObjectStyle = this.dragElement.style;
- dragObjectStyle.left = (e.screenX + this._leftOffset(e) - this.startx) + "px"
- dragObjectStyle.top = (e.screenY + this._topOffset(e) - this.starty) + "px";
- },
-
- _updateDropZonesHover: function(e) {
- var n = this.dropZones.length;
- for ( var i = 0 ; i < n ; i++ ) {
- if ( ! this._mousePointInDropZone( e, this.dropZones[i] ) )
- this.dropZones[i].hideHover();
- }
-
- for ( var i = 0 ; i < n ; i++ ) {
- if ( this._mousePointInDropZone( e, this.dropZones[i] ) ) {
- if ( this.dropZones[i].canAccept(this.currentDragObjects) )
- this.dropZones[i].showHover();
- }
- }
- },
-
- _startDrag: function(e) {
- for ( var i = 0 ; i < this.currentDragObjects.length ; i++ )
- this.currentDragObjects[i].startDrag();
-
- this._makeDraggableObjectVisible(e);
- },
-
- _mouseUpHandler: function(e) {
- if ( ! this.hasSelection() )
- return;
-
- var nsEvent = e.which != undefined;
- if ( (nsEvent && e.which != 1) || (!nsEvent && e.button != 1))
- return;
-
- this.interestedInMotionEvents = false;
-
- if ( this.dragElement == null ) {
- this._terminateEvent(e);
- return;
- }
-
- if ( this._placeDraggableInDropZone(e) )
- this._completeDropOperation(e);
- else {
- this._terminateEvent(e);
- new Rico.Effect.Position( this.dragElement,
- this.origPos.x,
- this.origPos.y,
- 200,
- 20,
- { complete : this._doCancelDragProcessing.bind(this) } );
- }
-
- Event.stopObserving(document.body, "mousemove", this._mouseMove);
- Event.stopObserving(document.body, "mouseup", this._mouseUp);
- },
-
- _retTrue: function () {
- return true;
- },
-
- _completeDropOperation: function(e) {
- if ( this.dragElement != this.currentDragObjects[0].getMouseDownHTMLElement() ) {
- if ( this.dragElement.parentNode != null )
- this.dragElement.parentNode.removeChild(this.dragElement);
- }
-
- this._deactivateRegisteredDropZones();
- this._endDrag();
- this.clearSelection();
- this.dragElement = null;
- this.currentDragObjectVisible = false;
- this._terminateEvent(e);
- },
-
- _doCancelDragProcessing: function() {
- this._cancelDrag();
-
- if ( this.dragElement != this.currentDragObjects[0].getMouseDownHTMLElement() && this.dragElement)
- if ( this.dragElement.parentNode != null )
- this.dragElement.parentNode.removeChild(this.dragElement);
-
-
- this._deactivateRegisteredDropZones();
- this.dragElement = null;
- this.currentDragObjectVisible = false;
- },
-
- _placeDraggableInDropZone: function(e) {
- var foundDropZone = false;
- var n = this.dropZones.length;
- for ( var i = 0 ; i < n ; i++ ) {
- if ( this._mousePointInDropZone( e, this.dropZones[i] ) ) {
- if ( this.dropZones[i].canAccept(this.currentDragObjects) ) {
- this.dropZones[i].hideHover();
- this.dropZones[i].accept(this.currentDragObjects);
- foundDropZone = true;
- break;
- }
- }
- }
-
- return foundDropZone;
- },
-
- _cancelDrag: function() {
- for ( var i = 0 ; i < this.currentDragObjects.length ; i++ )
- this.currentDragObjects[i].cancelDrag();
- },
-
- _endDrag: function() {
- for ( var i = 0 ; i < this.currentDragObjects.length ; i++ )
- this.currentDragObjects[i].endDrag();
- },
-
- _mousePointInDropZone: function( e, dropZone ) {
-
- var absoluteRect = dropZone.getAbsoluteRect();
-
- return e.clientX > absoluteRect.left + this._leftOffset(e) &&
- e.clientX < absoluteRect.right + this._leftOffset(e) &&
- e.clientY > absoluteRect.top + this._topOffset(e) &&
- e.clientY < absoluteRect.bottom + this._topOffset(e);
- },
-
- _addMouseDownHandler: function( aDraggable )
- {
- htmlElement = aDraggable.getMouseDownHTMLElement();
- if ( htmlElement != null ) {
- htmlElement.draggable = aDraggable;
- Event.observe(htmlElement , "mousedown", this._onmousedown.bindAsEventListener(this));
- Event.observe(htmlElement, "mousedown", this._mouseDown);
- }
- },
-
- _activateRegisteredDropZones: function() {
- var n = this.dropZones.length;
- for ( var i = 0 ; i < n ; i++ ) {
- var dropZone = this.dropZones[i];
- if ( dropZone.canAccept(this.currentDragObjects) )
- dropZone.activate();
- }
-
- this.activatedDropZones = true;
- },
-
- _deactivateRegisteredDropZones: function() {
- var n = this.dropZones.length;
- for ( var i = 0 ; i < n ; i++ )
- this.dropZones[i].deactivate();
- this.activatedDropZones = false;
- },
-
- _onmousedown: function () {
- Event.observe(document.body, "mousemove", this._mouseMove);
- Event.observe(document.body, "mouseup", this._mouseUp);
- },
-
- _terminateEvent: function(e) {
- if ( e.stopPropagation != undefined )
- e.stopPropagation();
- else if ( e.cancelBubble != undefined )
- e.cancelBubble = true;
-
- if ( e.preventDefault != undefined )
- e.preventDefault();
- else
- e.returnValue = false;
- },
-
-
- initializeEventHandlers: function() {
- if ( typeof document.implementation != "undefined" &&
- document.implementation.hasFeature("HTML", "1.0") &&
- document.implementation.hasFeature("Events", "2.0") &&
- document.implementation.hasFeature("CSS", "2.0") ) {
- document.addEventListener("mouseup", this._mouseUpHandler.bindAsEventListener(this), false);
- document.addEventListener("mousemove", this._mouseMoveHandler.bindAsEventListener(this), false);
- }
- else {
- document.attachEvent( "onmouseup", this._mouseUpHandler.bindAsEventListener(this) );
- document.attachEvent( "onmousemove", this._mouseMoveHandler.bindAsEventListener(this) );
- }
- }
- }
-
- var dndMgr = new Rico.DragAndDrop();
- dndMgr.initializeEventHandlers();
-
-
-//-------------------- ricoDraggable.js
-Rico.Draggable = Class.create();
-
-Rico.Draggable.prototype = {
-
- initialize: function( type, htmlElement ) {
- this.type = type;
- this.htmlElement = $(htmlElement);
- this.selected = false;
- },
-
- /**
- * Returns the HTML element that should have a mouse down event
- * added to it in order to initiate a drag operation
- *
- **/
- getMouseDownHTMLElement: function() {
- return this.htmlElement;
- },
-
- select: function() {
- this.selected = true;
-
- if ( this.showingSelected )
- return;
-
- var htmlElement = this.getMouseDownHTMLElement();
-
- var color = Rico.Color.createColorFromBackground(htmlElement);
- color.isBright() ? color.darken(0.033) : color.brighten(0.033);
-
- this.saveBackground = RicoUtil.getElementsComputedStyle(htmlElement, "backgroundColor", "background-color");
- htmlElement.style.backgroundColor = color.asHex();
- this.showingSelected = true;
- },
-
- deselect: function() {
- this.selected = false;
- if ( !this.showingSelected )
- return;
-
- var htmlElement = this.getMouseDownHTMLElement();
-
- htmlElement.style.backgroundColor = this.saveBackground;
- this.showingSelected = false;
- },
-
- isSelected: function() {
- return this.selected;
- },
-
- startDrag: function() {
- },
-
- cancelDrag: function() {
- },
-
- endDrag: function() {
- },
-
- getSingleObjectDragGUI: function() {
- return this.htmlElement;
- },
-
- getMultiObjectDragGUI: function( draggables ) {
- return this.htmlElement;
- },
-
- getDroppedGUI: function() {
- return this.htmlElement;
- },
-
- toString: function() {
- return this.type + ":" + this.htmlElement + ":";
- }
-
-}
-
-
-//-------------------- ricoDropzone.js
-Rico.Dropzone = Class.create();
-
-Rico.Dropzone.prototype = {
-
- initialize: function( htmlElement ) {
- this.htmlElement = $(htmlElement);
- this.absoluteRect = null;
- },
-
- getHTMLElement: function() {
- return this.htmlElement;
- },
-
- clearPositionCache: function() {
- this.absoluteRect = null;
- },
-
- getAbsoluteRect: function() {
- if ( this.absoluteRect == null ) {
- var htmlElement = this.getHTMLElement();
- var pos = RicoUtil.toViewportPosition(htmlElement);
-
- this.absoluteRect = {
- top: pos.y,
- left: pos.x,
- bottom: pos.y + htmlElement.offsetHeight,
- right: pos.x + htmlElement.offsetWidth
- };
- }
- return this.absoluteRect;
- },
-
- activate: function() {
- var htmlElement = this.getHTMLElement();
- if (htmlElement == null || this.showingActive)
- return;
-
- this.showingActive = true;
- this.saveBackgroundColor = htmlElement.style.backgroundColor;
-
- var fallbackColor = "#ffea84";
- var currentColor = Rico.Color.createColorFromBackground(htmlElement);
- if ( currentColor == null )
- htmlElement.style.backgroundColor = fallbackColor;
- else {
- currentColor.isBright() ? currentColor.darken(0.2) : currentColor.brighten(0.2);
- htmlElement.style.backgroundColor = currentColor.asHex();
- }
- },
-
- deactivate: function() {
- var htmlElement = this.getHTMLElement();
- if (htmlElement == null || !this.showingActive)
- return;
-
- htmlElement.style.backgroundColor = this.saveBackgroundColor;
- this.showingActive = false;
- this.saveBackgroundColor = null;
- },
-
- showHover: function() {
- var htmlElement = this.getHTMLElement();
- if ( htmlElement == null || this.showingHover )
- return;
-
- this.saveBorderWidth = htmlElement.style.borderWidth;
- this.saveBorderStyle = htmlElement.style.borderStyle;
- this.saveBorderColor = htmlElement.style.borderColor;
-
- this.showingHover = true;
- htmlElement.style.borderWidth = "1px";
- htmlElement.style.borderStyle = "solid";
- //htmlElement.style.borderColor = "#ff9900";
- htmlElement.style.borderColor = "#ffff00";
- },
-
- hideHover: function() {
- var htmlElement = this.getHTMLElement();
- if ( htmlElement == null || !this.showingHover )
- return;
-
- htmlElement.style.borderWidth = this.saveBorderWidth;
- htmlElement.style.borderStyle = this.saveBorderStyle;
- htmlElement.style.borderColor = this.saveBorderColor;
- this.showingHover = false;
- },
-
- canAccept: function(draggableObjects) {
- return true;
- },
-
- accept: function(draggableObjects) {
- var htmlElement = this.getHTMLElement();
- if ( htmlElement == null )
- return;
-
- n = draggableObjects.length;
- for ( var i = 0 ; i < n ; i++ )
- {
- var theGUI = draggableObjects[i].getDroppedGUI();
- if ( RicoUtil.getElementsComputedStyle( theGUI, "position" ) == "absolute" )
- {
- theGUI.style.position = "static";
- theGUI.style.top = "";
- theGUI.style.top = "";
- }
- htmlElement.appendChild(theGUI);
- }
- }
-}
-
-
-//-------------------- ricoEffects.js
-
-Rico.Effect = {};
-
-Rico.Effect.SizeAndPosition = Class.create();
-Rico.Effect.SizeAndPosition.prototype = {
-
- initialize: function(element, x, y, w, h, duration, steps, options) {
- this.element = $(element);
- this.x = x;
- this.y = y;
- this.w = w;
- this.h = h;
- this.duration = duration;
- this.steps = steps;
- this.options = arguments[7] || {};
-
- this.sizeAndPosition();
- },
-
- sizeAndPosition: function() {
- if (this.isFinished()) {
- if(this.options.complete) this.options.complete(this);
- return;
- }
-
- if (this.timer)
- clearTimeout(this.timer);
-
- var stepDuration = Math.round(this.duration/this.steps) ;
-
- // Get original values: x,y = top left corner; w,h = width height
- var currentX = this.element.offsetLeft;
- var currentY = this.element.offsetTop;
- var currentW = this.element.offsetWidth;
- var currentH = this.element.offsetHeight;
-
- // If values not set, or zero, we do not modify them, and take original as final as well
- this.x = (this.x) ? this.x : currentX;
- this.y = (this.y) ? this.y : currentY;
- this.w = (this.w) ? this.w : currentW;
- this.h = (this.h) ? this.h : currentH;
-
- // how much do we need to modify our values for each step?
- var difX = this.steps > 0 ? (this.x - currentX)/this.steps : 0;
- var difY = this.steps > 0 ? (this.y - currentY)/this.steps : 0;
- var difW = this.steps > 0 ? (this.w - currentW)/this.steps : 0;
- var difH = this.steps > 0 ? (this.h - currentH)/this.steps : 0;
-
- this.moveBy(difX, difY);
- this.resizeBy(difW, difH);
-
- this.duration -= stepDuration;
- this.steps--;
-
- this.timer = setTimeout(this.sizeAndPosition.bind(this), stepDuration);
- },
-
- isFinished: function() {
- return this.steps <= 0;
- },
-
- moveBy: function( difX, difY ) {
- var currentLeft = this.element.offsetLeft;
- var currentTop = this.element.offsetTop;
- var intDifX = parseInt(difX);
- var intDifY = parseInt(difY);
-
- var style = this.element.style;
- if ( intDifX != 0 )
- style.left = (currentLeft + intDifX) + "px";
- if ( intDifY != 0 )
- style.top = (currentTop + intDifY) + "px";
- },
-
- resizeBy: function( difW, difH ) {
- var currentWidth = this.element.offsetWidth;
- var currentHeight = this.element.offsetHeight;
- var intDifW = parseInt(difW);
- var intDifH = parseInt(difH);
-
- var style = this.element.style;
- if ( intDifW != 0 )
- style.width = (currentWidth + intDifW) + "px";
- if ( intDifH != 0 )
- style.height = (currentHeight + intDifH) + "px";
- }
-}
-
-Rico.Effect.Size = Class.create();
-Rico.Effect.Size.prototype = {
-
- initialize: function(element, w, h, duration, steps, options) {
- new Rico.Effect.SizeAndPosition(element, null, null, w, h, duration, steps, options);
- }
-}
-
-Rico.Effect.Position = Class.create();
-Rico.Effect.Position.prototype = {
-
- initialize: function(element, x, y, duration, steps, options) {
- new Rico.Effect.SizeAndPosition(element, x, y, null, null, duration, steps, options);
- }
-}
-
-Rico.Effect.Round = Class.create();
-Rico.Effect.Round.prototype = {
-
- initialize: function(tagName, className, options) {
- var elements = document.getElementsByTagAndClassName(tagName,className);
- for ( var i = 0 ; i < elements.length ; i++ )
- Rico.Corner.round( elements[i], options );
- }
-};
-
-Rico.Effect.FadeTo = Class.create();
-Rico.Effect.FadeTo.prototype = {
-
- initialize: function( element, opacity, duration, steps, options) {
- this.element = $(element);
- this.opacity = opacity;
- this.duration = duration;
- this.steps = steps;
- this.options = arguments[4] || {};
- this.fadeTo();
- },
-
- fadeTo: function() {
- if (this.isFinished()) {
- if(this.options.complete) this.options.complete(this);
- return;
- }
-
- if (this.timer)
- clearTimeout(this.timer);
-
- var stepDuration = Math.round(this.duration/this.steps) ;
- var currentOpacity = this.getElementOpacity();
- var delta = this.steps > 0 ? (this.opacity - currentOpacity)/this.steps : 0;
-
- this.changeOpacityBy(delta);
- this.duration -= stepDuration;
- this.steps--;
-
- this.timer = setTimeout(this.fadeTo.bind(this), stepDuration);
- },
-
- changeOpacityBy: function(v) {
- var currentOpacity = this.getElementOpacity();
- var newOpacity = Math.max(0, Math.min(currentOpacity+v, 1));
- this.element.ricoOpacity = newOpacity;
-
- this.element.style.filter = "alpha(opacity:"+Math.round(newOpacity*100)+")";
- this.element.style.opacity = newOpacity; /*//*/;
- },
-
- isFinished: function() {
- return this.steps <= 0;
- },
-
- getElementOpacity: function() {
- if ( this.element.ricoOpacity == undefined ) {
- var opacity = RicoUtil.getElementsComputedStyle(this.element, 'opacity');
- this.element.ricoOpacity = opacity != undefined ? opacity : 1.0;
- }
- return parseFloat(this.element.ricoOpacity);
- }
-}
-
-Rico.Effect.AccordionSize = Class.create();
-
-Rico.Effect.AccordionSize.prototype = {
-
- initialize: function(e1, e2, start, end, duration, steps, options) {
- this.e1 = $(e1);
- this.e2 = $(e2);
- this.start = start;
- this.end = end;
- this.duration = duration;
- this.steps = steps;
- this.options = arguments[6] || {};
-
- this.accordionSize();
- },
-
- accordionSize: function() {
-
- if (this.isFinished()) {
- // just in case there are round errors or such...
- this.e1.style.height = this.start + "px";
- this.e2.style.height = this.end + "px";
-
- if(this.options.complete)
- this.options.complete(this);
- return;
- }
-
- if (this.timer)
- clearTimeout(this.timer);
-
- var stepDuration = Math.round(this.duration/this.steps) ;
-
- var diff = this.steps > 0 ? (parseInt(this.e1.offsetHeight) - this.start)/this.steps : 0;
- this.resizeBy(diff);
-
- this.duration -= stepDuration;
- this.steps--;
-
- this.timer = setTimeout(this.accordionSize.bind(this), stepDuration);
- },
-
- isFinished: function() {
- return this.steps <= 0;
- },
-
- resizeBy: function(diff) {
- var h1Height = this.e1.offsetHeight;
- var h2Height = this.e2.offsetHeight;
- var intDiff = parseInt(diff);
- if ( diff != 0 ) {
- this.e1.style.height = (h1Height - intDiff) + "px";
- this.e2.style.height = (h2Height + intDiff) + "px";
- }
- }
-
-};
-
-
-//-------------------- ricoLiveGrid.js
-// Rico.LiveGridMetaData -----------------------------------------------------
-
-Rico.LiveGridMetaData = Class.create();
-
-Rico.LiveGridMetaData.prototype = {
-
- initialize: function( pageSize, totalRows, columnCount, options ) {
- this.pageSize = pageSize;
- this.totalRows = totalRows;
- this.setOptions(options);
- this.ArrowHeight = 16;
- this.columnCount = columnCount;
- },
-
- setOptions: function(options) {
- this.options = {
- largeBufferSize : 7.0, // 7 pages
- nearLimitFactor : 0.2 // 20% of buffer
- };
- Object.extend(this.options, options || {});
- },
-
- getPageSize: function() {
- return this.pageSize;
- },
-
- getTotalRows: function() {
- return this.totalRows;
- },
-
- setTotalRows: function(n) {
- this.totalRows = n;
- },
-
- getLargeBufferSize: function() {
- return parseInt(this.options.largeBufferSize * this.pageSize);
- },
-
- getLimitTolerance: function() {
- return parseInt(this.getLargeBufferSize() * this.options.nearLimitFactor);
- }
-};
-
-// Rico.LiveGridScroller -----------------------------------------------------
-
-Rico.LiveGridScroller = Class.create();
-
-Rico.LiveGridScroller.prototype = {
-
- initialize: function(liveGrid, viewPort) {
- this.isIE = navigator.userAgent.toLowerCase().indexOf("msie") >= 0;
- this.liveGrid = liveGrid;
- this.metaData = liveGrid.metaData;
- this.createScrollBar();
- this.scrollTimeout = null;
- this.lastScrollPos = 0;
- this.viewPort = viewPort;
- this.rows = new Array();
- },
-
- isUnPlugged: function() {
- return this.scrollerDiv.onscroll == null;
- },
-
- plugin: function() {
- this.scrollerDiv.onscroll = this.handleScroll.bindAsEventListener(this);
- },
-
- unplug: function() {
- this.scrollerDiv.onscroll = null;
- },
-
- sizeIEHeaderHack: function() {
- if ( !this.isIE ) return;
- var headerTable = $(this.liveGrid.tableId + "_header");
- if ( headerTable )
- headerTable.rows[0].cells[0].style.width =
- (headerTable.rows[0].cells[0].offsetWidth + 1) + "px";
- },
-
- createScrollBar: function() {
- var visibleHeight = this.liveGrid.viewPort.visibleHeight();
- // create the outer div...
- this.scrollerDiv = document.createElement("div");
- var scrollerStyle = this.scrollerDiv.style;
- scrollerStyle.borderRight = this.liveGrid.options.scrollerBorderRight;
- scrollerStyle.position = "relative";
- scrollerStyle.left = this.isIE ? "-6px" : "-3px";
- scrollerStyle.width = "19px";
- scrollerStyle.height = visibleHeight + "px";
- scrollerStyle.overflow = "auto";
-
- // create the inner div...
- this.heightDiv = document.createElement("div");
- this.heightDiv.style.width = "1px";
-
- this.heightDiv.style.height = parseInt(visibleHeight *
- this.metaData.getTotalRows()/this.metaData.getPageSize()) + "px" ;
- this.scrollerDiv.appendChild(this.heightDiv);
- this.scrollerDiv.onscroll = this.handleScroll.bindAsEventListener(this);
-
- var table = this.liveGrid.table;
- table.parentNode.parentNode.insertBefore( this.scrollerDiv, table.parentNode.nextSibling );
- var eventName = this.isIE ? "mousewheel" : "DOMMouseScroll";
- Event.observe(table, eventName,
- function(evt) {
- if (evt.wheelDelta>=0 || evt.detail < 0) //wheel-up
- this.scrollerDiv.scrollTop -= (2*this.viewPort.rowHeight);
- else
- this.scrollerDiv.scrollTop += (2*this.viewPort.rowHeight);
- this.handleScroll(false);
- }.bindAsEventListener(this),
- false);
- },
-
- updateSize: function() {
- var table = this.liveGrid.table;
- var visibleHeight = this.viewPort.visibleHeight();
- this.heightDiv.style.height = parseInt(visibleHeight *
- this.metaData.getTotalRows()/this.metaData.getPageSize()) + "px";
- },
-
- rowToPixel: function(rowOffset) {
- return (rowOffset / this.metaData.getTotalRows()) * this.heightDiv.offsetHeight
- },
-
- moveScroll: function(rowOffset) {
- this.scrollerDiv.scrollTop = this.rowToPixel(rowOffset);
- if ( this.metaData.options.onscroll )
- this.metaData.options.onscroll( this.liveGrid, rowOffset );
- },
-
- handleScroll: function() {
- if ( this.scrollTimeout )
- clearTimeout( this.scrollTimeout );
-
- var scrollDiff = this.lastScrollPos-this.scrollerDiv.scrollTop;
- if (scrollDiff != 0.00) {
- var r = this.scrollerDiv.scrollTop % this.viewPort.rowHeight;
- if (r != 0) {
- this.unplug();
- if ( scrollDiff < 0 ) {
- this.scrollerDiv.scrollTop += (this.viewPort.rowHeight-r);
- } else {
- this.scrollerDiv.scrollTop -= r;
- }
- this.plugin();
- }
- }
- var contentOffset = parseInt(this.scrollerDiv.scrollTop / this.viewPort.rowHeight);
- this.liveGrid.requestContentRefresh(contentOffset);
- this.viewPort.scrollTo(this.scrollerDiv.scrollTop);
-
- if ( this.metaData.options.onscroll )
- this.metaData.options.onscroll( this.liveGrid, contentOffset );
-
- this.scrollTimeout = setTimeout(this.scrollIdle.bind(this), 1200 );
- this.lastScrollPos = this.scrollerDiv.scrollTop;
-
- },
-
- scrollIdle: function() {
- if ( this.metaData.options.onscrollidle )
- this.metaData.options.onscrollidle();
- }
-};
-
-// Rico.LiveGridBuffer -----------------------------------------------------
-
-Rico.LiveGridBuffer = Class.create();
-
-Rico.LiveGridBuffer.prototype = {
-
- initialize: function(metaData, viewPort) {
- this.startPos = 0;
- this.size = 0;
- this.metaData = metaData;
- this.rows = new Array();
- this.updateInProgress = false;
- this.viewPort = viewPort;
- this.maxBufferSize = metaData.getLargeBufferSize() * 2;
- this.maxFetchSize = metaData.getLargeBufferSize();
- this.lastOffset = 0;
- },
-
- getBlankRow: function() {
- if (!this.blankRow ) {
- this.blankRow = new Array();
- for ( var i=0; i < this.metaData.columnCount ; i++ )
- this.blankRow[i] = " ";
- }
- return this.blankRow;
- },
-
- loadRows: function(ajaxResponse) {
- var rowsElement = ajaxResponse.getElementsByTagName('rows')[0];
- this.updateUI = rowsElement.getAttribute("update_ui") == "true"
- var newRows = new Array()
- var trs = rowsElement.getElementsByTagName("tr");
- for ( var i=0 ; i < trs.length; i++ ) {
- var row = newRows[i] = new Array();
- var cells = trs[i].getElementsByTagName("td");
- for ( var j=0; j < cells.length ; j++ ) {
- var cell = cells[j];
- var convertSpaces = cell.getAttribute("convert_spaces") == "true";
- var cellContent = RicoUtil.getContentAsString(cell);
- row[j] = convertSpaces ? this.convertSpaces(cellContent) : cellContent;
- if (!row[j])
- row[j] = ' ';
- }
- }
- return newRows;
- },
-
- update: function(ajaxResponse, start) {
- var newRows = this.loadRows(ajaxResponse);
- if (this.rows.length == 0) { // initial load
- this.rows = newRows;
- this.size = this.rows.length;
- this.startPos = start;
- return;
- }
- if (start > this.startPos) { //appending
- if (this.startPos + this.rows.length < start) {
- this.rows = newRows;
- this.startPos = start;//
- } else {
- this.rows = this.rows.concat( newRows.slice(0, newRows.length));
- if (this.rows.length > this.maxBufferSize) {
- var fullSize = this.rows.length;
- this.rows = this.rows.slice(this.rows.length - this.maxBufferSize, this.rows.length)
- this.startPos = this.startPos + (fullSize - this.rows.length);
- }
- }
- } else { //prepending
- if (start + newRows.length < this.startPos) {
- this.rows = newRows;
- } else {
- this.rows = newRows.slice(0, this.startPos).concat(this.rows);
- if (this.rows.length > this.maxBufferSize)
- this.rows = this.rows.slice(0, this.maxBufferSize)
- }
- this.startPos = start;
- }
- this.size = this.rows.length;
- },
-
- clear: function() {
- this.rows = new Array();
- this.startPos = 0;
- this.size = 0;
- },
-
- isOverlapping: function(start, size) {
- return ((start < this.endPos()) && (this.startPos < start + size)) || (this.endPos() == 0)
- },
-
- isInRange: function(position) {
- return (position >= this.startPos) && (position + this.metaData.getPageSize() <= this.endPos());
- //&& this.size() != 0;
- },
-
- isNearingTopLimit: function(position) {
- return position - this.startPos < this.metaData.getLimitTolerance();
- },
-
- endPos: function() {
- return this.startPos + this.rows.length;
- },
-
- isNearingBottomLimit: function(position) {
- return this.endPos() - (position + this.metaData.getPageSize()) < this.metaData.getLimitTolerance();
- },
-
- isAtTop: function() {
- return this.startPos == 0;
- },
-
- isAtBottom: function() {
- return this.endPos() == this.metaData.getTotalRows();
- },
-
- isNearingLimit: function(position) {
- return ( !this.isAtTop() && this.isNearingTopLimit(position)) ||
- ( !this.isAtBottom() && this.isNearingBottomLimit(position) )
- },
-
- getFetchSize: function(offset) {
- var adjustedOffset = this.getFetchOffset(offset);
- var adjustedSize = 0;
- if (adjustedOffset >= this.startPos) { //apending
- var endFetchOffset = this.maxFetchSize + adjustedOffset;
- if (endFetchOffset > this.metaData.totalRows)
- endFetchOffset = this.metaData.totalRows;
- adjustedSize = endFetchOffset - adjustedOffset;
- if(adjustedOffset == 0 && adjustedSize < this.maxFetchSize){
- adjustedSize = this.maxFetchSize;
- }
- } else {//prepending
- var adjustedSize = this.startPos - adjustedOffset;
- if (adjustedSize > this.maxFetchSize)
- adjustedSize = this.maxFetchSize;
- }
- return adjustedSize;
- },
-
- getFetchOffset: function(offset) {
- var adjustedOffset = offset;
- if (offset > this.startPos) //apending
- adjustedOffset = (offset > this.endPos()) ? offset : this.endPos();
- else { //prepending
- if (offset + this.maxFetchSize >= this.startPos) {
- var adjustedOffset = this.startPos - this.maxFetchSize;
- if (adjustedOffset < 0)
- adjustedOffset = 0;
- }
- }
- this.lastOffset = adjustedOffset;
- return adjustedOffset;
- },
-
- getRows: function(start, count) {
- var begPos = start - this.startPos
- var endPos = begPos + count
-
- // er? need more data...
- if ( endPos > this.size )
- endPos = this.size
-
- var results = new Array()
- var index = 0;
- for ( var i=begPos ; i < endPos; i++ ) {
- results[index++] = this.rows[i]
- }
- return results
- },
-
- convertSpaces: function(s) {
- return s.split(" ").join(" ");
- }
-
-};
-
-
-//Rico.GridViewPort --------------------------------------------------
-Rico.GridViewPort = Class.create();
-
-Rico.GridViewPort.prototype = {
-
- initialize: function(table, rowHeight, visibleRows, buffer, liveGrid) {
- this.lastDisplayedStartPos = 0;
- this.div = table.parentNode;
- this.table = table
- this.rowHeight = rowHeight;
- this.div.style.height = (this.rowHeight * visibleRows) + "px";
- this.div.style.overflow = "hidden";
- this.buffer = buffer;
- this.liveGrid = liveGrid;
- this.visibleRows = visibleRows + 1;
- this.lastPixelOffset = 0;
- this.startPos = 0;
- },
-
- populateRow: function(htmlRow, row) {
- for (var j=0; j < row.length; j++) {
- htmlRow.cells[j].innerHTML = row[j]
- }
- },
-
- bufferChanged: function() {
- this.refreshContents( parseInt(this.lastPixelOffset / this.rowHeight));
- },
-
- clearRows: function() {
- if (!this.isBlank) {
- this.liveGrid.table.className = this.liveGrid.options.loadingClass;
- for (var i=0; i < this.visibleRows; i++)
- this.populateRow(this.table.rows[i], this.buffer.getBlankRow());
- this.isBlank = true;
- }
- },
-
- clearContents: function() {
- this.clearRows();
- this.scrollTo(0);
- this.startPos = 0;
- this.lastStartPos = -1;
- },
-
- refreshContents: function(startPos) {
- if (startPos == this.lastRowPos && !this.isPartialBlank && !this.isBlank) {
- return;
- }
- if ((startPos + this.visibleRows < this.buffer.startPos)
- || (this.buffer.startPos + this.buffer.size < startPos)
- || (this.buffer.size == 0)) {
- this.clearRows();
- return;
- }
- this.isBlank = false;
- var viewPrecedesBuffer = this.buffer.startPos > startPos
- var contentStartPos = viewPrecedesBuffer ? this.buffer.startPos: startPos;
- var contentEndPos = (this.buffer.startPos + this.buffer.size < startPos + this.visibleRows)
- ? this.buffer.startPos + this.buffer.size
- : startPos + this.visibleRows;
- var rowSize = contentEndPos - contentStartPos;
- var rows = this.buffer.getRows(contentStartPos, rowSize );
- var blankSize = this.visibleRows - rowSize;
- var blankOffset = viewPrecedesBuffer ? 0: rowSize;
- var contentOffset = viewPrecedesBuffer ? blankSize: 0;
-
- for (var i=0; i < rows.length; i++) {//initialize what we have
- this.populateRow(this.table.rows[i + contentOffset], rows[i]);
- }
- for (var i=0; i < blankSize; i++) {// blank out the rest
- this.populateRow(this.table.rows[i + blankOffset], this.buffer.getBlankRow());
- }
- this.isPartialBlank = blankSize > 0;
- this.lastRowPos = startPos;
-
- this.liveGrid.table.className = this.liveGrid.options.tableClass;
- // Check if user has set a onRefreshComplete function
- var onRefreshComplete = this.liveGrid.options.onRefreshComplete;
- if (onRefreshComplete != null)
- onRefreshComplete();
- },
-
- scrollTo: function(pixelOffset) {
- if (this.lastPixelOffset == pixelOffset)
- return;
-
- this.refreshContents(parseInt(pixelOffset / this.rowHeight))
- this.div.scrollTop = pixelOffset % this.rowHeight
-
- this.lastPixelOffset = pixelOffset;
- },
-
- visibleHeight: function() {
- return parseInt(RicoUtil.getElementsComputedStyle(this.div, 'height'));
- }
-
-};
-
-
-Rico.LiveGridRequest = Class.create();
-Rico.LiveGridRequest.prototype = {
- initialize: function( requestOffset, options ) {
- this.requestOffset = requestOffset;
- }
-};
-
-// Rico.LiveGrid -----------------------------------------------------
-
-Rico.LiveGrid = Class.create();
-
-Rico.LiveGrid.prototype = {
-
- initialize: function( tableId, visibleRows, totalRows, url, options, ajaxOptions ) {
-
- this.options = {
- tableClass: $(tableId).className,
- loadingClass: $(tableId).className,
- scrollerBorderRight: '1px solid #ababab',
- bufferTimeout: 20000,
- sortAscendImg: 'images/sort_asc.gif',
- sortDescendImg: 'images/sort_desc.gif',
- sortImageWidth: 9,
- sortImageHeight: 5,
- ajaxSortURLParms: [],
- onRefreshComplete: null,
- requestParameters: null,
- inlineStyles: true
- };
- Object.extend(this.options, options || {});
-
- this.ajaxOptions = {parameters: null};
- Object.extend(this.ajaxOptions, ajaxOptions || {});
-
- this.tableId = tableId;
- this.table = $(tableId);
-
- this.addLiveGridHtml();
-
- var columnCount = this.table.rows[0].cells.length;
- this.metaData = new Rico.LiveGridMetaData(visibleRows, totalRows, columnCount, options);
- this.buffer = new Rico.LiveGridBuffer(this.metaData);
-
- var rowCount = this.table.rows.length;
- this.viewPort = new Rico.GridViewPort(this.table,
- this.table.offsetHeight/rowCount,
- visibleRows,
- this.buffer, this);
- this.scroller = new Rico.LiveGridScroller(this,this.viewPort);
- this.options.sortHandler = this.sortHandler.bind(this);
-
- if ( $(tableId + '_header') )
- this.sort = new Rico.LiveGridSort(tableId + '_header', this.options)
-
- this.processingRequest = null;
- this.unprocessedRequest = null;
-
- this.initAjax(url);
- if ( this.options.prefetchBuffer || this.options.prefetchOffset > 0) {
- var offset = 0;
- if (this.options.offset ) {
- offset = this.options.offset;
- this.scroller.moveScroll(offset);
- this.viewPort.scrollTo(this.scroller.rowToPixel(offset));
- }
- if (this.options.sortCol) {
- this.sortCol = options.sortCol;
- this.sortDir = options.sortDir;
- }
- this.requestContentRefresh(offset);
- }
- },
-
- addLiveGridHtml: function() {
- // Check to see if need to create a header table.
- if (this.table.getElementsByTagName("thead").length > 0){
- // Create Table this.tableId+'_header'
- var tableHeader = this.table.cloneNode(true);
- tableHeader.setAttribute('id', this.tableId+'_header');
- tableHeader.setAttribute('class', this.table.className+'_header');
-
- // Clean up and insert
- for( var i = 0; i < tableHeader.tBodies.length; i++ )
- tableHeader.removeChild(tableHeader.tBodies[i]);
- this.table.deleteTHead();
- this.table.parentNode.insertBefore(tableHeader,this.table);
- }
-
- new Insertion.Before(this.table, "<div id='"+this.tableId+"_container'></div>");
- this.table.previousSibling.appendChild(this.table);
- new Insertion.Before(this.table,"<div id='"+this.tableId+"_viewport' style='float:left;'></div>");
- this.table.previousSibling.appendChild(this.table);
- },
-
-
- resetContents: function() {
- this.scroller.moveScroll(0);
- this.buffer.clear();
- this.viewPort.clearContents();
- },
-
- sortHandler: function(column) {
- if(!column) return ;
- this.sortCol = column.name;
- this.sortDir = column.currentSort;
-
- this.resetContents();
- this.requestContentRefresh(0)
- },
-
- adjustRowSize: function() {
-
- },
-
- setTotalRows: function( newTotalRows ) {
- this.resetContents();
- this.metaData.setTotalRows(newTotalRows);
- this.scroller.updateSize();
- },
-
- initAjax: function(url) {
- ajaxEngine.registerRequest( this.tableId + '_request', url );
- ajaxEngine.registerAjaxObject( this.tableId + '_updater', this );
- },
-
- invokeAjax: function() {
- },
-
- handleTimedOut: function() {
- //server did not respond in 4 seconds... assume that there could have been
- //an error or something, and allow requests to be processed again...
- this.processingRequest = null;
- this.processQueuedRequest();
- },
-
- fetchBuffer: function(offset) {
- if ( this.buffer.isInRange(offset) &&
- !this.buffer.isNearingLimit(offset)) {
- return;
- }
- if (this.processingRequest) {
- this.unprocessedRequest = new Rico.LiveGridRequest(offset);
- return;
- }
- var bufferStartPos = this.buffer.getFetchOffset(offset);
- this.processingRequest = new Rico.LiveGridRequest(offset);
- this.processingRequest.bufferOffset = bufferStartPos;
- var fetchSize = this.buffer.getFetchSize(offset);
- var partialLoaded = false;
-
- var queryString
- if (this.options.requestParameters)
- queryString = this._createQueryString(this.options.requestParameters, 0);
-
- queryString = (queryString == null) ? '' : queryString+'&';
- queryString = queryString+'id='+this.tableId+'&page_size='+fetchSize+'&offset='+bufferStartPos;
- if (this.sortCol)
- queryString = queryString+'&sort_col='+escape(this.sortCol)+'&sort_dir='+this.sortDir;
-
- this.ajaxOptions.parameters = queryString;
-
- ajaxEngine.sendRequest( this.tableId + '_request', this.ajaxOptions );
-
- this.timeoutHandler = setTimeout( this.handleTimedOut.bind(this), this.options.bufferTimeout);
-
- },
-
- setRequestParams: function() {
- this.options.requestParameters = [];
- for ( var i=0 ; i < arguments.length ; i++ )
- this.options.requestParameters[i] = arguments[i];
- },
-
- requestContentRefresh: function(contentOffset) {
- this.fetchBuffer(contentOffset);
- },
-
- ajaxUpdate: function(ajaxResponse) {
- try {
- clearTimeout( this.timeoutHandler );
- this.buffer.update(ajaxResponse,this.processingRequest.bufferOffset);
- this.viewPort.bufferChanged();
- }
- catch(err) {}
- finally {this.processingRequest = null; }
- this.processQueuedRequest();
- },
-
- _createQueryString: function( theArgs, offset ) {
- var queryString = ""
- if (!theArgs)
- return queryString;
-
- for ( var i = offset ; i < theArgs.length ; i++ ) {
- if ( i != offset )
- queryString += "&";
-
- var anArg = theArgs[i];
-
- if ( anArg.name != undefined && anArg.value != undefined ) {
- queryString += anArg.name + "=" + escape(anArg.value);
- }
- else {
- var ePos = anArg.indexOf('=');
- var argName = anArg.substring( 0, ePos );
- var argValue = anArg.substring( ePos + 1 );
- queryString += argName + "=" + escape(argValue);
- }
- }
- return queryString;
- },
-
- processQueuedRequest: function() {
- if (this.unprocessedRequest != null) {
- this.requestContentRefresh(this.unprocessedRequest.requestOffset);
- this.unprocessedRequest = null
- }
- }
-};
-
-
-//-------------------- ricoLiveGridSort.js
-Rico.LiveGridSort = Class.create();
-
-Rico.LiveGridSort.prototype = {
-
- initialize: function(headerTableId, options) {
- this.headerTableId = headerTableId;
- this.headerTable = $(headerTableId);
- this.options = options;
- this.setOptions();
- this.applySortBehavior();
-
- if ( this.options.sortCol ) {
- this.setSortUI( this.options.sortCol, this.options.sortDir );
- }
- },
-
- setSortUI: function( columnName, sortDirection ) {
- var cols = this.options.columns;
- for ( var i = 0 ; i < cols.length ; i++ ) {
- if ( cols[i].name == columnName ) {
- this.setColumnSort(i, sortDirection);
- break;
- }
- }
- },
-
- setOptions: function() {
- // preload the images...
- new Image().src = this.options.sortAscendImg;
- new Image().src = this.options.sortDescendImg;
-
- this.sort = this.options.sortHandler;
- if ( !this.options.columns )
- this.options.columns = this.introspectForColumnInfo();
- else {
- // allow client to pass { columns: [ ["a", true], ["b", false] ] }
- // and convert to an array of Rico.TableColumn objs...
- this.options.columns = this.convertToTableColumns(this.options.columns);
- }
- },
-
- applySortBehavior: function() {
- var headerRow = this.headerTable.rows[0];
- var headerCells = headerRow.cells;
- for ( var i = 0 ; i < headerCells.length ; i++ ) {
- this.addSortBehaviorToColumn( i, headerCells[i] );
- }
- },
-
- addSortBehaviorToColumn: function( n, cell ) {
- if ( this.options.columns[n].isSortable() ) {
- cell.id = this.headerTableId + '_' + n;
- cell.style.cursor = 'pointer';
- cell.onclick = this.headerCellClicked.bindAsEventListener(this);
- cell.innerHTML = cell.innerHTML + '<span id="' + this.headerTableId + '_img_' + n + '">'
- + ' </span>';
- }
- },
-
- // event handler....
- headerCellClicked: function(evt) {
- var eventTarget = evt.target ? evt.target : evt.srcElement;
- var cellId = eventTarget.id;
- var columnNumber = parseInt(cellId.substring( cellId.lastIndexOf('_') + 1 ));
- var sortedColumnIndex = this.getSortedColumnIndex();
- if ( sortedColumnIndex != -1 ) {
- if ( sortedColumnIndex != columnNumber ) {
- this.removeColumnSort(sortedColumnIndex);
- this.setColumnSort(columnNumber, Rico.TableColumn.SORT_ASC);
- }
- else
- this.toggleColumnSort(sortedColumnIndex);
- }
- else
- this.setColumnSort(columnNumber, Rico.TableColumn.SORT_ASC);
-
- if (this.options.sortHandler) {
- this.options.sortHandler(this.options.columns[columnNumber]);
- }
- },
-
- removeColumnSort: function(n) {
- this.options.columns[n].setUnsorted();
- this.setSortImage(n);
- },
-
- setColumnSort: function(n, direction) {
- if(isNaN(n)) return ;
- this.options.columns[n].setSorted(direction);
- this.setSortImage(n);
- },
-
- toggleColumnSort: function(n) {
- this.options.columns[n].toggleSort();
- this.setSortImage(n);
- },
-
- setSortImage: function(n) {
- var sortDirection = this.options.columns[n].getSortDirection();
-
- var sortImageSpan = $( this.headerTableId + '_img_' + n );
- if ( sortDirection == Rico.TableColumn.UNSORTED )
- sortImageSpan.innerHTML = ' ';
- else if ( sortDirection == Rico.TableColumn.SORT_ASC )
- sortImageSpan.innerHTML = ' <img width="' + this.options.sortImageWidth + '" ' +
- 'height="'+ this.options.sortImageHeight + '" ' +
- 'src="' + this.options.sortAscendImg + '"/>';
- else if ( sortDirection == Rico.TableColumn.SORT_DESC )
- sortImageSpan.innerHTML = ' <img width="' + this.options.sortImageWidth + '" ' +
- 'height="'+ this.options.sortImageHeight + '" ' +
- 'src="' + this.options.sortDescendImg + '"/>';
- },
-
- getSortedColumnIndex: function() {
- var cols = this.options.columns;
- for ( var i = 0 ; i < cols.length ; i++ ) {
- if ( cols[i].isSorted() )
- return i;
- }
-
- return -1;
- },
-
- introspectForColumnInfo: function() {
- var columns = new Array();
- var headerRow = this.headerTable.rows[0];
- var headerCells = headerRow.cells;
- for ( var i = 0 ; i < headerCells.length ; i++ )
- columns.push( new Rico.TableColumn( this.deriveColumnNameFromCell(headerCells[i],i), true ) );
- return columns;
- },
-
- convertToTableColumns: function(cols) {
- var columns = new Array();
- for ( var i = 0 ; i < cols.length ; i++ )
- columns.push( new Rico.TableColumn( cols[i][0], cols[i][1] ) );
- return columns;
- },
-
- deriveColumnNameFromCell: function(cell,columnNumber) {
- var cellContent = cell.innerText != undefined ? cell.innerText : cell.textContent;
- return cellContent ? cellContent.toLowerCase().split(' ').join('_') : "col_" + columnNumber;
- }
-};
-
-Rico.TableColumn = Class.create();
-
-Rico.TableColumn.UNSORTED = 0;
-Rico.TableColumn.SORT_ASC = "ASC";
-Rico.TableColumn.SORT_DESC = "DESC";
-
-Rico.TableColumn.prototype = {
- initialize: function(name, sortable) {
- this.name = name;
- this.sortable = sortable;
- this.currentSort = Rico.TableColumn.UNSORTED;
- },
-
- isSortable: function() {
- return this.sortable;
- },
-
- isSorted: function() {
- return this.currentSort != Rico.TableColumn.UNSORTED;
- },
-
- getSortDirection: function() {
- return this.currentSort;
- },
-
- toggleSort: function() {
- if ( this.currentSort == Rico.TableColumn.UNSORTED || this.currentSort == Rico.TableColumn.SORT_DESC )
- this.currentSort = Rico.TableColumn.SORT_ASC;
- else if ( this.currentSort == Rico.TableColumn.SORT_ASC )
- this.currentSort = Rico.TableColumn.SORT_DESC;
- },
-
- setUnsorted: function(direction) {
- this.setSorted(Rico.TableColumn.UNSORTED);
- },
-
- setSorted: function(direction) {
- // direction must by one of Rico.TableColumn.UNSORTED, .SORT_ASC, or .SORT_DESC...
- this.currentSort = direction;
- }
-
-};
-
-
-//-------------------- ricoUtil.js
-var RicoUtil = {
-
- getElementsComputedStyle: function ( htmlElement, cssProperty, mozillaEquivalentCSS) {
- if ( arguments.length == 2 )
- mozillaEquivalentCSS = cssProperty;
-
- var el = $(htmlElement);
- if ( el.currentStyle )
- return el.currentStyle[cssProperty];
- else
- return document.defaultView.getComputedStyle(el, null).getPropertyValue(mozillaEquivalentCSS);
- },
-
- createXmlDocument : function() {
- if (document.implementation && document.implementation.createDocument) {
- var doc = document.implementation.createDocument("", "", null);
-
- if (doc.readyState == null) {
- doc.readyState = 1;
- doc.addEventListener("load", function () {
- doc.readyState = 4;
- if (typeof doc.onreadystatechange == "function")
- doc.onreadystatechange();
- }, false);
- }
-
- return doc;
- }
-
- if (window.ActiveXObject)
- return Try.these(
- function() { return new ActiveXObject('MSXML2.DomDocument') },
- function() { return new ActiveXObject('Microsoft.DomDocument')},
- function() { return new ActiveXObject('MSXML.DomDocument') },
- function() { return new ActiveXObject('MSXML3.DomDocument') }
- ) || false;
-
- return null;
- },
-
- getContentAsString: function( parentNode ) {
- return parentNode.xml != undefined ?
- this._getContentAsStringIE(parentNode) :
- this._getContentAsStringMozilla(parentNode);
- },
-
- _getContentAsStringIE: function(parentNode) {
- var contentStr = "";
- for ( var i = 0 ; i < parentNode.childNodes.length ; i++ ) {
- var n = parentNode.childNodes[i];
- if (n.nodeType == 4) {
- contentStr += n.nodeValue;
- }
- else {
- contentStr += n.xml;
- }
- }
- return contentStr;
- },
-
- _getContentAsStringMozilla: function(parentNode) {
- var xmlSerializer = new XMLSerializer();
- var contentStr = "";
- for ( var i = 0 ; i < parentNode.childNodes.length ; i++ ) {
- var n = parentNode.childNodes[i];
- if (n.nodeType == 4) { // CDATA node
- contentStr += n.nodeValue;
- }
- else {
- contentStr += xmlSerializer.serializeToString(n);
- }
- }
- return contentStr;
- },
-
- toViewportPosition: function(element) {
- return this._toAbsolute(element,true);
- },
-
- toDocumentPosition: function(element) {
- return this._toAbsolute(element,false);
- },
-
- /**
- * Compute the elements position in terms of the window viewport
- * so that it can be compared to the position of the mouse (dnd)
- * This is additions of all the offsetTop,offsetLeft values up the
- * offsetParent hierarchy, ...taking into account any scrollTop,
- * scrollLeft values along the way...
- *
- * IE has a bug reporting a correct offsetLeft of elements within a
- * a relatively positioned parent!!!
- **/
- _toAbsolute: function(element,accountForDocScroll) {
-
- if ( navigator.userAgent.toLowerCase().indexOf("msie") == -1 )
- return this._toAbsoluteMozilla(element,accountForDocScroll);
-
- var x = 0;
- var y = 0;
- var parent = element;
- while ( parent ) {
-
- var borderXOffset = 0;
- var borderYOffset = 0;
- if ( parent != element ) {
- var borderXOffset = parseInt(this.getElementsComputedStyle(parent, "borderLeftWidth" ));
- var borderYOffset = parseInt(this.getElementsComputedStyle(parent, "borderTopWidth" ));
- borderXOffset = isNaN(borderXOffset) ? 0 : borderXOffset;
- borderYOffset = isNaN(borderYOffset) ? 0 : borderYOffset;
- }
-
- x += parent.offsetLeft - parent.scrollLeft + borderXOffset;
- y += parent.offsetTop - parent.scrollTop + borderYOffset;
- parent = parent.offsetParent;
- }
-
- if ( accountForDocScroll ) {
- x -= this.docScrollLeft();
- y -= this.docScrollTop();
- }
-
- return { x:x, y:y };
- },
-
- /**
- * Mozilla did not report all of the parents up the hierarchy via the
- * offsetParent property that IE did. So for the calculation of the
- * offsets we use the offsetParent property, but for the calculation of
- * the scrollTop/scrollLeft adjustments we navigate up via the parentNode
- * property instead so as to get the scroll offsets...
- *
- **/
- _toAbsoluteMozilla: function(element,accountForDocScroll) {
- var x = 0;
- var y = 0;
- var parent = element;
- while ( parent ) {
- x += parent.offsetLeft;
- y += parent.offsetTop;
- parent = parent.offsetParent;
- }
-
- parent = element;
- while ( parent &&
- parent != document.body &&
- parent != document.documentElement ) {
- if ( parent.scrollLeft )
- x -= parent.scrollLeft;
- if ( parent.scrollTop )
- y -= parent.scrollTop;
- parent = parent.parentNode;
- }
-
- if ( accountForDocScroll ) {
- x -= this.docScrollLeft();
- y -= this.docScrollTop();
- }
-
- return { x:x, y:y };
- },
-
- docScrollLeft: function() {
- if ( window.pageXOffset )
- return window.pageXOffset;
- else if ( document.documentElement && document.documentElement.scrollLeft )
- return document.documentElement.scrollLeft;
- else if ( document.body )
- return document.body.scrollLeft;
- else
- return 0;
- },
-
- docScrollTop: function() {
- if ( window.pageYOffset )
- return window.pageYOffset;
- else if ( document.documentElement && document.documentElement.scrollTop )
- return document.documentElement.scrollTop;
- else if ( document.body )
- return document.body.scrollTop;
- else
- return 0;
- }
-
-};
+++ /dev/null
-body { background-color:#445566; color:#FFCC99; }
-a:link { color:#FF9966; }
-a:visited { color:#FF9900; }
-a:active { color:#FFFFFF; }
-
- /* allow room for 3 columns */
-ol
-{
- width: 45em;
-}
-
- /* float and allow room for the widest item */
-ol li
-{
- float: left;
- width: 15em;
-}
-
-/* stop the float */
-br
-{
- clear: left;
-}
-
- /* separate the list from subsequent markup */
-div.wrapper
-{
- margin-bottom: 1em;
-}
-
+++ /dev/null
-var url_getvolume = '/web/vol?set=info';
-var url_setvolume = '/web/vol?set=set'; // plus new value eq. set=set15
-var url_volumeup = '/web/vol?set=up';
-var url_volumedown = '/web/vol?set=down';
-var url_volumemute = '/web/vol?set=mute';
-
-var url_epgservice = "/web/epgservice?ref="; // plus serviceRev
-var url_epgsearch = "/web/epgsearch?search="; // plus serviceRev
-var url_epgnownext = "/web/epgnownext?ref="; // plus serviceRev
-
-function debug(text){
- //$('debug').innerHTML += "DEBUG: "+text+"<br>";
-}
-function set(what, value)
-{
- //debug(what+"-"+value);
- element = document.getElementById(what);
- element.innerHTML = value;
- $('scriptzone').innerHTML = ""; // deleting set() from page, to keep the page short and to save memory
-}
-
-function zap(li)
-{
- var request = getHTTPObject();
- var url = "/web/zap?ZapTo=" + escape(li.id);
- //debug("requesting "+url);
- new Ajax.Request( url,
- {
- method: 'get'
-
- });
-
-}
-
-function getHTTPObject()
-{
- var xmlhttp;
- /*@cc_on
- @if (@_jscript_version >= 5)
- try
- {
- xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
- }
- catch (e)
- {
- try
- {
- xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
- }
- catch (E)
- {
- xmlhttp = false;
- }
- }
- @else
- xmlhttp = false;
- @end @*/
- if (!xmlhttp && typeof XMLHttpRequest != 'undefined')
- {
- try
- {
- xmlhttp = new XMLHttpRequest();
- }
- catch (e)
- {
- xmlhttp = false;
- }
- }
- return xmlhttp;
-}
-
-
-//+++++++++++++++++++++++++++++++++++++++++++++++++++++
-//+++++++++++++++++++++++++++++++++++++++++++++++++++++
-//++++ EPG functions ++++
-//+++++++++++++++++++++++++++++++++++++++++++++++++++++
-//+++++++++++++++++++++++++++++++++++++++++++++++++++++
-var EPGList = Class.create();
-EPGList.prototype = {
- //contructor
- initialize: function(){
- debug("init class EPGList");
- },
- getBySearchString: function(string,element){
- debug("requesting "+ url_epgsearch+string);
- targetElement = element;
- new Ajax.Request( url_epgsearch+string,
- {
- method: 'get',
- onComplete: this.incomingEPGrequest
- });
-
- },
- getByServiceReference: function(serviceRef,element){
- targetElement = element;
- new Ajax.Request(url_epgservice+serviceRef,
- {
- method: 'get',
- onComplete: this.incomingEPGrequest
- });
-
- },
- renderTable: function(epglist){
- debug("rendering Table with "+epglist.length+" events");
- var html="<table width='100%'>";
- for (var i=0; i<epglist.length;i++){
- var item = epglist[i];
- html +="<tr bgcolor='gray'>";
- html +="<td>"+item.getTimeDay()+"</td>";
- html +="<td>"+item.getTimeStartString()+"</td>";
- html +="<td>"+item.getTimeEndString()+"</td>";
- html +="<td>"+item.getTitle()+"</td>";
- html +="<td>"+item.getDescription()+"</td>";
- html +="<td>"+item.getDescriptionExtended()+"</td>";
- html +="<td>"+(item.getDuration()/60000)+" min.</td>";
- html +="<td>"+item.getServiceName()+"</td>";
- html +="</tr>";
- }
- html +="</table>";
- targetElement.innerHTML = html;
-
- },
- incomingEPGrequest: function(originalRequest){
- debug("incoming request" +originalRequest.readyState);
- if (originalRequest.readyState == 4)
- {
- if (originalRequest.responseXML!="no data")
- {
- var EPGItems = originalRequest.responseXML.getElementsByTagName("e2eventlist").item(0).getElementsByTagName("e2event");
- debug("have "+EPGItems.length+" e2events");
- epglist = new Array();
- for(var i=0;i<EPGItems.length;i++)
- {
- epglist.push(new EPGEvent(EPGItems.item(i)));
- }
- EPGList.prototype.renderTable(epglist);
-
- }
- }
- }
-
-}
-
-function EPGEvent(element){
- // parsing values from xml-element
- this.eventID= element.getElementsByTagName('e2eventid').item(0).firstChild.data;
- this.startTime= element.getElementsByTagName('e2eventstart').item(0).firstChild.data;
- this.duration= element.getElementsByTagName('e2eventduration').item(0).firstChild.data;
- this.title= element.getElementsByTagName('e2eventtitle').item(0).firstChild.data;
- this.description= element.getElementsByTagName('e2eventdescription').item(0).firstChild.data;
- this.descriptionE= element.getElementsByTagName('e2eventdescriptionextended').item(0).firstChild.data;
- this.serviceRef= element.getElementsByTagName('e2eventservicereference').item(0).firstChild.data;
- this.serviceName= element.getElementsByTagName('e2eventservicename').item(0).firstChild.data;
-
- this.getEventId = function ()
- {
- return this.eventID;
- }
- this.getTimeStart = function ()
- {
- var date = new Date(parseInt(this.startTime)*1000);
- return date;
- }
- this.getTimeStartString = function ()
- {
- var h = this.getTimeStart().getHours();
- var m = this.getTimeStart().getMinutes();
- if (m < 10){
- m="0"+m;
- }
- return h+":"+m;
- }
- this.getTimeDay = function ()
- {
- var Wochentag = new Array("So", "Mo", "Di", "Mi", "Do", "Fr", "Sa");
- var wday = Wochentag[this.getTimeStart().getDay()];
- var day = this.getTimeStart().getDate();
- var month = this.getTimeStart().getMonth()+1;
- var year = this.getTimeStart().getFullYear();
-
- return wday+". "+day+"."+month+"."+year;
- }
- this.getTimeEnd = function ()
- {
- var date = new Date((parseInt(this.startTime)+parseInt(this.duration))*1000);
- return date;
- }
- this.getTimeEndString = function ()
- {
- var h = this.getTimeEnd().getHours();
- var m = this.getTimeEnd().getMinutes();
- if (m < 10){
- m="0"+m;
- }
- return h+":"+m;
- }
- this.getDuration = function ()
- {
- return new Date(parseInt(this.duration)*1000);
- }
- this.getTitle = function ()
- {
- return this.title;
- }
- this.getDescription = function ()
- {
- return this.description;
- }
- this.getDescriptionExtended = function ()
- {
- return this.descriptionE;
- }
- this.getServiceReference = function ()
- {
- return this.serviceRef;
- }
- this.getServiceName = function ()
- {
- return this.serviceName.replace(" "," ");
- }
-}//END class EPGEvent
-//+++++++++++++++++++++++++++++++++++++++++++++++++++++
-//+++++++++++++++++++++++++++++++++++++++++++++++++++++
-//++++ GUI functions ++++
-//+++++++++++++++++++++++++++++++++++++++++++++++++++++
-//+++++++++++++++++++++++++++++++++++++++++++++++++++++
-var currentBodyMainElement = null
-
-function setBodyMainContent(newelementname){
- newelement =document.getElementById(newelementname);
- if(currentBodyMainElement != null){
- currentBodyMainElement.style.display = "none";
-
- }
- newelement.style.display = "inline";
- currentBodyMainElement = newelement;
-}
-function doRequest(url,readyFunction){
-
- http_request =getHTTPObject();
- if(readyFunction){
- http_request.onreadystatechange = readyFunction;
- }
- http_request.open('GET', url, true);
- http_request.send(null);
- return http_request;
-}
-//+++++++++++++++++++++++++++++++++++++++++++++++++++++
-//+++++++++++++++++++++++++++++++++++++++++++++++++++++
-//++++ volume functions ++++
-//+++++++++++++++++++++++++++++++++++++++++++++++++++++
-//+++++++++++++++++++++++++++++++++++++++++++++++++++++
-
-
-function getVolume()
-{
- doRequest(url_getvolume,handleVolumeRequest);
-}
-function setVolume(newvalue)
-{
- doRequest(url_setvolume+newvalue,handleVolumeRequest);
-}
-function volumeUp()
-{
- doRequest(url_volumeup,handleVolumeRequest);
-}
-function volumeDown()
-{
- doRequest(url_volumedown,handleVolumeRequest);
-}
-function volumeMute()
-{
- doRequest(url_volumemute,handleVolumeRequest);
-}
-function handleVolumeRequest(){
- if (http_request.readyState == 4) {
- var a = http_request.responseText.split("\n");
- var newvalue = a[1];
- var mute=a[2];
- set("Volume_Current",newvalue);
- for (var i = 1; i <= 10; i++)
- {
- if ( (newvalue/10)>=i){
- $("volume"+i).src = "/webdata/gfx/led_on.png";
- }else{
- $("volume"+i).src = "/webdata/gfx/led_off.png";
- }
- }
- if (mute == "notmuted"){
- $("speaker").src = "/webdata/gfx/speak_on.png";
- }else{
- $("speaker").src = "/webdata/gfx/speak_off.png";
- }
- }
-}
-//+++++++++++++++++++++++++++++++++++++++++++++++++++++
-//+++++++++++++++++++++++++++++++++++++++++++++++++++++
-//++++ Bouqet managing functions ++++
-//+++++++++++++++++++++++++++++++++++++++++++++++++++++
-//+++++++++++++++++++++++++++++++++++++++++++++++++++++
- function loadRootTVBouqet(){
- //rootB = '/web/fetchchannels?ServiceListBrowse='+escape('1:7:1:0:0:0:0:0:0:0:(type == 1) FROM BOUQUET "bouquets.tv" ORDER BY bouquet');
- rootB = '/web/fetchchannels?ServiceListBrowse='+escape('1:7:1:0:0:0:0:0:0:0:(type == 1) || (type == 17) || (type == 195) || (type == 25) FROM BOUQUET "bouquets.tv" ORDER BY bouquet');
-
-
- loadRootBouqet(rootB);
- }
- function loadRootBouqet(rootB){
-
- t =getHTTPObject();
- t.onreadystatechange = incomingResult;
- t.open('GET', rootB, true);
- t.send(null);
-
- }
- function incomingResult(){
- if((t.readyState == 4) && (t.status == 200)) {
- // perfekt!
- var r = t.responseXML;
-
- var b = r.getElementsByTagName("e2servicelist").item(0).getElementsByTagName("e2service");
-
- bouquets = new Array();
- for ( var i=0; i < b.length; i++){
- bRef = b.item(i).getElementsByTagName('e2servicereference').item(0).firstChild.data;
- bName = b.item(i).getElementsByTagName('e2servicename').item(0).firstChild.data;
-
- bu = new Array(bName,bRef);
- bouquets.push(bu)
- }
- refreshSelect(bouquets);
- } else {
- // die Anfrage enthielt Fehler;
- // die Antwort war z.B. 404 (nicht gefunden)
- // oder 500 (interner Server-Fehler)
- }
-
- }
- // to add the bouqetts to the list
- function refreshSelect(arraybouqet){
-
- sel = document.getElementById("accordionMenueBouqetContent");
- // options neu eintragen
- html = "<table>";
- for ( var i = 0 ; i < arraybouqet.length ; i++ ){
- if(arraybouqet[i][0] && arraybouqet[i][1]){
- html+="<tr><td>";
- html+="<a onclick=\"bouqetSelected(this); setBodyMainContent('BodyContentChannellist');\" id='";
- html+= arraybouqet[i][1];
- html+="'>";
- html+= arraybouqet[i][0];
- html+="</a>";
- html+="</td></tr>";
- }
- }
- html+="</table>";
- sel.innerHTML=html;
- refreshChannellist(arraybouqet[0][0],arraybouqet[0][1]);
- }
- //++++++++++++++++++++++
- function bouqetSelected(element){
- refreshChannellist(element.value,element.id)
- }
-
- function refreshChannellist(bname,bref){
- urlx = '/web/fetchchannels?ServiceListBrowse='+escape(bref);
- w =getHTTPObject();
- w.onreadystatechange = incomingChannellist;
- w.open('GET', urlx, true);
- w.send(null);
-
-
-
- }
- function incomingChannellist(){
- if (w.readyState == 4) {
- // alles in Ordnung, Antwort wurde empfangen
- if (w.responseXML != "no data"){
- var services = w.responseXML.getElementsByTagName("e2servicelist").item(0).getElementsByTagName("e2service");
- listerHtml = "<table id=\"ChannelSelect\" >";
-
- for ( var i = 0; i < (services.length ); i++){
- sRef = services.item(i).getElementsByTagName('e2servicereference').item(0).firstChild.data;
- sName = services.item(i).getElementsByTagName('e2servicename').item(0).firstChild.data;
-
- listerHtml += '<tr bgcolor="gray"><td><div onclick=\"zap(this)\" id="';
- listerHtml += sRef;
- listerHtml += '">';
- listerHtml += sName;
- listerHtml += '</div></td>';
- listerHtml += '<td><a onclick=\"new EPGList().getByServiceReference(this.id,$(\'BodyEPGPanel\'));setBodyMainContent(\'BodyEPGPanel\');\" id="';
- listerHtml += sRef;
- listerHtml += '" >EPG</div><div><a target=\"blank" href=\"stream.m3u?ref=';
- listerHtml += sRef;
- listerHtml += '\">Stream</a></div></td>';
- listerHtml += '</tr>';
- }
- listerHtml += "</table>";
- document.getElementById("BodyContentChannellist").innerHTML = listerHtml;
- setBodyMainContent('BodyContentChannellist');
- } else {
- // die Anfrage enthielt Fehler;
- // die Antwort war z.B. 404 (nicht gefunden)
- // oder 500 (interner Server-Fehler)
- }
- }
-
- }
-
-
-
+++ /dev/null
-<e2:screen name="TestScreen"><?xml version="1.0" encoding="utf-8"?>
-<e2eventlist><e2:element source="EPGNOWNEXT" id="ref"><e2:convert type="web:ListFiller" >
- <e2event>
- <e2eventid><e2:item name="EventID" /> </e2eventid>
- <e2eventstart><e2:item name="TimeStart"/> </e2eventstart>
- <e2eventduration><e2:item name="Duration"/> </e2eventduration>
- <e2eventtitle><e2:item name="Title"/> </e2eventtitle>
- <e2eventdescription><e2:item name="Description"/> </e2eventdescription>
- <e2eventdescriptionextended><e2:item name="DescriptionExtended"/> </e2eventdescriptionextended>
- <e2eventservicereference><e2:item name="ServiceReference"/> </e2eventservicereference>
- <e2eventservicename><e2:item name="ServiceName"/> </e2eventservicename>
- </e2event></e2:convert><e2:convert type="web:TextToHTML" /></e2:element>
-</e2eventlist>
-</e2:screen>
\ No newline at end of file
+++ /dev/null
-<e2:screen name="TestScreen"><?xml version="1.0"?>
-<e2eventlist><e2:element source="EPGTITLE" id="search"><e2:convert type="web:ListFiller" >
- <e2event>
- <e2eventid><e2:item name="EventID" /> </e2eventid>
- <e2eventstart><e2:item name="TimeStart"/> </e2eventstart>
- <e2eventduration><e2:item name="Duration"/> </e2eventduration>
- <e2eventtitle><e2:item name="Title"/> </e2eventtitle>
- <e2eventdescription><e2:item name="Description"/> </e2eventdescription>
- <e2eventdescriptionextended><e2:item name="DescriptionExtended"/> </e2eventdescriptionextended>
- <e2eventservicereference><e2:item name="ServiceReference"/> </e2eventservicereference>
- <e2eventservicename><e2:item name="ServiceName"/> </e2eventservicename>
- </e2event></e2:convert><e2:convert type="web:TextToHTML" /></e2:element>
-</e2eventlist>
-</e2:screen>
\ No newline at end of file
+++ /dev/null
-<e2:screen name="TestScreen"><?xml version="1.0" encoding="utf-8"?>
-<e2eventlist><e2:element source="EPGSERVICE" id="ref"><e2:convert type="web:ListFiller" >
- <e2event>
- <e2eventid><e2:item name="EventID" /> </e2eventid>
- <e2eventstart><e2:item name="TimeStart"/> </e2eventstart>
- <e2eventduration><e2:item name="Duration"/> </e2eventduration>
- <e2eventtitle><e2:item name="Title"/> </e2eventtitle>
- <e2eventdescription><e2:item name="Description"/> </e2eventdescription>
- <e2eventdescriptionextended><e2:item name="DescriptionExtended"/> </e2eventdescriptionextended>
- <e2eventservicereference><e2:item name="ServiceReference"/> </e2eventservicereference>
- <e2eventservicename><e2:item name="ServiceName"/> </e2eventservicename>
- </e2event></e2:convert><e2:convert type="web:TextToHTML" /></e2:element>
-</e2eventlist>
-</e2:screen>
\ No newline at end of file
+++ /dev/null
-<e2:screen name="TestScreen"><?xml version="1.0" encoding="UTF-8"?>
-<e2servicelist>
-<e2:element source="ServiceListBrowse">
- <e2:convert type="web:ListFiller">
- <e2service>
- <e2servicereference><e2:item name="Reference" /></e2servicereference>
- <e2servicename><e2:item name="Name"/></e2servicename>
- </e2service>
- </e2:convert>
- <e2:convert type="web:TextToHTML" />
-</e2:element>
-</e2servicelist>
-</e2:screen>
\ No newline at end of file
+++ /dev/null
-<e2:screen name="TestScreen"><html>
-<head>
- <meta content="text/html; charset=UTF-8" http-equiv="content-type"/>
- <title>Enigma2 Webinterface</title>
- <script src="/webdata/prototype.js" type="text/javascript"/>
- <script src="/webdata/rico.js" type="text/javascript"/>
- <script src="/webdata/tools.js" type="text/javascript" />
- <link href="/webdata/theme.css" rel="stylesheet" type="text/css" />
-</head>
-
-<body>
-<div id="debug"></div>
-
-<table id="htmlDesignTable" width="100%" border="0">
-<tr><td>
-<!-- START SITE HEADER //-->
- <table width="100%" border="0">
- <tr>
- <td width="10%" rowspan="2">
- <div id="Current_Channel_Box" class="roundme" >
- <nobr><div id="CurrentService" > </div></nobr>
- <div id="CurrentServiceProvider" > </div>
- </div>
- </td>
- <td width="80%">
- <span id="Event_Now_Name" onclick="setBodyMainContent('BodyContentEPGNow')"> </span>
- </td>
- <td width="150" rowspan="2">
- <div id="Info_Box" class="roundme">
- <table width="100">
- <tr><td colspan="2"><div id="CurrentTime"> </div></td></tr>
- <tr><td>SNR:</td><td><div id="SNR"></div></td></tr>
- <tr><td>BER:</td><td><div id="BER"></div></td></tr>
- <tr><td>AGC:</td><td><div id="AGC"></div></td></tr>
- </table>
- </div>
- </td>
- </tr><tr>
-
- <td width="80%">
- <span id="Event_Next_Name" onclick="setBodyMainContent('BodyContentEPGNext')"> </span>
- </td>
- </tr>
- <tr><td colspan="2">
- Volume <span id="Volume_Current" >..</span>
- <span onclick="volumeUp()" >++</span>
- <span onclick="volumeDown()" >--</span>
- <span onclick="volumeMute()" >xx</span>
- <img src="/webdata/gfx/led_off.png" id="volume1" onclick="setVolume(10)"/>
- <img src="/webdata/gfx/led_off.png" id="volume2" onclick="setVolume(20)"/>
- <img src="/webdata/gfx/led_off.png" id="volume3" onclick="setVolume(30)"/>
- <img src="/webdata/gfx/led_off.png" id="volume4" onclick="setVolume(40)"/>
- <img src="/webdata/gfx/led_off.png" id="volume5" onclick="setVolume(50)"/>
- <img src="/webdata/gfx/led_off.png" id="volume6" onclick="setVolume(60)"/>
- <img src="/webdata/gfx/led_off.png" id="volume7" onclick="setVolume(70)"/>
- <img src="/webdata/gfx/led_off.png" id="volume8" onclick="setVolume(80)"/>
- <img src="/webdata/gfx/led_off.png" id="volume9" onclick="setVolume(90)"/>
- <img src="/webdata/gfx/led_off.png" id="volume10" onclick="setVolume(100)"/>
- <img src="/webdata/gfx/speak_on.png" id="speaker" onclick="volumeMute()" />
- </td>
- <td>
- <form onSubmit="new EPGList().getBySearchString($('searchText').value,$('BodyEPGPanel')); setBodyMainContent('BodyEPGPanel'); return false;">
- <input type="text" id="searchText" onfocus="this.value=''" value="EPG suchen"/>
- </form>
- </td>
- </tr>
- </table>
-
-<!-- END SITE HEADER //-->
-</td></tr>
-<tr><td>
-<!-- START SITE BODY //-->
- <table id="htmlDesignTableBody" width="100%" border="0">
- <tr>
- <td id="htmlDesignTableBodyMenue" width="150" valign="top">
- <!-- START BODY MENUE //-->
- <div id="accordionMenue">
- <div id="accordionMenueBouqetPanel">
- <div id="accordionMenueBouqetHeader">
- Bouquets
- </div>
- <div id="accordionMenueBouqetContent">
-
- </div>
- </div>
- <!--<div id="accordionMenueControlPanel">
- <div id="accordionMenueControlHeader">
- Control
- </div>
- <div id="accordionMenueControlContent">
- <table>
- <tr><td><a onclick="setBodyMainContent('BodyContentMessageform')">Nachricht</a></td></tr>
- <tr><td><a onclick="setBodyMainContent('BodyContentPower')">Shutdown</a></td></tr>
- <tr><td><a onclick="setBodyMainContent('BodyContentHDD')">HDD</a></td></tr>
- <tr><td><a onclick="setBodyMainContent('BodyContentDebugbox')">JscriptDebug</a></td></tr>
- </table>
- </div>
- </div>//-->
- </div>
-
- <!-- END BODY MENUE //-->
- </td>
- <td id="htmlDesignTableBodyMain" valign="top" witdh="100%" >
- <!-- START BODY MAIN //-->
- <!-- START BodyContentEPGNext //-->
- <div id="BodyContentEPGNext" style="display:none;" >
- <div id="Event_Next_Box">
- <table id="Event_Table_Next" width="100%" border="1">
- <tr>
- <td>
- <span id="Event_Next_Begin"></span> bis <span id="Event_Next_End"></span>
- </td>
- <td>
- <span id="Event_Next_Name" onclick="setBodyMainContent('BodyContentEPGNext')"> </span>
- <a href="javascript:imdb()">...</a>
- </td>
- <td>
- <span id="Event_Next_Remaining"> </span>
- </td>
- </tr>
- <tr>
- <td colspan="3">
- <div id="Event_Next_Description"> </div>
- </td>
- </tr>
- <tr>
- <td colspan="3">
- <div id="Event_Next_Extended_Description"> </div>
- </td>
- </tr>
- </table>
- </div>
- </div>
- <!-- ENDE BodyContentEPGNext //-->
- <!-- START BodyContentEPGNow //-->
- <div id="BodyContentEPGNow" style="display:none;">
- <div id="Event_Now_Box">
- <table id="Event_Table_Now" width="100%" border="1">
- <tr>
- <td>
- <span id="Event_Now_Begin"></span> bis <span id="Event_Now_End"></span>
- </td>
- <td>
- <span id="Event_Now_Name" onclick="setBodyMainContent('BodyContentEPGNow')"> </span>
- <a href="javascript:imdb()">...</a>
- </td>
- <td>
- <span id="Event_Now_Remaining"> </span>
- </td>
- </tr>
- <tr>
- <td colspan="3">
- <div id="Event_Now_Description"> </div>
- </td>
- </tr>
- <tr>
- <td colspan="3">
- <div id="Event_Now_Extended_Description"> </div>
- </td>
- </tr>
- </table>
- </div>
- </div>
- <!-- END BodyContentEPGNow //-->
- <!-- START BodyContentChannellist //-->
- <div id="BodyContentChannellist" style="display:none;"></div>
- <!-- END BodyContentChannellist //-->
- <!-- START BodyContentMessageform //-->
- <div id="BodyContentMessageform" style="display:none;">
- BodyContentText BodyContentText BodyContentText BodyContentText
- </div>
- <!-- END BodyContentMessageform //-->
- <!-- START BodyContentPower //-->
- <div id="BodyContentPower" style="display:none;">
- standby, Poweroff, E2restart
- </div>
- <!-- END BodyContentPower //-->
- <!-- START BodyContentHDD //-->
- <div id="BodyContentHDD" style="display:none;">
- <iframe src="/hdd/" width="100%" height="400"/>
- </div>
- <!-- END BodyContentHDD //-->
- <!-- START BodyContentDebugbox //-->
- <div id="BodyContentDebugbox" style="display:none;">
-
- </div>
- <!-- END BodyContentDebugbox //-->
- <!-- START BodyEPGPanel //-->
- <div id="BodyEPGPanel" style="display:none;">
-
- </div>
- <!-- END BodyEPGPanel //-->
-
- <!-- END CHANNELLIST //-->
- <!-- END BODY MAIN //-->
- </td>
- </tr>
- </table>
-<!-- END SITE BODY //-->
-</td></tr>
-</table>
-
-
-<script type="text/javascript" >
-// HTML Effekts by wwwopenrico.org
-new Rico.Effect.Round('div','roundme' );
-new Rico.Effect.Round('div','button' );
-new Rico.Accordion( $('accordionMenue') );
-//
-getVolume();
-loadRootTVBouqet();
-//loadRootRadioBouqet();
-setBodyMainContent('BodyContentChannellist');
-function updatePage()
-{
-}
-
-function imdb()
-{
- w = window.open("http://www.imdb.com/find?s=all&q=" + escape(document.getElementById("Event_Now_Name").innerHTML));
- w.focus();
-}
-
-</script>
-</body>
-<div id="scriptzone">
-<!-- realtime updates follow -->
-<e2:element source="CurrentTime" streaming="yes">
- <e2:convert type="ClockToText">WithSeconds</e2:convert>
- <e2:convert type="web:JavascriptUpdate" />
-</e2:element>
-<e2:element source="CurrentService" streaming="yes">
- <e2:convert type="ServiceName">Name</e2:convert>
- <e2:convert type="web:JavascriptUpdate" />
-</e2:element>
-<e2:element source="Event_Now" id="Event_Now_Name" streaming="yes">
- <e2:convert type="EventName">Name</e2:convert>
- <e2:convert type="web:JavascriptUpdate" />
-</e2:element>
-<e2:element source="Event_Now" id="Event_Now_Description" streaming="yes">
- <e2:convert type="EventName">Description</e2:convert>
- <e2:convert type="web:JavascriptUpdate" />
-</e2:element>
-<e2:element source="Event_Now" id="Event_Now_Extended_Description" streaming="yes">
- <e2:convert type="EventName">ExtendedDescription</e2:convert>
- <e2:convert type="web:JavascriptUpdate" />
-</e2:element>
-<e2:element source="Event_Now" id="Event_Now_Begin" streaming="yes">
- <e2:convert type="EventTime">StartTime</e2:convert>
- <e2:convert type="ClockToText">Default</e2:convert>
- <e2:convert type="web:JavascriptUpdate" />
-</e2:element>
-<e2:element source="Event_Now" id="Event_Now_End" streaming="yes">
- <e2:convert type="EventTime">EndTime</e2:convert>
- <e2:convert type="ClockToText">Default</e2:convert>
- <e2:convert type="web:JavascriptUpdate" />
-</e2:element>
-<e2:element source="Event_Now" id="Event_Now_Remaining" streaming="yes">
- <e2:convert type="EventTime">Remaining</e2:convert>
- <e2:convert type="RemainingToText">InMinutes</e2:convert>
- <e2:convert type="web:JavascriptUpdate" />
-</e2:element>
-
-
-<e2:element source="Event_Next" id="Event_Next_Name" streaming="yes">
- <e2:convert type="EventName">Name</e2:convert>
- <e2:convert type="web:JavascriptUpdate" />
-</e2:element>
-<e2:element source="Event_Next" id="Event_Next_Begin" streaming="yes">
- <e2:convert type="EventTime">StartTime</e2:convert>
- <e2:convert type="ClockToText">Default</e2:convert>
- <e2:convert type="web:JavascriptUpdate" />
-</e2:element>
-<e2:element source="Event_Next" id="Event_Next_End" streaming="yes">
- <e2:convert type="EventTime">EndTime</e2:convert>
- <e2:convert type="ClockToText">Default</e2:convert>
- <e2:convert type="web:JavascriptUpdate" />
-</e2:element>
-<e2:element source="Event_Next" id="Event_Next_Remaining" streaming="yes">
- <e2:convert type="EventTime">Remaining</e2:convert>
- <e2:convert type="RemainingToText">InMinutes</e2:convert>
- <e2:convert type="web:JavascriptUpdate" />
-</e2:element>
-<e2:element source="Event_Next" id="Event_Next_Extended_Description" streaming="yes">
- <e2:convert type="EventName">ExtendedDescription</e2:convert>
- <e2:convert type="web:JavascriptUpdate" />
-</e2:element>
-
-
-<e2:element source="FrontendStatus" id="SNR" streaming="yes">
- <e2:convert type="FrontendInfo">SNR</e2:convert>
- <e2:convert type="web:JavascriptUpdate" />
-</e2:element>
-<e2:element source="FrontendStatus" id="BER" streaming="yes">
- <e2:convert type="FrontendInfo">BER</e2:convert>
- <e2:convert type="web:JavascriptUpdate" />
-</e2:element>
-<e2:element source="FrontendStatus" id="AGC" streaming="yes">
- <e2:convert type="FrontendInfo">AGC</e2:convert>
- <e2:convert type="web:JavascriptUpdate" />
-</e2:element>
-
-
-<e2:element source="CurrentService" id="CurrentServiceProvider" streaming="yes">
- <e2:convert type="ServiceName">Provider</e2:convert>
- <e2:convert type="web:JavascriptUpdate" />
-</e2:element>
-
-
-
-</e2:screen>
+++ /dev/null
-<e2:screen name="StreamingM3U">#EXTM3U
-#EXTVLCOPT--http-reconnect=true
-http://<e2:element source="localip" />:8001/<e2:element source="ref"><e2:convert type="web:TextToHTML" /></e2:element>
-</e2:screen>
+++ /dev/null
-<e2:screen name="Streaming"><e2:element source="StreamService" streaming="yes">
-<e2:convert type="Streaming" />
-<e2:convert type="web:TextToHTML" />
-</e2:element></e2:screen>
+++ /dev/null
-<e2:screen name="TestScreen"><?xml version="1.0" encoding="utf-8"?>
-<e2timerlist><e2:element source="TimerList" ><e2:convert type="web:ListFiller" >
- <e2timer>
- <e2servicereference><e2:item name="ServiceReference" /></e2servicereference>
- <e2servicename><e2:item name="ServiceName" /></e2servicename>
- <e2eit><e2:item name="EIT" /></e2eit>
- <e2name><e2:item name="Name" /></e2name>
- <e2description><e2:item name="Description" /></e2description>
- <e2disabled><e2:item name="Disabled" /></e2disabled>
- <e2timebegin><e2:item name="TimeBegin" /></e2timebegin>
- <e2timeend><e2:item name="TimeEnd" /></e2timeend>
- <e2duration><e2:item name="Duration" /></e2duration>
- <e2startprepare><e2:item name="startPrepare" /></e2startprepare>
- <e2justplay><e2:item name="justPlay" /></e2justplay>
- <e2afterevent><e2:item name="afterEvent" /></e2afterevent>
- <e2logentries><e2:item name="LogEntries" /></e2logentries>
- <e2filename><e2:item name="Filename" /></e2filename>
- <e2backoff><e2:item name="Backoff" /></e2backoff>
- <e2nextactivation><e2:item name="nextActivation" /></e2nextactivation>
- <e2firsttryprepare><e2:item name="firstTryPrepare" /></e2firsttryprepare>
- <e2state><e2:item name="State" /></e2state>
- <e2repeated><e2:item name="Repeated" /></e2repeated>
- <e2dontsave><e2:item name="dontSave" /></e2dontsave>
- <e2cancled><e2:item name="Cancled" /></e2cancled>
- </e2timer>
- </e2:convert>
- <e2:convert type="web:TextToHTML" /></e2:element>
-</e2timerlist>
-</e2:screen>
\ No newline at end of file
+++ /dev/null
-<e2:screen name="TestScreen">
-<e2:element source="Volume" id="set">
-<e2:convert type="VolumeToText">CurrentVolume</e2:convert>
-</e2:element>
-</e2:screen>
+++ /dev/null
-<e2:screen name="TestScreen"><e2:element source="ServiceList" id="ZapTo">
- <e2:convert type="web:Null" />
-</e2:element></e2:screen>
+++ /dev/null
-#
-# OK, this is more than a proof of concept
-# things to improve:
-# - nicer code
-# - screens need to be defined somehow else.
-# I don't know how, yet. Probably each in an own file.
-# - more components, like the channellist
-# - better error handling
-# - use namespace parser
-
-from Screens.Screen import Screen
-from Tools.Import import my_import
-
-# for our testscreen
-from Screens.InfoBarGenerics import InfoBarServiceName, InfoBarEvent, InfoBarTuner
-
-from Components.Sources.Clock import Clock
-from Components.Sources.ServiceList import ServiceList
-from Components.Sources.Volume import Volume
-from Components.Sources.EPG import EPG
-from Components.Sources.Timer import Timer
-from Components.Sources.FrontendStatus import FrontendStatus
-
-from Components.Converter.Converter import Converter
-from Components.Converter.VolumeToText import VolumeToText
-
-from Components.Element import Element
-
-from xml.sax import make_parser
-from xml.sax.handler import ContentHandler, feature_namespaces
-from twisted.python import util
-import sys
-import time
-
-# prototype of the new web frontend template system.
-
-class WebScreen(Screen):
- def __init__(self, session):
- Screen.__init__(self, session)
- self.stand_alone = True
-
-# a test screen
-class TestScreen(InfoBarServiceName, InfoBarEvent,InfoBarTuner, WebScreen,Volume):
- def __init__(self, session):
- WebScreen.__init__(self, session)
- InfoBarServiceName.__init__(self)
- InfoBarEvent.__init__(self)
- InfoBarTuner.__init__(self)
- Volume.__init__(self,session);
- self["CurrentTime"] = Clock()
-# self["TVSystem"] = Config(config.av.tvsystem)
-# self["OSDLanguage"] = Config(config.osd.language)
-# self["FirstRun"] = Config(config.misc.firstrun)
- from enigma import eServiceReference
- fav = eServiceReference('1:7:1:0:0:0:0:0:0:0:(type == 1) || (type == 17) || (type == 195) || (type == 25) FROM BOUQUET "bouquets.tv" ORDER BY bouquet')
- self["ServiceList"] = ServiceList(fav, command_func = self.zapTo, validate_commands=False)
- self["ServiceListBrowse"] = ServiceList(fav, command_func = self.browseTo)
- self["Volume"] = Volume(session)
- self["EPGTITLE"] = EPG(session,func=EPG.TITLE)
- self["EPGSERVICE"] = EPG(session,func=EPG.SERVICE)
- self["EPGNOWNEXT"] = EPG(session,func=EPG.NOWNEXT)
- self["TimerList"] = Timer(session)
-
- def browseTo(self, reftobrowse):
- self["ServiceListBrowse"].root = reftobrowse
-
- def zapTo(self, reftozap):
- self.session.nav.playService(reftozap)
-
-# TODO: (really.) put screens into own files.
-class Streaming(WebScreen):
- def __init__(self, session):
- WebScreen.__init__(self, session)
- from Components.Sources.StreamService import StreamService
- self["StreamService"] = StreamService(self.session.nav)
-
-class StreamingM3U(WebScreen):
- def __init__(self, session):
- WebScreen.__init__(self, session)
- from Components.Sources.StaticText import StaticText
- from Components.Sources.Config import Config
- from Components.config import config
-
- self["ref"] = StaticText()
- self["localip"] = Config(config.network.ip)
-
-# implements the 'render'-call.
-# this will act as a downstream_element, like a renderer.
-class OneTimeElement(Element):
- def __init__(self, id):
- Element.__init__(self)
- self.source_id = id
-
- # CHECKME: is this ok performance-wise?
- def handleCommand(self, args):
- for c in args.get(self.source_id, []):
- self.source.handleCommand(c)
-
- def render(self, stream):
- t = self.source.getHTML(self.source_id)
- if isinstance(t, unicode):
- t = t.encode("utf-8")
- stream.write(t)
-
- def execBegin(self):
- pass
-
- def execEnd(self):
- pass
-
- def onShow(self):
- pass
-
- def onHide(self):
- pass
-
- def destroy(self):
- pass
-
-class StreamingElement(OneTimeElement):
- def __init__(self, id):
- OneTimeElement.__init__(self, id)
- self.stream = None
-
- def changed(self, what):
- if self.stream:
- self.render(self.stream)
-
- def setStream(self, stream):
- self.stream = stream
-
-# a to-be-filled list item
-class ListItem:
- def __init__(self, name):
- self.name = name
-
-class TextToHTML(Converter):
- def __init__(self, arg):
- Converter.__init__(self, arg)
-
- def getHTML(self, id):
- return self.source.text # encode & etc. here!
-
-# a null-output. Useful if you only want to issue a command.
-class Null(Converter):
- def __init__(self, arg):
- Converter.__init__(self, arg)
-
- def getHTML(self, id):
- return ""
-
-def escape(s):
- return s.replace("\\", "\\\\").replace("\n", "\\n").replace('"', '\\"')
-
-class JavascriptUpdate(Converter):
- def __init__(self, arg):
- Converter.__init__(self, arg)
-
- def getHTML(self, id):
- return '<script>set("' + id + '", "' + escape(self.source.text) + '");</script>\n'
-
-# the performant 'listfiller'-engine (plfe)
-class ListFiller(Converter):
- def __init__(self, arg):
- Converter.__init__(self, arg)
-
- def getText(self):
- l = self.source.list
- lut = self.source.lut
-
- # now build a ["string", 1, "string", 2]-styled list, with indices into the
- # list to avoid lookup of item name for each entry
- lutlist = []
- for element in self.converter_arguments:
- if isinstance(element, str):
- lutlist.append(element)
- elif isinstance(element, ListItem):
- lutlist.append(lut[element.name])
-
- # now, for the huge list, do:
- res = ""
- for item in l:
- for element in lutlist:
- if isinstance(element, str):
- res += element
- else:
- res += str(item[element])
- # (this will be done in c++ later!)
- return res
-
- text = property(getText)
-
-class webifHandler(ContentHandler):
- def __init__(self, session):
- self.res = [ ]
- self.mode = 0
- self.screen = None
- self.session = session
- self.screens = [ ]
-
- def startElement(self, name, attrs):
- if name == "e2:screen":
- self.screen = eval(attrs["name"])(self.session) # fixme
- self.screens.append(self.screen)
- return
-
- if name[:3] == "e2:":
- self.mode += 1
-
- tag = "<" + name + ''.join([' ' + key + '="' + val + '"' for (key, val) in attrs.items()]) + ">"
- tag = tag.encode("UTF-8")
-
- if self.mode == 0:
- self.res.append(tag)
- elif self.mode == 1: # expect "<e2:element>"
- assert name == "e2:element", "found %s instead of e2:element" % name
- source = attrs["source"]
- self.source_id = str(attrs.get("id", source))
- self.source = self.screen[source]
- self.is_streaming = "streaming" in attrs
- elif self.mode == 2: # expect "<e2:convert>"
- if name[:3] == "e2:":
- assert name == "e2:convert"
-
- ctype = attrs["type"]
- if ctype[:4] == "web:": # for now
- self.converter = eval(ctype[4:])
- else:
- self.converter = my_import('.'.join(["Components", "Converter", ctype])).__dict__.get(ctype)
- self.sub = [ ]
- else:
- self.sub.append(tag)
- elif self.mode == 3:
- assert name == "e2:item", "found %s instead of e2:item!" % name
- assert "name" in attrs, "e2:item must have a name= attribute!"
- self.sub.append(ListItem(attrs["name"]))
-
- def endElement(self, name):
- if name == "e2:screen":
- self.screen = None
- return
-
- tag = "</" + name + ">"
- if self.mode == 0:
- self.res.append(tag)
- elif self.mode == 2 and name[:3] != "e2:":
- self.sub.append(tag)
- elif self.mode == 2: # closed 'convert' -> sub
- self.sub = lreduce(self.sub)
- if len(self.sub) == 1:
- self.sub = self.sub[0]
- c = self.converter(self.sub)
- c.connect(self.source)
- self.source = c
-
- del self.sub
- elif self.mode == 1: # closed 'element'
- # instatiate either a StreamingElement or a OneTimeElement, depending on what's required.
- if not self.is_streaming:
- c = OneTimeElement(self.source_id)
- else:
- c = StreamingElement(self.source_id)
-
- c.connect(self.source)
- self.res.append(c)
- self.screen.renderer.append(c)
- del self.source
-
- if name[:3] == "e2:":
- self.mode -= 1
-
- def processingInstruction(self, target, data):
- self.res.append('<?' + target + ' ' + data + '>')
-
- def characters(self, ch):
- ch = ch.encode("UTF-8")
- if self.mode == 0:
- self.res.append(ch)
- elif self.mode == 2:
- self.sub.append(ch)
-
- def startEntity(self, name):
- self.res.append('&' + name + ';');
-
- def execBegin(self):
- for screen in self.screens:
- screen.execBegin()
-
- def cleanup(self):
- print "screen cleanup!"
- for screen in self.screens:
- screen.execEnd()
- screen.doClose()
- self.screens = [ ]
-
-def lreduce(list):
- # ouch, can be made better
- res = [ ]
- string = None
- for x in list:
- if isinstance(x, str) or isinstance(x, unicode):
- if isinstance(x, unicode):
- x = x.encode("UTF-8")
- if string is None:
- string = x
- else:
- string += x
- else:
- if string is not None:
- res.append(string)
- string = None
- res.append(x)
- if string is not None:
- res.append(string)
- string = None
- return res
-
-def renderPage(stream, path, req, session):
-
- # read in the template, create required screens
- # we don't have persistense yet.
- # if we had, this first part would only be done once.
- handler = webifHandler(session)
- parser = make_parser()
- parser.setFeature(feature_namespaces, 0)
- parser.setContentHandler(handler)
- parser.parse(open(util.sibpath(__file__, path)))
-
- # by default, we have non-streaming pages
- finish = True
-
- # first, apply "commands" (aka. URL argument)
- for x in handler.res:
- if isinstance(x, Element):
- x.handleCommand(req.args)
-
- handler.execBegin()
-
- # now, we have a list with static texts mixed
- # with non-static Elements.
- # flatten this list, write into the stream.
- for x in lreduce(handler.res):
- if isinstance(x, Element):
- if isinstance(x, StreamingElement):
- finish = False
- x.setStream(stream)
- x.render(stream)
- else:
- stream.write(str(x))
-
- def ping(s):
- from twisted.internet import reactor
- s.write("\n");
- reactor.callLater(3, ping, s)
-
- # if we met a "StreamingElement", there is at least one
- # element which wants to output data more than once,
- # i.e. on host-originated changes.
- # in this case, don't finish yet, don't cleanup yet,
- # but instead do that when the client disconnects.
- if finish:
- handler.cleanup()
- stream.finish()
- else:
- # ok.
- # you *need* something which constantly sends something in a regular interval,
- # in order to detect disconnected clients.
- # i agree that this "ping" sucks terrible, so better be sure to have something
- # similar. A "CurrentTime" is fine. Or anything that creates *some* output.
- ping(stream)
- stream.closed_callback = lambda: handler.cleanup()
--- /dev/null
+installdir = /usr/lib/enigma2/python/Plugins/Extensions/WebInterface/web-data/
+
+install_DATA = *.js
+
+SUBDIRS = gfx
--- /dev/null
+installdir = /usr/lib/enigma2/python/Plugins/Extensions/WebInterface/web-data/gfx/
+
+install_DATA = *.png
--- /dev/null
+/* Prototype JavaScript framework, version 1.4.0
+ * (c) 2005 Sam Stephenson <sam@conio.net>
+ *
+ * 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: '(?:<script.*?>)((\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 '#<Enumerable:' + this.toArray().inspect() + '>';
+ }
+}
+
+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 '#<Hash:{' + this.map(function(pair) {
+ return pair.map(Object.inspect).join(': ');
+ }).join(', ') + '}>';
+ }
+}
+
+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 = '<table><tbody>' + this.content + '</tbody></table>';
+ 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
--- /dev/null
+/**
+ *
+ * Copyright 2005 Sabre Airline Solutions
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
+ * file except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific language governing permissions
+ * and limitations under the License.
+ **/
+
+
+//-------------------- rico.js
+var Rico = {
+ Version: '1.1.2',
+ prototypeVersion: parseFloat(Prototype.Version.split(".")[0] + "." + Prototype.Version.split(".")[1])
+}
+
+if((typeof Prototype=='undefined') || Rico.prototypeVersion < 1.3)
+ throw("Rico requires the Prototype JavaScript framework >= 1.3");
+
+Rico.ArrayExtensions = new Array();
+
+if (Object.prototype.extend) {
+ Rico.ArrayExtensions[ Rico.ArrayExtensions.length ] = Object.prototype.extend;
+}else{
+ Object.prototype.extend = function(object) {
+ return Object.extend.apply(this, [this, object]);
+ }
+ Rico.ArrayExtensions[ Rico.ArrayExtensions.length ] = Object.prototype.extend;
+}
+
+if (Array.prototype.push) {
+ Rico.ArrayExtensions[ Rico.ArrayExtensions.length ] = Array.prototype.push;
+}
+
+if (!Array.prototype.remove) {
+ Array.prototype.remove = function(dx) {
+ if( isNaN(dx) || dx > this.length )
+ return false;
+ for( var i=0,n=0; i<this.length; i++ )
+ if( i != dx )
+ this[n++]=this[i];
+ this.length-=1;
+ };
+ Rico.ArrayExtensions[ Rico.ArrayExtensions.length ] = Array.prototype.remove;
+}
+
+if (!Array.prototype.removeItem) {
+ Array.prototype.removeItem = function(item) {
+ for ( var i = 0 ; i < this.length ; i++ )
+ if ( this[i] == item ) {
+ this.remove(i);
+ break;
+ }
+ };
+ Rico.ArrayExtensions[ Rico.ArrayExtensions.length ] = Array.prototype.removeItem;
+}
+
+if (!Array.prototype.indices) {
+ Array.prototype.indices = function() {
+ var indexArray = new Array();
+ for ( index in this ) {
+ var ignoreThis = false;
+ for ( var i = 0 ; i < Rico.ArrayExtensions.length ; i++ ) {
+ if ( this[index] == Rico.ArrayExtensions[i] ) {
+ ignoreThis = true;
+ break;
+ }
+ }
+ if ( !ignoreThis )
+ indexArray[ indexArray.length ] = index;
+ }
+ return indexArray;
+ }
+ Rico.ArrayExtensions[ Rico.ArrayExtensions.length ] = Array.prototype.indices;
+}
+
+// Create the loadXML method and xml getter for Mozilla
+if ( window.DOMParser &&
+ window.XMLSerializer &&
+ window.Node && Node.prototype && Node.prototype.__defineGetter__ ) {
+
+ if (!Document.prototype.loadXML) {
+ Document.prototype.loadXML = function (s) {
+ var doc2 = (new DOMParser()).parseFromString(s, "text/xml");
+ while (this.hasChildNodes())
+ this.removeChild(this.lastChild);
+
+ for (var i = 0; i < doc2.childNodes.length; i++) {
+ this.appendChild(this.importNode(doc2.childNodes[i], true));
+ }
+ };
+ }
+
+ Document.prototype.__defineGetter__( "xml",
+ function () {
+ return (new XMLSerializer()).serializeToString(this);
+ }
+ );
+}
+
+document.getElementsByTagAndClassName = function(tagName, className) {
+ if ( tagName == null )
+ tagName = '*';
+
+ var children = document.getElementsByTagName(tagName) || document.all;
+ var elements = new Array();
+
+ if ( className == null )
+ return children;
+
+ for (var i = 0; i < children.length; i++) {
+ var child = children[i];
+ var classNames = child.className.split(' ');
+ for (var j = 0; j < classNames.length; j++) {
+ if (classNames[j] == className) {
+ elements.push(child);
+ break;
+ }
+ }
+ }
+
+ return elements;
+}
+
+
+//-------------------- ricoAccordion.js
+Rico.Accordion = Class.create();
+
+Rico.Accordion.prototype = {
+
+ initialize: function(container, options) {
+ this.container = $(container);
+ this.lastExpandedTab = null;
+ this.accordionTabs = new Array();
+ this.setOptions(options);
+ this._attachBehaviors();
+ if(!container) return;
+
+ this.container.style.borderBottom = '1px solid ' + this.options.borderColor;
+ // validate onloadShowTab
+ if (this.options.onLoadShowTab >= this.accordionTabs.length)
+ this.options.onLoadShowTab = 0;
+
+ // set the initial visual state...
+ for ( var i=0 ; i < this.accordionTabs.length ; i++ )
+ {
+ if (i != this.options.onLoadShowTab){
+ this.accordionTabs[i].collapse();
+ this.accordionTabs[i].content.style.display = 'none';
+ }
+ }
+ this.lastExpandedTab = this.accordionTabs[this.options.onLoadShowTab];
+ if (this.options.panelHeight == 'auto'){
+ var tabToCheck = (this.options.onloadShowTab === 0)? 1 : 0;
+ var titleBarSize = parseInt(RicoUtil.getElementsComputedStyle(this.accordionTabs[tabToCheck].titleBar, 'height'));
+ if (isNaN(titleBarSize))
+ titleBarSize = this.accordionTabs[tabToCheck].titleBar.offsetHeight;
+
+ var totalTitleBarSize = this.accordionTabs.length * titleBarSize;
+ var parentHeight = parseInt(RicoUtil.getElementsComputedStyle(this.container.parentNode, 'height'));
+ if (isNaN(parentHeight))
+ parentHeight = this.container.parentNode.offsetHeight;
+
+ this.options.panelHeight = parentHeight - totalTitleBarSize-2;
+ }
+
+ this.lastExpandedTab.content.style.height = this.options.panelHeight + "px";
+ this.lastExpandedTab.showExpanded();
+ this.lastExpandedTab.titleBar.style.fontWeight = this.options.expandedFontWeight;
+
+ },
+
+ setOptions: function(options) {
+ this.options = {
+ expandedBg : '#63699c',
+ hoverBg : '#63699c',
+ collapsedBg : '#6b79a5',
+ expandedTextColor : '#ffffff',
+ expandedFontWeight : 'bold',
+ hoverTextColor : '#ffffff',
+ collapsedTextColor : '#ced7ef',
+ collapsedFontWeight : 'normal',
+ hoverTextColor : '#ffffff',
+ borderColor : '#1f669b',
+ panelHeight : 200,
+ onHideTab : null,
+ onShowTab : null,
+ onLoadShowTab : 0
+ }
+ Object.extend(this.options, options || {});
+ },
+
+ showTabByIndex: function( anIndex, animate ) {
+ var doAnimate = arguments.length == 1 ? true : animate;
+ this.showTab( this.accordionTabs[anIndex], doAnimate );
+ },
+
+ showTab: function( accordionTab, animate ) {
+ if ( this.lastExpandedTab == accordionTab )
+ return;
+
+ var doAnimate = arguments.length == 1 ? true : animate;
+
+ if ( this.options.onHideTab )
+ this.options.onHideTab(this.lastExpandedTab);
+
+ this.lastExpandedTab.showCollapsed();
+ var accordion = this;
+ var lastExpandedTab = this.lastExpandedTab;
+
+ this.lastExpandedTab.content.style.height = (this.options.panelHeight - 1) + 'px';
+ accordionTab.content.style.display = '';
+
+ accordionTab.titleBar.style.fontWeight = this.options.expandedFontWeight;
+
+ if ( doAnimate ) {
+ new Rico.Effect.AccordionSize( this.lastExpandedTab.content,
+ accordionTab.content,
+ 1,
+ this.options.panelHeight,
+ 100, 10,
+ { complete: function() {accordion.showTabDone(lastExpandedTab)} } );
+ this.lastExpandedTab = accordionTab;
+ }
+ else {
+ this.lastExpandedTab.content.style.height = "1px";
+ accordionTab.content.style.height = this.options.panelHeight + "px";
+ this.lastExpandedTab = accordionTab;
+ this.showTabDone(lastExpandedTab);
+ }
+ },
+
+ showTabDone: function(collapsedTab) {
+ collapsedTab.content.style.display = 'none';
+ this.lastExpandedTab.showExpanded();
+ if ( this.options.onShowTab )
+ this.options.onShowTab(this.lastExpandedTab);
+ },
+
+ _attachBehaviors: function() {
+ var panels = this._getDirectChildrenByTag(this.container, 'DIV');
+ for ( var i = 0 ; i < panels.length ; i++ ) {
+
+ var tabChildren = this._getDirectChildrenByTag(panels[i],'DIV');
+ if ( tabChildren.length != 2 )
+ continue; // unexpected
+
+ var tabTitleBar = tabChildren[0];
+ var tabContentBox = tabChildren[1];
+ this.accordionTabs.push( new Rico.Accordion.Tab(this,tabTitleBar,tabContentBox) );
+ }
+ },
+
+ _getDirectChildrenByTag: function(e, tagName) {
+ var kids = new Array();
+ var allKids = e.childNodes;
+ for( var i = 0 ; i < allKids.length ; i++ )
+ if ( allKids[i] && allKids[i].tagName && allKids[i].tagName == tagName )
+ kids.push(allKids[i]);
+ return kids;
+ }
+
+};
+
+Rico.Accordion.Tab = Class.create();
+
+Rico.Accordion.Tab.prototype = {
+
+ initialize: function(accordion, titleBar, content) {
+ this.accordion = accordion;
+ this.titleBar = titleBar;
+ this.content = content;
+ this._attachBehaviors();
+ },
+
+ collapse: function() {
+ this.showCollapsed();
+ this.content.style.height = "1px";
+ },
+
+ showCollapsed: function() {
+ this.expanded = false;
+ this.titleBar.style.backgroundColor = this.accordion.options.collapsedBg;
+ this.titleBar.style.color = this.accordion.options.collapsedTextColor;
+ this.titleBar.style.fontWeight = this.accordion.options.collapsedFontWeight;
+ this.content.style.overflow = "hidden";
+ },
+
+ showExpanded: function() {
+ this.expanded = true;
+ this.titleBar.style.backgroundColor = this.accordion.options.expandedBg;
+ this.titleBar.style.color = this.accordion.options.expandedTextColor;
+ this.content.style.overflow = "auto";
+ },
+
+ titleBarClicked: function(e) {
+ if ( this.accordion.lastExpandedTab == this )
+ return;
+ this.accordion.showTab(this);
+ },
+
+ hover: function(e) {
+ this.titleBar.style.backgroundColor = this.accordion.options.hoverBg;
+ this.titleBar.style.color = this.accordion.options.hoverTextColor;
+ },
+
+ unhover: function(e) {
+ if ( this.expanded ) {
+ this.titleBar.style.backgroundColor = this.accordion.options.expandedBg;
+ this.titleBar.style.color = this.accordion.options.expandedTextColor;
+ }
+ else {
+ this.titleBar.style.backgroundColor = this.accordion.options.collapsedBg;
+ this.titleBar.style.color = this.accordion.options.collapsedTextColor;
+ }
+ },
+
+ _attachBehaviors: function() {
+ this.content.style.border = "1px solid " + this.accordion.options.borderColor;
+ this.content.style.borderTopWidth = "0px";
+ this.content.style.borderBottomWidth = "0px";
+ this.content.style.margin = "0px";
+
+ this.titleBar.onclick = this.titleBarClicked.bindAsEventListener(this);
+ this.titleBar.onmouseover = this.hover.bindAsEventListener(this);
+ this.titleBar.onmouseout = this.unhover.bindAsEventListener(this);
+ }
+
+};
+
+
+//-------------------- ricoAjaxEngine.js
+Rico.AjaxEngine = Class.create();
+
+Rico.AjaxEngine.prototype = {
+
+ initialize: function() {
+ this.ajaxElements = new Array();
+ this.ajaxObjects = new Array();
+ this.requestURLS = new Array();
+ this.options = {};
+ },
+
+ registerAjaxElement: function( anId, anElement ) {
+ if ( !anElement )
+ anElement = $(anId);
+ this.ajaxElements[anId] = anElement;
+ },
+
+ registerAjaxObject: function( anId, anObject ) {
+ this.ajaxObjects[anId] = anObject;
+ },
+
+ registerRequest: function (requestLogicalName, requestURL) {
+ this.requestURLS[requestLogicalName] = requestURL;
+ },
+
+ sendRequest: function(requestName, options) {
+ // Allow for backwards Compatibility
+ if ( arguments.length >= 2 )
+ if (typeof arguments[1] == 'string')
+ options = {parameters: this._createQueryString(arguments, 1)};
+ this.sendRequestWithData(requestName, null, options);
+ },
+
+ sendRequestWithData: function(requestName, xmlDocument, options) {
+ var requestURL = this.requestURLS[requestName];
+ if ( requestURL == null )
+ return;
+
+ // Allow for backwards Compatibility
+ if ( arguments.length >= 3 )
+ if (typeof arguments[2] == 'string')
+ options.parameters = this._createQueryString(arguments, 2);
+
+ new Ajax.Request(requestURL, this._requestOptions(options,xmlDocument));
+ },
+
+ sendRequestAndUpdate: function(requestName,container,options) {
+ // Allow for backwards Compatibility
+ if ( arguments.length >= 3 )
+ if (typeof arguments[2] == 'string')
+ options.parameters = this._createQueryString(arguments, 2);
+
+ this.sendRequestWithDataAndUpdate(requestName, null, container, options);
+ },
+
+ sendRequestWithDataAndUpdate: function(requestName,xmlDocument,container,options) {
+ var requestURL = this.requestURLS[requestName];
+ if ( requestURL == null )
+ return;
+
+ // Allow for backwards Compatibility
+ if ( arguments.length >= 4 )
+ if (typeof arguments[3] == 'string')
+ options.parameters = this._createQueryString(arguments, 3);
+
+ var updaterOptions = this._requestOptions(options,xmlDocument);
+
+ new Ajax.Updater(container, requestURL, updaterOptions);
+ },
+
+ // Private -- not part of intended engine API --------------------------------------------------------------------
+
+ _requestOptions: function(options,xmlDoc) {
+ var requestHeaders = ['X-Rico-Version', Rico.Version ];
+ var sendMethod = 'post';
+ if ( xmlDoc == null )
+ if (Rico.prototypeVersion < 1.4)
+ requestHeaders.push( 'Content-type', 'text/xml' );
+ else
+ sendMethod = 'get';
+ (!options) ? options = {} : '';
+
+ if (!options._RicoOptionsProcessed){
+ // Check and keep any user onComplete functions
+ if (options.onComplete)
+ options.onRicoComplete = options.onComplete;
+ // Fix onComplete
+ if (options.overrideOnComplete)
+ options.onComplete = options.overrideOnComplete;
+ else
+ options.onComplete = this._onRequestComplete.bind(this);
+ options._RicoOptionsProcessed = true;
+ }
+
+ // Set the default options and extend with any user options
+ this.options = {
+ requestHeaders: requestHeaders,
+ parameters: options.parameters,
+ postBody: xmlDoc,
+ method: sendMethod,
+ onComplete: options.onComplete
+ };
+ // Set any user options:
+ Object.extend(this.options, options);
+ return this.options;
+ },
+
+ _createQueryString: function( theArgs, offset ) {
+ var queryString = ""
+ for ( var i = offset ; i < theArgs.length ; i++ ) {
+ if ( i != offset )
+ queryString += "&";
+
+ var anArg = theArgs[i];
+
+ if ( anArg.name != undefined && anArg.value != undefined ) {
+ queryString += anArg.name + "=" + escape(anArg.value);
+ }
+ else {
+ var ePos = anArg.indexOf('=');
+ var argName = anArg.substring( 0, ePos );
+ var argValue = anArg.substring( ePos + 1 );
+ queryString += argName + "=" + escape(argValue);
+ }
+ }
+ return queryString;
+ },
+
+ _onRequestComplete : function(request) {
+ if(!request)
+ return;
+ // User can set an onFailure option - which will be called by prototype
+ if (request.status != 200)
+ return;
+
+ var response = request.responseXML.getElementsByTagName("ajax-response");
+ if (response == null || response.length != 1)
+ return;
+ this._processAjaxResponse( response[0].childNodes );
+
+ // Check if user has set a onComplete function
+ var onRicoComplete = this.options.onRicoComplete;
+ if (onRicoComplete != null)
+ onRicoComplete();
+ },
+
+ _processAjaxResponse: function( xmlResponseElements ) {
+ for ( var i = 0 ; i < xmlResponseElements.length ; i++ ) {
+ var responseElement = xmlResponseElements[i];
+
+ // only process nodes of type element.....
+ if ( responseElement.nodeType != 1 )
+ continue;
+
+ var responseType = responseElement.getAttribute("type");
+ var responseId = responseElement.getAttribute("id");
+
+ if ( responseType == "object" )
+ this._processAjaxObjectUpdate( this.ajaxObjects[ responseId ], responseElement );
+ else if ( responseType == "element" )
+ this._processAjaxElementUpdate( this.ajaxElements[ responseId ], responseElement );
+ else
+ alert('unrecognized AjaxResponse type : ' + responseType );
+ }
+ },
+
+ _processAjaxObjectUpdate: function( ajaxObject, responseElement ) {
+ ajaxObject.ajaxUpdate( responseElement );
+ },
+
+ _processAjaxElementUpdate: function( ajaxElement, responseElement ) {
+ ajaxElement.innerHTML = RicoUtil.getContentAsString(responseElement);
+ }
+
+}
+
+var ajaxEngine = new Rico.AjaxEngine();
+
+
+//-------------------- ricoColor.js
+Rico.Color = Class.create();
+
+Rico.Color.prototype = {
+
+ initialize: function(red, green, blue) {
+ this.rgb = { r: red, g : green, b : blue };
+ },
+
+ setRed: function(r) {
+ this.rgb.r = r;
+ },
+
+ setGreen: function(g) {
+ this.rgb.g = g;
+ },
+
+ setBlue: function(b) {
+ this.rgb.b = b;
+ },
+
+ setHue: function(h) {
+
+ // get an HSB model, and set the new hue...
+ var hsb = this.asHSB();
+ hsb.h = h;
+
+ // convert back to RGB...
+ this.rgb = Rico.Color.HSBtoRGB(hsb.h, hsb.s, hsb.b);
+ },
+
+ setSaturation: function(s) {
+ // get an HSB model, and set the new hue...
+ var hsb = this.asHSB();
+ hsb.s = s;
+
+ // convert back to RGB and set values...
+ this.rgb = Rico.Color.HSBtoRGB(hsb.h, hsb.s, hsb.b);
+ },
+
+ setBrightness: function(b) {
+ // get an HSB model, and set the new hue...
+ var hsb = this.asHSB();
+ hsb.b = b;
+
+ // convert back to RGB and set values...
+ this.rgb = Rico.Color.HSBtoRGB( hsb.h, hsb.s, hsb.b );
+ },
+
+ darken: function(percent) {
+ var hsb = this.asHSB();
+ this.rgb = Rico.Color.HSBtoRGB(hsb.h, hsb.s, Math.max(hsb.b - percent,0));
+ },
+
+ brighten: function(percent) {
+ var hsb = this.asHSB();
+ this.rgb = Rico.Color.HSBtoRGB(hsb.h, hsb.s, Math.min(hsb.b + percent,1));
+ },
+
+ blend: function(other) {
+ this.rgb.r = Math.floor((this.rgb.r + other.rgb.r)/2);
+ this.rgb.g = Math.floor((this.rgb.g + other.rgb.g)/2);
+ this.rgb.b = Math.floor((this.rgb.b + other.rgb.b)/2);
+ },
+
+ isBright: function() {
+ var hsb = this.asHSB();
+ return this.asHSB().b > 0.5;
+ },
+
+ isDark: function() {
+ return ! this.isBright();
+ },
+
+ asRGB: function() {
+ return "rgb(" + this.rgb.r + "," + this.rgb.g + "," + this.rgb.b + ")";
+ },
+
+ asHex: function() {
+ return "#" + this.rgb.r.toColorPart() + this.rgb.g.toColorPart() + this.rgb.b.toColorPart();
+ },
+
+ asHSB: function() {
+ return Rico.Color.RGBtoHSB(this.rgb.r, this.rgb.g, this.rgb.b);
+ },
+
+ toString: function() {
+ return this.asHex();
+ }
+
+};
+
+Rico.Color.createFromHex = function(hexCode) {
+ if(hexCode.length==4) {
+ var shortHexCode = hexCode;
+ var hexCode = '#';
+ for(var i=1;i<4;i++) hexCode += (shortHexCode.charAt(i) +
+shortHexCode.charAt(i));
+ }
+ if ( hexCode.indexOf('#') == 0 )
+ hexCode = hexCode.substring(1);
+ var red = hexCode.substring(0,2);
+ var green = hexCode.substring(2,4);
+ var blue = hexCode.substring(4,6);
+ return new Rico.Color( parseInt(red,16), parseInt(green,16), parseInt(blue,16) );
+}
+
+/**
+ * Factory method for creating a color from the background of
+ * an HTML element.
+ */
+Rico.Color.createColorFromBackground = function(elem) {
+
+ var actualColor = RicoUtil.getElementsComputedStyle($(elem), "backgroundColor", "background-color");
+
+ if ( actualColor == "transparent" && elem.parentNode )
+ return Rico.Color.createColorFromBackground(elem.parentNode);
+
+ if ( actualColor == null )
+ return new Rico.Color(255,255,255);
+
+ if ( actualColor.indexOf("rgb(") == 0 ) {
+ var colors = actualColor.substring(4, actualColor.length - 1 );
+ var colorArray = colors.split(",");
+ return new Rico.Color( parseInt( colorArray[0] ),
+ parseInt( colorArray[1] ),
+ parseInt( colorArray[2] ) );
+
+ }
+ else if ( actualColor.indexOf("#") == 0 ) {
+ return Rico.Color.createFromHex(actualColor);
+ }
+ else
+ return new Rico.Color(255,255,255);
+}
+
+Rico.Color.HSBtoRGB = function(hue, saturation, brightness) {
+
+ var red = 0;
+ var green = 0;
+ var blue = 0;
+
+ if (saturation == 0) {
+ red = parseInt(brightness * 255.0 + 0.5);
+ green = red;
+ blue = red;
+ }
+ else {
+ var h = (hue - Math.floor(hue)) * 6.0;
+ var f = h - Math.floor(h);
+ var p = brightness * (1.0 - saturation);
+ var q = brightness * (1.0 - saturation * f);
+ var t = brightness * (1.0 - (saturation * (1.0 - f)));
+
+ switch (parseInt(h)) {
+ case 0:
+ red = (brightness * 255.0 + 0.5);
+ green = (t * 255.0 + 0.5);
+ blue = (p * 255.0 + 0.5);
+ break;
+ case 1:
+ red = (q * 255.0 + 0.5);
+ green = (brightness * 255.0 + 0.5);
+ blue = (p * 255.0 + 0.5);
+ break;
+ case 2:
+ red = (p * 255.0 + 0.5);
+ green = (brightness * 255.0 + 0.5);
+ blue = (t * 255.0 + 0.5);
+ break;
+ case 3:
+ red = (p * 255.0 + 0.5);
+ green = (q * 255.0 + 0.5);
+ blue = (brightness * 255.0 + 0.5);
+ break;
+ case 4:
+ red = (t * 255.0 + 0.5);
+ green = (p * 255.0 + 0.5);
+ blue = (brightness * 255.0 + 0.5);
+ break;
+ case 5:
+ red = (brightness * 255.0 + 0.5);
+ green = (p * 255.0 + 0.5);
+ blue = (q * 255.0 + 0.5);
+ break;
+ }
+ }
+
+ return { r : parseInt(red), g : parseInt(green) , b : parseInt(blue) };
+}
+
+Rico.Color.RGBtoHSB = function(r, g, b) {
+
+ var hue;
+ var saturation;
+ var brightness;
+
+ var cmax = (r > g) ? r : g;
+ if (b > cmax)
+ cmax = b;
+
+ var cmin = (r < g) ? r : g;
+ if (b < cmin)
+ cmin = b;
+
+ brightness = cmax / 255.0;
+ if (cmax != 0)
+ saturation = (cmax - cmin)/cmax;
+ else
+ saturation = 0;
+
+ if (saturation == 0)
+ hue = 0;
+ else {
+ var redc = (cmax - r)/(cmax - cmin);
+ var greenc = (cmax - g)/(cmax - cmin);
+ var bluec = (cmax - b)/(cmax - cmin);
+
+ if (r == cmax)
+ hue = bluec - greenc;
+ else if (g == cmax)
+ hue = 2.0 + redc - bluec;
+ else
+ hue = 4.0 + greenc - redc;
+
+ hue = hue / 6.0;
+ if (hue < 0)
+ hue = hue + 1.0;
+ }
+
+ return { h : hue, s : saturation, b : brightness };
+}
+
+
+//-------------------- ricoCorner.js
+Rico.Corner = {
+
+ round: function(e, options) {
+ var e = $(e);
+ this._setOptions(options);
+
+ var color = this.options.color;
+ if ( this.options.color == "fromElement" )
+ color = this._background(e);
+
+ var bgColor = this.options.bgColor;
+ if ( this.options.bgColor == "fromParent" )
+ bgColor = this._background(e.offsetParent);
+
+ this._roundCornersImpl(e, color, bgColor);
+ },
+
+ _roundCornersImpl: function(e, color, bgColor) {
+ if(this.options.border)
+ this._renderBorder(e,bgColor);
+ if(this._isTopRounded())
+ this._roundTopCorners(e,color,bgColor);
+ if(this._isBottomRounded())
+ this._roundBottomCorners(e,color,bgColor);
+ },
+
+ _renderBorder: function(el,bgColor) {
+ var borderValue = "1px solid " + this._borderColor(bgColor);
+ var borderL = "border-left: " + borderValue;
+ var borderR = "border-right: " + borderValue;
+ var style = "style='" + borderL + ";" + borderR + "'";
+ el.innerHTML = "<div " + style + ">" + el.innerHTML + "</div>"
+ },
+
+ _roundTopCorners: function(el, color, bgColor) {
+ var corner = this._createCorner(bgColor);
+ for(var i=0 ; i < this.options.numSlices ; i++ )
+ corner.appendChild(this._createCornerSlice(color,bgColor,i,"top"));
+ el.style.paddingTop = 0;
+ el.insertBefore(corner,el.firstChild);
+ },
+
+ _roundBottomCorners: function(el, color, bgColor) {
+ var corner = this._createCorner(bgColor);
+ for(var i=(this.options.numSlices-1) ; i >= 0 ; i-- )
+ corner.appendChild(this._createCornerSlice(color,bgColor,i,"bottom"));
+ el.style.paddingBottom = 0;
+ el.appendChild(corner);
+ },
+
+ _createCorner: function(bgColor) {
+ var corner = document.createElement("div");
+ corner.style.backgroundColor = (this._isTransparent() ? "transparent" : bgColor);
+ return corner;
+ },
+
+ _createCornerSlice: function(color,bgColor, n, position) {
+ var slice = document.createElement("span");
+
+ var inStyle = slice.style;
+ inStyle.backgroundColor = color;
+ inStyle.display = "block";
+ inStyle.height = "1px";
+ inStyle.overflow = "hidden";
+ inStyle.fontSize = "1px";
+
+ var borderColor = this._borderColor(color,bgColor);
+ if ( this.options.border && n == 0 ) {
+ inStyle.borderTopStyle = "solid";
+ inStyle.borderTopWidth = "1px";
+ inStyle.borderLeftWidth = "0px";
+ inStyle.borderRightWidth = "0px";
+ inStyle.borderBottomWidth = "0px";
+ inStyle.height = "0px"; // assumes css compliant box model
+ inStyle.borderColor = borderColor;
+ }
+ else if(borderColor) {
+ inStyle.borderColor = borderColor;
+ inStyle.borderStyle = "solid";
+ inStyle.borderWidth = "0px 1px";
+ }
+
+ if ( !this.options.compact && (n == (this.options.numSlices-1)) )
+ inStyle.height = "2px";
+
+ this._setMargin(slice, n, position);
+ this._setBorder(slice, n, position);
+ return slice;
+ },
+
+ _setOptions: function(options) {
+ this.options = {
+ corners : "all",
+ color : "fromElement",
+ bgColor : "fromParent",
+ blend : true,
+ border : false,
+ compact : false
+ }
+ Object.extend(this.options, options || {});
+
+ this.options.numSlices = this.options.compact ? 2 : 4;
+ if ( this._isTransparent() )
+ this.options.blend = false;
+ },
+
+ _whichSideTop: function() {
+ if ( this._hasString(this.options.corners, "all", "top") )
+ return "";
+
+ if ( this.options.corners.indexOf("tl") >= 0 && this.options.corners.indexOf("tr") >= 0 )
+ return "";
+
+ if (this.options.corners.indexOf("tl") >= 0)
+ return "left";
+ else if (this.options.corners.indexOf("tr") >= 0)
+ return "right";
+ return "";
+ },
+
+ _whichSideBottom: function() {
+ if ( this._hasString(this.options.corners, "all", "bottom") )
+ return "";
+
+ if ( this.options.corners.indexOf("bl")>=0 && this.options.corners.indexOf("br")>=0 )
+ return "";
+
+ if(this.options.corners.indexOf("bl") >=0)
+ return "left";
+ else if(this.options.corners.indexOf("br")>=0)
+ return "right";
+ return "";
+ },
+
+ _borderColor : function(color,bgColor) {
+ if ( color == "transparent" )
+ return bgColor;
+ else if ( this.options.border )
+ return this.options.border;
+ else if ( this.options.blend )
+ return this._blend( bgColor, color );
+ else
+ return "";
+ },
+
+
+ _setMargin: function(el, n, corners) {
+ var marginSize = this._marginSize(n);
+ var whichSide = corners == "top" ? this._whichSideTop() : this._whichSideBottom();
+
+ if ( whichSide == "left" ) {
+ el.style.marginLeft = marginSize + "px"; el.style.marginRight = "0px";
+ }
+ else if ( whichSide == "right" ) {
+ el.style.marginRight = marginSize + "px"; el.style.marginLeft = "0px";
+ }
+ else {
+ el.style.marginLeft = marginSize + "px"; el.style.marginRight = marginSize + "px";
+ }
+ },
+
+ _setBorder: function(el,n,corners) {
+ var borderSize = this._borderSize(n);
+ var whichSide = corners == "top" ? this._whichSideTop() : this._whichSideBottom();
+ if ( whichSide == "left" ) {
+ el.style.borderLeftWidth = borderSize + "px"; el.style.borderRightWidth = "0px";
+ }
+ else if ( whichSide == "right" ) {
+ el.style.borderRightWidth = borderSize + "px"; el.style.borderLeftWidth = "0px";
+ }
+ else {
+ el.style.borderLeftWidth = borderSize + "px"; el.style.borderRightWidth = borderSize + "px";
+ }
+ if (this.options.border != false)
+ el.style.borderLeftWidth = borderSize + "px"; el.style.borderRightWidth = borderSize + "px";
+ },
+
+ _marginSize: function(n) {
+ if ( this._isTransparent() )
+ return 0;
+
+ var marginSizes = [ 5, 3, 2, 1 ];
+ var blendedMarginSizes = [ 3, 2, 1, 0 ];
+ var compactMarginSizes = [ 2, 1 ];
+ var smBlendedMarginSizes = [ 1, 0 ];
+
+ if ( this.options.compact && this.options.blend )
+ return smBlendedMarginSizes[n];
+ else if ( this.options.compact )
+ return compactMarginSizes[n];
+ else if ( this.options.blend )
+ return blendedMarginSizes[n];
+ else
+ return marginSizes[n];
+ },
+
+ _borderSize: function(n) {
+ var transparentBorderSizes = [ 5, 3, 2, 1 ];
+ var blendedBorderSizes = [ 2, 1, 1, 1 ];
+ var compactBorderSizes = [ 1, 0 ];
+ var actualBorderSizes = [ 0, 2, 0, 0 ];
+
+ if ( this.options.compact && (this.options.blend || this._isTransparent()) )
+ return 1;
+ else if ( this.options.compact )
+ return compactBorderSizes[n];
+ else if ( this.options.blend )
+ return blendedBorderSizes[n];
+ else if ( this.options.border )
+ return actualBorderSizes[n];
+ else if ( this._isTransparent() )
+ return transparentBorderSizes[n];
+ return 0;
+ },
+
+ _hasString: function(str) { for(var i=1 ; i<arguments.length ; i++) if (str.indexOf(arguments[i]) >= 0) return true; return false; },
+ _blend: function(c1, c2) { var cc1 = Rico.Color.createFromHex(c1); cc1.blend(Rico.Color.createFromHex(c2)); return cc1; },
+ _background: function(el) { try { return Rico.Color.createColorFromBackground(el).asHex(); } catch(err) { return "#ffffff"; } },
+ _isTransparent: function() { return this.options.color == "transparent"; },
+ _isTopRounded: function() { return this._hasString(this.options.corners, "all", "top", "tl", "tr"); },
+ _isBottomRounded: function() { return this._hasString(this.options.corners, "all", "bottom", "bl", "br"); },
+ _hasSingleTextChild: function(el) { return el.childNodes.length == 1 && el.childNodes[0].nodeType == 3; }
+}
+
+
+//-------------------- ricoDragAndDrop.js
+Rico.DragAndDrop = Class.create();
+
+Rico.DragAndDrop.prototype = {
+
+ initialize: function() {
+ this.dropZones = new Array();
+ this.draggables = new Array();
+ this.currentDragObjects = new Array();
+ this.dragElement = null;
+ this.lastSelectedDraggable = null;
+ this.currentDragObjectVisible = false;
+ this.interestedInMotionEvents = false;
+ this._mouseDown = this._mouseDownHandler.bindAsEventListener(this);
+ this._mouseMove = this._mouseMoveHandler.bindAsEventListener(this);
+ this._mouseUp = this._mouseUpHandler.bindAsEventListener(this);
+ },
+
+ registerDropZone: function(aDropZone) {
+ this.dropZones[ this.dropZones.length ] = aDropZone;
+ },
+
+ deregisterDropZone: function(aDropZone) {
+ var newDropZones = new Array();
+ var j = 0;
+ for ( var i = 0 ; i < this.dropZones.length ; i++ ) {
+ if ( this.dropZones[i] != aDropZone )
+ newDropZones[j++] = this.dropZones[i];
+ }
+
+ this.dropZones = newDropZones;
+ },
+
+ clearDropZones: function() {
+ this.dropZones = new Array();
+ },
+
+ registerDraggable: function( aDraggable ) {
+ this.draggables[ this.draggables.length ] = aDraggable;
+ this._addMouseDownHandler( aDraggable );
+ },
+
+ clearSelection: function() {
+ for ( var i = 0 ; i < this.currentDragObjects.length ; i++ )
+ this.currentDragObjects[i].deselect();
+ this.currentDragObjects = new Array();
+ this.lastSelectedDraggable = null;
+ },
+
+ hasSelection: function() {
+ return this.currentDragObjects.length > 0;
+ },
+
+ setStartDragFromElement: function( e, mouseDownElement ) {
+ this.origPos = RicoUtil.toDocumentPosition(mouseDownElement);
+ this.startx = e.screenX - this.origPos.x
+ this.starty = e.screenY - this.origPos.y
+ //this.startComponentX = e.layerX ? e.layerX : e.offsetX;
+ //this.startComponentY = e.layerY ? e.layerY : e.offsetY;
+ //this.adjustedForDraggableSize = false;
+
+ this.interestedInMotionEvents = this.hasSelection();
+ this._terminateEvent(e);
+ },
+
+ updateSelection: function( draggable, extendSelection ) {
+ if ( ! extendSelection )
+ this.clearSelection();
+
+ if ( draggable.isSelected() ) {
+ this.currentDragObjects.removeItem(draggable);
+ draggable.deselect();
+ if ( draggable == this.lastSelectedDraggable )
+ this.lastSelectedDraggable = null;
+ }
+ else {
+ this.currentDragObjects[ this.currentDragObjects.length ] = draggable;
+ draggable.select();
+ this.lastSelectedDraggable = draggable;
+ }
+ },
+
+ _mouseDownHandler: function(e) {
+ if ( arguments.length == 0 )
+ e = event;
+
+ // if not button 1 ignore it...
+ var nsEvent = e.which != undefined;
+ if ( (nsEvent && e.which != 1) || (!nsEvent && e.button != 1))
+ return;
+
+ var eventTarget = e.target ? e.target : e.srcElement;
+ var draggableObject = eventTarget.draggable;
+
+ var candidate = eventTarget;
+ while (draggableObject == null && candidate.parentNode) {
+ candidate = candidate.parentNode;
+ draggableObject = candidate.draggable;
+ }
+
+ if ( draggableObject == null )
+ return;
+
+ this.updateSelection( draggableObject, e.ctrlKey );
+
+ // clear the drop zones postion cache...
+ if ( this.hasSelection() )
+ for ( var i = 0 ; i < this.dropZones.length ; i++ )
+ this.dropZones[i].clearPositionCache();
+
+ this.setStartDragFromElement( e, draggableObject.getMouseDownHTMLElement() );
+ },
+
+
+ _mouseMoveHandler: function(e) {
+ var nsEvent = e.which != undefined;
+ if ( !this.interestedInMotionEvents ) {
+ //this._terminateEvent(e);
+ return;
+ }
+
+ if ( ! this.hasSelection() )
+ return;
+
+ if ( ! this.currentDragObjectVisible )
+ this._startDrag(e);
+
+ if ( !this.activatedDropZones )
+ this._activateRegisteredDropZones();
+
+ //if ( !this.adjustedForDraggableSize )
+ // this._adjustForDraggableSize(e);
+
+ this._updateDraggableLocation(e);
+ this._updateDropZonesHover(e);
+
+ this._terminateEvent(e);
+ },
+
+ _makeDraggableObjectVisible: function(e)
+ {
+ if ( !this.hasSelection() )
+ return;
+
+ var dragElement;
+ if ( this.currentDragObjects.length > 1 )
+ dragElement = this.currentDragObjects[0].getMultiObjectDragGUI(this.currentDragObjects);
+ else
+ dragElement = this.currentDragObjects[0].getSingleObjectDragGUI();
+
+ // go ahead and absolute position it...
+ if ( RicoUtil.getElementsComputedStyle(dragElement, "position") != "absolute" )
+ dragElement.style.position = "absolute";
+
+ // need to parent him into the document...
+ if ( dragElement.parentNode == null || dragElement.parentNode.nodeType == 11 )
+ document.body.appendChild(dragElement);
+
+ this.dragElement = dragElement;
+ this._updateDraggableLocation(e);
+
+ this.currentDragObjectVisible = true;
+ },
+
+ /**
+ _adjustForDraggableSize: function(e) {
+ var dragElementWidth = this.dragElement.offsetWidth;
+ var dragElementHeight = this.dragElement.offsetHeight;
+ if ( this.startComponentX > dragElementWidth )
+ this.startx -= this.startComponentX - dragElementWidth + 2;
+ if ( e.offsetY ) {
+ if ( this.startComponentY > dragElementHeight )
+ this.starty -= this.startComponentY - dragElementHeight + 2;
+ }
+ this.adjustedForDraggableSize = true;
+ },
+ **/
+
+ _leftOffset: function(e) {
+ return e.offsetX ? document.body.scrollLeft : 0
+ },
+
+ _topOffset: function(e) {
+ return e.offsetY ? document.body.scrollTop:0
+ },
+
+
+ _updateDraggableLocation: function(e) {
+ var dragObjectStyle = this.dragElement.style;
+ dragObjectStyle.left = (e.screenX + this._leftOffset(e) - this.startx) + "px"
+ dragObjectStyle.top = (e.screenY + this._topOffset(e) - this.starty) + "px";
+ },
+
+ _updateDropZonesHover: function(e) {
+ var n = this.dropZones.length;
+ for ( var i = 0 ; i < n ; i++ ) {
+ if ( ! this._mousePointInDropZone( e, this.dropZones[i] ) )
+ this.dropZones[i].hideHover();
+ }
+
+ for ( var i = 0 ; i < n ; i++ ) {
+ if ( this._mousePointInDropZone( e, this.dropZones[i] ) ) {
+ if ( this.dropZones[i].canAccept(this.currentDragObjects) )
+ this.dropZones[i].showHover();
+ }
+ }
+ },
+
+ _startDrag: function(e) {
+ for ( var i = 0 ; i < this.currentDragObjects.length ; i++ )
+ this.currentDragObjects[i].startDrag();
+
+ this._makeDraggableObjectVisible(e);
+ },
+
+ _mouseUpHandler: function(e) {
+ if ( ! this.hasSelection() )
+ return;
+
+ var nsEvent = e.which != undefined;
+ if ( (nsEvent && e.which != 1) || (!nsEvent && e.button != 1))
+ return;
+
+ this.interestedInMotionEvents = false;
+
+ if ( this.dragElement == null ) {
+ this._terminateEvent(e);
+ return;
+ }
+
+ if ( this._placeDraggableInDropZone(e) )
+ this._completeDropOperation(e);
+ else {
+ this._terminateEvent(e);
+ new Rico.Effect.Position( this.dragElement,
+ this.origPos.x,
+ this.origPos.y,
+ 200,
+ 20,
+ { complete : this._doCancelDragProcessing.bind(this) } );
+ }
+
+ Event.stopObserving(document.body, "mousemove", this._mouseMove);
+ Event.stopObserving(document.body, "mouseup", this._mouseUp);
+ },
+
+ _retTrue: function () {
+ return true;
+ },
+
+ _completeDropOperation: function(e) {
+ if ( this.dragElement != this.currentDragObjects[0].getMouseDownHTMLElement() ) {
+ if ( this.dragElement.parentNode != null )
+ this.dragElement.parentNode.removeChild(this.dragElement);
+ }
+
+ this._deactivateRegisteredDropZones();
+ this._endDrag();
+ this.clearSelection();
+ this.dragElement = null;
+ this.currentDragObjectVisible = false;
+ this._terminateEvent(e);
+ },
+
+ _doCancelDragProcessing: function() {
+ this._cancelDrag();
+
+ if ( this.dragElement != this.currentDragObjects[0].getMouseDownHTMLElement() && this.dragElement)
+ if ( this.dragElement.parentNode != null )
+ this.dragElement.parentNode.removeChild(this.dragElement);
+
+
+ this._deactivateRegisteredDropZones();
+ this.dragElement = null;
+ this.currentDragObjectVisible = false;
+ },
+
+ _placeDraggableInDropZone: function(e) {
+ var foundDropZone = false;
+ var n = this.dropZones.length;
+ for ( var i = 0 ; i < n ; i++ ) {
+ if ( this._mousePointInDropZone( e, this.dropZones[i] ) ) {
+ if ( this.dropZones[i].canAccept(this.currentDragObjects) ) {
+ this.dropZones[i].hideHover();
+ this.dropZones[i].accept(this.currentDragObjects);
+ foundDropZone = true;
+ break;
+ }
+ }
+ }
+
+ return foundDropZone;
+ },
+
+ _cancelDrag: function() {
+ for ( var i = 0 ; i < this.currentDragObjects.length ; i++ )
+ this.currentDragObjects[i].cancelDrag();
+ },
+
+ _endDrag: function() {
+ for ( var i = 0 ; i < this.currentDragObjects.length ; i++ )
+ this.currentDragObjects[i].endDrag();
+ },
+
+ _mousePointInDropZone: function( e, dropZone ) {
+
+ var absoluteRect = dropZone.getAbsoluteRect();
+
+ return e.clientX > absoluteRect.left + this._leftOffset(e) &&
+ e.clientX < absoluteRect.right + this._leftOffset(e) &&
+ e.clientY > absoluteRect.top + this._topOffset(e) &&
+ e.clientY < absoluteRect.bottom + this._topOffset(e);
+ },
+
+ _addMouseDownHandler: function( aDraggable )
+ {
+ htmlElement = aDraggable.getMouseDownHTMLElement();
+ if ( htmlElement != null ) {
+ htmlElement.draggable = aDraggable;
+ Event.observe(htmlElement , "mousedown", this._onmousedown.bindAsEventListener(this));
+ Event.observe(htmlElement, "mousedown", this._mouseDown);
+ }
+ },
+
+ _activateRegisteredDropZones: function() {
+ var n = this.dropZones.length;
+ for ( var i = 0 ; i < n ; i++ ) {
+ var dropZone = this.dropZones[i];
+ if ( dropZone.canAccept(this.currentDragObjects) )
+ dropZone.activate();
+ }
+
+ this.activatedDropZones = true;
+ },
+
+ _deactivateRegisteredDropZones: function() {
+ var n = this.dropZones.length;
+ for ( var i = 0 ; i < n ; i++ )
+ this.dropZones[i].deactivate();
+ this.activatedDropZones = false;
+ },
+
+ _onmousedown: function () {
+ Event.observe(document.body, "mousemove", this._mouseMove);
+ Event.observe(document.body, "mouseup", this._mouseUp);
+ },
+
+ _terminateEvent: function(e) {
+ if ( e.stopPropagation != undefined )
+ e.stopPropagation();
+ else if ( e.cancelBubble != undefined )
+ e.cancelBubble = true;
+
+ if ( e.preventDefault != undefined )
+ e.preventDefault();
+ else
+ e.returnValue = false;
+ },
+
+
+ initializeEventHandlers: function() {
+ if ( typeof document.implementation != "undefined" &&
+ document.implementation.hasFeature("HTML", "1.0") &&
+ document.implementation.hasFeature("Events", "2.0") &&
+ document.implementation.hasFeature("CSS", "2.0") ) {
+ document.addEventListener("mouseup", this._mouseUpHandler.bindAsEventListener(this), false);
+ document.addEventListener("mousemove", this._mouseMoveHandler.bindAsEventListener(this), false);
+ }
+ else {
+ document.attachEvent( "onmouseup", this._mouseUpHandler.bindAsEventListener(this) );
+ document.attachEvent( "onmousemove", this._mouseMoveHandler.bindAsEventListener(this) );
+ }
+ }
+ }
+
+ var dndMgr = new Rico.DragAndDrop();
+ dndMgr.initializeEventHandlers();
+
+
+//-------------------- ricoDraggable.js
+Rico.Draggable = Class.create();
+
+Rico.Draggable.prototype = {
+
+ initialize: function( type, htmlElement ) {
+ this.type = type;
+ this.htmlElement = $(htmlElement);
+ this.selected = false;
+ },
+
+ /**
+ * Returns the HTML element that should have a mouse down event
+ * added to it in order to initiate a drag operation
+ *
+ **/
+ getMouseDownHTMLElement: function() {
+ return this.htmlElement;
+ },
+
+ select: function() {
+ this.selected = true;
+
+ if ( this.showingSelected )
+ return;
+
+ var htmlElement = this.getMouseDownHTMLElement();
+
+ var color = Rico.Color.createColorFromBackground(htmlElement);
+ color.isBright() ? color.darken(0.033) : color.brighten(0.033);
+
+ this.saveBackground = RicoUtil.getElementsComputedStyle(htmlElement, "backgroundColor", "background-color");
+ htmlElement.style.backgroundColor = color.asHex();
+ this.showingSelected = true;
+ },
+
+ deselect: function() {
+ this.selected = false;
+ if ( !this.showingSelected )
+ return;
+
+ var htmlElement = this.getMouseDownHTMLElement();
+
+ htmlElement.style.backgroundColor = this.saveBackground;
+ this.showingSelected = false;
+ },
+
+ isSelected: function() {
+ return this.selected;
+ },
+
+ startDrag: function() {
+ },
+
+ cancelDrag: function() {
+ },
+
+ endDrag: function() {
+ },
+
+ getSingleObjectDragGUI: function() {
+ return this.htmlElement;
+ },
+
+ getMultiObjectDragGUI: function( draggables ) {
+ return this.htmlElement;
+ },
+
+ getDroppedGUI: function() {
+ return this.htmlElement;
+ },
+
+ toString: function() {
+ return this.type + ":" + this.htmlElement + ":";
+ }
+
+}
+
+
+//-------------------- ricoDropzone.js
+Rico.Dropzone = Class.create();
+
+Rico.Dropzone.prototype = {
+
+ initialize: function( htmlElement ) {
+ this.htmlElement = $(htmlElement);
+ this.absoluteRect = null;
+ },
+
+ getHTMLElement: function() {
+ return this.htmlElement;
+ },
+
+ clearPositionCache: function() {
+ this.absoluteRect = null;
+ },
+
+ getAbsoluteRect: function() {
+ if ( this.absoluteRect == null ) {
+ var htmlElement = this.getHTMLElement();
+ var pos = RicoUtil.toViewportPosition(htmlElement);
+
+ this.absoluteRect = {
+ top: pos.y,
+ left: pos.x,
+ bottom: pos.y + htmlElement.offsetHeight,
+ right: pos.x + htmlElement.offsetWidth
+ };
+ }
+ return this.absoluteRect;
+ },
+
+ activate: function() {
+ var htmlElement = this.getHTMLElement();
+ if (htmlElement == null || this.showingActive)
+ return;
+
+ this.showingActive = true;
+ this.saveBackgroundColor = htmlElement.style.backgroundColor;
+
+ var fallbackColor = "#ffea84";
+ var currentColor = Rico.Color.createColorFromBackground(htmlElement);
+ if ( currentColor == null )
+ htmlElement.style.backgroundColor = fallbackColor;
+ else {
+ currentColor.isBright() ? currentColor.darken(0.2) : currentColor.brighten(0.2);
+ htmlElement.style.backgroundColor = currentColor.asHex();
+ }
+ },
+
+ deactivate: function() {
+ var htmlElement = this.getHTMLElement();
+ if (htmlElement == null || !this.showingActive)
+ return;
+
+ htmlElement.style.backgroundColor = this.saveBackgroundColor;
+ this.showingActive = false;
+ this.saveBackgroundColor = null;
+ },
+
+ showHover: function() {
+ var htmlElement = this.getHTMLElement();
+ if ( htmlElement == null || this.showingHover )
+ return;
+
+ this.saveBorderWidth = htmlElement.style.borderWidth;
+ this.saveBorderStyle = htmlElement.style.borderStyle;
+ this.saveBorderColor = htmlElement.style.borderColor;
+
+ this.showingHover = true;
+ htmlElement.style.borderWidth = "1px";
+ htmlElement.style.borderStyle = "solid";
+ //htmlElement.style.borderColor = "#ff9900";
+ htmlElement.style.borderColor = "#ffff00";
+ },
+
+ hideHover: function() {
+ var htmlElement = this.getHTMLElement();
+ if ( htmlElement == null || !this.showingHover )
+ return;
+
+ htmlElement.style.borderWidth = this.saveBorderWidth;
+ htmlElement.style.borderStyle = this.saveBorderStyle;
+ htmlElement.style.borderColor = this.saveBorderColor;
+ this.showingHover = false;
+ },
+
+ canAccept: function(draggableObjects) {
+ return true;
+ },
+
+ accept: function(draggableObjects) {
+ var htmlElement = this.getHTMLElement();
+ if ( htmlElement == null )
+ return;
+
+ n = draggableObjects.length;
+ for ( var i = 0 ; i < n ; i++ )
+ {
+ var theGUI = draggableObjects[i].getDroppedGUI();
+ if ( RicoUtil.getElementsComputedStyle( theGUI, "position" ) == "absolute" )
+ {
+ theGUI.style.position = "static";
+ theGUI.style.top = "";
+ theGUI.style.top = "";
+ }
+ htmlElement.appendChild(theGUI);
+ }
+ }
+}
+
+
+//-------------------- ricoEffects.js
+
+Rico.Effect = {};
+
+Rico.Effect.SizeAndPosition = Class.create();
+Rico.Effect.SizeAndPosition.prototype = {
+
+ initialize: function(element, x, y, w, h, duration, steps, options) {
+ this.element = $(element);
+ this.x = x;
+ this.y = y;
+ this.w = w;
+ this.h = h;
+ this.duration = duration;
+ this.steps = steps;
+ this.options = arguments[7] || {};
+
+ this.sizeAndPosition();
+ },
+
+ sizeAndPosition: function() {
+ if (this.isFinished()) {
+ if(this.options.complete) this.options.complete(this);
+ return;
+ }
+
+ if (this.timer)
+ clearTimeout(this.timer);
+
+ var stepDuration = Math.round(this.duration/this.steps) ;
+
+ // Get original values: x,y = top left corner; w,h = width height
+ var currentX = this.element.offsetLeft;
+ var currentY = this.element.offsetTop;
+ var currentW = this.element.offsetWidth;
+ var currentH = this.element.offsetHeight;
+
+ // If values not set, or zero, we do not modify them, and take original as final as well
+ this.x = (this.x) ? this.x : currentX;
+ this.y = (this.y) ? this.y : currentY;
+ this.w = (this.w) ? this.w : currentW;
+ this.h = (this.h) ? this.h : currentH;
+
+ // how much do we need to modify our values for each step?
+ var difX = this.steps > 0 ? (this.x - currentX)/this.steps : 0;
+ var difY = this.steps > 0 ? (this.y - currentY)/this.steps : 0;
+ var difW = this.steps > 0 ? (this.w - currentW)/this.steps : 0;
+ var difH = this.steps > 0 ? (this.h - currentH)/this.steps : 0;
+
+ this.moveBy(difX, difY);
+ this.resizeBy(difW, difH);
+
+ this.duration -= stepDuration;
+ this.steps--;
+
+ this.timer = setTimeout(this.sizeAndPosition.bind(this), stepDuration);
+ },
+
+ isFinished: function() {
+ return this.steps <= 0;
+ },
+
+ moveBy: function( difX, difY ) {
+ var currentLeft = this.element.offsetLeft;
+ var currentTop = this.element.offsetTop;
+ var intDifX = parseInt(difX);
+ var intDifY = parseInt(difY);
+
+ var style = this.element.style;
+ if ( intDifX != 0 )
+ style.left = (currentLeft + intDifX) + "px";
+ if ( intDifY != 0 )
+ style.top = (currentTop + intDifY) + "px";
+ },
+
+ resizeBy: function( difW, difH ) {
+ var currentWidth = this.element.offsetWidth;
+ var currentHeight = this.element.offsetHeight;
+ var intDifW = parseInt(difW);
+ var intDifH = parseInt(difH);
+
+ var style = this.element.style;
+ if ( intDifW != 0 )
+ style.width = (currentWidth + intDifW) + "px";
+ if ( intDifH != 0 )
+ style.height = (currentHeight + intDifH) + "px";
+ }
+}
+
+Rico.Effect.Size = Class.create();
+Rico.Effect.Size.prototype = {
+
+ initialize: function(element, w, h, duration, steps, options) {
+ new Rico.Effect.SizeAndPosition(element, null, null, w, h, duration, steps, options);
+ }
+}
+
+Rico.Effect.Position = Class.create();
+Rico.Effect.Position.prototype = {
+
+ initialize: function(element, x, y, duration, steps, options) {
+ new Rico.Effect.SizeAndPosition(element, x, y, null, null, duration, steps, options);
+ }
+}
+
+Rico.Effect.Round = Class.create();
+Rico.Effect.Round.prototype = {
+
+ initialize: function(tagName, className, options) {
+ var elements = document.getElementsByTagAndClassName(tagName,className);
+ for ( var i = 0 ; i < elements.length ; i++ )
+ Rico.Corner.round( elements[i], options );
+ }
+};
+
+Rico.Effect.FadeTo = Class.create();
+Rico.Effect.FadeTo.prototype = {
+
+ initialize: function( element, opacity, duration, steps, options) {
+ this.element = $(element);
+ this.opacity = opacity;
+ this.duration = duration;
+ this.steps = steps;
+ this.options = arguments[4] || {};
+ this.fadeTo();
+ },
+
+ fadeTo: function() {
+ if (this.isFinished()) {
+ if(this.options.complete) this.options.complete(this);
+ return;
+ }
+
+ if (this.timer)
+ clearTimeout(this.timer);
+
+ var stepDuration = Math.round(this.duration/this.steps) ;
+ var currentOpacity = this.getElementOpacity();
+ var delta = this.steps > 0 ? (this.opacity - currentOpacity)/this.steps : 0;
+
+ this.changeOpacityBy(delta);
+ this.duration -= stepDuration;
+ this.steps--;
+
+ this.timer = setTimeout(this.fadeTo.bind(this), stepDuration);
+ },
+
+ changeOpacityBy: function(v) {
+ var currentOpacity = this.getElementOpacity();
+ var newOpacity = Math.max(0, Math.min(currentOpacity+v, 1));
+ this.element.ricoOpacity = newOpacity;
+
+ this.element.style.filter = "alpha(opacity:"+Math.round(newOpacity*100)+")";
+ this.element.style.opacity = newOpacity; /*//*/;
+ },
+
+ isFinished: function() {
+ return this.steps <= 0;
+ },
+
+ getElementOpacity: function() {
+ if ( this.element.ricoOpacity == undefined ) {
+ var opacity = RicoUtil.getElementsComputedStyle(this.element, 'opacity');
+ this.element.ricoOpacity = opacity != undefined ? opacity : 1.0;
+ }
+ return parseFloat(this.element.ricoOpacity);
+ }
+}
+
+Rico.Effect.AccordionSize = Class.create();
+
+Rico.Effect.AccordionSize.prototype = {
+
+ initialize: function(e1, e2, start, end, duration, steps, options) {
+ this.e1 = $(e1);
+ this.e2 = $(e2);
+ this.start = start;
+ this.end = end;
+ this.duration = duration;
+ this.steps = steps;
+ this.options = arguments[6] || {};
+
+ this.accordionSize();
+ },
+
+ accordionSize: function() {
+
+ if (this.isFinished()) {
+ // just in case there are round errors or such...
+ this.e1.style.height = this.start + "px";
+ this.e2.style.height = this.end + "px";
+
+ if(this.options.complete)
+ this.options.complete(this);
+ return;
+ }
+
+ if (this.timer)
+ clearTimeout(this.timer);
+
+ var stepDuration = Math.round(this.duration/this.steps) ;
+
+ var diff = this.steps > 0 ? (parseInt(this.e1.offsetHeight) - this.start)/this.steps : 0;
+ this.resizeBy(diff);
+
+ this.duration -= stepDuration;
+ this.steps--;
+
+ this.timer = setTimeout(this.accordionSize.bind(this), stepDuration);
+ },
+
+ isFinished: function() {
+ return this.steps <= 0;
+ },
+
+ resizeBy: function(diff) {
+ var h1Height = this.e1.offsetHeight;
+ var h2Height = this.e2.offsetHeight;
+ var intDiff = parseInt(diff);
+ if ( diff != 0 ) {
+ this.e1.style.height = (h1Height - intDiff) + "px";
+ this.e2.style.height = (h2Height + intDiff) + "px";
+ }
+ }
+
+};
+
+
+//-------------------- ricoLiveGrid.js
+// Rico.LiveGridMetaData -----------------------------------------------------
+
+Rico.LiveGridMetaData = Class.create();
+
+Rico.LiveGridMetaData.prototype = {
+
+ initialize: function( pageSize, totalRows, columnCount, options ) {
+ this.pageSize = pageSize;
+ this.totalRows = totalRows;
+ this.setOptions(options);
+ this.ArrowHeight = 16;
+ this.columnCount = columnCount;
+ },
+
+ setOptions: function(options) {
+ this.options = {
+ largeBufferSize : 7.0, // 7 pages
+ nearLimitFactor : 0.2 // 20% of buffer
+ };
+ Object.extend(this.options, options || {});
+ },
+
+ getPageSize: function() {
+ return this.pageSize;
+ },
+
+ getTotalRows: function() {
+ return this.totalRows;
+ },
+
+ setTotalRows: function(n) {
+ this.totalRows = n;
+ },
+
+ getLargeBufferSize: function() {
+ return parseInt(this.options.largeBufferSize * this.pageSize);
+ },
+
+ getLimitTolerance: function() {
+ return parseInt(this.getLargeBufferSize() * this.options.nearLimitFactor);
+ }
+};
+
+// Rico.LiveGridScroller -----------------------------------------------------
+
+Rico.LiveGridScroller = Class.create();
+
+Rico.LiveGridScroller.prototype = {
+
+ initialize: function(liveGrid, viewPort) {
+ this.isIE = navigator.userAgent.toLowerCase().indexOf("msie") >= 0;
+ this.liveGrid = liveGrid;
+ this.metaData = liveGrid.metaData;
+ this.createScrollBar();
+ this.scrollTimeout = null;
+ this.lastScrollPos = 0;
+ this.viewPort = viewPort;
+ this.rows = new Array();
+ },
+
+ isUnPlugged: function() {
+ return this.scrollerDiv.onscroll == null;
+ },
+
+ plugin: function() {
+ this.scrollerDiv.onscroll = this.handleScroll.bindAsEventListener(this);
+ },
+
+ unplug: function() {
+ this.scrollerDiv.onscroll = null;
+ },
+
+ sizeIEHeaderHack: function() {
+ if ( !this.isIE ) return;
+ var headerTable = $(this.liveGrid.tableId + "_header");
+ if ( headerTable )
+ headerTable.rows[0].cells[0].style.width =
+ (headerTable.rows[0].cells[0].offsetWidth + 1) + "px";
+ },
+
+ createScrollBar: function() {
+ var visibleHeight = this.liveGrid.viewPort.visibleHeight();
+ // create the outer div...
+ this.scrollerDiv = document.createElement("div");
+ var scrollerStyle = this.scrollerDiv.style;
+ scrollerStyle.borderRight = this.liveGrid.options.scrollerBorderRight;
+ scrollerStyle.position = "relative";
+ scrollerStyle.left = this.isIE ? "-6px" : "-3px";
+ scrollerStyle.width = "19px";
+ scrollerStyle.height = visibleHeight + "px";
+ scrollerStyle.overflow = "auto";
+
+ // create the inner div...
+ this.heightDiv = document.createElement("div");
+ this.heightDiv.style.width = "1px";
+
+ this.heightDiv.style.height = parseInt(visibleHeight *
+ this.metaData.getTotalRows()/this.metaData.getPageSize()) + "px" ;
+ this.scrollerDiv.appendChild(this.heightDiv);
+ this.scrollerDiv.onscroll = this.handleScroll.bindAsEventListener(this);
+
+ var table = this.liveGrid.table;
+ table.parentNode.parentNode.insertBefore( this.scrollerDiv, table.parentNode.nextSibling );
+ var eventName = this.isIE ? "mousewheel" : "DOMMouseScroll";
+ Event.observe(table, eventName,
+ function(evt) {
+ if (evt.wheelDelta>=0 || evt.detail < 0) //wheel-up
+ this.scrollerDiv.scrollTop -= (2*this.viewPort.rowHeight);
+ else
+ this.scrollerDiv.scrollTop += (2*this.viewPort.rowHeight);
+ this.handleScroll(false);
+ }.bindAsEventListener(this),
+ false);
+ },
+
+ updateSize: function() {
+ var table = this.liveGrid.table;
+ var visibleHeight = this.viewPort.visibleHeight();
+ this.heightDiv.style.height = parseInt(visibleHeight *
+ this.metaData.getTotalRows()/this.metaData.getPageSize()) + "px";
+ },
+
+ rowToPixel: function(rowOffset) {
+ return (rowOffset / this.metaData.getTotalRows()) * this.heightDiv.offsetHeight
+ },
+
+ moveScroll: function(rowOffset) {
+ this.scrollerDiv.scrollTop = this.rowToPixel(rowOffset);
+ if ( this.metaData.options.onscroll )
+ this.metaData.options.onscroll( this.liveGrid, rowOffset );
+ },
+
+ handleScroll: function() {
+ if ( this.scrollTimeout )
+ clearTimeout( this.scrollTimeout );
+
+ var scrollDiff = this.lastScrollPos-this.scrollerDiv.scrollTop;
+ if (scrollDiff != 0.00) {
+ var r = this.scrollerDiv.scrollTop % this.viewPort.rowHeight;
+ if (r != 0) {
+ this.unplug();
+ if ( scrollDiff < 0 ) {
+ this.scrollerDiv.scrollTop += (this.viewPort.rowHeight-r);
+ } else {
+ this.scrollerDiv.scrollTop -= r;
+ }
+ this.plugin();
+ }
+ }
+ var contentOffset = parseInt(this.scrollerDiv.scrollTop / this.viewPort.rowHeight);
+ this.liveGrid.requestContentRefresh(contentOffset);
+ this.viewPort.scrollTo(this.scrollerDiv.scrollTop);
+
+ if ( this.metaData.options.onscroll )
+ this.metaData.options.onscroll( this.liveGrid, contentOffset );
+
+ this.scrollTimeout = setTimeout(this.scrollIdle.bind(this), 1200 );
+ this.lastScrollPos = this.scrollerDiv.scrollTop;
+
+ },
+
+ scrollIdle: function() {
+ if ( this.metaData.options.onscrollidle )
+ this.metaData.options.onscrollidle();
+ }
+};
+
+// Rico.LiveGridBuffer -----------------------------------------------------
+
+Rico.LiveGridBuffer = Class.create();
+
+Rico.LiveGridBuffer.prototype = {
+
+ initialize: function(metaData, viewPort) {
+ this.startPos = 0;
+ this.size = 0;
+ this.metaData = metaData;
+ this.rows = new Array();
+ this.updateInProgress = false;
+ this.viewPort = viewPort;
+ this.maxBufferSize = metaData.getLargeBufferSize() * 2;
+ this.maxFetchSize = metaData.getLargeBufferSize();
+ this.lastOffset = 0;
+ },
+
+ getBlankRow: function() {
+ if (!this.blankRow ) {
+ this.blankRow = new Array();
+ for ( var i=0; i < this.metaData.columnCount ; i++ )
+ this.blankRow[i] = " ";
+ }
+ return this.blankRow;
+ },
+
+ loadRows: function(ajaxResponse) {
+ var rowsElement = ajaxResponse.getElementsByTagName('rows')[0];
+ this.updateUI = rowsElement.getAttribute("update_ui") == "true"
+ var newRows = new Array()
+ var trs = rowsElement.getElementsByTagName("tr");
+ for ( var i=0 ; i < trs.length; i++ ) {
+ var row = newRows[i] = new Array();
+ var cells = trs[i].getElementsByTagName("td");
+ for ( var j=0; j < cells.length ; j++ ) {
+ var cell = cells[j];
+ var convertSpaces = cell.getAttribute("convert_spaces") == "true";
+ var cellContent = RicoUtil.getContentAsString(cell);
+ row[j] = convertSpaces ? this.convertSpaces(cellContent) : cellContent;
+ if (!row[j])
+ row[j] = ' ';
+ }
+ }
+ return newRows;
+ },
+
+ update: function(ajaxResponse, start) {
+ var newRows = this.loadRows(ajaxResponse);
+ if (this.rows.length == 0) { // initial load
+ this.rows = newRows;
+ this.size = this.rows.length;
+ this.startPos = start;
+ return;
+ }
+ if (start > this.startPos) { //appending
+ if (this.startPos + this.rows.length < start) {
+ this.rows = newRows;
+ this.startPos = start;//
+ } else {
+ this.rows = this.rows.concat( newRows.slice(0, newRows.length));
+ if (this.rows.length > this.maxBufferSize) {
+ var fullSize = this.rows.length;
+ this.rows = this.rows.slice(this.rows.length - this.maxBufferSize, this.rows.length)
+ this.startPos = this.startPos + (fullSize - this.rows.length);
+ }
+ }
+ } else { //prepending
+ if (start + newRows.length < this.startPos) {
+ this.rows = newRows;
+ } else {
+ this.rows = newRows.slice(0, this.startPos).concat(this.rows);
+ if (this.rows.length > this.maxBufferSize)
+ this.rows = this.rows.slice(0, this.maxBufferSize)
+ }
+ this.startPos = start;
+ }
+ this.size = this.rows.length;
+ },
+
+ clear: function() {
+ this.rows = new Array();
+ this.startPos = 0;
+ this.size = 0;
+ },
+
+ isOverlapping: function(start, size) {
+ return ((start < this.endPos()) && (this.startPos < start + size)) || (this.endPos() == 0)
+ },
+
+ isInRange: function(position) {
+ return (position >= this.startPos) && (position + this.metaData.getPageSize() <= this.endPos());
+ //&& this.size() != 0;
+ },
+
+ isNearingTopLimit: function(position) {
+ return position - this.startPos < this.metaData.getLimitTolerance();
+ },
+
+ endPos: function() {
+ return this.startPos + this.rows.length;
+ },
+
+ isNearingBottomLimit: function(position) {
+ return this.endPos() - (position + this.metaData.getPageSize()) < this.metaData.getLimitTolerance();
+ },
+
+ isAtTop: function() {
+ return this.startPos == 0;
+ },
+
+ isAtBottom: function() {
+ return this.endPos() == this.metaData.getTotalRows();
+ },
+
+ isNearingLimit: function(position) {
+ return ( !this.isAtTop() && this.isNearingTopLimit(position)) ||
+ ( !this.isAtBottom() && this.isNearingBottomLimit(position) )
+ },
+
+ getFetchSize: function(offset) {
+ var adjustedOffset = this.getFetchOffset(offset);
+ var adjustedSize = 0;
+ if (adjustedOffset >= this.startPos) { //apending
+ var endFetchOffset = this.maxFetchSize + adjustedOffset;
+ if (endFetchOffset > this.metaData.totalRows)
+ endFetchOffset = this.metaData.totalRows;
+ adjustedSize = endFetchOffset - adjustedOffset;
+ if(adjustedOffset == 0 && adjustedSize < this.maxFetchSize){
+ adjustedSize = this.maxFetchSize;
+ }
+ } else {//prepending
+ var adjustedSize = this.startPos - adjustedOffset;
+ if (adjustedSize > this.maxFetchSize)
+ adjustedSize = this.maxFetchSize;
+ }
+ return adjustedSize;
+ },
+
+ getFetchOffset: function(offset) {
+ var adjustedOffset = offset;
+ if (offset > this.startPos) //apending
+ adjustedOffset = (offset > this.endPos()) ? offset : this.endPos();
+ else { //prepending
+ if (offset + this.maxFetchSize >= this.startPos) {
+ var adjustedOffset = this.startPos - this.maxFetchSize;
+ if (adjustedOffset < 0)
+ adjustedOffset = 0;
+ }
+ }
+ this.lastOffset = adjustedOffset;
+ return adjustedOffset;
+ },
+
+ getRows: function(start, count) {
+ var begPos = start - this.startPos
+ var endPos = begPos + count
+
+ // er? need more data...
+ if ( endPos > this.size )
+ endPos = this.size
+
+ var results = new Array()
+ var index = 0;
+ for ( var i=begPos ; i < endPos; i++ ) {
+ results[index++] = this.rows[i]
+ }
+ return results
+ },
+
+ convertSpaces: function(s) {
+ return s.split(" ").join(" ");
+ }
+
+};
+
+
+//Rico.GridViewPort --------------------------------------------------
+Rico.GridViewPort = Class.create();
+
+Rico.GridViewPort.prototype = {
+
+ initialize: function(table, rowHeight, visibleRows, buffer, liveGrid) {
+ this.lastDisplayedStartPos = 0;
+ this.div = table.parentNode;
+ this.table = table
+ this.rowHeight = rowHeight;
+ this.div.style.height = (this.rowHeight * visibleRows) + "px";
+ this.div.style.overflow = "hidden";
+ this.buffer = buffer;
+ this.liveGrid = liveGrid;
+ this.visibleRows = visibleRows + 1;
+ this.lastPixelOffset = 0;
+ this.startPos = 0;
+ },
+
+ populateRow: function(htmlRow, row) {
+ for (var j=0; j < row.length; j++) {
+ htmlRow.cells[j].innerHTML = row[j]
+ }
+ },
+
+ bufferChanged: function() {
+ this.refreshContents( parseInt(this.lastPixelOffset / this.rowHeight));
+ },
+
+ clearRows: function() {
+ if (!this.isBlank) {
+ this.liveGrid.table.className = this.liveGrid.options.loadingClass;
+ for (var i=0; i < this.visibleRows; i++)
+ this.populateRow(this.table.rows[i], this.buffer.getBlankRow());
+ this.isBlank = true;
+ }
+ },
+
+ clearContents: function() {
+ this.clearRows();
+ this.scrollTo(0);
+ this.startPos = 0;
+ this.lastStartPos = -1;
+ },
+
+ refreshContents: function(startPos) {
+ if (startPos == this.lastRowPos && !this.isPartialBlank && !this.isBlank) {
+ return;
+ }
+ if ((startPos + this.visibleRows < this.buffer.startPos)
+ || (this.buffer.startPos + this.buffer.size < startPos)
+ || (this.buffer.size == 0)) {
+ this.clearRows();
+ return;
+ }
+ this.isBlank = false;
+ var viewPrecedesBuffer = this.buffer.startPos > startPos
+ var contentStartPos = viewPrecedesBuffer ? this.buffer.startPos: startPos;
+ var contentEndPos = (this.buffer.startPos + this.buffer.size < startPos + this.visibleRows)
+ ? this.buffer.startPos + this.buffer.size
+ : startPos + this.visibleRows;
+ var rowSize = contentEndPos - contentStartPos;
+ var rows = this.buffer.getRows(contentStartPos, rowSize );
+ var blankSize = this.visibleRows - rowSize;
+ var blankOffset = viewPrecedesBuffer ? 0: rowSize;
+ var contentOffset = viewPrecedesBuffer ? blankSize: 0;
+
+ for (var i=0; i < rows.length; i++) {//initialize what we have
+ this.populateRow(this.table.rows[i + contentOffset], rows[i]);
+ }
+ for (var i=0; i < blankSize; i++) {// blank out the rest
+ this.populateRow(this.table.rows[i + blankOffset], this.buffer.getBlankRow());
+ }
+ this.isPartialBlank = blankSize > 0;
+ this.lastRowPos = startPos;
+
+ this.liveGrid.table.className = this.liveGrid.options.tableClass;
+ // Check if user has set a onRefreshComplete function
+ var onRefreshComplete = this.liveGrid.options.onRefreshComplete;
+ if (onRefreshComplete != null)
+ onRefreshComplete();
+ },
+
+ scrollTo: function(pixelOffset) {
+ if (this.lastPixelOffset == pixelOffset)
+ return;
+
+ this.refreshContents(parseInt(pixelOffset / this.rowHeight))
+ this.div.scrollTop = pixelOffset % this.rowHeight
+
+ this.lastPixelOffset = pixelOffset;
+ },
+
+ visibleHeight: function() {
+ return parseInt(RicoUtil.getElementsComputedStyle(this.div, 'height'));
+ }
+
+};
+
+
+Rico.LiveGridRequest = Class.create();
+Rico.LiveGridRequest.prototype = {
+ initialize: function( requestOffset, options ) {
+ this.requestOffset = requestOffset;
+ }
+};
+
+// Rico.LiveGrid -----------------------------------------------------
+
+Rico.LiveGrid = Class.create();
+
+Rico.LiveGrid.prototype = {
+
+ initialize: function( tableId, visibleRows, totalRows, url, options, ajaxOptions ) {
+
+ this.options = {
+ tableClass: $(tableId).className,
+ loadingClass: $(tableId).className,
+ scrollerBorderRight: '1px solid #ababab',
+ bufferTimeout: 20000,
+ sortAscendImg: 'images/sort_asc.gif',
+ sortDescendImg: 'images/sort_desc.gif',
+ sortImageWidth: 9,
+ sortImageHeight: 5,
+ ajaxSortURLParms: [],
+ onRefreshComplete: null,
+ requestParameters: null,
+ inlineStyles: true
+ };
+ Object.extend(this.options, options || {});
+
+ this.ajaxOptions = {parameters: null};
+ Object.extend(this.ajaxOptions, ajaxOptions || {});
+
+ this.tableId = tableId;
+ this.table = $(tableId);
+
+ this.addLiveGridHtml();
+
+ var columnCount = this.table.rows[0].cells.length;
+ this.metaData = new Rico.LiveGridMetaData(visibleRows, totalRows, columnCount, options);
+ this.buffer = new Rico.LiveGridBuffer(this.metaData);
+
+ var rowCount = this.table.rows.length;
+ this.viewPort = new Rico.GridViewPort(this.table,
+ this.table.offsetHeight/rowCount,
+ visibleRows,
+ this.buffer, this);
+ this.scroller = new Rico.LiveGridScroller(this,this.viewPort);
+ this.options.sortHandler = this.sortHandler.bind(this);
+
+ if ( $(tableId + '_header') )
+ this.sort = new Rico.LiveGridSort(tableId + '_header', this.options)
+
+ this.processingRequest = null;
+ this.unprocessedRequest = null;
+
+ this.initAjax(url);
+ if ( this.options.prefetchBuffer || this.options.prefetchOffset > 0) {
+ var offset = 0;
+ if (this.options.offset ) {
+ offset = this.options.offset;
+ this.scroller.moveScroll(offset);
+ this.viewPort.scrollTo(this.scroller.rowToPixel(offset));
+ }
+ if (this.options.sortCol) {
+ this.sortCol = options.sortCol;
+ this.sortDir = options.sortDir;
+ }
+ this.requestContentRefresh(offset);
+ }
+ },
+
+ addLiveGridHtml: function() {
+ // Check to see if need to create a header table.
+ if (this.table.getElementsByTagName("thead").length > 0){
+ // Create Table this.tableId+'_header'
+ var tableHeader = this.table.cloneNode(true);
+ tableHeader.setAttribute('id', this.tableId+'_header');
+ tableHeader.setAttribute('class', this.table.className+'_header');
+
+ // Clean up and insert
+ for( var i = 0; i < tableHeader.tBodies.length; i++ )
+ tableHeader.removeChild(tableHeader.tBodies[i]);
+ this.table.deleteTHead();
+ this.table.parentNode.insertBefore(tableHeader,this.table);
+ }
+
+ new Insertion.Before(this.table, "<div id='"+this.tableId+"_container'></div>");
+ this.table.previousSibling.appendChild(this.table);
+ new Insertion.Before(this.table,"<div id='"+this.tableId+"_viewport' style='float:left;'></div>");
+ this.table.previousSibling.appendChild(this.table);
+ },
+
+
+ resetContents: function() {
+ this.scroller.moveScroll(0);
+ this.buffer.clear();
+ this.viewPort.clearContents();
+ },
+
+ sortHandler: function(column) {
+ if(!column) return ;
+ this.sortCol = column.name;
+ this.sortDir = column.currentSort;
+
+ this.resetContents();
+ this.requestContentRefresh(0)
+ },
+
+ adjustRowSize: function() {
+
+ },
+
+ setTotalRows: function( newTotalRows ) {
+ this.resetContents();
+ this.metaData.setTotalRows(newTotalRows);
+ this.scroller.updateSize();
+ },
+
+ initAjax: function(url) {
+ ajaxEngine.registerRequest( this.tableId + '_request', url );
+ ajaxEngine.registerAjaxObject( this.tableId + '_updater', this );
+ },
+
+ invokeAjax: function() {
+ },
+
+ handleTimedOut: function() {
+ //server did not respond in 4 seconds... assume that there could have been
+ //an error or something, and allow requests to be processed again...
+ this.processingRequest = null;
+ this.processQueuedRequest();
+ },
+
+ fetchBuffer: function(offset) {
+ if ( this.buffer.isInRange(offset) &&
+ !this.buffer.isNearingLimit(offset)) {
+ return;
+ }
+ if (this.processingRequest) {
+ this.unprocessedRequest = new Rico.LiveGridRequest(offset);
+ return;
+ }
+ var bufferStartPos = this.buffer.getFetchOffset(offset);
+ this.processingRequest = new Rico.LiveGridRequest(offset);
+ this.processingRequest.bufferOffset = bufferStartPos;
+ var fetchSize = this.buffer.getFetchSize(offset);
+ var partialLoaded = false;
+
+ var queryString
+ if (this.options.requestParameters)
+ queryString = this._createQueryString(this.options.requestParameters, 0);
+
+ queryString = (queryString == null) ? '' : queryString+'&';
+ queryString = queryString+'id='+this.tableId+'&page_size='+fetchSize+'&offset='+bufferStartPos;
+ if (this.sortCol)
+ queryString = queryString+'&sort_col='+escape(this.sortCol)+'&sort_dir='+this.sortDir;
+
+ this.ajaxOptions.parameters = queryString;
+
+ ajaxEngine.sendRequest( this.tableId + '_request', this.ajaxOptions );
+
+ this.timeoutHandler = setTimeout( this.handleTimedOut.bind(this), this.options.bufferTimeout);
+
+ },
+
+ setRequestParams: function() {
+ this.options.requestParameters = [];
+ for ( var i=0 ; i < arguments.length ; i++ )
+ this.options.requestParameters[i] = arguments[i];
+ },
+
+ requestContentRefresh: function(contentOffset) {
+ this.fetchBuffer(contentOffset);
+ },
+
+ ajaxUpdate: function(ajaxResponse) {
+ try {
+ clearTimeout( this.timeoutHandler );
+ this.buffer.update(ajaxResponse,this.processingRequest.bufferOffset);
+ this.viewPort.bufferChanged();
+ }
+ catch(err) {}
+ finally {this.processingRequest = null; }
+ this.processQueuedRequest();
+ },
+
+ _createQueryString: function( theArgs, offset ) {
+ var queryString = ""
+ if (!theArgs)
+ return queryString;
+
+ for ( var i = offset ; i < theArgs.length ; i++ ) {
+ if ( i != offset )
+ queryString += "&";
+
+ var anArg = theArgs[i];
+
+ if ( anArg.name != undefined && anArg.value != undefined ) {
+ queryString += anArg.name + "=" + escape(anArg.value);
+ }
+ else {
+ var ePos = anArg.indexOf('=');
+ var argName = anArg.substring( 0, ePos );
+ var argValue = anArg.substring( ePos + 1 );
+ queryString += argName + "=" + escape(argValue);
+ }
+ }
+ return queryString;
+ },
+
+ processQueuedRequest: function() {
+ if (this.unprocessedRequest != null) {
+ this.requestContentRefresh(this.unprocessedRequest.requestOffset);
+ this.unprocessedRequest = null
+ }
+ }
+};
+
+
+//-------------------- ricoLiveGridSort.js
+Rico.LiveGridSort = Class.create();
+
+Rico.LiveGridSort.prototype = {
+
+ initialize: function(headerTableId, options) {
+ this.headerTableId = headerTableId;
+ this.headerTable = $(headerTableId);
+ this.options = options;
+ this.setOptions();
+ this.applySortBehavior();
+
+ if ( this.options.sortCol ) {
+ this.setSortUI( this.options.sortCol, this.options.sortDir );
+ }
+ },
+
+ setSortUI: function( columnName, sortDirection ) {
+ var cols = this.options.columns;
+ for ( var i = 0 ; i < cols.length ; i++ ) {
+ if ( cols[i].name == columnName ) {
+ this.setColumnSort(i, sortDirection);
+ break;
+ }
+ }
+ },
+
+ setOptions: function() {
+ // preload the images...
+ new Image().src = this.options.sortAscendImg;
+ new Image().src = this.options.sortDescendImg;
+
+ this.sort = this.options.sortHandler;
+ if ( !this.options.columns )
+ this.options.columns = this.introspectForColumnInfo();
+ else {
+ // allow client to pass { columns: [ ["a", true], ["b", false] ] }
+ // and convert to an array of Rico.TableColumn objs...
+ this.options.columns = this.convertToTableColumns(this.options.columns);
+ }
+ },
+
+ applySortBehavior: function() {
+ var headerRow = this.headerTable.rows[0];
+ var headerCells = headerRow.cells;
+ for ( var i = 0 ; i < headerCells.length ; i++ ) {
+ this.addSortBehaviorToColumn( i, headerCells[i] );
+ }
+ },
+
+ addSortBehaviorToColumn: function( n, cell ) {
+ if ( this.options.columns[n].isSortable() ) {
+ cell.id = this.headerTableId + '_' + n;
+ cell.style.cursor = 'pointer';
+ cell.onclick = this.headerCellClicked.bindAsEventListener(this);
+ cell.innerHTML = cell.innerHTML + '<span id="' + this.headerTableId + '_img_' + n + '">'
+ + ' </span>';
+ }
+ },
+
+ // event handler....
+ headerCellClicked: function(evt) {
+ var eventTarget = evt.target ? evt.target : evt.srcElement;
+ var cellId = eventTarget.id;
+ var columnNumber = parseInt(cellId.substring( cellId.lastIndexOf('_') + 1 ));
+ var sortedColumnIndex = this.getSortedColumnIndex();
+ if ( sortedColumnIndex != -1 ) {
+ if ( sortedColumnIndex != columnNumber ) {
+ this.removeColumnSort(sortedColumnIndex);
+ this.setColumnSort(columnNumber, Rico.TableColumn.SORT_ASC);
+ }
+ else
+ this.toggleColumnSort(sortedColumnIndex);
+ }
+ else
+ this.setColumnSort(columnNumber, Rico.TableColumn.SORT_ASC);
+
+ if (this.options.sortHandler) {
+ this.options.sortHandler(this.options.columns[columnNumber]);
+ }
+ },
+
+ removeColumnSort: function(n) {
+ this.options.columns[n].setUnsorted();
+ this.setSortImage(n);
+ },
+
+ setColumnSort: function(n, direction) {
+ if(isNaN(n)) return ;
+ this.options.columns[n].setSorted(direction);
+ this.setSortImage(n);
+ },
+
+ toggleColumnSort: function(n) {
+ this.options.columns[n].toggleSort();
+ this.setSortImage(n);
+ },
+
+ setSortImage: function(n) {
+ var sortDirection = this.options.columns[n].getSortDirection();
+
+ var sortImageSpan = $( this.headerTableId + '_img_' + n );
+ if ( sortDirection == Rico.TableColumn.UNSORTED )
+ sortImageSpan.innerHTML = ' ';
+ else if ( sortDirection == Rico.TableColumn.SORT_ASC )
+ sortImageSpan.innerHTML = ' <img width="' + this.options.sortImageWidth + '" ' +
+ 'height="'+ this.options.sortImageHeight + '" ' +
+ 'src="' + this.options.sortAscendImg + '"/>';
+ else if ( sortDirection == Rico.TableColumn.SORT_DESC )
+ sortImageSpan.innerHTML = ' <img width="' + this.options.sortImageWidth + '" ' +
+ 'height="'+ this.options.sortImageHeight + '" ' +
+ 'src="' + this.options.sortDescendImg + '"/>';
+ },
+
+ getSortedColumnIndex: function() {
+ var cols = this.options.columns;
+ for ( var i = 0 ; i < cols.length ; i++ ) {
+ if ( cols[i].isSorted() )
+ return i;
+ }
+
+ return -1;
+ },
+
+ introspectForColumnInfo: function() {
+ var columns = new Array();
+ var headerRow = this.headerTable.rows[0];
+ var headerCells = headerRow.cells;
+ for ( var i = 0 ; i < headerCells.length ; i++ )
+ columns.push( new Rico.TableColumn( this.deriveColumnNameFromCell(headerCells[i],i), true ) );
+ return columns;
+ },
+
+ convertToTableColumns: function(cols) {
+ var columns = new Array();
+ for ( var i = 0 ; i < cols.length ; i++ )
+ columns.push( new Rico.TableColumn( cols[i][0], cols[i][1] ) );
+ return columns;
+ },
+
+ deriveColumnNameFromCell: function(cell,columnNumber) {
+ var cellContent = cell.innerText != undefined ? cell.innerText : cell.textContent;
+ return cellContent ? cellContent.toLowerCase().split(' ').join('_') : "col_" + columnNumber;
+ }
+};
+
+Rico.TableColumn = Class.create();
+
+Rico.TableColumn.UNSORTED = 0;
+Rico.TableColumn.SORT_ASC = "ASC";
+Rico.TableColumn.SORT_DESC = "DESC";
+
+Rico.TableColumn.prototype = {
+ initialize: function(name, sortable) {
+ this.name = name;
+ this.sortable = sortable;
+ this.currentSort = Rico.TableColumn.UNSORTED;
+ },
+
+ isSortable: function() {
+ return this.sortable;
+ },
+
+ isSorted: function() {
+ return this.currentSort != Rico.TableColumn.UNSORTED;
+ },
+
+ getSortDirection: function() {
+ return this.currentSort;
+ },
+
+ toggleSort: function() {
+ if ( this.currentSort == Rico.TableColumn.UNSORTED || this.currentSort == Rico.TableColumn.SORT_DESC )
+ this.currentSort = Rico.TableColumn.SORT_ASC;
+ else if ( this.currentSort == Rico.TableColumn.SORT_ASC )
+ this.currentSort = Rico.TableColumn.SORT_DESC;
+ },
+
+ setUnsorted: function(direction) {
+ this.setSorted(Rico.TableColumn.UNSORTED);
+ },
+
+ setSorted: function(direction) {
+ // direction must by one of Rico.TableColumn.UNSORTED, .SORT_ASC, or .SORT_DESC...
+ this.currentSort = direction;
+ }
+
+};
+
+
+//-------------------- ricoUtil.js
+var RicoUtil = {
+
+ getElementsComputedStyle: function ( htmlElement, cssProperty, mozillaEquivalentCSS) {
+ if ( arguments.length == 2 )
+ mozillaEquivalentCSS = cssProperty;
+
+ var el = $(htmlElement);
+ if ( el.currentStyle )
+ return el.currentStyle[cssProperty];
+ else
+ return document.defaultView.getComputedStyle(el, null).getPropertyValue(mozillaEquivalentCSS);
+ },
+
+ createXmlDocument : function() {
+ if (document.implementation && document.implementation.createDocument) {
+ var doc = document.implementation.createDocument("", "", null);
+
+ if (doc.readyState == null) {
+ doc.readyState = 1;
+ doc.addEventListener("load", function () {
+ doc.readyState = 4;
+ if (typeof doc.onreadystatechange == "function")
+ doc.onreadystatechange();
+ }, false);
+ }
+
+ return doc;
+ }
+
+ if (window.ActiveXObject)
+ return Try.these(
+ function() { return new ActiveXObject('MSXML2.DomDocument') },
+ function() { return new ActiveXObject('Microsoft.DomDocument')},
+ function() { return new ActiveXObject('MSXML.DomDocument') },
+ function() { return new ActiveXObject('MSXML3.DomDocument') }
+ ) || false;
+
+ return null;
+ },
+
+ getContentAsString: function( parentNode ) {
+ return parentNode.xml != undefined ?
+ this._getContentAsStringIE(parentNode) :
+ this._getContentAsStringMozilla(parentNode);
+ },
+
+ _getContentAsStringIE: function(parentNode) {
+ var contentStr = "";
+ for ( var i = 0 ; i < parentNode.childNodes.length ; i++ ) {
+ var n = parentNode.childNodes[i];
+ if (n.nodeType == 4) {
+ contentStr += n.nodeValue;
+ }
+ else {
+ contentStr += n.xml;
+ }
+ }
+ return contentStr;
+ },
+
+ _getContentAsStringMozilla: function(parentNode) {
+ var xmlSerializer = new XMLSerializer();
+ var contentStr = "";
+ for ( var i = 0 ; i < parentNode.childNodes.length ; i++ ) {
+ var n = parentNode.childNodes[i];
+ if (n.nodeType == 4) { // CDATA node
+ contentStr += n.nodeValue;
+ }
+ else {
+ contentStr += xmlSerializer.serializeToString(n);
+ }
+ }
+ return contentStr;
+ },
+
+ toViewportPosition: function(element) {
+ return this._toAbsolute(element,true);
+ },
+
+ toDocumentPosition: function(element) {
+ return this._toAbsolute(element,false);
+ },
+
+ /**
+ * Compute the elements position in terms of the window viewport
+ * so that it can be compared to the position of the mouse (dnd)
+ * This is additions of all the offsetTop,offsetLeft values up the
+ * offsetParent hierarchy, ...taking into account any scrollTop,
+ * scrollLeft values along the way...
+ *
+ * IE has a bug reporting a correct offsetLeft of elements within a
+ * a relatively positioned parent!!!
+ **/
+ _toAbsolute: function(element,accountForDocScroll) {
+
+ if ( navigator.userAgent.toLowerCase().indexOf("msie") == -1 )
+ return this._toAbsoluteMozilla(element,accountForDocScroll);
+
+ var x = 0;
+ var y = 0;
+ var parent = element;
+ while ( parent ) {
+
+ var borderXOffset = 0;
+ var borderYOffset = 0;
+ if ( parent != element ) {
+ var borderXOffset = parseInt(this.getElementsComputedStyle(parent, "borderLeftWidth" ));
+ var borderYOffset = parseInt(this.getElementsComputedStyle(parent, "borderTopWidth" ));
+ borderXOffset = isNaN(borderXOffset) ? 0 : borderXOffset;
+ borderYOffset = isNaN(borderYOffset) ? 0 : borderYOffset;
+ }
+
+ x += parent.offsetLeft - parent.scrollLeft + borderXOffset;
+ y += parent.offsetTop - parent.scrollTop + borderYOffset;
+ parent = parent.offsetParent;
+ }
+
+ if ( accountForDocScroll ) {
+ x -= this.docScrollLeft();
+ y -= this.docScrollTop();
+ }
+
+ return { x:x, y:y };
+ },
+
+ /**
+ * Mozilla did not report all of the parents up the hierarchy via the
+ * offsetParent property that IE did. So for the calculation of the
+ * offsets we use the offsetParent property, but for the calculation of
+ * the scrollTop/scrollLeft adjustments we navigate up via the parentNode
+ * property instead so as to get the scroll offsets...
+ *
+ **/
+ _toAbsoluteMozilla: function(element,accountForDocScroll) {
+ var x = 0;
+ var y = 0;
+ var parent = element;
+ while ( parent ) {
+ x += parent.offsetLeft;
+ y += parent.offsetTop;
+ parent = parent.offsetParent;
+ }
+
+ parent = element;
+ while ( parent &&
+ parent != document.body &&
+ parent != document.documentElement ) {
+ if ( parent.scrollLeft )
+ x -= parent.scrollLeft;
+ if ( parent.scrollTop )
+ y -= parent.scrollTop;
+ parent = parent.parentNode;
+ }
+
+ if ( accountForDocScroll ) {
+ x -= this.docScrollLeft();
+ y -= this.docScrollTop();
+ }
+
+ return { x:x, y:y };
+ },
+
+ docScrollLeft: function() {
+ if ( window.pageXOffset )
+ return window.pageXOffset;
+ else if ( document.documentElement && document.documentElement.scrollLeft )
+ return document.documentElement.scrollLeft;
+ else if ( document.body )
+ return document.body.scrollLeft;
+ else
+ return 0;
+ },
+
+ docScrollTop: function() {
+ if ( window.pageYOffset )
+ return window.pageYOffset;
+ else if ( document.documentElement && document.documentElement.scrollTop )
+ return document.documentElement.scrollTop;
+ else if ( document.body )
+ return document.body.scrollTop;
+ else
+ return 0;
+ }
+
+};
--- /dev/null
+body { background-color:#445566; color:#FFCC99; }
+a:link { color:#FF9966; }
+a:visited { color:#FF9900; }
+a:active { color:#FFFFFF; }
+
+ /* allow room for 3 columns */
+ol
+{
+ width: 45em;
+}
+
+ /* float and allow room for the widest item */
+ol li
+{
+ float: left;
+ width: 15em;
+}
+
+/* stop the float */
+br
+{
+ clear: left;
+}
+
+ /* separate the list from subsequent markup */
+div.wrapper
+{
+ margin-bottom: 1em;
+}
+
--- /dev/null
+var url_getvolume = '/web/vol?set=info';
+var url_setvolume = '/web/vol?set=set'; // plus new value eq. set=set15
+var url_volumeup = '/web/vol?set=up';
+var url_volumedown = '/web/vol?set=down';
+var url_volumemute = '/web/vol?set=mute';
+
+var url_epgservice = "/web/epgservice?ref="; // plus serviceRev
+var url_epgsearch = "/web/epgsearch?search="; // plus serviceRev
+var url_epgnownext = "/web/epgnownext?ref="; // plus serviceRev
+
+function debug(text){
+ //$('debug').innerHTML += "DEBUG: "+text+"<br>";
+}
+function set(what, value)
+{
+ //debug(what+"-"+value);
+ element = document.getElementById(what);
+ element.innerHTML = value;
+ $('scriptzone').innerHTML = ""; // deleting set() from page, to keep the page short and to save memory
+}
+
+function zap(li)
+{
+ var request = getHTTPObject();
+ var url = "/web/zap?ZapTo=" + escape(li.id);
+ //debug("requesting "+url);
+ new Ajax.Request( url,
+ {
+ method: 'get'
+
+ });
+
+}
+
+function getHTTPObject()
+{
+ var xmlhttp;
+ /*@cc_on
+ @if (@_jscript_version >= 5)
+ try
+ {
+ xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
+ }
+ catch (e)
+ {
+ try
+ {
+ xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
+ }
+ catch (E)
+ {
+ xmlhttp = false;
+ }
+ }
+ @else
+ xmlhttp = false;
+ @end @*/
+ if (!xmlhttp && typeof XMLHttpRequest != 'undefined')
+ {
+ try
+ {
+ xmlhttp = new XMLHttpRequest();
+ }
+ catch (e)
+ {
+ xmlhttp = false;
+ }
+ }
+ return xmlhttp;
+}
+
+
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++
+//++++ EPG functions ++++
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++
+var EPGList = Class.create();
+EPGList.prototype = {
+ //contructor
+ initialize: function(){
+ debug("init class EPGList");
+ },
+ getBySearchString: function(string,element){
+ debug("requesting "+ url_epgsearch+string);
+ targetElement = element;
+ new Ajax.Request( url_epgsearch+string,
+ {
+ method: 'get',
+ onComplete: this.incomingEPGrequest
+ });
+
+ },
+ getByServiceReference: function(serviceRef,element){
+ targetElement = element;
+ new Ajax.Request(url_epgservice+serviceRef,
+ {
+ method: 'get',
+ onComplete: this.incomingEPGrequest
+ });
+
+ },
+ renderTable: function(epglist){
+ debug("rendering Table with "+epglist.length+" events");
+ var html="<table width='100%'>";
+ for (var i=0; i<epglist.length;i++){
+ var item = epglist[i];
+ html +="<tr bgcolor='gray'>";
+ html +="<td>"+item.getTimeDay()+"</td>";
+ html +="<td>"+item.getTimeStartString()+"</td>";
+ html +="<td>"+item.getTimeEndString()+"</td>";
+ html +="<td>"+item.getTitle()+"</td>";
+ html +="<td>"+item.getDescription()+"</td>";
+ html +="<td>"+item.getDescriptionExtended()+"</td>";
+ html +="<td>"+(item.getDuration()/60000)+" min.</td>";
+ html +="<td>"+item.getServiceName()+"</td>";
+ html +="</tr>";
+ }
+ html +="</table>";
+ targetElement.innerHTML = html;
+
+ },
+ incomingEPGrequest: function(originalRequest){
+ debug("incoming request" +originalRequest.readyState);
+ if (originalRequest.readyState == 4)
+ {
+ if (originalRequest.responseXML!="no data")
+ {
+ var EPGItems = originalRequest.responseXML.getElementsByTagName("e2eventlist").item(0).getElementsByTagName("e2event");
+ debug("have "+EPGItems.length+" e2events");
+ epglist = new Array();
+ for(var i=0;i<EPGItems.length;i++)
+ {
+ epglist.push(new EPGEvent(EPGItems.item(i)));
+ }
+ EPGList.prototype.renderTable(epglist);
+
+ }
+ }
+ }
+
+}
+
+function EPGEvent(element){
+ // parsing values from xml-element
+ this.eventID= element.getElementsByTagName('e2eventid').item(0).firstChild.data;
+ this.startTime= element.getElementsByTagName('e2eventstart').item(0).firstChild.data;
+ this.duration= element.getElementsByTagName('e2eventduration').item(0).firstChild.data;
+ this.title= element.getElementsByTagName('e2eventtitle').item(0).firstChild.data;
+ this.description= element.getElementsByTagName('e2eventdescription').item(0).firstChild.data;
+ this.descriptionE= element.getElementsByTagName('e2eventdescriptionextended').item(0).firstChild.data;
+ this.serviceRef= element.getElementsByTagName('e2eventservicereference').item(0).firstChild.data;
+ this.serviceName= element.getElementsByTagName('e2eventservicename').item(0).firstChild.data;
+
+ this.getEventId = function ()
+ {
+ return this.eventID;
+ }
+ this.getTimeStart = function ()
+ {
+ var date = new Date(parseInt(this.startTime)*1000);
+ return date;
+ }
+ this.getTimeStartString = function ()
+ {
+ var h = this.getTimeStart().getHours();
+ var m = this.getTimeStart().getMinutes();
+ if (m < 10){
+ m="0"+m;
+ }
+ return h+":"+m;
+ }
+ this.getTimeDay = function ()
+ {
+ var Wochentag = new Array("So", "Mo", "Di", "Mi", "Do", "Fr", "Sa");
+ var wday = Wochentag[this.getTimeStart().getDay()];
+ var day = this.getTimeStart().getDate();
+ var month = this.getTimeStart().getMonth()+1;
+ var year = this.getTimeStart().getFullYear();
+
+ return wday+". "+day+"."+month+"."+year;
+ }
+ this.getTimeEnd = function ()
+ {
+ var date = new Date((parseInt(this.startTime)+parseInt(this.duration))*1000);
+ return date;
+ }
+ this.getTimeEndString = function ()
+ {
+ var h = this.getTimeEnd().getHours();
+ var m = this.getTimeEnd().getMinutes();
+ if (m < 10){
+ m="0"+m;
+ }
+ return h+":"+m;
+ }
+ this.getDuration = function ()
+ {
+ return new Date(parseInt(this.duration)*1000);
+ }
+ this.getTitle = function ()
+ {
+ return this.title;
+ }
+ this.getDescription = function ()
+ {
+ return this.description;
+ }
+ this.getDescriptionExtended = function ()
+ {
+ return this.descriptionE;
+ }
+ this.getServiceReference = function ()
+ {
+ return this.serviceRef;
+ }
+ this.getServiceName = function ()
+ {
+ return this.serviceName.replace(" "," ");
+ }
+}//END class EPGEvent
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++
+//++++ GUI functions ++++
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++
+var currentBodyMainElement = null
+
+function setBodyMainContent(newelementname){
+ newelement =document.getElementById(newelementname);
+ if(currentBodyMainElement != null){
+ currentBodyMainElement.style.display = "none";
+
+ }
+ newelement.style.display = "inline";
+ currentBodyMainElement = newelement;
+}
+function doRequest(url,readyFunction){
+
+ http_request =getHTTPObject();
+ if(readyFunction){
+ http_request.onreadystatechange = readyFunction;
+ }
+ http_request.open('GET', url, true);
+ http_request.send(null);
+ return http_request;
+}
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++
+//++++ volume functions ++++
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+
+function getVolume()
+{
+ doRequest(url_getvolume,handleVolumeRequest);
+}
+function setVolume(newvalue)
+{
+ doRequest(url_setvolume+newvalue,handleVolumeRequest);
+}
+function volumeUp()
+{
+ doRequest(url_volumeup,handleVolumeRequest);
+}
+function volumeDown()
+{
+ doRequest(url_volumedown,handleVolumeRequest);
+}
+function volumeMute()
+{
+ doRequest(url_volumemute,handleVolumeRequest);
+}
+function handleVolumeRequest(){
+ if (http_request.readyState == 4) {
+ var a = http_request.responseText.split("\n");
+ var newvalue = a[1];
+ var mute=a[2];
+ set("Volume_Current",newvalue);
+ for (var i = 1; i <= 10; i++)
+ {
+ if ( (newvalue/10)>=i){
+ $("volume"+i).src = "/webdata/gfx/led_on.png";
+ }else{
+ $("volume"+i).src = "/webdata/gfx/led_off.png";
+ }
+ }
+ if (mute == "notmuted"){
+ $("speaker").src = "/webdata/gfx/speak_on.png";
+ }else{
+ $("speaker").src = "/webdata/gfx/speak_off.png";
+ }
+ }
+}
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++
+//++++ Bouqet managing functions ++++
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++
+ function loadRootTVBouqet(){
+ //rootB = '/web/fetchchannels?ServiceListBrowse='+escape('1:7:1:0:0:0:0:0:0:0:(type == 1) FROM BOUQUET "bouquets.tv" ORDER BY bouquet');
+ rootB = '/web/fetchchannels?ServiceListBrowse='+escape('1:7:1:0:0:0:0:0:0:0:(type == 1) || (type == 17) || (type == 195) || (type == 25) FROM BOUQUET "bouquets.tv" ORDER BY bouquet');
+
+
+ loadRootBouqet(rootB);
+ }
+ function loadRootBouqet(rootB){
+
+ t =getHTTPObject();
+ t.onreadystatechange = incomingResult;
+ t.open('GET', rootB, true);
+ t.send(null);
+
+ }
+ function incomingResult(){
+ if((t.readyState == 4) && (t.status == 200)) {
+ // perfekt!
+ var r = t.responseXML;
+
+ var b = r.getElementsByTagName("e2servicelist").item(0).getElementsByTagName("e2service");
+
+ bouquets = new Array();
+ for ( var i=0; i < b.length; i++){
+ bRef = b.item(i).getElementsByTagName('e2servicereference').item(0).firstChild.data;
+ bName = b.item(i).getElementsByTagName('e2servicename').item(0).firstChild.data;
+
+ bu = new Array(bName,bRef);
+ bouquets.push(bu)
+ }
+ refreshSelect(bouquets);
+ } else {
+ // die Anfrage enthielt Fehler;
+ // die Antwort war z.B. 404 (nicht gefunden)
+ // oder 500 (interner Server-Fehler)
+ }
+
+ }
+ // to add the bouqetts to the list
+ function refreshSelect(arraybouqet){
+
+ sel = document.getElementById("accordionMenueBouqetContent");
+ // options neu eintragen
+ html = "<table>";
+ for ( var i = 0 ; i < arraybouqet.length ; i++ ){
+ if(arraybouqet[i][0] && arraybouqet[i][1]){
+ html+="<tr><td>";
+ html+="<a onclick=\"bouqetSelected(this); setBodyMainContent('BodyContentChannellist');\" id='";
+ html+= arraybouqet[i][1];
+ html+="'>";
+ html+= arraybouqet[i][0];
+ html+="</a>";
+ html+="</td></tr>";
+ }
+ }
+ html+="</table>";
+ sel.innerHTML=html;
+ refreshChannellist(arraybouqet[0][0],arraybouqet[0][1]);
+ }
+ //++++++++++++++++++++++
+ function bouqetSelected(element){
+ refreshChannellist(element.value,element.id)
+ }
+
+ function refreshChannellist(bname,bref){
+ urlx = '/web/fetchchannels?ServiceListBrowse='+escape(bref);
+ w =getHTTPObject();
+ w.onreadystatechange = incomingChannellist;
+ w.open('GET', urlx, true);
+ w.send(null);
+
+
+
+ }
+ function incomingChannellist(){
+ if (w.readyState == 4) {
+ // alles in Ordnung, Antwort wurde empfangen
+ if (w.responseXML != "no data"){
+ var services = w.responseXML.getElementsByTagName("e2servicelist").item(0).getElementsByTagName("e2service");
+ listerHtml = "<table id=\"ChannelSelect\" >";
+
+ for ( var i = 0; i < (services.length ); i++){
+ sRef = services.item(i).getElementsByTagName('e2servicereference').item(0).firstChild.data;
+ sName = services.item(i).getElementsByTagName('e2servicename').item(0).firstChild.data;
+
+ listerHtml += '<tr bgcolor="gray"><td><div onclick=\"zap(this)\" id="';
+ listerHtml += sRef;
+ listerHtml += '">';
+ listerHtml += sName;
+ listerHtml += '</div></td>';
+ listerHtml += '<td><a onclick=\"new EPGList().getByServiceReference(this.id,$(\'BodyEPGPanel\'));setBodyMainContent(\'BodyEPGPanel\');\" id="';
+ listerHtml += sRef;
+ listerHtml += '" >EPG</div><div><a target=\"blank" href=\"stream.m3u?ref=';
+ listerHtml += sRef;
+ listerHtml += '\">Stream</a></div></td>';
+ listerHtml += '</tr>';
+ }
+ listerHtml += "</table>";
+ document.getElementById("BodyContentChannellist").innerHTML = listerHtml;
+ setBodyMainContent('BodyContentChannellist');
+ } else {
+ // die Anfrage enthielt Fehler;
+ // die Antwort war z.B. 404 (nicht gefunden)
+ // oder 500 (interner Server-Fehler)
+ }
+ }
+
+ }
+
+
+
--- /dev/null
+installdir = /usr/lib/enigma2/python/Plugins/Extensions/WebInterface/web/
+
+install_DATA = *.xml
--- /dev/null
+<e2:screen name="TestScreen"><?xml version="1.0" encoding="utf-8"?>
+<e2eventlist><e2:element source="EPGNOWNEXT" id="ref"><e2:convert type="web:ListFiller" >
+ <e2event>
+ <e2eventid><e2:item name="EventID" /> </e2eventid>
+ <e2eventstart><e2:item name="TimeStart"/> </e2eventstart>
+ <e2eventduration><e2:item name="Duration"/> </e2eventduration>
+ <e2eventtitle><e2:item name="Title"/> </e2eventtitle>
+ <e2eventdescription><e2:item name="Description"/> </e2eventdescription>
+ <e2eventdescriptionextended><e2:item name="DescriptionExtended"/> </e2eventdescriptionextended>
+ <e2eventservicereference><e2:item name="ServiceReference"/> </e2eventservicereference>
+ <e2eventservicename><e2:item name="ServiceName"/> </e2eventservicename>
+ </e2event></e2:convert><e2:convert type="web:TextToHTML" /></e2:element>
+</e2eventlist>
+</e2:screen>
\ No newline at end of file
--- /dev/null
+<e2:screen name="TestScreen"><?xml version="1.0"?>
+<e2eventlist><e2:element source="EPGTITLE" id="search"><e2:convert type="web:ListFiller" >
+ <e2event>
+ <e2eventid><e2:item name="EventID" /> </e2eventid>
+ <e2eventstart><e2:item name="TimeStart"/> </e2eventstart>
+ <e2eventduration><e2:item name="Duration"/> </e2eventduration>
+ <e2eventtitle><e2:item name="Title"/> </e2eventtitle>
+ <e2eventdescription><e2:item name="Description"/> </e2eventdescription>
+ <e2eventdescriptionextended><e2:item name="DescriptionExtended"/> </e2eventdescriptionextended>
+ <e2eventservicereference><e2:item name="ServiceReference"/> </e2eventservicereference>
+ <e2eventservicename><e2:item name="ServiceName"/> </e2eventservicename>
+ </e2event></e2:convert><e2:convert type="web:TextToHTML" /></e2:element>
+</e2eventlist>
+</e2:screen>
\ No newline at end of file
--- /dev/null
+<e2:screen name="TestScreen"><?xml version="1.0" encoding="utf-8"?>
+<e2eventlist><e2:element source="EPGSERVICE" id="ref"><e2:convert type="web:ListFiller" >
+ <e2event>
+ <e2eventid><e2:item name="EventID" /> </e2eventid>
+ <e2eventstart><e2:item name="TimeStart"/> </e2eventstart>
+ <e2eventduration><e2:item name="Duration"/> </e2eventduration>
+ <e2eventtitle><e2:item name="Title"/> </e2eventtitle>
+ <e2eventdescription><e2:item name="Description"/> </e2eventdescription>
+ <e2eventdescriptionextended><e2:item name="DescriptionExtended"/> </e2eventdescriptionextended>
+ <e2eventservicereference><e2:item name="ServiceReference"/> </e2eventservicereference>
+ <e2eventservicename><e2:item name="ServiceName"/> </e2eventservicename>
+ </e2event></e2:convert><e2:convert type="web:TextToHTML" /></e2:element>
+</e2eventlist>
+</e2:screen>
\ No newline at end of file
--- /dev/null
+<e2:screen name="TestScreen"><?xml version="1.0" encoding="UTF-8"?>
+<e2servicelist>
+<e2:element source="ServiceListBrowse">
+ <e2:convert type="web:ListFiller">
+ <e2service>
+ <e2servicereference><e2:item name="Reference" /></e2servicereference>
+ <e2servicename><e2:item name="Name"/></e2servicename>
+ </e2service>
+ </e2:convert>
+ <e2:convert type="web:TextToHTML" />
+</e2:element>
+</e2servicelist>
+</e2:screen>
\ No newline at end of file
--- /dev/null
+<e2:screen name="TestScreen"><html>
+<head>
+ <meta content="text/html; charset=UTF-8" http-equiv="content-type"/>
+ <title>Enigma2 Webinterface</title>
+ <script src="/webdata/prototype.js" type="text/javascript"/>
+ <script src="/webdata/rico.js" type="text/javascript"/>
+ <script src="/webdata/tools.js" type="text/javascript" />
+ <link href="/webdata/theme.css" rel="stylesheet" type="text/css" />
+</head>
+
+<body>
+<div id="debug"></div>
+
+<table id="htmlDesignTable" width="100%" border="0">
+<tr><td>
+<!-- START SITE HEADER //-->
+ <table width="100%" border="0">
+ <tr>
+ <td width="10%" rowspan="2">
+ <div id="Current_Channel_Box" class="roundme" >
+ <nobr><div id="CurrentService" > </div></nobr>
+ <div id="CurrentServiceProvider" > </div>
+ </div>
+ </td>
+ <td width="80%">
+ <span id="Event_Now_Name" onclick="setBodyMainContent('BodyContentEPGNow')"> </span>
+ </td>
+ <td width="150" rowspan="2">
+ <div id="Info_Box" class="roundme">
+ <table width="100">
+ <tr><td colspan="2"><div id="CurrentTime"> </div></td></tr>
+ <tr><td>SNR:</td><td><div id="SNR"></div></td></tr>
+ <tr><td>BER:</td><td><div id="BER"></div></td></tr>
+ <tr><td>AGC:</td><td><div id="AGC"></div></td></tr>
+ </table>
+ </div>
+ </td>
+ </tr><tr>
+
+ <td width="80%">
+ <span id="Event_Next_Name" onclick="setBodyMainContent('BodyContentEPGNext')"> </span>
+ </td>
+ </tr>
+ <tr><td colspan="2">
+ Volume <span id="Volume_Current" >..</span>
+ <span onclick="volumeUp()" >++</span>
+ <span onclick="volumeDown()" >--</span>
+ <span onclick="volumeMute()" >xx</span>
+ <img src="/webdata/gfx/led_off.png" id="volume1" onclick="setVolume(10)"/>
+ <img src="/webdata/gfx/led_off.png" id="volume2" onclick="setVolume(20)"/>
+ <img src="/webdata/gfx/led_off.png" id="volume3" onclick="setVolume(30)"/>
+ <img src="/webdata/gfx/led_off.png" id="volume4" onclick="setVolume(40)"/>
+ <img src="/webdata/gfx/led_off.png" id="volume5" onclick="setVolume(50)"/>
+ <img src="/webdata/gfx/led_off.png" id="volume6" onclick="setVolume(60)"/>
+ <img src="/webdata/gfx/led_off.png" id="volume7" onclick="setVolume(70)"/>
+ <img src="/webdata/gfx/led_off.png" id="volume8" onclick="setVolume(80)"/>
+ <img src="/webdata/gfx/led_off.png" id="volume9" onclick="setVolume(90)"/>
+ <img src="/webdata/gfx/led_off.png" id="volume10" onclick="setVolume(100)"/>
+ <img src="/webdata/gfx/speak_on.png" id="speaker" onclick="volumeMute()" />
+ </td>
+ <td>
+ <form onSubmit="new EPGList().getBySearchString($('searchText').value,$('BodyEPGPanel')); setBodyMainContent('BodyEPGPanel'); return false;">
+ <input type="text" id="searchText" onfocus="this.value=''" value="EPG suchen"/>
+ </form>
+ </td>
+ </tr>
+ </table>
+
+<!-- END SITE HEADER //-->
+</td></tr>
+<tr><td>
+<!-- START SITE BODY //-->
+ <table id="htmlDesignTableBody" width="100%" border="0">
+ <tr>
+ <td id="htmlDesignTableBodyMenue" width="150" valign="top">
+ <!-- START BODY MENUE //-->
+ <div id="accordionMenue">
+ <div id="accordionMenueBouqetPanel">
+ <div id="accordionMenueBouqetHeader">
+ Bouquets
+ </div>
+ <div id="accordionMenueBouqetContent">
+
+ </div>
+ </div>
+ <!--<div id="accordionMenueControlPanel">
+ <div id="accordionMenueControlHeader">
+ Control
+ </div>
+ <div id="accordionMenueControlContent">
+ <table>
+ <tr><td><a onclick="setBodyMainContent('BodyContentMessageform')">Nachricht</a></td></tr>
+ <tr><td><a onclick="setBodyMainContent('BodyContentPower')">Shutdown</a></td></tr>
+ <tr><td><a onclick="setBodyMainContent('BodyContentHDD')">HDD</a></td></tr>
+ <tr><td><a onclick="setBodyMainContent('BodyContentDebugbox')">JscriptDebug</a></td></tr>
+ </table>
+ </div>
+ </div>//-->
+ </div>
+
+ <!-- END BODY MENUE //-->
+ </td>
+ <td id="htmlDesignTableBodyMain" valign="top" witdh="100%" >
+ <!-- START BODY MAIN //-->
+ <!-- START BodyContentEPGNext //-->
+ <div id="BodyContentEPGNext" style="display:none;" >
+ <div id="Event_Next_Box">
+ <table id="Event_Table_Next" width="100%" border="1">
+ <tr>
+ <td>
+ <span id="Event_Next_Begin"></span> bis <span id="Event_Next_End"></span>
+ </td>
+ <td>
+ <span id="Event_Next_Name" onclick="setBodyMainContent('BodyContentEPGNext')"> </span>
+ <a href="javascript:imdb()">...</a>
+ </td>
+ <td>
+ <span id="Event_Next_Remaining"> </span>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="3">
+ <div id="Event_Next_Description"> </div>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="3">
+ <div id="Event_Next_Extended_Description"> </div>
+ </td>
+ </tr>
+ </table>
+ </div>
+ </div>
+ <!-- ENDE BodyContentEPGNext //-->
+ <!-- START BodyContentEPGNow //-->
+ <div id="BodyContentEPGNow" style="display:none;">
+ <div id="Event_Now_Box">
+ <table id="Event_Table_Now" width="100%" border="1">
+ <tr>
+ <td>
+ <span id="Event_Now_Begin"></span> bis <span id="Event_Now_End"></span>
+ </td>
+ <td>
+ <span id="Event_Now_Name" onclick="setBodyMainContent('BodyContentEPGNow')"> </span>
+ <a href="javascript:imdb()">...</a>
+ </td>
+ <td>
+ <span id="Event_Now_Remaining"> </span>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="3">
+ <div id="Event_Now_Description"> </div>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="3">
+ <div id="Event_Now_Extended_Description"> </div>
+ </td>
+ </tr>
+ </table>
+ </div>
+ </div>
+ <!-- END BodyContentEPGNow //-->
+ <!-- START BodyContentChannellist //-->
+ <div id="BodyContentChannellist" style="display:none;"></div>
+ <!-- END BodyContentChannellist //-->
+ <!-- START BodyContentMessageform //-->
+ <div id="BodyContentMessageform" style="display:none;">
+ BodyContentText BodyContentText BodyContentText BodyContentText
+ </div>
+ <!-- END BodyContentMessageform //-->
+ <!-- START BodyContentPower //-->
+ <div id="BodyContentPower" style="display:none;">
+ standby, Poweroff, E2restart
+ </div>
+ <!-- END BodyContentPower //-->
+ <!-- START BodyContentHDD //-->
+ <div id="BodyContentHDD" style="display:none;">
+ <iframe src="/hdd/" width="100%" height="400"/>
+ </div>
+ <!-- END BodyContentHDD //-->
+ <!-- START BodyContentDebugbox //-->
+ <div id="BodyContentDebugbox" style="display:none;">
+
+ </div>
+ <!-- END BodyContentDebugbox //-->
+ <!-- START BodyEPGPanel //-->
+ <div id="BodyEPGPanel" style="display:none;">
+
+ </div>
+ <!-- END BodyEPGPanel //-->
+
+ <!-- END CHANNELLIST //-->
+ <!-- END BODY MAIN //-->
+ </td>
+ </tr>
+ </table>
+<!-- END SITE BODY //-->
+</td></tr>
+</table>
+
+
+<script type="text/javascript" >
+// HTML Effekts by wwwopenrico.org
+new Rico.Effect.Round('div','roundme' );
+new Rico.Effect.Round('div','button' );
+new Rico.Accordion( $('accordionMenue') );
+//
+getVolume();
+loadRootTVBouqet();
+//loadRootRadioBouqet();
+setBodyMainContent('BodyContentChannellist');
+function updatePage()
+{
+}
+
+function imdb()
+{
+ w = window.open("http://www.imdb.com/find?s=all&q=" + escape(document.getElementById("Event_Now_Name").innerHTML));
+ w.focus();
+}
+
+</script>
+</body>
+<div id="scriptzone">
+<!-- realtime updates follow -->
+<e2:element source="CurrentTime" streaming="yes">
+ <e2:convert type="ClockToText">WithSeconds</e2:convert>
+ <e2:convert type="web:JavascriptUpdate" />
+</e2:element>
+<e2:element source="CurrentService" streaming="yes">
+ <e2:convert type="ServiceName">Name</e2:convert>
+ <e2:convert type="web:JavascriptUpdate" />
+</e2:element>
+<e2:element source="Event_Now" id="Event_Now_Name" streaming="yes">
+ <e2:convert type="EventName">Name</e2:convert>
+ <e2:convert type="web:JavascriptUpdate" />
+</e2:element>
+<e2:element source="Event_Now" id="Event_Now_Description" streaming="yes">
+ <e2:convert type="EventName">Description</e2:convert>
+ <e2:convert type="web:JavascriptUpdate" />
+</e2:element>
+<e2:element source="Event_Now" id="Event_Now_Extended_Description" streaming="yes">
+ <e2:convert type="EventName">ExtendedDescription</e2:convert>
+ <e2:convert type="web:JavascriptUpdate" />
+</e2:element>
+<e2:element source="Event_Now" id="Event_Now_Begin" streaming="yes">
+ <e2:convert type="EventTime">StartTime</e2:convert>
+ <e2:convert type="ClockToText">Default</e2:convert>
+ <e2:convert type="web:JavascriptUpdate" />
+</e2:element>
+<e2:element source="Event_Now" id="Event_Now_End" streaming="yes">
+ <e2:convert type="EventTime">EndTime</e2:convert>
+ <e2:convert type="ClockToText">Default</e2:convert>
+ <e2:convert type="web:JavascriptUpdate" />
+</e2:element>
+<e2:element source="Event_Now" id="Event_Now_Remaining" streaming="yes">
+ <e2:convert type="EventTime">Remaining</e2:convert>
+ <e2:convert type="RemainingToText">InMinutes</e2:convert>
+ <e2:convert type="web:JavascriptUpdate" />
+</e2:element>
+
+
+<e2:element source="Event_Next" id="Event_Next_Name" streaming="yes">
+ <e2:convert type="EventName">Name</e2:convert>
+ <e2:convert type="web:JavascriptUpdate" />
+</e2:element>
+<e2:element source="Event_Next" id="Event_Next_Begin" streaming="yes">
+ <e2:convert type="EventTime">StartTime</e2:convert>
+ <e2:convert type="ClockToText">Default</e2:convert>
+ <e2:convert type="web:JavascriptUpdate" />
+</e2:element>
+<e2:element source="Event_Next" id="Event_Next_End" streaming="yes">
+ <e2:convert type="EventTime">EndTime</e2:convert>
+ <e2:convert type="ClockToText">Default</e2:convert>
+ <e2:convert type="web:JavascriptUpdate" />
+</e2:element>
+<e2:element source="Event_Next" id="Event_Next_Remaining" streaming="yes">
+ <e2:convert type="EventTime">Remaining</e2:convert>
+ <e2:convert type="RemainingToText">InMinutes</e2:convert>
+ <e2:convert type="web:JavascriptUpdate" />
+</e2:element>
+<e2:element source="Event_Next" id="Event_Next_Extended_Description" streaming="yes">
+ <e2:convert type="EventName">ExtendedDescription</e2:convert>
+ <e2:convert type="web:JavascriptUpdate" />
+</e2:element>
+
+
+<e2:element source="FrontendStatus" id="SNR" streaming="yes">
+ <e2:convert type="FrontendInfo">SNR</e2:convert>
+ <e2:convert type="web:JavascriptUpdate" />
+</e2:element>
+<e2:element source="FrontendStatus" id="BER" streaming="yes">
+ <e2:convert type="FrontendInfo">BER</e2:convert>
+ <e2:convert type="web:JavascriptUpdate" />
+</e2:element>
+<e2:element source="FrontendStatus" id="AGC" streaming="yes">
+ <e2:convert type="FrontendInfo">AGC</e2:convert>
+ <e2:convert type="web:JavascriptUpdate" />
+</e2:element>
+
+
+<e2:element source="CurrentService" id="CurrentServiceProvider" streaming="yes">
+ <e2:convert type="ServiceName">Provider</e2:convert>
+ <e2:convert type="web:JavascriptUpdate" />
+</e2:element>
+
+
+
+</e2:screen>
--- /dev/null
+<e2:screen name="StreamingM3U">#EXTM3U
+#EXTVLCOPT--http-reconnect=true
+http://<e2:element source="localip" />:8001/<e2:element source="ref"><e2:convert type="web:TextToHTML" /></e2:element>
+</e2:screen>
--- /dev/null
+<e2:screen name="Streaming"><e2:element source="StreamService" streaming="yes">
+<e2:convert type="Streaming" />
+<e2:convert type="web:TextToHTML" />
+</e2:element></e2:screen>
--- /dev/null
+<e2:screen name="TestScreen"><?xml version="1.0" encoding="utf-8"?>
+<e2timerlist><e2:element source="TimerList" ><e2:convert type="web:ListFiller" >
+ <e2timer>
+ <e2servicereference><e2:item name="ServiceReference" /></e2servicereference>
+ <e2servicename><e2:item name="ServiceName" /></e2servicename>
+ <e2eit><e2:item name="EIT" /></e2eit>
+ <e2name><e2:item name="Name" /></e2name>
+ <e2description><e2:item name="Description" /></e2description>
+ <e2disabled><e2:item name="Disabled" /></e2disabled>
+ <e2timebegin><e2:item name="TimeBegin" /></e2timebegin>
+ <e2timeend><e2:item name="TimeEnd" /></e2timeend>
+ <e2duration><e2:item name="Duration" /></e2duration>
+ <e2startprepare><e2:item name="startPrepare" /></e2startprepare>
+ <e2justplay><e2:item name="justPlay" /></e2justplay>
+ <e2afterevent><e2:item name="afterEvent" /></e2afterevent>
+ <e2logentries><e2:item name="LogEntries" /></e2logentries>
+ <e2filename><e2:item name="Filename" /></e2filename>
+ <e2backoff><e2:item name="Backoff" /></e2backoff>
+ <e2nextactivation><e2:item name="nextActivation" /></e2nextactivation>
+ <e2firsttryprepare><e2:item name="firstTryPrepare" /></e2firsttryprepare>
+ <e2state><e2:item name="State" /></e2state>
+ <e2repeated><e2:item name="Repeated" /></e2repeated>
+ <e2dontsave><e2:item name="dontSave" /></e2dontsave>
+ <e2cancled><e2:item name="Cancled" /></e2cancled>
+ </e2timer>
+ </e2:convert>
+ <e2:convert type="web:TextToHTML" /></e2:element>
+</e2timerlist>
+</e2:screen>
\ No newline at end of file
--- /dev/null
+<e2:screen name="TestScreen">
+<e2:element source="Volume" id="set">
+<e2:convert type="VolumeToText">CurrentVolume</e2:convert>
+</e2:element>
+</e2:screen>
--- /dev/null
+<e2:screen name="TestScreen"><e2:element source="ServiceList" id="ZapTo">
+ <e2:convert type="web:Null" />
+</e2:element></e2:screen>
--- /dev/null
+#
+# OK, this is more than a proof of concept
+# things to improve:
+# - nicer code
+# - screens need to be defined somehow else.
+# I don't know how, yet. Probably each in an own file.
+# - more components, like the channellist
+# - better error handling
+# - use namespace parser
+
+from Screens.Screen import Screen
+from Tools.Import import my_import
+
+# for our testscreen
+from Screens.InfoBarGenerics import InfoBarServiceName, InfoBarEvent, InfoBarTuner
+
+from Components.Sources.Clock import Clock
+from Components.Sources.ServiceList import ServiceList
+from Components.Sources.Volume import Volume
+from Components.Sources.EPG import EPG
+from Components.Sources.Timer import Timer
+from Components.Sources.FrontendStatus import FrontendStatus
+
+from Components.Converter.Converter import Converter
+from Components.Converter.VolumeToText import VolumeToText
+
+from Components.Element import Element
+
+from xml.sax import make_parser
+from xml.sax.handler import ContentHandler, feature_namespaces
+from twisted.python import util
+import sys
+import time
+
+# prototype of the new web frontend template system.
+
+class WebScreen(Screen):
+ def __init__(self, session):
+ Screen.__init__(self, session)
+ self.stand_alone = True
+
+# a test screen
+class TestScreen(InfoBarServiceName, InfoBarEvent,InfoBarTuner, WebScreen,Volume):
+ def __init__(self, session):
+ WebScreen.__init__(self, session)
+ InfoBarServiceName.__init__(self)
+ InfoBarEvent.__init__(self)
+ InfoBarTuner.__init__(self)
+ Volume.__init__(self,session);
+ self["CurrentTime"] = Clock()
+# self["TVSystem"] = Config(config.av.tvsystem)
+# self["OSDLanguage"] = Config(config.osd.language)
+# self["FirstRun"] = Config(config.misc.firstrun)
+ from enigma import eServiceReference
+ fav = eServiceReference('1:7:1:0:0:0:0:0:0:0:(type == 1) || (type == 17) || (type == 195) || (type == 25) FROM BOUQUET "bouquets.tv" ORDER BY bouquet')
+ self["ServiceList"] = ServiceList(fav, command_func = self.zapTo, validate_commands=False)
+ self["ServiceListBrowse"] = ServiceList(fav, command_func = self.browseTo)
+ self["Volume"] = Volume(session)
+ self["EPGTITLE"] = EPG(session,func=EPG.TITLE)
+ self["EPGSERVICE"] = EPG(session,func=EPG.SERVICE)
+ self["EPGNOWNEXT"] = EPG(session,func=EPG.NOWNEXT)
+ self["TimerList"] = Timer(session)
+
+ def browseTo(self, reftobrowse):
+ self["ServiceListBrowse"].root = reftobrowse
+
+ def zapTo(self, reftozap):
+ self.session.nav.playService(reftozap)
+
+# TODO: (really.) put screens into own files.
+class Streaming(WebScreen):
+ def __init__(self, session):
+ WebScreen.__init__(self, session)
+ from Components.Sources.StreamService import StreamService
+ self["StreamService"] = StreamService(self.session.nav)
+
+class StreamingM3U(WebScreen):
+ def __init__(self, session):
+ WebScreen.__init__(self, session)
+ from Components.Sources.StaticText import StaticText
+ from Components.Sources.Config import Config
+ from Components.config import config
+
+ self["ref"] = StaticText()
+ self["localip"] = Config(config.network.ip)
+
+# implements the 'render'-call.
+# this will act as a downstream_element, like a renderer.
+class OneTimeElement(Element):
+ def __init__(self, id):
+ Element.__init__(self)
+ self.source_id = id
+
+ # CHECKME: is this ok performance-wise?
+ def handleCommand(self, args):
+ for c in args.get(self.source_id, []):
+ self.source.handleCommand(c)
+
+ def render(self, stream):
+ t = self.source.getHTML(self.source_id)
+ if isinstance(t, unicode):
+ t = t.encode("utf-8")
+ stream.write(t)
+
+ def execBegin(self):
+ pass
+
+ def execEnd(self):
+ pass
+
+ def onShow(self):
+ pass
+
+ def onHide(self):
+ pass
+
+ def destroy(self):
+ pass
+
+class StreamingElement(OneTimeElement):
+ def __init__(self, id):
+ OneTimeElement.__init__(self, id)
+ self.stream = None
+
+ def changed(self, what):
+ if self.stream:
+ self.render(self.stream)
+
+ def setStream(self, stream):
+ self.stream = stream
+
+# a to-be-filled list item
+class ListItem:
+ def __init__(self, name):
+ self.name = name
+
+class TextToHTML(Converter):
+ def __init__(self, arg):
+ Converter.__init__(self, arg)
+
+ def getHTML(self, id):
+ return self.source.text # encode & etc. here!
+
+# a null-output. Useful if you only want to issue a command.
+class Null(Converter):
+ def __init__(self, arg):
+ Converter.__init__(self, arg)
+
+ def getHTML(self, id):
+ return ""
+
+def escape(s):
+ return s.replace("\\", "\\\\").replace("\n", "\\n").replace('"', '\\"')
+
+class JavascriptUpdate(Converter):
+ def __init__(self, arg):
+ Converter.__init__(self, arg)
+
+ def getHTML(self, id):
+ return '<script>set("' + id + '", "' + escape(self.source.text) + '");</script>\n'
+
+# the performant 'listfiller'-engine (plfe)
+class ListFiller(Converter):
+ def __init__(self, arg):
+ Converter.__init__(self, arg)
+
+ def getText(self):
+ l = self.source.list
+ lut = self.source.lut
+
+ # now build a ["string", 1, "string", 2]-styled list, with indices into the
+ # list to avoid lookup of item name for each entry
+ lutlist = []
+ for element in self.converter_arguments:
+ if isinstance(element, str):
+ lutlist.append(element)
+ elif isinstance(element, ListItem):
+ lutlist.append(lut[element.name])
+
+ # now, for the huge list, do:
+ res = ""
+ for item in l:
+ for element in lutlist:
+ if isinstance(element, str):
+ res += element
+ else:
+ res += str(item[element])
+ # (this will be done in c++ later!)
+ return res
+
+ text = property(getText)
+
+class webifHandler(ContentHandler):
+ def __init__(self, session):
+ self.res = [ ]
+ self.mode = 0
+ self.screen = None
+ self.session = session
+ self.screens = [ ]
+
+ def startElement(self, name, attrs):
+ if name == "e2:screen":
+ self.screen = eval(attrs["name"])(self.session) # fixme
+ self.screens.append(self.screen)
+ return
+
+ if name[:3] == "e2:":
+ self.mode += 1
+
+ tag = "<" + name + ''.join([' ' + key + '="' + val + '"' for (key, val) in attrs.items()]) + ">"
+ tag = tag.encode("UTF-8")
+
+ if self.mode == 0:
+ self.res.append(tag)
+ elif self.mode == 1: # expect "<e2:element>"
+ assert name == "e2:element", "found %s instead of e2:element" % name
+ source = attrs["source"]
+ self.source_id = str(attrs.get("id", source))
+ self.source = self.screen[source]
+ self.is_streaming = "streaming" in attrs
+ elif self.mode == 2: # expect "<e2:convert>"
+ if name[:3] == "e2:":
+ assert name == "e2:convert"
+
+ ctype = attrs["type"]
+ if ctype[:4] == "web:": # for now
+ self.converter = eval(ctype[4:])
+ else:
+ self.converter = my_import('.'.join(["Components", "Converter", ctype])).__dict__.get(ctype)
+ self.sub = [ ]
+ else:
+ self.sub.append(tag)
+ elif self.mode == 3:
+ assert name == "e2:item", "found %s instead of e2:item!" % name
+ assert "name" in attrs, "e2:item must have a name= attribute!"
+ self.sub.append(ListItem(attrs["name"]))
+
+ def endElement(self, name):
+ if name == "e2:screen":
+ self.screen = None
+ return
+
+ tag = "</" + name + ">"
+ if self.mode == 0:
+ self.res.append(tag)
+ elif self.mode == 2 and name[:3] != "e2:":
+ self.sub.append(tag)
+ elif self.mode == 2: # closed 'convert' -> sub
+ self.sub = lreduce(self.sub)
+ if len(self.sub) == 1:
+ self.sub = self.sub[0]
+ c = self.converter(self.sub)
+ c.connect(self.source)
+ self.source = c
+
+ del self.sub
+ elif self.mode == 1: # closed 'element'
+ # instatiate either a StreamingElement or a OneTimeElement, depending on what's required.
+ if not self.is_streaming:
+ c = OneTimeElement(self.source_id)
+ else:
+ c = StreamingElement(self.source_id)
+
+ c.connect(self.source)
+ self.res.append(c)
+ self.screen.renderer.append(c)
+ del self.source
+
+ if name[:3] == "e2:":
+ self.mode -= 1
+
+ def processingInstruction(self, target, data):
+ self.res.append('<?' + target + ' ' + data + '>')
+
+ def characters(self, ch):
+ ch = ch.encode("UTF-8")
+ if self.mode == 0:
+ self.res.append(ch)
+ elif self.mode == 2:
+ self.sub.append(ch)
+
+ def startEntity(self, name):
+ self.res.append('&' + name + ';');
+
+ def execBegin(self):
+ for screen in self.screens:
+ screen.execBegin()
+
+ def cleanup(self):
+ print "screen cleanup!"
+ for screen in self.screens:
+ screen.execEnd()
+ screen.doClose()
+ self.screens = [ ]
+
+def lreduce(list):
+ # ouch, can be made better
+ res = [ ]
+ string = None
+ for x in list:
+ if isinstance(x, str) or isinstance(x, unicode):
+ if isinstance(x, unicode):
+ x = x.encode("UTF-8")
+ if string is None:
+ string = x
+ else:
+ string += x
+ else:
+ if string is not None:
+ res.append(string)
+ string = None
+ res.append(x)
+ if string is not None:
+ res.append(string)
+ string = None
+ return res
+
+def renderPage(stream, path, req, session):
+
+ # read in the template, create required screens
+ # we don't have persistense yet.
+ # if we had, this first part would only be done once.
+ handler = webifHandler(session)
+ parser = make_parser()
+ parser.setFeature(feature_namespaces, 0)
+ parser.setContentHandler(handler)
+ parser.parse(open(util.sibpath(__file__, path)))
+
+ # by default, we have non-streaming pages
+ finish = True
+
+ # first, apply "commands" (aka. URL argument)
+ for x in handler.res:
+ if isinstance(x, Element):
+ x.handleCommand(req.args)
+
+ handler.execBegin()
+
+ # now, we have a list with static texts mixed
+ # with non-static Elements.
+ # flatten this list, write into the stream.
+ for x in lreduce(handler.res):
+ if isinstance(x, Element):
+ if isinstance(x, StreamingElement):
+ finish = False
+ x.setStream(stream)
+ x.render(stream)
+ else:
+ stream.write(str(x))
+
+ def ping(s):
+ from twisted.internet import reactor
+ s.write("\n");
+ reactor.callLater(3, ping, s)
+
+ # if we met a "StreamingElement", there is at least one
+ # element which wants to output data more than once,
+ # i.e. on host-originated changes.
+ # in this case, don't finish yet, don't cleanup yet,
+ # but instead do that when the client disconnects.
+ if finish:
+ handler.cleanup()
+ stream.finish()
+ else:
+ # ok.
+ # you *need* something which constantly sends something in a regular interval,
+ # in order to detect disconnected clients.
+ # i agree that this "ping" sucks terrible, so better be sure to have something
+ # similar. A "CurrentTime" is fine. Or anything that creates *some* output.
+ ping(stream)
+ stream.closed_callback = lambda: handler.cleanup()