From reebalazs at codespeak.net Fri Sep 1 13:21:16 2006 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Fri, 1 Sep 2006 13:21:16 +0200 (CEST) Subject: [Kukit-checkins] r31918 - kukit/kukit.js/trunk/kukit Message-ID: <20060901112116.6EE7D10068@code0.codespeak.net> Author: reebalazs Date: Fri Sep 1 13:21:14 2006 New Revision: 31918 Modified: kukit/kukit.js/trunk/kukit/kssparser.js Log: Make kss parsing error more explicit Modified: kukit/kukit.js/trunk/kukit/kssparser.js ============================================================================== --- kukit/kukit.js/trunk/kukit/kssparser.js (original) +++ kukit/kukit.js/trunk/kukit/kssparser.js Fri Sep 1 13:21:14 2006 @@ -477,7 +477,7 @@ } catch(e) { if (e.name == 'ParsingError') { // Log the message - var msg = 'Error parsing ' + this.href + ' : ' + e.toString(); + var msg = 'Error parsing KSS at ' + this.href + ' : ' + e.toString(); kukit.logFatal(msg); // just throw it too... throw msg; From reebalazs at codespeak.net Fri Sep 1 17:13:32 2006 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Fri, 1 Sep 2006 17:13:32 +0200 (CEST) Subject: [Kukit-checkins] r31938 - kukit/azax/trunk Message-ID: <20060901151332.8BA7D10068@code0.codespeak.net> Author: reebalazs Date: Fri Sep 1 17:13:31 2006 New Revision: 31938 Modified: kukit/azax/trunk/configure.zcml Log: Use the new concatresource options for faster debugging operation (commented out) Modified: kukit/azax/trunk/configure.zcml ============================================================================== --- kukit/azax/trunk/configure.zcml (original) +++ kukit/azax/trunk/configure.zcml Fri Sep 1 17:13:31 2006 @@ -28,8 +28,10 @@ name="kukit.js" compress_level="safe" /> - Author: reebalazs Date: Fri Sep 1 17:16:20 2006 New Revision: 31939 Modified: kukit/azax/branch/zope2.8/configure.zcml Log: Merge from trunk (concatresource debug options) Modified: kukit/azax/branch/zope2.8/configure.zcml ============================================================================== --- kukit/azax/branch/zope2.8/configure.zcml (original) +++ kukit/azax/branch/zope2.8/configure.zcml Fri Sep 1 17:16:20 2006 @@ -28,8 +28,10 @@ name="kukit.js" compress_level="safe" /> - Author: gotcha Date: Mon Sep 4 09:56:39 2006 New Revision: 31976 Modified: kukit/azax/trunk/azaxview.py kukit/azax/trunk/tests/test_azaxview.py Log: fix tests that I broke Modified: kukit/azax/trunk/azaxview.py ============================================================================== --- kukit/azax/trunk/azaxview.py (original) +++ kukit/azax/trunk/azaxview.py Mon Sep 4 09:56:39 2006 @@ -61,10 +61,14 @@ ''' return self.commands.render(self.request) + def getCommands(self): + return self.commands + def __getattr__(self, name): if name == '__provides__': raise AttributeError(name) elif hasattr(self.commands, name): + #XXX surface only actual commands, not inner guts return getattr(self.commands, name) else: raise AttributeError(name) Modified: kukit/azax/trunk/tests/test_azaxview.py ============================================================================== --- kukit/azax/trunk/tests/test_azaxview.py (original) +++ kukit/azax/trunk/tests/test_azaxview.py Mon Sep 4 09:56:39 2006 @@ -98,10 +98,10 @@ def test_addCommand(self): view = self.view - command = view.addCommand('setHtmlAsChild', 'selector') commands = view.getCommands() + command = commands.addCommand('replaceInnerHTML', 'selector') self.assertEqual(len(commands), 1) - self.assertEqual(command.getName(), 'setHtmlAsChild') + self.assertEqual(command.getName(), 'replaceInnerHTML') self.assertEqual(command.getSelector(), 'selector') params = command.getParams() self.assertEqual(len(params), 0) @@ -111,11 +111,11 @@ def _checkSetHtmlResult(self, content, content2=None): view = self.view - view.setHtmlAsChild('div.class', content) + view.replaceInnerHTML('div.class', content) commands = view.getCommands() self.assertEqual(len(commands), 1) command = commands[0] - self.assertEqual(command.getName(), 'setHtmlAsChild') + self.assertEqual(command.getName(), 'replaceInnerHTML') self.assertEqual(command.getSelector(), 'div.class') params = command.getParams() self.assertEqual(len(params), 1) @@ -124,28 +124,28 @@ content2 = content self.assertEqual(params[0].getContent(), content2) - def test_setHtmlAsChildTextPlusEntity(self): + def test_replaceInnerHTMLTextPlusEntity(self): 'See if non breaking space entity works' ##self._checkSetHtmlResult(' ') # XXX we remove html named entities now self._checkSetHtmlResult(' ', ' ') - def test_setHtmlAsChildTextPlusEntityOthers(self): + def test_replaceInnerHTMLTextPlusEntityOthers(self): 'See if the other HTML entities work as well' # XXX we remove html named entities now self._checkSetHtmlResult('

»Hello world!«

', '

»Hello world!«

') - def test_setHtmlAsChildTextOnly(self): + def test_replaceInnerHTMLTextOnly(self): self._checkSetHtmlResult('new content') - def test_setHtmlAsChildTagOnly(self): + def test_replaceInnerHTMLTagOnly(self): self._checkSetHtmlResult('

new_content

') - def test_setHtmlAsChildTagPlusText(self): + def test_replaceInnerHTMLTagPlusText(self): self._checkSetHtmlResult('

new_content

after') - def test_setHtmlAsChildTextTagPlusText(self): + def test_replaceInnerHTMLTextTagPlusText(self): self._checkSetHtmlResult('before

new_content

after') def test_setHtmlAcceptsUnicode(self): @@ -160,7 +160,7 @@ 'Functional tests' def _wrapped_commands(self, inline): - header = dedent('''\ + header = dedent(u'''\ @@ -182,16 +182,17 @@ self.assertEquals(view.request.response.getHeader('Content-Type'), 'text/xml;charset=utf-8') self.assertCommandsEqual(result, '') - def test_setHtmlAsChild(self): + def test_replaceInnerHTML(self): view = self.view - view.setHtmlAsChild('div.class', 'new content') + view.replaceInnerHTML('div.class', 'new content') result = view.render() - self.assertCommandsEqual(result, '''\ - -\tnew content + new content -''') +''' + self.assertCommandsEqual(result, awaited) def test_suite(): suites = [] From reebalazs at codespeak.net Mon Sep 4 18:56:48 2006 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Mon, 4 Sep 2006 18:56:48 +0200 (CEST) Subject: [Kukit-checkins] r31990 - kukit/azax/trunk/tests Message-ID: <20060904165648.E87CC1006C@code0.codespeak.net> Author: reebalazs Date: Mon Sep 4 18:56:47 2006 New Revision: 31990 Modified: kukit/azax/trunk/tests/test_azaxview.py Log: Fix unicode test Modified: kukit/azax/trunk/tests/test_azaxview.py ============================================================================== --- kukit/azax/trunk/tests/test_azaxview.py (original) +++ kukit/azax/trunk/tests/test_azaxview.py Mon Sep 4 18:56:47 2006 @@ -122,7 +122,7 @@ self.assertEqual(params[0].getName(), 'html') if content2 == None: content2 = content - self.assertEqual(params[0].getContent(), content2) + self.assertEqual(params[0].getContent().encode('ascii', 'xmlcharrefreplace'), content2.encode('ascii', 'xmlcharrefreplace')) def test_replaceInnerHTMLTextPlusEntity(self): 'See if non breaking space entity works' From reebalazs at codespeak.net Mon Sep 4 19:04:38 2006 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Mon, 4 Sep 2006 19:04:38 +0200 (CEST) Subject: [Kukit-checkins] r31991 - in kukit/azax/branch/zope2.8: . tests Message-ID: <20060904170438.5379C1006C@code0.codespeak.net> Author: reebalazs Date: Mon Sep 4 19:04:35 2006 New Revision: 31991 Modified: kukit/azax/branch/zope2.8/azaxview.py kukit/azax/branch/zope2.8/tests/test_azaxview.py Log: Merge from trunk (fix unittests) Modified: kukit/azax/branch/zope2.8/azaxview.py ============================================================================== --- kukit/azax/branch/zope2.8/azaxview.py (original) +++ kukit/azax/branch/zope2.8/azaxview.py Mon Sep 4 19:04:35 2006 @@ -61,10 +61,14 @@ ''' return self.commands.render(self.request) + def getCommands(self): + return self.commands + def __getattr__(self, name): if name == '__provides__': raise AttributeError(name) elif hasattr(self.commands, name): + #XXX surface only actual commands, not inner guts return getattr(self.commands, name) else: raise AttributeError(name) Modified: kukit/azax/branch/zope2.8/tests/test_azaxview.py ============================================================================== --- kukit/azax/branch/zope2.8/tests/test_azaxview.py (original) +++ kukit/azax/branch/zope2.8/tests/test_azaxview.py Mon Sep 4 19:04:35 2006 @@ -98,10 +98,10 @@ def test_addCommand(self): view = self.view - command = view.addCommand('setHtmlAsChild', 'selector') commands = view.getCommands() + command = commands.addCommand('replaceInnerHTML', 'selector') self.assertEqual(len(commands), 1) - self.assertEqual(command.getName(), 'setHtmlAsChild') + self.assertEqual(command.getName(), 'replaceInnerHTML') self.assertEqual(command.getSelector(), 'selector') params = command.getParams() self.assertEqual(len(params), 0) @@ -111,41 +111,41 @@ def _checkSetHtmlResult(self, content, content2=None): view = self.view - view.setHtmlAsChild('div.class', content) + view.replaceInnerHTML('div.class', content) commands = view.getCommands() self.assertEqual(len(commands), 1) command = commands[0] - self.assertEqual(command.getName(), 'setHtmlAsChild') + self.assertEqual(command.getName(), 'replaceInnerHTML') self.assertEqual(command.getSelector(), 'div.class') params = command.getParams() self.assertEqual(len(params), 1) self.assertEqual(params[0].getName(), 'html') if content2 == None: content2 = content - self.assertEqual(params[0].getContent(), content2) + self.assertEqual(params[0].getContent().encode('ascii', 'xmlcharrefreplace'), content2.encode('ascii', 'xmlcharrefreplace')) - def test_setHtmlAsChildTextPlusEntity(self): + def test_replaceInnerHTMLTextPlusEntity(self): 'See if non breaking space entity works' ##self._checkSetHtmlResult(' ') # XXX we remove html named entities now self._checkSetHtmlResult(' ', ' ') - def test_setHtmlAsChildTextPlusEntityOthers(self): + def test_replaceInnerHTMLTextPlusEntityOthers(self): 'See if the other HTML entities work as well' # XXX we remove html named entities now self._checkSetHtmlResult('

»Hello world!«

', '

»Hello world!«

') - def test_setHtmlAsChildTextOnly(self): + def test_replaceInnerHTMLTextOnly(self): self._checkSetHtmlResult('new content') - def test_setHtmlAsChildTagOnly(self): + def test_replaceInnerHTMLTagOnly(self): self._checkSetHtmlResult('

new_content

') - def test_setHtmlAsChildTagPlusText(self): + def test_replaceInnerHTMLTagPlusText(self): self._checkSetHtmlResult('

new_content

after') - def test_setHtmlAsChildTextTagPlusText(self): + def test_replaceInnerHTMLTextTagPlusText(self): self._checkSetHtmlResult('before

new_content

after') def test_setHtmlAcceptsUnicode(self): @@ -160,7 +160,7 @@ 'Functional tests' def _wrapped_commands(self, inline): - header = dedent('''\ + header = dedent(u'''\ @@ -182,16 +182,17 @@ self.assertEquals(view.request.response.getHeader('Content-Type'), 'text/xml;charset=utf-8') self.assertCommandsEqual(result, '') - def test_setHtmlAsChild(self): + def test_replaceInnerHTML(self): view = self.view - view.setHtmlAsChild('div.class', 'new content') + view.replaceInnerHTML('div.class', 'new content') result = view.render() - self.assertCommandsEqual(result, '''\ - -\tnew content + new content -''') +''' + self.assertCommandsEqual(result, awaited) def test_suite(): suites = [] From reebalazs at codespeak.net Mon Sep 4 19:21:58 2006 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Mon, 4 Sep 2006 19:21:58 +0200 (CEST) Subject: [Kukit-checkins] r31992 - kukit/azax/trunk/tests Message-ID: <20060904172158.C2AFE10053@code0.codespeak.net> Author: reebalazs Date: Mon Sep 4 19:21:56 2006 New Revision: 31992 Modified: kukit/azax/trunk/tests/test_azaxview.py Log: Fix tests on 2.10 Modified: kukit/azax/trunk/tests/test_azaxview.py ============================================================================== --- kukit/azax/trunk/tests/test_azaxview.py (original) +++ kukit/azax/trunk/tests/test_azaxview.py Mon Sep 4 19:21:56 2006 @@ -41,7 +41,7 @@ class AzaxViewTestCase(ZopeTestCase): def afterSetUp(self): - from zope.app.tests.placelesssetup import setUp + from zope.app.testing.placelesssetup import setUp setUp() # fake content fakecontent = FakeContent() @@ -59,7 +59,13 @@ else: from Products.Five.zcml import load_string, load_config load_config('meta.zcml', package=Products.Five) - load_string(dedent('''\ + try: + # Zope 2.10 / Five 1.3.6 has traversing.zcml + load_config('traversing.zcml', package=Products.Five) + except IOError: + # on Zope 2.9 we use the old method + # (this fails on 2.10 since zope.app.traversing is moved) + load_string(dedent('''\ @@ -78,7 +84,7 @@ load_config('configure.zcml', package=Products.azax) def beforeTearDown(self): - from zope.app.tests.placelesssetup import tearDown + from zope.app.testing.placelesssetup import tearDown tearDown() try: import Products.Five From gotcha at codespeak.net Tue Sep 5 12:40:33 2006 From: gotcha at codespeak.net (gotcha at codespeak.net) Date: Tue, 5 Sep 2006 12:40:33 +0200 (CEST) Subject: [Kukit-checkins] r31997 - in kukit/kukit.js/trunk: 3rd_party kukit Message-ID: <20060905104033.742D310075@code0.codespeak.net> Author: gotcha Date: Tue Sep 5 12:40:27 2006 New Revision: 31997 Added: kukit/kukit.js/trunk/3rd_party/effects.js kukit/kukit.js/trunk/3rd_party/prototype.js Modified: kukit/kukit.js/trunk/kukit/kssparser.js kukit/kukit.js/trunk/kukit/plugin.js Log: stuff for optilude Added: kukit/kukit.js/trunk/3rd_party/effects.js ============================================================================== --- (empty file) +++ kukit/kukit.js/trunk/3rd_party/effects.js Tue Sep 5 12:40:27 2006 @@ -0,0 +1,958 @@ +// Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) +// Contributors: +// Justin Palmer (http://encytemedia.com/) +// Mark Pilgrim (http://diveintomark.org/) +// Martin Bialasinki +// +// See scriptaculous.js for full license. + +// converts rgb() and #xxx to #xxxxxx format, +// returns self (or first argument) if not convertable +String.prototype.parseColor = function() { + var color = '#'; + if(this.slice(0,4) == 'rgb(') { + var cols = this.slice(4,this.length-1).split(','); + var i=0; do { color += parseInt(cols[i]).toColorPart() } while (++i<3); + } else { + if(this.slice(0,1) == '#') { + if(this.length==4) for(var i=1;i<4;i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase(); + if(this.length==7) color = this.toLowerCase(); + } + } + return(color.length==7 ? color : (arguments[0] || this)); +} + +/*--------------------------------------------------------------------------*/ + +Element.collectTextNodes = function(element) { + return $A($(element).childNodes).collect( function(node) { + return (node.nodeType==3 ? node.nodeValue : + (node.hasChildNodes() ? Element.collectTextNodes(node) : '')); + }).flatten().join(''); +} + +Element.collectTextNodesIgnoreClass = function(element, className) { + return $A($(element).childNodes).collect( function(node) { + return (node.nodeType==3 ? node.nodeValue : + ((node.hasChildNodes() && !Element.hasClassName(node,className)) ? + Element.collectTextNodesIgnoreClass(node, className) : '')); + }).flatten().join(''); +} + +Element.setContentZoom = function(element, percent) { + element = $(element); + Element.setStyle(element, {fontSize: (percent/100) + 'em'}); + if(navigator.appVersion.indexOf('AppleWebKit')>0) window.scrollBy(0,0); +} + +Element.getOpacity = function(element){ + var opacity; + if (opacity = Element.getStyle(element, 'opacity')) + return parseFloat(opacity); + if (opacity = (Element.getStyle(element, 'filter') || '').match(/alpha\(opacity=(.*)\)/)) + if(opacity[1]) return parseFloat(opacity[1]) / 100; + return 1.0; +} + +Element.setOpacity = function(element, value){ + element= $(element); + if (value == 1){ + Element.setStyle(element, { opacity: + (/Gecko/.test(navigator.userAgent) && !/Konqueror|Safari|KHTML/.test(navigator.userAgent)) ? + 0.999999 : null }); + if(/MSIE/.test(navigator.userAgent)) + Element.setStyle(element, {filter: Element.getStyle(element,'filter').replace(/alpha\([^\)]*\)/gi,'')}); + } else { + if(value < 0.00001) value = 0; + Element.setStyle(element, {opacity: value}); + if(/MSIE/.test(navigator.userAgent)) + Element.setStyle(element, + { filter: Element.getStyle(element,'filter').replace(/alpha\([^\)]*\)/gi,'') + + 'alpha(opacity='+value*100+')' }); + } +} + +Element.getInlineOpacity = function(element){ + return $(element).style.opacity || ''; +} + +Element.childrenWithClassName = function(element, className, findFirst) { + var classNameRegExp = new RegExp("(^|\\s)" + className + "(\\s|$)"); + var results = $A($(element).getElementsByTagName('*'))[findFirst ? 'detect' : 'select']( function(c) { + return (c.className && c.className.match(classNameRegExp)); + }); + if(!results) results = []; + return results; +} + +Element.forceRerendering = function(element) { + try { + element = $(element); + var n = document.createTextNode(' '); + element.appendChild(n); + element.removeChild(n); + } catch(e) { } +}; + +/*--------------------------------------------------------------------------*/ + +Array.prototype.call = function() { + var args = arguments; + this.each(function(f){ f.apply(this, args) }); +} + +/*--------------------------------------------------------------------------*/ + +var Effect = { + tagifyText: function(element) { + var tagifyStyle = 'position:relative'; + if(/MSIE/.test(navigator.userAgent)) tagifyStyle += ';zoom:1'; + element = $(element); + $A(element.childNodes).each( function(child) { + if(child.nodeType==3) { + child.nodeValue.toArray().each( function(character) { + element.insertBefore( + Builder.node('span',{style: tagifyStyle}, + character == ' ' ? String.fromCharCode(160) : character), + child); + }); + Element.remove(child); + } + }); + }, + multiple: function(element, effect) { + var elements; + if(((typeof element == 'object') || + (typeof element == 'function')) && + (element.length)) + elements = element; + else + elements = $(element).childNodes; + + var options = Object.extend({ + speed: 0.1, + delay: 0.0 + }, arguments[2] || {}); + var masterDelay = options.delay; + + $A(elements).each( function(element, index) { + new effect(element, Object.extend(options, { delay: index * options.speed + masterDelay })); + }); + }, + PAIRS: { + 'slide': ['SlideDown','SlideUp'], + 'blind': ['BlindDown','BlindUp'], + 'appear': ['Appear','Fade'] + }, + toggle: function(element, effect) { + element = $(element); + effect = (effect || 'appear').toLowerCase(); + var options = Object.extend({ + queue: { position:'end', scope:(element.id || 'global'), limit: 1 } + }, arguments[2] || {}); + Effect[element.visible() ? + Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options); + } +}; + +var Effect2 = Effect; // deprecated + +/* ------------- transitions ------------- */ + +Effect.Transitions = {} + +Effect.Transitions.linear = function(pos) { + return pos; +} +Effect.Transitions.sinoidal = function(pos) { + return (-Math.cos(pos*Math.PI)/2) + 0.5; +} +Effect.Transitions.reverse = function(pos) { + return 1-pos; +} +Effect.Transitions.flicker = function(pos) { + return ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random()/4; +} +Effect.Transitions.wobble = function(pos) { + return (-Math.cos(pos*Math.PI*(9*pos))/2) + 0.5; +} +Effect.Transitions.pulse = function(pos) { + return (Math.floor(pos*10) % 2 == 0 ? + (pos*10-Math.floor(pos*10)) : 1-(pos*10-Math.floor(pos*10))); +} +Effect.Transitions.none = function(pos) { + return 0; +} +Effect.Transitions.full = function(pos) { + return 1; +} + +/* ------------- core effects ------------- */ + +Effect.ScopedQueue = Class.create(); +Object.extend(Object.extend(Effect.ScopedQueue.prototype, Enumerable), { + initialize: function() { + this.effects = []; + this.interval = null; + }, + _each: function(iterator) { + this.effects._each(iterator); + }, + add: function(effect) { + var timestamp = new Date().getTime(); + + var position = (typeof effect.options.queue == 'string') ? + effect.options.queue : effect.options.queue.position; + + switch(position) { + case 'front': + // move unstarted effects after this effect + this.effects.findAll(function(e){ return e.state=='idle' }).each( function(e) { + e.startOn += effect.finishOn; + e.finishOn += effect.finishOn; + }); + break; + case 'end': + // start effect after last queued effect has finished + timestamp = this.effects.pluck('finishOn').max() || timestamp; + break; + } + + effect.startOn += timestamp; + effect.finishOn += timestamp; + + if(!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit)) + this.effects.push(effect); + + if(!this.interval) + this.interval = setInterval(this.loop.bind(this), 40); + }, + remove: function(effect) { + this.effects = this.effects.reject(function(e) { return e==effect }); + if(this.effects.length == 0) { + clearInterval(this.interval); + this.interval = null; + } + }, + loop: function() { + var timePos = new Date().getTime(); + this.effects.invoke('loop', timePos); + } +}); + +Effect.Queues = { + instances: $H(), + get: function(queueName) { + if(typeof queueName != 'string') return queueName; + + if(!this.instances[queueName]) + this.instances[queueName] = new Effect.ScopedQueue(); + + return this.instances[queueName]; + } +} +Effect.Queue = Effect.Queues.get('global'); + +Effect.DefaultOptions = { + transition: Effect.Transitions.sinoidal, + duration: 1.0, // seconds + fps: 25.0, // max. 25fps due to Effect.Queue implementation + sync: false, // true for combining + from: 0.0, + to: 1.0, + delay: 0.0, + queue: 'parallel' +} + +Effect.Base = function() {}; +Effect.Base.prototype = { + position: null, + start: function(options) { + this.options = Object.extend(Object.extend({},Effect.DefaultOptions), options || {}); + this.currentFrame = 0; + this.state = 'idle'; + this.startOn = this.options.delay*1000; + this.finishOn = this.startOn + (this.options.duration*1000); + this.event('beforeStart'); + if(!this.options.sync) + Effect.Queues.get(typeof this.options.queue == 'string' ? + 'global' : this.options.queue.scope).add(this); + }, + loop: function(timePos) { + if(timePos >= this.startOn) { + if(timePos >= this.finishOn) { + this.render(1.0); + this.cancel(); + this.event('beforeFinish'); + if(this.finish) this.finish(); + this.event('afterFinish'); + return; + } + var pos = (timePos - this.startOn) / (this.finishOn - this.startOn); + var frame = Math.round(pos * this.options.fps * this.options.duration); + if(frame > this.currentFrame) { + this.render(pos); + this.currentFrame = frame; + } + } + }, + render: function(pos) { + if(this.state == 'idle') { + this.state = 'running'; + this.event('beforeSetup'); + if(this.setup) this.setup(); + this.event('afterSetup'); + } + if(this.state == 'running') { + if(this.options.transition) pos = this.options.transition(pos); + pos *= (this.options.to-this.options.from); + pos += this.options.from; + this.position = pos; + this.event('beforeUpdate'); + if(this.update) this.update(pos); + this.event('afterUpdate'); + } + }, + cancel: function() { + if(!this.options.sync) + Effect.Queues.get(typeof this.options.queue == 'string' ? + 'global' : this.options.queue.scope).remove(this); + this.state = 'finished'; + }, + event: function(eventName) { + if(this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this); + if(this.options[eventName]) this.options[eventName](this); + }, + inspect: function() { + return '#'; + } +} + +Effect.Parallel = Class.create(); +Object.extend(Object.extend(Effect.Parallel.prototype, Effect.Base.prototype), { + initialize: function(effects) { + this.effects = effects || []; + this.start(arguments[1]); + }, + update: function(position) { + this.effects.invoke('render', position); + }, + finish: function(position) { + this.effects.each( function(effect) { + effect.render(1.0); + effect.cancel(); + effect.event('beforeFinish'); + if(effect.finish) effect.finish(position); + effect.event('afterFinish'); + }); + } +}); + +Effect.Opacity = Class.create(); +Object.extend(Object.extend(Effect.Opacity.prototype, Effect.Base.prototype), { + initialize: function(element) { + this.element = $(element); + // make this work on IE on elements without 'layout' + if(/MSIE/.test(navigator.userAgent) && (!this.element.hasLayout)) + this.element.setStyle({zoom: 1}); + var options = Object.extend({ + from: this.element.getOpacity() || 0.0, + to: 1.0 + }, arguments[1] || {}); + this.start(options); + }, + update: function(position) { + this.element.setOpacity(position); + } +}); + +Effect.Move = Class.create(); +Object.extend(Object.extend(Effect.Move.prototype, Effect.Base.prototype), { + initialize: function(element) { + this.element = $(element); + var options = Object.extend({ + x: 0, + y: 0, + mode: 'relative' + }, arguments[1] || {}); + this.start(options); + }, + setup: function() { + // Bug in Opera: Opera returns the "real" position of a static element or + // relative element that does not have top/left explicitly set. + // ==> Always set top and left for position relative elements in your stylesheets + // (to 0 if you do not need them) + this.element.makePositioned(); + this.originalLeft = parseFloat(this.element.getStyle('left') || '0'); + this.originalTop = parseFloat(this.element.getStyle('top') || '0'); + if(this.options.mode == 'absolute') { + // absolute movement, so we need to calc deltaX and deltaY + this.options.x = this.options.x - this.originalLeft; + this.options.y = this.options.y - this.originalTop; + } + }, + update: function(position) { + this.element.setStyle({ + left: this.options.x * position + this.originalLeft + 'px', + top: this.options.y * position + this.originalTop + 'px' + }); + } +}); + +// for backwards compatibility +Effect.MoveBy = function(element, toTop, toLeft) { + return new Effect.Move(element, + Object.extend({ x: toLeft, y: toTop }, arguments[3] || {})); +}; + +Effect.Scale = Class.create(); +Object.extend(Object.extend(Effect.Scale.prototype, Effect.Base.prototype), { + initialize: function(element, percent) { + this.element = $(element) + var options = Object.extend({ + scaleX: true, + scaleY: true, + scaleContent: true, + scaleFromCenter: false, + scaleMode: 'box', // 'box' or 'contents' or {} with provided values + scaleFrom: 100.0, + scaleTo: percent + }, arguments[2] || {}); + this.start(options); + }, + setup: function() { + this.restoreAfterFinish = this.options.restoreAfterFinish || false; + this.elementPositioning = this.element.getStyle('position'); + + this.originalStyle = {}; + ['top','left','width','height','fontSize'].each( function(k) { + this.originalStyle[k] = this.element.style[k]; + }.bind(this)); + + this.originalTop = this.element.offsetTop; + this.originalLeft = this.element.offsetLeft; + + var fontSize = this.element.getStyle('font-size') || '100%'; + ['em','px','%'].each( function(fontSizeType) { + if(fontSize.indexOf(fontSizeType)>0) { + this.fontSize = parseFloat(fontSize); + this.fontSizeType = fontSizeType; + } + }.bind(this)); + + this.factor = (this.options.scaleTo - this.options.scaleFrom)/100; + + this.dims = null; + if(this.options.scaleMode=='box') + this.dims = [this.element.offsetHeight, this.element.offsetWidth]; + if(/^content/.test(this.options.scaleMode)) + this.dims = [this.element.scrollHeight, this.element.scrollWidth]; + if(!this.dims) + this.dims = [this.options.scaleMode.originalHeight, + this.options.scaleMode.originalWidth]; + }, + update: function(position) { + var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position); + if(this.options.scaleContent && this.fontSize) + this.element.setStyle({fontSize: this.fontSize * currentScale + this.fontSizeType }); + this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale); + }, + finish: function(position) { + if (this.restoreAfterFinish) this.element.setStyle(this.originalStyle); + }, + setDimensions: function(height, width) { + var d = {}; + if(this.options.scaleX) d.width = width + 'px'; + if(this.options.scaleY) d.height = height + 'px'; + if(this.options.scaleFromCenter) { + var topd = (height - this.dims[0])/2; + var leftd = (width - this.dims[1])/2; + if(this.elementPositioning == 'absolute') { + if(this.options.scaleY) d.top = this.originalTop-topd + 'px'; + if(this.options.scaleX) d.left = this.originalLeft-leftd + 'px'; + } else { + if(this.options.scaleY) d.top = -topd + 'px'; + if(this.options.scaleX) d.left = -leftd + 'px'; + } + } + this.element.setStyle(d); + } +}); + +Effect.Highlight = Class.create(); +Object.extend(Object.extend(Effect.Highlight.prototype, Effect.Base.prototype), { + initialize: function(element) { + this.element = $(element); + var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || {}); + this.start(options); + }, + setup: function() { + // Prevent executing on elements not in the layout flow + if(this.element.getStyle('display')=='none') { this.cancel(); return; } + // Disable background image during the effect + this.oldStyle = { + backgroundImage: this.element.getStyle('background-image') }; + this.element.setStyle({backgroundImage: 'none'}); + if(!this.options.endcolor) + this.options.endcolor = this.element.getStyle('background-color').parseColor('#ffffff'); + if(!this.options.restorecolor) + this.options.restorecolor = this.element.getStyle('background-color'); + // init color calculations + this._base = $R(0,2).map(function(i){ return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16) }.bind(this)); + this._delta = $R(0,2).map(function(i){ return parseInt(this.options.endcolor.slice(i*2+1,i*2+3),16)-this._base[i] }.bind(this)); + }, + update: function(position) { + this.element.setStyle({backgroundColor: $R(0,2).inject('#',function(m,v,i){ + return m+(Math.round(this._base[i]+(this._delta[i]*position)).toColorPart()); }.bind(this)) }); + }, + finish: function() { + this.element.setStyle(Object.extend(this.oldStyle, { + backgroundColor: this.options.restorecolor + })); + } +}); + +Effect.ScrollTo = Class.create(); +Object.extend(Object.extend(Effect.ScrollTo.prototype, Effect.Base.prototype), { + initialize: function(element) { + this.element = $(element); + this.start(arguments[1] || {}); + }, + setup: function() { + Position.prepare(); + var offsets = Position.cumulativeOffset(this.element); + if(this.options.offset) offsets[1] += this.options.offset; + var max = window.innerHeight ? + window.height - window.innerHeight : + document.body.scrollHeight - + (document.documentElement.clientHeight ? + document.documentElement.clientHeight : document.body.clientHeight); + this.scrollStart = Position.deltaY; + this.delta = (offsets[1] > max ? max : offsets[1]) - this.scrollStart; + }, + update: function(position) { + Position.prepare(); + window.scrollTo(Position.deltaX, + this.scrollStart + (position*this.delta)); + } +}); + +/* ------------- combination effects ------------- */ + +Effect.Fade = function(element) { + element = $(element); + var oldOpacity = element.getInlineOpacity(); + var options = Object.extend({ + from: element.getOpacity() || 1.0, + to: 0.0, + afterFinishInternal: function(effect) { + if(effect.options.to!=0) return; + effect.element.hide(); + effect.element.setStyle({opacity: oldOpacity}); + }}, arguments[1] || {}); + return new Effect.Opacity(element,options); +} + +Effect.Appear = function(element) { + element = $(element); + var options = Object.extend({ + from: (element.getStyle('display') == 'none' ? 0.0 : element.getOpacity() || 0.0), + to: 1.0, + // force Safari to render floated elements properly + afterFinishInternal: function(effect) { + effect.element.forceRerendering(); + }, + beforeSetup: function(effect) { + effect.element.setOpacity(effect.options.from); + effect.element.show(); + }}, arguments[1] || {}); + return new Effect.Opacity(element,options); +} + +Effect.Puff = function(element) { + element = $(element); + var oldStyle = { opacity: element.getInlineOpacity(), position: element.getStyle('position') }; + return new Effect.Parallel( + [ new Effect.Scale(element, 200, + { sync: true, scaleFromCenter: true, scaleContent: true, restoreAfterFinish: true }), + new Effect.Opacity(element, { sync: true, to: 0.0 } ) ], + Object.extend({ duration: 1.0, + beforeSetupInternal: function(effect) { + effect.effects[0].element.setStyle({position: 'absolute'}); }, + afterFinishInternal: function(effect) { + effect.effects[0].element.hide(); + effect.effects[0].element.setStyle(oldStyle); } + }, arguments[1] || {}) + ); +} + +Effect.BlindUp = function(element) { + element = $(element); + element.makeClipping(); + return new Effect.Scale(element, 0, + Object.extend({ scaleContent: false, + scaleX: false, + restoreAfterFinish: true, + afterFinishInternal: function(effect) { + effect.element.hide(); + effect.element.undoClipping(); + } + }, arguments[1] || {}) + ); +} + +Effect.BlindDown = function(element) { + element = $(element); + var elementDimensions = element.getDimensions(); + return new Effect.Scale(element, 100, + Object.extend({ scaleContent: false, + scaleX: false, + scaleFrom: 0, + scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, + restoreAfterFinish: true, + afterSetup: function(effect) { + effect.element.makeClipping(); + effect.element.setStyle({height: '0px'}); + effect.element.show(); + }, + afterFinishInternal: function(effect) { + effect.element.undoClipping(); + } + }, arguments[1] || {}) + ); +} + +Effect.SwitchOff = function(element) { + element = $(element); + var oldOpacity = element.getInlineOpacity(); + return new Effect.Appear(element, { + duration: 0.4, + from: 0, + transition: Effect.Transitions.flicker, + afterFinishInternal: function(effect) { + new Effect.Scale(effect.element, 1, { + duration: 0.3, scaleFromCenter: true, + scaleX: false, scaleContent: false, restoreAfterFinish: true, + beforeSetup: function(effect) { + effect.element.makePositioned(); + effect.element.makeClipping(); + }, + afterFinishInternal: function(effect) { + effect.element.hide(); + effect.element.undoClipping(); + effect.element.undoPositioned(); + effect.element.setStyle({opacity: oldOpacity}); + } + }) + } + }); +} + +Effect.DropOut = function(element) { + element = $(element); + var oldStyle = { + top: element.getStyle('top'), + left: element.getStyle('left'), + opacity: element.getInlineOpacity() }; + return new Effect.Parallel( + [ new Effect.Move(element, {x: 0, y: 100, sync: true }), + new Effect.Opacity(element, { sync: true, to: 0.0 }) ], + Object.extend( + { duration: 0.5, + beforeSetup: function(effect) { + effect.effects[0].element.makePositioned(); + }, + afterFinishInternal: function(effect) { + effect.effects[0].element.hide(); + effect.effects[0].element.undoPositioned(); + effect.effects[0].element.setStyle(oldStyle); + } + }, arguments[1] || {})); +} + +Effect.Shake = function(element) { + element = $(element); + var oldStyle = { + top: element.getStyle('top'), + left: element.getStyle('left') }; + return new Effect.Move(element, + { x: 20, y: 0, duration: 0.05, afterFinishInternal: function(effect) { + new Effect.Move(effect.element, + { x: -40, y: 0, duration: 0.1, afterFinishInternal: function(effect) { + new Effect.Move(effect.element, + { x: 40, y: 0, duration: 0.1, afterFinishInternal: function(effect) { + new Effect.Move(effect.element, + { x: -40, y: 0, duration: 0.1, afterFinishInternal: function(effect) { + new Effect.Move(effect.element, + { x: 40, y: 0, duration: 0.1, afterFinishInternal: function(effect) { + new Effect.Move(effect.element, + { x: -20, y: 0, duration: 0.05, afterFinishInternal: function(effect) { + effect.element.undoPositioned(); + effect.element.setStyle(oldStyle); + }}) }}) }}) }}) }}) }}); +} + +Effect.SlideDown = function(element) { + element = $(element); + element.cleanWhitespace(); + // SlideDown need to have the content of the element wrapped in a container element with fixed height! + var oldInnerBottom = $(element.firstChild).getStyle('bottom'); + var elementDimensions = element.getDimensions(); + return new Effect.Scale(element, 100, Object.extend({ + scaleContent: false, + scaleX: false, + scaleFrom: window.opera ? 0 : 1, + scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, + restoreAfterFinish: true, + afterSetup: function(effect) { + effect.element.makePositioned(); + effect.element.firstChild.makePositioned(); + if(window.opera) effect.element.setStyle({top: ''}); + effect.element.makeClipping(); + effect.element.setStyle({height: '0px'}); + effect.element.show(); }, + afterUpdateInternal: function(effect) { + effect.element.firstChild.setStyle({bottom: + (effect.dims[0] - effect.element.clientHeight) + 'px' }); + }, + afterFinishInternal: function(effect) { + effect.element.undoClipping(); + // IE will crash if child is undoPositioned first + if(/MSIE/.test(navigator.userAgent)){ + effect.element.undoPositioned(); + effect.element.firstChild.undoPositioned(); + }else{ + effect.element.firstChild.undoPositioned(); + effect.element.undoPositioned(); + } + effect.element.firstChild.setStyle({bottom: oldInnerBottom}); } + }, arguments[1] || {}) + ); +} + +Effect.SlideUp = function(element) { + element = $(element); + element.cleanWhitespace(); + var oldInnerBottom = $(element.firstChild).getStyle('bottom'); + return new Effect.Scale(element, window.opera ? 0 : 1, + Object.extend({ scaleContent: false, + scaleX: false, + scaleMode: 'box', + scaleFrom: 100, + restoreAfterFinish: true, + beforeStartInternal: function(effect) { + effect.element.makePositioned(); + effect.element.firstChild.makePositioned(); + if(window.opera) effect.element.setStyle({top: ''}); + effect.element.makeClipping(); + effect.element.show(); }, + afterUpdateInternal: function(effect) { + effect.element.firstChild.setStyle({bottom: + (effect.dims[0] - effect.element.clientHeight) + 'px' }); }, + afterFinishInternal: function(effect) { + effect.element.hide(); + effect.element.undoClipping(); + effect.element.firstChild.undoPositioned(); + effect.element.undoPositioned(); + effect.element.setStyle({bottom: oldInnerBottom}); } + }, arguments[1] || {}) + ); +} + +// Bug in opera makes the TD containing this element expand for a instance after finish +Effect.Squish = function(element) { + return new Effect.Scale(element, window.opera ? 1 : 0, + { restoreAfterFinish: true, + beforeSetup: function(effect) { + effect.element.makeClipping(effect.element); }, + afterFinishInternal: function(effect) { + effect.element.hide(effect.element); + effect.element.undoClipping(effect.element); } + }); +} + +Effect.Grow = function(element) { + element = $(element); + var options = Object.extend({ + direction: 'center', + moveTransition: Effect.Transitions.sinoidal, + scaleTransition: Effect.Transitions.sinoidal, + opacityTransition: Effect.Transitions.full + }, arguments[1] || {}); + var oldStyle = { + top: element.style.top, + left: element.style.left, + height: element.style.height, + width: element.style.width, + opacity: element.getInlineOpacity() }; + + var dims = element.getDimensions(); + var initialMoveX, initialMoveY; + var moveX, moveY; + + switch (options.direction) { + case 'top-left': + initialMoveX = initialMoveY = moveX = moveY = 0; + break; + case 'top-right': + initialMoveX = dims.width; + initialMoveY = moveY = 0; + moveX = -dims.width; + break; + case 'bottom-left': + initialMoveX = moveX = 0; + initialMoveY = dims.height; + moveY = -dims.height; + break; + case 'bottom-right': + initialMoveX = dims.width; + initialMoveY = dims.height; + moveX = -dims.width; + moveY = -dims.height; + break; + case 'center': + initialMoveX = dims.width / 2; + initialMoveY = dims.height / 2; + moveX = -dims.width / 2; + moveY = -dims.height / 2; + break; + } + + return new Effect.Move(element, { + x: initialMoveX, + y: initialMoveY, + duration: 0.01, + beforeSetup: function(effect) { + effect.element.hide(); + effect.element.makeClipping(); + effect.element.makePositioned(); + }, + afterFinishInternal: function(effect) { + new Effect.Parallel( + [ new Effect.Opacity(effect.element, { sync: true, to: 1.0, from: 0.0, transition: options.opacityTransition }), + new Effect.Move(effect.element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }), + new Effect.Scale(effect.element, 100, { + scaleMode: { originalHeight: dims.height, originalWidth: dims.width }, + sync: true, scaleFrom: window.opera ? 1 : 0, transition: options.scaleTransition, restoreAfterFinish: true}) + ], Object.extend({ + beforeSetup: function(effect) { + effect.effects[0].element.setStyle({height: '0px'}); + effect.effects[0].element.show(); + }, + afterFinishInternal: function(effect) { + effect.effects[0].element.undoClipping(); + effect.effects[0].element.undoPositioned(); + effect.effects[0].element.setStyle(oldStyle); + } + }, options) + ) + } + }); +} + +Effect.Shrink = function(element) { + element = $(element); + var options = Object.extend({ + direction: 'center', + moveTransition: Effect.Transitions.sinoidal, + scaleTransition: Effect.Transitions.sinoidal, + opacityTransition: Effect.Transitions.none + }, arguments[1] || {}); + var oldStyle = { + top: element.style.top, + left: element.style.left, + height: element.style.height, + width: element.style.width, + opacity: element.getInlineOpacity() }; + + var dims = element.getDimensions(); + var moveX, moveY; + + switch (options.direction) { + case 'top-left': + moveX = moveY = 0; + break; + case 'top-right': + moveX = dims.width; + moveY = 0; + break; + case 'bottom-left': + moveX = 0; + moveY = dims.height; + break; + case 'bottom-right': + moveX = dims.width; + moveY = dims.height; + break; + case 'center': + moveX = dims.width / 2; + moveY = dims.height / 2; + break; + } + + return new Effect.Parallel( + [ new Effect.Opacity(element, { sync: true, to: 0.0, from: 1.0, transition: options.opacityTransition }), + new Effect.Scale(element, window.opera ? 1 : 0, { sync: true, transition: options.scaleTransition, restoreAfterFinish: true}), + new Effect.Move(element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }) + ], Object.extend({ + beforeStartInternal: function(effect) { + effect.effects[0].element.makePositioned(); + effect.effects[0].element.makeClipping(); }, + afterFinishInternal: function(effect) { + effect.effects[0].element.hide(); + effect.effects[0].element.undoClipping(); + effect.effects[0].element.undoPositioned(); + effect.effects[0].element.setStyle(oldStyle); } + }, options) + ); +} + +Effect.Pulsate = function(element) { + element = $(element); + var options = arguments[1] || {}; + var oldOpacity = element.getInlineOpacity(); + var transition = options.transition || Effect.Transitions.sinoidal; + var reverser = function(pos){ return transition(1-Effect.Transitions.pulse(pos)) }; + reverser.bind(transition); + return new Effect.Opacity(element, + Object.extend(Object.extend({ duration: 3.0, from: 0, + afterFinishInternal: function(effect) { effect.element.setStyle({opacity: oldOpacity}); } + }, options), {transition: reverser})); +} + +Effect.Fold = function(element) { + element = $(element); + var oldStyle = { + top: element.style.top, + left: element.style.left, + width: element.style.width, + height: element.style.height }; + Element.makeClipping(element); + return new Effect.Scale(element, 5, Object.extend({ + scaleContent: false, + scaleX: false, + afterFinishInternal: function(effect) { + new Effect.Scale(element, 1, { + scaleContent: false, + scaleY: false, + afterFinishInternal: function(effect) { + effect.element.hide(); + effect.element.undoClipping(); + effect.element.setStyle(oldStyle); + } }); + }}, arguments[1] || {})); +}; + +['setOpacity','getOpacity','getInlineOpacity','forceRerendering','setContentZoom', + 'collectTextNodes','collectTextNodesIgnoreClass','childrenWithClassName'].each( + function(f) { Element.Methods[f] = Element[f]; } +); + +Element.Methods.visualEffect = function(element, effect, options) { + s = effect.gsub(/_/, '-').camelize(); + effect_class = s.charAt(0).toUpperCase() + s.substring(1); + new Effect[effect_class](element, options); + return $(element); +}; + +Element.addMethods(); \ No newline at end of file Added: kukit/kukit.js/trunk/3rd_party/prototype.js ============================================================================== --- (empty file) +++ kukit/kukit.js/trunk/3rd_party/prototype.js Tue Sep 5 12:40:27 2006 @@ -0,0 +1,2006 @@ +/* Prototype JavaScript framework, version 1.5.0_rc0 + * (c) 2005 Sam Stephenson + * + * Prototype is freely distributable under the terms of an MIT-style license. + * For details, see the Prototype web site: http://prototype.conio.net/ + * +/*--------------------------------------------------------------------------*/ + +var Prototype = { + Version: '1.5.0_rc0', + ScriptFragment: '(?:)((\n|\r|.)*?)(?:<\/script>)', + + emptyFunction: function() {}, + K: function(x) {return x} +} + +var Class = { + create: function() { + return function() { + this.initialize.apply(this, arguments); + } + } +} + +var Abstract = new Object(); + +Object.extend = function(destination, source) { + for (var 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; + } + } + } +} +Object.extend(String.prototype, { + gsub: function(pattern, replacement) { + var result = '', source = this, match; + replacement = arguments.callee.prepareReplacement(replacement); + + while (source.length > 0) { + if (match = source.match(pattern)) { + result += source.slice(0, match.index); + result += (replacement(match) || '').toString(); + source = source.slice(match.index + match[0].length); + } else { + result += source, source = ''; + } + } + return result; + }, + + sub: function(pattern, replacement, count) { + replacement = this.gsub.prepareReplacement(replacement); + count = count === undefined ? 1 : count; + + return this.gsub(pattern, function(match) { + if (--count < 0) return match[0]; + return replacement(match); + }); + }, + + scan: function(pattern, iterator) { + this.gsub(pattern, iterator); + return this; + }, + + truncate: function(length, truncation) { + length = length || 30; + truncation = truncation === undefined ? '...' : truncation; + return this.length > length ? + this.slice(0, length - truncation.length) + truncation : this; + }, + + strip: function() { + return this.replace(/^\s+/, '').replace(/\s+$/, ''); + }, + + 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(function(script) { return eval(script) }); + }, + + 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(/\\/g, '\\\\').replace(/'/g, '\\\'') + "'"; + } +}); + +String.prototype.gsub.prepareReplacement = function(replacement) { + if (typeof replacement == 'function') return replacement; + var template = new Template(replacement); + return function(match) { return template.evaluate(match) }; +} + +String.prototype.parseQuery = String.prototype.toQueryParams; + +var Template = Class.create(); +Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/; +Template.prototype = { + initialize: function(template, pattern) { + this.template = template.toString(); + this.pattern = pattern || Template.Pattern; + }, + + evaluate: function(object) { + return this.template.gsub(this.pattern, function(match) { + var before = match[1]; + if (before == '\\') return match[2]; + return before + (object[match[3]] || '').toString(); + }); + } +} + +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 (result == undefined || value >= result) + result = value; + }); + return result; + }, + + min: function(iterator) { + var result; + this.each(function(value, index) { + value = (iterator || Prototype.K)(value, index); + if (result == undefined || value < result) + 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) { + return iterator(collections.pluck(index)); + }); + }, + + inspect: function() { + return '#'; + } +} + +Object.extend(Enumerable, { + map: Enumerable.collect, + find: Enumerable.detect, + select: Enumerable.findAll, + member: Enumerable.include, + entries: Enumerable.toArray +}); +var $A = Array.from = function(iterable) { + if (!iterable) return []; + if (iterable.toArray) { + return iterable.toArray(); + } else { + var results = []; + for (var i = 0; i < iterable.length; i++) + results.push(iterable[i]); + return results; + } +} + +Object.extend(Array.prototype, Enumerable); + +if (!Array.prototype._reverse) + 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 && 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(); + }, + + inspect: function() { + return '[' + this.map(Object.inspect).join(', ') + ']'; + } +}); +var Hash = { + _each: function(iterator) { + for (var key in this) { + var value = this[key]; + if (typeof value == 'function') continue; + + var pair = [key, value]; + pair.key = key; + pair.value = value; + iterator(pair); + } + }, + + keys: function() { + return this.pluck('key'); + }, + + values: function() { + return this.pluck('value'); + }, + + merge: function(hash) { + return $H(hash).inject($H(this), function(mergedHash, pair) { + mergedHash[pair.key] = pair.value; + return mergedHash; + }); + }, + + toQueryString: function() { + return this.map(function(pair) { + return pair.map(encodeURIComponent).join('='); + }).join('&'); + }, + + inspect: function() { + return '#'; + } +} + +function $H(object) { + var hash = Object.extend({}, object || {}); + Object.extend(hash, Enumerable); + Object.extend(hash, Hash); + return hash; +} +ObjectRange = Class.create(); +Object.extend(ObjectRange.prototype, Enumerable); +Object.extend(ObjectRange.prototype, { + initialize: function(start, end, exclusive) { + this.start = start; + this.end = end; + this.exclusive = exclusive; + }, + + _each: function(iterator) { + var value = this.start; + do { + iterator(value); + value = value.succ(); + } while (this.include(value)); + }, + + include: function(value) { + if (value < this.start) + return false; + if (this.exclusive) + return value < this.end; + return value <= this.end; + } +}); + +var $R = function(start, end, exclusive) { + return new ObjectRange(start, end, exclusive); +} + +var Ajax = { + getTransport: function() { + return Try.these( + function() {return new XMLHttpRequest()}, + function() {return new ActiveXObject('Msxml2.XMLHTTP')}, + function() {return new ActiveXObject('Microsoft.XMLHTTP')} + ) || 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, + contentType: 'application/x-www-form-urlencoded', + 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, + 'Accept', 'text/javascript, text/html, application/xml, text/xml, */*']; + + if (this.options.method == 'post') { + requestHeaders.push('Content-type', this.options.contentType); + + /* 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); + } +}); +function $() { + var results = [], element; + for (var i = 0; i < arguments.length; i++) { + element = arguments[i]; + if (typeof element == 'string') + element = document.getElementById(element); + results.push(Element.extend(element)); + } + return results.length < 2 ? results[0] : results; +} + +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(Element.extend(child)); + return elements; + }); +} + +/*--------------------------------------------------------------------------*/ + +if (!window.Element) + var Element = new Object(); + +Element.extend = function(element) { + if (!element) return; + if (_nativeExtensions) return element; + + if (!element._extended && element.tagName && element != window) { + var methods = Element.Methods, cache = Element.extend.cache; + for (property in methods) { + var value = methods[property]; + if (typeof value == 'function') + element[property] = cache.findOrStore(value); + } + } + + element._extended = true; + return element; +} + +Element.extend.cache = { + findOrStore: function(value) { + return this[value] = this[value] || function() { + return value.apply(null, [this].concat($A(arguments))); + } + } +} + +Element.Methods = { + 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); + }, + + replace: function(element, html) { + element = $(element); + if (element.outerHTML) { + element.outerHTML = html.stripScripts(); + } else { + var range = element.ownerDocument.createRange(); + range.selectNodeContents(element); + element.parentNode.replaceChild( + range.createContextualFragment(html.stripScripts()), element); + } + 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*$/); + }, + + childOf: function(element, ancestor) { + element = $(element), ancestor = $(ancestor); + while (element = element.parentNode) + if (element == ancestor) return true; + return false; + }, + + 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 (var 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; + } +} + +Object.extend(Element, Element.Methods); + +var _nativeExtensions = false; + +if(!HTMLElement && /Konqueror|Safari|KHTML/.test(navigator.userAgent)) { + var HTMLElement = {} + HTMLElement.prototype = document.createElement('div').__proto__; +} + +Element.addMethods = function(methods) { + Object.extend(Element.Methods, methods || {}); + + if(typeof HTMLElement != 'undefined') { + var methods = Element.Methods, cache = Element.extend.cache; + for (property in methods) { + var value = methods[property]; + if (typeof value == 'function') + HTMLElement.prototype[property] = cache.findOrStore(value); + } + _nativeExtensions = true; + } +} + +Element.addMethods(); + +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) { + var tagName = this.element.tagName.toLowerCase(); + if (tagName == 'tbody' || tagName == 'tr') { + this.insertContent(this.contentFromAnonymousTable()); + } else { + throw e; + } + } + } else { + this.range = this.element.ownerDocument.createRange(); + if (this.initializeRange) this.initializeRange(); + this.insertContent([this.range.createContextualFragment(this.content)]); + } + + setTimeout(function() {content.evalScripts()}, 10); + }, + + contentFromAnonymousTable: function() { + var div = document.createElement('div'); + div.innerHTML = '' + this.content + '
'; + return $A(div.childNodes[0].childNodes[0].childNodes); + } +} + +var Insertion = new Object(); + +Insertion.Before = Class.create(); +Insertion.Before.prototype = Object.extend(new Abstract.Insertion('beforeBegin'), { + initializeRange: function() { + this.range.setStartBefore(this.element); + }, + + insertContent: function(fragments) { + fragments.each((function(fragment) { + this.element.parentNode.insertBefore(fragment, this.element); + }).bind(this)); + } +}); + +Insertion.Top = Class.create(); +Insertion.Top.prototype = Object.extend(new Abstract.Insertion('afterBegin'), { + initializeRange: function() { + this.range.selectNodeContents(this.element); + this.range.collapse(true); + }, + + insertContent: function(fragments) { + fragments.reverse(false).each((function(fragment) { + this.element.insertBefore(fragment, this.element.firstChild); + }).bind(this)); + } +}); + +Insertion.Bottom = Class.create(); +Insertion.Bottom.prototype = Object.extend(new Abstract.Insertion('beforeEnd'), { + initializeRange: function() { + this.range.selectNodeContents(this.element); + this.range.collapse(this.element); + }, + + insertContent: function(fragments) { + fragments.each((function(fragment) { + this.element.appendChild(fragment); + }).bind(this)); + } +}); + +Insertion.After = Class.create(); +Insertion.After.prototype = Object.extend(new Abstract.Insertion('afterEnd'), { + initializeRange: function() { + this.range.setStartAfter(this.element); + }, + + insertContent: function(fragments) { + fragments.each((function(fragment) { + this.element.parentNode.insertBefore(fragment, + this.element.nextSibling); + }).bind(this)); + } +}); + +/*--------------------------------------------------------------------------*/ + +Element.ClassNames = Class.create(); +Element.ClassNames.prototype = { + initialize: function(element) { + this.element = $(element); + }, + + _each: function(iterator) { + this.element.className.split(/\s+/).select(function(name) { + return name.length > 0; + })._each(iterator); + }, + + set: function(className) { + this.element.className = className; + }, + + add: function(classNameToAdd) { + if (this.include(classNameToAdd)) return; + this.set(this.toArray().concat(classNameToAdd).join(' ')); + }, + + remove: function(classNameToRemove) { + if (!this.include(classNameToRemove)) return; + this.set(this.select(function(className) { + return className != classNameToRemove; + }).join(' ')); + }, + + toString: function() { + return this.toArray().join(' '); + } +} + +Object.extend(Element.ClassNames.prototype, Enumerable); +var Selector = Class.create(); +Selector.prototype = { + initialize: function(expression) { + this.params = {classNames: []}; + this.expression = expression.toString().strip(); + this.parseExpression(); + this.compileMatcher(); + }, + + parseExpression: function() { + function abort(message) { throw 'Parse error in selector: ' + message; } + + if (this.expression == '') abort('empty expression'); + + var params = this.params, expr = this.expression, match, modifier, clause, rest; + while (match = expr.match(/^(.*)\[([a-z0-9_:-]+?)(?:([~\|!]?=)(?:"([^"]*)"|([^\]\s]*)))?\]$/i)) { + params.attributes = params.attributes || []; + params.attributes.push({name: match[2], operator: match[3], value: match[4] || match[5] || ''}); + expr = match[1]; + } + + if (expr == '*') return this.params.wildcard = true; + + while (match = expr.match(/^([^a-z0-9_-])?([a-z0-9_-]+)(.*)/i)) { + modifier = match[1], clause = match[2], rest = match[3]; + switch (modifier) { + case '#': params.id = clause; break; + case '.': params.classNames.push(clause); break; + case '': + case undefined: params.tagName = clause.toUpperCase(); break; + default: abort(expr.inspect()); + } + expr = rest; + } + + if (expr.length > 0) abort(expr.inspect()); + }, + + buildMatchExpression: function() { + var params = this.params, conditions = [], clause; + + if (params.wildcard) + conditions.push('true'); + if (clause = params.id) + conditions.push('element.id == ' + clause.inspect()); + if (clause = params.tagName) + conditions.push('element.tagName.toUpperCase() == ' + clause.inspect()); + if ((clause = params.classNames).length > 0) + for (var i = 0; i < clause.length; i++) + conditions.push('Element.hasClassName(element, ' + clause[i].inspect() + ')'); + if (clause = params.attributes) { + clause.each(function(attribute) { + var value = 'element.getAttribute(' + attribute.name.inspect() + ')'; + var splitValueBy = function(delimiter) { + return value + ' && ' + value + '.split(' + delimiter.inspect() + ')'; + } + + switch (attribute.operator) { + case '=': conditions.push(value + ' == ' + attribute.value.inspect()); break; + case '~=': conditions.push(splitValueBy(' ') + '.include(' + attribute.value.inspect() + ')'); break; + case '|=': conditions.push( + splitValueBy('-') + '.first().toUpperCase() == ' + attribute.value.toUpperCase().inspect() + ); break; + case '!=': conditions.push(value + ' != ' + attribute.value.inspect()); break; + case '': + case undefined: conditions.push(value + ' != null'); break; + default: throw 'Unknown operator ' + attribute.operator + ' in selector'; + } + }); + } + + return conditions.join(' && '); + }, + + compileMatcher: function() { + this.match = new Function('element', 'if (!element.tagName) return false; \ + return ' + this.buildMatchExpression()); + }, + + findElements: function(scope) { + var element; + + if (element = $(this.params.id)) + if (this.match(element)) + if (!scope || Element.childOf(element, scope)) + return [element]; + + scope = (scope || document).getElementsByTagName(this.params.tagName || '*'); + + var results = []; + for (var i = 0; i < scope.length; i++) + if (this.match(element = scope[i])) + results.push(Element.extend(element)); + + return results; + }, + + toString: function() { + return this.expression; + } +} + +function $$() { + return $A(arguments).map(function(expression) { + return expression.strip().split(/\s+/).inject([null], function(results, expr) { + var selector = new Selector(expr); + return results.map(selector.findElements.bind(selector)).flatten(); + }); + }).flatten(); +} +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 (var 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 || opt.text; + } + return [element.name, value]; + }, + + selectMany: function(element) { + var value = []; + for (var i = 0; i < element.length; i++) { + var opt = element.options[i]; + if (opt.selected) + value.push(opt.value || opt.text); + } + 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 */ +if (navigator.appVersion.match(/\bMSIE\b/)) + 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 Modified: kukit/kukit.js/trunk/kukit/kssparser.js ============================================================================== --- kukit/kukit.js/trunk/kukit/kssparser.js (original) +++ kukit/kukit.js/trunk/kukit/kssparser.js Tue Sep 5 12:40:27 2006 @@ -128,9 +128,10 @@ // default-: // default-error: // + var KSS_PARAM_SYNTAX_ERROR = 'kss param key must be like xxx-yyy or evt-xxx-yyy"'; var splitkey = key.split('-'); if (splitkey.length < 2 || splitkey.length > 3) { - this.emitError('kss param key must be like xxx-yyy or evt-xxx-yyy"' + key + '"'); + this.emitError(KSS_PARAM_SYNTAX_ERROR + key + '"'); } var name = splitkey[0]; var qualifier = splitkey[1]; @@ -142,6 +143,7 @@ this.emitError('kss param key evt--yyy must not have different names "' + key + '", it must be "' + this.evt_name + '"'); } if (value.isMethod != false) { + /*XXX what does this error message mean ? */ this.emitError('evt-xxx-yyy: cannot use method as parm value, key "' + key + '"'); } this.evt_name = qualifier; Modified: kukit/kukit.js/trunk/kukit/plugin.js ============================================================================== --- kukit/kukit.js/trunk/kukit/plugin.js (original) +++ kukit/kukit.js/trunk/kukit/plugin.js Tue Sep 5 12:40:27 2006 @@ -462,3 +462,33 @@ kukit.cr.commandRegistry.registerFromAction('copyChildNodesTo', kukit.cr.makeSelectorCommand, 'copyChildrenTo'); kukit.cr.commandRegistry.registerFromAction('setStateVar', kukit.cr.makeGlobalCommand, 'setStatevar'); + +// Scriptaculous Effects + +try { + var dummy = Effect.transitions; + kukit.HASEFFECTS = 1; +} catch(e) { + kukit.HASEFFECTS = 0; +} + +if (kukit.HASEFFECTS) { + kukit.ar.actionRegistry.register("effect", function (oper) { + oper.completeParms([], {'type': 'fade'}, 'scriptaculous effect'); + var node = oper.node; + if (oper.parms.type == 'fade') { + Effect.Fade(node); + } else if (oper.parms.type == 'appear') { + Effect.Appear(node); + } else if (oper.parms.type == 'puff') { + Effect.Puff(node); + } else if (oper.parms.type == 'blinddown') { + Effect.BlindDown(node); + } else if (oper.parms.type == 'blindup') { + Effect.BlindUp(node); + } + }); + + kukit.cr.commandRegistry.registerFromAction('effect', kukit.cr.makeSelectorCommand); + +} From gotcha at codespeak.net Tue Sep 5 12:41:50 2006 From: gotcha at codespeak.net (gotcha at codespeak.net) Date: Tue, 5 Sep 2006 12:41:50 +0200 (CEST) Subject: [Kukit-checkins] r31998 - in kukit/azaxdemo/trunk: . browser Message-ID: <20060905104150.7AF9910075@code0.codespeak.net> Author: gotcha Date: Tue Sep 5 12:41:47 2006 New Revision: 31998 Added: kukit/azaxdemo/trunk/browser/azax_effects.kss kukit/azaxdemo/trunk/browser/azax_effects.pt Modified: kukit/azaxdemo/trunk/browser/azax_demo_index.pt kukit/azaxdemo/trunk/browser/header_macros.pt kukit/azaxdemo/trunk/configure.zcml kukit/azaxdemo/trunk/simplecontent.py Log: stuff for optilude Modified: kukit/azaxdemo/trunk/browser/azax_demo_index.pt ============================================================================== --- kukit/azaxdemo/trunk/browser/azax_demo_index.pt (original) +++ kukit/azaxdemo/trunk/browser/azax_demo_index.pt Tue Sep 5 12:41:47 2006 @@ -13,6 +13,7 @@
  • More complex selectors
  • Master-slave selects revisited
  • Form submit
  • +
  • Effects
  • Added: kukit/azaxdemo/trunk/browser/azax_effects.kss ============================================================================== --- (empty file) +++ kukit/azaxdemo/trunk/browser/azax_effects.kss Tue Sep 5 12:41:47 2006 @@ -0,0 +1,5 @@ +.effects:click { + action-client: effect; + effect-type: nodeAttr('id'); +} + Added: kukit/azaxdemo/trunk/browser/azax_effects.pt ============================================================================== --- (empty file) +++ kukit/azaxdemo/trunk/browser/azax_effects.pt Tue Sep 5 12:41:47 2006 @@ -0,0 +1,26 @@ + + + + + + + +

    All demos

    +

    Start logging pane

    +

    View KSS resource

    +

    Effects

    + +

    Demo

    +
    Click here to make me fade
    +
    Click here to make me puff
    +
    Click here to make me blinddown
    +
    Click here to make me blindup
    + + Modified: kukit/azaxdemo/trunk/browser/header_macros.pt ============================================================================== --- kukit/azaxdemo/trunk/browser/header_macros.pt (original) +++ kukit/azaxdemo/trunk/browser/header_macros.pt Tue Sep 5 12:41:47 2006 @@ -14,6 +14,14 @@ src="++resource++MochiKit.js"> + + Modified: kukit/azaxdemo/trunk/configure.zcml ============================================================================== --- kukit/azaxdemo/trunk/configure.zcml (original) +++ kukit/azaxdemo/trunk/configure.zcml Tue Sep 5 12:41:47 2006 @@ -376,4 +376,17 @@ /> + + + + +
    Modified: kukit/azaxdemo/trunk/simplecontent.py ============================================================================== --- kukit/azaxdemo/trunk/simplecontent.py (original) +++ kukit/azaxdemo/trunk/simplecontent.py Tue Sep 5 12:41:47 2006 @@ -36,6 +36,10 @@ meta_type = 'AzaxDemo SimpleContent' security = ClassSecurityInfo() + manage_options = ( + {'label':'Demos', 'action':''}, + ) + SimpleItem.manage_options + def __init__(self, id, title): self.id = id self.title = title From gotcha at codespeak.net Tue Sep 5 13:23:45 2006 From: gotcha at codespeak.net (gotcha at codespeak.net) Date: Tue, 5 Sep 2006 13:23:45 +0200 (CEST) Subject: [Kukit-checkins] r32002 - in kukit/azax/trunk: . plugins Message-ID: <20060905112345.5152910072@code0.codespeak.net> Author: gotcha Date: Tue Sep 5 13:23:42 2006 New Revision: 32002 Added: kukit/azax/trunk/concatresource.zcml Modified: kukit/azax/trunk/commands.py kukit/azax/trunk/configure.zcml kukit/azax/trunk/plugins/configure.zcml Log: stuff for optilude Modified: kukit/azax/trunk/commands.py ============================================================================== --- kukit/azax/trunk/commands.py (original) +++ kukit/azax/trunk/commands.py Tue Sep 5 13:23:42 2006 @@ -143,6 +143,11 @@ for key, value in kw.iteritems(): command.addParam(key, value) + def effect(self, selector, type): + """ see interfaces.py """ + command = self.addCommand('effect', selector) + data = command.addParam('type', type) + # XXX Deprecated ones def moveChildrenTo(self, selector, id): Added: kukit/azax/trunk/concatresource.zcml ============================================================================== --- (empty file) +++ kukit/azax/trunk/concatresource.zcml Tue Sep 5 13:23:42 2006 @@ -0,0 +1,37 @@ + + + + + + Modified: kukit/azax/trunk/configure.zcml ============================================================================== --- kukit/azax/trunk/configure.zcml (original) +++ kukit/azax/trunk/configure.zcml Tue Sep 5 13:23:42 2006 @@ -10,30 +10,18 @@ name="sarissa.js" /> - - + + + + + + + Author: gotcha Date: Tue Sep 5 13:24:16 2006 New Revision: 32003 Modified: kukit/azaxdemo/trunk/azaxview.py kukit/azaxdemo/trunk/browser/azax_effects.kss kukit/azaxdemo/trunk/browser/azax_effects.pt kukit/azaxdemo/trunk/configure.zcml Log: stuff for optilude - end Modified: kukit/azaxdemo/trunk/azaxview.py ============================================================================== --- kukit/azaxdemo/trunk/azaxview.py (original) +++ kukit/azaxdemo/trunk/azaxview.py Tue Sep 5 13:24:16 2006 @@ -157,3 +157,8 @@ retval = force_unicode(''.join(result), 'utf') self.replaceInnerHTML('div#async', retval) return self.render() + + def reset(self): + self.effect('.effects', 'appear') + return self.render() + Modified: kukit/azaxdemo/trunk/browser/azax_effects.kss ============================================================================== --- kukit/azaxdemo/trunk/browser/azax_effects.kss (original) +++ kukit/azaxdemo/trunk/browser/azax_effects.kss Tue Sep 5 13:24:16 2006 @@ -3,3 +3,7 @@ effect-type: nodeAttr('id'); } +input#resetEffects:click { + action-server: resetEffects; +} + Modified: kukit/azaxdemo/trunk/browser/azax_effects.pt ============================================================================== --- kukit/azaxdemo/trunk/browser/azax_effects.pt (original) +++ kukit/azaxdemo/trunk/browser/azax_effects.pt Tue Sep 5 13:24:16 2006 @@ -5,22 +5,23 @@

    All demos

    Start logging pane

    -

    View KSS resource

    +

    View KSS resource

    Effects

    Demo

    Click here to make me fade
    Click here to make me puff
    -
    Click here to make me blinddown
    Click here to make me blindup
    + Modified: kukit/azaxdemo/trunk/configure.zcml ============================================================================== --- kukit/azaxdemo/trunk/configure.zcml (original) +++ kukit/azaxdemo/trunk/configure.zcml Tue Sep 5 13:24:16 2006 @@ -388,5 +388,13 @@ file="browser/azax_effects.kss" name="effects.kss" /> + + From reebalazs at codespeak.net Tue Sep 5 13:30:56 2006 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Tue, 5 Sep 2006 13:30:56 +0200 (CEST) Subject: [Kukit-checkins] r32007 - kukit/bluekit/trunk Message-ID: <20060905113056.B2E3110075@code0.codespeak.net> Author: reebalazs Date: Tue Sep 5 13:30:55 2006 New Revision: 32007 Modified: kukit/bluekit/trunk/configure.zcml Log: Prototype is now defined as a resuorce from azax core Modified: kukit/bluekit/trunk/configure.zcml ============================================================================== --- kukit/bluekit/trunk/configure.zcml (original) +++ kukit/bluekit/trunk/configure.zcml Tue Sep 5 13:30:55 2006 @@ -20,10 +20,11 @@ name="mockup.js" /> - + Author: reebalazs Date: Tue Sep 5 16:45:10 2006 New Revision: 32015 Added: kukit/azax/trunk/pluginregistry/ - copied from r32011, kukit/azax/trunk/plugins/ Removed: kukit/azax/trunk/plugins/ Modified: kukit/azax/trunk/commands.py kukit/azax/trunk/configure.zcml kukit/azax/trunk/meta.zcml Log: plugins -> pluginregistry Modified: kukit/azax/trunk/commands.py ============================================================================== --- kukit/azax/trunk/commands.py (original) +++ kukit/azax/trunk/commands.py Tue Sep 5 16:45:10 2006 @@ -28,7 +28,7 @@ from zope.interface import implements from zope.app.pagetemplate.viewpagetemplatefile import ViewPageTemplateFile from interfaces import IAzaxCommands, IAzaxCommand, IAzaxParam -import plugins +import pluginregistry from unicode_quirks import force_unicode from zope.interface import Interface import zope.component @@ -189,7 +189,7 @@ implements(IAzaxCommand) def __init__(self, command_name, selector=None, **kw): - if plugins.Command.isRegistered(command_name): + if pluginregistry.Command.isRegistered(command_name): # ok. XXX this will be deprecated # All registerCommand commands are obsolete, by default import warnings, textwrap @@ -197,14 +197,14 @@ The usage of the kss command "%s" is deprecated''' % (command_name, )), DeprecationWarning, 2) else: - plugins.Action.checkRegisteredCommand(command_name) + pluginregistry.Action.checkRegisteredCommand(command_name) if selector is not None: if isinstance(selector, basestring): # the default selector - given just as a string self.selector = selector self.selectorType = '' else: - plugins.SelectorType.checkRegistered(selector.type) + pluginregistry.SelectorType.checkRegistered(selector.type) self.selector = selector.value self.selectorType = selector.type else: Modified: kukit/azax/trunk/configure.zcml ============================================================================== --- kukit/azax/trunk/configure.zcml (original) +++ kukit/azax/trunk/configure.zcml Tue Sep 5 16:45:10 2006 @@ -3,7 +3,7 @@ xmlns:five="http://namespaces.zope.org/five"> - + - + From reebalazs at codespeak.net Tue Sep 5 17:55:48 2006 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Tue, 5 Sep 2006 17:55:48 +0200 (CEST) Subject: [Kukit-checkins] r32016 - in kukit/kukit.js/trunk: 3rd_party kukit Message-ID: <20060905155548.36C361007D@code0.codespeak.net> Author: reebalazs Date: Tue Sep 5 17:55:45 2006 New Revision: 32016 Removed: kukit/kukit.js/trunk/3rd_party/effects.js kukit/kukit.js/trunk/3rd_party/prototype.js Modified: kukit/kukit.js/trunk/kukit/plugin.js Log: Refactor core plugins Deleted: /kukit/kukit.js/trunk/3rd_party/effects.js ============================================================================== --- /kukit/kukit.js/trunk/3rd_party/effects.js Tue Sep 5 17:55:45 2006 +++ (empty file) @@ -1,958 +0,0 @@ -// Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) -// Contributors: -// Justin Palmer (http://encytemedia.com/) -// Mark Pilgrim (http://diveintomark.org/) -// Martin Bialasinki -// -// See scriptaculous.js for full license. - -// converts rgb() and #xxx to #xxxxxx format, -// returns self (or first argument) if not convertable -String.prototype.parseColor = function() { - var color = '#'; - if(this.slice(0,4) == 'rgb(') { - var cols = this.slice(4,this.length-1).split(','); - var i=0; do { color += parseInt(cols[i]).toColorPart() } while (++i<3); - } else { - if(this.slice(0,1) == '#') { - if(this.length==4) for(var i=1;i<4;i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase(); - if(this.length==7) color = this.toLowerCase(); - } - } - return(color.length==7 ? color : (arguments[0] || this)); -} - -/*--------------------------------------------------------------------------*/ - -Element.collectTextNodes = function(element) { - return $A($(element).childNodes).collect( function(node) { - return (node.nodeType==3 ? node.nodeValue : - (node.hasChildNodes() ? Element.collectTextNodes(node) : '')); - }).flatten().join(''); -} - -Element.collectTextNodesIgnoreClass = function(element, className) { - return $A($(element).childNodes).collect( function(node) { - return (node.nodeType==3 ? node.nodeValue : - ((node.hasChildNodes() && !Element.hasClassName(node,className)) ? - Element.collectTextNodesIgnoreClass(node, className) : '')); - }).flatten().join(''); -} - -Element.setContentZoom = function(element, percent) { - element = $(element); - Element.setStyle(element, {fontSize: (percent/100) + 'em'}); - if(navigator.appVersion.indexOf('AppleWebKit')>0) window.scrollBy(0,0); -} - -Element.getOpacity = function(element){ - var opacity; - if (opacity = Element.getStyle(element, 'opacity')) - return parseFloat(opacity); - if (opacity = (Element.getStyle(element, 'filter') || '').match(/alpha\(opacity=(.*)\)/)) - if(opacity[1]) return parseFloat(opacity[1]) / 100; - return 1.0; -} - -Element.setOpacity = function(element, value){ - element= $(element); - if (value == 1){ - Element.setStyle(element, { opacity: - (/Gecko/.test(navigator.userAgent) && !/Konqueror|Safari|KHTML/.test(navigator.userAgent)) ? - 0.999999 : null }); - if(/MSIE/.test(navigator.userAgent)) - Element.setStyle(element, {filter: Element.getStyle(element,'filter').replace(/alpha\([^\)]*\)/gi,'')}); - } else { - if(value < 0.00001) value = 0; - Element.setStyle(element, {opacity: value}); - if(/MSIE/.test(navigator.userAgent)) - Element.setStyle(element, - { filter: Element.getStyle(element,'filter').replace(/alpha\([^\)]*\)/gi,'') + - 'alpha(opacity='+value*100+')' }); - } -} - -Element.getInlineOpacity = function(element){ - return $(element).style.opacity || ''; -} - -Element.childrenWithClassName = function(element, className, findFirst) { - var classNameRegExp = new RegExp("(^|\\s)" + className + "(\\s|$)"); - var results = $A($(element).getElementsByTagName('*'))[findFirst ? 'detect' : 'select']( function(c) { - return (c.className && c.className.match(classNameRegExp)); - }); - if(!results) results = []; - return results; -} - -Element.forceRerendering = function(element) { - try { - element = $(element); - var n = document.createTextNode(' '); - element.appendChild(n); - element.removeChild(n); - } catch(e) { } -}; - -/*--------------------------------------------------------------------------*/ - -Array.prototype.call = function() { - var args = arguments; - this.each(function(f){ f.apply(this, args) }); -} - -/*--------------------------------------------------------------------------*/ - -var Effect = { - tagifyText: function(element) { - var tagifyStyle = 'position:relative'; - if(/MSIE/.test(navigator.userAgent)) tagifyStyle += ';zoom:1'; - element = $(element); - $A(element.childNodes).each( function(child) { - if(child.nodeType==3) { - child.nodeValue.toArray().each( function(character) { - element.insertBefore( - Builder.node('span',{style: tagifyStyle}, - character == ' ' ? String.fromCharCode(160) : character), - child); - }); - Element.remove(child); - } - }); - }, - multiple: function(element, effect) { - var elements; - if(((typeof element == 'object') || - (typeof element == 'function')) && - (element.length)) - elements = element; - else - elements = $(element).childNodes; - - var options = Object.extend({ - speed: 0.1, - delay: 0.0 - }, arguments[2] || {}); - var masterDelay = options.delay; - - $A(elements).each( function(element, index) { - new effect(element, Object.extend(options, { delay: index * options.speed + masterDelay })); - }); - }, - PAIRS: { - 'slide': ['SlideDown','SlideUp'], - 'blind': ['BlindDown','BlindUp'], - 'appear': ['Appear','Fade'] - }, - toggle: function(element, effect) { - element = $(element); - effect = (effect || 'appear').toLowerCase(); - var options = Object.extend({ - queue: { position:'end', scope:(element.id || 'global'), limit: 1 } - }, arguments[2] || {}); - Effect[element.visible() ? - Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options); - } -}; - -var Effect2 = Effect; // deprecated - -/* ------------- transitions ------------- */ - -Effect.Transitions = {} - -Effect.Transitions.linear = function(pos) { - return pos; -} -Effect.Transitions.sinoidal = function(pos) { - return (-Math.cos(pos*Math.PI)/2) + 0.5; -} -Effect.Transitions.reverse = function(pos) { - return 1-pos; -} -Effect.Transitions.flicker = function(pos) { - return ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random()/4; -} -Effect.Transitions.wobble = function(pos) { - return (-Math.cos(pos*Math.PI*(9*pos))/2) + 0.5; -} -Effect.Transitions.pulse = function(pos) { - return (Math.floor(pos*10) % 2 == 0 ? - (pos*10-Math.floor(pos*10)) : 1-(pos*10-Math.floor(pos*10))); -} -Effect.Transitions.none = function(pos) { - return 0; -} -Effect.Transitions.full = function(pos) { - return 1; -} - -/* ------------- core effects ------------- */ - -Effect.ScopedQueue = Class.create(); -Object.extend(Object.extend(Effect.ScopedQueue.prototype, Enumerable), { - initialize: function() { - this.effects = []; - this.interval = null; - }, - _each: function(iterator) { - this.effects._each(iterator); - }, - add: function(effect) { - var timestamp = new Date().getTime(); - - var position = (typeof effect.options.queue == 'string') ? - effect.options.queue : effect.options.queue.position; - - switch(position) { - case 'front': - // move unstarted effects after this effect - this.effects.findAll(function(e){ return e.state=='idle' }).each( function(e) { - e.startOn += effect.finishOn; - e.finishOn += effect.finishOn; - }); - break; - case 'end': - // start effect after last queued effect has finished - timestamp = this.effects.pluck('finishOn').max() || timestamp; - break; - } - - effect.startOn += timestamp; - effect.finishOn += timestamp; - - if(!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit)) - this.effects.push(effect); - - if(!this.interval) - this.interval = setInterval(this.loop.bind(this), 40); - }, - remove: function(effect) { - this.effects = this.effects.reject(function(e) { return e==effect }); - if(this.effects.length == 0) { - clearInterval(this.interval); - this.interval = null; - } - }, - loop: function() { - var timePos = new Date().getTime(); - this.effects.invoke('loop', timePos); - } -}); - -Effect.Queues = { - instances: $H(), - get: function(queueName) { - if(typeof queueName != 'string') return queueName; - - if(!this.instances[queueName]) - this.instances[queueName] = new Effect.ScopedQueue(); - - return this.instances[queueName]; - } -} -Effect.Queue = Effect.Queues.get('global'); - -Effect.DefaultOptions = { - transition: Effect.Transitions.sinoidal, - duration: 1.0, // seconds - fps: 25.0, // max. 25fps due to Effect.Queue implementation - sync: false, // true for combining - from: 0.0, - to: 1.0, - delay: 0.0, - queue: 'parallel' -} - -Effect.Base = function() {}; -Effect.Base.prototype = { - position: null, - start: function(options) { - this.options = Object.extend(Object.extend({},Effect.DefaultOptions), options || {}); - this.currentFrame = 0; - this.state = 'idle'; - this.startOn = this.options.delay*1000; - this.finishOn = this.startOn + (this.options.duration*1000); - this.event('beforeStart'); - if(!this.options.sync) - Effect.Queues.get(typeof this.options.queue == 'string' ? - 'global' : this.options.queue.scope).add(this); - }, - loop: function(timePos) { - if(timePos >= this.startOn) { - if(timePos >= this.finishOn) { - this.render(1.0); - this.cancel(); - this.event('beforeFinish'); - if(this.finish) this.finish(); - this.event('afterFinish'); - return; - } - var pos = (timePos - this.startOn) / (this.finishOn - this.startOn); - var frame = Math.round(pos * this.options.fps * this.options.duration); - if(frame > this.currentFrame) { - this.render(pos); - this.currentFrame = frame; - } - } - }, - render: function(pos) { - if(this.state == 'idle') { - this.state = 'running'; - this.event('beforeSetup'); - if(this.setup) this.setup(); - this.event('afterSetup'); - } - if(this.state == 'running') { - if(this.options.transition) pos = this.options.transition(pos); - pos *= (this.options.to-this.options.from); - pos += this.options.from; - this.position = pos; - this.event('beforeUpdate'); - if(this.update) this.update(pos); - this.event('afterUpdate'); - } - }, - cancel: function() { - if(!this.options.sync) - Effect.Queues.get(typeof this.options.queue == 'string' ? - 'global' : this.options.queue.scope).remove(this); - this.state = 'finished'; - }, - event: function(eventName) { - if(this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this); - if(this.options[eventName]) this.options[eventName](this); - }, - inspect: function() { - return '#'; - } -} - -Effect.Parallel = Class.create(); -Object.extend(Object.extend(Effect.Parallel.prototype, Effect.Base.prototype), { - initialize: function(effects) { - this.effects = effects || []; - this.start(arguments[1]); - }, - update: function(position) { - this.effects.invoke('render', position); - }, - finish: function(position) { - this.effects.each( function(effect) { - effect.render(1.0); - effect.cancel(); - effect.event('beforeFinish'); - if(effect.finish) effect.finish(position); - effect.event('afterFinish'); - }); - } -}); - -Effect.Opacity = Class.create(); -Object.extend(Object.extend(Effect.Opacity.prototype, Effect.Base.prototype), { - initialize: function(element) { - this.element = $(element); - // make this work on IE on elements without 'layout' - if(/MSIE/.test(navigator.userAgent) && (!this.element.hasLayout)) - this.element.setStyle({zoom: 1}); - var options = Object.extend({ - from: this.element.getOpacity() || 0.0, - to: 1.0 - }, arguments[1] || {}); - this.start(options); - }, - update: function(position) { - this.element.setOpacity(position); - } -}); - -Effect.Move = Class.create(); -Object.extend(Object.extend(Effect.Move.prototype, Effect.Base.prototype), { - initialize: function(element) { - this.element = $(element); - var options = Object.extend({ - x: 0, - y: 0, - mode: 'relative' - }, arguments[1] || {}); - this.start(options); - }, - setup: function() { - // Bug in Opera: Opera returns the "real" position of a static element or - // relative element that does not have top/left explicitly set. - // ==> Always set top and left for position relative elements in your stylesheets - // (to 0 if you do not need them) - this.element.makePositioned(); - this.originalLeft = parseFloat(this.element.getStyle('left') || '0'); - this.originalTop = parseFloat(this.element.getStyle('top') || '0'); - if(this.options.mode == 'absolute') { - // absolute movement, so we need to calc deltaX and deltaY - this.options.x = this.options.x - this.originalLeft; - this.options.y = this.options.y - this.originalTop; - } - }, - update: function(position) { - this.element.setStyle({ - left: this.options.x * position + this.originalLeft + 'px', - top: this.options.y * position + this.originalTop + 'px' - }); - } -}); - -// for backwards compatibility -Effect.MoveBy = function(element, toTop, toLeft) { - return new Effect.Move(element, - Object.extend({ x: toLeft, y: toTop }, arguments[3] || {})); -}; - -Effect.Scale = Class.create(); -Object.extend(Object.extend(Effect.Scale.prototype, Effect.Base.prototype), { - initialize: function(element, percent) { - this.element = $(element) - var options = Object.extend({ - scaleX: true, - scaleY: true, - scaleContent: true, - scaleFromCenter: false, - scaleMode: 'box', // 'box' or 'contents' or {} with provided values - scaleFrom: 100.0, - scaleTo: percent - }, arguments[2] || {}); - this.start(options); - }, - setup: function() { - this.restoreAfterFinish = this.options.restoreAfterFinish || false; - this.elementPositioning = this.element.getStyle('position'); - - this.originalStyle = {}; - ['top','left','width','height','fontSize'].each( function(k) { - this.originalStyle[k] = this.element.style[k]; - }.bind(this)); - - this.originalTop = this.element.offsetTop; - this.originalLeft = this.element.offsetLeft; - - var fontSize = this.element.getStyle('font-size') || '100%'; - ['em','px','%'].each( function(fontSizeType) { - if(fontSize.indexOf(fontSizeType)>0) { - this.fontSize = parseFloat(fontSize); - this.fontSizeType = fontSizeType; - } - }.bind(this)); - - this.factor = (this.options.scaleTo - this.options.scaleFrom)/100; - - this.dims = null; - if(this.options.scaleMode=='box') - this.dims = [this.element.offsetHeight, this.element.offsetWidth]; - if(/^content/.test(this.options.scaleMode)) - this.dims = [this.element.scrollHeight, this.element.scrollWidth]; - if(!this.dims) - this.dims = [this.options.scaleMode.originalHeight, - this.options.scaleMode.originalWidth]; - }, - update: function(position) { - var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position); - if(this.options.scaleContent && this.fontSize) - this.element.setStyle({fontSize: this.fontSize * currentScale + this.fontSizeType }); - this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale); - }, - finish: function(position) { - if (this.restoreAfterFinish) this.element.setStyle(this.originalStyle); - }, - setDimensions: function(height, width) { - var d = {}; - if(this.options.scaleX) d.width = width + 'px'; - if(this.options.scaleY) d.height = height + 'px'; - if(this.options.scaleFromCenter) { - var topd = (height - this.dims[0])/2; - var leftd = (width - this.dims[1])/2; - if(this.elementPositioning == 'absolute') { - if(this.options.scaleY) d.top = this.originalTop-topd + 'px'; - if(this.options.scaleX) d.left = this.originalLeft-leftd + 'px'; - } else { - if(this.options.scaleY) d.top = -topd + 'px'; - if(this.options.scaleX) d.left = -leftd + 'px'; - } - } - this.element.setStyle(d); - } -}); - -Effect.Highlight = Class.create(); -Object.extend(Object.extend(Effect.Highlight.prototype, Effect.Base.prototype), { - initialize: function(element) { - this.element = $(element); - var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || {}); - this.start(options); - }, - setup: function() { - // Prevent executing on elements not in the layout flow - if(this.element.getStyle('display')=='none') { this.cancel(); return; } - // Disable background image during the effect - this.oldStyle = { - backgroundImage: this.element.getStyle('background-image') }; - this.element.setStyle({backgroundImage: 'none'}); - if(!this.options.endcolor) - this.options.endcolor = this.element.getStyle('background-color').parseColor('#ffffff'); - if(!this.options.restorecolor) - this.options.restorecolor = this.element.getStyle('background-color'); - // init color calculations - this._base = $R(0,2).map(function(i){ return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16) }.bind(this)); - this._delta = $R(0,2).map(function(i){ return parseInt(this.options.endcolor.slice(i*2+1,i*2+3),16)-this._base[i] }.bind(this)); - }, - update: function(position) { - this.element.setStyle({backgroundColor: $R(0,2).inject('#',function(m,v,i){ - return m+(Math.round(this._base[i]+(this._delta[i]*position)).toColorPart()); }.bind(this)) }); - }, - finish: function() { - this.element.setStyle(Object.extend(this.oldStyle, { - backgroundColor: this.options.restorecolor - })); - } -}); - -Effect.ScrollTo = Class.create(); -Object.extend(Object.extend(Effect.ScrollTo.prototype, Effect.Base.prototype), { - initialize: function(element) { - this.element = $(element); - this.start(arguments[1] || {}); - }, - setup: function() { - Position.prepare(); - var offsets = Position.cumulativeOffset(this.element); - if(this.options.offset) offsets[1] += this.options.offset; - var max = window.innerHeight ? - window.height - window.innerHeight : - document.body.scrollHeight - - (document.documentElement.clientHeight ? - document.documentElement.clientHeight : document.body.clientHeight); - this.scrollStart = Position.deltaY; - this.delta = (offsets[1] > max ? max : offsets[1]) - this.scrollStart; - }, - update: function(position) { - Position.prepare(); - window.scrollTo(Position.deltaX, - this.scrollStart + (position*this.delta)); - } -}); - -/* ------------- combination effects ------------- */ - -Effect.Fade = function(element) { - element = $(element); - var oldOpacity = element.getInlineOpacity(); - var options = Object.extend({ - from: element.getOpacity() || 1.0, - to: 0.0, - afterFinishInternal: function(effect) { - if(effect.options.to!=0) return; - effect.element.hide(); - effect.element.setStyle({opacity: oldOpacity}); - }}, arguments[1] || {}); - return new Effect.Opacity(element,options); -} - -Effect.Appear = function(element) { - element = $(element); - var options = Object.extend({ - from: (element.getStyle('display') == 'none' ? 0.0 : element.getOpacity() || 0.0), - to: 1.0, - // force Safari to render floated elements properly - afterFinishInternal: function(effect) { - effect.element.forceRerendering(); - }, - beforeSetup: function(effect) { - effect.element.setOpacity(effect.options.from); - effect.element.show(); - }}, arguments[1] || {}); - return new Effect.Opacity(element,options); -} - -Effect.Puff = function(element) { - element = $(element); - var oldStyle = { opacity: element.getInlineOpacity(), position: element.getStyle('position') }; - return new Effect.Parallel( - [ new Effect.Scale(element, 200, - { sync: true, scaleFromCenter: true, scaleContent: true, restoreAfterFinish: true }), - new Effect.Opacity(element, { sync: true, to: 0.0 } ) ], - Object.extend({ duration: 1.0, - beforeSetupInternal: function(effect) { - effect.effects[0].element.setStyle({position: 'absolute'}); }, - afterFinishInternal: function(effect) { - effect.effects[0].element.hide(); - effect.effects[0].element.setStyle(oldStyle); } - }, arguments[1] || {}) - ); -} - -Effect.BlindUp = function(element) { - element = $(element); - element.makeClipping(); - return new Effect.Scale(element, 0, - Object.extend({ scaleContent: false, - scaleX: false, - restoreAfterFinish: true, - afterFinishInternal: function(effect) { - effect.element.hide(); - effect.element.undoClipping(); - } - }, arguments[1] || {}) - ); -} - -Effect.BlindDown = function(element) { - element = $(element); - var elementDimensions = element.getDimensions(); - return new Effect.Scale(element, 100, - Object.extend({ scaleContent: false, - scaleX: false, - scaleFrom: 0, - scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, - restoreAfterFinish: true, - afterSetup: function(effect) { - effect.element.makeClipping(); - effect.element.setStyle({height: '0px'}); - effect.element.show(); - }, - afterFinishInternal: function(effect) { - effect.element.undoClipping(); - } - }, arguments[1] || {}) - ); -} - -Effect.SwitchOff = function(element) { - element = $(element); - var oldOpacity = element.getInlineOpacity(); - return new Effect.Appear(element, { - duration: 0.4, - from: 0, - transition: Effect.Transitions.flicker, - afterFinishInternal: function(effect) { - new Effect.Scale(effect.element, 1, { - duration: 0.3, scaleFromCenter: true, - scaleX: false, scaleContent: false, restoreAfterFinish: true, - beforeSetup: function(effect) { - effect.element.makePositioned(); - effect.element.makeClipping(); - }, - afterFinishInternal: function(effect) { - effect.element.hide(); - effect.element.undoClipping(); - effect.element.undoPositioned(); - effect.element.setStyle({opacity: oldOpacity}); - } - }) - } - }); -} - -Effect.DropOut = function(element) { - element = $(element); - var oldStyle = { - top: element.getStyle('top'), - left: element.getStyle('left'), - opacity: element.getInlineOpacity() }; - return new Effect.Parallel( - [ new Effect.Move(element, {x: 0, y: 100, sync: true }), - new Effect.Opacity(element, { sync: true, to: 0.0 }) ], - Object.extend( - { duration: 0.5, - beforeSetup: function(effect) { - effect.effects[0].element.makePositioned(); - }, - afterFinishInternal: function(effect) { - effect.effects[0].element.hide(); - effect.effects[0].element.undoPositioned(); - effect.effects[0].element.setStyle(oldStyle); - } - }, arguments[1] || {})); -} - -Effect.Shake = function(element) { - element = $(element); - var oldStyle = { - top: element.getStyle('top'), - left: element.getStyle('left') }; - return new Effect.Move(element, - { x: 20, y: 0, duration: 0.05, afterFinishInternal: function(effect) { - new Effect.Move(effect.element, - { x: -40, y: 0, duration: 0.1, afterFinishInternal: function(effect) { - new Effect.Move(effect.element, - { x: 40, y: 0, duration: 0.1, afterFinishInternal: function(effect) { - new Effect.Move(effect.element, - { x: -40, y: 0, duration: 0.1, afterFinishInternal: function(effect) { - new Effect.Move(effect.element, - { x: 40, y: 0, duration: 0.1, afterFinishInternal: function(effect) { - new Effect.Move(effect.element, - { x: -20, y: 0, duration: 0.05, afterFinishInternal: function(effect) { - effect.element.undoPositioned(); - effect.element.setStyle(oldStyle); - }}) }}) }}) }}) }}) }}); -} - -Effect.SlideDown = function(element) { - element = $(element); - element.cleanWhitespace(); - // SlideDown need to have the content of the element wrapped in a container element with fixed height! - var oldInnerBottom = $(element.firstChild).getStyle('bottom'); - var elementDimensions = element.getDimensions(); - return new Effect.Scale(element, 100, Object.extend({ - scaleContent: false, - scaleX: false, - scaleFrom: window.opera ? 0 : 1, - scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, - restoreAfterFinish: true, - afterSetup: function(effect) { - effect.element.makePositioned(); - effect.element.firstChild.makePositioned(); - if(window.opera) effect.element.setStyle({top: ''}); - effect.element.makeClipping(); - effect.element.setStyle({height: '0px'}); - effect.element.show(); }, - afterUpdateInternal: function(effect) { - effect.element.firstChild.setStyle({bottom: - (effect.dims[0] - effect.element.clientHeight) + 'px' }); - }, - afterFinishInternal: function(effect) { - effect.element.undoClipping(); - // IE will crash if child is undoPositioned first - if(/MSIE/.test(navigator.userAgent)){ - effect.element.undoPositioned(); - effect.element.firstChild.undoPositioned(); - }else{ - effect.element.firstChild.undoPositioned(); - effect.element.undoPositioned(); - } - effect.element.firstChild.setStyle({bottom: oldInnerBottom}); } - }, arguments[1] || {}) - ); -} - -Effect.SlideUp = function(element) { - element = $(element); - element.cleanWhitespace(); - var oldInnerBottom = $(element.firstChild).getStyle('bottom'); - return new Effect.Scale(element, window.opera ? 0 : 1, - Object.extend({ scaleContent: false, - scaleX: false, - scaleMode: 'box', - scaleFrom: 100, - restoreAfterFinish: true, - beforeStartInternal: function(effect) { - effect.element.makePositioned(); - effect.element.firstChild.makePositioned(); - if(window.opera) effect.element.setStyle({top: ''}); - effect.element.makeClipping(); - effect.element.show(); }, - afterUpdateInternal: function(effect) { - effect.element.firstChild.setStyle({bottom: - (effect.dims[0] - effect.element.clientHeight) + 'px' }); }, - afterFinishInternal: function(effect) { - effect.element.hide(); - effect.element.undoClipping(); - effect.element.firstChild.undoPositioned(); - effect.element.undoPositioned(); - effect.element.setStyle({bottom: oldInnerBottom}); } - }, arguments[1] || {}) - ); -} - -// Bug in opera makes the TD containing this element expand for a instance after finish -Effect.Squish = function(element) { - return new Effect.Scale(element, window.opera ? 1 : 0, - { restoreAfterFinish: true, - beforeSetup: function(effect) { - effect.element.makeClipping(effect.element); }, - afterFinishInternal: function(effect) { - effect.element.hide(effect.element); - effect.element.undoClipping(effect.element); } - }); -} - -Effect.Grow = function(element) { - element = $(element); - var options = Object.extend({ - direction: 'center', - moveTransition: Effect.Transitions.sinoidal, - scaleTransition: Effect.Transitions.sinoidal, - opacityTransition: Effect.Transitions.full - }, arguments[1] || {}); - var oldStyle = { - top: element.style.top, - left: element.style.left, - height: element.style.height, - width: element.style.width, - opacity: element.getInlineOpacity() }; - - var dims = element.getDimensions(); - var initialMoveX, initialMoveY; - var moveX, moveY; - - switch (options.direction) { - case 'top-left': - initialMoveX = initialMoveY = moveX = moveY = 0; - break; - case 'top-right': - initialMoveX = dims.width; - initialMoveY = moveY = 0; - moveX = -dims.width; - break; - case 'bottom-left': - initialMoveX = moveX = 0; - initialMoveY = dims.height; - moveY = -dims.height; - break; - case 'bottom-right': - initialMoveX = dims.width; - initialMoveY = dims.height; - moveX = -dims.width; - moveY = -dims.height; - break; - case 'center': - initialMoveX = dims.width / 2; - initialMoveY = dims.height / 2; - moveX = -dims.width / 2; - moveY = -dims.height / 2; - break; - } - - return new Effect.Move(element, { - x: initialMoveX, - y: initialMoveY, - duration: 0.01, - beforeSetup: function(effect) { - effect.element.hide(); - effect.element.makeClipping(); - effect.element.makePositioned(); - }, - afterFinishInternal: function(effect) { - new Effect.Parallel( - [ new Effect.Opacity(effect.element, { sync: true, to: 1.0, from: 0.0, transition: options.opacityTransition }), - new Effect.Move(effect.element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }), - new Effect.Scale(effect.element, 100, { - scaleMode: { originalHeight: dims.height, originalWidth: dims.width }, - sync: true, scaleFrom: window.opera ? 1 : 0, transition: options.scaleTransition, restoreAfterFinish: true}) - ], Object.extend({ - beforeSetup: function(effect) { - effect.effects[0].element.setStyle({height: '0px'}); - effect.effects[0].element.show(); - }, - afterFinishInternal: function(effect) { - effect.effects[0].element.undoClipping(); - effect.effects[0].element.undoPositioned(); - effect.effects[0].element.setStyle(oldStyle); - } - }, options) - ) - } - }); -} - -Effect.Shrink = function(element) { - element = $(element); - var options = Object.extend({ - direction: 'center', - moveTransition: Effect.Transitions.sinoidal, - scaleTransition: Effect.Transitions.sinoidal, - opacityTransition: Effect.Transitions.none - }, arguments[1] || {}); - var oldStyle = { - top: element.style.top, - left: element.style.left, - height: element.style.height, - width: element.style.width, - opacity: element.getInlineOpacity() }; - - var dims = element.getDimensions(); - var moveX, moveY; - - switch (options.direction) { - case 'top-left': - moveX = moveY = 0; - break; - case 'top-right': - moveX = dims.width; - moveY = 0; - break; - case 'bottom-left': - moveX = 0; - moveY = dims.height; - break; - case 'bottom-right': - moveX = dims.width; - moveY = dims.height; - break; - case 'center': - moveX = dims.width / 2; - moveY = dims.height / 2; - break; - } - - return new Effect.Parallel( - [ new Effect.Opacity(element, { sync: true, to: 0.0, from: 1.0, transition: options.opacityTransition }), - new Effect.Scale(element, window.opera ? 1 : 0, { sync: true, transition: options.scaleTransition, restoreAfterFinish: true}), - new Effect.Move(element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }) - ], Object.extend({ - beforeStartInternal: function(effect) { - effect.effects[0].element.makePositioned(); - effect.effects[0].element.makeClipping(); }, - afterFinishInternal: function(effect) { - effect.effects[0].element.hide(); - effect.effects[0].element.undoClipping(); - effect.effects[0].element.undoPositioned(); - effect.effects[0].element.setStyle(oldStyle); } - }, options) - ); -} - -Effect.Pulsate = function(element) { - element = $(element); - var options = arguments[1] || {}; - var oldOpacity = element.getInlineOpacity(); - var transition = options.transition || Effect.Transitions.sinoidal; - var reverser = function(pos){ return transition(1-Effect.Transitions.pulse(pos)) }; - reverser.bind(transition); - return new Effect.Opacity(element, - Object.extend(Object.extend({ duration: 3.0, from: 0, - afterFinishInternal: function(effect) { effect.element.setStyle({opacity: oldOpacity}); } - }, options), {transition: reverser})); -} - -Effect.Fold = function(element) { - element = $(element); - var oldStyle = { - top: element.style.top, - left: element.style.left, - width: element.style.width, - height: element.style.height }; - Element.makeClipping(element); - return new Effect.Scale(element, 5, Object.extend({ - scaleContent: false, - scaleX: false, - afterFinishInternal: function(effect) { - new Effect.Scale(element, 1, { - scaleContent: false, - scaleY: false, - afterFinishInternal: function(effect) { - effect.element.hide(); - effect.element.undoClipping(); - effect.element.setStyle(oldStyle); - } }); - }}, arguments[1] || {})); -}; - -['setOpacity','getOpacity','getInlineOpacity','forceRerendering','setContentZoom', - 'collectTextNodes','collectTextNodesIgnoreClass','childrenWithClassName'].each( - function(f) { Element.Methods[f] = Element[f]; } -); - -Element.Methods.visualEffect = function(element, effect, options) { - s = effect.gsub(/_/, '-').camelize(); - effect_class = s.charAt(0).toUpperCase() + s.substring(1); - new Effect[effect_class](element, options); - return $(element); -}; - -Element.addMethods(); \ No newline at end of file Deleted: /kukit/kukit.js/trunk/3rd_party/prototype.js ============================================================================== --- /kukit/kukit.js/trunk/3rd_party/prototype.js Tue Sep 5 17:55:45 2006 +++ (empty file) @@ -1,2006 +0,0 @@ -/* Prototype JavaScript framework, version 1.5.0_rc0 - * (c) 2005 Sam Stephenson - * - * Prototype is freely distributable under the terms of an MIT-style license. - * For details, see the Prototype web site: http://prototype.conio.net/ - * -/*--------------------------------------------------------------------------*/ - -var Prototype = { - Version: '1.5.0_rc0', - ScriptFragment: '(?:)((\n|\r|.)*?)(?:<\/script>)', - - emptyFunction: function() {}, - K: function(x) {return x} -} - -var Class = { - create: function() { - return function() { - this.initialize.apply(this, arguments); - } - } -} - -var Abstract = new Object(); - -Object.extend = function(destination, source) { - for (var 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; - } - } - } -} -Object.extend(String.prototype, { - gsub: function(pattern, replacement) { - var result = '', source = this, match; - replacement = arguments.callee.prepareReplacement(replacement); - - while (source.length > 0) { - if (match = source.match(pattern)) { - result += source.slice(0, match.index); - result += (replacement(match) || '').toString(); - source = source.slice(match.index + match[0].length); - } else { - result += source, source = ''; - } - } - return result; - }, - - sub: function(pattern, replacement, count) { - replacement = this.gsub.prepareReplacement(replacement); - count = count === undefined ? 1 : count; - - return this.gsub(pattern, function(match) { - if (--count < 0) return match[0]; - return replacement(match); - }); - }, - - scan: function(pattern, iterator) { - this.gsub(pattern, iterator); - return this; - }, - - truncate: function(length, truncation) { - length = length || 30; - truncation = truncation === undefined ? '...' : truncation; - return this.length > length ? - this.slice(0, length - truncation.length) + truncation : this; - }, - - strip: function() { - return this.replace(/^\s+/, '').replace(/\s+$/, ''); - }, - - 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(function(script) { return eval(script) }); - }, - - 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(/\\/g, '\\\\').replace(/'/g, '\\\'') + "'"; - } -}); - -String.prototype.gsub.prepareReplacement = function(replacement) { - if (typeof replacement == 'function') return replacement; - var template = new Template(replacement); - return function(match) { return template.evaluate(match) }; -} - -String.prototype.parseQuery = String.prototype.toQueryParams; - -var Template = Class.create(); -Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/; -Template.prototype = { - initialize: function(template, pattern) { - this.template = template.toString(); - this.pattern = pattern || Template.Pattern; - }, - - evaluate: function(object) { - return this.template.gsub(this.pattern, function(match) { - var before = match[1]; - if (before == '\\') return match[2]; - return before + (object[match[3]] || '').toString(); - }); - } -} - -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 (result == undefined || value >= result) - result = value; - }); - return result; - }, - - min: function(iterator) { - var result; - this.each(function(value, index) { - value = (iterator || Prototype.K)(value, index); - if (result == undefined || value < result) - 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) { - return iterator(collections.pluck(index)); - }); - }, - - inspect: function() { - return '#'; - } -} - -Object.extend(Enumerable, { - map: Enumerable.collect, - find: Enumerable.detect, - select: Enumerable.findAll, - member: Enumerable.include, - entries: Enumerable.toArray -}); -var $A = Array.from = function(iterable) { - if (!iterable) return []; - if (iterable.toArray) { - return iterable.toArray(); - } else { - var results = []; - for (var i = 0; i < iterable.length; i++) - results.push(iterable[i]); - return results; - } -} - -Object.extend(Array.prototype, Enumerable); - -if (!Array.prototype._reverse) - 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 && 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(); - }, - - inspect: function() { - return '[' + this.map(Object.inspect).join(', ') + ']'; - } -}); -var Hash = { - _each: function(iterator) { - for (var key in this) { - var value = this[key]; - if (typeof value == 'function') continue; - - var pair = [key, value]; - pair.key = key; - pair.value = value; - iterator(pair); - } - }, - - keys: function() { - return this.pluck('key'); - }, - - values: function() { - return this.pluck('value'); - }, - - merge: function(hash) { - return $H(hash).inject($H(this), function(mergedHash, pair) { - mergedHash[pair.key] = pair.value; - return mergedHash; - }); - }, - - toQueryString: function() { - return this.map(function(pair) { - return pair.map(encodeURIComponent).join('='); - }).join('&'); - }, - - inspect: function() { - return '#'; - } -} - -function $H(object) { - var hash = Object.extend({}, object || {}); - Object.extend(hash, Enumerable); - Object.extend(hash, Hash); - return hash; -} -ObjectRange = Class.create(); -Object.extend(ObjectRange.prototype, Enumerable); -Object.extend(ObjectRange.prototype, { - initialize: function(start, end, exclusive) { - this.start = start; - this.end = end; - this.exclusive = exclusive; - }, - - _each: function(iterator) { - var value = this.start; - do { - iterator(value); - value = value.succ(); - } while (this.include(value)); - }, - - include: function(value) { - if (value < this.start) - return false; - if (this.exclusive) - return value < this.end; - return value <= this.end; - } -}); - -var $R = function(start, end, exclusive) { - return new ObjectRange(start, end, exclusive); -} - -var Ajax = { - getTransport: function() { - return Try.these( - function() {return new XMLHttpRequest()}, - function() {return new ActiveXObject('Msxml2.XMLHTTP')}, - function() {return new ActiveXObject('Microsoft.XMLHTTP')} - ) || 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, - contentType: 'application/x-www-form-urlencoded', - 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, - 'Accept', 'text/javascript, text/html, application/xml, text/xml, */*']; - - if (this.options.method == 'post') { - requestHeaders.push('Content-type', this.options.contentType); - - /* 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); - } -}); -function $() { - var results = [], element; - for (var i = 0; i < arguments.length; i++) { - element = arguments[i]; - if (typeof element == 'string') - element = document.getElementById(element); - results.push(Element.extend(element)); - } - return results.length < 2 ? results[0] : results; -} - -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(Element.extend(child)); - return elements; - }); -} - -/*--------------------------------------------------------------------------*/ - -if (!window.Element) - var Element = new Object(); - -Element.extend = function(element) { - if (!element) return; - if (_nativeExtensions) return element; - - if (!element._extended && element.tagName && element != window) { - var methods = Element.Methods, cache = Element.extend.cache; - for (property in methods) { - var value = methods[property]; - if (typeof value == 'function') - element[property] = cache.findOrStore(value); - } - } - - element._extended = true; - return element; -} - -Element.extend.cache = { - findOrStore: function(value) { - return this[value] = this[value] || function() { - return value.apply(null, [this].concat($A(arguments))); - } - } -} - -Element.Methods = { - 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); - }, - - replace: function(element, html) { - element = $(element); - if (element.outerHTML) { - element.outerHTML = html.stripScripts(); - } else { - var range = element.ownerDocument.createRange(); - range.selectNodeContents(element); - element.parentNode.replaceChild( - range.createContextualFragment(html.stripScripts()), element); - } - 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*$/); - }, - - childOf: function(element, ancestor) { - element = $(element), ancestor = $(ancestor); - while (element = element.parentNode) - if (element == ancestor) return true; - return false; - }, - - 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 (var 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; - } -} - -Object.extend(Element, Element.Methods); - -var _nativeExtensions = false; - -if(!HTMLElement && /Konqueror|Safari|KHTML/.test(navigator.userAgent)) { - var HTMLElement = {} - HTMLElement.prototype = document.createElement('div').__proto__; -} - -Element.addMethods = function(methods) { - Object.extend(Element.Methods, methods || {}); - - if(typeof HTMLElement != 'undefined') { - var methods = Element.Methods, cache = Element.extend.cache; - for (property in methods) { - var value = methods[property]; - if (typeof value == 'function') - HTMLElement.prototype[property] = cache.findOrStore(value); - } - _nativeExtensions = true; - } -} - -Element.addMethods(); - -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) { - var tagName = this.element.tagName.toLowerCase(); - if (tagName == 'tbody' || tagName == 'tr') { - this.insertContent(this.contentFromAnonymousTable()); - } else { - throw e; - } - } - } else { - this.range = this.element.ownerDocument.createRange(); - if (this.initializeRange) this.initializeRange(); - this.insertContent([this.range.createContextualFragment(this.content)]); - } - - setTimeout(function() {content.evalScripts()}, 10); - }, - - contentFromAnonymousTable: function() { - var div = document.createElement('div'); - div.innerHTML = '' + this.content + '
    '; - return $A(div.childNodes[0].childNodes[0].childNodes); - } -} - -var Insertion = new Object(); - -Insertion.Before = Class.create(); -Insertion.Before.prototype = Object.extend(new Abstract.Insertion('beforeBegin'), { - initializeRange: function() { - this.range.setStartBefore(this.element); - }, - - insertContent: function(fragments) { - fragments.each((function(fragment) { - this.element.parentNode.insertBefore(fragment, this.element); - }).bind(this)); - } -}); - -Insertion.Top = Class.create(); -Insertion.Top.prototype = Object.extend(new Abstract.Insertion('afterBegin'), { - initializeRange: function() { - this.range.selectNodeContents(this.element); - this.range.collapse(true); - }, - - insertContent: function(fragments) { - fragments.reverse(false).each((function(fragment) { - this.element.insertBefore(fragment, this.element.firstChild); - }).bind(this)); - } -}); - -Insertion.Bottom = Class.create(); -Insertion.Bottom.prototype = Object.extend(new Abstract.Insertion('beforeEnd'), { - initializeRange: function() { - this.range.selectNodeContents(this.element); - this.range.collapse(this.element); - }, - - insertContent: function(fragments) { - fragments.each((function(fragment) { - this.element.appendChild(fragment); - }).bind(this)); - } -}); - -Insertion.After = Class.create(); -Insertion.After.prototype = Object.extend(new Abstract.Insertion('afterEnd'), { - initializeRange: function() { - this.range.setStartAfter(this.element); - }, - - insertContent: function(fragments) { - fragments.each((function(fragment) { - this.element.parentNode.insertBefore(fragment, - this.element.nextSibling); - }).bind(this)); - } -}); - -/*--------------------------------------------------------------------------*/ - -Element.ClassNames = Class.create(); -Element.ClassNames.prototype = { - initialize: function(element) { - this.element = $(element); - }, - - _each: function(iterator) { - this.element.className.split(/\s+/).select(function(name) { - return name.length > 0; - })._each(iterator); - }, - - set: function(className) { - this.element.className = className; - }, - - add: function(classNameToAdd) { - if (this.include(classNameToAdd)) return; - this.set(this.toArray().concat(classNameToAdd).join(' ')); - }, - - remove: function(classNameToRemove) { - if (!this.include(classNameToRemove)) return; - this.set(this.select(function(className) { - return className != classNameToRemove; - }).join(' ')); - }, - - toString: function() { - return this.toArray().join(' '); - } -} - -Object.extend(Element.ClassNames.prototype, Enumerable); -var Selector = Class.create(); -Selector.prototype = { - initialize: function(expression) { - this.params = {classNames: []}; - this.expression = expression.toString().strip(); - this.parseExpression(); - this.compileMatcher(); - }, - - parseExpression: function() { - function abort(message) { throw 'Parse error in selector: ' + message; } - - if (this.expression == '') abort('empty expression'); - - var params = this.params, expr = this.expression, match, modifier, clause, rest; - while (match = expr.match(/^(.*)\[([a-z0-9_:-]+?)(?:([~\|!]?=)(?:"([^"]*)"|([^\]\s]*)))?\]$/i)) { - params.attributes = params.attributes || []; - params.attributes.push({name: match[2], operator: match[3], value: match[4] || match[5] || ''}); - expr = match[1]; - } - - if (expr == '*') return this.params.wildcard = true; - - while (match = expr.match(/^([^a-z0-9_-])?([a-z0-9_-]+)(.*)/i)) { - modifier = match[1], clause = match[2], rest = match[3]; - switch (modifier) { - case '#': params.id = clause; break; - case '.': params.classNames.push(clause); break; - case '': - case undefined: params.tagName = clause.toUpperCase(); break; - default: abort(expr.inspect()); - } - expr = rest; - } - - if (expr.length > 0) abort(expr.inspect()); - }, - - buildMatchExpression: function() { - var params = this.params, conditions = [], clause; - - if (params.wildcard) - conditions.push('true'); - if (clause = params.id) - conditions.push('element.id == ' + clause.inspect()); - if (clause = params.tagName) - conditions.push('element.tagName.toUpperCase() == ' + clause.inspect()); - if ((clause = params.classNames).length > 0) - for (var i = 0; i < clause.length; i++) - conditions.push('Element.hasClassName(element, ' + clause[i].inspect() + ')'); - if (clause = params.attributes) { - clause.each(function(attribute) { - var value = 'element.getAttribute(' + attribute.name.inspect() + ')'; - var splitValueBy = function(delimiter) { - return value + ' && ' + value + '.split(' + delimiter.inspect() + ')'; - } - - switch (attribute.operator) { - case '=': conditions.push(value + ' == ' + attribute.value.inspect()); break; - case '~=': conditions.push(splitValueBy(' ') + '.include(' + attribute.value.inspect() + ')'); break; - case '|=': conditions.push( - splitValueBy('-') + '.first().toUpperCase() == ' + attribute.value.toUpperCase().inspect() - ); break; - case '!=': conditions.push(value + ' != ' + attribute.value.inspect()); break; - case '': - case undefined: conditions.push(value + ' != null'); break; - default: throw 'Unknown operator ' + attribute.operator + ' in selector'; - } - }); - } - - return conditions.join(' && '); - }, - - compileMatcher: function() { - this.match = new Function('element', 'if (!element.tagName) return false; \ - return ' + this.buildMatchExpression()); - }, - - findElements: function(scope) { - var element; - - if (element = $(this.params.id)) - if (this.match(element)) - if (!scope || Element.childOf(element, scope)) - return [element]; - - scope = (scope || document).getElementsByTagName(this.params.tagName || '*'); - - var results = []; - for (var i = 0; i < scope.length; i++) - if (this.match(element = scope[i])) - results.push(Element.extend(element)); - - return results; - }, - - toString: function() { - return this.expression; - } -} - -function $$() { - return $A(arguments).map(function(expression) { - return expression.strip().split(/\s+/).inject([null], function(results, expr) { - var selector = new Selector(expr); - return results.map(selector.findElements.bind(selector)).flatten(); - }); - }).flatten(); -} -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 (var 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 || opt.text; - } - return [element.name, value]; - }, - - selectMany: function(element) { - var value = []; - for (var i = 0; i < element.length; i++) { - var opt = element.options[i]; - if (opt.selected) - value.push(opt.value || opt.text); - } - 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 */ -if (navigator.appVersion.match(/\bMSIE\b/)) - 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 Modified: kukit/kukit.js/trunk/kukit/plugin.js ============================================================================== --- kukit/kukit.js/trunk/kukit/plugin.js (original) +++ kukit/kukit.js/trunk/kukit/plugin.js Tue Sep 5 17:55:45 2006 @@ -461,34 +461,4 @@ kukit.cr.commandRegistry.registerFromAction('copyChildNodesFrom', kukit.cr.makeSelectorCommand, 'copyChildrenFrom'); kukit.cr.commandRegistry.registerFromAction('copyChildNodesTo', kukit.cr.makeSelectorCommand, 'copyChildrenTo'); kukit.cr.commandRegistry.registerFromAction('setStateVar', kukit.cr.makeGlobalCommand, 'setStatevar'); - - -// Scriptaculous Effects - -try { - var dummy = Effect.transitions; - kukit.HASEFFECTS = 1; -} catch(e) { - kukit.HASEFFECTS = 0; -} - -if (kukit.HASEFFECTS) { - kukit.ar.actionRegistry.register("effect", function (oper) { - oper.completeParms([], {'type': 'fade'}, 'scriptaculous effect'); - var node = oper.node; - if (oper.parms.type == 'fade') { - Effect.Fade(node); - } else if (oper.parms.type == 'appear') { - Effect.Appear(node); - } else if (oper.parms.type == 'puff') { - Effect.Puff(node); - } else if (oper.parms.type == 'blinddown') { - Effect.BlindDown(node); - } else if (oper.parms.type == 'blindup') { - Effect.BlindUp(node); - } - }); - - kukit.cr.commandRegistry.registerFromAction('effect', kukit.cr.makeSelectorCommand); - -} + From reebalazs at codespeak.net Tue Sep 5 17:56:00 2006 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Tue, 5 Sep 2006 17:56:00 +0200 (CEST) Subject: [Kukit-checkins] r32017 - in kukit/azax/trunk: . pluginregistry plugins plugins/core plugins/effects plugins/effects/3rd_party plugins/effects/browser Message-ID: <20060905155600.7D21C1007E@code0.codespeak.net> Author: reebalazs Date: Tue Sep 5 17:55:55 2006 New Revision: 32017 Added: kukit/azax/trunk/plugins/ kukit/azax/trunk/plugins/README kukit/azax/trunk/plugins/__init__.py kukit/azax/trunk/plugins/configure.zcml kukit/azax/trunk/plugins/core/ kukit/azax/trunk/plugins/core/README kukit/azax/trunk/plugins/core/__init__.py kukit/azax/trunk/plugins/core/configure.zcml kukit/azax/trunk/plugins/effects/ kukit/azax/trunk/plugins/effects/3rd_party/ kukit/azax/trunk/plugins/effects/3rd_party/effects.js - copied unchanged from r32011, kukit/kukit.js/trunk/3rd_party/effects.js kukit/azax/trunk/plugins/effects/3rd_party/prototype.js - copied unchanged from r32011, kukit/kukit.js/trunk/3rd_party/prototype.js kukit/azax/trunk/plugins/effects/__init__.py kukit/azax/trunk/plugins/effects/browser/ kukit/azax/trunk/plugins/effects/browser/plugin.js kukit/azax/trunk/plugins/effects/configure.zcml Modified: kukit/azax/trunk/configure.zcml kukit/azax/trunk/pluginregistry/configure.zcml kukit/azax/trunk/pluginregistry/registry.py Log: Refactor core plugins Modified: kukit/azax/trunk/configure.zcml ============================================================================== --- kukit/azax/trunk/configure.zcml (original) +++ kukit/azax/trunk/configure.zcml Tue Sep 5 17:55:55 2006 @@ -5,22 +5,21 @@ - + + - + + + + + - - + + @@ -8,299 +7,4 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - /> - - - - - - - - - - - - - - - - - Modified: kukit/azax/trunk/pluginregistry/registry.py ============================================================================== --- kukit/azax/trunk/pluginregistry/registry.py (original) +++ kukit/azax/trunk/pluginregistry/registry.py Tue Sep 5 17:55:55 2006 @@ -37,7 +37,7 @@ 'Register a plugin' # register the plugin if self.isRegistered(plugin.plugintype, plugin.name): - raise AzaxPluginError, 'Duplicate registration attempt for plugin "%s" of type "%s"' % (self.name, self.plugintype) + raise AzaxPluginError, 'Duplicate registration attempt for plugin "%s" of type "%s"' % (plugin.name, plugin.plugintype) plugins_for_class = self.plugins[plugin.plugintype] plugins_for_class[plugin.name] = plugin # register jsfile Added: kukit/azax/trunk/plugins/README ============================================================================== --- (empty file) +++ kukit/azax/trunk/plugins/README Tue Sep 5 17:55:55 2006 @@ -0,0 +1,5 @@ + +These packages are distributed with the kukit core, however they can +be individually toggled from the configure.zcml, or also configured +as standalone python packages. + Added: kukit/azax/trunk/plugins/__init__.py ============================================================================== --- (empty file) +++ kukit/azax/trunk/plugins/__init__.py Tue Sep 5 17:55:55 2006 @@ -0,0 +1,4 @@ +'''\ +Module init +''' + Added: kukit/azax/trunk/plugins/configure.zcml ============================================================================== --- (empty file) +++ kukit/azax/trunk/plugins/configure.zcml Tue Sep 5 17:55:55 2006 @@ -0,0 +1,16 @@ + + + + + + + + + + + Added: kukit/azax/trunk/plugins/core/README ============================================================================== --- (empty file) +++ kukit/azax/trunk/plugins/core/README Tue Sep 5 17:55:55 2006 @@ -0,0 +1,4 @@ + +The core plugins have a missing browser directory as +the plugins are included in kukit/kukit.js. + Added: kukit/azax/trunk/plugins/core/__init__.py ============================================================================== --- (empty file) +++ kukit/azax/trunk/plugins/core/__init__.py Tue Sep 5 17:55:55 2006 @@ -0,0 +1,4 @@ +'''\ +Module init +''' + Added: kukit/azax/trunk/plugins/core/configure.zcml ============================================================================== --- (empty file) +++ kukit/azax/trunk/plugins/core/configure.zcml Tue Sep 5 17:55:55 2006 @@ -0,0 +1,296 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + /> + + + + + + + + + + + + + + + + + + Added: kukit/azax/trunk/plugins/effects/__init__.py ============================================================================== --- (empty file) +++ kukit/azax/trunk/plugins/effects/__init__.py Tue Sep 5 17:55:55 2006 @@ -0,0 +1,4 @@ +'''\ +Module init +''' + Added: kukit/azax/trunk/plugins/effects/browser/plugin.js ============================================================================== --- (empty file) +++ kukit/azax/trunk/plugins/effects/browser/plugin.js Tue Sep 5 17:55:55 2006 @@ -0,0 +1,30 @@ + +// Scriptaculous Effects + +try { + var dummy = Effect.transitions; + kukit.HASEFFECTS = 1; +} catch(e) { + kukit.HASEFFECTS = 0; +} + +if (kukit.HASEFFECTS) { + kukit.ar.actionRegistry.register("effect", function (oper) { + oper.completeParms([], {'type': 'fade'}, 'scriptaculous effect'); + var node = oper.node; + if (oper.parms.type == 'fade') { + Effect.Fade(node); + } else if (oper.parms.type == 'appear') { + Effect.Appear(node); + } else if (oper.parms.type == 'puff') { + Effect.Puff(node); + } else if (oper.parms.type == 'blinddown') { + Effect.BlindDown(node); + } else if (oper.parms.type == 'blindup') { + Effect.BlindUp(node); + } + }); + + kukit.cr.commandRegistry.registerFromAction('effect', kukit.cr.makeSelectorCommand); + +} Added: kukit/azax/trunk/plugins/effects/configure.zcml ============================================================================== --- (empty file) +++ kukit/azax/trunk/plugins/effects/configure.zcml Tue Sep 5 17:55:55 2006 @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + From reebalazs at codespeak.net Tue Sep 5 19:09:22 2006 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Tue, 5 Sep 2006 19:09:22 +0200 (CEST) Subject: [Kukit-checkins] r32023 - in kukit/azaxdemo/branch/zope2.8: . browser Message-ID: <20060905170922.0672E1007C@code0.codespeak.net> Author: reebalazs Date: Tue Sep 5 19:09:20 2006 New Revision: 32023 Added: kukit/azaxdemo/branch/zope2.8/browser/azax_effects.kss kukit/azaxdemo/branch/zope2.8/browser/azax_effects.pt Modified: kukit/azaxdemo/branch/zope2.8/azaxview.py kukit/azaxdemo/branch/zope2.8/browser/azax_demo_index.pt kukit/azaxdemo/branch/zope2.8/browser/header_macros.pt kukit/azaxdemo/branch/zope2.8/configure.zcml kukit/azaxdemo/branch/zope2.8/simplecontent.py Log: Merged from trunk Modified: kukit/azaxdemo/branch/zope2.8/azaxview.py ============================================================================== --- kukit/azaxdemo/branch/zope2.8/azaxview.py (original) +++ kukit/azaxdemo/branch/zope2.8/azaxview.py Tue Sep 5 19:09:20 2006 @@ -153,3 +153,8 @@ retval = force_unicode(''.join(result), 'utf') self.replaceInnerHTML('div#async', retval) return self.render() + + def reset(self): + self.effect('.effects', 'appear') + return self.render() + Modified: kukit/azaxdemo/branch/zope2.8/browser/azax_demo_index.pt ============================================================================== --- kukit/azaxdemo/branch/zope2.8/browser/azax_demo_index.pt (original) +++ kukit/azaxdemo/branch/zope2.8/browser/azax_demo_index.pt Tue Sep 5 19:09:20 2006 @@ -13,6 +13,7 @@
  • More complex selectors
  • Master-slave selects revisited
  • Form submit
  • +
  • Effects
  • Added: kukit/azaxdemo/branch/zope2.8/browser/azax_effects.kss ============================================================================== --- (empty file) +++ kukit/azaxdemo/branch/zope2.8/browser/azax_effects.kss Tue Sep 5 19:09:20 2006 @@ -0,0 +1,9 @@ +.effects:click { + action-client: effect; + effect-type: nodeAttr('id'); +} + +input#resetEffects:click { + action-server: resetEffects; +} + Added: kukit/azaxdemo/branch/zope2.8/browser/azax_effects.pt ============================================================================== --- (empty file) +++ kukit/azaxdemo/branch/zope2.8/browser/azax_effects.pt Tue Sep 5 19:09:20 2006 @@ -0,0 +1,27 @@ + + + + + + + +

    All demos

    +

    Start logging pane

    +

    View KSS resource

    +

    Effects

    + +

    Demo

    +
    Click here to make me fade
    +
    Click here to make me puff
    +
    Click here to make me blindup
    + + + Modified: kukit/azaxdemo/branch/zope2.8/browser/header_macros.pt ============================================================================== --- kukit/azaxdemo/branch/zope2.8/browser/header_macros.pt (original) +++ kukit/azaxdemo/branch/zope2.8/browser/header_macros.pt Tue Sep 5 19:09:20 2006 @@ -14,7 +14,15 @@ src="++resource++MochiKit.js"> + +
    Modified: kukit/azaxdemo/branch/zope2.8/configure.zcml ============================================================================== --- kukit/azaxdemo/branch/zope2.8/configure.zcml (original) +++ kukit/azaxdemo/branch/zope2.8/configure.zcml Tue Sep 5 19:09:20 2006 @@ -321,4 +321,25 @@ /> + + + + + + + Modified: kukit/azaxdemo/branch/zope2.8/simplecontent.py ============================================================================== --- kukit/azaxdemo/branch/zope2.8/simplecontent.py (original) +++ kukit/azaxdemo/branch/zope2.8/simplecontent.py Tue Sep 5 19:09:20 2006 @@ -29,6 +29,10 @@ meta_type = 'AzaxDemo SimpleContent' security = ClassSecurityInfo() + manage_options = ( + {'label':'Demos', 'action':''}, + ) + SimpleItem.manage_options + def __init__(self, id, title): self.id = id self.title = title From reebalazs at codespeak.net Tue Sep 5 18:56:40 2006 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Tue, 5 Sep 2006 18:56:40 +0200 (CEST) Subject: [Kukit-checkins] r32022 - in kukit/azax/branch/zope2.8: . pluginregistry plugins plugins/core plugins/effects plugins/effects/3rd_party plugins/effects/browser Message-ID: <20060905165640.6F5461007C@code0.codespeak.net> Author: reebalazs Date: Tue Sep 5 18:56:31 2006 New Revision: 32022 Added: kukit/azax/branch/zope2.8/concatresource.zcml kukit/azax/branch/zope2.8/pluginregistry/ - copied from r32017, kukit/azax/branch/zope2.8/plugins/ kukit/azax/branch/zope2.8/plugins/ kukit/azax/branch/zope2.8/plugins/README kukit/azax/branch/zope2.8/plugins/__init__.py kukit/azax/branch/zope2.8/plugins/configure.zcml kukit/azax/branch/zope2.8/plugins/core/ kukit/azax/branch/zope2.8/plugins/core/README kukit/azax/branch/zope2.8/plugins/core/__init__.py kukit/azax/branch/zope2.8/plugins/core/configure.zcml kukit/azax/branch/zope2.8/plugins/effects/ kukit/azax/branch/zope2.8/plugins/effects/3rd_party/ kukit/azax/branch/zope2.8/plugins/effects/3rd_party/effects.js kukit/azax/branch/zope2.8/plugins/effects/3rd_party/prototype.js kukit/azax/branch/zope2.8/plugins/effects/__init__.py kukit/azax/branch/zope2.8/plugins/effects/browser/ kukit/azax/branch/zope2.8/plugins/effects/browser/plugin.js kukit/azax/branch/zope2.8/plugins/effects/configure.zcml Modified: kukit/azax/branch/zope2.8/commands.py kukit/azax/branch/zope2.8/configure.zcml kukit/azax/branch/zope2.8/meta.zcml kukit/azax/branch/zope2.8/pluginregistry/configure.zcml kukit/azax/branch/zope2.8/pluginregistry/registry.py Log: Merge from trunk Modified: kukit/azax/branch/zope2.8/commands.py ============================================================================== --- kukit/azax/branch/zope2.8/commands.py (original) +++ kukit/azax/branch/zope2.8/commands.py Tue Sep 5 18:56:31 2006 @@ -28,7 +28,7 @@ from zope.interface import implements from zope.app.pagetemplate.viewpagetemplatefile import ViewPageTemplateFile from interfaces import IAzaxCommands, IAzaxCommand, IAzaxParam -import plugins +import pluginregistry from unicode_quirks import force_unicode from zope.interface import Interface import zope.component @@ -143,6 +143,11 @@ for key, value in kw.iteritems(): command.addParam(key, value) + def effect(self, selector, type): + """ see interfaces.py """ + command = self.addCommand('effect', selector) + data = command.addParam('type', type) + # XXX Deprecated ones def moveChildrenTo(self, selector, id): @@ -184,7 +189,7 @@ implements(IAzaxCommand) def __init__(self, command_name, selector=None, **kw): - if plugins.Command.isRegistered(command_name): + if pluginregistry.Command.isRegistered(command_name): # ok. XXX this will be deprecated # All registerCommand commands are obsolete, by default import warnings, textwrap @@ -192,14 +197,14 @@ The usage of the kss command "%s" is deprecated''' % (command_name, )), DeprecationWarning, 2) else: - plugins.Action.checkRegisteredCommand(command_name) + pluginregistry.Action.checkRegisteredCommand(command_name) if selector is not None: if isinstance(selector, basestring): # the default selector - given just as a string self.selector = selector self.selectorType = '' else: - plugins.SelectorType.checkRegistered(selector.type) + pluginregistry.SelectorType.checkRegistered(selector.type) self.selector = selector.value self.selectorType = selector.type else: Added: kukit/azax/branch/zope2.8/concatresource.zcml ============================================================================== --- (empty file) +++ kukit/azax/branch/zope2.8/concatresource.zcml Tue Sep 5 18:56:31 2006 @@ -0,0 +1,37 @@ + + + + + + Modified: kukit/azax/branch/zope2.8/configure.zcml ============================================================================== --- kukit/azax/branch/zope2.8/configure.zcml (original) +++ kukit/azax/branch/zope2.8/configure.zcml Tue Sep 5 18:56:31 2006 @@ -3,37 +3,24 @@ xmlns:five="http://namespaces.zope.org/five"> - + + + + + + + + + + - - - - + + + - + Modified: kukit/azax/branch/zope2.8/pluginregistry/configure.zcml ============================================================================== --- kukit/azax/branch/zope2.8/plugins/configure.zcml (original) +++ kukit/azax/branch/zope2.8/pluginregistry/configure.zcml Tue Sep 5 18:56:31 2006 @@ -1,298 +1,8 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - /> - - - - - - - - - - - - - - - - - Modified: kukit/azax/branch/zope2.8/pluginregistry/registry.py ============================================================================== --- kukit/azax/branch/zope2.8/plugins/registry.py (original) +++ kukit/azax/branch/zope2.8/pluginregistry/registry.py Tue Sep 5 18:56:31 2006 @@ -38,7 +38,7 @@ 'Register a plugin' # register the plugin if self.isRegistered(plugin.plugintype, plugin.name): - raise AzaxPluginError, 'Duplicate registration attempt for plugin "%s" of type "%s"' % (self.name, self.plugintype) + raise AzaxPluginError, 'Duplicate registration attempt for plugin "%s" of type "%s"' % (plugin.name, plugin.plugintype) plugins_for_class = self.plugins[plugin.plugintype] plugins_for_class[plugin.name] = plugin # register jsfile Added: kukit/azax/branch/zope2.8/plugins/README ============================================================================== --- (empty file) +++ kukit/azax/branch/zope2.8/plugins/README Tue Sep 5 18:56:31 2006 @@ -0,0 +1,5 @@ + +These packages are distributed with the kukit core, however they can +be individually toggled from the configure.zcml, or also configured +as standalone python packages. + Added: kukit/azax/branch/zope2.8/plugins/__init__.py ============================================================================== --- (empty file) +++ kukit/azax/branch/zope2.8/plugins/__init__.py Tue Sep 5 18:56:31 2006 @@ -0,0 +1,4 @@ +'''\ +Module init +''' + Added: kukit/azax/branch/zope2.8/plugins/configure.zcml ============================================================================== --- (empty file) +++ kukit/azax/branch/zope2.8/plugins/configure.zcml Tue Sep 5 18:56:31 2006 @@ -0,0 +1,16 @@ + + + + + + + + + + + Added: kukit/azax/branch/zope2.8/plugins/core/README ============================================================================== --- (empty file) +++ kukit/azax/branch/zope2.8/plugins/core/README Tue Sep 5 18:56:31 2006 @@ -0,0 +1,4 @@ + +The core plugins have a missing browser directory as +the plugins are included in kukit/kukit.js. + Added: kukit/azax/branch/zope2.8/plugins/core/__init__.py ============================================================================== --- (empty file) +++ kukit/azax/branch/zope2.8/plugins/core/__init__.py Tue Sep 5 18:56:31 2006 @@ -0,0 +1,4 @@ +'''\ +Module init +''' + Added: kukit/azax/branch/zope2.8/plugins/core/configure.zcml ============================================================================== --- (empty file) +++ kukit/azax/branch/zope2.8/plugins/core/configure.zcml Tue Sep 5 18:56:31 2006 @@ -0,0 +1,296 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + /> + + + + + + + + + + + + + + + + + + Added: kukit/azax/branch/zope2.8/plugins/effects/3rd_party/effects.js ============================================================================== --- (empty file) +++ kukit/azax/branch/zope2.8/plugins/effects/3rd_party/effects.js Tue Sep 5 18:56:31 2006 @@ -0,0 +1,958 @@ +// Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) +// Contributors: +// Justin Palmer (http://encytemedia.com/) +// Mark Pilgrim (http://diveintomark.org/) +// Martin Bialasinki +// +// See scriptaculous.js for full license. + +// converts rgb() and #xxx to #xxxxxx format, +// returns self (or first argument) if not convertable +String.prototype.parseColor = function() { + var color = '#'; + if(this.slice(0,4) == 'rgb(') { + var cols = this.slice(4,this.length-1).split(','); + var i=0; do { color += parseInt(cols[i]).toColorPart() } while (++i<3); + } else { + if(this.slice(0,1) == '#') { + if(this.length==4) for(var i=1;i<4;i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase(); + if(this.length==7) color = this.toLowerCase(); + } + } + return(color.length==7 ? color : (arguments[0] || this)); +} + +/*--------------------------------------------------------------------------*/ + +Element.collectTextNodes = function(element) { + return $A($(element).childNodes).collect( function(node) { + return (node.nodeType==3 ? node.nodeValue : + (node.hasChildNodes() ? Element.collectTextNodes(node) : '')); + }).flatten().join(''); +} + +Element.collectTextNodesIgnoreClass = function(element, className) { + return $A($(element).childNodes).collect( function(node) { + return (node.nodeType==3 ? node.nodeValue : + ((node.hasChildNodes() && !Element.hasClassName(node,className)) ? + Element.collectTextNodesIgnoreClass(node, className) : '')); + }).flatten().join(''); +} + +Element.setContentZoom = function(element, percent) { + element = $(element); + Element.setStyle(element, {fontSize: (percent/100) + 'em'}); + if(navigator.appVersion.indexOf('AppleWebKit')>0) window.scrollBy(0,0); +} + +Element.getOpacity = function(element){ + var opacity; + if (opacity = Element.getStyle(element, 'opacity')) + return parseFloat(opacity); + if (opacity = (Element.getStyle(element, 'filter') || '').match(/alpha\(opacity=(.*)\)/)) + if(opacity[1]) return parseFloat(opacity[1]) / 100; + return 1.0; +} + +Element.setOpacity = function(element, value){ + element= $(element); + if (value == 1){ + Element.setStyle(element, { opacity: + (/Gecko/.test(navigator.userAgent) && !/Konqueror|Safari|KHTML/.test(navigator.userAgent)) ? + 0.999999 : null }); + if(/MSIE/.test(navigator.userAgent)) + Element.setStyle(element, {filter: Element.getStyle(element,'filter').replace(/alpha\([^\)]*\)/gi,'')}); + } else { + if(value < 0.00001) value = 0; + Element.setStyle(element, {opacity: value}); + if(/MSIE/.test(navigator.userAgent)) + Element.setStyle(element, + { filter: Element.getStyle(element,'filter').replace(/alpha\([^\)]*\)/gi,'') + + 'alpha(opacity='+value*100+')' }); + } +} + +Element.getInlineOpacity = function(element){ + return $(element).style.opacity || ''; +} + +Element.childrenWithClassName = function(element, className, findFirst) { + var classNameRegExp = new RegExp("(^|\\s)" + className + "(\\s|$)"); + var results = $A($(element).getElementsByTagName('*'))[findFirst ? 'detect' : 'select']( function(c) { + return (c.className && c.className.match(classNameRegExp)); + }); + if(!results) results = []; + return results; +} + +Element.forceRerendering = function(element) { + try { + element = $(element); + var n = document.createTextNode(' '); + element.appendChild(n); + element.removeChild(n); + } catch(e) { } +}; + +/*--------------------------------------------------------------------------*/ + +Array.prototype.call = function() { + var args = arguments; + this.each(function(f){ f.apply(this, args) }); +} + +/*--------------------------------------------------------------------------*/ + +var Effect = { + tagifyText: function(element) { + var tagifyStyle = 'position:relative'; + if(/MSIE/.test(navigator.userAgent)) tagifyStyle += ';zoom:1'; + element = $(element); + $A(element.childNodes).each( function(child) { + if(child.nodeType==3) { + child.nodeValue.toArray().each( function(character) { + element.insertBefore( + Builder.node('span',{style: tagifyStyle}, + character == ' ' ? String.fromCharCode(160) : character), + child); + }); + Element.remove(child); + } + }); + }, + multiple: function(element, effect) { + var elements; + if(((typeof element == 'object') || + (typeof element == 'function')) && + (element.length)) + elements = element; + else + elements = $(element).childNodes; + + var options = Object.extend({ + speed: 0.1, + delay: 0.0 + }, arguments[2] || {}); + var masterDelay = options.delay; + + $A(elements).each( function(element, index) { + new effect(element, Object.extend(options, { delay: index * options.speed + masterDelay })); + }); + }, + PAIRS: { + 'slide': ['SlideDown','SlideUp'], + 'blind': ['BlindDown','BlindUp'], + 'appear': ['Appear','Fade'] + }, + toggle: function(element, effect) { + element = $(element); + effect = (effect || 'appear').toLowerCase(); + var options = Object.extend({ + queue: { position:'end', scope:(element.id || 'global'), limit: 1 } + }, arguments[2] || {}); + Effect[element.visible() ? + Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options); + } +}; + +var Effect2 = Effect; // deprecated + +/* ------------- transitions ------------- */ + +Effect.Transitions = {} + +Effect.Transitions.linear = function(pos) { + return pos; +} +Effect.Transitions.sinoidal = function(pos) { + return (-Math.cos(pos*Math.PI)/2) + 0.5; +} +Effect.Transitions.reverse = function(pos) { + return 1-pos; +} +Effect.Transitions.flicker = function(pos) { + return ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random()/4; +} +Effect.Transitions.wobble = function(pos) { + return (-Math.cos(pos*Math.PI*(9*pos))/2) + 0.5; +} +Effect.Transitions.pulse = function(pos) { + return (Math.floor(pos*10) % 2 == 0 ? + (pos*10-Math.floor(pos*10)) : 1-(pos*10-Math.floor(pos*10))); +} +Effect.Transitions.none = function(pos) { + return 0; +} +Effect.Transitions.full = function(pos) { + return 1; +} + +/* ------------- core effects ------------- */ + +Effect.ScopedQueue = Class.create(); +Object.extend(Object.extend(Effect.ScopedQueue.prototype, Enumerable), { + initialize: function() { + this.effects = []; + this.interval = null; + }, + _each: function(iterator) { + this.effects._each(iterator); + }, + add: function(effect) { + var timestamp = new Date().getTime(); + + var position = (typeof effect.options.queue == 'string') ? + effect.options.queue : effect.options.queue.position; + + switch(position) { + case 'front': + // move unstarted effects after this effect + this.effects.findAll(function(e){ return e.state=='idle' }).each( function(e) { + e.startOn += effect.finishOn; + e.finishOn += effect.finishOn; + }); + break; + case 'end': + // start effect after last queued effect has finished + timestamp = this.effects.pluck('finishOn').max() || timestamp; + break; + } + + effect.startOn += timestamp; + effect.finishOn += timestamp; + + if(!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit)) + this.effects.push(effect); + + if(!this.interval) + this.interval = setInterval(this.loop.bind(this), 40); + }, + remove: function(effect) { + this.effects = this.effects.reject(function(e) { return e==effect }); + if(this.effects.length == 0) { + clearInterval(this.interval); + this.interval = null; + } + }, + loop: function() { + var timePos = new Date().getTime(); + this.effects.invoke('loop', timePos); + } +}); + +Effect.Queues = { + instances: $H(), + get: function(queueName) { + if(typeof queueName != 'string') return queueName; + + if(!this.instances[queueName]) + this.instances[queueName] = new Effect.ScopedQueue(); + + return this.instances[queueName]; + } +} +Effect.Queue = Effect.Queues.get('global'); + +Effect.DefaultOptions = { + transition: Effect.Transitions.sinoidal, + duration: 1.0, // seconds + fps: 25.0, // max. 25fps due to Effect.Queue implementation + sync: false, // true for combining + from: 0.0, + to: 1.0, + delay: 0.0, + queue: 'parallel' +} + +Effect.Base = function() {}; +Effect.Base.prototype = { + position: null, + start: function(options) { + this.options = Object.extend(Object.extend({},Effect.DefaultOptions), options || {}); + this.currentFrame = 0; + this.state = 'idle'; + this.startOn = this.options.delay*1000; + this.finishOn = this.startOn + (this.options.duration*1000); + this.event('beforeStart'); + if(!this.options.sync) + Effect.Queues.get(typeof this.options.queue == 'string' ? + 'global' : this.options.queue.scope).add(this); + }, + loop: function(timePos) { + if(timePos >= this.startOn) { + if(timePos >= this.finishOn) { + this.render(1.0); + this.cancel(); + this.event('beforeFinish'); + if(this.finish) this.finish(); + this.event('afterFinish'); + return; + } + var pos = (timePos - this.startOn) / (this.finishOn - this.startOn); + var frame = Math.round(pos * this.options.fps * this.options.duration); + if(frame > this.currentFrame) { + this.render(pos); + this.currentFrame = frame; + } + } + }, + render: function(pos) { + if(this.state == 'idle') { + this.state = 'running'; + this.event('beforeSetup'); + if(this.setup) this.setup(); + this.event('afterSetup'); + } + if(this.state == 'running') { + if(this.options.transition) pos = this.options.transition(pos); + pos *= (this.options.to-this.options.from); + pos += this.options.from; + this.position = pos; + this.event('beforeUpdate'); + if(this.update) this.update(pos); + this.event('afterUpdate'); + } + }, + cancel: function() { + if(!this.options.sync) + Effect.Queues.get(typeof this.options.queue == 'string' ? + 'global' : this.options.queue.scope).remove(this); + this.state = 'finished'; + }, + event: function(eventName) { + if(this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this); + if(this.options[eventName]) this.options[eventName](this); + }, + inspect: function() { + return '#'; + } +} + +Effect.Parallel = Class.create(); +Object.extend(Object.extend(Effect.Parallel.prototype, Effect.Base.prototype), { + initialize: function(effects) { + this.effects = effects || []; + this.start(arguments[1]); + }, + update: function(position) { + this.effects.invoke('render', position); + }, + finish: function(position) { + this.effects.each( function(effect) { + effect.render(1.0); + effect.cancel(); + effect.event('beforeFinish'); + if(effect.finish) effect.finish(position); + effect.event('afterFinish'); + }); + } +}); + +Effect.Opacity = Class.create(); +Object.extend(Object.extend(Effect.Opacity.prototype, Effect.Base.prototype), { + initialize: function(element) { + this.element = $(element); + // make this work on IE on elements without 'layout' + if(/MSIE/.test(navigator.userAgent) && (!this.element.hasLayout)) + this.element.setStyle({zoom: 1}); + var options = Object.extend({ + from: this.element.getOpacity() || 0.0, + to: 1.0 + }, arguments[1] || {}); + this.start(options); + }, + update: function(position) { + this.element.setOpacity(position); + } +}); + +Effect.Move = Class.create(); +Object.extend(Object.extend(Effect.Move.prototype, Effect.Base.prototype), { + initialize: function(element) { + this.element = $(element); + var options = Object.extend({ + x: 0, + y: 0, + mode: 'relative' + }, arguments[1] || {}); + this.start(options); + }, + setup: function() { + // Bug in Opera: Opera returns the "real" position of a static element or + // relative element that does not have top/left explicitly set. + // ==> Always set top and left for position relative elements in your stylesheets + // (to 0 if you do not need them) + this.element.makePositioned(); + this.originalLeft = parseFloat(this.element.getStyle('left') || '0'); + this.originalTop = parseFloat(this.element.getStyle('top') || '0'); + if(this.options.mode == 'absolute') { + // absolute movement, so we need to calc deltaX and deltaY + this.options.x = this.options.x - this.originalLeft; + this.options.y = this.options.y - this.originalTop; + } + }, + update: function(position) { + this.element.setStyle({ + left: this.options.x * position + this.originalLeft + 'px', + top: this.options.y * position + this.originalTop + 'px' + }); + } +}); + +// for backwards compatibility +Effect.MoveBy = function(element, toTop, toLeft) { + return new Effect.Move(element, + Object.extend({ x: toLeft, y: toTop }, arguments[3] || {})); +}; + +Effect.Scale = Class.create(); +Object.extend(Object.extend(Effect.Scale.prototype, Effect.Base.prototype), { + initialize: function(element, percent) { + this.element = $(element) + var options = Object.extend({ + scaleX: true, + scaleY: true, + scaleContent: true, + scaleFromCenter: false, + scaleMode: 'box', // 'box' or 'contents' or {} with provided values + scaleFrom: 100.0, + scaleTo: percent + }, arguments[2] || {}); + this.start(options); + }, + setup: function() { + this.restoreAfterFinish = this.options.restoreAfterFinish || false; + this.elementPositioning = this.element.getStyle('position'); + + this.originalStyle = {}; + ['top','left','width','height','fontSize'].each( function(k) { + this.originalStyle[k] = this.element.style[k]; + }.bind(this)); + + this.originalTop = this.element.offsetTop; + this.originalLeft = this.element.offsetLeft; + + var fontSize = this.element.getStyle('font-size') || '100%'; + ['em','px','%'].each( function(fontSizeType) { + if(fontSize.indexOf(fontSizeType)>0) { + this.fontSize = parseFloat(fontSize); + this.fontSizeType = fontSizeType; + } + }.bind(this)); + + this.factor = (this.options.scaleTo - this.options.scaleFrom)/100; + + this.dims = null; + if(this.options.scaleMode=='box') + this.dims = [this.element.offsetHeight, this.element.offsetWidth]; + if(/^content/.test(this.options.scaleMode)) + this.dims = [this.element.scrollHeight, this.element.scrollWidth]; + if(!this.dims) + this.dims = [this.options.scaleMode.originalHeight, + this.options.scaleMode.originalWidth]; + }, + update: function(position) { + var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position); + if(this.options.scaleContent && this.fontSize) + this.element.setStyle({fontSize: this.fontSize * currentScale + this.fontSizeType }); + this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale); + }, + finish: function(position) { + if (this.restoreAfterFinish) this.element.setStyle(this.originalStyle); + }, + setDimensions: function(height, width) { + var d = {}; + if(this.options.scaleX) d.width = width + 'px'; + if(this.options.scaleY) d.height = height + 'px'; + if(this.options.scaleFromCenter) { + var topd = (height - this.dims[0])/2; + var leftd = (width - this.dims[1])/2; + if(this.elementPositioning == 'absolute') { + if(this.options.scaleY) d.top = this.originalTop-topd + 'px'; + if(this.options.scaleX) d.left = this.originalLeft-leftd + 'px'; + } else { + if(this.options.scaleY) d.top = -topd + 'px'; + if(this.options.scaleX) d.left = -leftd + 'px'; + } + } + this.element.setStyle(d); + } +}); + +Effect.Highlight = Class.create(); +Object.extend(Object.extend(Effect.Highlight.prototype, Effect.Base.prototype), { + initialize: function(element) { + this.element = $(element); + var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || {}); + this.start(options); + }, + setup: function() { + // Prevent executing on elements not in the layout flow + if(this.element.getStyle('display')=='none') { this.cancel(); return; } + // Disable background image during the effect + this.oldStyle = { + backgroundImage: this.element.getStyle('background-image') }; + this.element.setStyle({backgroundImage: 'none'}); + if(!this.options.endcolor) + this.options.endcolor = this.element.getStyle('background-color').parseColor('#ffffff'); + if(!this.options.restorecolor) + this.options.restorecolor = this.element.getStyle('background-color'); + // init color calculations + this._base = $R(0,2).map(function(i){ return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16) }.bind(this)); + this._delta = $R(0,2).map(function(i){ return parseInt(this.options.endcolor.slice(i*2+1,i*2+3),16)-this._base[i] }.bind(this)); + }, + update: function(position) { + this.element.setStyle({backgroundColor: $R(0,2).inject('#',function(m,v,i){ + return m+(Math.round(this._base[i]+(this._delta[i]*position)).toColorPart()); }.bind(this)) }); + }, + finish: function() { + this.element.setStyle(Object.extend(this.oldStyle, { + backgroundColor: this.options.restorecolor + })); + } +}); + +Effect.ScrollTo = Class.create(); +Object.extend(Object.extend(Effect.ScrollTo.prototype, Effect.Base.prototype), { + initialize: function(element) { + this.element = $(element); + this.start(arguments[1] || {}); + }, + setup: function() { + Position.prepare(); + var offsets = Position.cumulativeOffset(this.element); + if(this.options.offset) offsets[1] += this.options.offset; + var max = window.innerHeight ? + window.height - window.innerHeight : + document.body.scrollHeight - + (document.documentElement.clientHeight ? + document.documentElement.clientHeight : document.body.clientHeight); + this.scrollStart = Position.deltaY; + this.delta = (offsets[1] > max ? max : offsets[1]) - this.scrollStart; + }, + update: function(position) { + Position.prepare(); + window.scrollTo(Position.deltaX, + this.scrollStart + (position*this.delta)); + } +}); + +/* ------------- combination effects ------------- */ + +Effect.Fade = function(element) { + element = $(element); + var oldOpacity = element.getInlineOpacity(); + var options = Object.extend({ + from: element.getOpacity() || 1.0, + to: 0.0, + afterFinishInternal: function(effect) { + if(effect.options.to!=0) return; + effect.element.hide(); + effect.element.setStyle({opacity: oldOpacity}); + }}, arguments[1] || {}); + return new Effect.Opacity(element,options); +} + +Effect.Appear = function(element) { + element = $(element); + var options = Object.extend({ + from: (element.getStyle('display') == 'none' ? 0.0 : element.getOpacity() || 0.0), + to: 1.0, + // force Safari to render floated elements properly + afterFinishInternal: function(effect) { + effect.element.forceRerendering(); + }, + beforeSetup: function(effect) { + effect.element.setOpacity(effect.options.from); + effect.element.show(); + }}, arguments[1] || {}); + return new Effect.Opacity(element,options); +} + +Effect.Puff = function(element) { + element = $(element); + var oldStyle = { opacity: element.getInlineOpacity(), position: element.getStyle('position') }; + return new Effect.Parallel( + [ new Effect.Scale(element, 200, + { sync: true, scaleFromCenter: true, scaleContent: true, restoreAfterFinish: true }), + new Effect.Opacity(element, { sync: true, to: 0.0 } ) ], + Object.extend({ duration: 1.0, + beforeSetupInternal: function(effect) { + effect.effects[0].element.setStyle({position: 'absolute'}); }, + afterFinishInternal: function(effect) { + effect.effects[0].element.hide(); + effect.effects[0].element.setStyle(oldStyle); } + }, arguments[1] || {}) + ); +} + +Effect.BlindUp = function(element) { + element = $(element); + element.makeClipping(); + return new Effect.Scale(element, 0, + Object.extend({ scaleContent: false, + scaleX: false, + restoreAfterFinish: true, + afterFinishInternal: function(effect) { + effect.element.hide(); + effect.element.undoClipping(); + } + }, arguments[1] || {}) + ); +} + +Effect.BlindDown = function(element) { + element = $(element); + var elementDimensions = element.getDimensions(); + return new Effect.Scale(element, 100, + Object.extend({ scaleContent: false, + scaleX: false, + scaleFrom: 0, + scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, + restoreAfterFinish: true, + afterSetup: function(effect) { + effect.element.makeClipping(); + effect.element.setStyle({height: '0px'}); + effect.element.show(); + }, + afterFinishInternal: function(effect) { + effect.element.undoClipping(); + } + }, arguments[1] || {}) + ); +} + +Effect.SwitchOff = function(element) { + element = $(element); + var oldOpacity = element.getInlineOpacity(); + return new Effect.Appear(element, { + duration: 0.4, + from: 0, + transition: Effect.Transitions.flicker, + afterFinishInternal: function(effect) { + new Effect.Scale(effect.element, 1, { + duration: 0.3, scaleFromCenter: true, + scaleX: false, scaleContent: false, restoreAfterFinish: true, + beforeSetup: function(effect) { + effect.element.makePositioned(); + effect.element.makeClipping(); + }, + afterFinishInternal: function(effect) { + effect.element.hide(); + effect.element.undoClipping(); + effect.element.undoPositioned(); + effect.element.setStyle({opacity: oldOpacity}); + } + }) + } + }); +} + +Effect.DropOut = function(element) { + element = $(element); + var oldStyle = { + top: element.getStyle('top'), + left: element.getStyle('left'), + opacity: element.getInlineOpacity() }; + return new Effect.Parallel( + [ new Effect.Move(element, {x: 0, y: 100, sync: true }), + new Effect.Opacity(element, { sync: true, to: 0.0 }) ], + Object.extend( + { duration: 0.5, + beforeSetup: function(effect) { + effect.effects[0].element.makePositioned(); + }, + afterFinishInternal: function(effect) { + effect.effects[0].element.hide(); + effect.effects[0].element.undoPositioned(); + effect.effects[0].element.setStyle(oldStyle); + } + }, arguments[1] || {})); +} + +Effect.Shake = function(element) { + element = $(element); + var oldStyle = { + top: element.getStyle('top'), + left: element.getStyle('left') }; + return new Effect.Move(element, + { x: 20, y: 0, duration: 0.05, afterFinishInternal: function(effect) { + new Effect.Move(effect.element, + { x: -40, y: 0, duration: 0.1, afterFinishInternal: function(effect) { + new Effect.Move(effect.element, + { x: 40, y: 0, duration: 0.1, afterFinishInternal: function(effect) { + new Effect.Move(effect.element, + { x: -40, y: 0, duration: 0.1, afterFinishInternal: function(effect) { + new Effect.Move(effect.element, + { x: 40, y: 0, duration: 0.1, afterFinishInternal: function(effect) { + new Effect.Move(effect.element, + { x: -20, y: 0, duration: 0.05, afterFinishInternal: function(effect) { + effect.element.undoPositioned(); + effect.element.setStyle(oldStyle); + }}) }}) }}) }}) }}) }}); +} + +Effect.SlideDown = function(element) { + element = $(element); + element.cleanWhitespace(); + // SlideDown need to have the content of the element wrapped in a container element with fixed height! + var oldInnerBottom = $(element.firstChild).getStyle('bottom'); + var elementDimensions = element.getDimensions(); + return new Effect.Scale(element, 100, Object.extend({ + scaleContent: false, + scaleX: false, + scaleFrom: window.opera ? 0 : 1, + scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, + restoreAfterFinish: true, + afterSetup: function(effect) { + effect.element.makePositioned(); + effect.element.firstChild.makePositioned(); + if(window.opera) effect.element.setStyle({top: ''}); + effect.element.makeClipping(); + effect.element.setStyle({height: '0px'}); + effect.element.show(); }, + afterUpdateInternal: function(effect) { + effect.element.firstChild.setStyle({bottom: + (effect.dims[0] - effect.element.clientHeight) + 'px' }); + }, + afterFinishInternal: function(effect) { + effect.element.undoClipping(); + // IE will crash if child is undoPositioned first + if(/MSIE/.test(navigator.userAgent)){ + effect.element.undoPositioned(); + effect.element.firstChild.undoPositioned(); + }else{ + effect.element.firstChild.undoPositioned(); + effect.element.undoPositioned(); + } + effect.element.firstChild.setStyle({bottom: oldInnerBottom}); } + }, arguments[1] || {}) + ); +} + +Effect.SlideUp = function(element) { + element = $(element); + element.cleanWhitespace(); + var oldInnerBottom = $(element.firstChild).getStyle('bottom'); + return new Effect.Scale(element, window.opera ? 0 : 1, + Object.extend({ scaleContent: false, + scaleX: false, + scaleMode: 'box', + scaleFrom: 100, + restoreAfterFinish: true, + beforeStartInternal: function(effect) { + effect.element.makePositioned(); + effect.element.firstChild.makePositioned(); + if(window.opera) effect.element.setStyle({top: ''}); + effect.element.makeClipping(); + effect.element.show(); }, + afterUpdateInternal: function(effect) { + effect.element.firstChild.setStyle({bottom: + (effect.dims[0] - effect.element.clientHeight) + 'px' }); }, + afterFinishInternal: function(effect) { + effect.element.hide(); + effect.element.undoClipping(); + effect.element.firstChild.undoPositioned(); + effect.element.undoPositioned(); + effect.element.setStyle({bottom: oldInnerBottom}); } + }, arguments[1] || {}) + ); +} + +// Bug in opera makes the TD containing this element expand for a instance after finish +Effect.Squish = function(element) { + return new Effect.Scale(element, window.opera ? 1 : 0, + { restoreAfterFinish: true, + beforeSetup: function(effect) { + effect.element.makeClipping(effect.element); }, + afterFinishInternal: function(effect) { + effect.element.hide(effect.element); + effect.element.undoClipping(effect.element); } + }); +} + +Effect.Grow = function(element) { + element = $(element); + var options = Object.extend({ + direction: 'center', + moveTransition: Effect.Transitions.sinoidal, + scaleTransition: Effect.Transitions.sinoidal, + opacityTransition: Effect.Transitions.full + }, arguments[1] || {}); + var oldStyle = { + top: element.style.top, + left: element.style.left, + height: element.style.height, + width: element.style.width, + opacity: element.getInlineOpacity() }; + + var dims = element.getDimensions(); + var initialMoveX, initialMoveY; + var moveX, moveY; + + switch (options.direction) { + case 'top-left': + initialMoveX = initialMoveY = moveX = moveY = 0; + break; + case 'top-right': + initialMoveX = dims.width; + initialMoveY = moveY = 0; + moveX = -dims.width; + break; + case 'bottom-left': + initialMoveX = moveX = 0; + initialMoveY = dims.height; + moveY = -dims.height; + break; + case 'bottom-right': + initialMoveX = dims.width; + initialMoveY = dims.height; + moveX = -dims.width; + moveY = -dims.height; + break; + case 'center': + initialMoveX = dims.width / 2; + initialMoveY = dims.height / 2; + moveX = -dims.width / 2; + moveY = -dims.height / 2; + break; + } + + return new Effect.Move(element, { + x: initialMoveX, + y: initialMoveY, + duration: 0.01, + beforeSetup: function(effect) { + effect.element.hide(); + effect.element.makeClipping(); + effect.element.makePositioned(); + }, + afterFinishInternal: function(effect) { + new Effect.Parallel( + [ new Effect.Opacity(effect.element, { sync: true, to: 1.0, from: 0.0, transition: options.opacityTransition }), + new Effect.Move(effect.element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }), + new Effect.Scale(effect.element, 100, { + scaleMode: { originalHeight: dims.height, originalWidth: dims.width }, + sync: true, scaleFrom: window.opera ? 1 : 0, transition: options.scaleTransition, restoreAfterFinish: true}) + ], Object.extend({ + beforeSetup: function(effect) { + effect.effects[0].element.setStyle({height: '0px'}); + effect.effects[0].element.show(); + }, + afterFinishInternal: function(effect) { + effect.effects[0].element.undoClipping(); + effect.effects[0].element.undoPositioned(); + effect.effects[0].element.setStyle(oldStyle); + } + }, options) + ) + } + }); +} + +Effect.Shrink = function(element) { + element = $(element); + var options = Object.extend({ + direction: 'center', + moveTransition: Effect.Transitions.sinoidal, + scaleTransition: Effect.Transitions.sinoidal, + opacityTransition: Effect.Transitions.none + }, arguments[1] || {}); + var oldStyle = { + top: element.style.top, + left: element.style.left, + height: element.style.height, + width: element.style.width, + opacity: element.getInlineOpacity() }; + + var dims = element.getDimensions(); + var moveX, moveY; + + switch (options.direction) { + case 'top-left': + moveX = moveY = 0; + break; + case 'top-right': + moveX = dims.width; + moveY = 0; + break; + case 'bottom-left': + moveX = 0; + moveY = dims.height; + break; + case 'bottom-right': + moveX = dims.width; + moveY = dims.height; + break; + case 'center': + moveX = dims.width / 2; + moveY = dims.height / 2; + break; + } + + return new Effect.Parallel( + [ new Effect.Opacity(element, { sync: true, to: 0.0, from: 1.0, transition: options.opacityTransition }), + new Effect.Scale(element, window.opera ? 1 : 0, { sync: true, transition: options.scaleTransition, restoreAfterFinish: true}), + new Effect.Move(element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }) + ], Object.extend({ + beforeStartInternal: function(effect) { + effect.effects[0].element.makePositioned(); + effect.effects[0].element.makeClipping(); }, + afterFinishInternal: function(effect) { + effect.effects[0].element.hide(); + effect.effects[0].element.undoClipping(); + effect.effects[0].element.undoPositioned(); + effect.effects[0].element.setStyle(oldStyle); } + }, options) + ); +} + +Effect.Pulsate = function(element) { + element = $(element); + var options = arguments[1] || {}; + var oldOpacity = element.getInlineOpacity(); + var transition = options.transition || Effect.Transitions.sinoidal; + var reverser = function(pos){ return transition(1-Effect.Transitions.pulse(pos)) }; + reverser.bind(transition); + return new Effect.Opacity(element, + Object.extend(Object.extend({ duration: 3.0, from: 0, + afterFinishInternal: function(effect) { effect.element.setStyle({opacity: oldOpacity}); } + }, options), {transition: reverser})); +} + +Effect.Fold = function(element) { + element = $(element); + var oldStyle = { + top: element.style.top, + left: element.style.left, + width: element.style.width, + height: element.style.height }; + Element.makeClipping(element); + return new Effect.Scale(element, 5, Object.extend({ + scaleContent: false, + scaleX: false, + afterFinishInternal: function(effect) { + new Effect.Scale(element, 1, { + scaleContent: false, + scaleY: false, + afterFinishInternal: function(effect) { + effect.element.hide(); + effect.element.undoClipping(); + effect.element.setStyle(oldStyle); + } }); + }}, arguments[1] || {})); +}; + +['setOpacity','getOpacity','getInlineOpacity','forceRerendering','setContentZoom', + 'collectTextNodes','collectTextNodesIgnoreClass','childrenWithClassName'].each( + function(f) { Element.Methods[f] = Element[f]; } +); + +Element.Methods.visualEffect = function(element, effect, options) { + s = effect.gsub(/_/, '-').camelize(); + effect_class = s.charAt(0).toUpperCase() + s.substring(1); + new Effect[effect_class](element, options); + return $(element); +}; + +Element.addMethods(); \ No newline at end of file Added: kukit/azax/branch/zope2.8/plugins/effects/3rd_party/prototype.js ============================================================================== --- (empty file) +++ kukit/azax/branch/zope2.8/plugins/effects/3rd_party/prototype.js Tue Sep 5 18:56:31 2006 @@ -0,0 +1,2006 @@ +/* Prototype JavaScript framework, version 1.5.0_rc0 + * (c) 2005 Sam Stephenson + * + * Prototype is freely distributable under the terms of an MIT-style license. + * For details, see the Prototype web site: http://prototype.conio.net/ + * +/*--------------------------------------------------------------------------*/ + +var Prototype = { + Version: '1.5.0_rc0', + ScriptFragment: '(?:)((\n|\r|.)*?)(?:<\/script>)', + + emptyFunction: function() {}, + K: function(x) {return x} +} + +var Class = { + create: function() { + return function() { + this.initialize.apply(this, arguments); + } + } +} + +var Abstract = new Object(); + +Object.extend = function(destination, source) { + for (var 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; + } + } + } +} +Object.extend(String.prototype, { + gsub: function(pattern, replacement) { + var result = '', source = this, match; + replacement = arguments.callee.prepareReplacement(replacement); + + while (source.length > 0) { + if (match = source.match(pattern)) { + result += source.slice(0, match.index); + result += (replacement(match) || '').toString(); + source = source.slice(match.index + match[0].length); + } else { + result += source, source = ''; + } + } + return result; + }, + + sub: function(pattern, replacement, count) { + replacement = this.gsub.prepareReplacement(replacement); + count = count === undefined ? 1 : count; + + return this.gsub(pattern, function(match) { + if (--count < 0) return match[0]; + return replacement(match); + }); + }, + + scan: function(pattern, iterator) { + this.gsub(pattern, iterator); + return this; + }, + + truncate: function(length, truncation) { + length = length || 30; + truncation = truncation === undefined ? '...' : truncation; + return this.length > length ? + this.slice(0, length - truncation.length) + truncation : this; + }, + + strip: function() { + return this.replace(/^\s+/, '').replace(/\s+$/, ''); + }, + + 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(function(script) { return eval(script) }); + }, + + 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(/\\/g, '\\\\').replace(/'/g, '\\\'') + "'"; + } +}); + +String.prototype.gsub.prepareReplacement = function(replacement) { + if (typeof replacement == 'function') return replacement; + var template = new Template(replacement); + return function(match) { return template.evaluate(match) }; +} + +String.prototype.parseQuery = String.prototype.toQueryParams; + +var Template = Class.create(); +Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/; +Template.prototype = { + initialize: function(template, pattern) { + this.template = template.toString(); + this.pattern = pattern || Template.Pattern; + }, + + evaluate: function(object) { + return this.template.gsub(this.pattern, function(match) { + var before = match[1]; + if (before == '\\') return match[2]; + return before + (object[match[3]] || '').toString(); + }); + } +} + +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 (result == undefined || value >= result) + result = value; + }); + return result; + }, + + min: function(iterator) { + var result; + this.each(function(value, index) { + value = (iterator || Prototype.K)(value, index); + if (result == undefined || value < result) + 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) { + return iterator(collections.pluck(index)); + }); + }, + + inspect: function() { + return '#'; + } +} + +Object.extend(Enumerable, { + map: Enumerable.collect, + find: Enumerable.detect, + select: Enumerable.findAll, + member: Enumerable.include, + entries: Enumerable.toArray +}); +var $A = Array.from = function(iterable) { + if (!iterable) return []; + if (iterable.toArray) { + return iterable.toArray(); + } else { + var results = []; + for (var i = 0; i < iterable.length; i++) + results.push(iterable[i]); + return results; + } +} + +Object.extend(Array.prototype, Enumerable); + +if (!Array.prototype._reverse) + 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 && 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(); + }, + + inspect: function() { + return '[' + this.map(Object.inspect).join(', ') + ']'; + } +}); +var Hash = { + _each: function(iterator) { + for (var key in this) { + var value = this[key]; + if (typeof value == 'function') continue; + + var pair = [key, value]; + pair.key = key; + pair.value = value; + iterator(pair); + } + }, + + keys: function() { + return this.pluck('key'); + }, + + values: function() { + return this.pluck('value'); + }, + + merge: function(hash) { + return $H(hash).inject($H(this), function(mergedHash, pair) { + mergedHash[pair.key] = pair.value; + return mergedHash; + }); + }, + + toQueryString: function() { + return this.map(function(pair) { + return pair.map(encodeURIComponent).join('='); + }).join('&'); + }, + + inspect: function() { + return '#'; + } +} + +function $H(object) { + var hash = Object.extend({}, object || {}); + Object.extend(hash, Enumerable); + Object.extend(hash, Hash); + return hash; +} +ObjectRange = Class.create(); +Object.extend(ObjectRange.prototype, Enumerable); +Object.extend(ObjectRange.prototype, { + initialize: function(start, end, exclusive) { + this.start = start; + this.end = end; + this.exclusive = exclusive; + }, + + _each: function(iterator) { + var value = this.start; + do { + iterator(value); + value = value.succ(); + } while (this.include(value)); + }, + + include: function(value) { + if (value < this.start) + return false; + if (this.exclusive) + return value < this.end; + return value <= this.end; + } +}); + +var $R = function(start, end, exclusive) { + return new ObjectRange(start, end, exclusive); +} + +var Ajax = { + getTransport: function() { + return Try.these( + function() {return new XMLHttpRequest()}, + function() {return new ActiveXObject('Msxml2.XMLHTTP')}, + function() {return new ActiveXObject('Microsoft.XMLHTTP')} + ) || 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, + contentType: 'application/x-www-form-urlencoded', + 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, + 'Accept', 'text/javascript, text/html, application/xml, text/xml, */*']; + + if (this.options.method == 'post') { + requestHeaders.push('Content-type', this.options.contentType); + + /* 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); + } +}); +function $() { + var results = [], element; + for (var i = 0; i < arguments.length; i++) { + element = arguments[i]; + if (typeof element == 'string') + element = document.getElementById(element); + results.push(Element.extend(element)); + } + return results.length < 2 ? results[0] : results; +} + +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(Element.extend(child)); + return elements; + }); +} + +/*--------------------------------------------------------------------------*/ + +if (!window.Element) + var Element = new Object(); + +Element.extend = function(element) { + if (!element) return; + if (_nativeExtensions) return element; + + if (!element._extended && element.tagName && element != window) { + var methods = Element.Methods, cache = Element.extend.cache; + for (property in methods) { + var value = methods[property]; + if (typeof value == 'function') + element[property] = cache.findOrStore(value); + } + } + + element._extended = true; + return element; +} + +Element.extend.cache = { + findOrStore: function(value) { + return this[value] = this[value] || function() { + return value.apply(null, [this].concat($A(arguments))); + } + } +} + +Element.Methods = { + 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); + }, + + replace: function(element, html) { + element = $(element); + if (element.outerHTML) { + element.outerHTML = html.stripScripts(); + } else { + var range = element.ownerDocument.createRange(); + range.selectNodeContents(element); + element.parentNode.replaceChild( + range.createContextualFragment(html.stripScripts()), element); + } + 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*$/); + }, + + childOf: function(element, ancestor) { + element = $(element), ancestor = $(ancestor); + while (element = element.parentNode) + if (element == ancestor) return true; + return false; + }, + + 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 (var 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; + } +} + +Object.extend(Element, Element.Methods); + +var _nativeExtensions = false; + +if(!HTMLElement && /Konqueror|Safari|KHTML/.test(navigator.userAgent)) { + var HTMLElement = {} + HTMLElement.prototype = document.createElement('div').__proto__; +} + +Element.addMethods = function(methods) { + Object.extend(Element.Methods, methods || {}); + + if(typeof HTMLElement != 'undefined') { + var methods = Element.Methods, cache = Element.extend.cache; + for (property in methods) { + var value = methods[property]; + if (typeof value == 'function') + HTMLElement.prototype[property] = cache.findOrStore(value); + } + _nativeExtensions = true; + } +} + +Element.addMethods(); + +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) { + var tagName = this.element.tagName.toLowerCase(); + if (tagName == 'tbody' || tagName == 'tr') { + this.insertContent(this.contentFromAnonymousTable()); + } else { + throw e; + } + } + } else { + this.range = this.element.ownerDocument.createRange(); + if (this.initializeRange) this.initializeRange(); + this.insertContent([this.range.createContextualFragment(this.content)]); + } + + setTimeout(function() {content.evalScripts()}, 10); + }, + + contentFromAnonymousTable: function() { + var div = document.createElement('div'); + div.innerHTML = '' + this.content + '
    '; + return $A(div.childNodes[0].childNodes[0].childNodes); + } +} + +var Insertion = new Object(); + +Insertion.Before = Class.create(); +Insertion.Before.prototype = Object.extend(new Abstract.Insertion('beforeBegin'), { + initializeRange: function() { + this.range.setStartBefore(this.element); + }, + + insertContent: function(fragments) { + fragments.each((function(fragment) { + this.element.parentNode.insertBefore(fragment, this.element); + }).bind(this)); + } +}); + +Insertion.Top = Class.create(); +Insertion.Top.prototype = Object.extend(new Abstract.Insertion('afterBegin'), { + initializeRange: function() { + this.range.selectNodeContents(this.element); + this.range.collapse(true); + }, + + insertContent: function(fragments) { + fragments.reverse(false).each((function(fragment) { + this.element.insertBefore(fragment, this.element.firstChild); + }).bind(this)); + } +}); + +Insertion.Bottom = Class.create(); +Insertion.Bottom.prototype = Object.extend(new Abstract.Insertion('beforeEnd'), { + initializeRange: function() { + this.range.selectNodeContents(this.element); + this.range.collapse(this.element); + }, + + insertContent: function(fragments) { + fragments.each((function(fragment) { + this.element.appendChild(fragment); + }).bind(this)); + } +}); + +Insertion.After = Class.create(); +Insertion.After.prototype = Object.extend(new Abstract.Insertion('afterEnd'), { + initializeRange: function() { + this.range.setStartAfter(this.element); + }, + + insertContent: function(fragments) { + fragments.each((function(fragment) { + this.element.parentNode.insertBefore(fragment, + this.element.nextSibling); + }).bind(this)); + } +}); + +/*--------------------------------------------------------------------------*/ + +Element.ClassNames = Class.create(); +Element.ClassNames.prototype = { + initialize: function(element) { + this.element = $(element); + }, + + _each: function(iterator) { + this.element.className.split(/\s+/).select(function(name) { + return name.length > 0; + })._each(iterator); + }, + + set: function(className) { + this.element.className = className; + }, + + add: function(classNameToAdd) { + if (this.include(classNameToAdd)) return; + this.set(this.toArray().concat(classNameToAdd).join(' ')); + }, + + remove: function(classNameToRemove) { + if (!this.include(classNameToRemove)) return; + this.set(this.select(function(className) { + return className != classNameToRemove; + }).join(' ')); + }, + + toString: function() { + return this.toArray().join(' '); + } +} + +Object.extend(Element.ClassNames.prototype, Enumerable); +var Selector = Class.create(); +Selector.prototype = { + initialize: function(expression) { + this.params = {classNames: []}; + this.expression = expression.toString().strip(); + this.parseExpression(); + this.compileMatcher(); + }, + + parseExpression: function() { + function abort(message) { throw 'Parse error in selector: ' + message; } + + if (this.expression == '') abort('empty expression'); + + var params = this.params, expr = this.expression, match, modifier, clause, rest; + while (match = expr.match(/^(.*)\[([a-z0-9_:-]+?)(?:([~\|!]?=)(?:"([^"]*)"|([^\]\s]*)))?\]$/i)) { + params.attributes = params.attributes || []; + params.attributes.push({name: match[2], operator: match[3], value: match[4] || match[5] || ''}); + expr = match[1]; + } + + if (expr == '*') return this.params.wildcard = true; + + while (match = expr.match(/^([^a-z0-9_-])?([a-z0-9_-]+)(.*)/i)) { + modifier = match[1], clause = match[2], rest = match[3]; + switch (modifier) { + case '#': params.id = clause; break; + case '.': params.classNames.push(clause); break; + case '': + case undefined: params.tagName = clause.toUpperCase(); break; + default: abort(expr.inspect()); + } + expr = rest; + } + + if (expr.length > 0) abort(expr.inspect()); + }, + + buildMatchExpression: function() { + var params = this.params, conditions = [], clause; + + if (params.wildcard) + conditions.push('true'); + if (clause = params.id) + conditions.push('element.id == ' + clause.inspect()); + if (clause = params.tagName) + conditions.push('element.tagName.toUpperCase() == ' + clause.inspect()); + if ((clause = params.classNames).length > 0) + for (var i = 0; i < clause.length; i++) + conditions.push('Element.hasClassName(element, ' + clause[i].inspect() + ')'); + if (clause = params.attributes) { + clause.each(function(attribute) { + var value = 'element.getAttribute(' + attribute.name.inspect() + ')'; + var splitValueBy = function(delimiter) { + return value + ' && ' + value + '.split(' + delimiter.inspect() + ')'; + } + + switch (attribute.operator) { + case '=': conditions.push(value + ' == ' + attribute.value.inspect()); break; + case '~=': conditions.push(splitValueBy(' ') + '.include(' + attribute.value.inspect() + ')'); break; + case '|=': conditions.push( + splitValueBy('-') + '.first().toUpperCase() == ' + attribute.value.toUpperCase().inspect() + ); break; + case '!=': conditions.push(value + ' != ' + attribute.value.inspect()); break; + case '': + case undefined: conditions.push(value + ' != null'); break; + default: throw 'Unknown operator ' + attribute.operator + ' in selector'; + } + }); + } + + return conditions.join(' && '); + }, + + compileMatcher: function() { + this.match = new Function('element', 'if (!element.tagName) return false; \ + return ' + this.buildMatchExpression()); + }, + + findElements: function(scope) { + var element; + + if (element = $(this.params.id)) + if (this.match(element)) + if (!scope || Element.childOf(element, scope)) + return [element]; + + scope = (scope || document).getElementsByTagName(this.params.tagName || '*'); + + var results = []; + for (var i = 0; i < scope.length; i++) + if (this.match(element = scope[i])) + results.push(Element.extend(element)); + + return results; + }, + + toString: function() { + return this.expression; + } +} + +function $$() { + return $A(arguments).map(function(expression) { + return expression.strip().split(/\s+/).inject([null], function(results, expr) { + var selector = new Selector(expr); + return results.map(selector.findElements.bind(selector)).flatten(); + }); + }).flatten(); +} +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 (var 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 || opt.text; + } + return [element.name, value]; + }, + + selectMany: function(element) { + var value = []; + for (var i = 0; i < element.length; i++) { + var opt = element.options[i]; + if (opt.selected) + value.push(opt.value || opt.text); + } + 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 */ +if (navigator.appVersion.match(/\bMSIE\b/)) + 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 Added: kukit/azax/branch/zope2.8/plugins/effects/__init__.py ============================================================================== --- (empty file) +++ kukit/azax/branch/zope2.8/plugins/effects/__init__.py Tue Sep 5 18:56:31 2006 @@ -0,0 +1,4 @@ +'''\ +Module init +''' + Added: kukit/azax/branch/zope2.8/plugins/effects/browser/plugin.js ============================================================================== --- (empty file) +++ kukit/azax/branch/zope2.8/plugins/effects/browser/plugin.js Tue Sep 5 18:56:31 2006 @@ -0,0 +1,30 @@ + +// Scriptaculous Effects + +try { + var dummy = Effect.transitions; + kukit.HASEFFECTS = 1; +} catch(e) { + kukit.HASEFFECTS = 0; +} + +if (kukit.HASEFFECTS) { + kukit.ar.actionRegistry.register("effect", function (oper) { + oper.completeParms([], {'type': 'fade'}, 'scriptaculous effect'); + var node = oper.node; + if (oper.parms.type == 'fade') { + Effect.Fade(node); + } else if (oper.parms.type == 'appear') { + Effect.Appear(node); + } else if (oper.parms.type == 'puff') { + Effect.Puff(node); + } else if (oper.parms.type == 'blinddown') { + Effect.BlindDown(node); + } else if (oper.parms.type == 'blindup') { + Effect.BlindUp(node); + } + }); + + kukit.cr.commandRegistry.registerFromAction('effect', kukit.cr.makeSelectorCommand); + +} Added: kukit/azax/branch/zope2.8/plugins/effects/configure.zcml ============================================================================== --- (empty file) +++ kukit/azax/branch/zope2.8/plugins/effects/configure.zcml Tue Sep 5 18:56:31 2006 @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + From reebalazs at codespeak.net Wed Sep 6 11:46:04 2006 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Wed, 6 Sep 2006 11:46:04 +0200 (CEST) Subject: [Kukit-checkins] r32025 - kukit/azaxdemo/trunk/tests Message-ID: <20060906094604.C58611007F@code0.codespeak.net> Author: reebalazs Date: Wed Sep 6 11:46:02 2006 New Revision: 32025 Modified: kukit/azaxdemo/trunk/tests/test_azaxview.py Log: Fixing tests (new tests will be added via the new test harness) Modified: kukit/azaxdemo/trunk/tests/test_azaxview.py ============================================================================== --- kukit/azaxdemo/trunk/tests/test_azaxview.py (original) +++ kukit/azaxdemo/trunk/tests/test_azaxview.py Wed Sep 6 11:46:02 2006 @@ -21,35 +21,42 @@ import unittest, os from zope.testing import doctest from Testing.ZopeTestCase import ZopeTestCase - +from Products.azax.tests.test_azaxview import AzaxViewTestCase, FakeContent, TestRequest from Products.azaxdemo.azaxview import AzaxView +from Products.Five.zcml import load_string, load_config +import Products.azaxdemo -class FakeResponse: - _stuff = {} - - def setHeader(self, name, value): - self._stuff[name] = value - -class FakeRequest: - response = FakeResponse() - -class AzaxViewTestCase(ZopeTestCase): +class AzaxDemoTestCase(AzaxViewTestCase): + def afterSetUp(self): + AzaxViewTestCase.afterSetUp(self) + load_config('meta.zcml', package=Products.azaxdemo) + load_config('configure.zcml', package=Products.azaxdemo) + # fake content + # XXX This is a holy mess. Go go macro adapters! + fakecontent = FakeContent() + self.folder._delObject('ob') + self.folder._setObject('ob', fakecontent) + fakecontent = fakecontent.__of__(self.folder) + # Set up a fake view (with no content) + fakerequest = TestRequest() + self.view = AzaxView(fakecontent, fakerequest) def test_instanciation(self): - ob = AzaxView(None, None) - self.assertNotEquals(ob, None) - - def test_getDivContent(self): - req = FakeRequest() - - ob = AzaxView(None, req) - - res = ob.getDivContent() - self.assertEquals(res, 'div.clickableinnerHTML<h1>it worked</h1>') - + view = self.view + commands = view.getCommands() + self.assertNotEquals(view, None) + + # XXX Disable this test for now. The command responses should be + # tested by using a test infrastructure that supports easy checking + # of contents of commands. + def XXXtest_getDivContent(self): + view = self.view + commands = view.getCommands() + res = view.getDivContent() + self.assertEquals(res, 'div.clickablereplaceInnerHTML<h1>it worked</h1>') def test_suite(): return unittest.TestSuite(( - unittest.makeSuite(AzaxViewTestCase), + unittest.makeSuite(AzaxDemoTestCase), doctest.DocTestSuite('Products.azaxdemo.azaxview'), )) From reebalazs at codespeak.net Wed Sep 6 11:53:50 2006 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Wed, 6 Sep 2006 11:53:50 +0200 (CEST) Subject: [Kukit-checkins] r32026 - kukit/azaxdemo/branch/zope2.8/tests Message-ID: <20060906095350.CE0461007F@code0.codespeak.net> Author: reebalazs Date: Wed Sep 6 11:53:48 2006 New Revision: 32026 Modified: kukit/azaxdemo/branch/zope2.8/tests/test_azaxview.py Log: Merge from trunk (Fixing tests) Modified: kukit/azaxdemo/branch/zope2.8/tests/test_azaxview.py ============================================================================== --- kukit/azaxdemo/branch/zope2.8/tests/test_azaxview.py (original) +++ kukit/azaxdemo/branch/zope2.8/tests/test_azaxview.py Wed Sep 6 11:53:48 2006 @@ -21,35 +21,42 @@ import unittest, os from zope.testing import doctest from Testing.ZopeTestCase import ZopeTestCase - +from Products.azax.tests.test_azaxview import AzaxViewTestCase, FakeContent, TestRequest from Products.azaxdemo.azaxview import AzaxView +from Products.Five.zcml import load_string, load_config +import Products.azaxdemo -class FakeResponse: - _stuff = {} - - def setHeader(self, name, value): - self._stuff[name] = value - -class FakeRequest: - response = FakeResponse() - -class AzaxViewTestCase(ZopeTestCase): +class AzaxDemoTestCase(AzaxViewTestCase): + def afterSetUp(self): + AzaxViewTestCase.afterSetUp(self) + load_config('permissions.zcml', package=Products.Five) + load_config('configure.zcml', package=Products.azaxdemo) + # fake content + # XXX This is a holy mess. Go go macro adapters! + fakecontent = FakeContent() + self.folder._delObject('ob') + self.folder._setObject('ob', fakecontent) + fakecontent = fakecontent.__of__(self.folder) + # Set up a fake view (with no content) + fakerequest = TestRequest() + self.view = AzaxView(fakecontent, fakerequest) def test_instanciation(self): - ob = AzaxView(None, None) - self.assertNotEquals(ob, None) - - def test_getDivContent(self): - req = FakeRequest() - - ob = AzaxView(None, req) - - res = ob.getDivContent() - self.assertEquals(res, 'div.clickableinnerHTML<h1>it worked</h1>') - + view = self.view + commands = view.getCommands() + self.assertNotEquals(view, None) + + # XXX Disable this test for now. The command responses should be + # tested by using a test infrastructure that supports easy checking + # of contents of commands. + def XXXtest_getDivContent(self): + view = self.view + commands = view.getCommands() + res = view.getDivContent() + self.assertEquals(res, 'div.clickablereplaceInnerHTML<h1>it worked</h1>') def test_suite(): return unittest.TestSuite(( - unittest.makeSuite(AzaxViewTestCase), + unittest.makeSuite(AzaxDemoTestCase), doctest.DocTestSuite('Products.azaxdemo.azaxview'), )) From gotcha at codespeak.net Thu Sep 7 14:32:36 2006 From: gotcha at codespeak.net (gotcha at codespeak.net) Date: Thu, 7 Sep 2006 14:32:36 +0200 (CEST) Subject: [Kukit-checkins] r32048 - kukit/kukit.js/trunk/utils Message-ID: <20060907123236.2FC1F10072@code0.codespeak.net> Author: gotcha Date: Thu Sep 7 14:32:34 2006 New Revision: 32048 Added: kukit/kukit.js/trunk/utils/ kukit/kukit.js/trunk/utils/kss.vim Log: Vim syntax highlight Added: kukit/kukit.js/trunk/utils/kss.vim ============================================================================== --- (empty file) +++ kukit/kukit.js/trunk/utils/kss.vim Thu Sep 7 14:32:34 2006 @@ -0,0 +1,161 @@ +" Vim syntax file +" Language: Kukit Style Sheets +" Maintainer: Godefroid Chapelle + +" For version 5.x: Clear all syntax items +" For version 6.x: Quit when a syntax file was already loaded +if !exists("main_syntax") + if version < 600 + syntax clear + elseif exists("b:current_syntax") + finish +endif + let main_syntax = 'kss' +endif + +syn case ignore + +syn keyword cssTagName abbr acronym address applet area a b base +syn keyword cssTagName basefont bdo big blockquote body br button +syn keyword cssTagName caption center cite code col colgroup dd del +syn keyword cssTagName dfn dir div dl dt em fieldset font form frame +syn keyword cssTagName frameset h1 h2 h3 h4 h5 h6 head hr html img i +syn keyword cssTagName iframe img input ins isindex kbd label legend li +syn keyword cssTagName link map menu meta noframes noscript ol optgroup +syn keyword cssTagName option p param pre q s samp script select small +syn keyword cssTagName span strike strong style sub sup tbody td +syn keyword cssTagName textarea tfoot th thead title tr tt ul u var +syn match cssTagName "\" +syn match cssTagName "\*" + +syn match cssTagName "@page\>" nextgroup=cssDefinition + +syn match cssSelectorOp "[+>.]" +syn match cssSelectorOp2 "[~|]\?=" contained +syn region cssAttributeSelector matchgroup=cssSelectorOp start="\[" end="]" transparent contains=cssUnicodeEscape,cssSelectorOp2,cssStringQ,cssStringQQ + +try +syn match cssHtmlIdentifier "#[A-Za-z?-?_@][A-Za-z?-?0-9_ at -]*" +syn match cssIdentifier "[A-Za-z?-?_@][A-Za-z?-?0-9_ at -]*" +catch /^.*/ +syn match cssHtmlIdentifier "#[A-Za-z_@][A-Za-z0-9_ at -]*" +syn match cssIdentifier "[A-Za-z_@][A-Za-z0-9_ at -]*" +endtry + + +syn match cssValueInteger contained "[-+]\=\d\+" +syn match cssValueNumber contained "[-+]\=\d\+\(\.\d*\)\=" + +syn match cssUnicodeRange contained "U+[0-9A-Fa-f?]\+" +syn match cssUnicodeRange contained "U+\x\+-\x\+" + +" syn case match +syn region cssURL contained matchgroup=kssFunctionName start="\" + +syn case ignore + +" TODO not implemented in KSS +"syn keyword cssUIProp contained cursor +"syn match cssUIProp contained "\" +"syn match cssUIAttr contained "\<[ns]\=[ew]\=-resize\>" +"syn keyword cssUIAttr contained default crosshair pointer move wait help +"syn keyword cssUIAttr contained thin thick +"syn keyword cssUIAttr contained dotted dashed solid double groove ridge inset outset +"syn keyword cssUIAttr contained invert + +syn region cssInclude start="@import" end=";" contains=cssComment,cssURL,cssUnicodeEscape +syn match cssBraces contained "[{}]" +syn match cssError contained "{@<>" +syn region cssDefinition transparent matchgroup=cssBraces start='{' end='}' contains=cssComment,kssNameValue,cssValue.*,cssURL,cssError,cssStringQ,cssStringQQ,cssUnicodeEscape +syn match cssBraceError "}" + +syn match kssEventPseudoClass ":\S*" contains=kssEvent +syn match kssEvent "\S*" contained contains=kssEventId,kssEventInstance,cssUnicodeEscape +syn match kssEventInstance "([^)]\+)" contained transparent contains=cssIdentifier + +syn match kssNameValue "[^:]\+:[^;]\+;" contains=kssName,cssValue.*,kssFunction,cssStringQQ,cssStringQ +syn match kssName "[^-]\+-\([^-]\+-\)*[^-:]\+" contained nextgroup=cssValue.* contains=kssActionKeyword,kssEventKeyword,kssEventId,kssActionLocation,cssIdentifier +syn keyword kssEventKeyword evt nextgroup=kssEventId +syn keyword kssActionKeyword action nextgroup=kssActionLocation + + +syn keyword kssEventId contained click blur focus resize dblclick mousedown mouseup +syn keyword kssEventId contained mousemove mouseover mouseout change reset select +syn keyword kssEventId contained submit keydown keypress keyup timeout load + +syn keyword kssActionLocation contained server client + +syn region cssComment start="/\*" end="\*/" + +syn match cssUnicodeEscape "\\\x\{1,6}\s\?" +syn match cssSpecialCharQQ +\\"+ contained +syn match cssSpecialCharQ +\\'+ contained +syn region cssStringQQ start=+"+ skip=+\\\\\|\\"+ end=+"+ contains=cssUnicodeEscape,cssSpecialCharQQ +syn region cssStringQ start=+'+ skip=+\\\\\|\\'+ end=+'+ contains=cssUnicodeEscape,cssSpecialCharQ + +if main_syntax == "css" + syn sync minlines=10 +endif + +" Define the default highlighting. +" For version 5.7 and earlier: only when not done already +" For version 5.8 and later: only when an item doesn't have highlighting yet +if version >= 508 || !exists("did_css_syn_inits") + if version < 508 + let did_css_syn_inits = 1 + command -nargs=+ HiLink hi link + else + command -nargs=+ HiLink hi def link + endif + + HiLink cssComment Comment + HiLink cssTagName Statement + HiLink cssSelectorOp Special + HiLink cssSelectorOp2 Special +" HiLink cssUIProp StorageClass +" HiLink cssUIAttr Type + HiLink kssEvent Statement + HiLink kssEventId Constant + HiLink kssActionLocation Preproc + HiLink kssActionKeyword Type + HiLink kssEventKeyword Type + HiLink kssEvent Normal + HiLink kssName Type + HiLink cssValueLength Number + HiLink cssValueInteger Number + HiLink cssValueNumber Number + HiLink cssValueAngle Number + HiLink cssValueTime Number + HiLink cssValueFrequency Number + HiLink cssURL String + HiLink kssFunctionName Function + HiLink cssHtmlIdentifier Function + HiLink cssIdentifier Normal + HiLink cssInclude Include +" HiLink cssImportant Special + HiLink cssBraces Function + HiLink cssBraceError Error + HiLink cssError Error + HiLink cssInclude Include + HiLink cssUnicodeEscape Special + HiLink cssStringQQ String + HiLink cssStringQ String + HiLink cssUnicodeRange Constant + delcommand HiLink +endif + +let b:current_syntax = "kss" + +if main_syntax == 'kss' + unlet main_syntax +endif + + +" vim: ts=8 + From reebalazs at codespeak.net Sat Sep 9 20:19:50 2006 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Sat, 9 Sep 2006 20:19:50 +0200 (CEST) Subject: [Kukit-checkins] r32109 - kukit/kukit.js/trunk/tests Message-ID: <20060909181950.2CA8410083@code0.codespeak.net> Author: reebalazs Date: Sat Sep 9 20:19:47 2006 New Revision: 32109 Added: kukit/kukit.js/trunk/tests/testStyleParse.js - copied, changed from r32073, kukit/azax/trunk/tests/js/testStyleParse.js Modified: kukit/kukit.js/trunk/tests/runner.html kukit/kukit.js/trunk/tests/test_kssparser.js kukit/kukit.js/trunk/tests/test_tokenizer.js kukit/kukit.js/trunk/tests/test_utils.js kukit/kukit.js/trunk/tests/unittestUtilities.js Log: Making ecma unittests runnable from publisher Modified: kukit/kukit.js/trunk/tests/runner.html ============================================================================== --- kukit/kukit.js/trunk/tests/runner.html (original) +++ kukit/kukit.js/trunk/tests/runner.html Sat Sep 9 20:19:47 2006 @@ -1,5 +1,8 @@ - + + - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + +

    - Plone ECMAScript Unit Tests + KSS ECMAScript Unit Tests

    This page is the entry to the ECMAScript Unit Tests.

    +

    + Tests are running from the filesystem. +

    +
    Suite filter:
    -
    -
      -
      -
      +
      +
      +
      +
      +
      +
      Copied: kukit/kukit.js/trunk/tests/testStyleParse.js (from r32073, kukit/azax/trunk/tests/js/testStyleParse.js) ============================================================================== --- kukit/azax/trunk/tests/js/testStyleParse.js (original) +++ kukit/kukit.js/trunk/tests/testStyleParse.js Sat Sep 9 20:19:47 2006 @@ -1,3 +1,6 @@ +/* XXX This is totally out-of-date now, but + we may want to do something like this later. */ + function RuleParseTestCase() { this.name = 'RuleParseTestCase'; } Modified: kukit/kukit.js/trunk/tests/test_kssparser.js ============================================================================== --- kukit/kukit.js/trunk/tests/test_kssparser.js (original) +++ kukit/kukit.js/trunk/tests/test_kssparser.js Sat Sep 9 20:19:47 2006 @@ -2,7 +2,7 @@ * Copyright (c) 2005-2006 * Authors: * Martin Heidegger -* Bal?zs Re? +* Balazs Ree * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as published Modified: kukit/kukit.js/trunk/tests/test_tokenizer.js ============================================================================== --- kukit/kukit.js/trunk/tests/test_tokenizer.js (original) +++ kukit/kukit.js/trunk/tests/test_tokenizer.js Sat Sep 9 20:19:47 2006 @@ -2,7 +2,7 @@ * Copyright (c) 2005-2006 * Authors: * Martin Heidegger -* Bal?zs Re? +* Balazs Ree * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as published Modified: kukit/kukit.js/trunk/tests/test_utils.js ============================================================================== --- kukit/kukit.js/trunk/tests/test_utils.js (original) +++ kukit/kukit.js/trunk/tests/test_utils.js Sat Sep 9 20:19:47 2006 @@ -1,7 +1,7 @@ /* * Copyright (c) 2005-2006 * Authors: -* Bal?zs Re? +* Balazs Ree * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as published Modified: kukit/kukit.js/trunk/tests/unittestUtilities.js ============================================================================== --- kukit/kukit.js/trunk/tests/unittestUtilities.js (original) +++ kukit/kukit.js/trunk/tests/unittestUtilities.js Sat Sep 9 20:19:47 2006 @@ -88,7 +88,7 @@ // create toc element var toc_item = document.createElement("li"); - toc_item.appendChild(createLink("../runner.html#"+name, name+" Results", false)); + toc_item.appendChild(createLink("./runner.html#"+name, name+" Results", false)); toc.appendChild(toc_item); // append testcase section @@ -125,8 +125,8 @@ var test_filter = document.getElementById('test-filter').value; testcase_registry.setTestSuiteFilter(suite_filter); testcase_registry.setTestFilter(test_filter); - putTextInPlaceHolder(testcase_registry.getFilteredTestSuitNames() + - testcase_registry.getFilteredTestNames()); + putTextInPlaceHolder('Suits: [' + testcase_registry.getFilteredTestSuitNames().join(', ') + + '], Tests: [' + testcase_registry.getFilteredTestNames().join(', ') + ']'); } function showMarkup() { From reebalazs at codespeak.net Sat Sep 9 20:20:05 2006 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Sat, 9 Sep 2006 20:20:05 +0200 (CEST) Subject: [Kukit-checkins] r32110 - in kukit/azax/trunk: . tests tests/js Message-ID: <20060909182005.D010710083@code0.codespeak.net> Author: reebalazs Date: Sat Sep 9 20:20:03 2006 New Revision: 32110 Added: kukit/azax/trunk/tests/configure.zcml kukit/azax/trunk/tests/testview.py Removed: kukit/azax/trunk/tests/js/ Modified: kukit/azax/trunk/configure.zcml Log: Making ecma unittests runnable from publisher Modified: kukit/azax/trunk/configure.zcml ============================================================================== --- kukit/azax/trunk/configure.zcml (original) +++ kukit/azax/trunk/configure.zcml Sat Sep 9 20:20:03 2006 @@ -2,65 +2,46 @@ xmlns:browser="http://namespaces.zope.org/browser" xmlns:five="http://namespaces.zope.org/five"> - - + + - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + - + + + + + - + /> Added: kukit/azax/trunk/tests/configure.zcml ============================================================================== --- (empty file) +++ kukit/azax/trunk/tests/configure.zcml Sat Sep 9 20:20:03 2006 @@ -0,0 +1,15 @@ + + + + + + + Added: kukit/azax/trunk/tests/testview.py ============================================================================== --- (empty file) +++ kukit/azax/trunk/tests/testview.py Sat Sep 9 20:20:03 2006 @@ -0,0 +1,148 @@ +# Authors: +# Godefroid Chapelle +# Balazs Ree +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as published +# by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. +# + +try: + from Products.Five import BrowserView +except ImportError: + from zope.app.publisher.browser import BrowserView + +from zope.interface import Interface, implements +from zope.app import zapi +from zope.app.pagetemplate.viewpagetemplatefile import ViewPageTemplateFile +import os.path +from zope.publisher.interfaces.browser import IBrowserPublisher +from zope.publisher.interfaces import NotFound + +# Oh well... file resource has different import locations in zope and five, +# the factories take different parameters order, +# plus these are not "entirely clean" as far as caching is concerned... +# Instead, use the resources implemented from concatresource: +# this is version free and has properly implemented cache control. +try: + from azax.pluginregistry._concatresource.resource import ConcatResourceFactory +except ImportError: + from Products.azax.pluginregistry._concatresource.resource import ConcatResourceFactory + +_marker = object() + +# z3 only +from zope.security.checker import CheckerPublic, NamesChecker +allowed_names = ('GET', 'HEAD', 'publishTraverse', 'browserDefault', + 'request', '__call__') +permission = CheckerPublic +checker = NamesChecker(allowed_names, permission) + +class ViewFile(object): + '''A wrapper for file resources that can be used in a view + + Similar to ViewPageTemplate in usage. + (We only use the FileResource here, no distinction on content types + like in the resourceDirectory code.) + ''' + + def __init__(self, name, path): + # Create the resource with cache control most proper for debugging. + self.resource_factory = ConcatResourceFactory([path], name, + compress_level='none', caching='memory', lmt_check_period=0.0, + checker=checker) + self.name = name + + def __get__(self, obj, cls=None): + 'The view wants a method only.' + request = obj.request + resource = self.resource_factory(request) + resource.__parent__ = obj + resource.__name__ = self.name + return resource + +def absolute_dir(path): + here = os.path.split(globals()['__file__'])[0] + return os.path.abspath(os.path.join(here, path)) + +class TestView(BrowserView): + '''Kukit test view + + This allows the runner.html to be used on this view. + + This provides the tests run with the compiled kukit.js + resource, in the same way as they would be run + in production with azax. + ''' + + implements(IBrowserPublisher) + + _testdir = absolute_dir('../kukit/tests') + + _runner = ViewPageTemplateFile('../kukit/tests/runner.html', content_type='text/html;charset=utf-8') + + # The next is only necessary on Zope (<=) 2.9, + # provides a docstring to the method + def _runner_proxy(self, *arg, **kw): + 'Publishable method' + return self._runner(*arg, **kw) + + def publishTraverse(self, request, name): + '''See interface IBrowserPublisher''' + return self.get(name) + + def browserDefault(self, request): + '''See interface IBrowserPublisher''' + return self, () + + def __getitem__(self, name): + res = self.get(name, None) + if res is None: + raise KeyError(name) + return res + + def get(self, name, default=_marker): + # runner.html is compiled as a pagetemplate + if name == 'runner.html': + # XXX For Zope2.9 we need this. + if not hasattr(self.request, 'debug'): + self.request.debug = None + # proxy is used to make it publishable, on Zope <= 2.9 + return self._runner_proxy + + # We store them on the view on demand. + # Is it there yet? + if name[0] != '_': + try: + return getattr(self, name) + except AttributeError: + pass + + # See the file we need + path = os.path.join(self._testdir, name) + if os.path.isfile(path): + # Ok, this is a file. Cook it. + resource = ViewFile(name, path) + setattr(self.__class__, name, resource) + # important: return accessed *from* the view. + return getattr(self, name) + + # Not found. + if default is _marker: + raise NotFound(None, name) + return default + + def __call__(self): + 'By default we redirect to runner.html.' + # on Zope3, the url is of zope.publisher.http.URLGetter class, so we must stringify it + return self.request.response.redirect(str(self.request.URL) + '/runner.html') From reebalazs at codespeak.net Sat Sep 9 20:21:09 2006 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Sat, 9 Sep 2006 20:21:09 +0200 (CEST) Subject: [Kukit-checkins] r32111 - kukit/azax/branch/zope2.8 Message-ID: <20060909182109.EAE7810083@code0.codespeak.net> Author: reebalazs Date: Sat Sep 9 20:21:08 2006 New Revision: 32111 Modified: kukit/azax/branch/zope2.8/configure.zcml Log: Merge from trunk (Making ecma unittests runnable from publisher) Modified: kukit/azax/branch/zope2.8/configure.zcml ============================================================================== --- kukit/azax/branch/zope2.8/configure.zcml (original) +++ kukit/azax/branch/zope2.8/configure.zcml Sat Sep 9 20:21:08 2006 @@ -2,65 +2,46 @@ xmlns:browser="http://namespaces.zope.org/browser" xmlns:five="http://namespaces.zope.org/five"> - - + + - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + - + + + + + - + /> From reebalazs at codespeak.net Sat Sep 9 20:22:06 2006 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Sat, 9 Sep 2006 20:22:06 +0200 (CEST) Subject: [Kukit-checkins] r32112 - kukit/azaxdemo/trunk/browser Message-ID: <20060909182206.1DD2B10083@code0.codespeak.net> Author: reebalazs Date: Sat Sep 9 20:22:04 2006 New Revision: 32112 Modified: kukit/azaxdemo/trunk/browser/azax_demo_index.pt kukit/azaxdemo/trunk/browser/azax_effects.pt kukit/azaxdemo/trunk/browser/header_macros.pt Log: Ecma unittests are runnable from azaxdemo Modified: kukit/azaxdemo/trunk/browser/azax_demo_index.pt ============================================================================== --- kukit/azaxdemo/trunk/browser/azax_demo_index.pt (original) +++ kukit/azaxdemo/trunk/browser/azax_demo_index.pt Sat Sep 9 20:22:04 2006 @@ -15,5 +15,12 @@
    • Form submit
    • Effects
    • + +

      + + + Modified: kukit/azaxdemo/trunk/browser/azax_effects.pt ============================================================================== --- kukit/azaxdemo/trunk/browser/azax_effects.pt (original) +++ kukit/azaxdemo/trunk/browser/azax_effects.pt Sat Sep 9 20:22:04 2006 @@ -2,6 +2,7 @@ + + + +

      All demos

      +

      Start logging pane

      +

      View KSS resource

      + +

      Error handling demo

      +

      +
      +

      We try four cases here. "No error" and "Empty action" are both valid responses, + except that the second one gives a response with no commands and so it issues a warning into + the kss log. "Error" gives a failed responses due to an exception in the server method + on the server.

      +

      The buttons in the first row have no error handled.

      +
      + + + + +
      +

      The buttons in the second row have individual error handlers.

      +
      +
      + + + + +
      +

      + You can also try suspending your server process and start generating timed out requests. + Timed out responses are also handled like ones arriving with error. + The timeout period is by default 8 s now.

      +

      + In addition, the request queue manager queues up the outgoing responses and maximizes + their number (currently in 4): click like crazy on the buttons and you will see that + your server will not get hogged. More will be told about this topic in the upcoming + documentation.

      + + + Modified: kukit/azaxdemo/trunk/configure.zcml ============================================================================== --- kukit/azaxdemo/trunk/configure.zcml (original) +++ kukit/azaxdemo/trunk/configure.zcml Sun Sep 10 20:16:33 2006 @@ -397,4 +397,27 @@ permission="zope.View" /> + + + + + + + + + From reebalazs at codespeak.net Tue Sep 12 16:38:19 2006 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Tue, 12 Sep 2006 16:38:19 +0200 (CEST) Subject: [Kukit-checkins] r32220 - kukit/kukit.js/trunk/tests Message-ID: <20060912143819.55D391007E@code0.codespeak.net> Author: reebalazs Date: Tue Sep 12 16:38:18 2006 New Revision: 32220 Modified: kukit/kukit.js/trunk/tests/runner.html Log: Fix broken ecmaunit with ie. Since the - + + + tal:attributes="src string:../++resource++kukit.js"> + tal:replace="nothing"> + tal:replace="nothing"> + tal:replace="nothing"> + tal:replace="nothing"> + tal:replace="nothing"> + tal:replace="nothing"> + tal:replace="nothing"> + tal:replace="nothing"> + tal:replace="nothing"> + tal:replace="nothing"> + tal:replace="nothing"> + tal:replace="nothing"> + tal:replace="nothing"> - - - - + tal:replace="nothing"> + + + + From reebalazs at codespeak.net Tue Sep 12 16:38:32 2006 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Tue, 12 Sep 2006 16:38:32 +0200 (CEST) Subject: [Kukit-checkins] r32221 - kukit/azax/trunk/tests Message-ID: <20060912143832.6225F1007E@code0.codespeak.net> Author: reebalazs Date: Tue Sep 12 16:38:31 2006 New Revision: 32221 Modified: kukit/azax/trunk/tests/testview.py Log: Fix broken ecmaunit with ie. Modified: kukit/azax/trunk/tests/testview.py ============================================================================== --- kukit/azax/trunk/tests/testview.py (original) +++ kukit/azax/trunk/tests/testview.py Tue Sep 12 16:38:31 2006 @@ -89,7 +89,7 @@ _testdir = absolute_dir('../kukit/tests') - _runner = ViewPageTemplateFile('../kukit/tests/runner.html', content_type='text/html;charset=utf-8') + _runner = ViewPageTemplateFile('../kukit/tests/runner.html', content_type='text/html; charset=utf-8') # The next is only necessary on Zope (<=) 2.9, # provides a docstring to the method From reebalazs at codespeak.net Tue Sep 12 16:39:36 2006 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Tue, 12 Sep 2006 16:39:36 +0200 (CEST) Subject: [Kukit-checkins] r32222 - kukit/azax/branch/zope2.8/tests Message-ID: <20060912143936.B43631007E@code0.codespeak.net> Author: reebalazs Date: Tue Sep 12 16:39:35 2006 New Revision: 32222 Modified: kukit/azax/branch/zope2.8/tests/testview.py Log: Merge from trunk. Modified: kukit/azax/branch/zope2.8/tests/testview.py ============================================================================== --- kukit/azax/branch/zope2.8/tests/testview.py (original) +++ kukit/azax/branch/zope2.8/tests/testview.py Tue Sep 12 16:39:35 2006 @@ -89,7 +89,7 @@ _testdir = absolute_dir('../kukit/tests') - _runner = ViewPageTemplateFile('../kukit/tests/runner.html', content_type='text/html;charset=utf-8') + _runner = ViewPageTemplateFile('../kukit/tests/runner.html', content_type='text/html; charset=utf-8') # The next is only necessary on Zope (<=) 2.9, # provides a docstring to the method From reebalazs at codespeak.net Wed Sep 13 14:45:24 2006 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Wed, 13 Sep 2006 14:45:24 +0200 (CEST) Subject: [Kukit-checkins] r32258 - kukit/kukit.js/trunk/kukit Message-ID: <20060913124524.C8B201007B@code0.codespeak.net> Author: reebalazs Date: Wed Sep 13 14:45:21 2006 New Revision: 32258 Modified: kukit/kukit.js/trunk/kukit/kssparser.js kukit/kukit.js/trunk/kukit/kukit.js kukit/kukit.js/trunk/kukit/resourcedata.js Log: Enhance error logging at the page load (parsing, merging and binding) phase Modified: kukit/kukit.js/trunk/kukit/kssparser.js ============================================================================== --- kukit/kukit.js/trunk/kukit/kssparser.js (original) +++ kukit/kukit.js/trunk/kukit/kssparser.js Wed Sep 13 14:45:21 2006 @@ -451,7 +451,17 @@ name = splitname[1]; namespace = splitname[0]; } - this.kssSelector = new kukit.rd.KssSelector(isEvent, css, name, namespace, id); + // Protect the error for better logging + try { + this.kssSelector = new kukit.rd.KssSelector(isEvent, css, name, namespace, id); + } catch(e) { + if (e.name == 'KssSelectorError') { + // Log the message + this.emitError(e.toString()); + } else { + throw e; + } + } this.txt = ''; this.result = []; }; @@ -476,20 +486,7 @@ kukit.kssp.KssRuleProcessor.prototype.parse = function() { //Build a parser and parse the text into it var src = new kukit.tk.Cursor(this.txt); - var parser; - try { - parser = new kukit.kssp.document(src, null, true); - } catch(e) { - if (e.name == 'ParsingError') { - // Log the message - var msg = 'Error parsing KSS at ' + this.href + ' : ' + e.toString(); - kukit.logFatal(msg); - // just throw it too... - throw msg; - } else { - throw e; - } - } + var parser = new kukit.kssp.document(src, null, true); // Store event rules in the common list for (var i=0; i Author: reebalazs Date: Wed Sep 13 18:20:44 2006 New Revision: 32274 Modified: kukit/kukit.js/trunk/kukit/plugin.js kukit/kukit.js/trunk/kukit/requestmanager.js Log: adding spinner events Modified: kukit/kukit.js/trunk/kukit/plugin.js ============================================================================== --- kukit/kukit.js/trunk/kukit/plugin.js (original) +++ kukit/kukit.js/trunk/kukit/plugin.js Wed Sep 13 18:20:44 2006 @@ -222,6 +222,19 @@ kukit.er.eventRegistry.register(null, 'load', kukit.pl.LoadEventBinder, '__bind__', null); +kukit.pl.SpinnerEventBinder = function() { +}; + +kukit.pl.SpinnerEventBinder.prototype.__bind__ = function(name, func_to_bind, oper) { + oper.completeParms([], {}, 'spinner event binding'); + // Register the function with the global queue manager + kukit.requestManager.registerSpinnerEvent(func_to_bind, (name == 'spinneron')); +}; + +kukit.er.eventRegistry.register(null, 'spinneron', kukit.pl.SpinnerEventBinder, '__bind__', null); +kukit.er.eventRegistry.register(null, 'spinneroff', kukit.pl.SpinnerEventBinder, '__bind__', null); + + /* Core actions * Modified: kukit/kukit.js/trunk/kukit/requestmanager.js ============================================================================== --- kukit/kukit.js/trunk/kukit/requestmanager.js (original) +++ kukit/kukit.js/trunk/kukit/requestmanager.js Wed Sep 13 18:20:44 2006 @@ -170,6 +170,8 @@ schedulerClass = kukit.ut.Scheduler; } this.timeoutScheduler = new schedulerClass(checkTimeout); + this.spinnerEvents = {'off': [], 'on': []}; + this.spinnerState = false; }; // sending timeout in millisecs @@ -186,6 +188,17 @@ kukit.logDebug('RequestManager ' + this.namestr + txt + ' ' + this.getInfo()); }; +kukit.rm.RequestManager.prototype.setSpinnerState = function(newState) { + if (this.spinnerState != newState) { + this.spinnerState = newState; + // Call the registered spinner events for this state + var events = this.spinnerEvents[newState ? 'on' : 'off']; + for (var i=0; i Author: reebalazs Date: Wed Sep 13 18:20:52 2006 New Revision: 32275 Modified: kukit/azax/trunk/plugins/core/configure.zcml Log: adding spinner events Modified: kukit/azax/trunk/plugins/core/configure.zcml ============================================================================== --- kukit/azax/trunk/plugins/core/configure.zcml (original) +++ kukit/azax/trunk/plugins/core/configure.zcml Wed Sep 13 18:20:52 2006 @@ -92,6 +92,14 @@ name="load" /> + + + + Author: reebalazs Date: Wed Sep 13 18:22:11 2006 New Revision: 32276 Modified: kukit/azax/branch/zope2.8/plugins/core/configure.zcml Log: Merge from trunk Modified: kukit/azax/branch/zope2.8/plugins/core/configure.zcml ============================================================================== --- kukit/azax/branch/zope2.8/plugins/core/configure.zcml (original) +++ kukit/azax/branch/zope2.8/plugins/core/configure.zcml Wed Sep 13 18:22:11 2006 @@ -92,6 +92,14 @@ name="load" /> + + + + Author: reebalazs Date: Wed Sep 13 18:23:27 2006 New Revision: 32277 Modified: kukit/azaxdemo/trunk/browser/error_handling.kss kukit/azaxdemo/trunk/browser/error_handling.pt Log: Adding spinner control to errors demo Modified: kukit/azaxdemo/trunk/browser/error_handling.kss ============================================================================== --- kukit/azaxdemo/trunk/browser/error_handling.kss (original) +++ kukit/azaxdemo/trunk/browser/error_handling.kss Wed Sep 13 18:23:27 2006 @@ -31,3 +31,18 @@ executeCommand-html: 'Error handler activated.'; } +/* Spinner control +*/ + +#spinner-status:spinneron { + action-client: setStyle; + setStyle-name: display; + setStyle-value: block; +} + +#spinner-status:spinneroff { + action-client: setStyle; + setStyle-name: display; + setStyle-value: none; +} + Modified: kukit/azaxdemo/trunk/browser/error_handling.pt ============================================================================== --- kukit/azaxdemo/trunk/browser/error_handling.pt (original) +++ kukit/azaxdemo/trunk/browser/error_handling.pt Wed Sep 13 18:23:27 2006 @@ -4,6 +4,14 @@ tal:attributes="href string:${context/@@absolute_url}/++resource++error_handling.kss"/> + + +

      All demos

      +

      Start logging pane

      +

      View KSS resource

      + +

      Preventdefault Demo

      +

      + This is for testing the work of preventdefault to test a specific + workaround against a Safari bug. Specifically, none of the above + controls should cause a page reload. +

      +
      +

      Do not follow

      + + + +

      The same with allowbubbling combined:

      + +
      + +
      +
      + +
      +
      + +
      +
      + + Modified: kukit/azaxdemo/trunk/configure.zcml ============================================================================== --- kukit/azaxdemo/trunk/configure.zcml (original) +++ kukit/azaxdemo/trunk/configure.zcml Sun Sep 17 13:39:08 2006 @@ -419,5 +419,17 @@ permission="zope.View" /> + + + + From reebalazs at codespeak.net Sun Sep 17 19:17:52 2006 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Sun, 17 Sep 2006 19:17:52 +0200 (CEST) Subject: [Kukit-checkins] r32420 - in kukit/kukit.js/trunk: kukit tests Message-ID: <20060917171752.94BD21006C@code0.codespeak.net> Author: reebalazs Date: Sun Sep 17 19:17:49 2006 New Revision: 32420 Modified: kukit/kukit.js/trunk/kukit/kssparser.js kukit/kukit.js/trunk/kukit/oper.js kukit/kukit.js/trunk/kukit/utils.js kukit/kukit.js/trunk/tests/test_utils.js Log: Implement evelList, start to implement the event cancel hook. Modified: kukit/kukit.js/trunk/kukit/kssparser.js ============================================================================== --- kukit/kukit.js/trunk/kukit/kssparser.js (original) +++ kukit/kukit.js/trunk/kukit/kssparser.js Sun Sep 17 19:17:49 2006 @@ -121,6 +121,7 @@ // // action-server: // action-client: + // action-cancel: // // -: // -error: @@ -166,6 +167,9 @@ case 'client': { actionType = 'C'; } break; + case 'cancel': { + actionType = 'X'; + } break; default: { this.emitError('kss param key must be action-server or action-client "' + key + '"'); } break; Modified: kukit/kukit.js/trunk/kukit/oper.js ============================================================================== --- kukit/kukit.js/trunk/kukit/oper.js (original) +++ kukit/kukit.js/trunk/kukit/oper.js Sun Sep 17 19:17:49 2006 @@ -166,3 +166,8 @@ this.parms[key] = kukit.ut.evalInt(value, 'for key "' + key + '" in ' + errname); }; +kukit.op.Oper.prototype.evalList = function(key, errname) { + var value = this.parms[key]; + this.parms[key] = kukit.ut.evalList(value, 'for key "' + key + '" in ' + errname); +}; + Modified: kukit/kukit.js/trunk/kukit/utils.js ============================================================================== --- kukit/kukit.js/trunk/kukit/utils.js (original) +++ kukit/kukit.js/trunk/kukit/utils.js Sun Sep 17 19:17:49 2006 @@ -207,6 +207,23 @@ return value; }; +kukit.ut.evalList = function(value, errname) { + try { + // remove whitespace from beginning, end + value = value.replace(/^ +/, ''); + //while (value && value.charAt(0) == ' ') { + // value = value.substr(1); + //} + value = value.replace(/ +$/, ''); + // do the splitting + value = value.split(/ *, */); + } catch(e) { + throw 'Bad list value "' + value + '" ' + errname; + } + return value; +}; + + /* Timer counter for repeating or one time timing */ Modified: kukit/kukit.js/trunk/tests/test_utils.js ============================================================================== --- kukit/kukit.js/trunk/tests/test_utils.js (original) +++ kukit/kukit.js/trunk/tests/test_utils.js Sun Sep 17 19:17:49 2006 @@ -48,7 +48,7 @@ } this.assertEquals(a.length, b.length, reason + 'lists of different length'); for (var i=0; i Author: reebalazs Date: Sun Sep 17 20:41:37 2006 New Revision: 32424 Modified: kukit/azax/trunk/concatresource.zcml kukit/azax/trunk/plugins/core/configure.zcml Log: Add action insertHTMLAsLastChild' plugins/core/configure.zcml Modified: kukit/azax/trunk/concatresource.zcml ============================================================================== --- kukit/azax/trunk/concatresource.zcml (original) +++ kukit/azax/trunk/concatresource.zcml Sun Sep 17 20:41:37 2006 @@ -18,7 +18,9 @@ kukit/kukit/forms.js kukit/kukit/plugin.js" name="kukit.js" - compress_level="safe" + compress_level="none" + caching="default" + lmt_check_period="0" /> +

      All demos

      +

      Start logging pane

      +

      View KSS resource

      +

      HTML insertions (a.k.a. Change tags II.)

      +
        +
      • + +
      • +
      • + +
      • +
      • + +
      • +
      • + +
      • +
      • + +
      • +
      +

      The playground:

      +

      KSS for a life.

      + + Modified: kukit/azaxdemo/trunk/configure.zcml ============================================================================== --- kukit/azaxdemo/trunk/configure.zcml (original) +++ kukit/azaxdemo/trunk/configure.zcml Tue Sep 19 12:29:50 2006 @@ -432,4 +432,59 @@ name="preventdefault.kss" /> + + + + + + + + + + + + + + + + + From reebalazs at codespeak.net Tue Sep 19 12:40:26 2006 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Tue, 19 Sep 2006 12:40:26 +0200 (CEST) Subject: [Kukit-checkins] r32478 - kukit/azaxdemo/trunk/browser Message-ID: <20060919104026.2A26D10082@code0.codespeak.net> Author: reebalazs Date: Tue Sep 19 12:40:25 2006 New Revision: 32478 Modified: kukit/azaxdemo/trunk/browser/html_inserts.pt Log: fix demo titles etc Modified: kukit/azaxdemo/trunk/browser/html_inserts.pt ============================================================================== --- kukit/azaxdemo/trunk/browser/html_inserts.pt (original) +++ kukit/azaxdemo/trunk/browser/html_inserts.pt Tue Sep 19 12:40:25 2006 @@ -31,27 +31,27 @@
      From reebalazs at codespeak.net Tue Sep 19 12:41:59 2006 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Tue, 19 Sep 2006 12:41:59 +0200 (CEST) Subject: [Kukit-checkins] r32479 - kukit/kukit.js/trunk/kukit Message-ID: <20060919104159.315F010082@code0.codespeak.net> Author: reebalazs Date: Tue Sep 19 12:41:58 2006 New Revision: 32479 Modified: kukit/kukit.js/trunk/kukit/plugin.js Log: Add remark that insertHTMLBefore is missing Modified: kukit/kukit.js/trunk/kukit/plugin.js ============================================================================== --- kukit/kukit.js/trunk/kukit/plugin.js (original) +++ kukit/kukit.js/trunk/kukit/plugin.js Tue Sep 19 12:41:58 2006 @@ -433,6 +433,8 @@ }); kukit.cr.commandRegistry.registerFromAction('insertHTMLAfter', kukit.cr.makeSelectorCommand); +// XXX TODO find or implement insertHTMLBefore! + kukit.ar.actionRegistry.register('insertHTMLAsLastChild', function(oper) { oper.completeParms(['html'], {}, 'insertHTMLAsLastChild action'); oper.parms.html = kukit.dom.forceToDom(oper.parms.html); From reebalazs at codespeak.net Tue Sep 19 12:56:19 2006 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Tue, 19 Sep 2006 12:56:19 +0200 (CEST) Subject: [Kukit-checkins] r32482 - kukit/kukit.js/trunk/kukit Message-ID: <20060919105619.1120910078@code0.codespeak.net> Author: reebalazs Date: Tue Sep 19 12:56:17 2006 New Revision: 32482 Modified: kukit/kukit.js/trunk/kukit/plugin.js Log: Add insertHTMLBefore Modified: kukit/kukit.js/trunk/kukit/plugin.js ============================================================================== --- kukit/kukit.js/trunk/kukit/plugin.js (original) +++ kukit/kukit.js/trunk/kukit/plugin.js Tue Sep 19 12:56:17 2006 @@ -433,7 +433,18 @@ }); kukit.cr.commandRegistry.registerFromAction('insertHTMLAfter', kukit.cr.makeSelectorCommand); -// XXX TODO find or implement insertHTMLBefore! +kukit.ar.actionRegistry.register('insertHTMLBefore', function(oper) { + oper.completeParms(['html'], {}, 'insertHTMLBefore action'); + oper.parms.html = kukit.dom.forceToDom(oper.parms.html); + var content = oper.parms.html; + var toNode = oper.node; + var parentNode = toNode.parentNode; + var inserted = kukit.dom.insertBefore(content, parentNode, toNode); + // update the events for the new nodes + kukit.logDebug("Inserted nodes length: "+inserted.length); + kukit.setupEvents(inserted); +}); +kukit.cr.commandRegistry.registerFromAction('insertHTMLBefore', kukit.cr.makeSelectorCommand); kukit.ar.actionRegistry.register('insertHTMLAsLastChild', function(oper) { oper.completeParms(['html'], {}, 'insertHTMLAsLastChild action'); From reebalazs at codespeak.net Tue Sep 19 12:56:37 2006 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Tue, 19 Sep 2006 12:56:37 +0200 (CEST) Subject: [Kukit-checkins] r32483 - kukit/azaxdemo/trunk/browser Message-ID: <20060919105637.846B710078@code0.codespeak.net> Author: reebalazs Date: Tue Sep 19 12:56:36 2006 New Revision: 32483 Modified: kukit/azaxdemo/trunk/browser/html_inserts.kss kukit/azaxdemo/trunk/browser/html_inserts.pt Log: Add insertHTMLBefore Modified: kukit/azaxdemo/trunk/browser/html_inserts.kss ============================================================================== --- kukit/azaxdemo/trunk/browser/html_inserts.kss (original) +++ kukit/azaxdemo/trunk/browser/html_inserts.kss Tue Sep 19 12:56:36 2006 @@ -1,9 +1,7 @@ -/* defunct button#insertBefore:click { action-server: htmlInsertBefore; } -*/ button#insertAfter:click { action-server: htmlInsertAfter; Modified: kukit/azaxdemo/trunk/browser/html_inserts.pt ============================================================================== --- kukit/azaxdemo/trunk/browser/html_inserts.pt (original) +++ kukit/azaxdemo/trunk/browser/html_inserts.pt Tue Sep 19 12:56:36 2006 @@ -31,7 +31,7 @@
      • From reebalazs at codespeak.net Tue Sep 19 13:08:10 2006 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Tue, 19 Sep 2006 13:08:10 +0200 (CEST) Subject: [Kukit-checkins] r32484 - kukit/azax/trunk Message-ID: <20060919110810.749E110078@code0.codespeak.net> Author: reebalazs Date: Tue Sep 19 13:07:52 2006 New Revision: 32484 Modified: kukit/azax/trunk/ (props changed) kukit/azax/trunk/EXTERNALS.TXT kukit/azax/trunk/meta.zcml Log: Adding configfeature to azax Modified: kukit/azax/trunk/EXTERNALS.TXT ============================================================================== --- kukit/azax/trunk/EXTERNALS.TXT (original) +++ kukit/azax/trunk/EXTERNALS.TXT Tue Sep 19 13:07:52 2006 @@ -6,3 +6,4 @@ # svn propset svn:externals -F EXTERNALS.TXT . # kukit http://codespeak.net/svn/kukit/kukit.js/trunk +configfeature http://codespeak.net/svn/z3/jsonserver/branch/merge/configfeature Modified: kukit/azax/trunk/meta.zcml ============================================================================== --- kukit/azax/trunk/meta.zcml (original) +++ kukit/azax/trunk/meta.zcml Tue Sep 19 13:07:52 2006 @@ -1,6 +1,8 @@ + + From reebalazs at codespeak.net Tue Sep 19 13:21:04 2006 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Tue, 19 Sep 2006 13:21:04 +0200 (CEST) Subject: [Kukit-checkins] r32485 - kukit/azaxdemo/trunk Message-ID: <20060919112104.44D2010078@code0.codespeak.net> Author: reebalazs Date: Tue Sep 19 13:21:03 2006 New Revision: 32485 Modified: kukit/azaxdemo/trunk/azaxview.py Log: Beautify demo Modified: kukit/azaxdemo/trunk/azaxview.py ============================================================================== --- kukit/azaxdemo/trunk/azaxview.py (original) +++ kukit/azaxdemo/trunk/azaxview.py Tue Sep 19 13:21:03 2006 @@ -190,20 +190,20 @@ def htmlInsertBefore(self): """html insert""" - self.addCommand('insertHTMLBefore', '#core', html='

        KSS for a life. %s

        ' % (str(datetime.datetime.now()), )) + self.addCommand('insertHTMLBefore', '#core', html='
        KSS for a life. %s
        ' % (str(datetime.datetime.now()), )) return self.render() def htmlInsertAfter(self): """html insert""" - self.addCommand('insertHTMLAfter', '#core', html='

        KSS for a life. %s

        ' % (str(datetime.datetime.now()), )) + self.addCommand('insertHTMLAfter', '#core', html='
        KSS for a life. %s
        ' % (str(datetime.datetime.now()), )) return self.render() def htmlInsertAsFirstChild(self): """html insert""" - self.addCommand('insertHTMLAsFirstChild', 'div#frame', html='

        KSS for a life. %s

        ' % (str(datetime.datetime.now()), )) + self.addCommand('insertHTMLAsFirstChild', 'div#frame', html='
        KSS for a life. %s
        ' % (str(datetime.datetime.now()), )) return self.render() def htmlInsertAsLastChild(self): """html insert""" - self.addCommand('insertHTMLAsLastChild', 'div#frame', html='

        KSS for a life. %s

        ' % (str(datetime.datetime.now()), )) + self.addCommand('insertHTMLAsLastChild', 'div#frame', html='
        KSS for a life. %s
        ' % (str(datetime.datetime.now()), )) return self.render() From gotcha at codespeak.net Tue Sep 19 15:38:29 2006 From: gotcha at codespeak.net (gotcha at codespeak.net) Date: Tue, 19 Sep 2006 15:38:29 +0200 (CEST) Subject: [Kukit-checkins] r32493 - in kukit/azax/trunk: . plugins/core plugins/effects tests Message-ID: <20060919133829.7525610086@code0.codespeak.net> Author: gotcha Date: Tue Sep 19 15:38:26 2006 New Revision: 32493 Added: kukit/azax/trunk/plugins/core/commands.py kukit/azax/trunk/plugins/core/interfaces.py kukit/azax/trunk/plugins/effects/commands.py kukit/azax/trunk/plugins/effects/interfaces.py Modified: kukit/azax/trunk/azaxview.py kukit/azax/trunk/commands.py kukit/azax/trunk/plugins/core/configure.zcml kukit/azax/trunk/plugins/effects/configure.zcml kukit/azax/trunk/tests/test_azaxview.py Log: refactor use of adapters to do it right Modified: kukit/azax/trunk/azaxview.py ============================================================================== --- kukit/azax/trunk/azaxview.py (original) +++ kukit/azax/trunk/azaxview.py Tue Sep 19 15:38:26 2006 @@ -79,15 +79,15 @@ def getCommands(self): return self.commands - def __getattr__(self, name): - if name == '__provides__': - raise AttributeError(name) - elif hasattr(self.commands, name): - #XXX surface only actual commands, not inner guts - return getattr(self.commands, name) - else: - raise AttributeError(name) - def executeMacro(self, name, *args, **kwargs): adapter = zapi.getAdapter(self, IAzaxMacro, name) adapter.execute(*args, **kwargs) + +class AzaxViewAdapter: + + def __init__(self, view): + self.view = view + self.context = self.view.context + self.request = self.view.request + self.commands = self.view.commands + Modified: kukit/azax/trunk/commands.py ============================================================================== --- kukit/azax/trunk/commands.py (original) +++ kukit/azax/trunk/commands.py Tue Sep 19 15:38:26 2006 @@ -35,7 +35,6 @@ from selectors import Selector, CssSelector, HtmlIdSelector from parsers import XmlParser, HtmlParser -from deprecated import deprecated class AzaxCommands(list): implements(IAzaxCommands) @@ -63,110 +62,6 @@ def getHtmlIdSelector(self, selector): return HtmlIdSelector(selector) - # -- - # default set of commands - # -- - - # XXX the list is not full: maybe complete them? - - def replaceInnerHTML(self, selector, new_value): - """ see interfaces.py """ - new_value = HtmlParser(new_value)().encode('ascii', 'xmlcharrefreplace') - command = self.addCommand('replaceInnerHTML', selector) - data = command.addParam('html', new_value) - - def replaceHTML(self, selector, new_value): - """ see interfaces.py """ - new_value = HtmlParser(new_value)().encode('ascii', 'xmlcharrefreplace') - command = self.addCommand('replaceHTML', selector) - data = command.addParam('html', new_value) - - def setAttribute(self, selector, name, value): - """ see interfaces.py """ - command = self.addCommand('setAttribute', selector) - data = command.addParam('name', name) - data = command.addParam('value', value) - - def setStyle(self, selector, name, value): - """ see interfaces.py """ - command = self.addCommand('setStyle', selector) - data = command.addParam('name', name) - data = command.addParam('value', value) - - def insertHTMLAfter(self, selector, new_value): - """ see interfaces.py """ - new_value = HtmlParser(new_value)().encode('ascii', 'xmlcharrefreplace') - command = self.addCommand('insertHTMLAfter', selector) - data = command.addParam('html', new_value) - - def clearChildNodes(self, selector): - """ see interfaces.py """ - command = self.addCommand('clearChildNodes', selector) - - def deleteNode(self, selector): - """ see interfaces.py """ - command = self.addCommand('deleteNode', selector) - - def deleteNodeAfter(self, selector): - """ see interfaces.py """ - command = self.addCommand('deleteNodeAfter', selector) - - def deleteNodeBefore(self, selector): - """ see interfaces.py """ - command = self.addCommand('deleteNodeBefore', selector) - - def copyChildNodesFrom(self, selector, id): - """ see interfaces.py """ - command = self.addCommand('copyChildNodesFrom', selector) - data = command.addParam('html_id', id) - - def moveNodeAfter(self, selector, id): - """ see interfaces.py """ - command = self.addCommand('moveNodeAfter', selector) - data = command.addParam('html_id', id) - - def copyChildNodesTo(self, selector, id): - """ see interfaces.py """ - command = self.addCommand('copyChildNodesTo', selector) - data = command.addParam('html_id', id) - - def setStateVar(self, varname, value): - """ see interfaces.py """ - command = self.addCommand('setStateVar') - command.addParam('varname', varname) - command.addParam('value', value) - - def triggerEvent(self, name, **kw): - """ see interfaces.py """ - command = self.addCommand('triggerEvent') - command.addParam('name', name) - for key, value in kw.iteritems(): - command.addParam(key, value) - - def effect(self, selector, type): - """ see interfaces.py """ - command = self.addCommand('effect', selector) - data = command.addParam('type', type) - - # XXX Deprecated ones - - def moveChildrenTo(self, selector, id): - """ see interfaces.py """ - self.copyChildrenTo(selector, id) - self.clearChildren(selector) - moveChildrenTo = deprecated(moveChildrenTo, 'No more supported, use a sequence of copyChildrenTo and clearChildren') - - setHtmlAsChild = deprecated(replaceInnerHTML, 'use replaceInnerHTML instead') - addAfter = deprecated(insertHTMLAfter, 'use insertHTMLAfter instead') - clearChildren = deprecated(clearChildNodes, 'use clearChildNodes instead') - removeNode = deprecated(deleteNode, 'use deleteNode instead') - removeNextSibling = deprecated(deleteNodeAfter, 'use deleteNodeAfter instead') - removePreviousSibling = deprecated(deleteNodeBefore, 'use deleteNodeBefore instead') - copyChildrenFrom = deprecated(copyChildNodesFrom, 'use copyChildNodesFrom instead') - copyChildrenTo = deprecated(copyChildNodesTo, 'use copyChildNodesTo instead') - setStatevar = deprecated(setStateVar, 'use setStateVar (capital V) instead') - - # end deprecated class AzaxParam: implements(IAzaxParam) Added: kukit/azax/trunk/plugins/core/commands.py ============================================================================== --- (empty file) +++ kukit/azax/trunk/plugins/core/commands.py Tue Sep 19 15:38:26 2006 @@ -0,0 +1,133 @@ +from interfaces import IKSSCoreCommands + + +try: + from azax.azaxview import AzaxViewAdapter + from azax.deprecated import deprecated + from azax.parsers import XmlParser, HtmlParser +except ImportError: + from Products.azax.azaxview import AzaxViewAdapter + from Products.azax.deprecated import deprecated + from Products.azax.parsers import XmlParser, HtmlParser + + +class KSSCoreCommands(AzaxViewAdapter): + + # XXX the list is not full: maybe complete them? + + def replaceInnerHTML(self, selector, new_value): + """ see interfaces.py """ + new_value = HtmlParser(new_value)().encode('ascii', 'xmlcharrefreplace') + command = self.commands.addCommand('replaceInnerHTML', selector) + data = command.addParam('html', new_value) + + def replaceHTML(self, selector, new_value): + """ see interfaces.py """ + new_value = HtmlParser(new_value)().encode('ascii', 'xmlcharrefreplace') + command = self.commands.addCommand('replaceHTML', selector) + data = command.addParam('html', new_value) + + def setAttribute(self, selector, name, value): + """ see interfaces.py """ + command = self.commands.addCommand('setAttribute', selector) + data = command.addParam('name', name) + data = command.addParam('value', value) + + def setStyle(self, selector, name, value): + """ see interfaces.py """ + command = self.commands.addCommand('setStyle', selector) + data = command.addParam('name', name) + data = command.addParam('value', value) + + def insertHTMLAfter(self, selector, new_value): + """ see interfaces.py """ + new_value = HtmlParser(new_value)().encode('ascii', 'xmlcharrefreplace') + command = self.commands.addCommand('insertHTMLAfter', selector) + data = command.addParam('html', new_value) + + def insertHTMLAsFirstChild(self, selector, new_value): + """ see interfaces.py """ + new_value = HtmlParser(new_value)().encode('ascii', 'xmlcharrefreplace') + command = self.commands.addCommand('insertHTMLAsFirstChild', selector) + data = command.addParam('html', new_value) + + def insertHTMLAsLastChild(self, selector, new_value): + """ see interfaces.py """ + new_value = HtmlParser(new_value)().encode('ascii', 'xmlcharrefreplace') + command = self.commands.addCommand('insertHTMLAsLastChild', selector) + data = command.addParam('html', new_value) + + def insertHTMLBefore(self, selector, new_value): + """ see interfaces.py """ + new_value = HtmlParser(new_value)().encode('ascii', 'xmlcharrefreplace') + command = self.commands.addCommand('insertHTMLBefore', selector) + data = command.addParam('html', new_value) + + def clearChildNodes(self, selector): + """ see interfaces.py """ + command = self.commands.addCommand('clearChildNodes', selector) + + def deleteNode(self, selector): + """ see interfaces.py """ + command = self.commands.addCommand('deleteNode', selector) + + def deleteNodeAfter(self, selector): + """ see interfaces.py """ + command = self.commands.addCommand('deleteNodeAfter', selector) + + def deleteNodeBefore(self, selector): + """ see interfaces.py """ + command = self.commands.addCommand('deleteNodeBefore', selector) + + def copyChildNodesFrom(self, selector, id): + """ see interfaces.py """ + command = self.commands.addCommand('copyChildNodesFrom', selector) + data = command.addParam('html_id', id) + + def moveNodeAfter(self, selector, id): + """ see interfaces.py """ + command = self.commands.addCommand('moveNodeAfter', selector) + data = command.addParam('html_id', id) + + def copyChildNodesTo(self, selector, id): + """ see interfaces.py """ + command = self.commands.addCommand('copyChildNodesTo', selector) + data = command.addParam('html_id', id) + + def copyChildNodesTo(self, selector, id): + """ see interfaces.py """ + command = self.commands.addCommand('copyChildNodesTo', selector) + data = command.addParam('html_id', id) + + def setStateVar(self, varname, value): + """ see interfaces.py """ + command = self.commands.addCommand('setStateVar') + command.addParam('varname', varname) + command.addParam('value', value) + + def triggerEvent(self, name, **kw): + """ see interfaces.py """ + command = self.commands.addCommand('triggerEvent') + command.addParam('name', name) + for key, value in kw.iteritems(): + command.addParam(key, value) + + # XXX Deprecated ones + + def moveChildrenTo(self, selector, id): + """ see interfaces.py """ + self.copyChildrenTo(selector, id) + self.clearChildren(selector) + moveChildrenTo = deprecated(moveChildrenTo, 'No more supported, use a sequence of copyChildrenTo and clearChildren') + + setHtmlAsChild = deprecated(replaceInnerHTML, 'use replaceInnerHTML instead') + addAfter = deprecated(insertHTMLAfter, 'use insertHTMLAfter instead') + clearChildren = deprecated(clearChildNodes, 'use clearChildNodes instead') + removeNode = deprecated(deleteNode, 'use deleteNode instead') + removeNextSibling = deprecated(deleteNodeAfter, 'use deleteNodeAfter instead') + removePreviousSibling = deprecated(deleteNodeBefore, 'use deleteNodeBefore instead') + copyChildrenFrom = deprecated(copyChildNodesFrom, 'use copyChildNodesFrom instead') + copyChildrenTo = deprecated(copyChildNodesTo, 'use copyChildNodesTo instead') + setStatevar = deprecated(setStateVar, 'use setStateVar (capital V) instead') + + # end deprecated Modified: kukit/azax/trunk/plugins/core/configure.zcml ============================================================================== --- kukit/azax/trunk/plugins/core/configure.zcml (original) +++ kukit/azax/trunk/plugins/core/configure.zcml Tue Sep 19 15:38:26 2006 @@ -1,8 +1,24 @@ - + + + + + + Added: kukit/azax/trunk/plugins/effects/interfaces.py ============================================================================== --- (empty file) +++ kukit/azax/trunk/plugins/effects/interfaces.py Tue Sep 19 15:38:26 2006 @@ -0,0 +1,4 @@ +from zope.interface import Interface + +class IScriptaculousEffectsCommands(Interface): + '''effects commands''' Modified: kukit/azax/trunk/tests/test_azaxview.py ============================================================================== --- kukit/azax/trunk/tests/test_azaxview.py (original) +++ kukit/azax/trunk/tests/test_azaxview.py Tue Sep 19 15:38:26 2006 @@ -24,6 +24,7 @@ from zope.testing import doctest from base import AzaxViewTestCase,FakeContent, TestRequest, DebugTestRequest from Products.azax import AzaxUnicodeError +from Products.azax.plugins.core.interfaces import IKSSCoreCommands class TestAzaxView(AzaxViewTestCase): @@ -47,7 +48,7 @@ def _checkSetHtmlResult(self, content, content2=None): view = self.view - view.replaceInnerHTML('div.class', content) + IKSSCoreCommands(view).replaceInnerHTML('div.class', content) commands = view.getCommands() self.assertEqual(len(commands), 1) command = commands[0] @@ -122,7 +123,7 @@ def test_replaceInnerHTML(self): view = self.view - view.replaceInnerHTML('div.class', 'new content') + IKSSCoreCommands(view).replaceInnerHTML('div.class', 'new content') result = view.render() awaited = u'''\ Author: gotcha Date: Tue Sep 19 15:40:22 2006 New Revision: 32494 Modified: kukit/azaxdemo/trunk/azaxview.py Log: fixes after adaptor refactoring Modified: kukit/azaxdemo/trunk/azaxview.py ============================================================================== --- kukit/azaxdemo/trunk/azaxview.py (original) +++ kukit/azaxdemo/trunk/azaxview.py Tue Sep 19 15:40:22 2006 @@ -21,8 +21,12 @@ try: from azax import AzaxBaseView, force_unicode + from azax.plugins.core.interfaces import IKSSCoreCommands + from azax.plugins.effects.interfaces import IScriptaculousEffectsCommands except ImportError: from Products.azax import AzaxBaseView, force_unicode + from Products.azax.plugins.core.interfaces import IKSSCoreCommands + from Products.azax.plugins.effects.interfaces import IScriptaculousEffectsCommands import datetime, time @@ -34,29 +38,29 @@ def clearDivContent(self): """ clear div content """ - self.clearChildNodes('div#demo') + IKSSCoreCommands(self).clearChildNodes('div#demo') return self.render() def copyFromDivContent(self): """ copy div content """ - self.copyChildNodesFrom('div#copy', 'demo') + IKSSCoreCommands(self).copyChildNodesFrom('div#copy', 'demo') return self.render() def copyToDivContent(self): """ copy div content """ - self.copyChildNodesTo('div#copy', 'demo') + IKSSCoreCommands(self).copyChildNodesTo('div#copy', 'demo') return self.render() def moveToDivContent(self): """ copy div content """ - self.copyChildNodesTo('div#copy', 'demo') - self.clearChildNodes('div#copy') + IKSSCoreCommands(self).copyChildNodesTo('div#copy', 'demo') + IKSSCoreCommands(self).clearChildNodes('div#copy') return self.render() def getDivContent(self): """ returns div content """ - self.replaceInnerHTML('div#demo', '

        it worked

        ') - self.replaceInnerHTML('div#demo', '

        it worked again

        ') + IKSSCoreCommands(self).replaceInnerHTML('div#demo', '

        it worked

        ') + IKSSCoreCommands(self).replaceInnerHTML('div#demo', '

        it worked again

        ') return self.render() def getCorrespondingSelect(self, value): @@ -74,24 +78,24 @@ result = ['') - self.replaceHTML('select#second', ' '.join(result)) + IKSSCoreCommands(self).replaceHTML('select#second', ' '.join(result)) return self.render() def getAutoupdateMarkup(self): """ returns the current time """ - self.replaceInnerHTML('div#update-wrapper', '
        ') + IKSSCoreCommands(self).replaceInnerHTML('div#update-wrapper', '
        ') return self.render() def getCurrentTime(self): """ returns the current time """ - self.replaceInnerHTML('div#update-area', "

        %s

        " % str(datetime.datetime.now())) + IKSSCoreCommands(self).replaceInnerHTML('div#update-area', "

        %s

        " % str(datetime.datetime.now())) return self.render() def getInputField(self, value): 'Inserts the value as entered into an input field' # We need to make unicode. But on Z2 we receive utf-8, on Z3 unicode value = force_unicode(value, 'utf') - self.replaceInnerHTML('div#text', + IKSSCoreCommands(self).replaceInnerHTML('div#text', '
        ' \ '' ) @@ -101,34 +105,34 @@ 'Inserts the value to display it on the page' # We need to make unicode. But on Z2 we receive utf-8, on Z3 unicode value = force_unicode(value, 'utf') - self.replaceInnerHTML('div#text', value+'') + IKSSCoreCommands(self).replaceInnerHTML('div#text', value+'') return self.render() def expandSubTree(self, value, xvalue): 'Expands given subtree' - self.replaceInnerHTML('#text', 'works, expand %s (xhtml attr: %s)' % (value, xvalue)) + IKSSCoreCommands(self).replaceInnerHTML('#text', 'works, expand %s (xhtml attr: %s)' % (value, xvalue)) return self.render() def collapseSubTree(self, value, xvalue): 'Collapses given subtree' - self.replaceInnerHTML('#text', 'works, collapse %s (xhtml attr: %s)' % (value, xvalue)) + IKSSCoreCommands(self).replaceInnerHTML('#text', 'works, collapse %s (xhtml attr: %s)' % (value, xvalue)) return self.render() def cancelSubmitSave(self, text_save): # We need to make unicode. But on Z2 we receive utf-8, on Z3 unicode text_save = force_unicode(text_save, 'utf') - self.replaceInnerHTML('div#async', 'Async saved %s' % text_save) + IKSSCoreCommands(self).replaceInnerHTML('div#async', 'Async saved %s' % text_save) return self.render() def removeNodeXpath(self): # XXX the xpath selector is now moved out of the core, see suppl, product "azaxslt" sel = self.getSelector('xpath', "//P[@id='xpath']/following-sibling::*[position()=1]") - self.deleteNode(sel) + IKSSCoreCommands(self).deleteNode(sel) return self.render() def clickedButton(self, id): 'Show status of the button clicked' - self.replaceInnerHTML('#update-status', "

        Button %s clicked. %s

        " % (id, datetime.datetime.now())) + IKSSCoreCommands(self).replaceInnerHTML('#update-status', "

        Button %s clicked. %s

        " % (id, datetime.datetime.now())) return self.render() def updateSlaveSelector(self, masterid, value): @@ -145,7 +149,7 @@ result.extend(['' % item for item in mapping[value]]) result.append('') # XXX See above remark why we need to replace the outer select. - self.replaceHTML('select#%s' % slaveid, ' '.join(result)) + IKSSCoreCommands(self).replaceHTML('select#%s' % slaveid, ' '.join(result)) return self.render() def formSubmitSave(self, data): @@ -155,11 +159,11 @@ result.append('') # We need to make unicode. But on Z2 we receive utf-8, on Z3 unicode retval = force_unicode(''.join(result), 'utf') - self.replaceInnerHTML('div#async', retval) + IKSSCoreCommands(self).replaceInnerHTML('div#async', retval) return self.render() def reset(self): - self.effect('.effects', 'appear') + IScriptaculousEffectsCommands(self).effect('.effects', 'appear') return self.render() def errTest(self, id, act): @@ -180,30 +184,30 @@ # self.replaceInnerHTML('#update-status', u'Timeout response, button %s clicked. %s' % (id, datetime.datetime.now())) else: # act = noerror: standard response. - self.replaceInnerHTML('#update-status', u'Normal response, button %s clicked. %s' % (id, datetime.datetime.now())) + IKSSCoreCommands(self).replaceInnerHTML('#update-status', u'Normal response, button %s clicked. %s' % (id, datetime.datetime.now())) return self.render() def htmlReplace(self): """html replace""" - self.addCommand('replaceHTML', 'div#frame', html='

        KSS for a life.

        ') + IKSSCoreCommands(self).replaceHTML('div#frame', '

        KSS for a life.

        ') return self.render() def htmlInsertBefore(self): """html insert""" - self.addCommand('insertHTMLBefore', '#core', html='
        KSS for a life. %s
        ' % (str(datetime.datetime.now()), )) + IKSSCoreCommands(self).insertHTMLBefore('#core', '
        KSS for a life. %s
        ' % (str(datetime.datetime.now()), )) return self.render() def htmlInsertAfter(self): """html insert""" - self.addCommand('insertHTMLAfter', '#core', html='
        KSS for a life. %s
        ' % (str(datetime.datetime.now()), )) + IKSSCoreCommands(self).insertHTMLAfter('#core', '
        KSS for a life. %s
        ' % (str(datetime.datetime.now()), )) return self.render() def htmlInsertAsFirstChild(self): """html insert""" - self.addCommand('insertHTMLAsFirstChild', 'div#frame', html='
        KSS for a life. %s
        ' % (str(datetime.datetime.now()), )) + IKSSCoreCommands(self).insertHTMLAsFirstChild('div#frame', '
        KSS for a life. %s
        ' % (str(datetime.datetime.now()), )) return self.render() def htmlInsertAsLastChild(self): """html insert""" - self.addCommand('insertHTMLAsLastChild', 'div#frame', html='
        KSS for a life. %s
        ' % (str(datetime.datetime.now()), )) + IKSSCoreCommands(self).insertHTMLAsLastChild('div#frame', '
        KSS for a life. %s
        ' % (str(datetime.datetime.now()), )) return self.render() From reebalazs at codespeak.net Tue Sep 19 15:53:21 2006 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Tue, 19 Sep 2006 15:53:21 +0200 (CEST) Subject: [Kukit-checkins] r32495 - kukit/kukit.js/trunk/kukit Message-ID: <20060919135321.69A9D10083@code0.codespeak.net> Author: reebalazs Date: Tue Sep 19 15:53:20 2006 New Revision: 32495 Modified: kukit/kukit.js/trunk/kukit/resourcedata.js Log: implement parameter producer currentFormVarFromKssAttr Modified: kukit/kukit.js/trunk/kukit/resourcedata.js ============================================================================== --- kukit/kukit.js/trunk/kukit/resourcedata.js (original) +++ kukit/kukit.js/trunk/kukit/resourcedata.js Tue Sep 19 15:53:20 2006 @@ -130,6 +130,11 @@ throw 'currentFormVar method needs 0 or 1 argument (varname)'; } } break; + case 'currentFormVarFromKssAttr': { + if (this.args.length != 0 && this.args.length != 1) { + throw 'currentFormVarFromKssAttr method needs 1 or 2 argument (attrname, [recurseParents])'; + } + } break; case 'form': { if (this.args.length != 1) { throw 'form method needs 1 arguments (formname)'; @@ -193,6 +198,16 @@ parms[key] = kukit.fo.getValueOfFormElement(node); } } break; + case 'currentFormVarFromKssAttr': { + var argname = this.args[0]; + var recurseParents = false; + if (this.args.length == 2) { + kukit.ut.evalBool(this.args[1], '2nd attribute of currentFormVarForKssAttr must be a boolean'); + recurseParents = this.args[1]; + } + var formvarname = kukit.dom.getRecursiveAttribute(node, argname, recurseParents, kukit.dom.getKssAttribute); + parms[key] = kukit.fo.getFormVarFromCurrentForm(node, formvarname); + } break; case 'form': { parms[key] = kukit.fo.getAllFormVarsFromNamedForm(this.args[0]); } break; From reebalazs at codespeak.net Tue Sep 19 16:01:44 2006 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Tue, 19 Sep 2006 16:01:44 +0200 (CEST) Subject: [Kukit-checkins] r32496 - kukit/kukit.js/trunk/kukit Message-ID: <20060919140144.D9D6410083@code0.codespeak.net> Author: reebalazs Date: Tue Sep 19 16:01:43 2006 New Revision: 32496 Modified: kukit/kukit.js/trunk/kukit/resourcedata.js Log: fix Modified: kukit/kukit.js/trunk/kukit/resourcedata.js ============================================================================== --- kukit/kukit.js/trunk/kukit/resourcedata.js (original) +++ kukit/kukit.js/trunk/kukit/resourcedata.js Tue Sep 19 16:01:43 2006 @@ -131,7 +131,7 @@ } } break; case 'currentFormVarFromKssAttr': { - if (this.args.length != 0 && this.args.length != 1) { + if (this.args.length != 1 && this.args.length != 2) { throw 'currentFormVarFromKssAttr method needs 1 or 2 argument (attrname, [recurseParents])'; } } break; From gotcha at codespeak.net Tue Sep 19 16:11:36 2006 From: gotcha at codespeak.net (gotcha at codespeak.net) Date: Tue, 19 Sep 2006 16:11:36 +0200 (CEST) Subject: [Kukit-checkins] r32497 - in kukit/azax/trunk: . plugins/core Message-ID: <20060919141136.80D081007F@code0.codespeak.net> Author: gotcha Date: Tue Sep 19 16:11:34 2006 New Revision: 32497 Modified: kukit/azax/trunk/commands.py kukit/azax/trunk/plugins/core/commands.py Log: move selector creation Modified: kukit/azax/trunk/commands.py ============================================================================== --- kukit/azax/trunk/commands.py (original) +++ kukit/azax/trunk/commands.py Tue Sep 19 16:11:34 2006 @@ -32,7 +32,6 @@ from unicode_quirks import force_unicode from zope.interface import Interface import zope.component -from selectors import Selector, CssSelector, HtmlIdSelector from parsers import XmlParser, HtmlParser @@ -50,18 +49,6 @@ adapter = zope.component.getMultiAdapter((self, request), Interface, 'render') return adapter.render() - def getSelector(self, type, selector): - 'Get a selector of a given type' - return Selector(type, selector) - - # some more helpers... - - def getCssSelector(self, selector): - return CssSelector(selector) - - def getHtmlIdSelector(self, selector): - return HtmlIdSelector(selector) - class AzaxParam: implements(IAzaxParam) Modified: kukit/azax/trunk/plugins/core/commands.py ============================================================================== --- kukit/azax/trunk/plugins/core/commands.py (original) +++ kukit/azax/trunk/plugins/core/commands.py Tue Sep 19 16:11:34 2006 @@ -2,16 +2,29 @@ try: + from azax.selectors import Selector, CssSelector, HtmlIdSelector from azax.azaxview import AzaxViewAdapter from azax.deprecated import deprecated from azax.parsers import XmlParser, HtmlParser except ImportError: + from Products.azax.selectors import Selector, CssSelector, HtmlIdSelector from Products.azax.azaxview import AzaxViewAdapter from Products.azax.deprecated import deprecated from Products.azax.parsers import XmlParser, HtmlParser class KSSCoreCommands(AzaxViewAdapter): + + def getSelector(self, type, selector): + 'Get a selector of a given type' + return Selector(type, selector) + + def getCssSelector(self, selector): + return CssSelector(selector) + + def getHtmlIdSelector(self, selector): + return HtmlIdSelector(selector) + # XXX the list is not full: maybe complete them? From reebalazs at codespeak.net Tue Sep 19 17:52:11 2006 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Tue, 19 Sep 2006 17:52:11 +0200 (CEST) Subject: [Kukit-checkins] r32503 - kukit/kukit.js/trunk/kukit Message-ID: <20060919155211.2C8DF10082@code0.codespeak.net> Author: reebalazs Date: Tue Sep 19 17:52:10 2006 New Revision: 32503 Modified: kukit/kukit.js/trunk/kukit/plugin.js kukit/kukit.js/trunk/kukit/resourcedata.js Log: LoadEvent execution in a deferred way Modified: kukit/kukit.js/trunk/kukit/plugin.js ============================================================================== --- kukit/kukit.js/trunk/kukit/plugin.js (original) +++ kukit/kukit.js/trunk/kukit/plugin.js Tue Sep 19 17:52:10 2006 @@ -246,16 +246,19 @@ } if (oper.node != null && oper.node.tagName.toLowerCase() == 'iframe' && phase == 2) { kukit.logDebug('EventRule #' + oper.eventrule.getNr() + ' mergeid ' + oper.eventrule.kss_selector.mergeid + ' event selected delayed execution.'); + + // XXX + // This is really crap. We have no way to wait until the frame hase // loaded, the only workaround is to wait. This works or not. // XXX How could we do this in a solid way? var timer = new kukit.ut.TimerCounter(1000, function() { func_to_bind(); }); - timer.start(); + kukit.rd.loadScheduler.push(timer.start); } else { // for any other node than iframe, or even for iframe in phase1, we need to execute immediately. - func_to_bind(); + kukit.rd.loadScheduler.push(func_to_bind); } }; Modified: kukit/kukit.js/trunk/kukit/resourcedata.js ============================================================================== --- kukit/kukit.js/trunk/kukit/resourcedata.js (original) +++ kukit/kukit.js/trunk/kukit/resourcedata.js Tue Sep 19 17:52:10 2006 @@ -651,6 +651,48 @@ a concatenation of the event id and the event name. */ +// XXX TODO this has to be refactored, since it's all global now + +kukit.rd.LoadScheduler = function() { + this.items = []; +}; + +kukit.rd.LoadScheduler.prototype.empty = function() { + return (this.length() == 0); +}; + +kukit.rd.LoadScheduler.prototype.length = function() { + return this.items.length; +}; + +kukit.rd.LoadScheduler.prototype.push = function(f) { + if (this.items.length >= 100) { + throw ('Infinite recursion, stack full'); + } + this.items.push(f); +}; + +kukit.rd.LoadScheduler.prototype.execute = function() { + f = this.items.unshift(); + if (f) { + f(); + return true; + } else { + return false; + } +}; + +kukit.rd.LoadScheduler.prototype.executeAll = function() { + while(true) { + var success = this.execute(); + if (! success) { + break; + } + } +}; + +kukit.rd.loadScheduler = new kukit.rd.LoadScheduler(); + kukit.rd.RuleTable = function() { this.nodes = {}; }; @@ -681,6 +723,14 @@ counter += 1; } kukit.logDebug('Binding to ' + counter + ' nodes in grand total'); + // Execute the load actions in a deferred manner + var loadactions = kukit.rd.loadScheduler; + var action_length = loadactions.length(); + if (length != 0) { + kukit.logDebug('Start executing delayed load actions'); + loadactions.executeAll(); + kukit.logDebug('Executed' + action_length + ' load actions'); + } }; kukit.rd.uid = 0; From reebalazs at codespeak.net Tue Sep 19 18:19:57 2006 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Tue, 19 Sep 2006 18:19:57 +0200 (CEST) Subject: [Kukit-checkins] r32504 - kukit/kukit.js/trunk/kukit Message-ID: <20060919161957.F15B41007B@code0.codespeak.net> Author: reebalazs Date: Tue Sep 19 18:19:56 2006 New Revision: 32504 Modified: kukit/kukit.js/trunk/kukit/plugin.js Log: Fix Modified: kukit/kukit.js/trunk/kukit/plugin.js ============================================================================== --- kukit/kukit.js/trunk/kukit/plugin.js (original) +++ kukit/kukit.js/trunk/kukit/plugin.js Tue Sep 19 18:19:56 2006 @@ -255,7 +255,10 @@ var timer = new kukit.ut.TimerCounter(1000, function() { func_to_bind(); }); - kukit.rd.loadScheduler.push(timer.start); + var f = function () { + timer.start(); + } + kukit.rd.loadScheduler.push(f); } else { // for any other node than iframe, or even for iframe in phase1, we need to execute immediately. kukit.rd.loadScheduler.push(func_to_bind); From reebalazs at codespeak.net Tue Sep 19 19:03:10 2006 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Tue, 19 Sep 2006 19:03:10 +0200 (CEST) Subject: [Kukit-checkins] r32507 - kukit/kukit.js/trunk/kukit Message-ID: <20060919170310.9092110083@code0.codespeak.net> Author: reebalazs Date: Tue Sep 19 19:03:08 2006 New Revision: 32507 Modified: kukit/kukit.js/trunk/kukit/plugin.js kukit/kukit.js/trunk/kukit/resourcedata.js Log: Fix Modified: kukit/kukit.js/trunk/kukit/plugin.js ============================================================================== --- kukit/kukit.js/trunk/kukit/plugin.js (original) +++ kukit/kukit.js/trunk/kukit/plugin.js Tue Sep 19 19:03:08 2006 @@ -260,6 +260,7 @@ } kukit.rd.loadScheduler.push(f); } else { + kukit.logDebug('EventRule #' + oper.eventrule.getNr() + ' mergeid ' + oper.eventrule.kss_selector.mergeid + ' event selected normal postponed execution.'); // for any other node than iframe, or even for iframe in phase1, we need to execute immediately. kukit.rd.loadScheduler.push(func_to_bind); } Modified: kukit/kukit.js/trunk/kukit/resourcedata.js ============================================================================== --- kukit/kukit.js/trunk/kukit/resourcedata.js (original) +++ kukit/kukit.js/trunk/kukit/resourcedata.js Tue Sep 19 19:03:08 2006 @@ -658,10 +658,10 @@ }; kukit.rd.LoadScheduler.prototype.empty = function() { - return (this.length() == 0); + return (this.size() == 0); }; -kukit.rd.LoadScheduler.prototype.length = function() { +kukit.rd.LoadScheduler.prototype.size = function() { return this.items.length; }; @@ -683,12 +683,15 @@ }; kukit.rd.LoadScheduler.prototype.executeAll = function() { + var i = 0; while(true) { var success = this.execute(); + i++; if (! success) { break; } } + return i; }; kukit.rd.loadScheduler = new kukit.rd.LoadScheduler(); @@ -725,11 +728,10 @@ kukit.logDebug('Binding to ' + counter + ' nodes in grand total'); // Execute the load actions in a deferred manner var loadactions = kukit.rd.loadScheduler; - var action_length = loadactions.length(); - if (length != 0) { + if (! loadactions.empty()) { kukit.logDebug('Start executing delayed load actions'); - loadactions.executeAll(); - kukit.logDebug('Executed' + action_length + ' load actions'); + var nr = loadactions.executeAll(); + kukit.logDebug('Executed' + nr + ' load actions'); } }; From reebalazs at codespeak.net Tue Sep 19 19:18:20 2006 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Tue, 19 Sep 2006 19:18:20 +0200 (CEST) Subject: [Kukit-checkins] r32509 - in kukit/kukit.js/trunk: kukit tests Message-ID: <20060919171820.324D610087@code0.codespeak.net> Author: reebalazs Date: Tue Sep 19 19:18:17 2006 New Revision: 32509 Modified: kukit/kukit.js/trunk/kukit/requestmanager.js kukit/kukit.js/trunk/kukit/resourcedata.js kukit/kukit.js/trunk/tests/test_requestmanager.js Log: fix Modified: kukit/kukit.js/trunk/kukit/requestmanager.js ============================================================================== --- kukit/kukit.js/trunk/kukit/requestmanager.js (original) +++ kukit/kukit.js/trunk/kukit/requestmanager.js Tue Sep 19 19:18:17 2006 @@ -31,16 +31,20 @@ /* Request item. Encapsulates the sendout function and data. */ -kukit.rm.RequestItem = function(sendHook, url, timeoutHook, timeout, now) { +kukit.rm.RequestItem = function(sendHook, url, timeoutHook, timeout, category, now) { if (typeof(now) == 'undefined') { now = (new Date()).valueOf(); } + if (typeof(category) == 'undefined') { + category = null; + } this.sent = now; this.expire = now + timeout; this.handled = false; this.sendHook = sendHook; this.url = url; this.timeoutHook = timeoutHook; + this.category = category; // Generate a RID. Due to timeouting, we have enough // of these for not to overlap ever. this.rid = kukit.rm._rid; @@ -122,8 +126,7 @@ break; } else { // call the callback for this element - item.handled = true; - this.nr -= 1; + this.pop(item); this.callback(item); } } @@ -139,17 +142,70 @@ return next_expire; }; +/* The category timer queue manager + In addition of being a normal queue, + it handles one element per category + and cancels the previous one immediately. + +*/ + +kukit.rm.CategoryTimerQueue = function(callback) { + this.mainq = new kukit.rm.TimerQueue(callback); + this.categories = {}; +}; + +kukit.rm.CategoryTimerQueue.prototype.push = function(item) { + this.mainq.push(item); + // if this has a category, and we already have one out: + // cancel it. + var cat = item.category; + if (cat != null) { + var previtem = this.categories[cat]; + print(previtem); + if (typeof(previtem) != 'undefined') { + // Cancellation of the item + var success = this.pop(previtem); + if (success) { + // call the error callback. + this.callback(previtem); + } + // Remember this item + this.categories[cat] = item; + } + } +}; + +kukit.rm.CategoryTimerQueue.prototype.pop = function(item) { + var result = this.mainq.pop(item); + return result +}; + +kukit.rm.CategoryTimerQueue.prototype.handleExpiration = function(now) { + var nextWake = this.mainq.handleExpiration(now); + // clean up the cat tables + for (var cat in this.categories) { + var item = this.categories[cat]; + if (typeof(item) != 'undefined' && item.handled) { + delete this.categories[cat]; + } + } + return nextWake; +}; + /* The request manager */ -kukit.rm.RequestManager = function (name, maxNr, schedulerClass) { +kukit.rm.RequestManager = function (name, maxNr, timerQueueClass, schedulerClass) { // schedulerClass is mainly provided for debugging... this.waitingQueue = new kukit.ut.FifoQueue(); this.sentNr = 0; + if (! timerQueueClass) { + timerQueueClass = kukit.rm.TimerQueue; + } var self = this; var timeoutItem = function(item) { self.timeoutItem(item); } - this.timerQueue = new kukit.rm.TimerQueue(timeoutItem); + this.timerQueue = new timerQueueClass(timeoutItem); if (typeof(name) == undefined) { name = null; } @@ -308,7 +364,7 @@ /* request manager notification API */ -kukit.rm.RequestManager.prototype.notifyServer = function(sendHook, url, timeoutHook, timeout, now) { +kukit.rm.RequestManager.prototype.notifyServer = function(sendHook, url, timeoutHook, timeout, timerQueueClass, now) { // url is only for the logging // sendHook is the function that actually sends out the request. // sendHook will be called with one parameter: the 'item' array. @@ -324,7 +380,7 @@ // Default value of timeout timeout = this.sendingTimeout; } - var item = new kukit.rm.RequestItem(sendHook, url, timeoutHook, timeout, now); + var item = new kukit.rm.RequestItem(sendHook, url, timeoutHook, timeout, timerQueueClass, now); // Start timing the item immediately this.timerQueue.push(item); if (! this.isSentRequestQueueFull()) { Modified: kukit/kukit.js/trunk/kukit/resourcedata.js ============================================================================== --- kukit/kukit.js/trunk/kukit/resourcedata.js (original) +++ kukit/kukit.js/trunk/kukit/resourcedata.js Tue Sep 19 19:18:17 2006 @@ -673,7 +673,7 @@ }; kukit.rd.LoadScheduler.prototype.execute = function() { - f = this.items.unshift(); + var f = this.items.shift(); if (f) { f(); return true; @@ -686,10 +686,10 @@ var i = 0; while(true) { var success = this.execute(); - i++; if (! success) { break; } + i++; } return i; }; Modified: kukit/kukit.js/trunk/tests/test_requestmanager.js ============================================================================== --- kukit/kukit.js/trunk/tests/test_requestmanager.js (original) +++ kukit/kukit.js/trunk/tests/test_requestmanager.js Tue Sep 19 19:18:17 2006 @@ -46,13 +46,13 @@ }; // Push items at different timepoints, with same timeout q = new kukit.rm.TimerQueue(cbe); - var i1 = new kukit.rm.RequestItem(null, 1, null, 10000, 1000); + var i1 = new kukit.rm.RequestItem(null, 1, null, 10000, null, 1000); q.push(i1); - var i2 = new kukit.rm.RequestItem(null, 2, null, 10000, 2000); + var i2 = new kukit.rm.RequestItem(null, 2, null, 10000, null, 2000); q.push(i2); - var i3 = new kukit.rm.RequestItem(null, 3, null, 10000, 3000); + var i3 = new kukit.rm.RequestItem(null, 3, null, 10000, null, 3000); q.push(i3); - var i4 = new kukit.rm.RequestItem(null, 4, null, 10000, 4000); + var i4 = new kukit.rm.RequestItem(null, 4, null, 10000, null, 4000); q.push(i4); this.assertEquals(q.nr, 4); // pop 2, 4 @@ -79,7 +79,7 @@ this.testNormalSend = function() { // Test a simple send situation - var rm = new kukit.rm.RequestManager(null, 2, kukit.DummyScheduler); + var rm = new kukit.rm.RequestManager(null, 2, null, kukit.DummyScheduler); this.assertRmQueues(rm, 0, 0); // queues var sent = []; @@ -88,15 +88,15 @@ }; // send some elements - rm.notifyServer(cbs, 1, null, 10000, 1000); + rm.notifyServer(cbs, 1, null, 10000, null, 1000); this.assertRmQueues(rm, 1, 0); this.assertEquals(sent.length, 1); this.assertEquals(sent[0].url, 1); - rm.notifyServer(cbs, 2, null, 10000, 2000); + rm.notifyServer(cbs, 2, null, 10000, null, 2000); this.assertRmQueues(rm, 2, 0); this.assertEquals(sent.length, 2); this.assertEquals(sent[1].url, 2); - rm.notifyServer(cbs, 3, null, 10000, 3000); + rm.notifyServer(cbs, 3, null, 10000, null, 3000); this.assertRmQueues(rm, 2, 1); this.assertEquals(sent.length, 2); @@ -116,7 +116,7 @@ this.testSendWithTimeouts = function() { // Test a simple timeout situation - var rm = new kukit.rm.RequestManager(null, 2, kukit.DummyScheduler); + var rm = new kukit.rm.RequestManager(null, 2, null, kukit.DummyScheduler); this.assertRmQueues(rm, 0, 0); // queues var sent = []; @@ -129,12 +129,12 @@ }; // send some elements - rm.notifyServer(cbs, 1, thook, 10000, 1000); + rm.notifyServer(cbs, 1, thook, 10000, null, 1000); this.assertRmQueues(rm, 1, 0); this.assertEquals(sent.length, 1); this.assertEquals(sent[0].url, 1); this.assertEquals(timeout.length, 0); - rm.notifyServer(cbs, 2, thook, 10000, 2000); + rm.notifyServer(cbs, 2, thook, 10000, null, 2000); this.assertRmQueues(rm, 2, 0); this.assertEquals(sent.length, 2); this.assertEquals(sent[1].url, 2); @@ -161,7 +161,7 @@ this.testSendWithQueuedTimeout = function() { // Test timeout with queues not sent out - var rm = new kukit.rm.RequestManager(null, 2, kukit.DummyScheduler); + var rm = new kukit.rm.RequestManager(null, 2, null, kukit.DummyScheduler); this.assertRmQueues(rm, 0, 0); // queues var sent = []; @@ -170,15 +170,15 @@ }; // send some elements - rm.notifyServer(cbs, 1, null, 10000, 1000); + rm.notifyServer(cbs, 1, null, 10000, null, 1000); this.assertRmQueues(rm, 1, 0); this.assertEquals(sent.length, 1); this.assertEquals(sent[0].url, 1); - rm.notifyServer(cbs, 2, null, 10000, 2000); + rm.notifyServer(cbs, 2, null, 10000, null, 2000); this.assertRmQueues(rm, 2, 0); this.assertEquals(sent.length, 2); this.assertEquals(sent[1].url, 2); - rm.notifyServer(cbs, 3, null, 10000, 3000); + rm.notifyServer(cbs, 3, null, 10000, null, 3000); this.assertRmQueues(rm, 2, 1); this.assertEquals(sent.length, 2); @@ -203,7 +203,7 @@ this.testSendWithQueuedSwallowed = function() { // If the queued element is timed out, it it not sent out - var rm = new kukit.rm.RequestManager(null, 2, kukit.DummyScheduler); + var rm = new kukit.rm.RequestManager(null, 2, null, kukit.DummyScheduler); this.assertRmQueues(rm, 0, 0); // queues var sent = []; @@ -212,15 +212,15 @@ }; // send some elements - rm.notifyServer(cbs, 1, null, 10000, 1000); + rm.notifyServer(cbs, 1, null, 10000, null, 1000); this.assertRmQueues(rm, 1, 0); this.assertEquals(sent.length, 1); this.assertEquals(sent[0].url, 1); - rm.notifyServer(cbs, 2, null, 10000, 2000); + rm.notifyServer(cbs, 2, null, 10000, null, 2000); this.assertRmQueues(rm, 2, 0); this.assertEquals(sent.length, 2); this.assertEquals(sent[1].url, 2); - rm.notifyServer(cbs, 3, null, 8500, 3000); + rm.notifyServer(cbs, 3, null, 8500, null, 3000); this.assertRmQueues(rm, 2, 1); this.assertEquals(sent.length, 2); @@ -246,7 +246,7 @@ this.testAllTimedOut = function() { // If all elements are timed out - var rm = new kukit.rm.RequestManager(null, 2, kukit.DummyScheduler); + var rm = new kukit.rm.RequestManager(null, 2, null, kukit.DummyScheduler); this.assertRmQueues(rm, 0, 0); // queues var sent = []; @@ -255,15 +255,15 @@ }; // send some elements - rm.notifyServer(cbs, 1, null, 10000, 1000); + rm.notifyServer(cbs, 1, null, 10000, null, 1000); this.assertRmQueues(rm, 1, 0); this.assertEquals(sent.length, 1); this.assertEquals(sent[0].url, 1); - rm.notifyServer(cbs, 2, null, 10000, 2000); + rm.notifyServer(cbs, 2, null, 10000, null, 2000); this.assertRmQueues(rm, 2, 0); this.assertEquals(sent.length, 2); this.assertEquals(sent[1].url, 2); - rm.notifyServer(cbs, 3, null, 10000, 3000); + rm.notifyServer(cbs, 3, null, 10000, null, 3000); this.assertRmQueues(rm, 2, 1); this.assertEquals(sent.length, 2); @@ -284,7 +284,7 @@ this.testTimeoutHooks = function() { // Test if timeout hook(s) are called - var rm = new kukit.rm.RequestManager(null, 2, kukit.DummyScheduler); + var rm = new kukit.rm.RequestManager(null, 2, null, kukit.DummyScheduler); this.assertRmQueues(rm, 0, 0); // queues var sent = []; @@ -305,15 +305,15 @@ }; // send some elements - rm.notifyServer(cbs, 1, thook1, 10000, 1000); + rm.notifyServer(cbs, 1, thook1, 10000, null, 1000); this.assertRmQueues(rm, 1, 0); this.assertEquals(sent.length, 1); this.assertEquals(sent[0].url, 1); - rm.notifyServer(cbs, 2, thook2, 10000, 2000); + rm.notifyServer(cbs, 2, thook2, 10000, null, 2000); this.assertRmQueues(rm, 2, 0); this.assertEquals(sent.length, 2); this.assertEquals(sent[1].url, 2); - rm.notifyServer(cbs, 3, thook3, 10000, 3000); + rm.notifyServer(cbs, 3, thook3, 10000, null, 3000); this.assertRmQueues(rm, 2, 1); this.assertEquals(sent.length, 2); @@ -331,7 +331,85 @@ this.assertEquals(timeout3[0].url, 3); }; - + + this.testCategoryQueue = function() { + // If all elements are timed out + var rm = new kukit.rm.RequestManager(null, 2, kukit.rm.CategoryTimerQueue, kukit.DummyScheduler); + this.assertRmQueues(rm, 0, 0); + // queues + var sent = []; + var cbs = function(item) { + sent.push(item); + }; + + // send some elements + rm.notifyServer(cbs, 1, null, 10000, null, 1000); + this.assertRmQueues(rm, 1, 0); + this.assertEquals(sent.length, 1); + this.assertEquals(sent[0].url, 1); + rm.notifyServer(cbs, 2, null, 10000, null, 2000); + this.assertRmQueues(rm, 2, 0); + this.assertEquals(sent.length, 2); + this.assertEquals(sent[1].url, 2); + rm.notifyServer(cbs, 3, null, 10000, null, 3000); + this.assertRmQueues(rm, 2, 1); + this.assertEquals(sent.length, 2); + + // time out 1, 2, 3 + rm.checkTimeout(20000); + this.assertRmQueues(rm, 2, 1); + this.assertEquals(sent.length, 2); + + // receive the elements (will swallow the queued one) + this.assertEquals(sent[0].receivedResult(20010), false); + this.assertRmQueues(rm, 1, 0); + this.assertEquals(sent.length, 2); + this.assertEquals(sent[1].receivedResult(20020), false); + this.assertRmQueues(rm, 0, 0); + this.assertEquals(sent.length, 2); + + }; + + this.testCategoryQueueCancel = function() { + // Category queue cancellation + var rm = new kukit.rm.RequestManager(null, 2, kukit.rm.CategoryTimerQueue, kukit.DummyScheduler); + this.assertRmQueues(rm, 0, 0); + // queues + var sent = []; + var cbs = function(item) { + sent.push(item); + }; + + // send some elements + rm.notifyServer(cbs, 1, null, 10000, 1, 1000); + this.assertRmQueues(rm, 1, 0); + this.assertEquals(sent.length, 1); + this.assertEquals(sent[0].url, 1); + rm.notifyServer(cbs, 2, null, 10000, 1, 2000); + this.assertRmQueues(rm, 2, 0); + this.assertEquals(sent.length, 2); + this.assertEquals(sent[1].url, 2); + rm.notifyServer(cbs, 3, null, 10000, 1, 3000); + this.assertRmQueues(rm, 2, 1); + this.assertEquals(sent.length, 2); + + // no time out yet. + rm.checkTimeout(4000); + this.assertRmQueues(rm, 2, 1); + this.assertEquals(sent.length, 2); + + // receive the elements (will swallow the queued one) + this.assertEquals(sent[0].receivedResult(20010), false); + this.assertRmQueues(rm, 1, 0); + this.assertEquals(sent.length, 2); + this.assertEquals(sent[1].receivedResult(20020), false); + this.assertRmQueues(rm, 0, 0); + this.assertEquals(sent.length, 2); + + }; + + + }; kukit.RequestManagerTestCase.prototype = new kukit.UtilsTestCaseBase; From reebalazs at codespeak.net Tue Sep 19 19:20:06 2006 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Tue, 19 Sep 2006 19:20:06 +0200 (CEST) Subject: [Kukit-checkins] r32510 - in kukit/kukit.js/trunk: kukit tests Message-ID: <20060919172006.8BE0C10087@code0.codespeak.net> Author: reebalazs Date: Tue Sep 19 19:20:01 2006 New Revision: 32510 Modified: kukit/kukit.js/trunk/kukit/requestmanager.js kukit/kukit.js/trunk/tests/test_requestmanager.js Log: Ups Modified: kukit/kukit.js/trunk/kukit/requestmanager.js ============================================================================== --- kukit/kukit.js/trunk/kukit/requestmanager.js (original) +++ kukit/kukit.js/trunk/kukit/requestmanager.js Tue Sep 19 19:20:01 2006 @@ -31,20 +31,16 @@ /* Request item. Encapsulates the sendout function and data. */ -kukit.rm.RequestItem = function(sendHook, url, timeoutHook, timeout, category, now) { +kukit.rm.RequestItem = function(sendHook, url, timeoutHook, timeout, now) { if (typeof(now) == 'undefined') { now = (new Date()).valueOf(); } - if (typeof(category) == 'undefined') { - category = null; - } this.sent = now; this.expire = now + timeout; this.handled = false; this.sendHook = sendHook; this.url = url; this.timeoutHook = timeoutHook; - this.category = category; // Generate a RID. Due to timeouting, we have enough // of these for not to overlap ever. this.rid = kukit.rm._rid; @@ -126,7 +122,8 @@ break; } else { // call the callback for this element - this.pop(item); + item.handled = true; + this.nr -= 1; this.callback(item); } } @@ -142,70 +139,17 @@ return next_expire; }; -/* The category timer queue manager - In addition of being a normal queue, - it handles one element per category - and cancels the previous one immediately. - -*/ - -kukit.rm.CategoryTimerQueue = function(callback) { - this.mainq = new kukit.rm.TimerQueue(callback); - this.categories = {}; -}; - -kukit.rm.CategoryTimerQueue.prototype.push = function(item) { - this.mainq.push(item); - // if this has a category, and we already have one out: - // cancel it. - var cat = item.category; - if (cat != null) { - var previtem = this.categories[cat]; - print(previtem); - if (typeof(previtem) != 'undefined') { - // Cancellation of the item - var success = this.pop(previtem); - if (success) { - // call the error callback. - this.callback(previtem); - } - // Remember this item - this.categories[cat] = item; - } - } -}; - -kukit.rm.CategoryTimerQueue.prototype.pop = function(item) { - var result = this.mainq.pop(item); - return result -}; - -kukit.rm.CategoryTimerQueue.prototype.handleExpiration = function(now) { - var nextWake = this.mainq.handleExpiration(now); - // clean up the cat tables - for (var cat in this.categories) { - var item = this.categories[cat]; - if (typeof(item) != 'undefined' && item.handled) { - delete this.categories[cat]; - } - } - return nextWake; -}; - /* The request manager */ -kukit.rm.RequestManager = function (name, maxNr, timerQueueClass, schedulerClass) { +kukit.rm.RequestManager = function (name, maxNr, schedulerClass) { // schedulerClass is mainly provided for debugging... this.waitingQueue = new kukit.ut.FifoQueue(); this.sentNr = 0; - if (! timerQueueClass) { - timerQueueClass = kukit.rm.TimerQueue; - } var self = this; var timeoutItem = function(item) { self.timeoutItem(item); } - this.timerQueue = new timerQueueClass(timeoutItem); + this.timerQueue = new kukit.rm.TimerQueue(timeoutItem); if (typeof(name) == undefined) { name = null; } @@ -364,7 +308,7 @@ /* request manager notification API */ -kukit.rm.RequestManager.prototype.notifyServer = function(sendHook, url, timeoutHook, timeout, timerQueueClass, now) { +kukit.rm.RequestManager.prototype.notifyServer = function(sendHook, url, timeoutHook, timeout, now) { // url is only for the logging // sendHook is the function that actually sends out the request. // sendHook will be called with one parameter: the 'item' array. @@ -380,7 +324,7 @@ // Default value of timeout timeout = this.sendingTimeout; } - var item = new kukit.rm.RequestItem(sendHook, url, timeoutHook, timeout, timerQueueClass, now); + var item = new kukit.rm.RequestItem(sendHook, url, timeoutHook, timeout, now); // Start timing the item immediately this.timerQueue.push(item); if (! this.isSentRequestQueueFull()) { Modified: kukit/kukit.js/trunk/tests/test_requestmanager.js ============================================================================== --- kukit/kukit.js/trunk/tests/test_requestmanager.js (original) +++ kukit/kukit.js/trunk/tests/test_requestmanager.js Tue Sep 19 19:20:01 2006 @@ -46,13 +46,13 @@ }; // Push items at different timepoints, with same timeout q = new kukit.rm.TimerQueue(cbe); - var i1 = new kukit.rm.RequestItem(null, 1, null, 10000, null, 1000); + var i1 = new kukit.rm.RequestItem(null, 1, null, 10000, 1000); q.push(i1); - var i2 = new kukit.rm.RequestItem(null, 2, null, 10000, null, 2000); + var i2 = new kukit.rm.RequestItem(null, 2, null, 10000, 2000); q.push(i2); - var i3 = new kukit.rm.RequestItem(null, 3, null, 10000, null, 3000); + var i3 = new kukit.rm.RequestItem(null, 3, null, 10000, 3000); q.push(i3); - var i4 = new kukit.rm.RequestItem(null, 4, null, 10000, null, 4000); + var i4 = new kukit.rm.RequestItem(null, 4, null, 10000, 4000); q.push(i4); this.assertEquals(q.nr, 4); // pop 2, 4 @@ -79,7 +79,7 @@ this.testNormalSend = function() { // Test a simple send situation - var rm = new kukit.rm.RequestManager(null, 2, null, kukit.DummyScheduler); + var rm = new kukit.rm.RequestManager(null, 2, kukit.DummyScheduler); this.assertRmQueues(rm, 0, 0); // queues var sent = []; @@ -88,15 +88,15 @@ }; // send some elements - rm.notifyServer(cbs, 1, null, 10000, null, 1000); + rm.notifyServer(cbs, 1, null, 10000, 1000); this.assertRmQueues(rm, 1, 0); this.assertEquals(sent.length, 1); this.assertEquals(sent[0].url, 1); - rm.notifyServer(cbs, 2, null, 10000, null, 2000); + rm.notifyServer(cbs, 2, null, 10000, 2000); this.assertRmQueues(rm, 2, 0); this.assertEquals(sent.length, 2); this.assertEquals(sent[1].url, 2); - rm.notifyServer(cbs, 3, null, 10000, null, 3000); + rm.notifyServer(cbs, 3, null, 10000, 3000); this.assertRmQueues(rm, 2, 1); this.assertEquals(sent.length, 2); @@ -116,7 +116,7 @@ this.testSendWithTimeouts = function() { // Test a simple timeout situation - var rm = new kukit.rm.RequestManager(null, 2, null, kukit.DummyScheduler); + var rm = new kukit.rm.RequestManager(null, 2, kukit.DummyScheduler); this.assertRmQueues(rm, 0, 0); // queues var sent = []; @@ -129,12 +129,12 @@ }; // send some elements - rm.notifyServer(cbs, 1, thook, 10000, null, 1000); + rm.notifyServer(cbs, 1, thook, 10000, 1000); this.assertRmQueues(rm, 1, 0); this.assertEquals(sent.length, 1); this.assertEquals(sent[0].url, 1); this.assertEquals(timeout.length, 0); - rm.notifyServer(cbs, 2, thook, 10000, null, 2000); + rm.notifyServer(cbs, 2, thook, 10000, 2000); this.assertRmQueues(rm, 2, 0); this.assertEquals(sent.length, 2); this.assertEquals(sent[1].url, 2); @@ -161,7 +161,7 @@ this.testSendWithQueuedTimeout = function() { // Test timeout with queues not sent out - var rm = new kukit.rm.RequestManager(null, 2, null, kukit.DummyScheduler); + var rm = new kukit.rm.RequestManager(null, 2, kukit.DummyScheduler); this.assertRmQueues(rm, 0, 0); // queues var sent = []; @@ -170,15 +170,15 @@ }; // send some elements - rm.notifyServer(cbs, 1, null, 10000, null, 1000); + rm.notifyServer(cbs, 1, null, 10000, 1000); this.assertRmQueues(rm, 1, 0); this.assertEquals(sent.length, 1); this.assertEquals(sent[0].url, 1); - rm.notifyServer(cbs, 2, null, 10000, null, 2000); + rm.notifyServer(cbs, 2, null, 10000, 2000); this.assertRmQueues(rm, 2, 0); this.assertEquals(sent.length, 2); this.assertEquals(sent[1].url, 2); - rm.notifyServer(cbs, 3, null, 10000, null, 3000); + rm.notifyServer(cbs, 3, null, 10000, 3000); this.assertRmQueues(rm, 2, 1); this.assertEquals(sent.length, 2); @@ -203,7 +203,7 @@ this.testSendWithQueuedSwallowed = function() { // If the queued element is timed out, it it not sent out - var rm = new kukit.rm.RequestManager(null, 2, null, kukit.DummyScheduler); + var rm = new kukit.rm.RequestManager(null, 2, kukit.DummyScheduler); this.assertRmQueues(rm, 0, 0); // queues var sent = []; @@ -212,15 +212,15 @@ }; // send some elements - rm.notifyServer(cbs, 1, null, 10000, null, 1000); + rm.notifyServer(cbs, 1, null, 10000, 1000); this.assertRmQueues(rm, 1, 0); this.assertEquals(sent.length, 1); this.assertEquals(sent[0].url, 1); - rm.notifyServer(cbs, 2, null, 10000, null, 2000); + rm.notifyServer(cbs, 2, null, 10000, 2000); this.assertRmQueues(rm, 2, 0); this.assertEquals(sent.length, 2); this.assertEquals(sent[1].url, 2); - rm.notifyServer(cbs, 3, null, 8500, null, 3000); + rm.notifyServer(cbs, 3, null, 8500, 3000); this.assertRmQueues(rm, 2, 1); this.assertEquals(sent.length, 2); @@ -246,7 +246,7 @@ this.testAllTimedOut = function() { // If all elements are timed out - var rm = new kukit.rm.RequestManager(null, 2, null, kukit.DummyScheduler); + var rm = new kukit.rm.RequestManager(null, 2, kukit.DummyScheduler); this.assertRmQueues(rm, 0, 0); // queues var sent = []; @@ -255,15 +255,15 @@ }; // send some elements - rm.notifyServer(cbs, 1, null, 10000, null, 1000); + rm.notifyServer(cbs, 1, null, 10000, 1000); this.assertRmQueues(rm, 1, 0); this.assertEquals(sent.length, 1); this.assertEquals(sent[0].url, 1); - rm.notifyServer(cbs, 2, null, 10000, null, 2000); + rm.notifyServer(cbs, 2, null, 10000, 2000); this.assertRmQueues(rm, 2, 0); this.assertEquals(sent.length, 2); this.assertEquals(sent[1].url, 2); - rm.notifyServer(cbs, 3, null, 10000, null, 3000); + rm.notifyServer(cbs, 3, null, 10000, 3000); this.assertRmQueues(rm, 2, 1); this.assertEquals(sent.length, 2); @@ -284,7 +284,7 @@ this.testTimeoutHooks = function() { // Test if timeout hook(s) are called - var rm = new kukit.rm.RequestManager(null, 2, null, kukit.DummyScheduler); + var rm = new kukit.rm.RequestManager(null, 2, kukit.DummyScheduler); this.assertRmQueues(rm, 0, 0); // queues var sent = []; @@ -305,15 +305,15 @@ }; // send some elements - rm.notifyServer(cbs, 1, thook1, 10000, null, 1000); + rm.notifyServer(cbs, 1, thook1, 10000, 1000); this.assertRmQueues(rm, 1, 0); this.assertEquals(sent.length, 1); this.assertEquals(sent[0].url, 1); - rm.notifyServer(cbs, 2, thook2, 10000, null, 2000); + rm.notifyServer(cbs, 2, thook2, 10000, 2000); this.assertRmQueues(rm, 2, 0); this.assertEquals(sent.length, 2); this.assertEquals(sent[1].url, 2); - rm.notifyServer(cbs, 3, thook3, 10000, null, 3000); + rm.notifyServer(cbs, 3, thook3, 10000, 3000); this.assertRmQueues(rm, 2, 1); this.assertEquals(sent.length, 2); @@ -331,85 +331,7 @@ this.assertEquals(timeout3[0].url, 3); }; - - this.testCategoryQueue = function() { - // If all elements are timed out - var rm = new kukit.rm.RequestManager(null, 2, kukit.rm.CategoryTimerQueue, kukit.DummyScheduler); - this.assertRmQueues(rm, 0, 0); - // queues - var sent = []; - var cbs = function(item) { - sent.push(item); - }; - - // send some elements - rm.notifyServer(cbs, 1, null, 10000, null, 1000); - this.assertRmQueues(rm, 1, 0); - this.assertEquals(sent.length, 1); - this.assertEquals(sent[0].url, 1); - rm.notifyServer(cbs, 2, null, 10000, null, 2000); - this.assertRmQueues(rm, 2, 0); - this.assertEquals(sent.length, 2); - this.assertEquals(sent[1].url, 2); - rm.notifyServer(cbs, 3, null, 10000, null, 3000); - this.assertRmQueues(rm, 2, 1); - this.assertEquals(sent.length, 2); - - // time out 1, 2, 3 - rm.checkTimeout(20000); - this.assertRmQueues(rm, 2, 1); - this.assertEquals(sent.length, 2); - - // receive the elements (will swallow the queued one) - this.assertEquals(sent[0].receivedResult(20010), false); - this.assertRmQueues(rm, 1, 0); - this.assertEquals(sent.length, 2); - this.assertEquals(sent[1].receivedResult(20020), false); - this.assertRmQueues(rm, 0, 0); - this.assertEquals(sent.length, 2); - - }; - - this.testCategoryQueueCancel = function() { - // Category queue cancellation - var rm = new kukit.rm.RequestManager(null, 2, kukit.rm.CategoryTimerQueue, kukit.DummyScheduler); - this.assertRmQueues(rm, 0, 0); - // queues - var sent = []; - var cbs = function(item) { - sent.push(item); - }; - - // send some elements - rm.notifyServer(cbs, 1, null, 10000, 1, 1000); - this.assertRmQueues(rm, 1, 0); - this.assertEquals(sent.length, 1); - this.assertEquals(sent[0].url, 1); - rm.notifyServer(cbs, 2, null, 10000, 1, 2000); - this.assertRmQueues(rm, 2, 0); - this.assertEquals(sent.length, 2); - this.assertEquals(sent[1].url, 2); - rm.notifyServer(cbs, 3, null, 10000, 1, 3000); - this.assertRmQueues(rm, 2, 1); - this.assertEquals(sent.length, 2); - - // no time out yet. - rm.checkTimeout(4000); - this.assertRmQueues(rm, 2, 1); - this.assertEquals(sent.length, 2); - - // receive the elements (will swallow the queued one) - this.assertEquals(sent[0].receivedResult(20010), false); - this.assertRmQueues(rm, 1, 0); - this.assertEquals(sent.length, 2); - this.assertEquals(sent[1].receivedResult(20020), false); - this.assertRmQueues(rm, 0, 0); - this.assertEquals(sent.length, 2); - - }; - - - + }; kukit.RequestManagerTestCase.prototype = new kukit.UtilsTestCaseBase; From gotcha at codespeak.net Tue Sep 19 20:07:05 2006 From: gotcha at codespeak.net (gotcha at codespeak.net) Date: Tue, 19 Sep 2006 20:07:05 +0200 (CEST) Subject: [Kukit-checkins] r32512 - kukit/azax/trunk Message-ID: <20060919180705.392231008F@code0.codespeak.net> Author: gotcha Date: Tue Sep 19 20:07:03 2006 New Revision: 32512 Modified: kukit/azax/trunk/azaxview.py kukit/azax/trunk/interfaces.py Log: end of refactoring Modified: kukit/azax/trunk/azaxview.py ============================================================================== --- kukit/azax/trunk/azaxview.py (original) +++ kukit/azax/trunk/azaxview.py Tue Sep 19 20:07:03 2006 @@ -42,7 +42,6 @@ from Products.statusmessages import STATUSMESSAGEKEY from interfaces import IAzaxView -from interfaces import IAzaxMacro from commands import AzaxCommands class AzaxBaseView(BrowserView): @@ -79,11 +78,10 @@ def getCommands(self): return self.commands - def executeMacro(self, name, *args, **kwargs): - adapter = zapi.getAdapter(self, IAzaxMacro, name) - adapter.execute(*args, **kwargs) class AzaxViewAdapter: + + implements(IAzaxView) def __init__(self, view): self.view = view Modified: kukit/azax/trunk/interfaces.py ============================================================================== --- kukit/azax/trunk/interfaces.py (original) +++ kukit/azax/trunk/interfaces.py Tue Sep 19 20:07:03 2006 @@ -93,10 +93,6 @@ def getContent(self): '' -class IAzaxMacro(Interface): - def execute(*args, **kwargs): - '' - class IAzaxView(Interface): #XXX document all interface def render(): From gotcha at codespeak.net Tue Sep 19 20:07:45 2006 From: gotcha at codespeak.net (gotcha at codespeak.net) Date: Tue, 19 Sep 2006 20:07:45 +0200 (CEST) Subject: [Kukit-checkins] r32513 - kukit/kukit.js/trunk/kukit Message-ID: <20060919180745.8BB0D1008F@code0.codespeak.net> Author: gotcha Date: Tue Sep 19 20:07:43 2006 New Revision: 32513 Modified: kukit/kukit.js/trunk/kukit/resourcedata.js Log: cosmetics Modified: kukit/kukit.js/trunk/kukit/resourcedata.js ============================================================================== --- kukit/kukit.js/trunk/kukit/resourcedata.js (original) +++ kukit/kukit.js/trunk/kukit/resourcedata.js Tue Sep 19 20:07:43 2006 @@ -731,7 +731,7 @@ if (! loadactions.empty()) { kukit.logDebug('Start executing delayed load actions'); var nr = loadactions.executeAll(); - kukit.logDebug('Executed' + nr + ' load actions'); + kukit.logDebug('Executed ' + nr + ' load actions'); } }; From reebalazs at codespeak.net Wed Sep 20 09:17:10 2006 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Wed, 20 Sep 2006 09:17:10 +0200 (CEST) Subject: [Kukit-checkins] r32514 - kukit/azax/trunk Message-ID: <20060920071710.5F17210076@code0.codespeak.net> Author: reebalazs Date: Wed Sep 20 09:17:08 2006 New Revision: 32514 Modified: kukit/azax/trunk/azaxview.py Log: Remove unnecessary import that breaks zope 2.9 Modified: kukit/azax/trunk/azaxview.py ============================================================================== --- kukit/azax/trunk/azaxview.py (original) +++ kukit/azax/trunk/azaxview.py Wed Sep 20 09:17:08 2006 @@ -39,8 +39,6 @@ from zope.interface import implements from zope.app import zapi -from Products.statusmessages import STATUSMESSAGEKEY - from interfaces import IAzaxView from commands import AzaxCommands From reebalazs at codespeak.net Thu Sep 21 08:36:14 2006 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Thu, 21 Sep 2006 08:36:14 +0200 (CEST) Subject: [Kukit-checkins] r32550 - kukit/azaxdemo/trunk/browser Message-ID: <20060921063614.C980210075@code0.codespeak.net> Author: reebalazs Date: Thu Sep 21 08:36:13 2006 New Revision: 32550 Modified: kukit/azaxdemo/trunk/browser/preventdefault.kss Log: Adjust keyCode -> keyCodes syntax change Modified: kukit/azaxdemo/trunk/browser/preventdefault.kss ============================================================================== --- kukit/azaxdemo/trunk/browser/preventdefault.kss (original) +++ kukit/azaxdemo/trunk/browser/preventdefault.kss Thu Sep 21 08:36:13 2006 @@ -7,7 +7,7 @@ /* preventdefault is explicit on this.*/ input#text:keydown { evt-keydown-preventdefault: true; - evt-keydown-keyCode: 13; + evt-keydown-keyCodes: 13; action-client: log; } @@ -29,7 +29,7 @@ div#text-wrapper:keydown { evt-keydown-preventdefault: true; evt-keydown-allowbubbling: true; - evt-keydown-keyCode: 13; + evt-keydown-keyCodes: 13; action-client: log; } From reebalazs at codespeak.net Fri Sep 29 14:16:41 2006 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Fri, 29 Sep 2006 14:16:41 +0200 (CEST) Subject: [Kukit-checkins] r32738 - kukit/kukit.js/trunk/kukit Message-ID: <20060929121641.0335410036@code0.codespeak.net> Author: reebalazs Date: Fri Sep 29 14:16:39 2006 New Revision: 32738 Modified: kukit/kukit.js/trunk/kukit/plugin.js kukit/kukit.js/trunk/kukit/requestmanager.js Log: Critical IE fixes Modified: kukit/kukit.js/trunk/kukit/plugin.js ============================================================================== --- kukit/kukit.js/trunk/kukit/plugin.js (original) +++ kukit/kukit.js/trunk/kukit/plugin.js Fri Sep 29 14:16:39 2006 @@ -215,7 +215,7 @@ } else { kukit.logDebug('timer event key entered for actionEvent #' + key + ' ' + oper.eventrule.kss_selector.css); - var counter = new kukit.ut.TimerCounter(oper.parms.delay, func_to_bind, oper.parms.repeat) + var counter = new kukit.ut.TimerCounter(oper.parms.delay, func_to_bind, oper.parms.repeat); this.counters[key] = counter; // Start the counter counter.start(); Modified: kukit/kukit.js/trunk/kukit/requestmanager.js ============================================================================== --- kukit/kukit.js/trunk/kukit/requestmanager.js (original) +++ kukit/kukit.js/trunk/kukit/requestmanager.js Fri Sep 29 14:16:39 2006 @@ -150,7 +150,7 @@ self.timeoutItem(item); } this.timerQueue = new kukit.rm.TimerQueue(timeoutItem); - if (typeof(name) == undefined) { + if (typeof(name) == 'undefined') { name = null; } this.name = name; @@ -159,7 +159,7 @@ namestr = '[' + name + '] '; } this.namestr = namestr; - if (typeof(maxNr) != undefined && maxNr != null) { + if (typeof(maxNr) != 'undefined' && maxNr != null) { this.maxNr = maxNr; } // sets the timeout scheduler