From jvloothuis at codespeak.net Wed Jan 2 00:25:30 2008 From: jvloothuis at codespeak.net (jvloothuis at codespeak.net) Date: Wed, 2 Jan 2008 00:25:30 +0100 (CET) Subject: [KSS-checkins] r50246 - kukit/kss.base/branches/protocol-data-types/kss/base Message-ID: <20080101232530.B32ED1684E1@codespeak.net> Author: jvloothuis Date: Wed Jan 2 00:25:28 2008 New Revision: 50246 Modified: kukit/kss.base/branches/protocol-data-types/kss/base/commands.py Log: Ported support for global commands Changed the parameter types so that they have a specific `node` method. This is method used with a try except block in place of an instance type check (which makes the code more duck-typing aware). Modified: kukit/kss.base/branches/protocol-data-types/kss/base/commands.py ============================================================================== --- kukit/kss.base/branches/protocol-data-types/kss/base/commands.py (original) +++ kukit/kss.base/branches/protocol-data-types/kss/base/commands.py Wed Jan 2 00:25:28 2008 @@ -8,9 +8,10 @@ kss_response_footer = '' - kss_command_start = '' +kss_command_start_global = '' + kss_command_end = '' kss_param = '%(value)s' @@ -19,7 +20,8 @@ def __init__(self, value): self.value = value - def __str__(self): + def node(self): + '''Return the XML node representation of this object''' return '' % self.value.replace(']]>', ']]>') def __repr__(self): @@ -49,26 +51,32 @@ def render(self): output = [kss_response_header] for action, selector, options in self.commands: - try: - selector_type = selector.type - selector = selector.value - except AttributeError: - # It is probably a string or unicode object so we can - # let the client decide the default selector - selector_type = '' - - output.append(kss_command_start % dict( - selector=quoteattr(selector), - selector_type=quoteattr(selector_type), - action=quoteattr(action))) + if selector is None: + output.append(kss_command_start_global % dict( + action=quoteattr(action))) + else: + try: + selector_type = selector.type + selector = selector.value + except AttributeError: + # It is probably a string or unicode object so we + # can let the client decide the default selector + selector_type = '' + + output.append(kss_command_start % dict( + selector=quoteattr(selector), + selector_type=quoteattr(selector_type), + action=quoteattr(action))) for name, value in options.items(): - if isinstance(value, basestring): - value = escape(value) - else: - value = str(value) + try: + node = value.node() + except AttributeError: + # If it the value does not explicitly convert to a + # node make it a text node + node = escape(value) output.append(kss_param % dict( - name=quoteattr(name), value=value)) + name=quoteattr(name), value=node)) output.append(kss_command_end) output.append(kss_response_footer) return ''.join(output) From reebalazs at codespeak.net Wed Jan 2 22:14:39 2008 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Wed, 2 Jan 2008 22:14:39 +0100 (CET) Subject: [KSS-checkins] r50272 - in kukit/kukit.js/branch/ree-service-layer-and-refactoring: . tests Message-ID: <20080102211439.92477168508@codespeak.net> Author: reebalazs Date: Wed Jan 2 22:14:39 2008 New Revision: 50272 Modified: kukit/kukit.js/branch/ree-service-layer-and-refactoring/ (props changed) kukit/kukit.js/branch/ree-service-layer-and-refactoring/tests/test_interfaces.js Log: Fix typo Modified: kukit/kukit.js/branch/ree-service-layer-and-refactoring/tests/test_interfaces.js ============================================================================== --- kukit/kukit.js/branch/ree-service-layer-and-refactoring/tests/test_interfaces.js (original) +++ kukit/kukit.js/branch/ree-service-layer-and-refactoring/tests/test_interfaces.js Wed Jan 2 22:14:39 2008 @@ -383,7 +383,7 @@ iface.getAttribute('first').require({ preferredSources: ['corelib', 'extralib'], fallbackProvider: '++resource++one'}); - iface.getAttribute('seconf').require({ + iface.getAttribute('second').require({ preferredSources: ['corelib', 'extralib'], fallbackProvider: '++resource++two'}); iface.getAttribute('third').require({ From reebalazs at codespeak.net Fri Jan 4 16:07:32 2008 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Fri, 4 Jan 2008 16:07:32 +0100 (CET) Subject: [KSS-checkins] r50311 - kukit/kss.core/branch/finish-closures/docs Message-ID: <20080104150732.ABC00168513@codespeak.net> Author: reebalazs Date: Fri Jan 4 16:07:30 2008 New Revision: 50311 Added: kukit/kss.core/branch/finish-closures/docs/ - copied from r50168, kukit/kss.core/trunk/docs/ kukit/kss.core/branch/finish-closures/docs/HISTORY.txt - copied unchanged from r50168, kukit/kss.core/trunk/docs/HISTORY.txt kukit/kss.core/branch/finish-closures/docs/INSTALL.txt - copied unchanged from r50168, kukit/kss.core/trunk/docs/INSTALL.txt kukit/kss.core/branch/finish-closures/docs/LICENSE.GPL - copied unchanged from r50168, kukit/kss.core/trunk/docs/LICENSE.GPL kukit/kss.core/branch/finish-closures/docs/LICENSE.txt - copied unchanged from r50168, kukit/kss.core/trunk/docs/LICENSE.txt kukit/kss.core/branch/finish-closures/docs/TODO.txt - copied unchanged from r50168, kukit/kss.core/trunk/docs/TODO.txt kukit/kss.core/branch/finish-closures/docs/tutorial_part2.rst - copied unchanged from r50168, kukit/kss.core/trunk/docs/tutorial_part2.rst Log: (forgot) Add back docs where they belong, ported from trunk From reebalazs at codespeak.net Fri Jan 4 16:21:38 2008 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Fri, 4 Jan 2008 16:21:38 +0100 (CET) Subject: [KSS-checkins] r50312 - kukit/kss.demo/branch/finish-closures/kss/demo Message-ID: <20080104152138.0AF5F16850F@codespeak.net> Author: reebalazs Date: Fri Jan 4 16:21:38 2008 New Revision: 50312 Modified: kukit/kss.demo/branch/finish-closures/kss/demo/registry.py Log: Remove debug message that I forgot. Modified: kukit/kss.demo/branch/finish-closures/kss/demo/registry.py ============================================================================== --- kukit/kss.demo/branch/finish-closures/kss/demo/registry.py (original) +++ kukit/kss.demo/branch/finish-closures/kss/demo/registry.py Fri Jan 4 16:21:38 2008 @@ -141,8 +141,6 @@ """Add a demo collection to the registry. """ test_filenames = self._getSeleniumTestsFromPlugin(plugin) - # Sort filenames alphabetically - test_filenames.sort() for test_filename in test_filenames: self.registerSeleniumTestFile(test_filename) @@ -156,7 +154,6 @@ def registerSeleniumTestFile(self, test_filename): """Register a selenium test by absolute filename """ - print "-----", test_filename if test_filename in self.selenium_tests: raise Exception, 'The selenium test for %s has already been registered. Cannot add.' % (test_filename, ) self.selenium_tests.append(test_filename) From reebalazs at codespeak.net Fri Jan 4 17:49:09 2008 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Fri, 4 Jan 2008 17:49:09 +0100 (CET) Subject: [KSS-checkins] r50317 - kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes Message-ID: <20080104164909.A5F3616843F@codespeak.net> Author: reebalazs Date: Fri Jan 4 17:49:08 2008 New Revision: 50317 Added: kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/ - copied from r50316, kukit/kukit.js/trunk/ Log: Branch off From reebalazs at codespeak.net Fri Jan 4 17:57:25 2008 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Fri, 4 Jan 2008 17:57:25 +0100 (CET) Subject: [KSS-checkins] r50319 - in kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes: . doc kukit Message-ID: <20080104165725.E70D4168446@codespeak.net> Author: reebalazs Date: Fri Jan 4 17:57:24 2008 New Revision: 50319 Modified: kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/ (props changed) kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/doc/HISTORY.txt kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/forms.js kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/kssparser.js kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/oper.js kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/providerreg.js kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/resourcedata.js kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/selectorreg.js Log: Refactor value provider evaluation, make 1 registry out of 3. Remove deprecated form(), currentForm() providers in normal parameters. (It would take some more code to make them working but since they are deprecated long ago, I just removed them.) Modified: kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/doc/HISTORY.txt ============================================================================== --- kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/doc/HISTORY.txt (original) +++ kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/doc/HISTORY.txt Fri Jan 4 17:57:24 2008 @@ -6,6 +6,19 @@ - ... + - refactor the value provider registry to use + a single registry in place of 3. + This will enable to define value + providers that recieve non-string parameters + like a node selection. + + Remove previously deprecated form() and + currentForm() value providers from normal + action parameters (remark: they should + be used with kssSelector.) + They now give a parsing error. + [ree] + - Fix multiple selection form fields marshalling on Safari (fixes #22 in kssproject) Modified: kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/forms.js ============================================================================== --- kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/forms.js (original) +++ kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/forms.js Fri Jan 4 17:57:24 2008 @@ -1,5 +1,5 @@ /* -* Copyright (c) 2005-2007 +* Copyright (c) 2005-2008 * Authors: KSS Project Contributors (see doc/CREDITS.txt) * * This program is free software; you can redistribute it and/or modify @@ -307,14 +307,14 @@ this.fieldUpdateRegistry = new _FieldUpdateRegistry(); -// Registry of the pprovider functions for kssSubmitForm - -fo.pproviderFormRegistry = new kukit.pr.ValueProviderRegistry(); - -// form, currentForm will provide identical functions to those -// in normal parameters -// except they return a tuple list, not a dictionary. +// +// form, currentForm will fetch an entire form for marshalling. // This is needed because duplications and order must be preserved. +// The returnType of them will be registered as "formquery". This +// represents a list of (key, value) tuples that need to be marshalled. +// This assures to preserve order of keys, which is important +// for multi-values. +// /* * @@ -335,7 +335,7 @@ return fo.getAllFormVars(locator, collector); } }; -fo.pproviderFormRegistry.register('form', _FormValueProvider); +kukit.pprovidersGlobalRegistry.register('form', _FormValueProvider, 'formquery'); /* * @@ -355,12 +355,7 @@ return fo.getAllFormVars(locator, collector); } }; -fo.pproviderFormRegistry.register('currentForm', _CurrentFormValueProvider); - -// If a string is given, that will look like a form lookup, -// ie. identical to form -fo.pproviderFormRegistry.register('', _FormValueProvider); - +kukit.pprovidersGlobalRegistry.register('currentForm', _CurrentFormValueProvider, 'formquery'); /* BBB. To be deprecated on 2008-06-15 */ Modified: kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/kssparser.js ============================================================================== --- kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/kssparser.js (original) +++ kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/kssparser.js Fri Jan 4 17:57:24 2008 @@ -1,5 +1,5 @@ /* -* Copyright (c) 2005-2007 +* Copyright (c) 2005-2008 * Authors: KSS Project Contributors (see doc/CREDITS.txt) * * This program is free software; you can redistribute it and/or modify @@ -266,12 +266,6 @@ } kukit.kssp.Block.prototype.addActionParameter = function(action, key, value) { - var ppRegistries = { - '': kukit.pprovidersGlobalRegistry, - 'kssSelector': kukit.sr.pproviderSelRegistry, - 'kssSubmitForm': kukit.fo.pproviderFormRegistry - }; - // -: // default-: // @@ -282,22 +276,42 @@ // This will also set the value providers on the value // (from check). // - // Figure out which registry to use. - var registry = ppRegistries[key]; - if (typeof(registry) == 'undefined') { - // use default pproviders - registry = ppRegistries['']; - } - // try { // Check also sets the value provider on the value. - value.check(registry); + value.check(); } catch(e) { ;;; kukit.E = 'Error in value : ' + e + '.'; this.emitError(kukit.E); } +;;; // Check return type +;;; // strings are currently unwrapped and will have +;;; // returnType == undefined, so we check for that. +;;; var returnType = value.pprovider.returnType; +;;; if (key == 'kssSelector') { +;;; // for kssSelector, string or formquery expected +;;; if (returnType && returnType != 'string' && returnType != 'selection') { +;;; kukit.E = 'Expected string or a selection result and got [' + returnType; +;;; kukit.E += '] in the kss action parameter [kssSelector].'; +;;; this.emitError(kukit.E); +;;; } +;;; } else if (key == 'kssSubmitForm') { +;;; // for kssSelector, string or formquery expected +;;; if (returnType && returnType != 'string' && returnType != 'formquery') { +;;; kukit.E = 'Expected string or a formquery result and got [' + returnType; +;;; kukit.E += '] in the kss action parameter [kssSubmitForm].'; +;;; this.emitError(kukit.E); +;;; } +;;; } else { +;;; // for all other cases, string is expected +;;; if (returnType && returnType != 'string') { +;;; kukit.E = 'Expected string and got [' + returnType; +;;; kukit.E += '] in the action parameter [' + key + '].'; +;;; this.emitError(kukit.E); +;;; } +;;; } + // store the value action.parms[key] = value; -} +}; kukit.kssp.Block.prototype.addDeclaration = function(key, value) { // p.s. value is here a KssXxParm. In most cases we check and unwrap it. Modified: kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/oper.js ============================================================================== --- kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/oper.js (original) +++ kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/oper.js Fri Jan 4 17:57:24 2008 @@ -204,18 +204,27 @@ }; kukit.op.Oper.prototype.executeServerAction = function(name) { -;;; for (key in this.kssParms) { -;;; if (key == 'kssUrl') { -;;; // Value will be evaluated. -;;; } else if (key == 'kssSubmitForm') { + for (key in this.kssParms) { + if (key == 'kssSubmitForm') { + // Value has been evaluated at this point. + var formQuery = this.kssParms[key]; + // If a string is returned: this is to support + // kssSubmitForm: "formname"; + // in this case this is evaluated as form("formname"). + if (typeof(formQuery) == 'string') { + var locator = new kukit.fo.NamedFormLocator(formQuery); + var collector = new kukit.ut.TupleCollector(); + formQuery = kukit.fo.getAllFormVars(locator, collector); + } +;;; } else if (key == 'kssUrl') { ;;; // Value will be evaluated. ;;; } else { ;;; kukit.E = 'Wrong parameter : [' + key + '] starts with "kss";'; ;;; kukit.E += ' normal parms (that do not start with kss)'; ;;; kukit.E += ' only are allowed in action-server keys.'; ;;; throw new Error(kukit.E); -;;; } -;;; } + } + } // oper will be accessible to some commands that execute in return var sa = new kukit.sa.ServerAction(name, this); }; Modified: kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/providerreg.js ============================================================================== --- kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/providerreg.js (original) +++ kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/providerreg.js Fri Jan 4 17:57:24 2008 @@ -1,5 +1,5 @@ /* -* Copyright (c) 2005-2007 +* Copyright (c) 2005-2008 * Authors: KSS Project Contributors (see doc/CREDITS.txt) * * This program is free software; you can redistribute it and/or modify @@ -29,7 +29,7 @@ this.content = {}; }; -kukit.pr.ValueProviderRegistry.prototype.register = function(name, func) { +kukit.pr.ValueProviderRegistry.prototype.register = function(name, func, returnType) { if (typeof(func) == 'undefined') { ;;; kukit.E = 'func argument is mandatory when registering a parameter' ;;; kukit.E += ' provider [ValueProviderRegistry.register].'; @@ -43,6 +43,11 @@ ;;; return; ;;; } this.content[name] = func; + // Handle return type + // XXX Store it on the func's prototype. + // This is a temporary solution, the service-layer + // branch offers a proper way to do this. + func.prototype.returnType = returnType; }; kukit.pr.ValueProviderRegistry.prototype.exists = function(name) { @@ -165,43 +170,6 @@ kukit.pprovidersGlobalRegistry.register('currentFormVarFromKssAttr', kukit.pr.CurrentFormVarFromKssAttrPP); - -/* BBB. To be deprecated at 2007-08-15 */ -kukit.pr.FormPP = function() {}; -kukit.pr.FormPP.prototype = { - check: function(args) { -;;; if (args.length != 1) { -;;; throw new Error('form method needs 1 arguments [formname]'); -;;; } -;;; var msg = 'Deprecated the [form(formname)] parameter provider,'; -;;; msg += ' use [xxx-kssSubmitForm: form(formname)] instead !'; -;;; kukit.logWarning(msg); - }, - eval: function(args, node) { - return kukit.fo.getAllFormVars(new kukit.fo.NamedFormLocator(args[0]), - new kukit.ut.DictCollector()); - } -}; -kukit.pprovidersGlobalRegistry.register('form', kukit.pr.FormPP); - -/* BBB. To be deprecated at 2007-08-15 */ -kukit.pr.CurrentFormPP = function() {}; -kukit.pr.CurrentFormPP.prototype = { - check: function(args) { -;;; if (args.length != 0) { -;;; throw new Error('currentForm method needs no argument'); -;;; } -;;; var msg = 'Deprecated the [currentForm()] parameter provider,'; -;;; msg += ' use [xxx-kssSubmitForm: currentForm()] instead !'; -;;; kukit.logWarning(msg); - }, - eval: function(args, node) { - return kukit.fo.getAllFormVars(new kukit.fo.CurrentFormLocator(node), - new kukit.ut.DictCollector()); - } -}; -kukit.pprovidersGlobalRegistry.register('currentForm', kukit.pr.CurrentFormPP); - kukit.pr.NodeAttrPP = function() {}; kukit.pr.NodeAttrPP.prototype = { check: function(args) { Modified: kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/resourcedata.js ============================================================================== --- kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/resourcedata.js (original) +++ kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/resourcedata.js Fri Jan 4 17:57:24 2008 @@ -1,5 +1,5 @@ /* -* Copyright (c) 2005-2007 +* Copyright (c) 2005-2008 * Authors: KSS Project Contributors (see doc/CREDITS.txt) * * This program is free software; you can redistribute it and/or modify @@ -154,9 +154,9 @@ kukit.rd.KssTextValue.prototype.isMethod = false; -kukit.rd.KssTextValue.prototype.check = function(registry) { +kukit.rd.KssTextValue.prototype.check = function() { // use the IdentityPP provider. - this.pprovider = new (registry.get(''))(); + this.pprovider = new (kukit.pprovidersGlobalRegistry.get(''))(); }; kukit.rd.KssTextValue.prototype.evaluate = @@ -179,22 +179,44 @@ kukit.rd.KssMethodValue.prototype.isMethod = true; -kukit.rd.KssMethodValue.prototype.check = function(registry) { +kukit.rd.KssMethodValue.prototype.check = function() { // Check syntax - var f = registry.get(this.methodName); + var f = kukit.pprovidersGlobalRegistry.get(this.methodName); this.pprovider = new f(); +;;; //Check the provider first. +;;; this.pprovider.check(this.args); + // After checking the provider, we check the args recursively. for(i=0; i < this.args.length; i++){ // XXX We treat text values separetly because // they are now currently wrapped as KssTextValue // (as they should). TODO var arg = this.args[i]; + // XXX this is a check for a MethodValue, since + // all text arguments are strings. -- this is fixed + // on the service-layer branch if(arg.check){ - // With the recursion we always use the global - // provider registry - arg.check(kukit.pprovidersGlobalRegistry); + arg.check(); +;;; // The page provider should have checked if the parameters +;;; // return the appropriate value type. If it has done +;;; // this check, it has set checkedArgTypes. +;;; // If a provider expects all strings +;;; // (like most value providers), it simply leaves this flag +;;; // intact, and we do the check here. +;;; if (! this.checkedArgTypes) { +;;; // We expect a string to each position. +;;; // By default, returnType is "string" so we also +;;; // check undefined. +;;; var returnType = arg.pprovider.returnType; +;;; if (returnType && returnType != 'string') { +;;; kukit.E = 'Expected string value and got [' + returnType; +;;; kukit.E += '] in argument #[' + (i + 1) + '] of provider ['; +;;; kukit.E += this.methodName + '].'; +;;; throw new Error(kukit.E); +;;; } +;;; } + } } -;;; this.pprovider.check(this.args); }; kukit.rd.KssMethodValue.prototype.evaluate = @@ -599,6 +621,17 @@ } }; +// The evaluation of string is handled specially +// in case of some parameter names. +// +// kssSelector string "foo" evaluates as css("foo") +// kssSubmitForm string "foo" evaluates as form("foo") +// +kukit.rd.Action.prototype.defaultStringHandling = { + 'kssSelector': 'css', + 'kssSubmitForm': 'form' +}; + kukit.rd.Action.prototype.makeActionOper = function(oper) { // Fill the completed action parms, based on the node // The kssXxx parms, reserved for the action, are @@ -610,16 +643,30 @@ if (typeof(oper.defaultParameters) == 'undefined') { oper.defaultParameters = {}; } + // Evaluate all parameters. for (var key in this.parms) { - var kssvalue = this.parms[key]; + // Evaluate the value of the parameter. + var value = this.parms[key].evaluate(oper.node, + oper.defaultParameters); + // Final handling of special cases. + // This is needed in case we have a string, and we + // look up the provider we need from the defaultStringHandling table. + var providerName = this.defaultStringHandling[key]; + if (providerName && typeof(value) == 'string') { + // Use the value provider. This means the string is + // a shortcut and this provider is applied. + var providerClass = kukit.pprovidersGlobalRegistry.get(providerName); + var provider = new providerClass(); + // check is not needed now... we evaluate it right away + value = provider.eval([value], oper.node, oper.defaultParameters); + } + // Store it, depending if it's a kss or normal parameter. if (key.match(/^kss/)) { // kssXxx parms are separated to kssParms. - kssParms[key] = kssvalue.evaluate(oper.node, - oper.defaultParameters); + kssParms[key] = value; } else { // evaluate the method parms into parms - parms[key] = kssvalue.evaluate(oper.node, - oper.defaultParameters); + parms[key] = value; } } var anOper = oper.clone({ Modified: kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/selectorreg.js ============================================================================== --- kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/selectorreg.js (original) +++ kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/selectorreg.js Fri Jan 4 17:57:24 2008 @@ -1,5 +1,5 @@ /* -* Copyright (c) 2005-2007 +* Copyright (c) 2005-2008 * Authors: KSS Project Contributors (see doc/CREDITS.txt) * * This program is free software; you can redistribute it and/or modify @@ -19,11 +19,6 @@ kukit.sr = {}; -// Registry of the pprovider functions for selecting - -kukit.sr.pproviderSelRegistry = new kukit.pr.ValueProviderRegistry(); - - // this will provide an arbitrary selector, and is designed to // be used with the makeAnyPP factory function. kukit.sr.AnyPP = function() {}; @@ -43,8 +38,6 @@ } }; -kukit.sr.pproviderSelRegistry.register('', kukit.sr.AnyPP); - kukit.sr.makeAnyPP = function(selector_type) { var pp = function () {}; pp.prototype.eval = kukit.sr.AnyPP.prototype.eval; @@ -72,7 +65,7 @@ return nodes; } }; -kukit.sr.pproviderSelRegistry.register('passnode', kukit.sr.PassnodePP); +kukit.pprovidersGlobalRegistry.register('passnode', kukit.sr.PassnodePP, 'selection'); /* @@ -103,7 +96,8 @@ this.mapping[name] = func; // Also register the selector param provider var pp = kukit.sr.makeAnyPP(name); - kukit.sr.pproviderSelRegistry.register(name, pp); + // register them with returnType = 'nodes' + kukit.pprovidersGlobalRegistry.register(name, pp, 'selection'); }; kukit.sr.SelectorTypeRegistry.prototype.get = function(name) { From reebalazs at codespeak.net Fri Jan 4 17:57:29 2008 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Fri, 4 Jan 2008 17:57:29 +0100 (CET) Subject: [KSS-checkins] r50320 - in kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes: . kukit tests Message-ID: <20080104165729.9CC3B16844E@codespeak.net> Author: reebalazs Date: Fri Jan 4 17:57:28 2008 New Revision: 50320 Modified: kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/ (props changed) kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/providerreg.js kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/resourcedata.js kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/tests/runtests.js kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/tests/test_kssparser.js Log: Add ecma tests to check handling of value provider return types Modified: kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/providerreg.js ============================================================================== --- kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/providerreg.js (original) +++ kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/providerreg.js Fri Jan 4 17:57:28 2008 @@ -178,15 +178,15 @@ ;;; kukit.E += ' [recurseParents]).'; ;;; throw new Error(kukit.E); ;;; } -;;; if (args[0].toLowerCase() == 'style') { + }, + eval: function(args, node) { + var argname = args[0]; +;;; if (argname.toLowerCase() == 'style') { ;;; throw new Error('nodeAttr method does not accept [style] as attrname.'); ;;; } -;;; if (args[0].match(/[ ]/)) { +;;; if (argname.match(/[ ]/)) { ;;; throw new Error('attrname parameter in nodeAttr method cannot contain space.'); ;;; } - }, - eval: function(args, node) { - var argname = args[0]; var recurseParents = false; if (args.length == 2) { recurseParents = args[1]; Modified: kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/resourcedata.js ============================================================================== --- kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/resourcedata.js (original) +++ kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/resourcedata.js Fri Jan 4 17:57:28 2008 @@ -186,7 +186,7 @@ ;;; //Check the provider first. ;;; this.pprovider.check(this.args); // After checking the provider, we check the args recursively. - for(i=0; i < this.args.length; i++){ + for(var i=0; i < this.args.length; i++){ // XXX We treat text values separetly because // they are now currently wrapped as KssTextValue // (as they should). TODO Modified: kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/tests/runtests.js ============================================================================== --- kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/tests/runtests.js (original) +++ kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/tests/runtests.js Fri Jan 4 17:57:28 2008 @@ -22,6 +22,7 @@ testsuite.registerTest(kukit.TokenizerTestCase); testsuite.registerTest(kukit.KssParserTestCase); testsuite.registerTest(kukit.KssParserSelectorsTestCase); + testsuite.registerTest(kukit.KssParserValueProvidersCheckTestCase); testsuite.registerTest(kukit.KssParserSelectorTestCase); testsuite.runSuite(); }; Modified: kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/tests/test_kssparser.js ============================================================================== --- kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/tests/test_kssparser.js (original) +++ kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/tests/test_kssparser.js Fri Jan 4 17:57:28 2008 @@ -226,7 +226,7 @@ this.assertParsingError(kukit.kssp.PropValue, cursor, null, true, 'Wrong value : unallowed characters after the property', 17); }; - + this.testEventValueSimple = function() { // Parsing event value var txt= "b"; @@ -813,6 +813,245 @@ kukit.KssParserTestCase.prototype = new kukit.KssParserTestCaseBase; +kukit.KssParserValueProvidersCheckTestCase = function() { + this.name = 'kukit.KssParserValueProvidersCheckTestCase'; + // Different tests to see if the syntax type check of + // the value providers is working correctly. + // At the moment we have the following return value types: + // string, selection, formquery + // We do not check the actual evaluation here, as we + // have no DOM at hand. + // + // This testcase is added in DEVELOPMENT MODE ONLY. + + this.testNormalProviderAcceptsString = function() { + // normal providers does accept string + // + // This test can only run in development mode, pass otherwise. + if (! kukit.isDevelMode) {return;} + // + var txt= "nodeAttr('id')"; + var cursor = new kukit.tk.Cursor(txt); + var parser = new kukit.kssp.PropValue(cursor, null, true); + var value = parser.value; + value.check(); + }; + + this.testNormalProviderRejectsSelection = function() { + // normal providers does not accept selection + // + // This test can only run in development mode, pass otherwise. + if (! kukit.isDevelMode) {return;} + // + var txt= "nodeAttr('id')"; + var txt= "nodeAttr(htmlid('id'))"; + var cursor = new kukit.tk.Cursor(txt); + var parser = new kukit.kssp.PropValue(cursor, null, true); + var value = parser.value; + this.assertThrows(function() { + value.check(); + }, + Error); + }; + + this.testNormalProviderRejectsSelectionFullRule = function() { + // normal providers do not accept selection + // full rule + // + // This test can only run in development mode, pass otherwise. + if (! kukit.isDevelMode) {return;} + // + var txt= "nodeAttr('id')"; + var txt= "#id:click {\n" + + " action-client: log;\n" + + " log-message: nodeAttr(htmlid('id'));\n" + + "}\n" + var cursor = new kukit.tk.Cursor(txt); + this.assertParsingError(kukit.kssp.Document, cursor, null, true, + // XXX This error message will be fixed in service-layer branch + 'Error in value : Error: Expected string value and got [selection] in argument #[1] of provider [nodeAttr].., at row 1, column 11'); + }; + + this.testNormalProviderRejectsFormQuery = function() { + // normal providers do not accept form query + // + // This test can only run in development mode, pass otherwise. + if (! kukit.isDevelMode) {return;} + // + var txt= "nodeAttr('id')"; + var txt= "nodeAttr(form('name'))"; + var cursor = new kukit.tk.Cursor(txt); + var parser = new kukit.kssp.PropValue(cursor, null, true); + var value = parser.value; + this.assertThrows(function() { + value.check(); + }, + Error); + }; + + this.testNormalProviderRejectsFormQueryFullRule = function() { + // normal providers do not accept form query + // full rule + // + // This test can only run in development mode, pass otherwise. + if (! kukit.isDevelMode) {return;} + // + var txt= "nodeAttr('id')"; + var txt= "#id:click {\n" + + " action-client: log;\n" + + " log-message: nodeAttr(form('name'));\n" + + "}\n" + var cursor = new kukit.tk.Cursor(txt); + this.assertParsingError(kukit.kssp.Document, cursor, null, true, + // XXX This error message will be fixed in service-layer branch + 'Error in value : Error: Expected string value and got [formquery] in argument #[1] of provider [nodeAttr].., at row 1, column 11'); + }; + + this.testNormalProviderRejectsSelector = function() { + // normal parameters do not accept selector + // + // This test can only run in development mode, pass otherwise. + if (! kukit.isDevelMode) {return;} + // + var txt= "nodeAttr('id')"; + var txt= "#id:click {\n" + + " action-client: log;\n" + + " log-message: htmlid('id');\n" + + "}\n" + var cursor = new kukit.tk.Cursor(txt); + this.assertParsingError(kukit.kssp.Document, cursor, null, true, + // XXX This error message will be fixed in service-layer branch + 'Expected string and got [selection] in the action parameter [message]., at row 1, column 11'); + }; + + this.testNormalProviderRejectsFormQuery = function() { + // normal parameters do not accept form query + // + // This test can only run in development mode, pass otherwise. + if (! kukit.isDevelMode) {return;} + // + var txt= "nodeAttr('id')"; + var txt= "#id:click {\n" + + " action-client: log;\n" + + " log-message: form('name');\n" + + "}\n" + var cursor = new kukit.tk.Cursor(txt); + this.assertParsingError(kukit.kssp.Document, cursor, null, true, + // XXX This error message will be fixed in service-layer branch + 'Expected string and got [formquery] in the action parameter [message]., at row 1, column 11'); + }; + + this.testKssSelectorAcceptsSelector = function() { + // kssSelector accepts selector + // + // This test can only run in development mode, pass otherwise. + if (! kukit.isDevelMode) {return;} + // + var txt= "nodeAttr('id')"; + var txt= "#id:click {\n" + + " action-client: setAttribute;\n" + + " setAttribute-kssSelector: htmlid('id');\n" + + " setAttribute-name: name;\n" + + " setAttribute-value: value;\n" + + "}\n" + var cursor = new kukit.tk.Cursor(txt); + var parser = new kukit.kssp.Document(cursor, null, true); + this.assertEquals(parser.finished, true); + }; + + this.testKssSelectorAcceptsString = function() { + // kssSelector accepts string + // (it will evaluate as css(xxx), but we can't check that without a dom) + // + // This test can only run in development mode, pass otherwise. + if (! kukit.isDevelMode) {return;} + // + var txt= "nodeAttr('id')"; + var txt= "#id:click {\n" + + " action-client: setAttribute;\n" + + " setAttribute-kssSelector: htmlid('id');\n" + + " setAttribute-name: name;\n" + + " setAttribute-value: value;\n" + + "}\n" + var cursor = new kukit.tk.Cursor(txt); + var parser = new kukit.kssp.Document(cursor, null, true); + this.assertEquals(parser.finished, true); + }; + + this.testKssSelectorRejectsFormQuery = function() { + // kssSelector rejects form query + // + // This test can only run in development mode, pass otherwise. + if (! kukit.isDevelMode) {return;} + // + var txt= "nodeAttr('id')"; + var txt= "#id:click {\n" + + " action-client: setAttribute;\n" + + " setAttribute-kssSelector: form('name');\n" + + " setAttribute-name: name;\n" + + " setAttribute-value: value;\n" + + "}\n" + var cursor = new kukit.tk.Cursor(txt); + this.assertParsingError(kukit.kssp.Document, cursor, null, true, + // XXX This error message will be fixed in service-layer branch + 'Expected string or a selection result and got [formquery] in the kss action parameter [kssSelector]., at row 1, column 11'); + }; + + this.testKssSubmitFormAcceptsFormQuery = function() { + // kssSubmitForm accepts form query + // + // This test can only run in development mode, pass otherwise. + if (! kukit.isDevelMode) {return;} + // + var txt= "nodeAttr('id')"; + var txt= "#id:click {\n" + + " action-server: doIt;\n" + + " doIt-kssSubmitForm: form('name');\n" + + "}\n" + var cursor = new kukit.tk.Cursor(txt); + var parser = new kukit.kssp.Document(cursor, null, true); + this.assertEquals(parser.finished, true); + }; + + this.testKssSubmitFormAcceptsString = function() { + // kssSubmitForm accepts string + // (it will evaluate as form(xxx), but we can't check that without a dom) + // + // This test can only run in development mode, pass otherwise. + if (! kukit.isDevelMode) {return;} + // + var txt= "nodeAttr('id')"; + var txt= "#id:click {\n" + + " action-server: doIt;\n" + + " doIt-kssSubmitForm: 'name';\n" + + "}\n" + var cursor = new kukit.tk.Cursor(txt); + var parser = new kukit.kssp.Document(cursor, null, true); + this.assertEquals(parser.finished, true); + }; + + this.testKssSubmitFormRejectsSelection = function() { + // kssSubmitForm rejects selection + // + // This test can only run in development mode, pass otherwise. + if (! kukit.isDevelMode) {return;} + // + var txt= "nodeAttr('id')"; + var txt= "#id:click {\n" + + " action-server: doIt;\n" + + " doIt-kssSubmitForm: htmlid('id');\n" + + "}\n" + var cursor = new kukit.tk.Cursor(txt); + this.assertParsingError(kukit.kssp.Document, cursor, null, true, + // XXX This error message will be fixed in service-layer branch + 'Expected string or a formquery result and got [selection] in the kss action parameter [kssSubmitForm]., at row 1, column 11'); + }; + +}; + +kukit.KssParserValueProvidersCheckTestCase.prototype = new kukit.KssParserTestCaseBase; + + kukit.KssParserSelectorTestCase = function() { this.name = 'kukit.KssParserSelectorTestCase'; @@ -1115,6 +1354,7 @@ this.assertParsingError(kukit.kssp.KssSelector, cursor, null, true, 'Error : undefined namespace or event in [dnd-drog].'); } + }; kukit.KssParserSelectorTestCase.prototype = new kukit.KssParserTestCaseBase; @@ -1476,6 +1716,8 @@ if (typeof(testcase_registry) != 'undefined') { testcase_registry.registerTestCase(kukit.KssParserTestCase, 'kukit.KssParserTestCase'); + testcase_registry.registerTestCase(kukit.KssParserValueProvidersCheckTestCase, + 'kukit.KssParserValueProvidersCheckTestCase'); testcase_registry.registerTestCase(kukit.KssParserSelectorTestCase, 'kukit.KssParserSelectorTestCase'); testcase_registry.registerTestCase(kukit.KssParserSelectorsTestCase, From reebalazs at codespeak.net Fri Jan 4 17:57:32 2008 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Fri, 4 Jan 2008 17:57:32 +0100 (CET) Subject: [KSS-checkins] r50321 - in kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes: . kukit Message-ID: <20080104165732.1FC61168449@codespeak.net> Author: reebalazs Date: Fri Jan 4 17:57:31 2008 New Revision: 50321 Modified: kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/ (props changed) kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/providerreg.js Log: Relocate a check that needs to be in eval now, because it needs to check the evaluated value. Modified: kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/providerreg.js ============================================================================== --- kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/providerreg.js (original) +++ kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/providerreg.js Fri Jan 4 17:57:31 2008 @@ -207,15 +207,15 @@ ;;; kukit.E += ' [recurseParents]).'; ;;; throw new Error(kukit.E); ;;; } -;;; if (args[0].match(/[ -]/)) { -;;; kukit.E = 'attrname parameter in kssAttr method cannot contain'; -;;; kukit.E += ' dashes or spaces.'; -;;; throw new Error(kukit.E); -;;; } }, eval: function(args, node) { var argname = args[0]; var recurseParents = false; +;;; if (argname.match(/[ -]/)) { +;;; kukit.E = 'attrname parameter in kssAttr method cannot contain'; +;;; kukit.E += ' dashes or spaces.'; +;;; throw new Error(kukit.E); +;;; } if (args.length == 2) { recurseParents = args[1]; ;;; kukit.E = '2nd attribute of kssAttr must be a boolean.'; From reebalazs at codespeak.net Fri Jan 4 17:57:36 2008 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Fri, 4 Jan 2008 17:57:36 +0100 (CET) Subject: [KSS-checkins] r50322 - in kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes: . kukit Message-ID: <20080104165736.09743168449@codespeak.net> Author: reebalazs Date: Fri Jan 4 17:57:35 2008 New Revision: 50322 Modified: kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/ (props changed) kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/dom.js kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/providerreg.js Log: Refactor the recursive attribute lookup. Add getKssValue provider. Modified: kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/dom.js ============================================================================== --- kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/dom.js (original) +++ kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/dom.js Fri Jan 4 17:57:35 2008 @@ -227,27 +227,57 @@ var _kssAttrNamespace = 'kssattr'; +// the namespace prefix for kss values, +// i.e.: +// class="... kss-attr-key-value..." +// id=="kss-id-key-value" +// (XHTML:) kss-attr:key-value +// +var _kssNamespacePrefix = 'kss'; + +var _getKssValueFromEncodings = function(encodings, prefix) { + // Value us a list of values. + // If a value equals prefix-value, it will find it + // and return the value after the prefix and the dash. + // (First value found will be returned.) + // + // For example: + // + // _getKssValueFromEncodings(['kss-attr-key1-value1', 'kss-attr-key2-value2', + // 'kss-id-key1-value1'], "kss-attr-key1') + // + // results 'value1'. + // + // Legacy example: + // + // _getKssValueFromEncodings(['kssattr-key1-value1', 'kssatt-rkey2-value2'], + // "kss-attr-key1') + // + // results 'value1'. + // + prefix = prefix + '-'; + var prefixLength = prefix.length; + for (var i=0; i Author: reebalazs Date: Fri Jan 4 17:57:38 2008 New Revision: 50323 Modified: kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/ (props changed) kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/dom.js kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/providerreg.js Log: Fix code by testing. Add KssIdOfValue provider. Modified: kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/dom.js ============================================================================== --- kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/dom.js (original) +++ kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/dom.js Fri Jan 4 17:57:38 2008 @@ -318,6 +318,9 @@ // This means setting an attribute to '' is the same as deleting it - // at least at the moment if (! result) { + // Make sure result is null, in case we can't produce one + // below. + result = null; // Now try to get it from the class and id encodings. // Having it in the id gives the advantage that we can use // kss-id-key-value both as a unique html id, and widget markup. @@ -337,9 +340,8 @@ // Get the result- var prefix = namespacedName + '-' + key; return _getKssValueFromEncodings(encodings, prefix); - } else { - return null; } + return result; }; dom.setKssValue = function(node, keyType, key, value) { Modified: kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/providerreg.js ============================================================================== --- kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/providerreg.js (original) +++ kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/providerreg.js Fri Jan 4 17:57:38 2008 @@ -158,8 +158,7 @@ if (args.length == 2) { ;;; kukit.E = '2nd attribute of currentFormVarForKssAttr must be a'; ;;; kukit.E += ' boolean'; - kukit.ut.evalBool(args[1], kukit.E); - recurseParents = args[1]; + recurseParents = kukit.ut.evalBool(args[1], kukit.E); } var formvarname = kukit.dom.getRecursiveAttribute(node, argname, recurseParents, kukit.dom.getKssAttribute); @@ -191,7 +190,7 @@ if (args.length == 2) { recurseParents = args[1]; ;;; kukit.E = '2nd attribute of nodeAttr must be a boolean.'; - kukit.ut.evalBool(recurseParents, kukit.E); + recurseParents = kukit.ut.evalBool(recurseParents, kukit.E); } return kukit.dom.getRecursiveAttribute(node, argname, recurseParents, kukit.dom.getAttribute); @@ -219,7 +218,7 @@ if (args.length == 2) { recurseParents = args[1]; ;;; kukit.E = '2nd attribute of kssAttr must be a boolean.'; - kukit.ut.evalBool(recurseParents, kukit.E); + recurseParents = kukit.ut.evalBool(recurseParents, kukit.E); } return kukit.dom.getRecursiveAttribute(node, argname, recurseParents, kukit.dom.getKssAttribute); @@ -287,7 +286,7 @@ kukit.pr.KssValuePP = function() {}; kukit.pr.KssValuePP.prototype = { check: function(args) { -;;; if (args.length != 1 && args.length != 2) { +;;; if (args.length != 2 && args.length != 3) { ;;; kukit.E = 'kssValue provider needs 2 or 3 argument (keytype, key,'; ;;; kukit.E += ' [recurseParents]).'; ;;; throw new Error(kukit.E); @@ -311,12 +310,49 @@ if (args.length == 3) { recurseParents = args[2]; ;;; kukit.E = '3rd attribute of kssAttr must be a boolean.'; - kukit.ut.evalBool(recurseParents, kukit.E); + recurseParents = kukit.ut.evalBool(recurseParents, kukit.E); } - return kukit.dom.getRecursiveAttribute(node, argname, recurseParents, - kukit.dom.getKssValue); + return kukit.dom.locateMarkup(node, recurseParents, + kukit.dom.getKssValue, + keytype, key).value; + } }; kukit.pprovidersGlobalRegistry.register('kssValue', kukit.pr.KssValuePP); +kukit.pr.KssIdOfValuePP = function() {}; +kukit.pr.KssIdOfValuePP.prototype = { + check: function(args) { +;;; if (args.length != 2) { +;;; kukit.E = 'kssIdOfValue provider needs 2 arguments (keytype, key).'; +;;; throw new Error(kukit.E); +;;; } + }, + eval: function(args, node) { + var keytype = args[0]; + var key = args[1]; +;;; if (keytype.match(/[ -]/)) { +;;; kukit.E = 'keytype parameter in kssIdOfValue provider cannot contain'; +;;; kukit.E += ' dashes or spaces.'; +;;; throw new Error(kukit.E); +;;; } +;;; if (key.match(/[ -]/)) { +;;; kukit.E = 'key parameter in kssIdOfValue provider cannot contain'; +;;; kukit.E += ' dashes or spaces.'; +;;; throw new Error(kukit.E); +;;; } + var markup = kukit.dom.locateMarkup(node, true, + kukit.dom.getKssValue, + keytype, key); + // return the id of the node where the markup is found + var id = markup.node.idd; + if (typeof(id) == 'undefined') { + // notfound arguments will get null + id = null; + } + return id; + } +}; +kukit.pprovidersGlobalRegistry.register('kssIdOfValue', kukit.pr.KssIdOfValuePP); + From reebalazs at codespeak.net Fri Jan 4 17:57:42 2008 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Fri, 4 Jan 2008 17:57:42 +0100 (CET) Subject: [KSS-checkins] r50324 - in kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes: . kukit Message-ID: <20080104165742.8DE0C1684CE@codespeak.net> Author: reebalazs Date: Fri Jan 4 17:57:41 2008 New Revision: 50324 Modified: kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/ (props changed) kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/commandreg.js Log: Change the lookup of selectors when executing for commands We now look up the selector from the provider, not the other way around. This will make it possible for commands to use selectors with more parameters. (todo later) Modified: kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/commandreg.js ============================================================================== --- kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/commandreg.js (original) +++ kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/commandreg.js Fri Jan 4 17:57:41 2008 @@ -114,10 +114,30 @@ }; var _executeCommandOnSelector = function(oper) { - var selfunc = kukit.selectorTypesGlobalRegistry.get(this.selectorType); - // When applying the selection, the original event target will be used + // if the selector type is null or undefined or '', + // we use the default type. + var selectorType = this.selectorType || + kukit.selectorTypesGlobalRegistry.defaultSelectorType; + // Use the provider registry to look up the selection provider. + var providerClass = kukit.pprovidersGlobalRegistry.get(selectorType); + // See if if is really a selection provider. + if (providerClass.prototype.returnType != 'selection') { + kukit.E = 'Undefined selector type [' + selectorType + '], '; + kukit.E = 'it exists as provider but it does not return a selection.'; + throw new Error(kukit.E); + } + // Instantiate it + var provider = new providerClass(); + var args = [this.selector]; +;;; // Check the provider first. +;;; provider.check(args); + // When evaluating the provider, the original event target will be used // as a starting point for the selection. - var nodes = selfunc(this.selector, oper.orignode, {}); + // args will contain a single item, since the server side currently + // cannot marshall selectors with more parameters + // defaultParameters will be empty when using from commands. + var nodes = provider.eval(args, oper.orignode, {}); + // ;;;var printType; ;;;if (this.selectorType) { ;;; printType = this.selectorType; From reebalazs at codespeak.net Fri Jan 4 17:57:46 2008 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Fri, 4 Jan 2008 17:57:46 +0100 (CET) Subject: [KSS-checkins] r50325 - in kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes: . kukit Message-ID: <20080104165746.C01F11684CE@codespeak.net> Author: reebalazs Date: Fri Jan 4 17:57:46 2008 New Revision: 50325 Modified: kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/ (props changed) kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/providerreg.js kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/selectorreg.js Log: Add kssWidget selector Modified: kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/providerreg.js ============================================================================== --- kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/providerreg.js (original) +++ kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/providerreg.js Fri Jan 4 17:57:46 2008 @@ -345,7 +345,7 @@ kukit.dom.getKssValue, keytype, key); // return the id of the node where the markup is found - var id = markup.node.idd; + var id = markup.node.id; if (typeof(id) == 'undefined') { // notfound arguments will get null id = null; Modified: kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/selectorreg.js ============================================================================== --- kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/selectorreg.js (original) +++ kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/selectorreg.js Fri Jan 4 17:57:46 2008 @@ -21,6 +21,7 @@ // this will provide an arbitrary selector, and is designed to // be used with the makeAnyPP factory function. +// It produces selectors that have a single input parameter. kukit.sr.AnyPP = function() {}; kukit.sr.AnyPP.prototype = { check: function(args) { @@ -160,3 +161,33 @@ } return results; }); + +kukit.sr.KssWidgetPP = function() {}; +kukit.sr.KssWidgetPP.prototype = { + check: function(args) { +;;; if (args.length != 2) { +;;; throw new Error('kssWidget selector method needs 2 arguments'); +;;; } + }, + eval: function(args, node, defaultParameters) { + var keytype = args[0]; + var key = args[1]; +;;; if (keytype.match(/[ -]/)) { +;;; kukit.E = 'keytype parameter in kssIdOfValue provider cannot contain'; +;;; kukit.E += ' dashes or spaces.'; +;;; throw new Error(kukit.E); +;;; } +;;; if (key.match(/[ -]/)) { +;;; kukit.E = 'key parameter in kssIdOfValue provider cannot contain'; +;;; kukit.E += ' dashes or spaces.'; +;;; throw new Error(kukit.E); +;;; } + var markup = kukit.dom.locateMarkup(node, true, + kukit.dom.getKssValue, + keytype, key); + // Just return the markup's node as a single result. + return [markup.node]; + } +}; +kukit.pprovidersGlobalRegistry.register('kssWidget', kukit.sr.KssWidgetPP, 'selection'); + From reebalazs at codespeak.net Fri Jan 4 18:03:19 2008 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Fri, 4 Jan 2008 18:03:19 +0100 (CET) Subject: [KSS-checkins] r50326 - kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes Message-ID: <20080104170319.5BA12168446@codespeak.net> Author: reebalazs Date: Fri Jan 4 18:03:18 2008 New Revision: 50326 Added: kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/ - copied from r50325, kukit/kss.core/trunk/ Log: Branch off From reebalazs at codespeak.net Fri Jan 4 18:11:10 2008 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Fri, 4 Jan 2008 18:11:10 +0100 (CET) Subject: [KSS-checkins] r50327 - in kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes: docs kss/core/plugins/core/demo kss/core/plugins/core/demo/markup kss/core/plugins/core/demo/markup/selenium_tests kss/core/plugins/core/demo/parameterfunction Message-ID: <20080104171110.101E21684C4@codespeak.net> Author: reebalazs Date: Fri Jan 4 18:11:10 2008 New Revision: 50327 Added: kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/markup/ kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/markup/README kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/markup/__init__.py kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/markup/config.py kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/markup/configure.zcml kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/markup/markup.kss kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/markup/markup.pt kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/markup/selenium_tests/ kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/markup/selenium_tests/README.txt kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/markup/selenium_tests/markup.html kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/markup/zopeconfig.py Modified: kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/docs/HISTORY.txt kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/config.py kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/configure.zcml kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/demoview.py kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/form_submit.kss kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/parameterfunction/forms.kss kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/parameterfunction/forms.pt kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/zopeconfig.py Log: Start of work. Adding an extra demo and test. Modified: kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/docs/HISTORY.txt ============================================================================== --- kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/docs/HISTORY.txt (original) +++ kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/docs/HISTORY.txt Fri Jan 4 18:11:10 2008 @@ -6,6 +6,19 @@ - ... + - refactor the value provider registry to use + a single registry in place of 3. + This will enable to define value + providers that recieve non-string parameters + like a node selection. + + Remove previously deprecated form() and + currentForm() value providers from normal + action parameters (remark: they should + be used with kssSelector.) + They now give a parsing error. + [ree] + - Fix multiple selection form fields marshalling on Safari (fixes #22 in kssproject) Modified: kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/config.py ============================================================================== --- kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/config.py (original) +++ kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/config.py Fri Jan 4 18:11:10 2008 @@ -21,7 +21,7 @@ KSSDemo('', '', "preventdefault.html", "Preventdefault (a.k.a. Safari workarounds)"), KSSDemo('', '', "html_inserts.html", "HTML insertions (Change tag content returns)"), KSSDemo('', '', "client-server-protocol", "Client server protocol"), - KSSDemo('', 'Parameter functions', 'pf_forms.html', 'Forms'), + KSSDemo('', 'Value providers', 'pf_forms.html', 'Forms'), KSSDemo('', 'Selectors', 'selectors.html', 'Parent node selector'), KSSDemo('', 'Core syntax', "kss_selector_param.html", "Kss selector parameters"), KSSDemo('', 'Core syntax', "kss_url_param.html", "Kss url parameters"), Modified: kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/configure.zcml ============================================================================== --- kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/configure.zcml (original) +++ kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/configure.zcml Fri Jan 4 18:11:10 2008 @@ -15,6 +15,7 @@ + + + + + + + + + + + + + + Added: kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/markup/markup.kss ============================================================================== --- (empty file) +++ kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/markup/markup.kss Fri Jan 4 18:11:10 2008 @@ -0,0 +1,43 @@ + +/* Set up kss rules needed for your demo. + * Use the following rule as an example only. + */ + +.buttons:click { + action-client: replaceInnerHTML; + replaceInnerHTML-kssSelector: #logger; +} + +#log-reset a:click { + evt-click-preventdefault: true; + action-client: clearChildNodes; + clearChildNodes-kssSelector: #logger; +} + +#button1:click { + replaceInnerHTML-html: kssValue(attr, key); +} + +#button2:click { + replaceInnerHTML-html: kssValue(id, key); +} + +#button3:click { + replaceInnerHTML-html: kssValue(attr, key); +} + +#button4:click, #button5:click { + replaceInnerHTML-html: kssValue(mymarkup, key, false); +} + +#button6:click { + replaceInnerHTML-html: kssIdOfValue(attr, key); +} + +#button7:click { + replaceInnerHTML-html: "Executed, look at button's text."; + action-client: insertHTMLAsFirstChild; + insertHTMLAsFirstChild-kssSelector: kssWidget(attr, key); + insertHTMLAsFirstChild-html: 'Selector succeeded'; +} + Added: kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/markup/markup.pt ============================================================================== --- (empty file) +++ kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/markup/markup.pt Fri Jan 4 18:11:10 2008 @@ -0,0 +1,76 @@ + + + + + +

header

+ + +

HTML markup

+ +
+ + +

Log

+

Reset log

+

You clicked:

+
+

+
+ +
+ +

kssValue(attr, key) encoding in class

+ +
+ +
+ +
+

kssValue(id, key) encoding in id

+ +
+ +
+ +
+

kssValue(attr, key) as XHTML attribute

+ +
+ +
+ +
+

kssValue(mymarkup, key, false) encoding in class

+ +
+ +
+ +
+

kssValue(mymarkup, key, false) encoding in class (should give no result)

+ +
+ +
+ +
+

kssIdOfValue(attr, key) encoding in class

+ +
+ +
+ +
+

xxx-kssSelector: kssWidget(attr, key); encoding in class

+ +
+ +
+ + +
+ + + + Added: kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/markup/selenium_tests/README.txt ============================================================================== --- (empty file) +++ kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/markup/selenium_tests/README.txt Fri Jan 4 18:11:10 2008 @@ -0,0 +1,4 @@ + +Save sour selenium tests into this directory, in html format. +All the tests ending with .html will be processed automatically. + Added: kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/markup/selenium_tests/markup.html ============================================================================== --- (empty file) +++ kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/markup/selenium_tests/markup.html Fri Jan 4 18:11:10 2008 @@ -0,0 +1,84 @@ + + + +markup + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
markup
open/demo/markup.html
clickbutton1
waitForTextPresentvalue1
clickbutton2
waitForTextPresentvalue2
clickbutton3
waitForTextPresentvalue3
clickbutton4
waitForTextPresentvalue4
clickbutton5
waitForTextPresent
clickbutton7
waitForTextPresentExecuted, look at button's text.
verifyTextPresentSelector succeeded
+ + Added: kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/markup/zopeconfig.py ============================================================================== --- (empty file) +++ kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/markup/zopeconfig.py Fri Jan 4 18:11:10 2008 @@ -0,0 +1,35 @@ + +from kss.demo.interfaces import ( + IKSSDemoResource, + IKSSSeleniumTestResource, + ) +from kss.demo.resource import ( + KSSDemo, + KSSSeleniumTestDirectory, + ) +from zope.interface import implements + +# Create a mesh of provided interfaces +# This is needed, because an utility must have a single interface. +class IResource(IKSSDemoResource, IKSSSeleniumTestResource): + pass + +# XXX you do not need to change anything above here +# ------------------------------------------------- + +class KSSDemos(object): + implements(IResource) + + demos = ( + # List your demos here. + # (Second parameter can be a subcategory within the demo if needed.) + KSSDemo('', 'Value providers', 'markup.html', 'HTML markup'), + + ) + + # directories are relative from the location of this .py file + selenium_tests = ( + # if you only have one test directory, you + # need not change anything here. + KSSSeleniumTestDirectory('selenium_tests'), + ) Modified: kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/parameterfunction/forms.kss ============================================================================== --- kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/parameterfunction/forms.kss (original) +++ kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/parameterfunction/forms.kss Fri Jan 4 18:11:10 2008 @@ -53,16 +53,6 @@ executeCommand-html: currentFormVar(radio-by-name); } -#fullform-simple:click { - action-server: submitFullForm; - submitFullForm-form: currentForm(); -} - -#fullform-simplenamed:click { - action-server: submitFullForm; - submitFullForm-form: form(full1); -} - #fullform-current:click { action-server: submitFullFormIntoRequest; submitFullFormIntoRequest-kssSubmitForm: currentForm(); Modified: kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/parameterfunction/forms.pt ============================================================================== --- kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/parameterfunction/forms.pt (original) +++ kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/parameterfunction/forms.pt Fri Jan 4 18:11:10 2008 @@ -143,24 +143,14 @@ form(full1) with simple field names, named form
- Click the button. + Removed after deprecation. +
+

+ currentForm() with simple field names +

+
+ Removed after deprecation.
- Click me ! -
-
-

- currentForm() with simple field names -

-
- Click the button. -
- Click me ! - - -
-

xxx-kssSubmitForm: form(full2) with complex field names, named form

Modified: kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/zopeconfig.py ============================================================================== --- kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/zopeconfig.py (original) +++ kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/zopeconfig.py Fri Jan 4 18:11:10 2008 @@ -33,7 +33,7 @@ KSSDemo('', '', "html_inserts.html", "HTML insertions (Change tag content returns)"), KSSDemo('', '', "client-server-protocol", "Client server protocol"), ## KSSDemo('', '', "draganddrop.html", "Scriptaculous drag and drop"), - KSSDemo('', 'Parameter functions', 'pf_forms.html', 'Forms'), + KSSDemo('', 'Value providers', 'pf_forms.html', 'Forms'), KSSDemo('', 'Selectors', 'selectors.html', 'Parent node selector'), KSSDemo('', 'Core syntax', "kss_selector_param.html", "Kss selector parameters"), KSSDemo('', 'Core syntax', "kss_url_param.html", "Kss url parameters"), From reebalazs at codespeak.net Fri Jan 4 18:12:24 2008 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Fri, 4 Jan 2008 18:12:24 +0100 (CET) Subject: [KSS-checkins] r50328 - kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core Message-ID: <20080104171224.B5A4E1684C4@codespeak.net> Author: reebalazs Date: Fri Jan 4 18:12:24 2008 New Revision: 50328 Modified: kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/ (props changed) kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/EXTERNALS.TXT Log: Set branch Modified: kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/EXTERNALS.TXT ============================================================================== --- kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/EXTERNALS.TXT (original) +++ kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/EXTERNALS.TXT Fri Jan 4 18:12:24 2008 @@ -5,4 +5,5 @@ # You can update your working dir by: # svn propset svn:externals -F EXTERNALS.TXT . # -kukit http://codespeak.net/svn/kukit/kukit.js/trunk/ +kukit http://codespeak.net/svn/kukit/kukit.js/trunk/branch/ree-1.4-markup-and-syntax-changes + From kukit-checkins at codespeak.net Sat Jan 5 10:15:29 2008 From: kukit-checkins at codespeak.net (kukit-checkins at codespeak.net) Date: Sat, 5 Jan 2008 10:15:29 +0100 (CET) Subject: [KSS-checkins] Penis Today, Not Gone Tomorrow! Message-ID: <20080105131900.5671.qmail@static-212.56.199.17.mldnet.com> An HTML attachment was scrubbed... URL: http://codespeak.net/pipermail/kukit-checkins/attachments/20080105/d1d53bd2/attachment.htm From kukit-checkins at codespeak.net Sat Jan 5 10:44:59 2008 From: kukit-checkins at codespeak.net (kukit-checkins at codespeak.net) Date: Sat, 5 Jan 2008 10:44:59 +0100 (CET) Subject: [KSS-checkins] Penis Today, Not Gone Tomorrow! Message-ID: <20080105114500.11653.qmail@caching1-pnc2.asianet.co.th> An HTML attachment was scrubbed... URL: http://codespeak.net/pipermail/kukit-checkins/attachments/20080105/7b2987c2/attachment.htm From kukit-checkins at codespeak.net Sat Jan 5 10:45:17 2008 From: kukit-checkins at codespeak.net (kukit-checkins at codespeak.net) Date: Sat, 5 Jan 2008 10:45:17 +0100 (CET) Subject: [KSS-checkins] Penis Today, Not Gone Tomorrow! Message-ID: <20080105114519.2508.qmail@bn170.osiedle.net.pl> An HTML attachment was scrubbed... URL: http://codespeak.net/pipermail/kukit-checkins/attachments/20080105/152b0f71/attachment-0001.htm From jvloothuis at codespeak.net Sun Jan 6 15:24:58 2008 From: jvloothuis at codespeak.net (jvloothuis at codespeak.net) Date: Sun, 6 Jan 2008 15:24:58 +0100 (CET) Subject: [KSS-checkins] r50377 - in kukit/kss.core/trunk/kss/core: . browser plugins/core/demo plugins/core/demo/selenium_tests tests Message-ID: <20080106142458.E13051684CE@codespeak.net> Author: jvloothuis Date: Sun Jan 6 15:24:58 2008 New Revision: 50377 Added: kukit/kss.core/trunk/kss/core/plugins/core/demo/selenium_tests/protocol.html Modified: kukit/kss.core/trunk/kss/core/browser/errorresponse.pt kukit/kss.core/trunk/kss/core/commands.py kukit/kss.core/trunk/kss/core/plugins/core/demo/protocol.pt kukit/kss.core/trunk/kss/core/tests/kukitresponse_test.pt kukit/kss.core/trunk/kss/core/tests/test_browserview.py kukit/kss.core/trunk/kss/core/tests/test_kssview_core.py Log: Increased the version number of all responses to 1.1 as discussed with Godefroid and Balazs since we currently put HTML inside CDATA nodes (we previously made HTML part of the response DOM). Fixed problems in the protocol due to improper escaping Fixed a problem with the protocol and Firefox where Firefox splits text nodes larger than 4K Modified: kukit/kss.core/trunk/kss/core/browser/errorresponse.pt ============================================================================== --- kukit/kss.core/trunk/kss/core/browser/errorresponse.pt (original) +++ kukit/kss.core/trunk/kss/core/browser/errorresponse.pt Sun Jan 6 15:24:58 2008 @@ -1,5 +1,5 @@ - Modified: kukit/kss.core/trunk/kss/core/commands.py ============================================================================== --- kukit/kss.core/trunk/kss/core/commands.py (original) +++ kukit/kss.core/trunk/kss/core/commands.py Sun Jan 6 15:24:58 2008 @@ -22,6 +22,7 @@ in the defined format ''' +from xml.sax.saxutils import escape as xml_escape from zope.interface import implements from zope.app.pagetemplate.viewpagetemplatefile import ViewPageTemplateFile from interfaces import IKSSCommands, IKSSCommand, IKSSParam, IKSSCommandView @@ -106,6 +107,16 @@ # just send complex data types directly with AddParam def addParam(self, name, content=''): + # Check for the size of the content. Larger than 4K will give + # problems with Firefox (which splits text nodes). Therefore + # we give this special treatment. + if len(content) > 4096: + return self.addCdataParam(name, content) + else: + # Escape all XML characters + return self._addParam(name, content=xml_escape(content)) + + def _addParam(self, name, content=''): 'Add the param as is' param = KSSParam(name, content) self.params.append(param) @@ -115,14 +126,14 @@ # Some helpers # - def addUnicodeParam(self, name, content=''): + def addUnicodeParam(self, name, content=u''): 'Add the param as unicode' - self.addParam(name, content=content) + self.addParam(name, content) - def addStringParam(self, name, content='', encoding='utf'): + def addStringParam(self, name, content='', encoding='utf8'): 'Add the param as an encoded string, by default UTF-8' - content = unicode(content, 'utf') - self.addParam(name, content=content) + content = unicode(content, encoding) + self.addUnicodeParam(name, content=content) def addHtmlParam(self, name, content=''): 'Add the param as an HTML content.' @@ -134,12 +145,14 @@ def addXmlParam(self, name, content=''): 'Add the param as XML content' content = XmlParser(content)().encode('ascii', 'xmlcharrefreplace') - self.addParam(name, content=content) + self._addParam(name, content=content) def addCdataParam(self, name, content=''): 'Add the param as a CDATA node' - content = '' % (content, ) - self.addParam(name, content=content) + # Replace `>` part of `]]>` with the entity ref so it won't + # accidentally close the CDATA (required by the XML spec) + content = '' % content.replace(']]>', ']]>') + self._addParam(name, content=content) # -- Modified: kukit/kss.core/trunk/kss/core/plugins/core/demo/protocol.pt ============================================================================== --- kukit/kss.core/trunk/kss/core/plugins/core/demo/protocol.pt (original) +++ kukit/kss.core/trunk/kss/core/plugins/core/demo/protocol.pt Sun Jan 6 15:24:58 2008 @@ -29,6 +29,9 @@
  • Small dataset
  • Large dataset
  • +
    + The contents of this node will change +

    Currently kss.core treats non-HTML commands differently from others. The following examples show why I think this to be a Added: kukit/kss.core/trunk/kss/core/plugins/core/demo/selenium_tests/protocol.html ============================================================================== --- (empty file) +++ kukit/kss.core/trunk/kss/core/plugins/core/demo/selenium_tests/protocol.html Sun Jan 6 15:24:58 2008 @@ -0,0 +1,169 @@ + + + +protocol + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    protocol
    open/demo/client-server-protocol
    clicksmall-dataset
    waitForTextcss=#dataset-output emWorked
    clicklarge-dataset
    waitForTextcss=#dataset-output emreally really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really large text
    clicksmall-attribute
    waitForAttributeattribute-output at classsome smallattr
    verifyAttributeattribute-output at classsome smallattr
    clicklarge-attribute
    waitForAttributeattribute-output at classh h1 h22 h333 h4444 h55555 h666666 h7777777 h88888888 h999999999 haaaaaaaaaa hbbbbbbbbbbb hcccccccccccc hddddddddddddd heeeeeeeeeeeeee hfffffffffffffff h10101010101010101010101010101010 h1111111111111111111111111111111111 h121212121212121212121212121212121212 h13131313131313131313131313131313131313 h1414141414141414141414141414141414141414 h151515151515151515151515151515151515151515 h16161616161616161616161616161616161616161616 h1717171717171717171717171717171717171717171717 h181818181818181818181818181818181818181818181818 h19191919191919191919191919191919191919191919191919 h1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a h1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b h1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c h1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d h1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e h1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f h2020202020202020202020202020202020202020202020202020202020202020 h212121212121212121212121212121212121212121212121212121212121212121 h22222222222222222222222222222222222222222222222222222222222222222222 h2323232323232323232323232323232323232323232323232323232323232323232323 h242424242424242424242424242424242424242424242424242424242424242424242424 h25252525252525252525252525252525252525252525252525252525252525252525252525 h2626262626262626262626262626262626262626262626262626262626262626262626262626 h272727272727272727272727272727272727272727272727272727272727272727272727272727 h28282828282828282828282828282828282828282828282828282828282828282828282828282828 h2929292929292929292929292929292929292929292929292929292929292929292929292929292929 h2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a h2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b h2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c h2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d h2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e h2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f h303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030 h31313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131 h3232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232 h333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333 h34343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434 h3535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535 h363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636 h37373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737 h3838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838 h393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939 h3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a h3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b h3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c h3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d h3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e h3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f h40404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040 h4141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141 h424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242 h43434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343 h4444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444 h454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545 largeattr
    verifyAttributeattribute-output at classh h1 h22 h333 h4444 h55555 h666666 h7777777 h88888888 h999999999 haaaaaaaaaa hbbbbbbbbbbb hcccccccccccc hddddddddddddd heeeeeeeeeeeeee hfffffffffffffff h10101010101010101010101010101010 h1111111111111111111111111111111111 h121212121212121212121212121212121212 h13131313131313131313131313131313131313 h1414141414141414141414141414141414141414 h151515151515151515151515151515151515151515 h16161616161616161616161616161616161616161616 h1717171717171717171717171717171717171717171717 h181818181818181818181818181818181818181818181818 h19191919191919191919191919191919191919191919191919 h1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a h1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b h1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c h1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d h1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e h1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f h2020202020202020202020202020202020202020202020202020202020202020 h212121212121212121212121212121212121212121212121212121212121212121 h22222222222222222222222222222222222222222222222222222222222222222222 h2323232323232323232323232323232323232323232323232323232323232323232323 h242424242424242424242424242424242424242424242424242424242424242424242424 h25252525252525252525252525252525252525252525252525252525252525252525252525 h2626262626262626262626262626262626262626262626262626262626262626262626262626 h272727272727272727272727272727272727272727272727272727272727272727272727272727 h28282828282828282828282828282828282828282828282828282828282828282828282828282828 h2929292929292929292929292929292929292929292929292929292929292929292929292929292929 h2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a h2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b h2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c h2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d h2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e h2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f h303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030 h31313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131 h3232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232 h333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333 h34343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434 h3535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535 h363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636 h37373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737 h3838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838 h393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939 h3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a h3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b h3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c h3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d h3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e h3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f h40404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040 h4141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141 h424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242 h43434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343 h4444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444 h454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545 largeattr
    clickamp
    waitForTextcharacter-outputtext & stuff
    clicklt
    waitForTextcharacter-outputtext < stuff
    clickgt
    waitForTextcharacter-outputtext > stuff
    clickendcdata
    waitForTextcharacter-outputbefore ]]> after
    clickattr-amp
    waitForAttributecharacter-attr-output at titletext & stuff
    verifyAttributecharacter-attr-output at titletext & stuff
    clickattr-lt
    waitForAttributecharacter-attr-output at titletext < stuff
    verifyAttributecharacter-attr-output at titletext < stuff
    clickattr-gt
    waitForAttributecharacter-attr-output at titletext > stuff
    verifyAttributecharacter-attr-output at titletext > stuff
    clickattr-endcdata
    waitForAttributecharacter-attr-output at titlebefore ]]> after
    verifyAttributecharacter-attr-output at titlebefore ]]> after
    + + Modified: kukit/kss.core/trunk/kss/core/tests/kukitresponse_test.pt ============================================================================== --- kukit/kss.core/trunk/kss/core/tests/kukitresponse_test.pt (original) +++ kukit/kss.core/trunk/kss/core/tests/kukitresponse_test.pt Sun Jan 6 15:24:58 2008 @@ -1,5 +1,5 @@ - Modified: kukit/kss.core/trunk/kss/core/tests/test_browserview.py ============================================================================== --- kukit/kss.core/trunk/kss/core/tests/test_browserview.py (original) +++ kukit/kss.core/trunk/kss/core/tests/test_browserview.py Sun Jan 6 15:24:58 2008 @@ -31,7 +31,7 @@ header = response.getHeader('x-ksscommands') self.assert_('the_&lt;&gt;message' in header) # no < > in the message self.assert_('\n' not in header) # no /n in the payload: would destroy the page - self.assertEqual(header, ' \t \t\tsystem \t\tTheError: the_&lt;&gt;message \t ') + self.assertEqual(header, ' \t \t\tsystem \t\tTheError: the_&lt;&gt;message \t ') def test_suite(): suites = [] Modified: kukit/kss.core/trunk/kss/core/tests/test_kssview_core.py ============================================================================== --- kukit/kss.core/trunk/kss/core/tests/test_kssview_core.py (original) +++ kukit/kss.core/trunk/kss/core/tests/test_kssview_core.py Sun Jan 6 15:24:58 2008 @@ -100,7 +100,7 @@ def _wrapped_commands(self, inline): header = textwrap.dedent(u'''\ - + ''') footer = textwrap.dedent('''\ From reebalazs at codespeak.net Sun Jan 6 17:08:10 2008 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Sun, 6 Jan 2008 17:08:10 +0100 (CET) Subject: [KSS-checkins] r50392 - in kukit/kukit.js/branch/ree-service-layer-and-refactoring: . tests Message-ID: <20080106160810.B72EE168476@codespeak.net> Author: reebalazs Date: Sun Jan 6 17:08:09 2008 New Revision: 50392 Modified: kukit/kukit.js/branch/ree-service-layer-and-refactoring/ (props changed) kukit/kukit.js/branch/ree-service-layer-and-refactoring/tests/test_errors.js Log: Make each test that can only run in development mode, pass green in production mode, rather then adding the testcase conditionally. Modified: kukit/kukit.js/branch/ree-service-layer-and-refactoring/tests/test_errors.js ============================================================================== --- kukit/kukit.js/branch/ree-service-layer-and-refactoring/tests/test_errors.js (original) +++ kukit/kukit.js/branch/ree-service-layer-and-refactoring/tests/test_errors.js Sun Jan 6 17:08:09 2008 @@ -30,6 +30,10 @@ this.testCreateGenuineError = function() { // Create a genuine error message. // An error message of a given type can be created on the fly. + // + // This test can only run in development mode, pass otherwise. + if (! kukit.isDevelMode) {return;} + // var E = kukit.err.setErrorInfo(null, 'MyError', 'Something went wrong', {a:1, b:2}); // Check that error has the message this.assertEquals(E.message, 'MyError: Something went wrong'); @@ -40,7 +44,12 @@ }; this.testCreateErrorFromTxt = function() { + // Create a genuine error message. // Create an annotated error from text. + // + // This test can only run in development mode, pass otherwise. + if (! kukit.isDevelMode) {return;} + // // XXX this works but gives warning: this way we cannot preserve the traceback. var orig_txt = "Original error"; var E = kukit.err.setErrorInfo(orig_txt, 'MyError', 'Something went wrong', {a:1, b:2}); @@ -54,7 +63,12 @@ }; this.testCreateErrorFromRawError = function() { + // Create a genuine error message. // Create an annotated error from a raw, unannorated error. + // + // This test can only run in development mode, pass otherwise. + if (! kukit.isDevelMode) {return;} + // var orig_err = new Error("Original error"); var E = kukit.err.setErrorInfo(orig_err, 'MyError', 'Something went wrong', {a:1, b:2}); // Check that error has the message @@ -67,9 +81,14 @@ }; this.testCreateErrorFromAnnotatedError = function() { + // Create a genuine error message. // Create an error from an annotated error message. // this message is a genuine error created by us // create chain of errors + // + // This test can only run in development mode, pass otherwise. + if (! kukit.isDevelMode) {return;} + // var orig_err = kukit.err.setErrorInfo(null, 'MyError', 'Something went wrong', {a:1, b:2}); var E = kukit.err.setErrorInfo(orig_err, 'YourError', 'Wrong here too', {a:2, b:3}); // Check that error has the message @@ -82,9 +101,14 @@ }; this.testCreateErrorFromAnnotatedError2 = function() { + // Create a genuine error message. // Create an error from an annotated error message. // this message is a string error // create chain of errors + // + // This test can only run in development mode, pass otherwise. + if (! kukit.isDevelMode) {return;} + // var orig_txt = "Original error"; var err1 = kukit.err.setErrorInfo(orig_txt, 'MyError', 'Something went wrong', {a:1, b:2}); var E = kukit.err.setErrorInfo(err1, 'YourError', 'Wrong here too', {a:2, b:3}); @@ -99,9 +123,14 @@ }; this.testCreateErrorFromAnnotatedError3 = function() { + // Create a genuine error message. // Create an error from an annotated error message. // This message is an unannotated error object // create chain of errors + // + // This test can only run in development mode, pass otherwise. + if (! kukit.isDevelMode) {return;} + // var orig_err = new Error("Original error"); var err1 = kukit.err.setErrorInfo(orig_err, 'MyError', 'Something went wrong', {a:1, b:2}); var E = kukit.err.setErrorInfo(err1, 'YourError', 'Wrong here too', {a:2, b:3}); @@ -116,8 +145,13 @@ }; this.testCreateErrorManyLevels = function() { + // Create a genuine error message. // Many levels together // create chain of errors + // + // This test can only run in development mode, pass otherwise. + if (! kukit.isDevelMode) {return;} + // var orig_err = new Error("Original error"); var err1 = kukit.err.setErrorInfo(orig_err, 'Error1', 'Wrong 1', {a:1, b:2}); var err2 = kukit.err.setErrorInfo(err1, 'Error2', 'Wrong 2', {a:2, b:3}); @@ -138,18 +172,10 @@ this.assertDictEquals(E.info.kw, {a:5, b:6}); }; - - - - }; kukit.ErrorsTestCase.prototype = new kukit.UtilsTestCaseBase; if (typeof(testcase_registry) != 'undefined') { - // Only add these tests for development mode - // (For the console, they are added elsewhere permanently.) - if (kukit.isDevelMode) { - testcase_registry.registerTestCase(kukit.ErrorsTestCase, 'kukit.ErrorsTestCase'); - } + testcase_registry.registerTestCase(kukit.ErrorsTestCase, 'kukit.ErrorsTestCase'); } From reebalazs at codespeak.net Sun Jan 6 17:08:14 2008 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Sun, 6 Jan 2008 17:08:14 +0100 (CET) Subject: [KSS-checkins] r50393 - in kukit/kukit.js/branch/ree-service-layer-and-refactoring: . tests Message-ID: <20080106160814.5AE091684D0@codespeak.net> Author: reebalazs Date: Sun Jan 6 17:08:13 2008 New Revision: 50393 Modified: kukit/kukit.js/branch/ree-service-layer-and-refactoring/ (props changed) kukit/kukit.js/branch/ree-service-layer-and-refactoring/tests/test_tokenizer.js Log: Fix the ecma test testException itself, to run on IE All ecma is green on IE6, and Safari 3.0.3 Modified: kukit/kukit.js/branch/ree-service-layer-and-refactoring/tests/test_tokenizer.js ============================================================================== --- kukit/kukit.js/branch/ree-service-layer-and-refactoring/tests/test_tokenizer.js (original) +++ kukit/kukit.js/branch/ree-service-layer-and-refactoring/tests/test_tokenizer.js Sun Jan 6 17:08:13 2008 @@ -105,26 +105,19 @@ } catch(e) { exc = e; } + // It is pointless to test for exc.toString(), first IE returns the constant + // '[object Error]' in some versions, then it is not really important + // for us since we use our own annotation info anyway. this.assertNotEquals(exc, null); this.assertEquals(exc.name, 'ParsingError'); - // test here under tries to discriminate IE - // it does work for IE 6.0.2900.2180.xpsp_sp2 - // it does not work at least for IE 6.0.2800.1106 - if (typeof(exc.number) == 'number') { - // IE - this.assertEquals(exc.description, 'ParsingError: Error happened'); - this.assertEquals(exc.info.message, 'Error happened'); - } else { - // toString result is browser dependent. - // colon in FF - // dash in Safari - // reason for the indexOf below - var toString = exc.toString(); - this.assertTrue(toString.indexOf('ParsingError') != -1, '"ParsingError" not in toString() : ' + toString); - this.assertTrue(toString.indexOf('Error happened') != -1, '"Error happened" not in toString() : ' + toString); - this.assertEquals(exc.message, 'ParsingError: Error happened'); - this.assertEquals(exc.info.message, 'Error happened'); - }; + // exc.description is needed for IE, + // ... exc.message is for all W3C compliant browsers. + this.assert(exc.message =='ParsingError: Error happened' || + exc.description == 'ParsingError: Error happened'); + // Most important is to have the annotation info, + // since we use this for logging and testing: + this.assertEquals(exc.info.message, 'Error happened'); + // check positions this.assertEquals(exc.errpos, null); this.assertEquals(exc.errrow, null); this.assertEquals(exc.errcol, null); @@ -143,24 +136,19 @@ } this.assertNotEquals(exc, null); this.assertEquals(exc.name, 'ParsingError'); - // test here under tries to discriminate IE - // it does work for IE 6.0.2900.2180.xpsp_sp2 - // it does not work at least for IE 6.0.2800.1106 - if (typeof(exc.number) == 'number') { - // IE - this.assertEquals(exc.description, 'ParsingError: Error happened, at row 3, column 4'); - this.assertEquals(exc.info.message, 'Error happened, at row 3, column 4'); - } else { - // toString result is browser dependent. - // colon in FF - // dash in Safari - // reason for the indexOf below - var toString = exc.toString(); - this.assertTrue(toString.indexOf('ParsingError') != -1, '"ParsingError" not in toString() : ' + toString); - this.assertTrue(toString.indexOf('Error happened, at row 3, column 4') != -1, '"Error happened, at row 3, column 4" not in toString() : ' + toString); - this.assertEquals(exc.message, 'ParsingError: Error happened, at row 3, column 4'); - this.assertEquals(exc.info.message, 'Error happened, at row 3, column 4'); - }; + // It is pointless to test for exc.toString(), first IE returns the constant + // '[object Error]' in some versions, then it is not really important + // for us since we use our own annotation info anyway. + this.assertNotEquals(exc, null); + this.assertEquals(exc.name, 'ParsingError'); + // exc.description is needed for IE, + // ... exc.message is for all W3C compliant browsers. + this.assert(exc.message == 'ParsingError: Error happened, at row 3, column 4' || + exc.description == 'Error happened'); + // Most important is to have the annotation info, + // since we use this for logging and testing: + this.assertEquals(exc.info.message, 'Error happened, at row 3, column 4'); + // check positions this.assertEquals(exc.info.kw.errpos, 13); this.assertEquals(exc.info.kw.errrow, 3); this.assertEquals(exc.info.kw.errcol, 4); From reebalazs at codespeak.net Sun Jan 6 17:19:25 2008 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Sun, 6 Jan 2008 17:19:25 +0100 (CET) Subject: [KSS-checkins] r50395 - in kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes: . kukit tests Message-ID: <20080106161925.BE7DC168477@codespeak.net> Author: reebalazs Date: Sun Jan 6 17:19:25 2008 New Revision: 50395 Modified: kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/ (props changed) kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/kssparser.js kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/tests/test_kssparser.js Log: Remove PropValueInMethod: it's not used or needed any more Modified: kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/kssparser.js ============================================================================== --- kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/kssparser.js (original) +++ kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/kssparser.js Sun Jan 6 17:19:25 2008 @@ -446,29 +446,6 @@ }; /* -* class PropValueInMethod -* -* PropValue in method cannot have method-style vars. -*/ -kukit.kssp.PropValueInMethod = kukit.tk.mkParser('propValue', { - ";": 'this.emitAndReturn()', - "}": 'this.emitAndReturn()', - ")": 'this.emitAndReturn()', - "]": 'this.emitAndReturn()', - ",": 'this.emitAndReturn()', - "'": 'new kukit.kssp.String(this.cursor, kukit.kssp.quote)', - '"': 'new kukit.kssp.String2(this.cursor, kukit.kssp.dquote)', - "\/\*": 'new kukit.kssp.Comment(this.cursor, kukit.kssp.openComment)' - }); -kukit.kssp.PropValueInMethod.prototype.multiword_allowed = false; -kukit.kssp.PropValueInMethod.prototype.process = - kukit.kssp.PropValue.prototype.process; -kukit.kssp.PropValueInMethod.prototype.produceTxt = function(txt) { - // txt parms are returned unwrapped - this.txt = txt; -}; - -/* * class EventValue * * PropValue in pseudo must be single word with no spaces around. Modified: kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/tests/test_kssparser.js ============================================================================== --- kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/tests/test_kssparser.js (original) +++ kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/tests/test_kssparser.js Sun Jan 6 17:19:25 2008 @@ -69,89 +69,6 @@ kukit.KssParserTestCase = function() { this.name = 'kukit.KssParserTestCase'; - this.testPropvalueInMethod = function() { - // Parsing prop values (no methods allowed) - var txt= "apple;"; - var cursor = new kukit.tk.Cursor(txt); - var parser = new kukit.kssp.PropValueInMethod(cursor, null, true); - this.assertEquals(parser.finished, true); - this.assertEquals(parser.txt, 'apple'); - - txt= "'a string';"; - cursor = new kukit.tk.Cursor(txt); - parser = new kukit.kssp.PropValueInMethod(cursor, null, true); - this.assertEquals(parser.finished, true); - this.assertEquals(parser.txt, 'a string'); - - txt= '"a string";'; - cursor = new kukit.tk.Cursor(txt); - parser = new kukit.kssp.PropValueInMethod(cursor, null, true); - this.assertEquals(parser.finished, true); - this.assertEquals(parser.txt, 'a string'); - - txt= '"a \\"string";'; - cursor = new kukit.tk.Cursor(txt); - parser = new kukit.kssp.PropValueInMethod(cursor, null, true); - this.assertEquals(parser.finished, true); - this.assertEquals(parser.txt, 'a "string'); - - txt= " /* valid */ 'a string' /* here*/ /*and*/ /*there*/;"; - cursor = new kukit.tk.Cursor(txt); - parser = new kukit.kssp.PropValueInMethod(cursor, null, true); - this.assertEquals(parser.finished, true); - this.assertEquals(parser.txt, 'a string'); - - txt= " in /* valid */ 'a string';"; - cursor = new kukit.tk.Cursor(txt); - this.assertParsingError(kukit.kssp.PropValueInMethod, cursor, null, true, 'Wrong value : unallowed characters [in] before a string.'); - - txt= " 'a string' trashy;"; - cursor = new kukit.tk.Cursor(txt); - this.assertParsingError(kukit.kssp.PropValueInMethod, cursor, null, true, 'Wrong value : unallowed characters after the property.'); - - txt= " 'a string' trashy \"trishy\";"; - cursor = new kukit.tk.Cursor(txt); - this.assertParsingError(kukit.kssp.PropValueInMethod, cursor, null, true, 'Wrong value : unallowed characters after the property.'); - - // multiword not ok - txt= "b c"; - cursor = new kukit.tk.Cursor(txt); - this.assertParsingError(kukit.kssp.PropValueInMethod, cursor, null, true, - 'Wrong value : [b c] cannot have spaces.', 5); - - txt= " apples and oranges ;"; - cursor = new kukit.tk.Cursor(txt); - this.assertParsingError(kukit.kssp.PropValueInMethod, cursor, null, true, - 'Wrong value : [apples and oranges] cannot have spaces.', 25); - - txt= " /* comments; */ apples and /* more comments and*/ oranges ;"; - cursor = new kukit.tk.Cursor(txt); - this.assertParsingError(kukit.kssp.PropValueInMethod, cursor, null, true, - //'Wrong value : [/* comments; */ apples and /* more comments and*/ oranges ;] cannot have spaces.', 62); - 'Wrong value : [apples and oranges] cannot have spaces.', 62); - - // in string, multiword ok even in method - txt= "'b c' "; - cursor = new kukit.tk.Cursor(txt); - parser = new kukit.kssp.PropValueInMethod(cursor, null, true); - this.assertEquals(parser.finished, true); - this.assertEquals(parser.txt, 'b c'); - this.assertEquals(parser.parms, null); - - // Not ok - txt= "a'b c'"; - cursor = new kukit.tk.Cursor(txt); - this.assertParsingError(kukit.kssp.PropValueInMethod, cursor, null, true, - 'Wrong value : unallowed characters [a] before a string', 6); - - // Not ok - txt= "'a''b c'"; - cursor = new kukit.tk.Cursor(txt); - this.assertParsingError(kukit.kssp.PropValueInMethod, cursor, null, true, - 'Wrong value : unallowed characters after the property.', 6); - - }; - this.testPropValue = function() { // Parsing property values From reebalazs at codespeak.net Sun Jan 6 17:19:29 2008 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Sun, 6 Jan 2008 17:19:29 +0100 (CET) Subject: [KSS-checkins] r50396 - in kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes: . kukit tests Message-ID: <20080106161929.5F47E168477@codespeak.net> Author: reebalazs Date: Sun Jan 6 17:19:29 2008 New Revision: 50396 Modified: kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/ (props changed) kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/kssparser.js kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/tests/test_kssparser.js Log: Refactor PropValue, add MultiPropValue Modified: kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/kssparser.js ============================================================================== --- kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/kssparser.js (original) +++ kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/kssparser.js Sun Jan 6 17:19:29 2008 @@ -393,58 +393,120 @@ "(": 'new kukit.kssp.MethodArgs(this.cursor, kukit.kssp.openParent)' }); kukit.kssp.PropValue.prototype.process = function() { + // For multivalue only + this.values = [] // Parse all tokens (including first and last) var context = {'nextTokenIndex': 0}; - this.digestTxt(context, kukit.tk.Fraction, kukit.kssp.Comment); this.txt = ''; - var txt = context.txt; - if (this.notInTokens(context, kukit.kssp.String)) { - // The previous txt must be all whitespace. - if (txt) { -;;; kukit.E = 'Wrong value : unallowed characters [' + txt + ']'; -;;; kukit.E += ' before a string.'; - this.emitError(kukit.E); - } - // the next one must be a string. - this.expectToken(context, kukit.kssp.String); - this.produceTxt(context.token.txt); - } else if (this.notInTokens(context, kukit.kssp.MethodArgs)) { - // see if not empty and has no spaces in it - if (! txt || txt.indexOf(' ') != -1) { -;;; kukit.E = 'Wrong value : method name [' + txt + '] cannot '; -;;; kukit.E += 'have spaces.'; - this.emitError(kukit.E); - } - // the next one must be the rules - this.expectToken(context, kukit.kssp.MethodArgs); - this.value = new this.valueClass(txt, context.token.args); - } else { - // not a string or method: check if we allowed multiword. - if (! this.multiword_allowed && txt.indexOf(' ') != -1) { -;;; kukit.E = 'Wrong value : [' + txt + '] cannot have spaces.'; - this.emitError(kukit.E); + // Iterate for multiple values (in case allowed.) + // txtCarry holds the part of text that we need to consider + // as a possible method name, in case method args follow. + var txtCarry = ''; + while (context.nextTokenIndex < this.result.length) { + if (this.notInTokens(context, kukit.kssp.String)) { + // A string token follows: + if (txtCarry) { + // If we have a txt carry left, it needs to be + // produced first, separately. + this.produceTxt(txtCarry); + txtCarry = ''; + } + // the next one must be a string. + this.expectToken(context, kukit.kssp.String); + this.produceTxt(context.token.txt); + } else if (this.notInTokens(context, kukit.kssp.MethodArgs)) { + // A MethodArgs token follows: + // see if not empty + if (! txtCarry) { +;;; // Be a little more intelligent with this error. +;;; // If we are single value, and there is a value, +;;; // the following raises a smarter error message, complaining +;;; // about the () as excess. +;;; this.addValue(null, '('); +;;; // otherwise, just do the next error message: +;;; kukit.E = 'Wrong value : empty method name.'; + this.emitError(kukit.E); + } + // the next one must be the (a1, a2, ...an) method args. + this.expectToken(context, kukit.kssp.MethodArgs); + // The txtCarry will be used as the name of the method. + this.addValue(new kukit.rd.KssMethodValue(txtCarry, context.token.args), + txtCarry); + txtCarry = ''; + } else { + // Try to digest another fraction. + this.digestTxt(context, kukit.tk.Fraction, kukit.kssp.Comment); + // + // Split the fraction to words. We may have a word + // and we may have a MethodArg after: + // wordone ... wordlast(...) ... + // ^^^^^^^^^^^^^^^^^^^^ - these are in the Fraction + // ^^^^^ - these are the MethodArgs + // So we produce all strings except the last one, and + // continue the cycle with the last one (worlast) as txt. + // This enables it to be produced with the MethodArgs. + // + var words = context.txt.split(' '); + // Emit the original txtCarry - if there is one. + if (txtCarry) { + this.produceTxt(txtCarry); + txtCarry = ''; + } + // If we have input, process it. + if (words.length > 0) { + // Produce all strings except the last one + for (var i=0; i Author: reebalazs Date: Sun Jan 6 17:19:33 2008 New Revision: 50397 Modified: kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/ (props changed) kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/kssparser.js kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/resourcedata.js kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/tests/test_kssparser.js Log: Implement handling of MultoPropValue in action lines and normal parameters. Add and adjust ecma tests. Work in progress. Modified: kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/kssparser.js ============================================================================== --- kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/kssparser.js (original) +++ kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/kssparser.js Sun Jan 6 17:19:33 2008 @@ -91,7 +91,8 @@ */ kukit.kssp.Block = kukit.tk.mkParser('block', { ";": 'new kukit.kssp.semicolon(this.cursor)', - ":": '[new kukit.kssp.colon(this.cursor), new kukit.kssp.PropValue(this.cursor)]', + // XXX Merging hint: next line has changed. + ":": '[new kukit.kssp.colon(this.cursor), new kukit.kssp.MultiPropValue(this.cursor)]', "}": 'this.emitAndReturn(new kukit.kssp.closeBrace(this.cursor))' }); kukit.kssp.Block.prototype.process = function() { @@ -107,9 +108,9 @@ break; } this.expectToken(context, kukit.kssp.colon); - this.expectToken(context, kukit.kssp.PropValue); + this.expectToken(context, kukit.kssp.MultiPropValue); // store the wrapped prop - this.addDeclaration(key, context.token.value); + this.addDeclaration(key, context.token.values); if (context.nextTokenIndex == this.result.length-1) break; this.expectToken(context, kukit.kssp.semicolon); } @@ -165,7 +166,7 @@ return results; } -kukit.kssp.Block.prototype.addEventDeclaration = function(key, splitkey, value) { +kukit.kssp.Block.prototype.addEventDeclaration = function(key, splitkey, values) { // evt--: // evt---: @@ -193,6 +194,11 @@ eventKey = splitkey[3]; eventFullName = eventNamespace + '-' + eventName; } + // preprocess values + var allowedReturnTypes; +;;; allowedReturnTypes = {string: true}; +;;; kukit.E = 'event parameter [' + key + ']'; + var value = this.preprocessValues(values, allowedReturnTypes, kukit.E).string; ;;; if (value.isMethod != false) { ;;; kukit.E = 'Wrong value for key [' + key + '] : '; ;;; kukit.E += 'value providers are not '; @@ -206,9 +212,9 @@ eventParameters = this.eventFullNames[eventFullName]; } eventParameters[eventKey] = value.txt; -} +}; -kukit.kssp.Block.prototype.addActionDeclaration = function(key, splitkey, value) { +kukit.kssp.Block.prototype.addActionDeclaration = function(key, splitkey, values) { // action-server: // action-client: // action-client: - @@ -219,12 +225,6 @@ ;;; kukit.E += 'action- keys can have only one dash.'; ;;; this.emitError(kukit.E); ;;; } -;;; if (value.isMethod != false) { -;;; kukit.E = 'Wrong value for key [' + key + '] : '; -;;; kukit.E += 'value providers are not '; -;;; kukit.E += 'allowed for action- keys.'; -;;; this.emitError(kukit.E); -;;; } var atab = {'server': 'S', 'client': 'C', 'cancel': 'X'}; var actionType = atab[splitkey[1]]; ;;; if (! actionType) { @@ -233,6 +233,23 @@ ;;; kukit.E += '"server" or "client" or "cancel".'; ;;; this.emitError(kukit.E); ;;; } + // preprocess values + var allowedReturnTypes; +;;; if (actionType == 'S') { +;;; allowedReturnTypes = {string: true, formquery: true, url: true}; +;;; } else { +;;; allowedReturnTypes = {string: true, selection: true}; +;;; } +;;; kukit.E = 'action definition [' + key + ']'; + var valuesByReturnType = this.preprocessValues(values, allowedReturnTypes, kukit.E); + var value = valuesByReturnType.string; + // +;;; if (value.isMethod != false) { +;;; kukit.E = 'Wrong value for key [' + key + '] : '; +;;; kukit.E += 'value providers are not '; +;;; kukit.E += 'allowed for action- keys.'; +;;; this.emitError(kukit.E); +;;; } ;;; // force value to be or - ;;; var splitvalue = value.txt.split('-'); ;;; if (splitvalue.length > 2) { @@ -242,17 +259,28 @@ ;;; this.emitError(kukit.E); ;;; } // set it - var action = this.actions.getOrCreateAction(value.txt); - if (actionType != 'X' || action.type == null) { - action.setType(actionType); + if (actionType != 'X') { + // any other qualifier then delete + var action = this.actions.getOrCreateAction(value.txt, valuesByReturnType); + if (action.type == null) { + action.setType(actionType); + } } else { + // action-cancel this.actions.deleteAction(value.txt); } -} +}; -kukit.kssp.Block.prototype.addActionError = function(action, key, value) { +kukit.kssp.Block.prototype.addActionError = function(action, key, values) { // -error: // default-error: + // + // This can only accept string. + var allowedReturnTypes; +;;; allowedReturnTypes = {string: true}; +;;; kukit.E = 'action error parameter [' + key + ']'; + var value = this.preprocessValues(values, allowedReturnTypes, kukit.E).string; +;;; // It cannot be a provider, it must be a real string. ;;; if (value.isMethod == true) { ;;; kukit.E = 'Wrong value for key [' + key + '] : '; ;;; kukit.E += 'value providers are not '; @@ -261,11 +289,11 @@ ;;; } action.setError(value.txt); // also create the action for the error itself. - var err_action = this.actions.getOrCreateAction(value.txt); + var err_action = this.actions.getOrCreateAction(value.txt, {}); err_action.setType('E'); -} +}; -kukit.kssp.Block.prototype.addActionParameter = function(action, key, value) { +kukit.kssp.Block.prototype.addActionParameter = function(action, key, values) { // -: // default-: // @@ -276,46 +304,52 @@ // This will also set the value providers on the value // (from check). // - try { - // Check also sets the value provider on the value. - value.check(); - } catch(e) { -;;; kukit.E = 'Error in value : ' + e + '.'; - this.emitError(kukit.E); - } -;;; // Check return type -;;; // strings are currently unwrapped and will have -;;; // returnType == undefined, so we check for that. -;;; var returnType = value.pprovider.returnType; -;;; if (key == 'kssSelector') { -;;; // for kssSelector, string or formquery expected -;;; if (returnType && returnType != 'string' && returnType != 'selection') { -;;; kukit.E = 'Expected string or a selection result and got [' + returnType; -;;; kukit.E += '] in the kss action parameter [kssSelector].'; + var value; + if (key.substr(0, 3) == 'kss') { +;;; // Special selector types can have only one value +;;; if (values.length != 1) { +;;; kukit.E = 'Must have exactly one value, and got [' + values.length; +;;; kukit.E += '] in the kss action parameter [' + key + '].'; ;;; this.emitError(kukit.E); ;;; } -;;; } else if (key == 'kssSubmitForm') { -;;; // for kssSelector, string or formquery expected -;;; if (returnType && returnType != 'string' && returnType != 'formquery') { -;;; kukit.E = 'Expected string or a formquery result and got [' + returnType; -;;; kukit.E += '] in the kss action parameter [kssSubmitForm].'; -;;; this.emitError(kukit.E); -;;; } -;;; } else { -;;; // for all other cases, string is expected -;;; if (returnType && returnType != 'string') { -;;; kukit.E = 'Expected string and got [' + returnType; -;;; kukit.E += '] in the action parameter [' + key + '].'; -;;; this.emitError(kukit.E); + value = values[0]; +;;; // kss special parameter need special checking of the strings. +;;; // (not needed in production mode, since we have the value already) +;;; var allowedReturnTypes = {}; +;;; if (key == 'kssSelector') { +;;; // for kssSelector, one of string or formquery expected +;;; allowedReturnTypes = {string: true, selection: true}; +;;; } else if (key == 'kssSubmitForm') { +;;; // for kssSubmitForm string or formquery expected +;;; allowedReturnTypes = {string: true, formquery: true}; +;;; } else if (key == 'kssUrl') { +;;; // for kssSubmitForm string or url expected +;;; allowedReturnTypes = {string: true, url: true}; ;;; } -;;; } - // store the value +;;; // We ignore actual results here, and just check. +;;; kukit.E = 'kss action parameter [' + key + ']'; +;;; // last parameter is true: means we do _not_ require the existence +;;; // of a string type. +;;; this.preprocessValues(values, allowedReturnTypes, kukit.E, true); + } else { + // Normal selectors: can have more values + // check its return types + var allowedReturnTypes; +;;; allowedReturnTypes = {string: true, selection: true}; +;;; kukit.E = 'action parameter [' + key + ']'; + var valuesByReturnType = this.preprocessValues(values, allowedReturnTypes, kukit.E); + value = valuesByReturnType.string; + // Store the selector on the value. + value.selectorProvider = valuesByReturnType.selection; + } + // store the (main, string) value action.parms[key] = value; }; -kukit.kssp.Block.prototype.addDeclaration = function(key, value) { - // p.s. value is here a KssXxParm. In most cases we check and unwrap it. - // the keys look like this: +kukit.kssp.Block.prototype.addDeclaration = function(key, values) { + // values contains a list of arguments (KssTextValue or KssMethodValue) + // + // the key looks like this: // // evt--: // evt---: @@ -343,11 +377,13 @@ ;;; kukit.E += '"evt---".'; ;;; this.emitError(kukit.E); ;;; } + // Preprocess the values + // var name = splitkey[0]; if (name == 'evt') { - this.addEventDeclaration(key, splitkey, value); + this.addEventDeclaration(key, splitkey, values); } else if (name == 'action') { - this.addActionDeclaration(key, splitkey, value); + this.addActionDeclaration(key, splitkey, values); } else { // -: // --: @@ -370,15 +406,75 @@ actionName = splitkey[0] + '-' + splitkey[1]; actionKey = splitkey[2]; } - var action = this.actions.getOrCreateAction(actionName); + var action = this.actions.getOrCreateAction(actionName, {}); if (actionKey == 'error') { - this.addActionError(action, key, value); + this.addActionError(action, key, values); } else { - this.addActionParameter(action, actionKey, value); + this.addActionParameter(action, actionKey, values); } } }; +kukit.kssp.Block.prototype.preprocessValues = function(values, allowedReturnTypes, + errInfo, noStringRequired) { + // allowedReturnTypes is a dict keyed by the returnType, containing true as value. + // key is only used for the error reporting + // This will also call check on all the value names! + // noStringRequired is set to true at the kss special parameters. All other + // occasions require at least a string to be present, so we check for that too. + var valuesByReturnType = {}; + + for (var i=0; i . + // Now we found the token that must be . tokenIndex -= 2; if (tokenIndex < 0 || (this.result[tokenIndex+2].symbol != Modified: kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/resourcedata.js ============================================================================== --- kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/resourcedata.js (original) +++ kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/resourcedata.js Sun Jan 6 17:19:33 2008 @@ -502,13 +502,25 @@ } }; -kukit.rd.ActionSet.prototype.getOrCreateAction = function(name) { +kukit.rd.ActionSet.prototype.getOrCreateAction = function(name, valuesByReturnType) { + // kss parameters will ve set from valuesByReturnType var action = this.content[name]; if (typeof(action) == 'undefined') { action = new kukit.rd.Action(); action.setName(name); this.content[name] = action; } + // Set other values that were given at the same line as the name. + // This enables individual overriding. + if (valuesByReturnType.selection) { + action.parms.kssSelector = valuesByReturnType.selection; + } + if (valuesByReturnType.formquery) { + action.parms.kssSubmitForm = valuesByReturnType.formquery; + } + if (valuesByReturnType.url) { + action.parms.kssUrl = valuesByReturnType.url; + } return action; }; Modified: kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/tests/test_kssparser.js ============================================================================== --- kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/tests/test_kssparser.js (original) +++ kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/tests/test_kssparser.js Sun Jan 6 17:19:33 2008 @@ -922,7 +922,6 @@ // This test can only run in development mode, pass otherwise. if (! kukit.isDevelMode) {return;} // - var txt= "nodeAttr('id')"; var txt= "nodeAttr(htmlid('id'))"; var cursor = new kukit.tk.Cursor(txt); var parser = new kukit.kssp.PropValue(cursor, null, true); @@ -940,7 +939,6 @@ // This test can only run in development mode, pass otherwise. if (! kukit.isDevelMode) {return;} // - var txt= "nodeAttr('id')"; var txt= "#id:click {\n" + " action-client: log;\n" + " log-message: nodeAttr(htmlid('id'));\n" @@ -948,7 +946,7 @@ var cursor = new kukit.tk.Cursor(txt); this.assertParsingError(kukit.kssp.Document, cursor, null, true, // XXX This error message will be fixed in service-layer branch - 'Error in value : Error: Expected string value and got [selection] in argument #[1] of provider [nodeAttr].., at row 1, column 11'); + 'Error in value for action parameter [message] : Error: Expected string value and got [selection] in argument #[1] of provider [nodeAttr].., at row 1, column 11'); }; this.testNormalProviderRejectsFormQuery = function() { @@ -957,15 +955,11 @@ // This test can only run in development mode, pass otherwise. if (! kukit.isDevelMode) {return;} // - var txt= "nodeAttr('id')"; var txt= "nodeAttr(form('name'))"; var cursor = new kukit.tk.Cursor(txt); - var parser = new kukit.kssp.PropValue(cursor, null, true); - var value = parser.value; - this.assertThrows(function() { - value.check(); - }, - Error); + this.assertParsingError(kukit.kssp.Document, cursor, null, true, + // XXX This error message will be fixed in service-layer branch + 'Error in value for action parameter [message] : Error: Expected string value and got [selection] in argument #[1] of provider [nodeAttr].., at row 1, column 11'); }; this.testNormalProviderRejectsFormQueryFullRule = function() { @@ -983,7 +977,7 @@ var cursor = new kukit.tk.Cursor(txt); this.assertParsingError(kukit.kssp.Document, cursor, null, true, // XXX This error message will be fixed in service-layer branch - 'Error in value : Error: Expected string value and got [formquery] in argument #[1] of provider [nodeAttr].., at row 1, column 11'); + 'Error in value for action parameter [message] : Error: Expected string value and got [formquery] in argument #[1] of provider [nodeAttr].., at row 1, column 11'); }; this.testNormalProviderRejectsSelector = function() { @@ -992,7 +986,6 @@ // This test can only run in development mode, pass otherwise. if (! kukit.isDevelMode) {return;} // - var txt= "nodeAttr('id')"; var txt= "#id:click {\n" + " action-client: log;\n" + " log-message: htmlid('id');\n" @@ -1000,7 +993,7 @@ var cursor = new kukit.tk.Cursor(txt); this.assertParsingError(kukit.kssp.Document, cursor, null, true, // XXX This error message will be fixed in service-layer branch - 'Expected string and got [selection] in the action parameter [message]., at row 1, column 11'); + 'One string or one value provider with the result type [string] is needed in the action parameter [message]., at row 1, column 1'); }; this.testNormalProviderRejectsFormQuery = function() { @@ -1017,7 +1010,7 @@ var cursor = new kukit.tk.Cursor(txt); this.assertParsingError(kukit.kssp.Document, cursor, null, true, // XXX This error message will be fixed in service-layer branch - 'Expected string and got [formquery] in the action parameter [message]., at row 1, column 11'); + 'Provider result type [formquery] not allowed in the action parameter [message]., at row 1, column 1'); }; this.testKssSelectorAcceptsSelector = function() { @@ -1073,7 +1066,7 @@ var cursor = new kukit.tk.Cursor(txt); this.assertParsingError(kukit.kssp.Document, cursor, null, true, // XXX This error message will be fixed in service-layer branch - 'Expected string or a selection result and got [formquery] in the kss action parameter [kssSelector]., at row 1, column 11'); + 'Provider result type [formquery] not allowed in the kss action parameter [kssSelector]., at row 1, column 11'); }; this.testKssSubmitFormAcceptsFormQuery = function() { @@ -1123,12 +1116,11 @@ var cursor = new kukit.tk.Cursor(txt); this.assertParsingError(kukit.kssp.Document, cursor, null, true, // XXX This error message will be fixed in service-layer branch - 'Expected string or a formquery result and got [selection] in the kss action parameter [kssSubmitForm]., at row 1, column 11'); + 'Provider result type [selection] not allowed in the kss action parameter [kssSubmitForm]., at row 1, column 11'); }; this.testCombinedClientAction = function() { // Client action accepts a list of combined providers. - // (it will evaluate as form(xxx), but we can't check that without a dom) // // This test can only run in development mode, pass otherwise. if (! kukit.isDevelMode) {return;} @@ -1142,6 +1134,52 @@ this.assertEquals(parser.finished, true); }; + this.testCombinedClientActionRejectsFormQuery = function() { + // Client action rejects form query. + // + // This test can only run in development mode, pass otherwise. + if (! kukit.isDevelMode) {return;} + // + var txt= "nodeAttr('id')"; + var txt= "#id:click {\n" + + " action-client: htmlid(id) doIt form();\n" + + "}\n" + var cursor = new kukit.tk.Cursor(txt); + this.assertParsingError(kukit.kssp.Document, cursor, null, true, + // XXX This error message will be fixed in service-layer branch + 'Error in value for action definition [action-client] : Error: form method needs 1 arguments (formname)., at row 1, column 11'); + }; + + this.testCombinedServerAction = function() { + // Server action accepts a list of combined providers. + // + // This test can only run in development mode, pass otherwise. + if (! kukit.isDevelMode) {return;} + // + var txt= "nodeAttr('id')"; + var txt= "#id:click {\n" + + " action-server: doIt currentForm();\n" + + "}\n" + var cursor = new kukit.tk.Cursor(txt); + var parser = new kukit.kssp.Document(cursor, null, true); + this.assertEquals(parser.finished, true); + }; + + this.testCombinedServerActionRejectsSelector = function() { + // Server action rejects a selection provider. + // + // This test can only run in development mode, pass otherwise. + if (! kukit.isDevelMode) {return;} + // + var txt= "nodeAttr('id')"; + var txt= "#id:click {\n" + + " action-server: doIt currentForm() htmlid(id);\n" + + "}\n" + var cursor = new kukit.tk.Cursor(txt); + this.assertParsingError(kukit.kssp.Document, cursor, null, true, + // XXX This error message will be fixed in service-layer branch + 'Provider result type [selection] not allowed in the action definition [action-server]., at row 1, column 11'); + }; }; From reebalazs at codespeak.net Sun Jan 6 17:19:36 2008 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Sun, 6 Jan 2008 17:19:36 +0100 (CET) Subject: [KSS-checkins] r50398 - in kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes: . kukit Message-ID: <20080106161936.537F81684CE@codespeak.net> Author: reebalazs Date: Sun Jan 6 17:19:36 2008 New Revision: 50398 Modified: kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/ (props changed) kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/kssparser.js Log: Fix handling of kss special parameters in production mode. preprocessValues is now doing value.check(), which is needed always, so preprocessValues also needs to be called in production mode. Modified: kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/kssparser.js ============================================================================== --- kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/kssparser.js (original) +++ kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/kssparser.js Sun Jan 6 17:19:36 2008 @@ -328,9 +328,11 @@ ;;; } ;;; // We ignore actual results here, and just check. ;;; kukit.E = 'kss action parameter [' + key + ']'; -;;; // last parameter is true: means we do _not_ require the existence -;;; // of a string type. -;;; this.preprocessValues(values, allowedReturnTypes, kukit.E, true); + // Call preprocessValues in both production and development mode: + // it is always needed, since it calls check() on the value. + // Last parameter is true: means we do _not_ require the existence + // of a string type. + this.preprocessValues(values, allowedReturnTypes, kukit.E, true); } else { // Normal selectors: can have more values // check its return types From reebalazs at codespeak.net Sun Jan 6 17:19:40 2008 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Sun, 6 Jan 2008 17:19:40 +0100 (CET) Subject: [KSS-checkins] r50399 - in kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes: . doc kukit Message-ID: <20080106161940.934851684D0@codespeak.net> Author: reebalazs Date: Sun Jan 6 17:19:40 2008 New Revision: 50399 Modified: kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/ (props changed) kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/doc/HISTORY.txt kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/kssparser.js kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/resourcedata.js Log: Implement evaluation of value providers with multiprop (selector in same line) Modified: kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/doc/HISTORY.txt ============================================================================== --- kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/doc/HISTORY.txt (original) +++ kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/doc/HISTORY.txt Sun Jan 6 17:19:40 2008 @@ -17,6 +17,10 @@ action parameters (remark: they should be used with kssSelector.) They now give a parsing error. + + Implement multiproperties in + * action-client and action-server + * any value provider [ree] - Fix multiple selection form fields Modified: kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/kssparser.js ============================================================================== --- kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/kssparser.js (original) +++ kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/kssparser.js Sun Jan 6 17:19:40 2008 @@ -342,7 +342,7 @@ var valuesByReturnType = this.preprocessValues(values, allowedReturnTypes, kukit.E); value = valuesByReturnType.string; // Store the selector on the value. - value.selectorProvider = valuesByReturnType.selection; + value.selectionValue = valuesByReturnType.selection; } // store the (main, string) value action.parms[key] = value; Modified: kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/resourcedata.js ============================================================================== --- kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/resourcedata.js (original) +++ kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/resourcedata.js Sun Jan 6 17:19:40 2008 @@ -202,7 +202,7 @@ ;;; // If a provider expects all strings ;;; // (like most value providers), it simply leaves this flag ;;; // intact, and we do the check here. -;;; if (! this.checkedArgTypes) { +;;; if (! this.pprovider.checkedArgTypes) { ;;; // We expect a string to each position. ;;; // By default, returnType is "string" so we also ;;; // check undefined. @@ -221,6 +221,20 @@ kukit.rd.KssMethodValue.prototype.evaluate = function(node, defaultParameters) { + // In case we have a selector, evaluate it. + if (this.selectionValue) { + var nodes = this.selectionValue.evaluate(node, defaultParameters) + // This must have returned exactly one node. If not, we raise error. + if (nodes.length != 1) { +;;; kukit.E = 'Selection provider [' + this.selectionValue.methodName; +;;; kukit.E += '] of value provider [' + this.methodName; +;;; kukit.E += '] must select exactly one node, ' +;;; kukit.E += 'got [' + nodes.length + '] instead.'; + throw new Error(kukit.E); + } + // Use this as node! + node = nodes[0]; + } // First recursivly evaluate all arguments var newArgs = []; for(var i=0; i < this.args.length; i++){ From reebalazs at codespeak.net Sun Jan 6 17:19:43 2008 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Sun, 6 Jan 2008 17:19:43 +0100 (CET) Subject: [KSS-checkins] r50400 - in kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes: . tests Message-ID: <20080106161943.ABF161684D9@codespeak.net> Author: reebalazs Date: Sun Jan 6 17:19:43 2008 New Revision: 50400 Modified: kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/ (props changed) kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/tests/test_kssparser.js Log: Add ecma tests for providers with multiproperty Modified: kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/tests/test_kssparser.js ============================================================================== --- kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/tests/test_kssparser.js (original) +++ kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/tests/test_kssparser.js Sun Jan 6 17:19:43 2008 @@ -981,7 +981,7 @@ }; this.testNormalProviderRejectsSelector = function() { - // normal parameters do not accept selector + // normal parameters do not accept selector (in itself) // // This test can only run in development mode, pass otherwise. if (! kukit.isDevelMode) {return;} @@ -1181,6 +1181,83 @@ 'Provider result type [selection] not allowed in the action definition [action-server]., at row 1, column 11'); }; + this.testNormalProviderAcceptsValueAndSelector = function() { + // normal parameters accepts value and selector + // + // This test can only run in development mode, pass otherwise. + if (! kukit.isDevelMode) {return;} + // + var txt= "#id:click {\n" + + " action-client: log;\n" + + " log-message: kssAttr(blah) htmlid('id');\n" + + "}\n" + var cursor = new kukit.tk.Cursor(txt); + var parser = new kukit.kssp.Document(cursor, null, true); + this.assertEquals(parser.finished, true); + }; + + this.testNormalProviderAcceptsSelectorAndValue = function() { + // normal parameters accepts value and selector + // + // This test can only run in development mode, pass otherwise. + if (! kukit.isDevelMode) {return;} + // + var txt= "#id:click {\n" + + " action-client: log;\n" + + " log-message: htmlid('id') kssAttr(blah);\n" + + "}\n" + var cursor = new kukit.tk.Cursor(txt); + var parser = new kukit.kssp.Document(cursor, null, true); + this.assertEquals(parser.finished, true); + }; + + this.testNormalProviderAcceptsStringAndSelector = function() { + // normal parameters accepts string and selector + // although this does not make much sense... but it's allowed. + // + // This test can only run in development mode, pass otherwise. + if (! kukit.isDevelMode) {return;} + // + var txt= "#id:click {\n" + + " action-client: log;\n" + + " log-message: 'message' htmlid('id');\n" + + "}\n" + var cursor = new kukit.tk.Cursor(txt); + var parser = new kukit.kssp.Document(cursor, null, true); + this.assertEquals(parser.finished, true); + }; + + this.testNormalProviderAcceptsSelectorAndString = function() { + // normal parameters accepts selector and string + // although this does not make much sense... but it's allowed. + // + // This test can only run in development mode, pass otherwise. + if (! kukit.isDevelMode) {return;} + // + var txt= "#id:click {\n" + + " action-client: log;\n" + + " log-message: htmlid('id') 'message';\n" + + "}\n" + var cursor = new kukit.tk.Cursor(txt); + var parser = new kukit.kssp.Document(cursor, null, true); + this.assertEquals(parser.finished, true); + }; + + this.testNormalProviderAcceptsValueAndSelector = function() { + // normal parameters accepts value and selector + // + // This test can only run in development mode, pass otherwise. + if (! kukit.isDevelMode) {return;} + // + var txt= "#id:click {\n" + + " action-client: log;\n" + + " log-message: kssAttr(blah) htmlid('id');\n" + + "}\n" + var cursor = new kukit.tk.Cursor(txt); + var parser = new kukit.kssp.Document(cursor, null, true); + this.assertEquals(parser.finished, true); + }; + }; kukit.KssParserValueProvidersCheckTestCase.prototype = new kukit.KssParserTestCaseBase; From reebalazs at codespeak.net Sun Jan 6 17:19:48 2008 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Sun, 6 Jan 2008 17:19:48 +0100 (CET) Subject: [KSS-checkins] r50401 - in kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes: . kukit tests Message-ID: <20080106161948.1C63A2A013E@codespeak.net> Author: reebalazs Date: Sun Jan 6 17:19:47 2008 New Revision: 50401 Modified: kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/ (props changed) kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/kssparser.js kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/providerreg.js kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/tests/test_kssparser.js Log: Add url() provider. Add ecma tests. Make some error messages more meaningful in some cases. Modified: kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/kssparser.js ============================================================================== --- kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/kssparser.js (original) +++ kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/kssparser.js Sun Jan 6 17:19:47 2008 @@ -457,8 +457,10 @@ ;;; if (typeof(valuesByReturnType[returnType]) != 'undefined') { ;;; if (returnType == 'string') { ;;; // Give a more sensible message for strings. -;;; kukit.E = 'Only one string or one value provider with result type '; -;;; kukit.E += '[string] is allowed in the ' + errInfo + '.'; +;;; // (Do not mention the word "provider" in the message +;;; // as action-xxx cannot take providers, only real strings. +;;; kukit.E = 'Only one [string] value '; +;;; kukit.E += 'is allowed in the ' + errInfo + '.'; ;;; } else { ;;; kukit.E = 'Only one provider with result type [' + returnType; ;;; kukit.E += '] is allowed in the ' + errInfo + '.'; @@ -470,8 +472,10 @@ } ;;; // Check we have at least a string type. (unless asked otherwise) ;;; if (! noStringRequired && typeof(valuesByReturnType.string) == 'undefined') { -;;; kukit.E = 'One string or one value provider with the result type [string] '; -;;; kukit.E += 'is needed in the ' + errInfo + '.'; +;;; // (Do not mention the word "provider" in the message +;;; // as action-xxx cannot take providers, only real strings. +;;; kukit.E = 'Missing [string] value '; +;;; kukit.E += 'in the ' + errInfo + '.'; ;;; this.emitError(kukit.E); ;;; } return valuesByReturnType; Modified: kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/providerreg.js ============================================================================== --- kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/providerreg.js (original) +++ kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/providerreg.js Sun Jan 6 17:19:47 2008 @@ -355,4 +355,18 @@ }; kukit.pprovidersGlobalRegistry.register('kssIdOfValue', kukit.pr.KssIdOfValuePP); +/* The url() provider just passes the parameters, and is used to have + * a different return type. It can be used in the line of action-server. + * as an alternative to a separate kssUrl line. + */ +kukit.pr.UrlPP = function() { + this.check = function(args) { +;;; if (args.length != 1) { +;;; throw new Error('url() needs 1 argument'); +;;; } + }; +}; +kukit.pr.UrlPP.prototype = kukit.pr.IdentityPP; +// returnType = 'url' +kukit.pprovidersGlobalRegistry.register('url', kukit.pr.UrlPP, 'url'); Modified: kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/tests/test_kssparser.js ============================================================================== --- kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/tests/test_kssparser.js (original) +++ kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/tests/test_kssparser.js Sun Jan 6 17:19:47 2008 @@ -901,7 +901,10 @@ // We also check how these providers can be combined // on one line. // - // This testcase is added in DEVELOPMENT MODE ONLY. + // This testcase can run in DEVELOPMENT MODE ONLY, + // (because the checks are ignored in production mode) + // and all tests will be skipped + // and pass GREEN in production mode. this.testNormalProviderAcceptsString = function() { // normal providers does accept string @@ -916,7 +919,7 @@ value.check(); }; - this.testNormalProviderRejectsSelection = function() { + this.testNormalProviderRejectsSelectionAsParameter = function() { // normal providers does not accept selection // // This test can only run in development mode, pass otherwise. @@ -957,9 +960,10 @@ // var txt= "nodeAttr(form('name'))"; var cursor = new kukit.tk.Cursor(txt); - this.assertParsingError(kukit.kssp.Document, cursor, null, true, - // XXX This error message will be fixed in service-layer branch - 'Error in value for action parameter [message] : Error: Expected string value and got [selection] in argument #[1] of provider [nodeAttr].., at row 1, column 11'); + this.assertThrows(function() { + value.check(); + }, + Error); }; this.testNormalProviderRejectsFormQueryFullRule = function() { @@ -969,7 +973,6 @@ // This test can only run in development mode, pass otherwise. if (! kukit.isDevelMode) {return;} // - var txt= "nodeAttr('id')"; var txt= "#id:click {\n" + " action-client: log;\n" + " log-message: nodeAttr(form('name'));\n" @@ -980,7 +983,7 @@ 'Error in value for action parameter [message] : Error: Expected string value and got [formquery] in argument #[1] of provider [nodeAttr].., at row 1, column 11'); }; - this.testNormalProviderRejectsSelector = function() { + this.testNormalParameterRejectsSelectorInItself = function() { // normal parameters do not accept selector (in itself) // // This test can only run in development mode, pass otherwise. @@ -993,16 +996,15 @@ var cursor = new kukit.tk.Cursor(txt); this.assertParsingError(kukit.kssp.Document, cursor, null, true, // XXX This error message will be fixed in service-layer branch - 'One string or one value provider with the result type [string] is needed in the action parameter [message]., at row 1, column 1'); + 'Missing [string] value in the action parameter [message]., at row 1, column 11'); }; - this.testNormalProviderRejectsFormQuery = function() { + this.testNormalParameterRejectsFormQuery = function() { // normal parameters do not accept form query // // This test can only run in development mode, pass otherwise. if (! kukit.isDevelMode) {return;} // - var txt= "nodeAttr('id')"; var txt= "#id:click {\n" + " action-client: log;\n" + " log-message: form('name');\n" @@ -1019,7 +1021,6 @@ // This test can only run in development mode, pass otherwise. if (! kukit.isDevelMode) {return;} // - var txt= "nodeAttr('id')"; var txt= "#id:click {\n" + " action-client: setAttribute;\n" + " setAttribute-kssSelector: htmlid('id');\n" @@ -1038,7 +1039,6 @@ // This test can only run in development mode, pass otherwise. if (! kukit.isDevelMode) {return;} // - var txt= "nodeAttr('id')"; var txt= "#id:click {\n" + " action-client: setAttribute;\n" + " setAttribute-kssSelector: htmlid('id');\n" @@ -1056,7 +1056,6 @@ // This test can only run in development mode, pass otherwise. if (! kukit.isDevelMode) {return;} // - var txt= "nodeAttr('id')"; var txt= "#id:click {\n" + " action-client: setAttribute;\n" + " setAttribute-kssSelector: form('name');\n" @@ -1075,7 +1074,6 @@ // This test can only run in development mode, pass otherwise. if (! kukit.isDevelMode) {return;} // - var txt= "nodeAttr('id')"; var txt= "#id:click {\n" + " action-server: doIt;\n" + " doIt-kssSubmitForm: form('name');\n" @@ -1092,7 +1090,6 @@ // This test can only run in development mode, pass otherwise. if (! kukit.isDevelMode) {return;} // - var txt= "nodeAttr('id')"; var txt= "#id:click {\n" + " action-server: doIt;\n" + " doIt-kssSubmitForm: 'name';\n" @@ -1108,7 +1105,6 @@ // This test can only run in development mode, pass otherwise. if (! kukit.isDevelMode) {return;} // - var txt= "nodeAttr('id')"; var txt= "#id:click {\n" + " action-server: doIt;\n" + " doIt-kssSubmitForm: htmlid('id');\n" @@ -1125,7 +1121,6 @@ // This test can only run in development mode, pass otherwise. if (! kukit.isDevelMode) {return;} // - var txt= "nodeAttr('id')"; var txt= "#id:click {\n" + " action-client: htmlid(id) doIt;\n" + "}\n" @@ -1140,7 +1135,6 @@ // This test can only run in development mode, pass otherwise. if (! kukit.isDevelMode) {return;} // - var txt= "nodeAttr('id')"; var txt= "#id:click {\n" + " action-client: htmlid(id) doIt form();\n" + "}\n" @@ -1156,7 +1150,6 @@ // This test can only run in development mode, pass otherwise. if (! kukit.isDevelMode) {return;} // - var txt= "nodeAttr('id')"; var txt= "#id:click {\n" + " action-server: doIt currentForm();\n" + "}\n" @@ -1171,7 +1164,6 @@ // This test can only run in development mode, pass otherwise. if (! kukit.isDevelMode) {return;} // - var txt= "nodeAttr('id')"; var txt= "#id:click {\n" + " action-server: doIt currentForm() htmlid(id);\n" + "}\n" @@ -1181,6 +1173,111 @@ 'Provider result type [selection] not allowed in the action definition [action-server]., at row 1, column 11'); }; + this.testCombinedServerActionAcceptsStringAndUrl = function() { + // Server action accepts a string and an url. + // + // This test can only run in development mode, pass otherwise. + if (! kukit.isDevelMode) {return;} + // + var txt= "#id:click {\n" + + " action-server: doIt url('http://foo.bar');\n" + + "}\n" + var cursor = new kukit.tk.Cursor(txt); + var parser = new kukit.kssp.Document(cursor, null, true); + this.assertEquals(parser.finished, true); + }; + + this.testCombinedServerActionAcceptsUrlAndString = function() { + // Server action accepts a string and an url. + // + // This test can only run in development mode, pass otherwise. + if (! kukit.isDevelMode) {return;} + // + var txt= "#id:click {\n" + + " action-server: doIt url('http://foo.bar');\n" + + "}\n" + var cursor = new kukit.tk.Cursor(txt); + var parser = new kukit.kssp.Document(cursor, null, true); + this.assertEquals(parser.finished, true); + }; + + this.testCombinedServerActionAcceptsStringAndFormAndUrl = function() { + // Server action accepts string, form, and url providers together. + // + // This test can only run in development mode, pass otherwise. + if (! kukit.isDevelMode) {return;} + // + var txt= "#id:click {\n" + + " action-server: doIt currentForm() url('http://foo.bar');\n" + + "}\n" + var cursor = new kukit.tk.Cursor(txt); + var parser = new kukit.kssp.Document(cursor, null, true); + this.assertEquals(parser.finished, true); + }; + + this.testCombinedServerActionRejectsUrlInItself = function() { + // Server action rejects url() in itself. + // It should have a string in any case. + // + // This test can only run in development mode, pass otherwise. + if (! kukit.isDevelMode) {return;} + // + var txt= "#id:click {\n" + + " action-server: url('http://foo.bar');\n" + + "}\n" + var cursor = new kukit.tk.Cursor(txt); + this.assertParsingError(kukit.kssp.Document, cursor, null, true, + // XXX This error message will be fixed in service-layer branch + 'Missing [string] value in the action definition [action-server]., at row 1, column 11'); + }; + + this.testCombinedServerActionRejectsTwoStrings = function() { + // Server action rejects two strings. + // + // This test can only run in development mode, pass otherwise. + if (! kukit.isDevelMode) {return;} + // + var txt= "#id:click {\n" + + " action-server: foo 'bar';\n" + + "}\n" + var cursor = new kukit.tk.Cursor(txt); + this.assertParsingError(kukit.kssp.Document, cursor, null, true, + // XXX This error message will be fixed in service-layer branch + 'Only one [string] value is allowed in the action definition [action-server]., at row 1, column 11'); + }; + + + this.testCombinedServerActionRejectsUrlWithoutParms = function() { + // Server action rejects url() if url has no parameter. + // It should have a string in any case. + // + // This test can only run in development mode, pass otherwise. + if (! kukit.isDevelMode) {return;} + // + var txt= "#id:click {\n" + + " action-server: doIt url();\n" + + "}\n" + var cursor = new kukit.tk.Cursor(txt); + this.assertParsingError(kukit.kssp.Document, cursor, null, true, + // XXX This error message will be fixed in service-layer branch + 'Error in value for action definition [action-server] : Error: url() needs 1 argument., at row 1, column 11'); + }; + + this.testServerActionRejectsValueProviderForString = function() { + // Server action must have a string, no value provider is allowed here. + // + // This test can only run in development mode, pass otherwise. + if (! kukit.isDevelMode) {return;} + // + var txt= "#id:click {\n" + + " action-server: kssAttr(blah);\n" + + "}\n" + var cursor = new kukit.tk.Cursor(txt); + this.assertParsingError(kukit.kssp.Document, cursor, null, true, + // XXX This error message will be fixed in service-layer branch + 'Wrong value for key [action-server] : value providers are not allowed for action- keys., at row 1, column 11'); + }; + this.testNormalProviderAcceptsValueAndSelector = function() { // normal parameters accepts value and selector // From reebalazs at codespeak.net Sun Jan 6 17:19:51 2008 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Sun, 6 Jan 2008 17:19:51 +0100 (CET) Subject: [KSS-checkins] r50402 - in kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes: . kukit Message-ID: <20080106161951.DFEC71684DA@codespeak.net> Author: reebalazs Date: Sun Jan 6 17:19:51 2008 New Revision: 50402 Modified: kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/ (props changed) kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/kssparser.js kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/oper.js kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/providerreg.js Log: Fix url() provider... remove some formquery evaluation that is not needed any more Modified: kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/kssparser.js ============================================================================== --- kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/kssparser.js (original) +++ kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/kssparser.js Sun Jan 6 17:19:51 2008 @@ -323,7 +323,7 @@ ;;; // for kssSubmitForm string or formquery expected ;;; allowedReturnTypes = {string: true, formquery: true}; ;;; } else if (key == 'kssUrl') { -;;; // for kssSubmitForm string or url expected +;;; // for string or url expected ;;; allowedReturnTypes = {string: true, url: true}; ;;; } ;;; // We ignore actual results here, and just check. Modified: kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/oper.js ============================================================================== --- kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/oper.js (original) +++ kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/oper.js Sun Jan 6 17:19:51 2008 @@ -207,15 +207,6 @@ for (key in this.kssParms) { if (key == 'kssSubmitForm') { // Value has been evaluated at this point. - var formQuery = this.kssParms[key]; - // If a string is returned: this is to support - // kssSubmitForm: "formname"; - // in this case this is evaluated as form("formname"). - if (typeof(formQuery) == 'string') { - var locator = new kukit.fo.NamedFormLocator(formQuery); - var collector = new kukit.ut.TupleCollector(); - formQuery = kukit.fo.getAllFormVars(locator, collector); - } ;;; } else if (key == 'kssUrl') { ;;; // Value will be evaluated. ;;; } else { Modified: kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/providerreg.js ============================================================================== --- kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/providerreg.js (original) +++ kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/providerreg.js Sun Jan 6 17:19:51 2008 @@ -366,7 +366,7 @@ ;;; } }; }; -kukit.pr.UrlPP.prototype = kukit.pr.IdentityPP; +kukit.pr.UrlPP.prototype = new kukit.pr.IdentityPP(); // returnType = 'url' kukit.pprovidersGlobalRegistry.register('url', kukit.pr.UrlPP, 'url'); From reebalazs at codespeak.net Sun Jan 6 17:19:56 2008 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Sun, 6 Jan 2008 17:19:56 +0100 (CET) Subject: [KSS-checkins] r50403 - in kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes: . kukit tests Message-ID: <20080106161956.6810A1684DA@codespeak.net> Author: reebalazs Date: Sun Jan 6 17:19:55 2008 New Revision: 50403 Modified: kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/ (props changed) kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/forms.js kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/kssparser.js kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/resourcedata.js kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/tests/test_kssparser.js Log: Rename formquery -> formdata Modified: kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/forms.js ============================================================================== --- kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/forms.js (original) +++ kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/forms.js Sun Jan 6 17:19:55 2008 @@ -310,7 +310,7 @@ // // form, currentForm will fetch an entire form for marshalling. // This is needed because duplications and order must be preserved. -// The returnType of them will be registered as "formquery". This +// The returnType of them will be registered as "formdata". This // represents a list of (key, value) tuples that need to be marshalled. // This assures to preserve order of keys, which is important // for multi-values. @@ -335,7 +335,7 @@ return fo.getAllFormVars(locator, collector); } }; -kukit.pprovidersGlobalRegistry.register('form', _FormValueProvider, 'formquery'); +kukit.pprovidersGlobalRegistry.register('form', _FormValueProvider, 'formdata'); /* * @@ -355,7 +355,7 @@ return fo.getAllFormVars(locator, collector); } }; -kukit.pprovidersGlobalRegistry.register('currentForm', _CurrentFormValueProvider, 'formquery'); +kukit.pprovidersGlobalRegistry.register('currentForm', _CurrentFormValueProvider, 'formdata'); /* BBB. To be deprecated on 2008-06-15 */ Modified: kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/kssparser.js ============================================================================== --- kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/kssparser.js (original) +++ kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/kssparser.js Sun Jan 6 17:19:55 2008 @@ -236,7 +236,7 @@ // preprocess values var allowedReturnTypes; ;;; if (actionType == 'S') { -;;; allowedReturnTypes = {string: true, formquery: true, url: true}; +;;; allowedReturnTypes = {string: true, formdata: true, url: true}; ;;; } else { ;;; allowedReturnTypes = {string: true, selection: true}; ;;; } @@ -317,13 +317,13 @@ ;;; // (not needed in production mode, since we have the value already) ;;; var allowedReturnTypes = {}; ;;; if (key == 'kssSelector') { -;;; // for kssSelector, one of string or formquery expected +;;; // for kssSelector, one of string or selection is expected ;;; allowedReturnTypes = {string: true, selection: true}; ;;; } else if (key == 'kssSubmitForm') { -;;; // for kssSubmitForm string or formquery expected -;;; allowedReturnTypes = {string: true, formquery: true}; +;;; // for kssSubmitForm, one of string or formdata is expected +;;; allowedReturnTypes = {string: true, formdata: true}; ;;; } else if (key == 'kssUrl') { -;;; // for string or url expected +;;; // for kssUrl, one of string or url is expected ;;; allowedReturnTypes = {string: true, url: true}; ;;; } ;;; // We ignore actual results here, and just check. Modified: kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/resourcedata.js ============================================================================== --- kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/resourcedata.js (original) +++ kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/resourcedata.js Sun Jan 6 17:19:55 2008 @@ -529,8 +529,8 @@ if (valuesByReturnType.selection) { action.parms.kssSelector = valuesByReturnType.selection; } - if (valuesByReturnType.formquery) { - action.parms.kssSubmitForm = valuesByReturnType.formquery; + if (valuesByReturnType.formdata) { + action.parms.kssSubmitForm = valuesByReturnType.formdata; } if (valuesByReturnType.url) { action.parms.kssUrl = valuesByReturnType.url; Modified: kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/tests/test_kssparser.js ============================================================================== --- kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/tests/test_kssparser.js (original) +++ kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/tests/test_kssparser.js Sun Jan 6 17:19:55 2008 @@ -894,7 +894,13 @@ // Different tests to see if the syntax type check of // the value providers is working correctly. // At the moment we have the following return value types: - // string, selection, formquery + // + // string: almost all normal providers return string + // selection: a selector provider returns a list of nodes + // formdata: a form provider returns an ordered list + // of key-value pairs to be marshalled + // url: the return type of the url() provider + // // We do not check the actual evaluation here, as we // have no DOM at hand. // @@ -952,7 +958,7 @@ 'Error in value for action parameter [message] : Error: Expected string value and got [selection] in argument #[1] of provider [nodeAttr].., at row 1, column 11'); }; - this.testNormalProviderRejectsFormQuery = function() { + this.testNormalProviderRejectsFormData = function() { // normal providers do not accept form query // // This test can only run in development mode, pass otherwise. @@ -966,7 +972,7 @@ Error); }; - this.testNormalProviderRejectsFormQueryFullRule = function() { + this.testNormalProviderRejectsFormDataFullRule = function() { // normal providers do not accept form query // full rule // @@ -980,7 +986,7 @@ var cursor = new kukit.tk.Cursor(txt); this.assertParsingError(kukit.kssp.Document, cursor, null, true, // XXX This error message will be fixed in service-layer branch - 'Error in value for action parameter [message] : Error: Expected string value and got [formquery] in argument #[1] of provider [nodeAttr].., at row 1, column 11'); + 'Error in value for action parameter [message] : Error: Expected string value and got [formdata] in argument #[1] of provider [nodeAttr].., at row 1, column 11'); }; this.testNormalParameterRejectsSelectorInItself = function() { @@ -999,7 +1005,7 @@ 'Missing [string] value in the action parameter [message]., at row 1, column 11'); }; - this.testNormalParameterRejectsFormQuery = function() { + this.testNormalParameterRejectsFormData = function() { // normal parameters do not accept form query // // This test can only run in development mode, pass otherwise. @@ -1012,7 +1018,7 @@ var cursor = new kukit.tk.Cursor(txt); this.assertParsingError(kukit.kssp.Document, cursor, null, true, // XXX This error message will be fixed in service-layer branch - 'Provider result type [formquery] not allowed in the action parameter [message]., at row 1, column 1'); + 'Provider result type [formdata] not allowed in the action parameter [message]., at row 1, column 1'); }; this.testKssSelectorAcceptsSelector = function() { @@ -1050,7 +1056,7 @@ this.assertEquals(parser.finished, true); }; - this.testKssSelectorRejectsFormQuery = function() { + this.testKssSelectorRejectsFormData = function() { // kssSelector rejects form query // // This test can only run in development mode, pass otherwise. @@ -1065,10 +1071,10 @@ var cursor = new kukit.tk.Cursor(txt); this.assertParsingError(kukit.kssp.Document, cursor, null, true, // XXX This error message will be fixed in service-layer branch - 'Provider result type [formquery] not allowed in the kss action parameter [kssSelector]., at row 1, column 11'); + 'Provider result type [formdata] not allowed in the kss action parameter [kssSelector]., at row 1, column 11'); }; - this.testKssSubmitFormAcceptsFormQuery = function() { + this.testKssSubmitFormAcceptsFormData = function() { // kssSubmitForm accepts form query // // This test can only run in development mode, pass otherwise. @@ -1129,7 +1135,7 @@ this.assertEquals(parser.finished, true); }; - this.testCombinedClientActionRejectsFormQuery = function() { + this.testCombinedClientActionRejectsFormData = function() { // Client action rejects form query. // // This test can only run in development mode, pass otherwise. From reebalazs at codespeak.net Sun Jan 6 17:19:59 2008 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Sun, 6 Jan 2008 17:19:59 +0100 (CET) Subject: [KSS-checkins] r50404 - in kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes: . tests Message-ID: <20080106161959.3780F1684DA@codespeak.net> Author: reebalazs Date: Sun Jan 6 17:19:58 2008 New Revision: 50404 Modified: kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/ (props changed) kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/tests/test_kssparser.js Log: Add comments for ecma tests broken on IE They are broken because of the error text checking. This is already fixed (and tested against) on the service-layer branch. Modified: kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/tests/test_kssparser.js ============================================================================== --- kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/tests/test_kssparser.js (original) +++ kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/tests/test_kssparser.js Sun Jan 6 17:19:58 2008 @@ -955,6 +955,7 @@ var cursor = new kukit.tk.Cursor(txt); this.assertParsingError(kukit.kssp.Document, cursor, null, true, // XXX This error message will be fixed in service-layer branch + // XXX This will also fix runnin from IE, currently broken at error assert. 'Error in value for action parameter [message] : Error: Expected string value and got [selection] in argument #[1] of provider [nodeAttr].., at row 1, column 11'); }; @@ -986,6 +987,7 @@ var cursor = new kukit.tk.Cursor(txt); this.assertParsingError(kukit.kssp.Document, cursor, null, true, // XXX This error message will be fixed in service-layer branch + // XXX This will also fix runnin from IE, currently broken at error assert. 'Error in value for action parameter [message] : Error: Expected string value and got [formdata] in argument #[1] of provider [nodeAttr].., at row 1, column 11'); }; @@ -1002,6 +1004,7 @@ var cursor = new kukit.tk.Cursor(txt); this.assertParsingError(kukit.kssp.Document, cursor, null, true, // XXX This error message will be fixed in service-layer branch + // XXX This will also fix runnin from IE, currently broken at error assert. 'Missing [string] value in the action parameter [message]., at row 1, column 11'); }; @@ -1018,6 +1021,7 @@ var cursor = new kukit.tk.Cursor(txt); this.assertParsingError(kukit.kssp.Document, cursor, null, true, // XXX This error message will be fixed in service-layer branch + // XXX This will also fix runnin from IE, currently broken at error assert. 'Provider result type [formdata] not allowed in the action parameter [message]., at row 1, column 1'); }; @@ -1071,6 +1075,7 @@ var cursor = new kukit.tk.Cursor(txt); this.assertParsingError(kukit.kssp.Document, cursor, null, true, // XXX This error message will be fixed in service-layer branch + // XXX This will also fix runnin from IE, currently broken at error assert. 'Provider result type [formdata] not allowed in the kss action parameter [kssSelector]., at row 1, column 11'); }; @@ -1118,6 +1123,7 @@ var cursor = new kukit.tk.Cursor(txt); this.assertParsingError(kukit.kssp.Document, cursor, null, true, // XXX This error message will be fixed in service-layer branch + // XXX This will also fix runnin from IE, currently broken at error assert. 'Provider result type [selection] not allowed in the kss action parameter [kssSubmitForm]., at row 1, column 11'); }; @@ -1147,6 +1153,7 @@ var cursor = new kukit.tk.Cursor(txt); this.assertParsingError(kukit.kssp.Document, cursor, null, true, // XXX This error message will be fixed in service-layer branch + // XXX This will also fix runnin from IE, currently broken at error assert. 'Error in value for action definition [action-client] : Error: form method needs 1 arguments (formname)., at row 1, column 11'); }; @@ -1176,6 +1183,7 @@ var cursor = new kukit.tk.Cursor(txt); this.assertParsingError(kukit.kssp.Document, cursor, null, true, // XXX This error message will be fixed in service-layer branch + // XXX This will also fix runnin from IE, currently broken at error assert. 'Provider result type [selection] not allowed in the action definition [action-server]., at row 1, column 11'); }; @@ -1234,6 +1242,7 @@ var cursor = new kukit.tk.Cursor(txt); this.assertParsingError(kukit.kssp.Document, cursor, null, true, // XXX This error message will be fixed in service-layer branch + // XXX This will also fix runnin from IE, currently broken at error assert. 'Missing [string] value in the action definition [action-server]., at row 1, column 11'); }; @@ -1249,6 +1258,7 @@ var cursor = new kukit.tk.Cursor(txt); this.assertParsingError(kukit.kssp.Document, cursor, null, true, // XXX This error message will be fixed in service-layer branch + // XXX This will also fix runnin from IE, currently broken at error assert. 'Only one [string] value is allowed in the action definition [action-server]., at row 1, column 11'); }; @@ -1266,6 +1276,7 @@ var cursor = new kukit.tk.Cursor(txt); this.assertParsingError(kukit.kssp.Document, cursor, null, true, // XXX This error message will be fixed in service-layer branch + // XXX This will also fix runnin from IE, currently broken at error assert. 'Error in value for action definition [action-server] : Error: url() needs 1 argument., at row 1, column 11'); }; @@ -1281,6 +1292,7 @@ var cursor = new kukit.tk.Cursor(txt); this.assertParsingError(kukit.kssp.Document, cursor, null, true, // XXX This error message will be fixed in service-layer branch + // XXX This will also fix runnin from IE, currently broken at error assert. 'Wrong value for key [action-server] : value providers are not allowed for action- keys., at row 1, column 11'); }; From reebalazs at codespeak.net Sun Jan 6 17:20:46 2008 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Sun, 6 Jan 2008 17:20:46 +0100 (CET) Subject: [KSS-checkins] r50405 - in kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo: . coresyntax coresyntax/selenium_tests parameterfunction parameterfunction/selenium_tests selenium_tests Message-ID: <20080106162046.A870E16847D@codespeak.net> Author: reebalazs Date: Sun Jan 6 17:20:45 2008 New Revision: 50405 Added: kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/coresyntax/__init__.pyc (contents, props changed) kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/coresyntax/config.py kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/coresyntax/demoview.pyc (contents, props changed) kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/coresyntax/kss_providers_multiprop.kss kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/coresyntax/kss_providers_multiprop.pt kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/coresyntax/kss_selector_param_multiprop.kss kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/coresyntax/kss_selector_param_multiprop.pt kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/coresyntax/kss_url_param_multiprop.kss kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/coresyntax/kss_url_param_multiprop.pt kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/coresyntax/selenium_tests/ kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/coresyntax/selenium_tests/README.txt - copied unchanged from r50327, kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/markup/selenium_tests/README.txt kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/coresyntax/selenium_tests/kss_providers_multiprop.html kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/coresyntax/selenium_tests/kss_selector_param.html kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/coresyntax/selenium_tests/kss_selector_param_multiprop.html - copied, changed from r50326, kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/selenium_tests/kss_selector_param.html kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/coresyntax/selenium_tests/kss_url_param_multiprop.html - copied, changed from r50326, kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/selenium_tests/urlparam.html kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/coresyntax/selenium_tests/urlparam.html - copied unchanged from r50326, kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/selenium_tests/urlparam.html kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/coresyntax/zopeconfig.py kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/parameterfunction/config.py - copied, changed from r50327, kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/config.py kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/parameterfunction/kss_form_submit_multiprop.kss - copied, changed from r50327, kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/parameterfunction/forms.kss kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/parameterfunction/kss_form_submit_multiprop.pt - copied, changed from r50327, kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/parameterfunction/forms.pt kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/parameterfunction/kssid-UNUSED.kss - copied unchanged from r50326, kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/parameterfunction/kssid.kss kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/parameterfunction/kssid-UNUSED.pt - copied unchanged from r50326, kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/parameterfunction/kssid.pt kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/parameterfunction/selenium_tests/ kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/parameterfunction/selenium_tests/README.txt - copied unchanged from r50327, kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/markup/selenium_tests/README.txt kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/parameterfunction/selenium_tests/kss_form_submit_multiprop.html - copied, changed from r50326, kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/selenium_tests/pf_forms.html kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/parameterfunction/selenium_tests/pf_forms.html - copied unchanged from r50326, kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/selenium_tests/pf_forms.html kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/parameterfunction/zopeconfig.py - copied, changed from r50327, kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/zopeconfig.py Removed: kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/parameterfunction/kssid.kss kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/parameterfunction/kssid.pt kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/selenium_tests/kss_selector_param.html kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/selenium_tests/pf_forms.html kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/selenium_tests/urlparam.html Modified: kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/config.py kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/coresyntax/configure.zcml kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/more_selectors.pt kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/parameterfunction/configure.zcml kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/parameterfunction/forms.pt kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/zopeconfig.py Log: Adding tests for coresyntax and providers Modified: kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/config.py ============================================================================== --- kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/config.py (original) +++ kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/config.py Sun Jan 6 17:20:45 2008 @@ -21,10 +21,7 @@ KSSDemo('', '', "preventdefault.html", "Preventdefault (a.k.a. Safari workarounds)"), KSSDemo('', '', "html_inserts.html", "HTML insertions (Change tag content returns)"), KSSDemo('', '', "client-server-protocol", "Client server protocol"), - KSSDemo('', 'Value providers', 'pf_forms.html', 'Forms'), KSSDemo('', 'Selectors', 'selectors.html', 'Parent node selector'), - KSSDemo('', 'Core syntax', "kss_selector_param.html", "Kss selector parameters"), - KSSDemo('', 'Core syntax', "kss_url_param.html", "Kss url parameters"), KSSDemo('', 'Core events', "kss_evt_preventbubbling.html", "Prevent bubbling KSS event parameter"), KSSDemo('', 'Core events', "kss_keyevents.html", "Key events"), KSSDemo('', 'Commands/Actions', "ca_focus.html", "Focus"), Added: kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/coresyntax/__init__.pyc ============================================================================== Binary file. No diff available. Added: kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/coresyntax/config.py ============================================================================== --- (empty file) +++ kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/coresyntax/config.py Sun Jan 6 17:20:45 2008 @@ -0,0 +1,21 @@ + +from kss.base.plugin import Plugin +from kss.demo.resource import ( + KSSDemo, + KSSSeleniumTestDirectory, + ) + +class CoreSyntaxDemos(Plugin): + + zope_demos = ( + KSSDemo('', 'Core syntax', "kss_selector_param.html", "Kss selector parameters"), + KSSDemo('', 'Core syntax', "kss_url_param.html", "Kss url parameters"), + KSSDemo('', 'Core syntax', "kss_selector_param_multiprop.html", "Kss selector parameters, with multiproperties"), + KSSDemo('', 'Core syntax', "kss_url_param_multiprop.html", "Kss url parameters, with multiproperties"), + KSSDemo('', 'Core syntax', "kss_providers_multiprop.html", "Kss providers, with multiproperties"), + ) + + # directories are relative from the location of this .py file + zope_selenium_testsuites = ( + KSSSeleniumTestDirectory('selenium_tests'), + ) Modified: kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/coresyntax/configure.zcml ============================================================================== --- kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/coresyntax/configure.zcml (original) +++ kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/coresyntax/configure.zcml Sun Jan 6 17:20:45 2008 @@ -1,8 +1,19 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Added: kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/coresyntax/demoview.pyc ============================================================================== Binary file. No diff available. Added: kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/coresyntax/kss_providers_multiprop.kss ============================================================================== --- (empty file) +++ kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/coresyntax/kss_providers_multiprop.kss Sun Jan 6 17:20:45 2008 @@ -0,0 +1,49 @@ + +/* log reset: we use kssSelector and not the straight way... + * since we test the multiprops now.. */ +/* XXX no idea how to wait for the log being cleared, + * so I rather just insert a text now */ +#log-reset a:click { + evt-click-preventdefault: true; + action-client: replaceInnerHTML; + replaceInnerHTML-kssSelector: htmlid(target); + replaceInnerHTML-html: 'Target'; +} + /*clearChildNodes-kssSelector: #logger;>*/ + + + +#button1:click { + evt-click-preventdefault: true; + action-client: replaceInnerHTML htmlid(target); + replaceInnerHTML-html: nodeAttr(id) htmlid(source); +} + +#button2:click { + evt-click-preventdefault: true; + action-client: replaceInnerHTML htmlid(target); + replaceInnerHTML-html: 'Error, OK'; + action-client: insertHTMLAsLastChild htmlid(target); + insertHTMLAsLastChild-html: nodeAttr(id) htmlid(nonexistent); +} + +#button3:click { + evt-click-preventdefault: true; + action-client: replaceInnerHTML htmlid(target); + replaceInnerHTML-html: 'Error, OK'; + action-client: insertHTMLAsLastChild htmlid(target); + insertHTMLAsLastChild-html: nodeAttr(id) css(h3); +} + +#button4:click { + evt-click-preventdefault: true; + action-client: replaceInnerHTML htmlid(target); + replaceInnerHTML-html: css("#source a") nodeAttr(href); +} + +#button5:click { + evt-click-preventdefault: true; + action-client: replaceInnerHTML htmlid(target); + replaceInnerHTML-html: css("#source a") nodeContent(); +} + Added: kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/coresyntax/kss_providers_multiprop.pt ============================================================================== --- (empty file) +++ kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/coresyntax/kss_providers_multiprop.pt Sun Jan 6 17:20:45 2008 @@ -0,0 +1,84 @@ + + + + + + + + + + +

    header

    + +

    Value providers with multiproperty

    + +

    We test the parameter functions can stand with a selector at the same line. + (The order of the providers on the line is irrelevant.)

    + + +

    Log

    +

    Reset log

    +
    Target
    +
    + + + + +
    + +

    + nodeAttr(id) htmlid(source); results "source". +

    +
    + Click the button. +
    + Click me ! + +
    + +

    + nodeAttr(id) htmlid(nonexistent); returns 0 node, causes error. +

    +
    + Click the button. +
    + Click me ! + +
    + +

    + nodeAttr(id) css(h3); returns more nodes, causes error. +

    +
    + Click the button. +
    + Click me ! + +
    + +

    + css("#source a") nodeAttr(href); results "http://foo.bar". +

    +
    + Click the button. +
    + Click me ! + +
    + +

    + css("#source a") nodeContent(); results "Do not click this.". +

    +
    + Click the button. +
    + Click me ! + + + +
    + + + Added: kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/coresyntax/kss_selector_param_multiprop.kss ============================================================================== --- (empty file) +++ kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/coresyntax/kss_selector_param_multiprop.kss Sun Jan 6 17:20:45 2008 @@ -0,0 +1,43 @@ + + +.clickable:click { + evt-click-preventdefault: true; +} + + +#button_1:click { + action-client: setStyle htmlid(button_2); + setStyle-name: backgroundColor; + setStyle-value: #FFa0a0; + action-client: setAttribute htmlid(button_2); + setAttribute-name: value; + setAttribute-value: 'RESET ME'; + +} + +#button_2:click { + action-client: setStyle; + setStyle-name: backgroundColor; + setStyle-value: white; + action-client: setAttribute; + setAttribute-name: value; + setAttribute-value: 'Watch me'; +} + +#button_3:click { + action-client: setStyle css("#button_4"); + setStyle-name: backgroundColor; + setStyle-value: #FFa0a0; + action-client: setAttribute css('#button_4'); + setAttribute-name: value; + setAttribute-value: 'RESET ME'; +} + +#button_4:click { + action-client: setStyle; + setStyle-name: backgroundColor; + setStyle-value: white; + action-client: setAttribute; + setAttribute-name: value; + setAttribute-value: 'Watch me'; +} Added: kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/coresyntax/kss_selector_param_multiprop.pt ============================================================================== --- (empty file) +++ kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/coresyntax/kss_selector_param_multiprop.pt Sun Jan 6 17:20:45 2008 @@ -0,0 +1,56 @@ + + + + + + + + + + +

    header

    + +

    Kss selector parameter with multiple properties demo

    +
    +

    There are two buttons. If you click on the first button, it changes the style of the + second button. Look at the link on the kss file to understand. +

    + +

    We use multiple properties, which means that instead the kssSelector line, the + selector is in the same line as the action-client. (See kss file.) +

    + +

    + action-client: setAttribute htmlid(button_2); +

    +
    + Click the button here. +
    + +
    + + +
    + + +

    + action-client: setAttribute css('#button_4'); +

    +
    + Click the button here. +
    + +
    + + +
    + + +
    + + + Added: kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/coresyntax/kss_url_param_multiprop.kss ============================================================================== --- (empty file) +++ kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/coresyntax/kss_url_param_multiprop.kss Sun Jan 6 17:20:45 2008 @@ -0,0 +1,23 @@ + + +.click:click { + evt-click-preventdefault: true; +} + + +#button_1:click { + action-server: urlMethod1; +} + +#button_2:click { + action-server: urlMethodAlias url(urlMethod2); +} + +#button_3:click { + action-server: urlMethodAnotherAlias url("@@urlMethod3/urlMethod3"); +} + +#button_4:click { + action-server: urlMethodAnotherAlias url(kssValue(attr, methodname)); +} + Added: kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/coresyntax/kss_url_param_multiprop.pt ============================================================================== --- (empty file) +++ kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/coresyntax/kss_url_param_multiprop.pt Sun Jan 6 17:20:45 2008 @@ -0,0 +1,68 @@ + + + + + + + + + + +

    header

    + + +

    Kss url parameter

    +
    +

    Click on buttons will call server-side. Each button exercise a different syntax to express which URL to call. Server will update the div hereunder with corresponding text.

    + +
    Target
    + +

    Relative URL

    +
    + Click the button; it will call urlMethod1 on the server. +
    #button_1:click 
    +  action-server: urlMethod1;
    +}
    + + + +

    Alias URL

    +
    + Click the button; it will call urlMethod2 on the server. +
    #button_2:click {
    +    action-server: urlMethodAlias url(urlMethod2);
    +}
    + + + +

    Alias URL with @@

    +
    + Click the button; it will call @@urlMethod3/urlMethod3 on the server. +
    #button_3:click {
    +    action-server: urlMethodAnotherAlias url("@@urlMethod3/urlMethod3");
    +}
    + + + + +

    Alias URL from provider

    +
    + Click the button; it will call @@urlMethod3/urlMethod3 on the server. +
    #button_4:click {
    +    action-server: urlMethodAnotherAlias url(kssValue(attr, methodname));
    +}
    + + + +
    + + + Added: kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/coresyntax/selenium_tests/kss_providers_multiprop.html ============================================================================== --- (empty file) +++ kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/coresyntax/selenium_tests/kss_providers_multiprop.html Sun Jan 6 17:20:45 2008 @@ -0,0 +1,109 @@ + + + +kss_providers_multiprop + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    kss_providers_multiprop
    open/demo/kss_providers_multiprop.html
    clickbutton1
    waitForTextPresentsource
    clicklink=Reset log
    waitForTextPresentTarget
    clickbutton2
    waitForTextPresentError, OK
    clicklink=Reset log
    waitForTextPresentTarget
    clickbutton3
    waitForTextPresentError, OK
    clicklink=Reset log
    waitForTextPresentTarget
    clickbutton4
    waitForTextPresentexact:http://foo.bar
    clicklink=Reset log
    waitForTextPresentTarget
    clickbutton5
    waitForTextPresentDo not click this.
    + + Added: kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/coresyntax/selenium_tests/kss_selector_param.html ============================================================================== --- (empty file) +++ kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/coresyntax/selenium_tests/kss_selector_param.html Sun Jan 6 17:20:45 2008 @@ -0,0 +1,109 @@ + + + +kss_selector_param + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    kss_selector_param
    open/demo/kss_selector_param.html
    clickbutton_1
    waitForValuebutton_2RESET ME
    assertValuebutton_2RESET ME
    clickbutton_2
    waitForValuebutton_2Watch me
    assertValuebutton_2Watch me
    clickbutton_3
    waitForValuebutton_4RESET ME
    assertValuebutton_4RESET ME
    clickbutton_4
    waitForValuebutton_4Watch me
    assertValuebutton_4Watch me
    clickbutton_5
    waitForValuebutton_6RESET ME
    assertValuebutton_6RESET ME
    clickbutton_6
    waitForValuebutton_6Watch me
    assertValuebutton_6Watch me
    + + Copied: kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/coresyntax/selenium_tests/kss_selector_param_multiprop.html (from r50326, kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/selenium_tests/kss_selector_param.html) ============================================================================== --- kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/selenium_tests/kss_selector_param.html (original) +++ kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/coresyntax/selenium_tests/kss_selector_param_multiprop.html Sun Jan 6 17:20:45 2008 @@ -10,7 +10,7 @@ open - /demo/kss_selector_param.html + /demo/kss_selector_param_multiprop.html @@ -73,36 +73,6 @@ button_4 Watch me - - click - button_5 - - - - waitForValue - button_6 - RESET ME - - - assertValue - button_6 - RESET ME - - - click - button_6 - - - - waitForValue - button_6 - Watch me - - - assertValue - button_6 - Watch me - Copied: kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/coresyntax/selenium_tests/kss_url_param_multiprop.html (from r50326, kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/selenium_tests/urlparam.html) ============================================================================== --- kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/selenium_tests/urlparam.html (original) +++ kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/coresyntax/selenium_tests/kss_url_param_multiprop.html Sun Jan 6 17:20:45 2008 @@ -10,7 +10,7 @@ open - /demo/kss_url_param.html + /demo/kss_url_param_multiprop.html @@ -63,6 +63,22 @@ Method 3 called + + click + button_4 + + + + waitForTextPresent + Method 3 called + + + + assertTextPresent + Method 3 called + + + Added: kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/coresyntax/zopeconfig.py ============================================================================== --- (empty file) +++ kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/coresyntax/zopeconfig.py Sun Jan 6 17:20:45 2008 @@ -0,0 +1,31 @@ + +from kss.demo.interfaces import ( + IKSSDemoResource, + IKSSSeleniumTestResource, + ) +from kss.demo.resource import ( + KSSDemo, + KSSSeleniumTestDirectory, + ) +from zope.interface import implements + +# Create a mesh of provided interfaces +# This is needed, because an utility must have a single interface. +class IResource(IKSSDemoResource, IKSSSeleniumTestResource): + pass + +class KSSCoreSyntaxDemos(object): + implements(IResource) + + demos = ( + KSSDemo('', 'Core syntax', "kss_selector_param.html", "Kss selector parameters"), + KSSDemo('', 'Core syntax', "kss_url_param.html", "Kss url parameters"), + KSSDemo('', 'Core syntax', "kss_selector_param_multiprop.html", "Kss selector parameters, with multiproperties"), + KSSDemo('', 'Core syntax', "kss_url_param_multiprop.html", "Kss url parameters, with multiproperties"), + KSSDemo('', 'Core syntax', "kss_providers_multiprop.html", "Kss providers, with multiproperties"), + ) + + # directories are relative from the location of this .py file + selenium_tests = ( + KSSSeleniumTestDirectory('selenium_tests'), + ) Modified: kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/more_selectors.pt ============================================================================== --- kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/more_selectors.pt (original) +++ kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/more_selectors.pt Sun Jan 6 17:20:45 2008 @@ -40,7 +40,7 @@

    Log

    -

    Reset log

    +

    Reset log

    You clicked :

    Copied: kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/parameterfunction/config.py (from r50327, kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/config.py) ============================================================================== --- kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/config.py (original) +++ kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/parameterfunction/config.py Sun Jan 6 17:20:45 2008 @@ -5,32 +5,11 @@ KSSSeleniumTestDirectory, ) -class CoreDemos(Plugin): +class ValueProviderDemos(Plugin): zope_demos = ( - KSSDemo('', '', "basic_commands.html", "Change tag content"), - KSSDemo('', '', "two_selects.html", "Two selects"), - KSSDemo('', '', "autoupdate.html", "Auto update"), - KSSDemo('', '', "inline_edit.html", "Inline edit"), - KSSDemo('', '', "cancel_submit.html", "Cancel Submit Click"), - KSSDemo('', '', "tree.html", "Tree"), - KSSDemo('', '', "more_selectors.html", "More complex selectors"), - KSSDemo('', '', "two_select_revisited.html", "Master-slave selects revisited"), - KSSDemo('', '', "form_submit.html", "Form submit"), - KSSDemo('', '', "error_handling.html", "Error handling"), - KSSDemo('', '', "preventdefault.html", "Preventdefault (a.k.a. Safari workarounds)"), - KSSDemo('', '', "html_inserts.html", "HTML insertions (Change tag content returns)"), - KSSDemo('', '', "client-server-protocol", "Client server protocol"), KSSDemo('', 'Value providers', 'pf_forms.html', 'Forms'), - KSSDemo('', 'Selectors', 'selectors.html', 'Parent node selector'), - KSSDemo('', 'Core syntax', "kss_selector_param.html", "Kss selector parameters"), - KSSDemo('', 'Core syntax', "kss_url_param.html", "Kss url parameters"), - KSSDemo('', 'Core events', "kss_evt_preventbubbling.html", "Prevent bubbling KSS event parameter"), - KSSDemo('', 'Core events', "kss_keyevents.html", "Key events"), - KSSDemo('', 'Commands/Actions', "ca_focus.html", "Focus"), - KSSDemo('', 'Commands/Actions', "actions.html", "Toggle case action"), - # XXX this should go to the other plugin wuth all its stuff - KSSDemo('Effects', '', "effects.html", "Effects"), + KSSDemo('', 'Value providers', 'kss_form_submit_multiprop.html', 'Form submit, with multiproperties'), ) # directories are relative from the location of this .py file Modified: kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/parameterfunction/configure.zcml ============================================================================== --- kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/parameterfunction/configure.zcml (original) +++ kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/parameterfunction/configure.zcml Sun Jan 6 17:20:45 2008 @@ -1,8 +1,20 @@ + + + + + + + + + + + + Modified: kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/parameterfunction/forms.pt ============================================================================== --- kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/parameterfunction/forms.pt (original) +++ kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/parameterfunction/forms.pt Sun Jan 6 17:20:45 2008 @@ -159,7 +159,7 @@
    Click me !

    - xxx-kssSubmitForm: 'field2' with complex field names, named form, given as string + xxx-kssSubmitForm: 'full2' with complex field names, named form, given as string

    Click the button. Copied: kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/parameterfunction/kss_form_submit_multiprop.kss (from r50327, kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/parameterfunction/forms.kss) ============================================================================== --- kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/parameterfunction/forms.kss (original) +++ kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/parameterfunction/kss_form_submit_multiprop.kss Sun Jan 6 17:20:45 2008 @@ -1,81 +1,23 @@ -#text:click { - action-client: executeCommand; - executeCommand-name: replaceInnerHTML; - executeCommand-selector: "#target"; - executeCommand-html: currentFormVar(); -} - -#text-by-name:click { - action-client: executeCommand; - executeCommand-name: replaceInnerHTML; - executeCommand-selector: "#target"; - executeCommand-html: currentFormVar(text-by-name); -} - -#text-by-kssname:click { - action-client: executeCommand; - executeCommand-name: replaceInnerHTML; - executeCommand-selector: "#target"; - executeCommand-html: currentFormVar(kssAttr(key1, true)); -} -#textarea:click { - action-client: executeCommand; - executeCommand-name: replaceInnerHTML; - executeCommand-selector: "#target"; - executeCommand-html: currentFormVar(); -} - -#textarea-by-name:click { - action-client: executeCommand; - executeCommand-name: replaceInnerHTML; - executeCommand-selector: "#target"; - executeCommand-html: currentFormVar("textarea-by-name"); -} - -#radio1:click { - action-client: executeCommand; - executeCommand-name: replaceInnerHTML; - executeCommand-selector: "#target"; - executeCommand-html: currentFormVar(); -} - -#radio2:click { - action-client: executeCommand; - executeCommand-name: replaceInnerHTML; - executeCommand-selector: "#target"; - executeCommand-html: currentFormVar(); -} - -#radio-by-name:click { - action-client: executeCommand; - executeCommand-name: replaceInnerHTML; - executeCommand-selector: "#target"; - executeCommand-html: currentFormVar(radio-by-name); -} -#fullform-current:click { - action-server: submitFullFormIntoRequest; - submitFullFormIntoRequest-kssSubmitForm: currentForm(); +/* log reset: we use kssSelector and not the straight way... + * since we test the multiprops now.. */ +/* XXX no idea how to wait for the log being cleared, + * so I rather just insert a text now */ +#log-reset a:click { + evt-click-preventdefault: true; + action-client: replaceInnerHTML; + replaceInnerHTML-kssSelector: htmlid(target); + replaceInnerHTML-html: 'Target'; } + /*clearChildNodes-kssSelector: #logger;>*/ + + #fullform-named:click { - action-server: submitFullFormIntoRequest; - submitFullFormIntoRequest-kssSubmitForm: form(full2); + action-server: submitFullFormIntoRequest form(full2); } -#fullform-namedbystring:click { - action-server: submitFullFormIntoRequest; - submitFullFormIntoRequest-kssSubmitForm: 'full2'; +#fullform-current:click { + action-server: submitFullFormIntoRequest currentForm(); } -#single-select:click { - action-client: executeCommand; - executeCommand-name: replaceInnerHTML; - executeCommand-selector: "#target"; - executeCommand-html: currentFormVar(single-select); -} - -#multiple-select:click { - action-server: submitMultiSelect; - submitMultiSelect-items: currentFormVar(multiple-select); -} Copied: kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/parameterfunction/kss_form_submit_multiprop.pt (from r50327, kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/parameterfunction/forms.pt) ============================================================================== --- kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/parameterfunction/forms.pt (original) +++ kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/parameterfunction/kss_form_submit_multiprop.pt Sun Jan 6 17:20:45 2008 @@ -1,4 +1,4 @@ - + @@ -13,161 +13,32 @@

    Forms

    We test the parameter functions related to forms : those functions extract values from fields to use them in the kinetic stylesheet.

    -

    The inner HTML of the div below will be replaced with the - value of the form element.

    -
    Target
    -
    -

    - currentFormVar() with text field. -

    -
    - Click the text field. -
    -
    - -
    -

    - currentFormVar(name) with text field. -

    -
    - Click the button. -
    -
    -
    - Click me ! - -
    -
    -

    - currentFormVar(kssAttr('name')) with text field. -

    -
    - Click the button. -
    -
    -
    - Click me ! - -
    -
    -

    - currentFormVar() with textarea field. -

    -
    - Click the textarea field. -
    -
    - -
    -

    - currentFormVar(name) with textarea field. -

    -
    - Click the button. -
    -
    -
    - Click me ! - -
    -
    -

    - currentFormVar() with radio field. -

    -
    - Click one of the radio buttons. -
    -
    radio-1 - - radio-2 - -
    -

    - currentFormVar(name) with radio field. -

    -
    - Click the button. -
    -
    - Click me ! - radio-1 - - radio-2 - -
    +

    We use multiple properties, which means that instead the kssSubmitForm line, the + form data provider is in the same line as the action-server. (See kss file.) +

    -

    - currentFormVar(name) with select field. -

    -
    - Click the button. -
    -
    - Click me ! - -
    +

    The inner HTML of the div below will be replaced with the + value of the form element.

    -

    - currentFormVar(name) with multiple select field. -

    -
    - Click the button. -
    -
    - Click me ! - -
    + +

    Log

    +

    Reset log

    +
    Target
    +
    -
    -

    - form(full1) with simple field names, named form -

    -
    - Removed after deprecation. -
    -

    - currentForm() with simple field names -

    -
    - Removed after deprecation. -

    - xxx-kssSubmitForm: form(full2) with complex field names, named form + action-server: submitFullFormIntoRequest form(full2); + with complex field names, named form

    Click the button.
    Click me ! -

    - xxx-kssSubmitForm: 'field2' with complex field names, named form, given as string -

    -
    - Click the button. -
    - Click me !

    - xxx-kssSubmitForm: currentForm() with complex field names + action-server: submitFullFormIntoRequest currentForm(); + with complex field names

    Click the button. Deleted: /kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/parameterfunction/kssid.kss ============================================================================== --- /kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/parameterfunction/kssid.kss Sun Jan 6 17:20:45 2008 +++ (empty file) @@ -1,91 +0,0 @@ -#text:click { - action-client: executeCommand; - executeCommand-name: replaceInnerHTML; - executeCommand-selector: "#target"; - executeCommand-html: currentFormVar(); -} - -#text-by-name:click { - action-client: executeCommand; - executeCommand-name: replaceInnerHTML; - executeCommand-selector: "#target"; - executeCommand-html: currentFormVar(text-by-name); -} - -#text-by-kssname:click { - action-client: executeCommand; - executeCommand-name: replaceInnerHTML; - executeCommand-selector: "#target"; - executeCommand-html: currentFormVar(kssAttr(key1, true)); -} -#textarea:click { - action-client: executeCommand; - executeCommand-name: replaceInnerHTML; - executeCommand-selector: "#target"; - executeCommand-html: currentFormVar(); -} - -#textarea-by-name:click { - action-client: executeCommand; - executeCommand-name: replaceInnerHTML; - executeCommand-selector: "#target"; - executeCommand-html: currentFormVar("textarea-by-name"); -} - -#radio1:click { - action-client: executeCommand; - executeCommand-name: replaceInnerHTML; - executeCommand-selector: "#target"; - executeCommand-html: currentFormVar(); -} - -#radio2:click { - action-client: executeCommand; - executeCommand-name: replaceInnerHTML; - executeCommand-selector: "#target"; - executeCommand-html: currentFormVar(); -} - -#radio-by-name:click { - action-client: executeCommand; - executeCommand-name: replaceInnerHTML; - executeCommand-selector: "#target"; - executeCommand-html: currentFormVar(radio-by-name); -} - -#fullform-simple:click { - action-server: submitFullForm; - submitFullForm-form: currentForm(); -} - -#fullform-simplenamed:click { - action-server: submitFullForm; - submitFullForm-form: form(full1); -} - -#fullform-current:click { - action-server: submitFullFormIntoRequest; - submitFullFormIntoRequest-kssSubmitForm: currentForm(); -} - -#fullform-named:click { - action-server: submitFullFormIntoRequest; - submitFullFormIntoRequest-kssSubmitForm: form(full2); -} - -#fullform-namedbystring:click { - action-server: submitFullFormIntoRequest; - submitFullFormIntoRequest-kssSubmitForm: 'full2'; -} - -#single-select:click { - action-client: executeCommand; - executeCommand-name: replaceInnerHTML; - executeCommand-selector: "#target"; - executeCommand-html: currentFormVar(single-select); -} - -#multiple-select:click { - action-server: submitMultiSelect; - submitMultiSelect-items: currentFormVar(multiple-select); -} Deleted: /kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/parameterfunction/kssid.pt ============================================================================== --- /kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/parameterfunction/kssid.pt Sun Jan 6 17:20:45 2008 +++ (empty file) @@ -1,224 +0,0 @@ - - - - - - - -

    Forms

    -

    We test the parameter functions related to forms : those functions - extract values from fields to use them in the kinetic stylesheet.

    -

    The inner HTML of the div below will be replaced with the - value of the form element.

    -
    Target
    - -

    - currentFormVar() with text field. -

    -
    - Click the text field. -
    -
    - -
    -

    - currentFormVar(name) with text field. -

    -
    - Click the button. -
    -
    -
    - Click me ! - -
    -
    -

    - currentFormVar(kssAttr('name')) with text field. -

    -
    - Click the button. -
    -
    -
    - Click me ! - -
    -
    - -

    - currentFormVar() with textarea field. -

    -
    - Click the textarea field. -
    -
    - -
    -

    - currentFormVar(name) with textarea field. -

    -
    - Click the button. -
    -
    -
    - Click me ! - -
    -
    -

    - currentFormVar() with radio field. -

    -
    - Click one of the radio buttons. -
    -
    radio-1 - - radio-2 - -
    -

    - currentFormVar(name) with radio field. -

    -
    - Click the button. -
    -
    - Click me ! - radio-1 - - radio-2 - -
    - -

    - currentFormVar(name) with select field. -

    -
    - Click the button. -
    -
    - Click me ! - -
    - -

    - currentFormVar(name) with multiple select field. -

    -
    - Click the button. -
    -
    - Click me ! - -
    - - -

    - form(full1) with simple field names, named form -

    -
    - Click the button. -
    - Click me ! -
    -
    -

    - currentForm() with simple field names -

    -
    - Click the button. -
    - Click me ! - - -
    -
    -

    - xxx-kssSubmitForm: form(full2) with complex field names, named form -

    -
    - Click the button. -
    - Click me ! -

    - xxx-kssSubmitForm: 'field2' with complex field names, named form, given as string -

    -
    - Click the button. -
    - Click me ! -
    -

    - xxx-kssSubmitForm: currentForm() with complex field names -

    -
    - Click the button. -
    - Click me ! -
    - value1: - - value2: - -
    - listval: - - -
    - recordval: - - -
    - recordsval: - - - - -
    -
    - - - - Copied: kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/parameterfunction/selenium_tests/kss_form_submit_multiprop.html (from r50326, kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/selenium_tests/pf_forms.html) ============================================================================== --- kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/selenium_tests/pf_forms.html (original) +++ kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/parameterfunction/selenium_tests/kss_form_submit_multiprop.html Sun Jan 6 17:20:45 2008 @@ -1,130 +1,45 @@ -pf_forms +kss_form_submit_multiprop - + - + - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - - - - - - - - + - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - + Copied: kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/parameterfunction/zopeconfig.py (from r50327, kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/zopeconfig.py) ============================================================================== --- kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/zopeconfig.py (original) +++ kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/parameterfunction/zopeconfig.py Sun Jan 6 17:20:45 2008 @@ -14,33 +14,12 @@ class IResource(IKSSDemoResource, IKSSSeleniumTestResource): pass -class KSSCoreDemos(object): +class ValueProviderDemos(object): implements(IResource) demos = ( - KSSDemo('', '', "basic_commands.html", "Change tag content"), - KSSDemo('', '', "two_selects.html", "Two selects"), - KSSDemo('', '', "autoupdate.html", "Auto update"), - KSSDemo('', '', "inline_edit.html", "Inline edit"), - KSSDemo('', '', "cancel_submit.html", "Cancel Submit Click"), - KSSDemo('', '', "tree.html", "Tree"), - KSSDemo('', '', "more_selectors.html", "More complex selectors"), - KSSDemo('', '', "two_select_revisited.html", "Master-slave selects revisited"), - KSSDemo('', '', "form_submit.html", "Form submit"), - KSSDemo('', '', "effects.html", "Effects"), - KSSDemo('', '', "error_handling.html", "Error handling"), - KSSDemo('', '', "preventdefault.html", "Preventdefault (a.k.a. Safari workarounds)"), - KSSDemo('', '', "html_inserts.html", "HTML insertions (Change tag content returns)"), - KSSDemo('', '', "client-server-protocol", "Client server protocol"), -## KSSDemo('', '', "draganddrop.html", "Scriptaculous drag and drop"), KSSDemo('', 'Value providers', 'pf_forms.html', 'Forms'), - KSSDemo('', 'Selectors', 'selectors.html', 'Parent node selector'), - KSSDemo('', 'Core syntax', "kss_selector_param.html", "Kss selector parameters"), - KSSDemo('', 'Core syntax', "kss_url_param.html", "Kss url parameters"), - KSSDemo('', 'Core events', "kss_evt_preventbubbling.html", "Prevent bubbling KSS event parameter"), - KSSDemo('', 'Core events', "kss_keyevents.html", "Key events"), - KSSDemo('', 'Commands/Actions', "ca_focus.html", "Focus"), - KSSDemo('', 'Commands/Actions', "actions.html", "Toggle case action"), + KSSDemo('', 'Value providers', 'kss_form_submit_multiprop.html', 'Form submit, with multiproperties'), ) # directories are relative from the location of this .py file Deleted: /kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/selenium_tests/kss_selector_param.html ============================================================================== --- /kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/selenium_tests/kss_selector_param.html Sun Jan 6 17:20:45 2008 +++ (empty file) @@ -1,109 +0,0 @@ - - - -kss_selector_param - - -
    pf_forms
    kss_form_submit_multiprop
    open/demo/pf_forms.html/demo/kss_form_submit_multiprop.html
    assertElementPresenttarget
    assertTexttargetTarget
    clicktextfullform-named
    waitForTexttargettext
    assertTexttargettext
    clicktext-by-name
    waitForTexttargettext-by-name
    assertTexttargettext-by-name
    clicktextarea
    waitForTexttargettextarea
    assertTexttargettextarea
    clicktextarea-by-namewaitForTextPresent[('listval', ['listval1', 'listval2']), ('multiple-select', ['Value 1', 'Value 3']), ('recordsval', [{'a': 'recordval_a_1', 'b': 'recordval_b_1'}, {'a': 'recordval_a_2', 'b': 'recordval_b_2'}]), ('recordval', {'a': 'recordval_a', 'b': 'recordval_b'}), ('value1', 'value1'), ('value2', 'value2')]
    waitForTexttargettextarea-by-name
    assertTexttargettextarea-by-name
    clickradio1link=Reset log
    waitForTexttargetradio-1
    assertTexttargetradio-1
    clickradio-by-namewaitForTextPresentTarget
    waitForTexttargetradio-2
    assertTexttargetradio-2
    click fullform-current
    waitForTexttarget[('listval', ['listval1', 'listval2']), ('multiple-select', ['Value 1', 'Value 3']), ('recordsval', [{'a': 'recordval_a_1', 'b': 'recordval_b_1'}, {'a': 'recordval_a_2', 'b': 'recordval_b_2'}]), ('recordval', {'a': 'recordval_a', 'b': 'recordval_b'}), ('value1', 'value1'), ('value2', 'value2')]
    verifyTextPresentwaitForTextPresent [('listval', ['listval1', 'listval2']), ('multiple-select', ['Value 1', 'Value 3']), ('recordsval', [{'a': 'recordval_a_1', 'b': 'recordval_b_1'}, {'a': 'recordval_a_2', 'b': 'recordval_b_2'}]), ('recordval', {'a': 'recordval_a', 'b': 'recordval_b'}), ('value1', 'value1'), ('value2', 'value2')]
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    kss_selector_param
    open/demo/kss_selector_param.html
    clickbutton_1
    waitForValuebutton_2RESET ME
    assertValuebutton_2RESET ME
    clickbutton_2
    waitForValuebutton_2Watch me
    assertValuebutton_2Watch me
    clickbutton_3
    waitForValuebutton_4RESET ME
    assertValuebutton_4RESET ME
    clickbutton_4
    waitForValuebutton_4Watch me
    assertValuebutton_4Watch me
    clickbutton_5
    waitForValuebutton_6RESET ME
    assertValuebutton_6RESET ME
    clickbutton_6
    waitForValuebutton_6Watch me
    assertValuebutton_6Watch me
    - - Deleted: /kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/selenium_tests/pf_forms.html ============================================================================== --- /kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/selenium_tests/pf_forms.html Sun Jan 6 17:20:45 2008 +++ (empty file) @@ -1,134 +0,0 @@ - - - -pf_forms - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    pf_forms
    open/demo/pf_forms.html
    assertElementPresenttarget
    assertTexttargetTarget
    clicktext
    waitForTexttargettext
    assertTexttargettext
    clicktext-by-name
    waitForTexttargettext-by-name
    assertTexttargettext-by-name
    clicktextarea
    waitForTexttargettextarea
    assertTexttargettextarea
    clicktextarea-by-name
    waitForTexttargettextarea-by-name
    assertTexttargettextarea-by-name
    clickradio1
    waitForTexttargetradio-1
    assertTexttargetradio-1
    clickradio-by-name
    waitForTexttargetradio-2
    assertTexttargetradio-2
    clickfullform-current
    waitForTexttarget[('listval', ['listval1', 'listval2']), ('multiple-select', ['Value 1', 'Value 3']), ('recordsval', [{'a': 'recordval_a_1', 'b': 'recordval_b_1'}, {'a': 'recordval_a_2', 'b': 'recordval_b_2'}]), ('recordval', {'a': 'recordval_a', 'b': 'recordval_b'}), ('value1', 'value1'), ('value2', 'value2')]
    verifyTextPresent[('listval', ['listval1', 'listval2']), ('multiple-select', ['Value 1', 'Value 3']), ('recordsval', [{'a': 'recordval_a_1', 'b': 'recordval_b_1'}, {'a': 'recordval_a_2', 'b': 'recordval_b_2'}]), ('recordval', {'a': 'recordval_a', 'b': 'recordval_b'}), ('value1', 'value1'), ('value2', 'value2')]
    - - Deleted: /kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/selenium_tests/urlparam.html ============================================================================== --- /kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/selenium_tests/urlparam.html Sun Jan 6 17:20:45 2008 +++ (empty file) @@ -1,69 +0,0 @@ - - - -urlparam - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    urlparam
    open/demo/kss_url_param.html
    assertElementPresenttarget
    clickbutton_1
    waitForTextPresentMethod 1 called
    assertTextPresentMethod 1 called
    clickbutton_2
    waitForTextPresentMethod 2 called
    assertTextPresentMethod 2 called
    clickbutton_3
    waitForTextPresentMethod 3 called
    assertTextPresentMethod 3 called
    - - Modified: kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/zopeconfig.py ============================================================================== --- kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/zopeconfig.py (original) +++ kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/zopeconfig.py Sun Jan 6 17:20:45 2008 @@ -33,10 +33,7 @@ KSSDemo('', '', "html_inserts.html", "HTML insertions (Change tag content returns)"), KSSDemo('', '', "client-server-protocol", "Client server protocol"), ## KSSDemo('', '', "draganddrop.html", "Scriptaculous drag and drop"), - KSSDemo('', 'Value providers', 'pf_forms.html', 'Forms'), KSSDemo('', 'Selectors', 'selectors.html', 'Parent node selector'), - KSSDemo('', 'Core syntax', "kss_selector_param.html", "Kss selector parameters"), - KSSDemo('', 'Core syntax', "kss_url_param.html", "Kss url parameters"), KSSDemo('', 'Core events', "kss_evt_preventbubbling.html", "Prevent bubbling KSS event parameter"), KSSDemo('', 'Core events', "kss_keyevents.html", "Key events"), KSSDemo('', 'Commands/Actions', "ca_focus.html", "Focus"), From reebalazs at codespeak.net Sun Jan 6 17:21:33 2008 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Sun, 6 Jan 2008 17:21:33 +0100 (CET) Subject: [KSS-checkins] r50406 - kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/coresyntax Message-ID: <20080106162133.DD64416847D@codespeak.net> Author: reebalazs Date: Sun Jan 6 17:21:33 2008 New Revision: 50406 Removed: kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/coresyntax/__init__.pyc kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/coresyntax/demoview.pyc Log: No idea why they dod not get ignored. Deleted: /kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/coresyntax/__init__.pyc ============================================================================== Binary file. No diff available. Deleted: /kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/coresyntax/demoview.pyc ============================================================================== Binary file. No diff available. From reebalazs at codespeak.net Mon Jan 7 00:17:45 2008 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Mon, 7 Jan 2008 00:17:45 +0100 (CET) Subject: [KSS-checkins] r50411 - in kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes: . kukit tests Message-ID: <20080106231745.7B4DD168459@codespeak.net> Author: reebalazs Date: Mon Jan 7 00:17:43 2008 New Revision: 50411 Modified: kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/ (props changed) kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/kssparser.js kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/providerreg.js kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/resourcedata.js kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/tests/test_kssparser.js Log: Adding client action aliasing Modified: kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/kssparser.js ============================================================================== --- kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/kssparser.js (original) +++ kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/kssparser.js Mon Jan 7 00:17:43 2008 @@ -236,9 +236,14 @@ // preprocess values var allowedReturnTypes; ;;; if (actionType == 'S') { +;;; // action-server ;;; allowedReturnTypes = {string: true, formdata: true, url: true}; +;;; } else if (actionType == 'C') { +;;; // action-client +;;; allowedReturnTypes = {string: true, selection: true, alias: true}; ;;; } else { -;;; allowedReturnTypes = {string: true, selection: true}; +;;; // action-cancel +;;; allowedReturnTypes = {string: true}; ;;; } ;;; kukit.E = 'action definition [' + key + ']'; var valuesByReturnType = this.preprocessValues(values, allowedReturnTypes, kukit.E); @@ -425,7 +430,6 @@ // noStringRequired is set to true at the kss special parameters. All other // occasions require at least a string to be present, so we check for that too. var valuesByReturnType = {}; - for (var i=0; i keys., at row 1, column 11'); }; @@ -1373,6 +1408,58 @@ this.assertEquals(parser.finished, true); }; + this.testAliasedClientAction = function() { + // Client action can be aliased. + // + // This test can only run in development mode, pass otherwise. + // Note that merging the rules is not really tested from here, + // as we don't have DOM. So we can't really see if the alias + // is working, only that it is parsed well. + if (! kukit.isDevelMode) {return;} + // + var txt= "#id:click {\n" + + " action-client: doIt alias(doAlias);\n" + + " doAlias-foo: bar;\n" + + "}\n" + var cursor = new kukit.tk.Cursor(txt); + var parser = new kukit.kssp.Document(cursor, null, true); + this.assertEquals(parser.finished, true); + }; + + this.testServerActionRejectsAlias = function() { + // Server action rejects alias(). + // + // This test can only run in development mode, pass otherwise. + if (! kukit.isDevelMode) {return;} + // + var txt= "#id:click {\n" + + " action-server: doIt alias(doAlias);\n" + + " doAlias-foo: bar;\n" + + "}\n" + var cursor = new kukit.tk.Cursor(txt); + this.assertParsingError(kukit.kssp.Document, cursor, null, true, + // XXX This error message will be fixed in service-layer branch + // XXX This will also fix running from IE, currently broken at error assert. + 'Provider result type [alias] not allowed in the action definition [action-server]., at row 1, column 11'); + }; + + this.testNormalParameterRejectsAlias = function() { + // normal parameters do not accept alias. + // + // This test can only run in development mode, pass otherwise. + if (! kukit.isDevelMode) {return;} + // + var txt= "#id:click {\n" + + " action-client: log;\n" + + " log-message: whatever alias('name');\n" + + "}\n" + var cursor = new kukit.tk.Cursor(txt); + this.assertParsingError(kukit.kssp.Document, cursor, null, true, + // XXX This error message will be fixed in service-layer branch + // XXX This will also fix running from IE, currently broken at error assert. + 'Provider result type [alias] not allowed in the action parameter [message]., at row 1, column 11'); + }; + }; kukit.KssParserValueProvidersCheckTestCase.prototype = new kukit.KssParserTestCaseBase; From reebalazs at codespeak.net Mon Jan 7 00:18:21 2008 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Mon, 7 Jan 2008 00:18:21 +0100 (CET) Subject: [KSS-checkins] r50412 - in kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/coresyntax: . selenium_tests Message-ID: <20080106231821.5D1B216844C@codespeak.net> Author: reebalazs Date: Mon Jan 7 00:18:15 2008 New Revision: 50412 Added: kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/coresyntax/kss_client_action_alias.kss kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/coresyntax/kss_client_action_alias.pt kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/coresyntax/selenium_tests/kss_client_action_alias.html Modified: kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/coresyntax/config.py kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/coresyntax/configure.zcml kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/coresyntax/zopeconfig.py Log: Adding demo and test for client action aliasing Modified: kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/coresyntax/config.py ============================================================================== --- kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/coresyntax/config.py (original) +++ kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/coresyntax/config.py Mon Jan 7 00:18:15 2008 @@ -13,6 +13,7 @@ KSSDemo('', 'Core syntax', "kss_selector_param_multiprop.html", "Kss selector parameters, with multiproperties"), KSSDemo('', 'Core syntax', "kss_url_param_multiprop.html", "Kss url parameters, with multiproperties"), KSSDemo('', 'Core syntax', "kss_providers_multiprop.html", "Kss providers, with multiproperties"), + KSSDemo('', 'Core syntax', "kss_client_action_alias.html", "Client action aliases"), ) # directories are relative from the location of this .py file Modified: kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/coresyntax/configure.zcml ============================================================================== --- kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/coresyntax/configure.zcml (original) +++ kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/coresyntax/configure.zcml Mon Jan 7 00:18:15 2008 @@ -109,6 +109,18 @@ name="kss_providers_multiprop.kss" /> + + + + Added: kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/coresyntax/kss_client_action_alias.kss ============================================================================== --- (empty file) +++ kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/coresyntax/kss_client_action_alias.kss Mon Jan 7 00:18:15 2008 @@ -0,0 +1,92 @@ + + +.clickable:click { + evt-click-preventdefault: true; +} + +#button_1:click { + action-client: setStyle htmlid(button_2); + setStyle-name: backgroundColor; + setStyle-value: #FFa0a0; + action-client: setAttribute htmlid(button_2); + setAttribute-name: value; + setAttribute-value: 'RESET ME'; + + action-client: setStyle htmlid(button_3) alias(setStyleRight); + setStyleRight-name: backgroundColor; + setStyleRight-value: #a0FFa0; + action-client: setAttribute htmlid(button_3) alias(setAttributeRight); + setAttributeRight-name: value; + setAttributeRight-value: 'RESET ME TOO'; +} + +/* Similar to the first case, but we check + * if aliased actions merge properly. + */ +#button_4:click { + action-client: setStyle htmlid(button_5); + setStyle-name: backgroundColor; + setStyle-value: #FFa0a0; + action-client: setAttribute htmlid(button_5); + setAttribute-name: value; + setAttribute-value: 'RESET ME'; + + action-client: setStyle htmlid(button_6) alias(setStyleRight); + setStyleRight-name: backgroundColor; + + action-client: setAttribute htmlid(button_6) alias(setAttributeRight); + setAttributeRight-name: value; +} +/* this will merge to the previous one. */ +#button_4:click { + setStyleRight-value: #a0FFa0; + setAttributeRight-value: 'RESET ME TOO'; +} + + +/* Similar to the first case, but we check + * if aliased actions merge properly. + * We override the action completely. + */ +#button_7:click { + action-client: setStyle htmlid(button_8); + setStyle-name: backgroundColor; + setStyle-value: #FFa0a0; + action-client: setAttribute htmlid(button_8); + setAttribute-name: value; + setAttribute-value: 'RESET ME'; + + action-client: setStyle htmlid(button_6) alias(setStyleRight); + setStyleRight-name: backgroundColor; + + action-client: setAttribute htmlid(button_6) alias(setAttributeRight); + setAttributeRight-name: value; +} +/* this will merge to the previous one. This will act on button_9 + * and _not_ on button_6 as the previous + * rule would have specified. + * + * Note that overriding the action _name_ is not allowed but we + * cannot test this here, because it would give parsing error.*/ +#button_7:click { + action-client: setStyle htmlid(button_9) alias(setStyleRight); + setStyleRight-value: #a0FFa0; + + action-client: setAttribute htmlid(button_9) alias(setAttributeRight); + setAttributeRight-value: 'RESET ME TOO'; +} + + + +/* Resetting the buttons */ +#button_2:click, #button_3:click, +#button_5:click, #button_6:click, +#button_8:click, #button_9:click { + action-client: setStyle; + setStyle-name: backgroundColor; + setStyle-value: white; + action-client: setAttribute; + setAttribute-name: value; + setAttribute-value: 'Watch me'; +} + Added: kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/coresyntax/kss_client_action_alias.pt ============================================================================== --- (empty file) +++ kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/coresyntax/kss_client_action_alias.pt Mon Jan 7 00:18:15 2008 @@ -0,0 +1,84 @@ + + + + + + + + + + +

    header

    + +

    Kss client action aliasing demo

    +
    +

    There are three buttons. If you click on the first button, it changes the + text (and style) of the + second and third button. Since we have the same action twice, they would merge if we + had not used aliases. + Look at the link on the kss file to understand. +

    + +

    +
    action-client: setAttribute htmlid(button_2);
    +setAttribute-name: value;
    +setAttribute-value: 'RESET ME';
    +
    +action-client: setAttribute htmlid(button_3) alias(setAttributeRight);
    +setAttributeRight-name: value;
    +setAttributeRight-value: 'RESET ME TOO';
    +

    +
    + Click the button here. +
    + +
    + + + +
    + +

    + Check if aliased rules can merge. Click on the kss link above + to understand more. +

    +
    + Click the button here. +
    + +
    + + + +
    + + +

    + Check if aliased rules can merge. This will act on the second + and third button, and we need to check that the third + button in the row above (button_6) did not change. +

    +
    + Click the button here. +
    + +
    + + + +
    + + +
    + + + Added: kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/coresyntax/selenium_tests/kss_client_action_alias.html ============================================================================== --- (empty file) +++ kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/coresyntax/selenium_tests/kss_client_action_alias.html Mon Jan 7 00:18:15 2008 @@ -0,0 +1,129 @@ + + + +kss_client_action_alias + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    kss_client_action_alias
    open/demo/kss_client_action_alias.html
    clickbutton_1
    waitForValuebutton_2RESET ME
    verifyValuebutton_3RESET ME TOO
    clickbutton_2
    waitForValuebutton_2Watch me
    clickbutton_3
    waitForValuebutton_3Watch me
    clickbutton_4
    waitForValuebutton_5RESET ME
    verifyValuebutton_6RESET ME TOO
    clickbutton_5
    waitForValuebutton_5Watch me
    clickbutton_6
    waitForValuebutton_6Watch me
    clickbutton_7
    waitForValuebutton_8RESET ME
    verifyValuebutton_9RESET ME TOO
    verifyValuebutton_6Watch me
    clickbutton_8
    waitForValuebutton_8Watch me
    clickbutton_9
    waitForValuebutton_9Watch me
    + + Modified: kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/coresyntax/zopeconfig.py ============================================================================== --- kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/coresyntax/zopeconfig.py (original) +++ kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/coresyntax/zopeconfig.py Mon Jan 7 00:18:15 2008 @@ -23,6 +23,7 @@ KSSDemo('', 'Core syntax', "kss_selector_param_multiprop.html", "Kss selector parameters, with multiproperties"), KSSDemo('', 'Core syntax', "kss_url_param_multiprop.html", "Kss url parameters, with multiproperties"), KSSDemo('', 'Core syntax', "kss_providers_multiprop.html", "Kss providers, with multiproperties"), + KSSDemo('', 'Core syntax', "kss_client_action_alias.html", "Client action aliases"), ) # directories are relative from the location of this .py file From reebalazs at codespeak.net Mon Jan 7 08:04:04 2008 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Mon, 7 Jan 2008 08:04:04 +0100 (CET) Subject: [KSS-checkins] r50414 - kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/markup Message-ID: <20080107070404.3020916844C@codespeak.net> Author: reebalazs Date: Mon Jan 7 08:04:01 2008 New Revision: 50414 Modified: kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/markup/markup.kss kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/markup/markup.pt Log: Rename kssWidget -> kssMarkedNode Modified: kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/markup/markup.kss ============================================================================== --- kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/markup/markup.kss (original) +++ kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/markup/markup.kss Mon Jan 7 08:04:01 2008 @@ -37,7 +37,7 @@ #button7:click { replaceInnerHTML-html: "Executed, look at button's text."; action-client: insertHTMLAsFirstChild; - insertHTMLAsFirstChild-kssSelector: kssWidget(attr, key); + insertHTMLAsFirstChild-kssSelector: kssMarkedNode(attr, key); insertHTMLAsFirstChild-html: 'Selector succeeded'; } Modified: kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/markup/markup.pt ============================================================================== --- kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/markup/markup.pt (original) +++ kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/markup/markup.pt Mon Jan 7 08:04:01 2008 @@ -62,7 +62,7 @@

    -

    xxx-kssSelector: kssWidget(attr, key); encoding in class

    +

    xxx-kssSelector: kssMarkedNode(attr, key); encoding in class

    From reebalazs at codespeak.net Mon Jan 7 08:08:06 2008 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Mon, 7 Jan 2008 08:08:06 +0100 (CET) Subject: [KSS-checkins] r50415 - in kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes: . kukit Message-ID: <20080107070806.AA28216844C@codespeak.net> Author: reebalazs Date: Mon Jan 7 08:08:00 2008 New Revision: 50415 Modified: kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/ (props changed) kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/selectorreg.js Log: Rename kssWidget -> kssMarkedNode Modified: kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/selectorreg.js ============================================================================== --- kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/selectorreg.js (original) +++ kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/selectorreg.js Mon Jan 7 08:08:00 2008 @@ -162,32 +162,32 @@ return results; }); -kukit.sr.KssWidgetPP = function() {}; -kukit.sr.KssWidgetPP.prototype = { - check: function(args) { +kukit.sr.KssMarkedNodePP = function() { + this.check = function(args){ ;;; if (args.length != 2) { -;;; throw new Error('kssWidget selector method needs 2 arguments'); +;;; throw new Error('kssMarkedNode selector method needs 2 arguments (keyType, key)'); ;;; } - }, - eval: function(args, node, defaultParameters) { - var keytype = args[0]; + }; + this.eval = function(args, node, defaultParameters) { + var keyType = args[0]; var key = args[1]; -;;; if (keytype.match(/[ -]/)) { -;;; kukit.E = 'keytype parameter in kssIdOfValue provider cannot contain'; +;;; if (keyType.match(/[ -]/)) { +;;; kukit.E = 'keyType parameter in kssMarkedNode selection provider cannot contain'; ;;; kukit.E += ' dashes or spaces.'; ;;; throw new Error(kukit.E); ;;; } ;;; if (key.match(/[ -]/)) { -;;; kukit.E = 'key parameter in kssIdOfValue provider cannot contain'; +;;; kukit.E = 'key parameter in kssMarkedNode provider cannot contain'; ;;; kukit.E += ' dashes or spaces.'; ;;; throw new Error(kukit.E); ;;; } var markup = kukit.dom.locateMarkup(node, true, kukit.dom.getKssValue, - keytype, key); - // Just return the markup's node as a single result. + keyType, key); + // Just return the markup's node as a single selection result. return [markup.node]; - } + }; }; -kukit.pprovidersGlobalRegistry.register('kssWidget', kukit.sr.KssWidgetPP, 'selection'); +// returnTyoe is 'selection'. +kukit.pprovidersGlobalRegistry.register('kssMarkedNode', kukit.sr.KssMarkedNodePP, 'selection'); From reebalazs at codespeak.net Mon Jan 7 08:38:04 2008 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Mon, 7 Jan 2008 08:38:04 +0100 (CET) Subject: [KSS-checkins] r50416 - in kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/markup: . selenium_tests Message-ID: <20080107073804.5265F168449@codespeak.net> Author: reebalazs Date: Mon Jan 7 08:38:03 2008 New Revision: 50416 Modified: kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/markup/markup.kss kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/markup/markup.pt kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/markup/selenium_tests/markup.html Log: Adding more cases to markup demo Modified: kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/markup/markup.kss ============================================================================== --- kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/markup/markup.kss (original) +++ kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/markup/markup.kss Mon Jan 7 08:38:03 2008 @@ -30,6 +30,13 @@ replaceInnerHTML-html: kssValue(mymarkup, key, false); } +/* for button5 we give an additional text next to the button, + * for testability */ +#button5:click { + action-client: insertHTMLBefore; + insertHTMLBefore-html: 'Event succeeded'; +} + #button6:click { replaceInnerHTML-html: kssIdOfValue(attr, key); } @@ -41,3 +48,9 @@ insertHTMLAsFirstChild-html: 'Selector succeeded'; } +/* these are equivalent to kssIdOfValue */ +#button8:click, #button9:click { + replaceInnerHTML-html: kssMarkedNode(attr, key) nodeAttr(id); +} + + Modified: kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/markup/markup.pt ============================================================================== --- kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/markup/markup.pt (original) +++ kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/markup/markup.pt Mon Jan 7 08:38:03 2008 @@ -57,17 +57,31 @@

    kssIdOfValue(attr, key) encoding in class

    -
    +

    xxx-kssSelector: kssMarkedNode(attr, key); encoding in class

    -
    +
    +
    +

    replaceInnerHTML-html: kssMarkedNode(attr, key) nodeAttr(id); encoding in class

    + +
    + +
    + +
    +

    replaceInnerHTML-html: kssMarkedNode(attr, key) nodeAttr(id); encoding in XHTML

    + +
    + +
    +
    Modified: kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/markup/selenium_tests/markup.html ============================================================================== --- kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/markup/selenium_tests/markup.html (original) +++ kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/markup/selenium_tests/markup.html Mon Jan 7 08:38:03 2008 @@ -59,8 +59,13 @@ - waitForTextPresent + verifyTextPresent + Event succeeded + + + verifyText + logger @@ -78,6 +83,26 @@ Selector succeeded + + click + button8 + + + + waitForTextPresent + value8 + + + + click + button9 + + + + waitForTextPresent + value9 + + From reebalazs at codespeak.net Mon Jan 7 09:06:44 2008 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Mon, 7 Jan 2008 09:06:44 +0100 (CET) Subject: [KSS-checkins] r50417 - kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/markup/selenium_tests Message-ID: <20080107080644.35FAB168449@codespeak.net> Author: reebalazs Date: Mon Jan 7 09:06:42 2008 New Revision: 50417 Modified: kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/markup/selenium_tests/markup.html Log: Fix markup test for IE (explanation: we check that the kssValue does not recurse if recursion=false. So the provider returns null. We insert this into the logger, but FF inserts while IE inserts null so we need to check the value with a regexp.) Modified: kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/markup/selenium_tests/markup.html ============================================================================== --- kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/markup/selenium_tests/markup.html (original) +++ kukit/kss.core/branch/ree-1.4-markup-and-syntax-changes/kss/core/plugins/core/demo/markup/selenium_tests/markup.html Mon Jan 7 09:06:42 2008 @@ -63,10 +63,11 @@ Event succeeded + verifyText logger - + regexp:(null)? click From reebalazs at codespeak.net Mon Jan 7 09:26:08 2008 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Mon, 7 Jan 2008 09:26:08 +0100 (CET) Subject: [KSS-checkins] r50418 - in kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes: . kukit Message-ID: <20080107082608.E394F168487@codespeak.net> Author: reebalazs Date: Mon Jan 7 09:26:08 2008 New Revision: 50418 Modified: kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/ (props changed) kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/providerreg.js Log: Add future BBB to kssAttr - currently inactive. Modified: kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/providerreg.js ============================================================================== --- kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/providerreg.js (original) +++ kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/providerreg.js Mon Jan 7 09:26:08 2008 @@ -201,6 +201,18 @@ kukit.pr.KssAttrPP = function() {}; kukit.pr.KssAttrPP.prototype = { check: function(args) { +;;; // Uncomment next part to activate BBB: +;;; //kukit.E = 'kssAttr is deprecated and will be removed at '; +;;; //kukit.E += '2008-XX-XX'; +;;; //kukit.E += ', use kssValue. Change your html '; +;;; //kukit.E += 'class markup from kssattr-key-value to '; +;;; //kukit.E += 'kss-attr-key-value, '; +;;; //kukit.E += 'and change the provider from kssAttr(key, true) to '; +;;; //kukit.E += 'kssValue(attr, key). Note that kssValue has a third '; +;;; //kukit.E += 'parameter to enable/disable recursion, but in contrary '; +;;; //kukit.E += 'to kssAttr, kssValue has recursion by default enabled '; +;;; //kukit.E += '(true).'; +;;; //kukit.logWarning(kukit.E); ;;; if (args.length != 1 && args.length != 2) { ;;; kukit.E = 'kssAttr method needs 1 or 2 argument (attrname,'; ;;; kukit.E += ' [recurseParents]).'; From reebalazs at codespeak.net Mon Jan 7 10:59:10 2008 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Mon, 7 Jan 2008 10:59:10 +0100 (CET) Subject: [KSS-checkins] r50419 - in kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes: . kukit Message-ID: <20080107095910.99A3116844D@codespeak.net> Author: reebalazs Date: Mon Jan 7 10:59:08 2008 New Revision: 50419 Modified: kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/ (props changed) kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/forms.js Log: Fix getValueOfFormElement on Safari 3.0.3 this fixes formVar() on radio buttons, in this browser reason why this is needed, is probably some change in the dom api). Modified: kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/forms.js ============================================================================== --- kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/forms.js (original) +++ kukit/kukit.js/branch/ree-1.4-markup-and-syntax-changes/kukit/forms.js Mon Jan 7 10:59:08 2008 @@ -195,13 +195,21 @@ } } } + // Safari 3.0.3 no longer has "item", instead it works + // with direct array access []. Although other browsers + // seem to support this as well, we provide checking + // in both ways. (No idea if item is still needed.) } else if (typeof element.length != 'undefined' && - typeof element.item != 'undefined' && - element.item(0).type == "radio") { + ((typeof element[0] != 'undefined' && + element[0].type == "radio") || + (typeof element.item(0) != 'undefined' && + element.item(0).type == "radio"))) { + // element really contains a list of input nodes, + // in this case. var radioList = element; value = null; for (var i=0; i < radioList.length; i++) { - var radio = radioList.item(i); + var radio = radioList[i] || radioList.item(i); if (radio.checked) { value = radio.value; } @@ -230,6 +238,8 @@ // Extract the value of a formvar var value = null; var element = form[name]; + // (in case of a radio button this will give a collection + // that contains the list of input nodes.) if (element) { var value = fo.getValueOfFormElement(element); ;;; if (value != null) { From reebalazs at codespeak.net Tue Jan 8 15:25:59 2008 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Tue, 8 Jan 2008 15:25:59 +0100 (CET) Subject: [KSS-checkins] r50444 - in kukit/kukit.js/branch/ree-service-layer-and-refactoring: . kukit tests Message-ID: <20080108142559.A77AE168404@codespeak.net> Author: reebalazs Date: Tue Jan 8 15:25:58 2008 New Revision: 50444 Modified: kukit/kukit.js/branch/ree-service-layer-and-refactoring/ (props changed) kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/eventreg.js kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/interfaces.js kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/plugin.js kukit/kukit.js/branch/ree-service-layer-and-refactoring/tests/test_interfaces.js Log: Add kukit.interfaces.registerPlugin method, that can be used for batch registering plugin information. Since we only register data, we can parse the entire registry from the server by a simple markup and json. Modified: kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/eventreg.js ============================================================================== --- kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/eventreg.js (original) +++ kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/eventreg.js Tue Jan 8 15:25:58 2008 @@ -76,7 +76,6 @@ // register the event informataion var events = kukit.interfaces.global.schema.events; events.getAttribute(eventName).register({ - eventName: eventName, defaultActionMethodName: defaultActionMethodName, parmTypes: null // missing from this api. }); Modified: kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/interfaces.js ============================================================================== --- kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/interfaces.js (original) +++ kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/interfaces.js Tue Jan 8 15:25:58 2008 @@ -548,4 +548,69 @@ // The finalization of these interfaces will be done from bootstrap. + + +/* + * Plugin registration method + * + * To allow an easy way to register plugin interfaces, a + * simple method is provided. + * + * This appends a batch of information into the plugin + * registry. + * + * It is intended to be the new method for registering + * plugins. It also fulfills the need that we will + * be able to parse the actual information from the + * javascript files, and access the complete plugin + * registry, from the server side. + * + */ + +this.registerPlugins = function(items, interfaces) { + // interfaces is optional, and mainly used for tests + if (typeof(interfaces) == 'undefined') { + // use global interfaces + interfaces = this.global; + } + // + for (var i=0; i Author: gotcha Date: Thu Jan 10 13:54:10 2008 New Revision: 50487 Added: kukit/kss.core/trunk/kss/core/plugins/core/demo/binderclasses/ - copied from r50485, kukit/kss.core/branch/finish-closures/kss/core/plugins/core/demo/binderclasses/ kukit/kss.core/trunk/kss/core/plugins/core/demo/binderclasses/README - copied unchanged from r50485, kukit/kss.core/branch/finish-closures/kss/core/plugins/core/demo/binderclasses/README kukit/kss.core/trunk/kss/core/plugins/core/demo/binderclasses/__init__.py - copied unchanged from r50485, kukit/kss.core/branch/finish-closures/kss/core/plugins/core/demo/binderclasses/__init__.py kukit/kss.core/trunk/kss/core/plugins/core/demo/binderclasses/configure.zcml - copied unchanged from r50485, kukit/kss.core/branch/finish-closures/kss/core/plugins/core/demo/binderclasses/configure.zcml kukit/kss.core/trunk/kss/core/plugins/core/demo/binderclasses/kss_binder_classes.js - copied unchanged from r50485, kukit/kss.core/branch/finish-closures/kss/core/plugins/core/demo/binderclasses/kss_binder_classes.js kukit/kss.core/trunk/kss/core/plugins/core/demo/binderclasses/kss_binder_classes.kss - copied unchanged from r50485, kukit/kss.core/branch/finish-closures/kss/core/plugins/core/demo/binderclasses/kss_binder_classes.kss kukit/kss.core/trunk/kss/core/plugins/core/demo/binderclasses/kss_binder_classes.pt - copied unchanged from r50485, kukit/kss.core/branch/finish-closures/kss/core/plugins/core/demo/binderclasses/kss_binder_classes.pt kukit/kss.core/trunk/kss/core/plugins/core/demo/binderclasses/selenium_tests/ - copied from r50485, kukit/kss.core/branch/finish-closures/kss/core/plugins/core/demo/binderclasses/selenium_tests/ kukit/kss.core/trunk/kss/core/plugins/core/demo/binderclasses/selenium_tests/README.txt - copied unchanged from r50485, kukit/kss.core/branch/finish-closures/kss/core/plugins/core/demo/binderclasses/selenium_tests/README.txt kukit/kss.core/trunk/kss/core/plugins/core/demo/binderclasses/selenium_tests/binderclasses.html - copied unchanged from r50485, kukit/kss.core/branch/finish-closures/kss/core/plugins/core/demo/binderclasses/selenium_tests/binderclasses.html kukit/kss.core/trunk/kss/core/plugins/core/demo/binderclasses/zopeconfig.py - copied unchanged from r50485, kukit/kss.core/branch/finish-closures/kss/core/plugins/core/demo/binderclasses/zopeconfig.py kukit/kss.core/trunk/kss/core/plugins/core/demo/binderids/selenium_tests/binderids.html - copied unchanged from r50485, kukit/kss.core/branch/finish-closures/kss/core/plugins/core/demo/binderids/selenium_tests/binderids.html kukit/kss.core/trunk/kss/core/plugins/core/demo/selenium_tests/0_ecmaunit_tests.html - copied unchanged from r50485, kukit/kss.core/branch/finish-closures/kss/core/plugins/core/demo/selenium_tests/0_ecmaunit_tests.html Removed: kukit/kss.core/trunk/kss/core/docs/ Modified: kukit/kss.core/trunk/docs/HISTORY.txt kukit/kss.core/trunk/kss/core/pluginregistry/browser/develui.css kukit/kss.core/trunk/kss/core/plugins/core/demo/binderids/binderids.kss kukit/kss.core/trunk/kss/core/plugins/core/demo/binderids/binderids.pt kukit/kss.core/trunk/kss/core/plugins/core/demo/configure.zcml kukit/kss.core/trunk/kss/core/plugins/core/demo/coreplugin/kss_evt_preventbubbling.kss kukit/kss.core/trunk/kss/core/plugins/core/demo/coreplugin/kss_evt_preventbubbling.pt kukit/kss.core/trunk/kss/core/plugins/core/demo/error_handling.kss kukit/kss.core/trunk/kss/core/plugins/core/demo/error_handling.pt kukit/kss.core/trunk/kss/core/plugins/core/demo/more_selectors.js kukit/kss.core/trunk/kss/core/plugins/core/demo/more_selectors.kss kukit/kss.core/trunk/kss/core/plugins/core/demo/more_selectors.pt kukit/kss.core/trunk/kss/core/plugins/core/demo/parameterfunction/forms.kss kukit/kss.core/trunk/kss/core/plugins/core/demo/selenium_tests/error_handling.html kukit/kss.core/trunk/kss/core/plugins/core/demo/selenium_tests/html_inserts.html kukit/kss.core/trunk/kss/core/plugins/core/demo/selenium_tests/more_selectors.html Log: merge finish-closures branch; see HISTORY.txt for details Modified: kukit/kss.core/trunk/docs/HISTORY.txt ============================================================================== --- kukit/kss.core/trunk/docs/HISTORY.txt (original) +++ kukit/kss.core/trunk/docs/HISTORY.txt Thu Jan 10 13:54:10 2008 @@ -6,6 +6,24 @@ - ... + - Change develui.css to have its style inline with + kssproject.org. + [gotcha] + + - Add some tests for binder classes. + [ree] + + - Improve some of the demos to make them Selenium testable + under both dev and prod mode, fix their tests. + [gotcha] + + - Use functions in token table instead of code strings + that were evaluated. 'eval' is very slow. + in kukit.js [gotcha] + + - Refactor code towards module and class closures. + in kukit.js [gotcha] + - Fix multiple selection form fields marshalling on Safari (fixes #22 in kssproject) Modified: kukit/kss.core/trunk/kss/core/pluginregistry/browser/develui.css ============================================================================== --- kukit/kss.core/trunk/kss/core/pluginregistry/browser/develui.css (original) +++ kukit/kss.core/trunk/kss/core/pluginregistry/browser/develui.css Thu Jan 10 13:54:10 2008 @@ -1,6 +1,30 @@ +html { + background-color: white; +} + body { font-family: Verdana, Arial, sans-serif; font-size: 11pt; + background-color: #FAFAED; + border: 1px solid #A8A890; + padding: 1em; + margin: 3em; +} + +h1, h2, h3, h4, h5, a { + color: #FF4916; +} + +h1, h2, h3, h4, h5 { + border-bottom: 1px solid #A8A890; +} + +h1 { + font-size: 130%; +} + +h2 { + font-size: 120%; } h3 { @@ -14,7 +38,7 @@ font-size: 80%; } -#global-links ul { +#global-links ul, #log-reset { display: table-row; } @@ -22,50 +46,54 @@ display: table-cell; } -#global-links a { +#global-links a, #log-reset a { display: block; padding: 0.25em; margin: 0.25em; - border: 1px solid #FF8888; - color: #CC0000; + border: 1px solid #FF4916; + color: #FF4916; text-decoration: none; } #global-links a:hover { - border-color: #FF0000; - background-color: #FFCCCC; + border-color: #FF4916; + background-color: #FF4916; + color: white; } #target { padding: 1em; margin: 0.5em 0; - border: 1px solid #CCCCCC; - background-color: #EEEEEE; + border: 1px solid #A8A890; + background-color: #D8D8C0; } .cursorPointer { cursor: pointer; } -.click { - color: #880000; +code, .click { + color: #FF4916; } radio.click { - background-color: #880000; + background-color: #FF4916; } a.button, .clickable { width: auto; padding: 0.2em; - border: 1px solid #FF8888; - color: #CC0000; + border: 1px solid #FF4916; + color: #FF4916; text-decoration: none; font-size: 80%; + background-color: #FAFAED; } fieldset { margin: 0.5em 0; + border: 2px solid #A8A890; + background-color: white; } fieldset div { @@ -74,13 +102,13 @@ .help { font-size: 80%; - color: #AAAAAA; + color: #A8A890; } -.help pre { +pre { color: black; - border: 1px solid #CCCCCC; - background-color: #EEEEEE; + border: 1px solid #A8A890; + background-color: #D8D8C0; padding: 0.5em; margin: 0.25em; } @@ -89,6 +117,14 @@ padding : 1em; } +.log { + margin: 0; + padding: 0.4em; + background: #A8A890; + color: white; + font-style: italic; +} + .production, .error { color: red; } Modified: kukit/kss.core/trunk/kss/core/plugins/core/demo/binderids/binderids.kss ============================================================================== --- kukit/kss.core/trunk/kss/core/plugins/core/demo/binderids/binderids.kss (original) +++ kukit/kss.core/trunk/kss/core/plugins/core/demo/binderids/binderids.kss Thu Jan 10 13:54:10 2008 @@ -4,17 +4,20 @@ */ .buttons:click(manual) { - action-client: alert; - alert-message: "manual"; + action-client: insertHTMLAsLastChild; + insertHTMLAsLastChild-kssSelector: #logger; + insertHTMLAsLastChild-html: "manual"; } #button1:click(manual2) { - action-client: alert; - alert-message: "manual2"; + action-client: insertHTMLAsLastChild; + insertHTMLAsLastChild-kssSelector: #logger; + insertHTMLAsLastChild-html: "manual2"; } .buttons.bindable_by_parm:click(kssAttr(binderid)) { - action-client: alert; - alert-message: kssAttr(binderid); + action-client: insertHTMLAsLastChild; + insertHTMLAsLastChild-kssSelector: #logger; + insertHTMLAsLastChild-html: kssAttr(binderid); } Modified: kukit/kss.core/trunk/kss/core/plugins/core/demo/binderids/binderids.pt ============================================================================== --- kukit/kss.core/trunk/kss/core/plugins/core/demo/binderids/binderids.pt (original) +++ kukit/kss.core/trunk/kss/core/plugins/core/demo/binderids/binderids.pt Thu Jan 10 13:54:10 2008 @@ -12,8 +12,8 @@ Events bound to different binders will not merge. (Note that this is not the typical usage if event ids, only a simple check that it really works. - )If you click the buttons, you need to - receive alerts per each event bound. + )If you click the buttons, you must + receive logs per each event bound.


    @@ -28,6 +28,10 @@ value="button3">
    + +
    + +

    logger

    First we bind an event with id "manual" to each button. We also bind event with id "manual2" to the first button. Then Modified: kukit/kss.core/trunk/kss/core/plugins/core/demo/configure.zcml ============================================================================== --- kukit/kss.core/trunk/kss/core/plugins/core/demo/configure.zcml (original) +++ kukit/kss.core/trunk/kss/core/plugins/core/demo/configure.zcml Thu Jan 10 13:54:10 2008 @@ -15,6 +15,7 @@ + - - Modified: kukit/kss.demo/trunk/kss/demo/browser/kss_demo_index.pt ============================================================================== --- kukit/kss.demo/trunk/kss/demo/browser/kss_demo_index.pt (original) +++ kukit/kss.demo/trunk/kss/demo/browser/kss_demo_index.pt Thu Jan 10 13:54:45 2008 @@ -1,8 +1,6 @@ - Modified: kukit/kss.demo/trunk/kss/demo/browser/registry.py ============================================================================== --- kukit/kss.demo/trunk/kss/demo/browser/registry.py (original) +++ kukit/kss.demo/trunk/kss/demo/browser/registry.py Thu Jan 10 13:54:45 2008 @@ -64,6 +64,12 @@ elif filename.lower().endswith('.htm'): filename = filename[:-4] words = os.path.basename(filename).split('_') + # if the first word is a number: it is ignored in the title + # This can be used to somelimited ordering, since filenames + # are listed in alphabetical order, ie. 00_xxx.html will come first. + if not words[0] or '0' <= words[0][0] <= '9': + words = words[1:] + # Compile the result. result = ' '.join([word.capitalize() for word in words]) return result Modified: kukit/kss.demo/trunk/kss/demo/registry.py ============================================================================== --- kukit/kss.demo/trunk/kss/demo/registry.py (original) +++ kukit/kss.demo/trunk/kss/demo/registry.py Thu Jan 10 13:54:45 2008 @@ -140,7 +140,8 @@ def registerSeleniumTestsFromPlugin(self, plugin, registration=None, event=None, new_event=None): """Add a demo collection to the registry. """ - for test_filename in self._getSeleniumTestsFromPlugin(plugin): + test_filenames = self._getSeleniumTestsFromPlugin(plugin) + for test_filename in test_filenames: self.registerSeleniumTestFile(test_filename) @adapter(IKSSSeleniumTestResource, IUtilityRegistration, IUnregistered, IKSSDemoRegistrationEvent) Modified: kukit/kss.demo/trunk/kss/demo/selenium_utils/builder.py ============================================================================== --- kukit/kss.demo/trunk/kss/demo/selenium_utils/builder.py (original) +++ kukit/kss.demo/trunk/kss/demo/selenium_utils/builder.py Thu Jan 10 13:54:45 2008 @@ -1,4 +1,3 @@ - import sys, os, re, textwrap from elementtree import HTMLTreeBuilder from string import Template @@ -31,7 +30,11 @@ for test_filename in os.listdir(tests_root_dir): if test_filename.lower().endswith('.html') or \ test_filename.endswith('.htm'): - test_filenames.append(os.path.join(tests_root_dir, test_filename)) + test_filenames.append((test_filename, os.path.join(tests_root_dir, test_filename))) + # sort the testfilenames + test_filenames.sort() + # return only the absolute filenames + test_filenames = [filename[1] for filename in test_filenames] return test_filenames template = Template(textwrap.dedent('''\ Modified: kukit/kss.demo/trunk/setup.py ============================================================================== --- kukit/kss.demo/trunk/setup.py (original) +++ kukit/kss.demo/trunk/setup.py Thu Jan 10 13:54:45 2008 @@ -26,6 +26,7 @@ zip_safe=False, install_requires=[ # -*- Extra requirements: -*- + 'setuptools', 'kss.core>=dev', ], entry_points=""" From gotcha at codespeak.net Thu Jan 10 13:53:51 2008 From: gotcha at codespeak.net (gotcha at codespeak.net) Date: Thu, 10 Jan 2008 13:53:51 +0100 (CET) Subject: [KSS-checkins] r50486 - in kukit/kukit.js/trunk: doc kukit tests Message-ID: <20080110125351.0D2B5168508@codespeak.net> Author: gotcha Date: Thu Jan 10 13:53:49 2008 New Revision: 50486 Modified: kukit/kukit.js/trunk/doc/HISTORY.txt kukit/kukit.js/trunk/kukit/actionreg.js kukit/kukit.js/trunk/kukit/commandprocessor.js kukit/kukit.js/trunk/kukit/commandreg.js kukit/kukit.js/trunk/kukit/dom.js kukit/kukit.js/trunk/kukit/errors.js kukit/kukit.js/trunk/kukit/eventreg.js kukit/kukit.js/trunk/kukit/forms.js kukit/kukit.js/trunk/kukit/kssparser.js kukit/kukit.js/trunk/kukit/kukit.js kukit/kukit.js/trunk/kukit/oper.js kukit/kukit.js/trunk/kukit/plugin.js kukit/kukit.js/trunk/kukit/providerreg.js kukit/kukit.js/trunk/kukit/requestmanager.js kukit/kukit.js/trunk/kukit/resourcedata.js kukit/kukit.js/trunk/kukit/selectorreg.js kukit/kukit.js/trunk/kukit/serveraction.js kukit/kukit.js/trunk/kukit/tokenizer.js kukit/kukit.js/trunk/kukit/utils.js kukit/kukit.js/trunk/tests/test_requestmanager.js kukit/kukit.js/trunk/tests/test_tokenizer.js kukit/kukit.js/trunk/tests/unittestUtilities.js Log: merge finish-closures branch; see HISTORY.txt for details Modified: kukit/kukit.js/trunk/doc/HISTORY.txt ============================================================================== --- kukit/kukit.js/trunk/doc/HISTORY.txt (original) +++ kukit/kukit.js/trunk/doc/HISTORY.txt Thu Jan 10 13:53:49 2008 @@ -3,13 +3,18 @@ (name of developer listed in brackets) kukit.js - 1.4dev Unreleased - + - ... - - Fix multiple selection form fields - marshalling on Safari - (fixes #22 in kssproject) - and on IE. + - Use functions in token table instead of code strings + that were evaluated. 'eval' is very slow. + [gotcha] + + - Refactor code towards module and class closures. + [gotcha] + + - Fix multiple selection form fields marshalling on Safari + (fixes #22 in kssproject) and on IE. [ree] - Fix error fallback handling Modified: kukit/kukit.js/trunk/kukit/actionreg.js ============================================================================== --- kukit/kukit.js/trunk/kukit/actionreg.js (original) +++ kukit/kukit.js/trunk/kukit/actionreg.js Thu Jan 10 13:53:49 2008 @@ -22,53 +22,58 @@ var ar = this; /* -* class ActionRegistry +* class actionregistry * -* The local event actions need to be registered here. +* the local event actions need to be registered here. */ -var ActionRegistry = function () { +var _ActionRegistry = function () { +this.initialize = function() { this.content = {}; }; -ActionRegistry.prototype.register = function(name, func) { -;;;if (typeof(func) == 'undefined') { -;;; kukit.E = '[func] argument is mandatory when registering an action'; -;;; kukit.E += ' [ActionRegistry.register].'; -;;; throw new Error(kukit.E); -;;;} +this.register = function(name, func) { +;;; if (typeof(func) == 'undefined') { +;;; kukit.e = '[func] argument is mandatory when registering an action'; +;;; kukit.e += ' [actionregistry.register].'; +;;; throw new error(kukit.e); +;;; } if (this.content[name]) { - // Do not allow redefinition -;;; kukit.logError('Error : action [' + name + '] already registered.'); + // do not allow redefinition +;;; kukit.logerror('error : action [' + name + '] already registered.'); return; } this.content[name] = func; }; -ActionRegistry.prototype.exists = function(name) { +this.exists = function(name) { var entry = this.content[name]; return (typeof(entry) != 'undefined'); }; -ActionRegistry.prototype.get = function(name) { +this.get = function(name) { var func = this.content[name]; if (! func) { // not found -;;; kukit.E = 'Error : undefined local action [' + name + '].'; +;;; kukit.E = 'Error : undefined local action [' + name + '].'; throw Error(kukit.E); } return func; }; +this.initialize.apply(this, arguments); +}; + -kukit.actionsGlobalRegistry = new ActionRegistry(); +kukit.actionsGlobalRegistry = new _ActionRegistry(); /* XXX deprecated methods, to be removed asap */ -ar.actionRegistry = {}; -ar.actionRegistry.register = function(name, func) { -;;;var msg='Deprecated kukit.ar.actionRegistry.register, use '; -;;;msg += 'kukit.actionsGlobalRegistry.register instead !'; -;;;kukit.logWarning(msg); - kukit.actionsGlobalRegistry.register(name, func); +ar.actionRegistry = function() { + this.register = function(name, func) { +;;; var msg='Deprecated kukit.ar.actionRegistry.register, use '; +;;; msg += 'kukit.actionsGlobalRegistry.register instead !'; +;;; kukit.logWarning(msg); + kukit.actionsGlobalRegistry.register(name, func); + }; }; }(); /// MODULE END Modified: kukit/kukit.js/trunk/kukit/commandprocessor.js ============================================================================== --- kukit/kukit.js/trunk/kukit/commandprocessor.js (original) +++ kukit/kukit.js/trunk/kukit/commandprocessor.js Thu Jan 10 13:53:49 2008 @@ -25,13 +25,14 @@ * class CommandProcessor */ cp.CommandProcessor = function() { - this.commands = new Array(); + +this.initialize = function() { + this.commands = new Array(); }; -cp.CommandProcessor.prototype.parseCommands = - function(commands, transport) { -;;;kukit.log('Parsing commands.'); -;;;kukit.logDebug('Number of commands : ' + commands.length + '.'); +this.parseCommands = function(commands, transport) { +;;; kukit.log('Parsing commands.'); +;;; kukit.logDebug('Number of commands : ' + commands.length + '.'); for (var y=0;y < commands.length;y++) { var command = commands[y]; this.parseCommand(command, transport); @@ -48,8 +49,7 @@ } }; -cp.CommandProcessor.prototype.parseCommand = - function(command, transport) { +this.parseCommand = function(command, transport) { var selector = ""; var params = {}; var name = ""; @@ -86,12 +86,12 @@ // we have a single text node // OR // we have a single CDATA node (HTML parameter CDATA-style) -;;; var isTextNode = childNode.firstChild.nodeType == 3; -;;; var isCData = childNode.firstChild.nodeType == 4; -;;; if (! (childCount == 1 && (isTextNode || isCData))) { -;;; kukit.E = 'Bad payload, expected a text or a CDATA node'; -;;; throw new Error(kukit.E); -;;; } +;;; var isTextNode = childNode.firstChild.nodeType == 3; +;;; var isCData = childNode.firstChild.nodeType == 4; +;;; if (! (childCount == 1 && (isTextNode || isCData))) { +;;; kukit.E = 'Bad payload, expected a text or a CDATA node'; +;;; throw new Error(kukit.E); +;;; } // we consider this as html payload // The result is always a string from here. result = childNode.firstChild.nodeValue; @@ -106,12 +106,11 @@ this.addCommand(command); }; -cp.CommandProcessor.prototype.addCommand = function(command) { +this.addCommand = function(command) { this.commands[this.commands.length] = command; }; -cp.CommandProcessor.prototype.executeCommands = function(oper) { - kukit.engine.beginSetupEventsCollection(); +this.executeCommands = function(oper) { // node, eventRule, binder are given on oper, in case // the command was called up from an event if (typeof(oper) == 'undefined' || oper == null) { @@ -120,18 +119,19 @@ var commands = this.commands; for (var y=0;y < commands.length;y++) { var command = commands[y]; -;;; try { +;;; try { command.execute(oper); -;;; } catch (e) { -;;; if (e.name == 'RuleMergeError' || e.name == 'EventBindError') { -;;; throw(e); -;;; } else { -;;; // augment the error message -;;; throw kukit.err.commandExecutionError(e, command); -;;; } -;;; } +;;; } catch (e) { +;;; if (e.name == 'RuleMergeError' || e.name == 'EventBindError') { +;;; throw(e); +;;; } else { +;;; // augment the error message +;;; throw kukit.err.commandExecutionError(e, command); +;;; } +;;; } } - kukit.engine.finishSetupEventsCollection(); +}; +this.initialize.apply(this, arguments); }; }(); /// MODULE END Modified: kukit/kukit.js/trunk/kukit/commandreg.js ============================================================================== --- kukit/kukit.js/trunk/kukit/commandreg.js (original) +++ kukit/kukit.js/trunk/kukit/commandreg.js Thu Jan 10 13:53:49 2008 @@ -27,24 +27,12 @@ * class _CommandRegistry */ var _CommandRegistry = function () { + +this.initialize = function() { this.commands = {}; }; -/* -* This is the proposed way of registration, as we like all commands to be -* client actions first. -* -* Examples: -* -* kukit.actionsGlobalRegistry.register('log', f1); -* kukit.commandsGlobalRegistry.registerFromAction('log', -* kukit.cr.makeGlobalCommand); -* -* kukit.actionsGlobalRegistry.register('replaceInnerHTML', f2); -* kukit.commandsGlobalRegistry.registerFromAction('replaceInnerHTML', -* kukit.cr.makeSelectorCommand); -*/ -_CommandRegistry.prototype.registerFromAction = +this.registerFromAction = function(srcname, factory, name) { if (typeof(name) == 'undefined') { // allows to set a different name as the action name, @@ -57,26 +45,42 @@ factory(name, f); }; -_CommandRegistry.prototype.register = function(name, klass) { +this.register = function(name, klass) { if (this.commands[name]) { // Do not allow redefinition -;;; var msg = 'ValueError : command [' + name + '] is already registered.'; -;;; kukit.logError(msg); +;;; var msg = 'ValueError : command [' + name + '] is already registered.'; +;;; kukit.logError(msg); return; } this.commands[name] = klass; }; -_CommandRegistry.prototype.get = function(name) { +this.get = function(name) { var klass = this.commands[name]; -;;;if (! klass) { -;;; // not found -;;; var msg = 'ValueError : no command registered under [' + name + '].'; -;;; kukit.logError(msg); -;;; } +;;; if (! klass) { +;;; // not found +;;; var msg = 'ValueError : no command registered under [' + name + '].'; +;;; kukit.logError(msg); +;;; } return klass; }; +this.initialize.apply(this, arguments); +}; +/* +* This is the proposed way of registration, as we like all commands to be +* client actions first. +* +* Examples: +* +* kukit.actionsGlobalRegistry.register('log', f1); +* kukit.commandsGlobalRegistry.registerFromAction('log', +* kukit.cr.makeGlobalCommand); +* +* kukit.actionsGlobalRegistry.register('replaceInnerHTML', f2); +* kukit.commandsGlobalRegistry.registerFromAction('replaceInnerHTML', +* kukit.cr.makeSelectorCommand); +*/ kukit.commandsGlobalRegistry = new _CommandRegistry(); @@ -141,22 +145,20 @@ }; cr.makeSelectorCommand = function(name, executeOnSingleNode) { - var commandClass = function() {}; - commandClass.prototype = { - execute: _executeCommand, - executeOnScope: _executeCommandOnSelector, - executeOnSingleNode: executeOnSingleNode - }; + var commandClass = function() { + this.execute = _executeCommand; + this.executeOnScope = _executeCommandOnSelector; + this.executeOnSingleNode = executeOnSingleNode; + }; kukit.commandsGlobalRegistry.register(name, commandClass); }; cr.makeGlobalCommand = function(name, executeOnce) { - var commandClass = function() {}; - commandClass.prototype = { - execute: _executeCommand, - executeOnScope: executeOnce, - executeOnSingleNode: executeOnce - }; + var commandClass = function() { + this.execute = _executeCommand; + this.executeOnScope = executeOnce; + this.executeOnSingleNode = executeOnce; + }; kukit.commandsGlobalRegistry.register(name, commandClass); }; Modified: kukit/kukit.js/trunk/kukit/dom.js ============================================================================== --- kukit/kukit.js/trunk/kukit/dom.js (original) +++ kukit/kukit.js/trunk/kukit/dom.js Thu Jan 10 13:53:49 2008 @@ -299,12 +299,27 @@ }; /* +* From http://xkr.us/articles/dom/iframe-document/ +* Note it's not necessary for the iframe to have the name +* attribute since we don't access it from window.frames by name. +*/ +var _getIframeDocument = function(framename) { + var iframe = document.getElementById(framename); + var doc = iframe.contentWindow || iframe.contentDocument; + if (doc.document) { + doc = doc.document; + } + return doc; +}; + +/* * class EmbeddedContentLoadedScheduler * * Scheduler for embedded window content loaded */ -dom.EmbeddedContentLoadedScheduler = - function(framename, func, autodetect) { +dom.EmbeddedContentLoadedScheduler = function() { + +this.initialize = function(framename, func, autodetect) { this.framename = framename; this.func = func; this.autodetect = autodetect; @@ -319,23 +334,9 @@ this.counter.start(); }; -/* -* From http://xkr.us/articles/dom/iframe-document/ -* Note it's not necessary for the iframe to have the name -* attribute since we don't access it from window.frames by name. -*/ -var _getIframeDocument = function(framename) { - var iframe = document.getElementById(framename); - var doc = iframe.contentWindow || iframe.contentDocument; - if (doc.document) { - doc = doc.document; - } - return doc; -}; - -dom.EmbeddedContentLoadedScheduler.prototype.check = function() { +this.check = function() { -;;;kukit.logDebug('Is iframe loaded ?'); +;;; kukit.logDebug('Is iframe loaded ?'); var doc = _getIframeDocument(this.framename); @@ -345,9 +346,9 @@ // even in strings //if (doc._embeddedContentLoadedInitDone) { if (doc['_' + 'embeddedContentLoadedInitDone']) { -;;; var msg = 'Iframe already initialized, but we execute the action'; -;;; msg += ' anyway, as requested.'; -;;; kukit.logWarning(msg); +;;; var msg = 'Iframe already initialized, but we execute the action'; +;;; msg += ' anyway, as requested.'; +;;; kukit.logWarning(msg); this.counter.restart = false; } @@ -391,7 +392,7 @@ } if ( ! this.counter.restart) { -;;; kukit.logDebug('Yes, iframe is loaded.'); +;;; kukit.logDebug('Yes, iframe is loaded.'); // XXX attribute access starting with _ breaks full compression, // even in strings // doc._embeddedContentLoadedInitDone = true; @@ -399,6 +400,8 @@ this.func(); } }; +this.initialize.apply(this, arguments); +}; dom.getNsTags = function(dom_obj, tagName) { // Now, all the document is in the kukit namespace, Modified: kukit/kukit.js/trunk/kukit/errors.js ============================================================================== --- kukit/kukit.js/trunk/kukit/errors.js (original) +++ kukit/kukit.js/trunk/kukit/errors.js Thu Jan 10 13:53:49 2008 @@ -54,6 +54,9 @@ * */ +/* +* class ErrorAnnotation +*/ var ErrorAnnotation = function() { Modified: kukit/kukit.js/trunk/kukit/eventreg.js ============================================================================== --- kukit/kukit.js/trunk/kukit/eventreg.js (original) +++ kukit/kukit.js/trunk/kukit/eventreg.js Thu Jan 10 13:53:49 2008 @@ -31,15 +31,18 @@ * * usage: * -* kukit.eventsGlobalRegistry.register(namespace, eventName, func, +* kukit.eventsGlobalRegistry.register(namespace, eventName, func, * bindMethodName, defaultActionMethodName); -* -* namespace = null: means global namespace -* defaultActionMethodName = null: if there is no default action implemented -* func must be a class (constructor) function, this is the class that -* implements the binder. +* +* namespace = null: means global namespace +* defaultActionMethodName = null: if there is no default action implemented +* klass must be a class (constructor) function, this is the class that +* implements the binder. +* */ -var _EventRegistry = function () { +var _EventRegistry = function() { + +this.initialize = function() { this.content = {}; this.classes = {}; this.eventSets = []; @@ -47,57 +50,67 @@ /* binder registration */ -_EventRegistry.prototype.registerBinder = function(className, func) { - if (typeof(func) == 'undefined') { -;;; kukit.E = 'func argument is mandatory when registering an event'; +this.registerBinder = function(klass) { + if (typeof(klass) == 'undefined') { +;;; kukit.E = 'klass argument is mandatory when registering an event'; ;;; kukit.E += ' binder (_EventRegistry.registerBinder).'; throw new Error(kukit.E); } - if (this.classes[className]) { - // Do not allow redefinition -;;; var msg = 'Error : event class [' + className + '] already registered.'; -;;; kukit.logError(msg); + // See if we are set up already? + // We make a mark not on the class prototype, + // but on the class itself. This will make + // sure inherited classes get a distinct class name. + if (klass.__decorated_for_kss__) { return; - } - // Decorate and store the class - decorateEventBinderClass(func); - this.classes[className] = func; -}; - -_EventRegistry.prototype.existsBinder = function(className) { - var func = this.classes[className]; - return (typeof(func) != 'undefined'); -}; - -_EventRegistry.prototype.getBinderClass = function(className) { - var func = this.classes[className]; - if (! func) { + // We do _not_ overwrite the class's prototype, since + // that destroys any inheritance it has. Our purpose + // is to allow any javascript class to function, so + // we copy the class's attributes to the prototype. + var binder_prototype = new _EventBinder(); + for (var key in binder_prototype) { + klass.prototype[key] = binder_prototype[key]; + } + // Create a className, and register it too. + // + // The reason to create a __className__ is to provide a + // way to lookup the class by a string. This is needed + // because dict keys in javascript can only be strings. + className = '' + _eventClassCounter; + _eventClassCounter += 1; + klass.prototype.__className__ = className; + this.classes[className] = klass; + // mark decorated. We store the class there + // so we can decide if this class has been + // decorated or not. + klass.__decorated_for_kss__ = true; +}; + +this.existsBinder = function(className) { + var klass = this.classes[className]; + return (typeof(klass) != 'undefined'); +}; + +this.getBinderClass = function(className) { + var klass = this.classes[className]; + if (! klass) { // not found ;;; kukit.E = 'Error : undefined event setup type [' + className + '].'; throw new Error(kukit.E); } - return func; + return klass; }; /* events (methods) registration helpers (not to be called directly) */ -_EventRegistry.prototype._register = - function(namespace, eventName, klass, +this._register = function(namespace, eventName, klass, bindMethodName, defaultActionMethodName, iterName) { if (typeof(defaultActionMethodName) == 'undefined') { ;;; kukit.E = 'Missing arguments when calling [_EventRegistry.register].'; throw new Error(kukit.E); } - // Find out the class name. (Not specified now.) - var className = klass.prototype.__className__; - if (typeof(className) == 'undefined') { - // Create a className, and register it too. - className = '' + _eventClassCounter; - _eventClassCounter += 1; - this.registerBinder(className, klass); - klass.prototype.__className__ = className; - } + // Register and decorate the binder's class. + this.registerBinder(klass); if (!eventName) { ;;; kukit.E = '[eventName] argument cannot be empty when registering'; ;;; kukit.E += ' an event with [_EventRegistry.register].'; @@ -114,19 +127,9 @@ ;;; kukit.E += ' an event with [_EventRegistry.register].'; throw new Error(kukit.E); } - // check bindMethodName and defaultActionMethodName - if (bindMethodName && ! klass.prototype[bindMethodName]) { -;;; kukit.E = 'In _EventRegistry.register bind method [' + bindMethodName; -;;; kukit.E += '] is undefined for event [' + eventName; -;;; kukit.E += '] namespace [' + namespace + '].'; - throw new Error(kukit.E); - } - if (defaultActionMethodName && ! klass.prototype[defaultActionMethodName]) { -;;; kukit.E = 'In _EventRegistry.register default action method ['; -;;; kukit.E += defaultActionMethodName + '] is undefined for event ['; -;;; kukit.E += eventName + '] namespace [' + namespace + '].'; - throw new Error(kukit.E); - } + // XXX We do not check bindMethodName and defaltActionMethodName + // here, because at this point they may be hidden by closure. + // // check the iterator. if (! er.getBindIterator(iterName)) { ;;; kukit.E = 'In _EventRegistry.register unknown bind iterator ['; @@ -144,7 +147,7 @@ /* events (methods) binding [ForAll] registration */ -_EventRegistry.prototype._registerEventSet = +this._registerEventSet = function(namespace, names, iterName, bindMethodName) { // At this name the values should be checked already. so this should // be called _after_ _register. @@ -158,7 +161,7 @@ /* there are the actual registration methods, to be called from plugins */ -_EventRegistry.prototype.register = +this.register = function(namespace, eventName, klass, bindMethodName, defaultActionMethodName) { this._register(namespace, eventName, klass, bindMethodName, @@ -167,7 +170,7 @@ bindMethodName); }; -_EventRegistry.prototype.unregister = +this.unregister = function(namespace, eventName) { var key = this._getKey(namespace, eventName); delete this.content[key]; @@ -184,7 +187,7 @@ } }; -_EventRegistry.prototype.registerForAllEvents = +this.registerForAllEvents = function(namespace, eventNames, klass, bindMethodName, defaultActionMethodName, iterName) { if (typeof(eventNames) == 'string') { @@ -198,7 +201,7 @@ this._registerEventSet(namespace, eventNames, iterName, bindMethodName); }; -_EventRegistry.prototype._getKey = function(namespace, eventName) { +this._getKey = function(namespace, eventName) { if (namespace == null) { namespace = ''; } else if (namespace.split('-') > 1) { @@ -209,13 +212,13 @@ return namespace + '-' + eventName; }; -_EventRegistry.prototype.exists = function(namespace, eventName) { +this.exists = function(namespace, eventName) { var key = this._getKey(namespace, eventName); var entry = this.content[key]; return (typeof(entry) != 'undefined'); }; -_EventRegistry.prototype.get = function(namespace, eventName) { +this.get = function(namespace, eventName) { var key = this._getKey(namespace, eventName); var entry = this.content[key]; if (typeof(entry) == 'undefined') { @@ -231,30 +234,79 @@ return entry; }; +this.getBinderClassByEventNamespace = function(namespace, eventName) { + return this.getBinderClass(this.get(namespace, eventName).className); +}; +this.initialize.apply(this, arguments); +}; + + kukit.eventsGlobalRegistry = new _EventRegistry(); /* XXX deprecated methods, to be removed asap */ -var _eventRegistry = {}; -_eventRegistry.register = function(namespace, eventName, klass, - bindMethodName, defaultActionMethodName) { -;;; var msg = 'Deprecated _eventRegistry.register,'; -;;; msg += ' use kukit.eventsGlobalRegistry.register instead ! ['; -;;; msg += namespace + '-' + eventName + '].'; -;;; kukit.logWarning(msg); - kukit.eventsGlobalRegistry.register(namespace, eventName, klass, - bindMethodName, defaultActionMethodName); +var _eventRegistry = function() { + this.register = function(namespace, eventName, klass, + bindMethodName, defaultActionMethodName) { +;;; var msg = 'Deprecated _eventRegistry.register,'; +;;; msg += ' use kukit.eventsGlobalRegistry.register instead ! ['; +;;; msg += namespace + '-' + eventName + '].'; +;;; kukit.logWarning(msg); + kukit.eventsGlobalRegistry.register(namespace, eventName, klass, + bindMethodName, defaultActionMethodName); + }; }; -/* Event class decoration +/* * -* poor man's subclassing -* This is called automatically on registration, to dress -* up the event class with the necessary methods +* class _LateBinder +* +* postpone binding of actions until called first time * */ +var _LateBinder = function() { + +this.initialize = function(binder, name, node) { + this.binder = binder; + this.name = name; + this.node = node; + this.boundEvent = null; +}; + +this.executeActions = function() { + if (! this.boundEvent) { +;;; var msg = 'Attempt of late binding for event [' + this.name; +;;; msg += '], node [' + this.node.nodeName + '].'; +;;; kukit.log(msg); + if (kukit.hasFirebug) { + kukit.log(this.node); + } + var info = kukit.engine.binderInfoRegistry.getBinderInfoById( + this.binder.__binderId__); + var oper = info.bound.getBoundOperForNode(this.name, this.node); + if (oper) { + // (if eventRule is null here, we could still have the default + // method, so go on.) + oper.parms = {}; + this.boundEvent = function() { + this.binder.triggerEvent(this.name, oper); + }; +;;; kukit.log('Node bound.'); + } else { +;;; kukit.logWarning('No node bound.'); + this.boundEvent = function() {}; + } + } + this.boundEvent(); +}; +this.initialize.apply(this, arguments); +}; -/* Provide callins on the state instance that execute a given +/* +* +* class _EventBinder +* +* Provide callins on the state instance that execute a given * continuation event. * Parameters will be the ones specified in the call + * those defined in the rule will be added too. (Parameters can @@ -264,7 +316,7 @@ * * trigger an event bound to a given state instance, same node * -* binder.__continueEvent__('doit', oper.node, {'extravalue': '5'}); +* binder.continueEvent('doit', oper.node, {'extravalue': '5'}); * * with kss rule: * @@ -283,7 +335,7 @@ * trigger an event bound to a given state instance, and the document * (different from current scope) * -* binder.__continueEvent__('doit', null, {'extravalue': '5'}); +* binder.continueEvent('doit', null, {'extravalue': '5'}); * * with kss rule: * @@ -301,7 +353,7 @@ * * trigger an event on all the nodes + document bound to a given state instance * -* binder.__continueEvent_allNodes__('doit', {'extravalue': '5'}); +* binder.continueEventAllNodes('doit', {'extravalue': '5'}); * * with kss rule: * @@ -314,8 +366,9 @@ * so we create a new oper below */ -var _EventBinder__continueEvent__ = - function(name, node, defaultParameters) { +var _EventBinder = function() { + +this.continueEvent = function(name, node, defaultParameters) { // Trigger a continuation event bound to a given state instance, given node // (or on document, if node = null) // @@ -359,12 +412,18 @@ oper.defaultParameters = {}; } // if eventRule is null here, we can yet have the default method, so go on. - this._EventBinder_triggerEvent(name, oper); + this.triggerEvent(name, oper); ;;; kukit.logDebug('Continuation event [' + name + '] executed on same node.'); }; -var _EventBinder__continueEvent_allNodes__ = - function(name, defaultParameters) { +this.__continueEvent__ = function(name, node, defaultParameters) { +;;; var msg = 'Deprecated [__continueEvent__],'; +;;; msg += 'use [continueEvent] instead !'; +;;; kukit.logWarning(msg); + this.continueEvent(name, node, defaultParameters); +}; + +this.continueEventAllNodes = function(name, defaultParameters) { // Trigger an event bound to a given state instance, on all nodes. // (or on document, if node = null) // if no other nodes execute. @@ -383,62 +442,35 @@ } else { newOper.defaultParameters = {}; } - this._EventBinder_triggerEvent(name, newOper); + this.triggerEvent(name, newOper); executed += 1; } ;;; kukit.logDebug('Event [' + name + '] executed on ' + executed + ' nodes.'); }; -var _EventBinder_makeFuncToBind = function(name, node) { +this.__continueEvent_allNodes__ = function(name, defaultParameters) { +;;; var msg = 'Deprecated [__continueEvent_allNodes__],'; +;;; msg += 'use [continueEventAllNodes] instead !'; +;;; kukit.logWarning(msg); + this.continueEventAllNodes(name, defaultParameters); +}; + +this.makeFuncToBind = function(name, node) { var executor = new er._LateBinder(this, name, node); return function() { executor.executeActions(); }; }; -/* -* -* class _LateBinder -* -* postpone binding of actions until called first time -* -*/ -var _LateBinder = function(binder, name, node) { - this.binder = binder; - this.name = name; - this.node = node; - this.boundEvent = null; +this.__makeFuncToBind__ = function(name, node) { +;;; var msg = 'Deprecated [__makeFuncToBind__],'; +;;; msg += 'use [makeFuncToBind] instead !'; +;;; kukit.logWarning(msg); + this.makeFuncToBind(name, node); }; -_LateBinder.prototype.executeActions = function() { - if (! this.boundEvent) { -;;; var msg = 'Attempt of late binding for event [' + this.name; -;;; msg += '], node [' + this.node.nodeName + '].'; -;;; kukit.log(msg); - if (kukit.hasFirebug) { - kukit.log(this.node); - } - var info = kukit.engine.binderInfoRegistry.getBinderInfoById( - this.binder.__binderId__); - var oper = info.bound.getBoundOperForNode(this.name, this.node); - if (oper) { - // (if eventRule is null here, we could still have the default - // method, so go on.) - oper.parms = {}; - this.boundEvent = function() { - this.binder._EventBinder_triggerEvent(this.name, oper); - }; -;;; kukit.log('Node bound.'); - } else { -;;; kukit.logWarning('No node bound.'); - this.boundEvent = function() {}; - } - } - this.boundEvent(); -}; - -var _EventBinder_triggerEvent = function(name, oper) { - // Private. Called from __continueEvent__ or from main event execution. +this.triggerEvent = function(name, oper) { + // Private. Called from continueEvent or from main event execution. oper.binder = this; if (oper.eventRule) { // Call the actions, if we had an event rule. @@ -463,9 +495,16 @@ } }; +this._EventBinder_triggerEvent = function(name, oper) { +;;; var msg = 'Deprecated [_EventBinder_triggerEvent],'; +;;; msg += 'use [triggerEvent] instead !'; +;;; kukit.logWarning(msg); + this.triggerEvent(name, oper); +}; + /* (default) method call handling */ -var _EventBinder_callMethod = function(namespace, name, oper, methodName) { +this.callMethod = function(namespace, name, oper, methodName) { // hidden method for calling just a method and checking that is exists. // (called from oper) var method = this[methodName]; @@ -480,13 +519,13 @@ method.call(this, name, oper); }; -var decorateEventBinderClass = function(cls) { - cls.prototype.__continueEvent__ = _EventBinder__continueEvent__; - cls.prototype.__continueEvent_allNodes__ = - _EventBinder__continueEvent_allNodes__; - cls.prototype._EventBinder_triggerEvent = _EventBinder_triggerEvent; - cls.prototype._EventBinder_callMethod = _EventBinder_callMethod; - cls.prototype.__makeFuncToBind__ = _EventBinder_makeFuncToBind; +this._EventBinder_callMethod = function(namespace, name, oper, methodName) { +;;; var msg = 'Deprecated [_EventBinder_callMethod],'; +;;; msg += 'use [callMethod] instead !'; +;;; kukit.logWarning(msg); + this.callMethod(namespace, name, oper, methodName); +}; + }; /* Event instance registry @@ -496,12 +535,13 @@ * used in run-time to keep track of the event instances * */ +er.BinderInfoRegistry = function() { -er.BinderInfoRegistry = function () { +this.initialize = function() { this.info = {}; }; -er.BinderInfoRegistry.prototype.getOrCreateBinderInfo = +this.getOrCreateBinderInfo = function (id, className, namespace) { // Get or create the event. var binderInfo = this.info[id]; @@ -532,7 +572,7 @@ return binderInfo; }; -er.BinderInfoRegistry.prototype.getBinderInfoById = function (id) { +this.getBinderInfoById = function (id) { // Get an event. var binderInfo = this.info[id]; if (typeof(binderInfo) == 'undefined') { @@ -542,7 +582,7 @@ return binderInfo; }; -er.BinderInfoRegistry.prototype.getSingletonBinderInfoByName = +this.getSingletonBinderInfoByName = function (namespace, name) { //Get className var className = kukit.eventsGlobalRegistry.get(namespace, name).className; @@ -557,7 +597,7 @@ return binderInfo; }; -er.BinderInfoRegistry.prototype.startBindingPhase = function () { +this.startBindingPhase = function () { // At the end of the binding phase, we want to process our events. This // must include all the binder instances we bound in this phase. for (var id in this.info) { @@ -567,7 +607,7 @@ } }; -er.BinderInfoRegistry.prototype.processBindingEvents = function () { +this.processBindingEvents = function () { // At the end of the binding phase, we want to process our events. This // must include all the binder instances we bound in this phase. for (var id in this.info) { @@ -576,6 +616,8 @@ binderInfo.processBindingEvents(); } }; +this.initialize.apply(this, arguments); +}; /* * class _BinderInfo @@ -584,24 +626,25 @@ * various binding info. Follows the workflow of the binding in different stages. * */ +var _BinderInfo = function() { -var _BinderInfo = function (binder) { +this.initialize = function(binder) { this.binder = binder; this.bound = new _OperRegistry(); this.startBindingPhase(); }; -_BinderInfo.prototype.getBinder = function () { +this.getBinder = function () { return this.binder; }; -_BinderInfo.prototype.startBindingPhase = function () { +this.startBindingPhase = function () { // The binding phase starts and it has the information for // the currently on-bound events. this.binding = new _OperRegistry(); }; -_BinderInfo.prototype.bindOper = function (oper) { +this.bindOper = function (oper) { // We mark a given oper. This means a binding on the binder // for given event, node and eventRule (containing event namespace, // name, and evt- parms.) @@ -612,7 +655,7 @@ this.binding.bindOper(oper); }; -_BinderInfo.prototype.processBindingEvents = function () { +this.processBindingEvents = function () { // We came to the end of the binding phase. Now we process all our binding // events, This will do the actual binding on the browser side. this.binding.processBindingEvents(this.binder); @@ -621,25 +664,174 @@ // Delete them from the registry, to protect against accidents. this.binding = null; }; +this.initialize.apply(this, arguments); +}; + +var _iterators = {}; + + // This calls the bind method by each bound oper one by one. + // Eventname and funcToBind are passed too. + // this is the legacy ([EachLegacy]) way + _iterators['EachLegacy'] = + function (eventSet, binder) { + for (var i=0; i AllNodes, not handled by + // the previous line + if (canonical == 'Allnodes') { + canonical = 'AllNodes'; + } + if (iterName != canonical) { + // BBB 2007.12.31, this will turn into an exception. +;;; var msg = 'Deprecated the lowercase iterator names in last '; +;;; msg += 'parameters of '; +;;; msg += 'kukit.eventsGlobalRegistry.registerForAllEvents, use ['; +;;; msg += canonical + '] instead of [' + iterName + '] (2007-12-31)'; +;;; kukit.logWarning(msg); + iterName = canonical; + } + return _iterators[iterName]; +}; /* -* class _OperRegistry +* class _OperRegistry +* +* OperRegistry is associated with a binder instance in the +* BinderInfoRegistry, and remembers bounding information. +* This is used both to remember all the bindings for a given +* instance, but also just to remember the bindings done during +* a given event setup phase. * -* OperRegistry is associated with a binder instance in the -* BinderInfoRegistry, and remembers bounding information. -* This is used both to remember all the bindings for a given -* instance, but also just to remember the bindings done during -* a given event setup phase. */ +var _OperRegistry = function() { -var _OperRegistry = function () { +this.initialize = function() { this.infoPerName = {}; this.infoPerNode = {}; }; // XXX we can do this without full cloning, more efficiently. -_OperRegistry.prototype.propagateTo = function (newreg) { +this.propagateTo = function (newreg) { for (var key in this.infoPerName) { var rulesPerName = this.infoPerName[key]; for (var name in rulesPerName) { @@ -649,7 +841,7 @@ } }; -_OperRegistry.prototype.checkOperBindable = +this.checkOperBindable = function (oper, name, nodeHash) { // Check if the binding with this oper could be done. // Throw exception otherwise. @@ -676,7 +868,7 @@ return rulesPerName; }; -_OperRegistry.prototype.bindOper = function (oper) { +this.bindOper = function (oper) { // Marks binding between binder, eventName, node. var name = oper.eventRule.kssSelector.name; var nodeHash = kukit.rd.hashNode(oper.node); @@ -693,7 +885,7 @@ // XXX This will need refactoring. /// We would only want to lookup from our registry and not the other way around. -_OperRegistry.prototype.processBindingEvents = +this.processBindingEvents = function (binder) { var eventRegistry = kukit.eventsGlobalRegistry; for (var i=0; i < eventRegistry.eventSets.length; i++) { @@ -714,7 +906,7 @@ // XXX The following methods will probably disappear as iterators // replace their functionality. -_OperRegistry.prototype.getBoundOperForNode = function (name, node) { +this.getBoundOperForNode = function (name, node) { // Get the oper that is bound to a given eventName // to a node in this binder // returns null, if there is no such oper. @@ -731,7 +923,7 @@ return oper; }; -_OperRegistry.prototype.getBoundOpers = function (name) { +this.getBoundOpers = function (name) { // Get the opers bound to a given eventName (to any node) // in this binder var opers = []; @@ -746,40 +938,7 @@ return opers; }; -// Iterators -// The getBindIterator returns a function that gets executed on -// the oper registry. -// -// Iterators receive the eventSet as a parameter -// plus a binder and a method. They need to iterate by calling this -// as method.call(binder, ...); where ... can be any parms this -// given iteration specifies. -// - -er.getBindIterator = function(iterName) { - // attempt to find canonical version of string - // and shout if it does not match. - // String must start uppercase. - var canonical = iterName.substring(0, 1).toUpperCase() + - iterName.substring(1); - // Special case: allnodes -> AllNodes, not handled by - // the previous line - if (canonical == 'Allnodes') { - canonical = 'AllNodes'; - } - if (iterName != canonical) { - // BBB 2007.12.31, this will turn into an exception. -;;; var msg = 'Deprecated the lowercase iterator names in last '; -;;; msg += 'parameters of '; -;;; msg += 'kukit.eventsGlobalRegistry.registerForAllEvents, use ['; -;;; msg += canonical + '] instead of [' + iterName + '] (2007-12-31)'; -;;; kukit.logWarning(msg); - iterName = canonical; - } - return _OperRegistry.prototype['_iterate' + iterName]; -}; - -_OperRegistry.prototype.callBindMethod = +this.callBindMethod = function (eventSet, binder, p1, p2, p3, p4, p5, p6) { var method = binder[eventSet.bindMethodName]; // Protect the binding for better logging @@ -792,117 +951,7 @@ ;;; throw new Error(kukit.E); ;;; } }; - -// This calls the bind method by each bound oper one by one. -// Eventname and funcToBind are passed too. -// this is the legacy ([EachLegacy]) way -_OperRegistry.prototype._iterateEachLegacy = - function (eventSet, binder) { - for (var i=0; i-: // evt---: @@ -206,9 +258,9 @@ eventParameters = this.eventFullNames[eventFullName]; } eventParameters[eventKey] = value.txt; -} +}; -kukit.kssp.Block.prototype.addActionDeclaration = function(key, splitkey, value) { +this.addActionDeclaration = function(key, splitkey, value) { // action-server: // action-client: // action-client: - @@ -218,13 +270,13 @@ ;;; kukit.E = 'Wrong key [' + key + '] : '; ;;; kukit.E += 'action- keys can have only one dash.'; ;;; this.emitError(kukit.E); -;;; } +;;; } ;;; if (value.isMethod != false) { ;;; kukit.E = 'Wrong value for key [' + key + '] : '; ;;; kukit.E += 'value providers are not '; ;;; kukit.E += 'allowed for action- keys.'; ;;; this.emitError(kukit.E); -;;; } +;;; } var atab = {'server': 'S', 'client': 'C', 'cancel': 'X'}; var actionType = atab[splitkey[1]]; ;;; if (! actionType) { @@ -232,7 +284,7 @@ ;;; kukit.E += 'qualifier in action- keys must be '; ;;; kukit.E += '"server" or "client" or "cancel".'; ;;; this.emitError(kukit.E); -;;; } +;;; } ;;; // force value to be or - ;;; var splitvalue = value.txt.split('-'); ;;; if (splitvalue.length > 2) { @@ -240,7 +292,7 @@ ;;; kukit.E += 'value must be or '; ;;; kukit.E += '- for action- keys.'; ;;; this.emitError(kukit.E); -;;; } +;;; } // set it var action = this.actions.getOrCreateAction(value.txt); if (actionType != 'X' || action.type == null) { @@ -248,9 +300,9 @@ } else { this.actions.deleteAction(value.txt); } -} +}; -kukit.kssp.Block.prototype.addActionError = function(action, key, value) { +this.addActionError = function(action, key, value) { // -error: // default-error: ;;; if (value.isMethod == true) { @@ -263,9 +315,9 @@ // also create the action for the error itself. var err_action = this.actions.getOrCreateAction(value.txt); err_action.setType('E'); -} +}; -kukit.kssp.Block.prototype.addActionParameter = function(action, key, value) { +this.addActionParameter = function(action, key, value) { var ppRegistries = { '': kukit.pprovidersGlobalRegistry, 'kssSelector': kukit.sr.pproviderSelRegistry, @@ -297,9 +349,9 @@ this.emitError(kukit.E); } action.parms[key] = value; -} +}; -kukit.kssp.Block.prototype.addDeclaration = function(key, value) { +this.addDeclaration = function(key, value) { // p.s. value is here a KssXxParm. In most cases we check and unwrap it. // the keys look like this: // @@ -365,26 +417,30 @@ } }; +}; +kssp.Block = kukit.tk.mkParser('block', { + ";": _mkReturnToken(kssp.semicolon), + ":": function() { + return [new kssp.colon(this.cursor), + new kssp.PropValue(this.cursor)] + }, + "}": _mkEmitAndReturnToken(kssp.closeBrace) + }, + _Block + ); + /* * class PropValue */ -kukit.kssp.PropValue = kukit.tk.mkParser('propValue', { - ";": 'this.emitAndReturn()', - "}": 'this.emitAndReturn()', - ")": 'this.emitAndReturn()', - ",": 'this.emitAndReturn()', - "'": 'new kukit.kssp.String(this.cursor, kukit.kssp.quote)', - '"': 'new kukit.kssp.String2(this.cursor, kukit.kssp.dquote)', - "\/\*": 'new kukit.kssp.Comment(this.cursor, kukit.kssp.openComment)', - "(": 'new kukit.kssp.MethodArgs(this.cursor, kukit.kssp.openParent)' - }); -kukit.kssp.PropValue.prototype.process = function() { +var _PropValue = function() { + +this.process = function() { // Parse all tokens (including first and last) var context = {'nextTokenIndex': 0}; - this.digestTxt(context, kukit.tk.Fraction, kukit.kssp.Comment); + this.digestTxt(context, kukit.tk.Fraction, kssp.Comment); this.txt = ''; var txt = context.txt; - if (this.notInTokens(context, kukit.kssp.String)) { + if (this.notInTokens(context, kssp.String)) { // The previous txt must be all whitespace. if (txt) { ;;; kukit.E = 'Wrong value : unallowed characters [' + txt + ']'; @@ -392,9 +448,9 @@ this.emitError(kukit.E); } // the next one must be a string. - this.expectToken(context, kukit.kssp.String); + this.expectToken(context, kssp.String); this.produceTxt(context.token.txt); - } else if (this.notInTokens(context, kukit.kssp.MethodArgs)) { + } else if (this.notInTokens(context, kssp.MethodArgs)) { // see if not empty and has no spaces in it if (! txt || txt.indexOf(' ') != -1) { ;;; kukit.E = 'Wrong value : method name [' + txt + '] cannot '; @@ -402,7 +458,7 @@ this.emitError(kukit.E); } // the next one must be the rules - this.expectToken(context, kukit.kssp.MethodArgs); + this.expectToken(context, kssp.MethodArgs); this.value = new this.valueClass(txt, context.token.args); } else { // not a string or method: check if we allowed multiword. @@ -414,7 +470,7 @@ } // see what's after if (context.nextTokenIndex < this.result.length) { - this.digestTxt(context, kukit.tk.Fraction, kukit.kssp.Comment); + this.digestTxt(context, kukit.tk.Fraction, kssp.Comment); // we have to be at the end and have no text after if (context.nextTokenIndex < this.result.length || context.txt) { ;;; kukit.E = 'Wrong value : unallowed characters after '; @@ -424,60 +480,80 @@ } this.result = []; }; -kukit.kssp.PropValue.prototype.multiword_allowed = true; -kukit.kssp.PropValue.prototype.valueClass = kukit.rd.KssMethodValue; -kukit.kssp.PropValue.prototype.produceTxt = function(txt) { + +this.initialize = function() { + this.multiword_allowed = true; + this.valueClass = kukit.rd.KssMethodValue; +}; + +this.produceTxt = function(txt) { // txt parms are returned embedded this.value = new kukit.rd.KssTextValue(txt); }; +this.initialize.apply(this, arguments); +}; +kssp.PropValue = kukit.tk.mkParser('propValue', { + ";": _emitAndReturn, + "}": _emitAndReturn, + ")": _emitAndReturn, + ",": _emitAndReturn, + "'": _returnString, + '"': _returnString2, + "\/\*": _returnComment, + "(": _returnMethodArgs + }, + _PropValue + ); /* * class PropValueInMethod * * PropValue in method cannot have method-style vars. */ -kukit.kssp.PropValueInMethod = kukit.tk.mkParser('propValue', { - ";": 'this.emitAndReturn()', - "}": 'this.emitAndReturn()', - ")": 'this.emitAndReturn()', - "]": 'this.emitAndReturn()', - ",": 'this.emitAndReturn()', - "'": 'new kukit.kssp.String(this.cursor, kukit.kssp.quote)', - '"': 'new kukit.kssp.String2(this.cursor, kukit.kssp.dquote)', - "\/\*": 'new kukit.kssp.Comment(this.cursor, kukit.kssp.openComment)' - }); -kukit.kssp.PropValueInMethod.prototype.multiword_allowed = false; -kukit.kssp.PropValueInMethod.prototype.process = - kukit.kssp.PropValue.prototype.process; -kukit.kssp.PropValueInMethod.prototype.produceTxt = function(txt) { +var _PropValueInMethod = function() { + +this.initialize = function() { + this.multiword_allowed = false; +}; + +this.produceTxt = function(txt) { // txt parms are returned unwrapped this.txt = txt; }; +this.initialize.apply(this, arguments); +}; +// this assignment needs to remain after initialization of _PropValue +kssp.PropValueInMethod = kukit.tk.mkParser('propValue', { + ";": _emitAndReturn, + "}": _emitAndReturn, + ")": _emitAndReturn, + "]": _emitAndReturn, + ",": _emitAndReturn, + "'": _returnString, + '"': _returnString2, + "\/\*": _returnComment + }, + _PropValueInMethod + ); +kssp.PropValueInMethod.prototype.process = kssp.PropValue.prototype.process; /* * class EventValue * -* PropValue in pseudo must be single word with no spaces around. */ -kukit.kssp.EventValue = kukit.tk.mkParser('propValue', { - "{": 'this.emitAndReturn()', - " ": 'this.emitAndReturn()', - "\t": 'this.emitAndReturn()', - "\n": 'this.emitAndReturn()', - "\r": 'this.emitAndReturn()', - "\/\*": 'this.emitAndReturn()', - ":": 'this.emitAndReturn()', - "(": '[new kukit.kssp.openParent(this.cursor), new kukit.kssp.PropValue(this.cursor)]', - ")": 'this.emitAndReturn(new kukit.kssp.closeParent(this.cursor))' - }); -kukit.kssp.EventValue.prototype.multiword_allowed = false; -kukit.kssp.EventValue.prototype.process = function() { +var _EventValue = function() { + +this.initialize = function() { + this.multiword_allowed = false; +}; + +this.process = function() { // Parse all tokens (including first and last) var context = {'nextTokenIndex': 0}; - this.digestTxt(context, kukit.tk.Fraction, kukit.kssp.Comment); + this.digestTxt(context, kukit.tk.Fraction, kssp.Comment); this.txt = ''; var txt = context.txt; - if (this.notInTokens(context, kukit.kssp.String)) { + if (this.notInTokens(context, kssp.String)) { // The previous txt must be all whitespace. if (txt) { ;;; kukit.E = 'Wrong value : unallowed characters [' + txt + ']'; @@ -485,13 +561,13 @@ this.emitError(kukit.E); } // the next one must be a string. - this.expectToken(context, kukit.kssp.String); + this.expectToken(context, kssp.String); this.produceTxt(context.token.txt); - } else if (this.notInTokens(context, kukit.kssp.openParent)) { - this.expectToken(context, kukit.kssp.openParent); - this.expectToken(context, kukit.kssp.PropValue); + } else if (this.notInTokens(context, kssp.openParent)) { + this.expectToken(context, kssp.openParent); + this.expectToken(context, kssp.PropValue); this.value = new kukit.rd.KssEventValue(txt, context.token.value); - this.digestTxt(context, kukit.tk.Fraction, kukit.kssp.Comment); + this.digestTxt(context, kukit.tk.Fraction, kssp.Comment); // we have to be at the end and have no text after if (context.txt) { ;;; kukit.E = 'Wrong event selector : [' + context.txt; @@ -501,7 +577,7 @@ this.emitError(kukit.E); } // eat up everything before the closing parent - this.expectToken(context, kukit.kssp.closeParent); + this.expectToken(context, kssp.closeParent); } else { // not a string or method: check if we allowed multiword. if (! this.multiword_allowed && txt.indexOf(' ') != -1) { @@ -512,7 +588,7 @@ } // see what's after if (context.nextTokenIndex < this.result.length) { - this.digestTxt(context, kukit.tk.Fraction, kukit.kssp.Comment); + this.digestTxt(context, kukit.tk.Fraction, kssp.Comment); // we have to be at the end and have no text after if (context.nextTokenIndex < this.result.length || context.txt) { ;;; kukit.E = 'Excess characters after the property value'; @@ -522,19 +598,35 @@ this.result = []; }; -kukit.kssp.EventValue.prototype.produceTxt = function(txt) { +this.produceTxt = function(txt) { // txt parms are returned embedded this.value = new kukit.rd.KssEventValue(txt, null); }; +this.initialize.apply(this, arguments); +}; +kssp.EventValue = kukit.tk.mkParser('propValue', { + "{": _emitAndReturn, + " ": _emitAndReturn, + "\t": _emitAndReturn, + "\n": _emitAndReturn, + "\r": _emitAndReturn, + "\/\*": _emitAndReturn, + ":": _emitAndReturn, + "(": function() { + return [new kssp.openParent(this.cursor), + new kssp.PropValue(this.cursor)] + }, + ")": _mkEmitAndReturnToken(kssp.closeParent) + }, + _EventValue + ); /* * class String */ -kukit.kssp.String = kukit.tk.mkParser('string', { - "'": 'this.emitAndReturn(new kukit.kssp.quote(this.cursor))', - '\x5c': 'new kukit.kssp.Backslashed(this.cursor, kukit.kssp.backslash)' - }); -kukit.kssp.String.prototype.process = function() { +var _String = function() { + +this.process = function() { // collect up the value of the string, omitting the quotes this.txt = ''; for (var i=1; i following + // (in case of allowbubbling we have to apply it to all clicks, as there + // might be a link inside that we cannot detect on the current node) + // + if (oper.parms.preventdefault && kukit.HAVE_SAFARI + && (oper.parms.allowbubbling || eventName == 'click' + && oper.node.tagName.toLowerCase() == 'a')) { + oper.node.onclick = function cancelClickSafari() { + return false; + }; + } }; /* * class NativeEventBinder */ -kukit.pl.NativeEventBinder = function() { -}; +pl.NativeEventBinder = function() { -kukit.pl.NativeEventBinder.prototype.__bind__node = - function(name, func_to_bind, oper) { +this.__bind__node = function(name, func_to_bind, oper) { ;;; if (oper.node == null) { ;;; throw new Error('Native event [' + name + '] must be bound to a node.'); ;;; } this.__bind__(name, func_to_bind, oper); }; -kukit.pl.NativeEventBinder.prototype.__bind__nodeorwindow = - function(name, func_to_bind, oper) { +this.__bind__nodeorwindow = function(name, func_to_bind, oper) { if (oper.node == null) { oper.node = window; } this.__bind__(name, func_to_bind, oper); }; -kukit.pl.NativeEventBinder.prototype.__bind__window = - function(name, func_to_bind, oper) { +this.__bind__window = function(name, func_to_bind, oper) { ;;; if (oper.node != null) { ;;; throw new Error('Native event [' + name + '] must not be bound to a node.'); ;;; } @@ -163,16 +177,14 @@ this.__bind__(name, func_to_bind, oper); }; -kukit.pl.NativeEventBinder.prototype.__bind__nodeordocument = - function(name, func_to_bind, oper) { +this.__bind__nodeordocument = function(name, func_to_bind, oper) { if (oper.node == null) { oper.node = document; } this.__bind__(name, func_to_bind, oper); }; -kukit.pl.NativeEventBinder.prototype.__bind__ = - function(name, func_to_bind, oper) { +this.__bind__ = function(name, func_to_bind, oper) { ;;; oper.componentName = 'native event binding'; oper.evaluateParameters([], {'preventdefault': '', 'allowbubbling': '', 'preventbubbling': ''}); @@ -186,25 +198,12 @@ throw new Error(kukit.E); } } - kukit.pl.registerBrowserEvent(oper); - // - // XXX Safari hack - // necessary since Safari does not prevent the following - // (in case of allowbubbling we have to apply it to all clicks, as there - // might be a link inside that we cannot detect on the current node) - // - // XXX not needed since we have the legacy name parameter: - // var name = oper.getEventName(); - if (oper.parms.preventdefault && kukit.HAVE_SAFARI - && (oper.parms.allowbubbling || name == 'click' - && oper.node.tagName.toLowerCase() == 'a')) { - oper.node.onclick = function cancelClickSafari() { - return false; - }; - } + // we give the name parameter to the registration, so we + // really bind to the event name we want. + pl.registerBrowserEvent(oper, null, name); }; -kukit.pl.NativeEventBinder.prototype.__bind_key__ = +this.__bind_key__ = function(name, func_to_bind, oper) { ;;; oper.componentName = 'native key event binding'; oper.evaluateParameters([], @@ -275,52 +274,10 @@ return true; } }; - kukit.pl.registerBrowserEvent(oper, filter); + pl.registerBrowserEvent(oper, filter); +}; }; -/* -* Registration of all the native events that can bound -* to a node or to document -* (= document or window, depending on the event specs) -* Unsupported are those with absolute no hope to work in a cross browser way -* Preventdefault is only allowed for click and key events, currently -*/ -kukit.eventsGlobalRegistry.register(null, 'blur', kukit.pl.NativeEventBinder, - '__bind__nodeorwindow', null); -kukit.eventsGlobalRegistry.register(null, 'focus', kukit.pl.NativeEventBinder, - '__bind__nodeorwindow', null); -kukit.eventsGlobalRegistry.register(null, 'resize', kukit.pl.NativeEventBinder, - '__bind__nodeorwindow', null); -kukit.eventsGlobalRegistry.register(null, 'click', kukit.pl.NativeEventBinder, - '__bind__nodeordocument', null); -kukit.eventsGlobalRegistry.register(null, 'dblclick', - kukit.pl.NativeEventBinder, '__bind__node', null); -kukit.eventsGlobalRegistry.register(null, 'mousedown', - kukit.pl.NativeEventBinder, '__bind__nodeordocument', null); -kukit.eventsGlobalRegistry.register(null, 'mouseup', - kukit.pl.NativeEventBinder, '__bind__nodeordocument', null); -kukit.eventsGlobalRegistry.register(null, 'mousemove', - kukit.pl.NativeEventBinder, '__bind__nodeordocument', null); -kukit.eventsGlobalRegistry.register(null, 'mouseover', - kukit.pl.NativeEventBinder, '__bind__node', null); -kukit.eventsGlobalRegistry.register(null, 'mouseout', - kukit.pl.NativeEventBinder, '__bind__node', null); -kukit.eventsGlobalRegistry.register(null, 'change', - kukit.pl.NativeEventBinder, '__bind__node', null); -kukit.eventsGlobalRegistry.register(null, 'reset', - kukit.pl.NativeEventBinder, '__bind__node', null); -kukit.eventsGlobalRegistry.register(null, 'select', - kukit.pl.NativeEventBinder, '__bind__node', null); -kukit.eventsGlobalRegistry.register(null, 'submit', - kukit.pl.NativeEventBinder, '__bind__node', null); -kukit.eventsGlobalRegistry.register(null, 'keydown', - kukit.pl.NativeEventBinder, '__bind_key__', null); -kukit.eventsGlobalRegistry.register(null, 'keypress', - kukit.pl.NativeEventBinder, '__bind_key__', null); -kukit.eventsGlobalRegistry.register(null, 'keyup', - kukit.pl.NativeEventBinder, '__bind_key__', null); -//kukit.eventsGlobalRegistry.register(null, 'unload', -// kukit.pl.NativeEventBinder, '__bind__window', null); /* * class TimeoutEventBinder @@ -331,12 +288,13 @@ * unless the binding node has been deleted, in which case it stops, * or it runs only once if repeat=false is given. */ -kukit.pl.TimeoutEventBinder = function() { +pl.TimeoutEventBinder = function() { + +this.initialize = function() { this.counters = {}; }; -kukit.pl.TimeoutEventBinder.prototype.__bind__ = - function(name, func_to_bind, oper) { +this.__bind__ = function(name, func_to_bind, oper) { ;;; oper.componentName = 'timeout event binding'; oper.evaluateParameters(['delay'], {'repeat': 'true'}); oper.evalBool('repeat'); @@ -371,17 +329,15 @@ ;;; kukit.logDebug(msg); } }; - -kukit.eventsGlobalRegistry.register(null, 'timeout', - kukit.pl.TimeoutEventBinder, '__bind__', null); +this.initialize.apply(this, arguments); +}; /* * class LoadEventBinder */ -kukit.pl.LoadEventBinder = function() { -}; +pl.LoadEventBinder = function() { -kukit.pl.LoadEventBinder.prototype.processParameters = +this.processParameters = function(oper, iload) { if (! oper) { return; @@ -428,7 +384,7 @@ return oper; }; -kukit.pl.LoadEventBinder.prototype.__bind__ = function(opers_by_eventName) { +this.__bind__ = function(opers_by_eventName) { // This bind method handles load and iload events together, and // opers_by_eventName is // a dictionary of opers which can contain a load and an iload key, @@ -541,11 +497,7 @@ } }; -// Use the [node] iterator to provide expected invocation -// and call signature of the bind method. -kukit.eventsGlobalRegistry.registerForAllEvents(null, ['load', 'iload'], - kukit.pl.LoadEventBinder, '__bind__', null, 'Node'); - +}; /* * class SpinnerEventBinder @@ -553,17 +505,18 @@ * Spinner support. Besides the event itself we use some utility * classes to introduce lazyness (delay) for the spinner. */ -kukit.pl.SpinnerEventBinder = function() { +pl.SpinnerEventBinder = function() { + +this.initialize = function() { this.state = false; var self = this; - var timeoutSetState = function(spinnerevent) { + var _timeoutSetState = function(spinnerevent) { self.timeoutSetState(spinnerevent); }; - this.scheduler = new kukit.ut.Scheduler(timeoutSetState); + this.scheduler = new kukit.ut.Scheduler(_timeoutSetState); }; -kukit.pl.SpinnerEventBinder.prototype.__bind__ = function(name, func_to_bind, - oper) { +this.__bind__ = function(name, func_to_bind, oper) { ;;; oper.componentName = '[spinner] event binding'; oper.evaluateParameters([], {'laziness': 0}); oper.evalInt('laziness'); @@ -576,8 +529,7 @@ kukit.engine.requestManager.registerSpinnerEvent(func, state_to_bind); }; -kukit.pl.SpinnerEventBinder.prototype.setState = function(func_to_bind, state, - laziness) { +this.setState = function(func_to_bind, state, laziness) { // This is called when state changes. We introduce laziness // before calling the func. this.func_to_bind = func_to_bind; @@ -587,17 +539,73 @@ this.scheduler.setNextWakeAtLeast(wakeUp); }; -kukit.pl.SpinnerEventBinder.prototype.timeoutSetState = function() { +this.timeoutSetState = function() { // really call the bound actions which should set the spinner this.func_to_bind(); }; +this.initialize.apply(this, arguments); +}; + +}(); /// MODULE END + +/* +* Registration of all the native events that can bound +* to a node or to document +* (= document or window, depending on the event specs) +* Unsupported are those with absolute no hope to work in a cross browser way +* Preventdefault is only allowed for click and key events, currently +*/ +kukit.eventsGlobalRegistry.register(null, 'blur', kukit.pl.NativeEventBinder, + '__bind__nodeorwindow', null); +kukit.eventsGlobalRegistry.register(null, 'focus', kukit.pl.NativeEventBinder, + '__bind__nodeorwindow', null); +kukit.eventsGlobalRegistry.register(null, 'resize', kukit.pl.NativeEventBinder, + '__bind__nodeorwindow', null); +kukit.eventsGlobalRegistry.register(null, 'click', kukit.pl.NativeEventBinder, + '__bind__nodeordocument', null); +kukit.eventsGlobalRegistry.register(null, 'dblclick', + kukit.pl.NativeEventBinder, '__bind__node', null); +kukit.eventsGlobalRegistry.register(null, 'mousedown', + kukit.pl.NativeEventBinder, '__bind__nodeordocument', null); +kukit.eventsGlobalRegistry.register(null, 'mouseup', + kukit.pl.NativeEventBinder, '__bind__nodeordocument', null); +kukit.eventsGlobalRegistry.register(null, 'mousemove', + kukit.pl.NativeEventBinder, '__bind__nodeordocument', null); +kukit.eventsGlobalRegistry.register(null, 'mouseover', + kukit.pl.NativeEventBinder, '__bind__node', null); +kukit.eventsGlobalRegistry.register(null, 'mouseout', + kukit.pl.NativeEventBinder, '__bind__node', null); +kukit.eventsGlobalRegistry.register(null, 'change', + kukit.pl.NativeEventBinder, '__bind__node', null); +kukit.eventsGlobalRegistry.register(null, 'reset', + kukit.pl.NativeEventBinder, '__bind__node', null); +kukit.eventsGlobalRegistry.register(null, 'select', + kukit.pl.NativeEventBinder, '__bind__node', null); +kukit.eventsGlobalRegistry.register(null, 'submit', + kukit.pl.NativeEventBinder, '__bind__node', null); +kukit.eventsGlobalRegistry.register(null, 'keydown', + kukit.pl.NativeEventBinder, '__bind_key__', null); +kukit.eventsGlobalRegistry.register(null, 'keypress', + kukit.pl.NativeEventBinder, '__bind_key__', null); +kukit.eventsGlobalRegistry.register(null, 'keyup', + kukit.pl.NativeEventBinder, '__bind_key__', null); +//kukit.eventsGlobalRegistry.register(null, 'unload', +// kukit.pl.NativeEventBinder, '__bind__window', null); + +kukit.eventsGlobalRegistry.register(null, 'timeout', + kukit.pl.TimeoutEventBinder, '__bind__', null); + +// Use the [node] iterator to provide expected invocation +// and call signature of the bind method. +kukit.eventsGlobalRegistry.registerForAllEvents(null, ['load', 'iload'], + kukit.pl.LoadEventBinder, '__bind__', null, 'Node'); + kukit.eventsGlobalRegistry.register(null, 'spinneron', kukit.pl.SpinnerEventBinder, '__bind__', null); kukit.eventsGlobalRegistry.register(null, 'spinneroff', kukit.pl.SpinnerEventBinder, '__bind__', null); - /* Core actions * * The core client actions that can be executed on the client Modified: kukit/kukit.js/trunk/kukit/providerreg.js ============================================================================== --- kukit/kukit.js/trunk/kukit/providerreg.js (original) +++ kukit/kukit.js/trunk/kukit/providerreg.js Thu Jan 10 13:53:49 2008 @@ -17,19 +17,22 @@ * 02111-1307, USA. */ -kukit.pr = {}; +kukit.pr = new function() { /// MODULE START + +var pr = this; /* * class ValueProviderRegistry * * The parameter providers need to be registered here. */ +pr.ValueProviderRegistry = function () { -kukit.pr.ValueProviderRegistry = function () { +this.initialize = function() { this.content = {}; }; -kukit.pr.ValueProviderRegistry.prototype.register = function(name, func) { +this.register = function(name, func) { if (typeof(func) == 'undefined') { ;;; kukit.E = 'func argument is mandatory when registering a parameter' ;;; kukit.E += ' provider [ValueProviderRegistry.register].'; @@ -45,27 +48,21 @@ this.content[name] = func; }; -kukit.pr.ValueProviderRegistry.prototype.exists = function(name) { +this.exists = function(name) { var entry = this.content[name]; return (typeof(entry) != 'undefined'); }; -kukit.pr.ValueProviderRegistry.prototype.get = function(name) { +this.get = function(name) { var func = this.content[name]; if (! func) { - // not found - if (name == '') { - // default provider for the strings - return kukit.pr.IdentityPP; - } else { -;;; kukit.E = 'Error : undefined parameter provider [' + name + '].'; - throw new Error(kukit.E); - } +;;; kukit.E = 'Error : undefined parameter provider [' + name + '].'; + throw new Error(kukit.E); } return func; }; - -kukit.pprovidersGlobalRegistry = new kukit.pr.ValueProviderRegistry(); +this.initialize.apply(this, arguments); +}; /* * Register the core parameter providers @@ -90,229 +87,289 @@ * this provider expects a single parameter, the string. */ -kukit.pr.IdentityPP = function() {}; -kukit.pr.IdentityPP.prototype = { - check: function(args) { - // check does not need to be used here actually. -;;; if (args.length != 1) { -;;; throw new Error('internal error, IdentityPP needs 1 argument'); -;;; } - }, - eval: function(args, node) { - return args[0]; - } +/* +* class _IdentityPP +*/ +var _IdentityPP = function() { + +this.check = function(args) { + // check does not need to be used here actually. +;;; if (args.length != 1) { +;;; throw new Error('internal error, _IdentityPP needs 1 argument'); +;;; } }; -kukit.pprovidersGlobalRegistry.register('', kukit.pr.IdentityPP); -kukit.pr.FormVarPP = function() {}; -kukit.pr.FormVarPP.prototype = { - check: function(args) { -;;; if (args.length != 2) { -;;; throw new Error('formVar method needs 2 arguments [formname, varname]'); -;;; } - }, - eval: function(args, node) { - return kukit.fo.getFormVar(new kukit.fo.NamedFormLocator(args[0]), - args[1]); - } +this.eval = function(args, node) { + return args[0]; }; -kukit.pprovidersGlobalRegistry.register('formVar', kukit.pr.FormVarPP); -kukit.pr.CurrentFormVarPP = function() {}; -kukit.pr.CurrentFormVarPP.prototype = { - check: function(args) { -;;; if (args.length != 0 && args.length != 1) { -;;; throw new Error('currentFormVar method needs 0 or 1 argument [varname]'); -;;; } - }, - eval: function(args, node) { - if (args.length == 1) { - return kukit.fo.getFormVar(new kukit.fo.CurrentFormLocator(node), - args[0]); - } else { - // no form var name, just get the value of the node. - return kukit.fo.getValueOfFormElement(node); - } - } }; -kukit.pprovidersGlobalRegistry.register('currentFormVar', - kukit.pr.CurrentFormVarPP); -kukit.pr.CurrentFormVarFromKssAttrPP = function() {}; -kukit.pr.CurrentFormVarFromKssAttrPP.prototype = { - check: function(args) { -;;; if (args.length != 1 && args.length != 2) { -;;; kukit.E = 'currentFormVarFromKssAttr method needs 1 or 2 argument'; -;;; kukit.E += ' [attrname, [recurseParents]]'; -;;; throw new Error(kukit.E); -;;; } - }, - eval: function(args, node) { - var argname = args[0]; - var recurseParents = false; - if (args.length == 2) { -;;; kukit.E = '2nd attribute of currentFormVarForKssAttr must be a'; -;;; kukit.E += ' boolean'; - kukit.ut.evalBool(args[1], kukit.E); - recurseParents = args[1]; - } - var formvarname = kukit.dom.getRecursiveAttribute(node, argname, - recurseParents, kukit.dom.getKssAttribute); +/* +* class _FormVarPP +*/ +var _FormVarPP = function() { + +this.check = function(args) { +;;; if (args.length != 2) { +;;; throw new Error('formVar method needs 2 arguments [formname, varname]'); +;;; } +}; + +this.eval = function(args, node) { + return kukit.fo.getFormVar(new kukit.fo.NamedFormLocator(args[0]), args[1]); +}; + +}; + +/* +* class _CurrentFormPP +*/ +var _CurrentFormVarPP = function() { + +this.check = function(args) { +;;; if (args.length != 0 && args.length != 1) { +;;; throw new Error('currentFormVar method needs 0 or 1 argument [varname]'); +;;; } +}; + +this.eval = function(args, node) { + if (args.length == 1) { return kukit.fo.getFormVar(new kukit.fo.CurrentFormLocator(node), - formvarname); + args[0]); + } else { + // no form var name, just get the value of the node. + return kukit.fo.getValueOfFormElement(node); } }; -kukit.pprovidersGlobalRegistry.register('currentFormVarFromKssAttr', - kukit.pr.CurrentFormVarFromKssAttrPP); + +}; + +/* +* class _CurrentFormVarFromKssAttrPP +*/ +var _CurrentFormVarFromKssAttrPP = function() { + +this.check = function(args) { +;;; if (args.length != 1 && args.length != 2) { +;;; kukit.E = 'currentFormVarFromKssAttr method needs 1 or 2 argument'; +;;; kukit.E += ' [attrname, [recurseParents]]'; +;;; throw new Error(kukit.E); +;;; } +}; + +this.eval = function(args, node) { + var argname = args[0]; + var recurseParents = false; + if (args.length == 2) { +;;; kukit.E = '2nd attribute of currentFormVarForKssAttr must be a'; +;;; kukit.E += ' boolean'; + kukit.ut.evalBool(args[1], kukit.E); + recurseParents = args[1]; + } + var formvarname = kukit.dom.getRecursiveAttribute(node, argname, + recurseParents, kukit.dom.getKssAttribute); + return kukit.fo.getFormVar(new kukit.fo.CurrentFormLocator(node), + formvarname); +}; + +}; /* BBB. To be deprecated at 2007-08-15 */ -kukit.pr.FormPP = function() {}; -kukit.pr.FormPP.prototype = { - check: function(args) { -;;; if (args.length != 1) { -;;; throw new Error('form method needs 1 arguments [formname]'); -;;; } -;;; var msg = 'Deprecated the [form(formname)] parameter provider,'; -;;; msg += ' use [xxx-kssSubmitForm: form(formname)] instead !'; -;;; kukit.logWarning(msg); - }, - eval: function(args, node) { - return kukit.fo.getAllFormVars(new kukit.fo.NamedFormLocator(args[0]), - new kukit.ut.DictCollector()); - } +/* +* class _FormPP +*/ +var _FormPP = function() { + +this.check = function(args) { +;;; if (args.length != 1) { +;;; throw new Error('form method needs 1 arguments [formname]'); +;;; } +;;; var msg = 'Deprecated the [form(formname)] parameter provider,'; +;;; msg += ' use [xxx-kssSubmitForm: form(formname)] instead !'; +;;; kukit.logWarning(msg); +}; + +this.eval = function(args, node) { + return kukit.fo.getAllFormVars(new kukit.fo.NamedFormLocator(args[0]), + new kukit.ut.DictCollector()); +}; + }; -kukit.pprovidersGlobalRegistry.register('form', kukit.pr.FormPP); /* BBB. To be deprecated at 2007-08-15 */ -kukit.pr.CurrentFormPP = function() {}; -kukit.pr.CurrentFormPP.prototype = { - check: function(args) { -;;; if (args.length != 0) { -;;; throw new Error('currentForm method needs no argument'); -;;; } -;;; var msg = 'Deprecated the [currentForm()] parameter provider,'; -;;; msg += ' use [xxx-kssSubmitForm: currentForm()] instead !'; -;;; kukit.logWarning(msg); - }, - eval: function(args, node) { - return kukit.fo.getAllFormVars(new kukit.fo.CurrentFormLocator(node), - new kukit.ut.DictCollector()); - } +/* +* class _CurrentFormPP +*/ +var _CurrentFormPP = function() { + +this.check = function(args) { +;;; if (args.length != 0) { +;;; throw new Error('currentForm method needs no argument'); +;;; } +;;; var msg = 'Deprecated the [currentForm()] parameter provider,'; +;;; msg += ' use [xxx-kssSubmitForm: currentForm()] instead !'; +;;; kukit.logWarning(msg); }; -kukit.pprovidersGlobalRegistry.register('currentForm', kukit.pr.CurrentFormPP); -kukit.pr.NodeAttrPP = function() {}; -kukit.pr.NodeAttrPP.prototype = { - check: function(args) { -;;; if (args.length != 1 && args.length != 2) { -;;; kukit.E = 'nodeAttr method needs 1 or 2 argument (attrname,'; -;;; kukit.E += ' [recurseParents]).'; -;;; throw new Error(kukit.E); -;;; } -;;; if (args[0].toLowerCase() == 'style') { -;;; throw new Error('nodeAttr method does not accept [style] as attrname.'); -;;; } -;;; if (args[0].match(/[ ]/)) { -;;; throw new Error('attrname parameter in nodeAttr method cannot contain space.'); -;;; } - }, - eval: function(args, node) { - var argname = args[0]; - var recurseParents = false; - if (args.length == 2) { - recurseParents = args[1]; -;;; kukit.E = '2nd attribute of nodeAttr must be a boolean.'; - kukit.ut.evalBool(recurseParents, kukit.E); - } - return kukit.dom.getRecursiveAttribute(node, argname, recurseParents, - kukit.dom.getAttribute); +this.eval = function(args, node) { + return kukit.fo.getAllFormVars(new kukit.fo.CurrentFormLocator(node), + new kukit.ut.DictCollector()); +}; + +}; + +/* +* class _NodeAttrPP +*/ +var _NodeAttrPP = function() { + +this.check = function(args) { +;;; if (args.length != 1 && args.length != 2) { +;;; kukit.E = 'nodeAttr method needs 1 or 2 argument (attrname,'; +;;; kukit.E += ' [recurseParents]).'; +;;; throw new Error(kukit.E); +;;; } +;;; if (args[0].toLowerCase() == 'style') { +;;; throw new Error('nodeAttr method does not accept [style] as attrname.'); +;;; } +;;; if (args[0].match(/[ ]/)) { +;;; throw new Error('attrname parameter in nodeAttr method cannot contain space.'); +;;; } +}; + +this.eval = function(args, node) { + var argname = args[0]; + var recurseParents = false; + if (args.length == 2) { + recurseParents = args[1]; +;;; kukit.E = '2nd attribute of nodeAttr must be a boolean.'; + kukit.ut.evalBool(recurseParents, kukit.E); } + return kukit.dom.getRecursiveAttribute(node, argname, recurseParents, + kukit.dom.getAttribute); +}; + }; -kukit.pprovidersGlobalRegistry.register('nodeAttr', kukit.pr.NodeAttrPP); -kukit.pr.KssAttrPP = function() {}; -kukit.pr.KssAttrPP.prototype = { - check: function(args) { -;;; if (args.length != 1 && args.length != 2) { -;;; kukit.E = 'kssAttr method needs 1 or 2 argument (attrname,'; -;;; kukit.E += ' [recurseParents]).'; -;;; throw new Error(kukit.E); -;;; } -;;; if (args[0].match(/[ -]/)) { -;;; kukit.E = 'attrname parameter in kssAttr method cannot contain'; -;;; kukit.E += ' dashes or spaces.'; -;;; throw new Error(kukit.E); -;;; } - }, - eval: function(args, node) { - var argname = args[0]; - var recurseParents = false; - if (args.length == 2) { - recurseParents = args[1]; -;;; kukit.E = '2nd attribute of kssAttr must be a boolean.'; - kukit.ut.evalBool(recurseParents, kukit.E); - } - return kukit.dom.getRecursiveAttribute(node, argname, recurseParents, - kukit.dom.getKssAttribute); +/* +* class _KssAttrPP +*/ +var _KssAttrPP = function() { + +this.check = function(args) { +;;; if (args.length != 1 && args.length != 2) { +;;; kukit.E = 'kssAttr method needs 1 or 2 argument (attrname,'; +;;; kukit.E += ' [recurseParents]).'; +;;; throw new Error(kukit.E); +;;; } +;;; if (args[0].match(/[ -]/)) { +;;; kukit.E = 'attrname parameter in kssAttr method cannot contain'; +;;; kukit.E += ' dashes or spaces.'; +;;; throw new Error(kukit.E); +;;; } +}; + +this.eval = function(args, node) { + var argname = args[0]; + var recurseParents = false; + if (args.length == 2) { + recurseParents = args[1]; +;;; kukit.E = '2nd attribute of kssAttr must be a boolean.'; + kukit.ut.evalBool(recurseParents, kukit.E); } + return kukit.dom.getRecursiveAttribute(node, argname, recurseParents, + kukit.dom.getKssAttribute); }; -kukit.pprovidersGlobalRegistry.register('kssAttr', kukit.pr.KssAttrPP); -kukit.pr.NodeContentPP = function() {}; -kukit.pr.NodeContentPP.prototype = { - check: function(args) { -;;; if (args.length != 0 && args.length != 1) { -;;; throw new Error('nodeContent method needs 0 or 1 argument [recursive].'); -;;; } - }, - eval: function(args, node) { - var recursive = false; - if (args.length == 1) { - recursive = args[0]; - } - return kukit.dom.textContent(node, recursive); +}; + +/* +* class _NodeContentPP +*/ +var _NodeContentPP = function() { + +this.check = function(args) { +;;; if (args.length != 0 && args.length != 1) { +;;; throw new Error('nodeContent method needs 0 or 1 argument [recursive].'); +;;; } +}; + +this.eval = function(args, node) { + var recursive = false; + if (args.length == 1) { + recursive = args[0]; } + return kukit.dom.textContent(node, recursive); +}; + +}; + +/* +* class _StateVarPP +*/ +var _StateVarPP = function() { + +this.check = function(args) { +;;; if (args.length != 1) { +;;; throw new Error('stateVar method needs 1 argument [varname].'); +;;; } }; -kukit.pprovidersGlobalRegistry.register('nodeContent', kukit.pr.NodeContentPP); -kukit.pr.StateVarPP = function() {}; -kukit.pr.StateVarPP.prototype = { - check: function(args) { -;;; if (args.length != 1) { -;;; throw new Error('stateVar method needs 1 argument [varname].'); -;;; } - }, - eval: function(args, node) { - var key = args[0]; - var value = kukit.engine.stateVariables[key]; - if (typeof(value) == 'undefined') { - // notfound arguments will get null -;;; kukit.E = 'Nonexistent statevar ['+ key +'].'; - throw new Error(kukit.E); - } - return value; +this.eval = function(args, node) { + var key = args[0]; + var value = kukit.engine.stateVariables[key]; + if (typeof(value) == 'undefined') { + // notfound arguments will get null +;;; kukit.E = 'Nonexistent statevar ['+ key +'].'; + throw new Error(kukit.E); } + return value; }; -kukit.pprovidersGlobalRegistry.register('stateVar', kukit.pr.StateVarPP); -kukit.pr.PassPP = function() {}; -kukit.pr.PassPP.prototype = { - check: function(args) { -;;; if (args.length != 1) { -;;; throw new Error('pass method needs 1 argument [attrname].'); -;;; } - }, - eval: function(args, node, defaultParameters) { - var key = args[0]; - var value = defaultParameters[key]; - if (typeof(value) == 'undefined') { - // notfound arguments will get null -;;; kukit.E = 'Nonexistent default parm ['+ key +'].'; - throw new Error(kukit.E); - } - return value; +}; + +/* +* class _PassPP +*/ +var _PassPP = function() { + +this.check = function(args) { +;;; if (args.length != 1) { +;;; throw new Error('pass method needs 1 argument [attrname].'); +;;; } +}; + +this.eval = function(args, node, defaultParameters) { + var key = args[0]; + var value = defaultParameters[key]; + if (typeof(value) == 'undefined') { + // notfound arguments will get null +;;; kukit.E = 'Nonexistent default parm ['+ key +'].'; + throw new Error(kukit.E); } + return value; +}; + }; -kukit.pprovidersGlobalRegistry.register('pass', kukit.pr.PassPP); + + +kukit.pprovidersGlobalRegistry = new this.ValueProviderRegistry(); + +kukit.pprovidersGlobalRegistry.register('', _IdentityPP); +kukit.pprovidersGlobalRegistry.register('currentFormVar', + _CurrentFormVarPP); +kukit.pprovidersGlobalRegistry.register('currentFormVarFromKssAttr', + _CurrentFormVarFromKssAttrPP); +kukit.pprovidersGlobalRegistry.register('formVar', _FormVarPP); +kukit.pprovidersGlobalRegistry.register('kssAttr', _KssAttrPP); +kukit.pprovidersGlobalRegistry.register('stateVar', _StateVarPP); +kukit.pprovidersGlobalRegistry.register('pass', _PassPP); +kukit.pprovidersGlobalRegistry.register('nodeContent', _NodeContentPP); +kukit.pprovidersGlobalRegistry.register('nodeAttr', _NodeAttrPP); +kukit.pprovidersGlobalRegistry.register('form', _FormPP); +kukit.pprovidersGlobalRegistry.register('currentForm', _CurrentFormPP); + +}(); /// MODULE END Modified: kukit/kukit.js/trunk/kukit/requestmanager.js ============================================================================== --- kukit/kukit.js/trunk/kukit/requestmanager.js (original) +++ kukit/kukit.js/trunk/kukit/requestmanager.js Thu Jan 10 13:53:49 2008 @@ -19,19 +19,24 @@ /* Request manager */ -kukit.rm = {}; +kukit.rm = new function() { /// MODULE START + +var rm = this; + /* Generation of an integer uid on request objects */ -kukit.rm._rid = 0; +rm._rid = 0; /* -* class RequestItem +* class _RequestItem * * Request item. Encapsulates the sendout function and data. */ -kukit.rm.RequestItem = function(sendHook, url, timeoutHook, timeout, now) { +var _RequestItem = function() { + +this.initialize = function(sendHook, url, timeoutHook, timeout, now) { if (typeof(now) == 'undefined') { now = (new Date()).valueOf(); } @@ -43,27 +48,27 @@ this.timeoutHook = timeoutHook; // Generate a RID. Due to timeouting, we have enough // of these for not to overlap ever. - this.rid = kukit.rm._rid; - kukit.rm._rid ++; - if (kukit.rm._rid >= 10000000000) { - kukit.rm._rid = 0; + this.rid = rm._rid; + rm._rid ++; + if (rm._rid >= 10000000000) { + rm._rid = 0; } }; -kukit.rm.RequestItem.prototype.callTimeoutHook = function() { +this.callTimeoutHook = function() { // Calls the timeout hook for this item if (this.timeoutHook) { this.timeoutHook(this); } }; -kukit.rm.RequestItem.prototype.setReceivedCallback = function(func) { +this.setReceivedCallback = function(func) { // Sets the received callback function. It will be // called with the item as first parameter. this._receivedCallback = func; }; -kukit.rm.RequestItem.prototype.receivedResult = function(now) { +this.receivedResult = function(now) { // This is called when the result response has arrived. It // returns a booolean value, if this is false, the caller // must give up processing the result that has been timed @@ -72,35 +77,45 @@ this._receivedCallback = null; return result; }; +this.initialize.apply(this, arguments); +}; + +rm.TestRequestItem = function() { +kukit.logWarning('Use class [rm.TestRequestItem] only in tests !'); +this.initialize.apply(this, arguments); +}; +rm.TestRequestItem.prototype = new _RequestItem(); /* -* class TimerQueue +* class _TimerQueue * * the send queue. This handles timeouts, and executes * a callback for timed out items. * Callback is called with the request item as parameter. */ -kukit.rm.TimerQueue = function(callback) { +var _TimerQueue = function() { + +this.initialize = function(callback) { this.callback = callback; this.queue = new kukit.ut.SortedQueue(this._sentSort); this.count = 0; }; -kukit.rm.TimerQueue.prototype._sentSort = function(a, b) { +this._sentSort = function(a, b) { // sorting of the sent queue, by expiration if (a.expire < b.expire) return -1; else if (a.expire > b.expire) return +1; else return 0; }; -kukit.rm.TimerQueue.prototype.push = function(item) { +this.push = function(item) { // push a given slot this.queue.push(item); this.count += 1; }; -kukit.rm.TimerQueue.prototype.pop = function(item) { +this.pop = function(item) { // pop a given slot, return true if it was valid, // return false if it was already handled by timeout. // An object can be popped more times! @@ -113,7 +128,7 @@ } }; -kukit.rm.TimerQueue.prototype.handleExpiration = function(now) { +this.handleExpiration = function(now) { if (typeof(now) == 'undefined') { now = (new Date()).valueOf(); } @@ -141,11 +156,22 @@ } return next_expire; }; +this.initialize.apply(this, arguments); +}; + +rm.TestTimerQueue = function() { +kukit.logWarning('Use class [rm.TestTimerQueue] only in tests !'); +this.initialize.apply(this, arguments); +}; +rm.TestTimerQueue.prototype = new _TimerQueue(); + /* * class RequestManager */ -kukit.rm.RequestManager = function (name, maxNr, schedulerClass) { +rm.RequestManager = function () { + +this.initialize = function (maxNr, name, schedulerClass) { // schedulerClass is mainly provided for debugging... this.waitingQueue = new kukit.ut.FifoQueue(); this.sentNr = 0; @@ -153,7 +179,7 @@ var timeoutItem = function(item) { self.timeoutItem(item); }; - this.timerQueue = new kukit.rm.TimerQueue(timeoutItem); + this.timerQueue = new _TimerQueue(timeoutItem); if (typeof(name) == 'undefined') { name = null; } @@ -176,27 +202,24 @@ this.timeoutScheduler = new schedulerClass(checkTimeout); this.spinnerEvents = {'off': [], 'on': []}; this.spinnerState = false; -}; - -// sending timeout in millisecs -kukit.rm.RequestManager.prototype.sendingTimeout = 8000; + // sending timeout in millisecs + this.sendingTimeout = 8000; -// max request number -kukit.rm.RequestManager.prototype.maxNr = 4; +}; -;;; kukit.rm.RequestManager.prototype.getInfo = function() { +;;; this.getInfo = function() { ;;; var msg = '(RQ: ' + this.sentNr + ' OUT, ' + this.waitingQueue.size(); ;;; msg += ' WAI)'; ;;; return msg; ;;; }; -;;; kukit.rm.RequestManager.prototype.log = function(txt) { +;;; this.log = function(txt) { ;;; var msg = 'RequestManager ' + this.nameString + txt + ' '; ;;; msg += this.getInfo() + '.'; ;;; kukit.logDebug(msg); ;;; }; -kukit.rm.RequestManager.prototype.setSpinnerState = function(newState) { +this.setSpinnerState = function(newState) { if (this.spinnerState != newState) { this.spinnerState = newState; // Call the registered spinner events for this state @@ -207,13 +230,13 @@ } }; -kukit.rm.RequestManager.prototype.pushWaitingRequest = function(item, now) { +this.pushWaitingRequest = function(item, now) { this.waitingQueue.push(item); // Set the timeout this.checkTimeout(now); }; -kukit.rm.RequestManager.prototype.popWaitingRequest = function() { +this.popWaitingRequest = function() { var q = this.waitingQueue; // pop handled elements, we don't send them out at all while (! q.empty() && q.front().handled) { @@ -227,7 +250,7 @@ } }; -kukit.rm.RequestManager.prototype.pushSentRequest = function(item, now) { +this.pushSentRequest = function(item, now) { this.sentNr += 1; ;;; this.log('notifies server ' + item.url + ', rid=' + item.rid); // Set the spinner state @@ -245,7 +268,7 @@ item.sendHook(item); }; -kukit.rm.RequestManager.prototype.checkTimeout = function(now) { +this.checkTimeout = function(now) { var nextWake = this.timerQueue.handleExpiration(now); if (nextWake) { // To make sure, add 50ms to the nextwake @@ -262,7 +285,7 @@ this.timeoutScheduler.setNextWakeAtLeast(nextWake); }; -kukit.rm.RequestManager.prototype.popSentRequest = function(item) { +this.popSentRequest = function(item) { var success = this.timerQueue.pop(item); // We remove both to be processed, and timed out requests from the queue. // This means: possibly more physical requests are out, but this @@ -271,11 +294,11 @@ return success; }; -kukit.rm.RequestManager.prototype.isSentRequestQueueFull = function() { +this.isSentRequestQueueFull = function() { return (this.sentNr >= this.maxNr); }; -kukit.rm.RequestManager.prototype.receivedResult = function(item, now) { +this.receivedResult = function(item, now) { // called automatically when the result gets processed. // Mark that we have one less request out. var success = this.popSentRequest(item); @@ -298,7 +321,7 @@ }; -kukit.rm.RequestManager.prototype.receiveItem = function(item, now) { +this.receiveItem = function(item, now) { // calls result processing var success = this.receivedResult(item, now); ;;; if (success) { @@ -311,7 +334,7 @@ return success; }; -kukit.rm.RequestManager.prototype.timeoutItem = function(item) { +this.timeoutItem = function(item) { /* Time out this item. */ ;;; this.log('timed out request rid [' + item.rid + ']'); // Call the timeout hook on the item @@ -320,7 +343,7 @@ /* request manager notification API */ -kukit.rm.RequestManager.prototype.notifyServer = +this.notifyServer = function(sendHook, url, timeoutHook, timeout, now) { // url is only for the logging // sendHook is the function that actually sends out the request. @@ -338,7 +361,7 @@ // Default value of timeout timeout = this.sendingTimeout; } - var item = new kukit.rm.RequestItem(sendHook, url, timeoutHook, timeout, + var item = new _RequestItem(sendHook, url, timeoutHook, timeout, now); // Start timing the item immediately this.timerQueue.push(item); @@ -353,7 +376,10 @@ } }; -kukit.rm.RequestManager.prototype.registerSpinnerEvent = function(func, state) { +this.registerSpinnerEvent = function(func, state) { this.spinnerEvents[state ? 'on' : 'off'].push(func); }; +this.initialize.apply(this, arguments); +}; +}(); /// MODULE END Modified: kukit/kukit.js/trunk/kukit/resourcedata.js ============================================================================== --- kukit/kukit.js/trunk/kukit/resourcedata.js (original) +++ kukit/kukit.js/trunk/kukit/resourcedata.js Thu Jan 10 13:53:49 2008 @@ -19,12 +19,16 @@ /* Supplemental data that the parser builds up */ -kukit.rd = {}; +kukit.rd = new function() { /// MODULE START + +var rd = this; /* * class KssSelector */ -kukit.rd.KssSelector = function(isEvent, css, name, namespace, id, ppid) { +rd.KssSelector = function() { + +this.initialize = function(isEvent, css, name, namespace, id, ppid, eventRegistry) { this.isEventSelector = isEvent; this.isMethodSelector = ! isEvent; // XXX GC row and column are wrong... @@ -66,25 +70,22 @@ this.className = null; this.id = id; this.ppid = ppid; - // finish up the KSS on it - // XXX We should not have this here, because this disables testing the parser - // standalone, without a plugin registry. Original behaviour - // should be reverted instead. - this.setClassName(); + this.setClassName(eventRegistry); }; - -kukit.rd.KssSelector.prototype.setClassName = function() { + +// finish up the KSS on it +this.setClassName = function(eventRegistry) { // Sets up id and class on the selector, based on registration info // XXX GC instead of relying on exceptions, test if key exists try { - this.className = kukit.eventsGlobalRegistry.get( + this.className = eventRegistry.get( this.namespace, this.name).className; } catch(e) { throw kukit.err.parsingError(e.message); } }; -kukit.rd.KssSelector.prototype.prepareId = function() { +this.prepareId = function() { if (this.ppid == null) { if (this.id == null && this.ppid == null) { // singleton for class @@ -96,7 +97,7 @@ } }; -kukit.rd.KssSelector.prototype.getId = function(node) { +this.getId = function(node) { // Gives the id depending on a node. if (this.id) { // Statically set. @@ -122,7 +123,7 @@ } }; -kukit.rd.KssSelector.prototype.getMergeId = function(node) { +this.getMergeId = function(node) { // Gives the merge id depending on a node. if (this.mergeId) { // Statically set. @@ -133,6 +134,8 @@ this.mergeId = kukit.er.makeMergeId(id, this.namespace, this.name); } }; +this.initialize.apply(this, arguments); +}; /* * Kss parameter values. There are two kinds: text and method. @@ -146,40 +149,42 @@ /* * class KssTextValue */ -kukit.rd.KssTextValue = function(txt) { +rd.KssTextValue = function(txt) { // A text parameter in the format // key: value; +this.initialize = function(txt) { this.txt = txt; -}; - -kukit.rd.KssTextValue.prototype.isMethod = false; +} -kukit.rd.KssTextValue.prototype.check = function(registry) { +this.check = function(registry) { // use the IdentityPP provider. this.pprovider = new (registry.get(''))(); }; -kukit.rd.KssTextValue.prototype.evaluate = +this.evaluate = function(node, defaultParameters) { // For normal string parms, this would return the string itself. // In other execution contexts (like kssSelector, for example) this can // do something else. return this.pprovider.eval([this.txt], node, defaultParameters); }; +this.initialize.apply(this, arguments); +}; +rd.KssTextValue.prototype.isMethod = false; /* -* class KssTextValue +* class KssMethodValue */ -kukit.rd.KssMethodValue = function(methodName, args) { +rd.KssMethodValue = function() { + +this.initialize = function(methodName, args) { // A method parameter in the format // key: methodName(v1, v2, ... vn); this.methodName = methodName; this.args = args; }; -kukit.rd.KssMethodValue.prototype.isMethod = true; - -kukit.rd.KssMethodValue.prototype.check = function(registry) { +this.check = function(registry) { // Check syntax var f = registry.get(this.methodName); this.pprovider = new f(); @@ -197,7 +202,7 @@ ;;; this.pprovider.check(this.args); }; -kukit.rd.KssMethodValue.prototype.evaluate = +this.evaluate = function(node, defaultParameters) { // First recursivly evaluate all arguments var newArgs = []; @@ -215,11 +220,15 @@ // return the value return this.pprovider.eval(newArgs, node, defaultParameters); }; +this.initialize.apply(this, arguments); +}; +rd.KssMethodValue.prototype.isMethod = true; + /* * class KssEventValue */ -kukit.rd.KssEventValue = function(methodName, arg) { +rd.KssEventValue = function(methodName, arg) { // A method parameter in the format // methodname(v1) // can be also: @@ -227,19 +236,18 @@ // in both cases, arg is KssTextValue, or KssMethodValue this.methodName = methodName; this.arg = arg; + this.check = function() {}; }; +rd.KssEventValue.prototype.isMethod = true; -kukit.rd.KssEventValue.prototype.isMethod = true; - -kukit.rd.KssEventValue.prototype.check = function() { -}; - -kukit.rd.EventRuleNr = 0; // just a counter +rd.EventRuleNr = 0; // just a counter /* * class EventRule */ -kukit.rd.EventRule = function(kssSelector, parms, actions) { +rd.EventRule = function() { + +this.initialize = function(kssSelector, parms, actions) { if (typeof(parms) == 'undefined') { // called for merging clone // Setting up kssSelector is enough here. Parms and the rest @@ -247,9 +255,9 @@ // on the rule after creation. this.kssSelector = kssSelector; } else { - this.index = kukit.rd.EventRuleNr; + this.index = rd.EventRuleNr; this.mergedIndex = null; - kukit.rd.EventRuleNr = this.index + 1; + rd.EventRuleNr = this.index + 1; ;;; var namestr; ;;; if (kssSelector.namespace) { ;;; namestr = kssSelector.namespace + '-' + kssSelector.name; @@ -265,7 +273,7 @@ } }; -kukit.rd.EventRule.prototype.getIndex = function() { +this.getIndex = function() { if (this.mergedIndex) { return this.mergedIndex; } else { @@ -273,7 +281,7 @@ } }; -kukit.rd.EventRule.prototype.mergeForSelectedNodes = +this.mergeForSelectedNodes = function(ruletable, phase, inNodes) { // Select all nodes within the inNodes for phase==2. @@ -306,7 +314,7 @@ } }; -kukit.rd.EventRule.prototype.getBinderInfo = function(node) { +this.getBinderInfo = function(node) { // Figure out what will be the "state id" for the kss event rule. var id = this.kssSelector.getId(node); // Gets the event instance for the rule. @@ -326,7 +334,7 @@ * */ -kukit.rd.EventRule.prototype.bind = function(node) { +this.bind = function(node) { this.store(node); // Creation of the binding oper var oper = new kukit.op.Oper(); @@ -339,7 +347,7 @@ binderInfo.bindOper(oper); }; -kukit.rd.EventRule.prototype.store = function(node) { +this.store = function(node) { if (node == null) { // node == null is *always* valid, it means "document". return; @@ -350,19 +358,18 @@ } node.kukitEventRules.push(this); }; - /* * Merging event rules */ -kukit.rd.EventRule.prototype.isMerged = function() { +this.isMerged = function() { return (this.mergedIndex != null); }; -kukit.rd.EventRule.prototype.cloneForMerge = function() { +this.cloneForMerge = function() { // Do not touch ourselves, make a new copy for the merge. - var merged = new kukit.rd.EventRule(this.kssSelector); - merged.actions = new kukit.rd.ActionSet(); + var merged = new rd.EventRule(this.kssSelector); + merged.actions = new rd.ActionSet(); merged.parms = {}; merged.mergedIndex = 'X'; merged.merge(this); @@ -370,7 +377,7 @@ return merged; }; -kukit.rd.EventRule.prototype.merge = function(other) { +this.merge = function(other) { ;;; if (! this.isMerged()) { ;;; throw new Error('Cannot merge into a genuine event rule'); ;;; } @@ -398,7 +405,7 @@ ;;; } }; -kukit.rd.EventRule.prototype.mergeIntoDict = function(dict, key) { +this.mergeIntoDict = function(dict, key) { // Merge into the given dictionary by given key. // If possible, store the genuine rule first - if not, // clone it and do a merge. Never destroy the genuine @@ -417,29 +424,34 @@ mergedRule.merge(this); } }; +this.initialize.apply(this, arguments); +}; + /* * class ActionSet */ -kukit.rd.ActionSet = function() { +rd.ActionSet = function() { + +this.initialize = function() { this.content = {}; }; -kukit.rd.ActionSet.prototype.hasActions = function() { +this.hasActions = function() { for (var name in this.content) { return true; } return false; }; -kukit.rd.ActionSet.prototype.merge = function(other) { +this.merge = function(other) { for (var key in other.content) { var action = this.content[key]; var action2 = other.content[key]; if (typeof(action) == 'undefined') { if (action2.type != 'X') { // new action - action = new kukit.rd.Action(); + action = new _Action(); this.content[key] = action; } else { ;;; var msg = 'Cannot action-delete unexisting action, ['; @@ -460,7 +472,7 @@ } }; -kukit.rd.ActionSet.prototype.execute = function(oper) { +this.execute = function(oper) { for (var key in this.content) { var action = this.content[key]; // do not execute error actions! @@ -480,17 +492,17 @@ } }; -kukit.rd.ActionSet.prototype.getOrCreateAction = function(name) { +this.getOrCreateAction = function(name) { var action = this.content[name]; if (typeof(action) == 'undefined') { - action = new kukit.rd.Action(); + action = new _Action(); action.setName(name); this.content[name] = action; } return action; }; -kukit.rd.ActionSet.prototype.getActionOrNull = function(name) { +this.getActionOrNull = function(name) { var action = this.content[name]; if (typeof(action) == 'undefined') { action = null; @@ -498,7 +510,7 @@ return action; }; -kukit.rd.ActionSet.prototype.deleteAction = function(name) { +this.deleteAction = function(name) { var action = this.content[name]; ;;; if (typeof(action) == 'undefined') { ;;; throw new Error('Action [' + name + '] does not exist and cannot be deleted.'); @@ -507,27 +519,31 @@ }; -kukit.rd.ActionSet.prototype.getDefaultAction = function() { +this.getDefaultAction = function() { return this.getActionOrNull('default'); }; -kukit.rd.ActionSet.prototype.getErrorActionFor = function(action) { +this.getErrorActionFor = function(action) { // Get the error action of a given action: or null, // if the action does not define an error handler. return this.getActionOrNull(action.error); }; +this.initialize.apply(this, arguments); +}; /* -* class Action +* class _Action */ -kukit.rd.Action = function() { +var _Action = function() { + +this.initialize = function() { this.name = null; this.error = null; this.parms = {}; this.type = null; }; -kukit.rd.Action.prototype.setName = function(name) { +this.setName = function(name) { ;;; if (this.name != null && this.name != name) { ;;; var msg = 'Error overriding action name [' + this.name; ;;; msg = msg + '] to [' + name + '] (Unmatching action names at merge?)'; @@ -544,7 +560,7 @@ } }; -kukit.rd.Action.prototype.setType = function(type) { +this.setType = function(type) { // Allowed types: // // S = server @@ -573,7 +589,7 @@ this.type = type; }; -kukit.rd.Action.prototype.setError = function(error) { +this.setError = function(error) { ;;; if (this.type != null && this.type != 'S') { ;;; var msg = 'Error setting action error handler on action [' + this.name; ;;; msg = msg + '], this is only allowed on server actions.'; @@ -582,7 +598,7 @@ this.error = error; }; -kukit.rd.Action.prototype.merge = function(other) { +this.merge = function(other) { // Merge to the instance. if (other.name != null) { this.setName(other.name); @@ -599,7 +615,7 @@ } }; -kukit.rd.Action.prototype.makeActionOper = function(oper) { +this.makeActionOper = function(oper) { // Fill the completed action parms, based on the node // The kssXxx parms, reserved for the action, are // handled as appropriate. @@ -630,7 +646,7 @@ return anOper; }; -kukit.rd.Action.prototype.execute = function(oper) { +this.execute = function(oper) { oper = this.makeActionOper(oper); switch (this.type) { case 'D': { @@ -652,31 +668,35 @@ } break; } }; +this.initialize.apply(this, arguments); +}; /* * class LoadActions */ -kukit.rd.LoadActions = function() { +rd.LoadActions = function() { + +this.initialize = function() { this.items = []; }; -kukit.rd.LoadActions.prototype.empty = function() { +this.empty = function() { return (this.size() == 0); }; -kukit.rd.LoadActions.prototype.size = function() { +this.size = function() { return this.items.length; }; -kukit.rd.LoadActions.prototype.push = function(f) { +this.push = function(f) { if (this.items.length >= 100) { throw ('Infinite recursion, stack full'); } this.items.push(f); }; -kukit.rd.LoadActions.prototype.execute = function() { +this.execute = function() { var f = this.items.shift(); if (f) { f(); @@ -686,7 +706,7 @@ } }; -kukit.rd.LoadActions.prototype.executeAll = function() { +this.executeAll = function() { var i = 0; while(true) { var success = this.execute(); @@ -697,7 +717,8 @@ } return i; }; - +this.initialize.apply(this, arguments); +}; /* * class RuleTable @@ -722,14 +743,16 @@ * */ -kukit.rd.RuleTable = function(loadScheduler) { +rd.RuleTable = function() { + +this.initialize = function(loadScheduler) { this.loadScheduler = loadScheduler; this.nodes = {}; }; -kukit.rd.RuleTable.prototype.add = function(node, eventRule) { +this.add = function(node, eventRule) { // look up node - var nodehash = kukit.rd.hashNode(node); + var nodehash = rd.hashNode(node); var nodeval = this.nodes[nodehash]; if (typeof(nodeval) == 'undefined') { nodeval = {'node': node, 'val': {}}; @@ -740,7 +763,7 @@ nodeval.val, eventRule.kssSelector.getMergeId(node)); }; -kukit.rd.RuleTable.prototype.bindall = function(phase) { +this.bindall = function(phase) { // Bind all nodes var counter = 0; for (var nodehash in this.nodes) { @@ -762,10 +785,12 @@ ;;; kukit.logDebug(count + ' load actions executed.'); } }; +this.initialize.apply(this, arguments); +}; -kukit.rd.uid = 0; +rd.uid = 0; -kukit.rd.hashNode = function(node) { +rd.hashNode = function(node) { // It is, generally, not possible to use a node as a key. // However we try to set this right. // We generate an uniqueID on the node. This does not work @@ -776,9 +801,9 @@ } var id = node.uniqueID; if (typeof(id) == 'undefined') { - id = kukit.rd.uid; + id = rd.uid; node.uniqueID = id; - kukit.rd.uid ++; + rd.uid ++; } return id; }; @@ -791,13 +816,15 @@ * Unlike the rule table that is specific for each binding, * this is unique to the page. */ -kukit.rd.MethodTable = function() { +rd.MethodTable = function() { + +this.initialize = function() { this.content = {}; this.content['document'] = {}; this.content['behaviour'] = {}; }; -kukit.rd.MethodTable.prototype.add = function(eventRule) { +this.add = function(eventRule) { // Get the entry by the type which is now at css var category = eventRule.kssSelector.css; var dict = this.content[category]; @@ -809,7 +836,7 @@ eventRule.mergeIntoDict(dict, eventRule.kssSelector.getMergeId()); }; -kukit.rd.MethodTable.prototype.getMergedRule = +this.getMergedRule = function(category, name, binder) { // Returns the rule for a given event instance, @@ -830,7 +857,7 @@ return mergedRule; }; -kukit.rd.MethodTable.prototype.bindall = function() { +this.bindall = function() { // bind document events var documentRules = this.content['document']; var counter = 0; @@ -841,3 +868,7 @@ } ;;; kukit.logDebug(counter + ' rules bound to document.'); }; +this.initialize.apply(this, arguments); +}; + +}(); /// MODULE END Modified: kukit/kukit.js/trunk/kukit/selectorreg.js ============================================================================== --- kukit/kukit.js/trunk/kukit/selectorreg.js (original) +++ kukit/kukit.js/trunk/kukit/selectorreg.js Thu Jan 10 13:53:49 2008 @@ -17,62 +17,74 @@ * 02111-1307, USA. */ -kukit.sr = {}; +kukit.sr = new function() { /// MODULE START + +var sr = this; // Registry of the pprovider functions for selecting -kukit.sr.pproviderSelRegistry = new kukit.pr.ValueProviderRegistry(); +sr.pproviderSelRegistry = new kukit.pr.ValueProviderRegistry(); +/* +* class _AnyPP +* +* This will provide an arbitrary selector, and is designed to +* be used with the makeAnyPP factory function. +* +*/ +var _AnyPP = function() { -// this will provide an arbitrary selector, and is designed to -// be used with the makeAnyPP factory function. -kukit.sr.AnyPP = function() {}; -kukit.sr.AnyPP.prototype = { - check: function(args) { - // check does not need to be used here actually. -;;; if (args.length != 1) { -;;; throw new Error('internal error, xxxselector() needs 1 argument'); -;;; } - }, - eval: function(args, node, defaultParameters) { - var f = kukit.selectorTypesGlobalRegistry.get(this.selector_type); - // We don't have orignode if we evaluate from here, consequently - // the orignode parameter cannot be used from selectors. We pass - // node just to be sure... - return f(args[0], node, defaultParameters, node); - } +this.check = function(args) { + // check does not need to be used here actually. +;;; if (args.length != 1) { +;;; throw new Error('internal error, xxxselector() needs 1 argument'); +;;; } +}; +this.eval = function(args, node, defaultParameters) { + var f = kukit.selectorTypesGlobalRegistry.get(this.selector_type); + // We don't have orignode if we evaluate from here, consequently + // the orignode parameter cannot be used from selectors. We pass + // node just to be sure... + return f(args[0], node, defaultParameters, node); }; -kukit.sr.pproviderSelRegistry.register('', kukit.sr.AnyPP); +}; + +sr.pproviderSelRegistry.register('', _AnyPP); -kukit.sr.makeAnyPP = function(selector_type) { +sr.makeAnyPP = function(selector_type) { var pp = function () {}; - pp.prototype.eval = kukit.sr.AnyPP.prototype.eval; -;;; pp.prototype.check = kukit.sr.AnyPP.prototype.check; + pp.prototype = new _AnyPP(); pp.prototype.selector_type = selector_type; return pp; }; -// this can be used to pass a node programmatically -kukit.sr.PassnodePP = function() {}; -kukit.sr.PassnodePP.prototype = { - check: function(args) { -;;; if (args.length != 1) { -;;; throw new Error('passnode selector method needs 1 argument'); -;;; } - }, - eval: function(args, node, defaultParameters) { - var value = defaultParameters[args[0]]; - if (typeof(value) == 'undefined') { - // notfound arguments will get null -;;; kukit.E = 'Nonexistent default parm "'+ key +'"'; - throw new Error(kukit.E); - } - nodes = [value]; - return nodes; +/* +* class _AnyPP +* +* This can be used to pass a node programmatically +* +*/ +var _PassnodePP = function() { + +this.check = function(args) { +;;; if (args.length != 1) { +;;; throw new Error('passnode selector method needs 1 argument'); +;;; } +}; +this.eval = function(args, node, defaultParameters) { + var value = defaultParameters[args[0]]; + if (typeof(value) == 'undefined') { + // notfound arguments will get null +;;; kukit.E = 'Nonexistent default parm "'+ key +'"'; + throw new Error(kukit.E); } + nodes = [value]; + return nodes; +}; + }; -kukit.sr.pproviderSelRegistry.register('passnode', kukit.sr.PassnodePP); +sr.pproviderSelRegistry.register('passnode', _PassnodePP); /* @@ -85,13 +97,13 @@ * kukit.selectorTypesGlobalRegistry.register(name, func); * */ -kukit.sr.SelectorTypeRegistry = function () { +var _SelectorTypeRegistry = function () { + +this.initialize = function() { this.mapping = {}; }; -kukit.sr.SelectorTypeRegistry.prototype.defaultSelectorType = 'css'; - -kukit.sr.SelectorTypeRegistry.prototype.register = function(name, func) { +this.register = function(name, func) { if (typeof(func) == 'undefined') { throw new Error('Func is mandatory.'); } @@ -102,11 +114,11 @@ ;;; } this.mapping[name] = func; // Also register the selector param provider - var pp = kukit.sr.makeAnyPP(name); - kukit.sr.pproviderSelRegistry.register(name, pp); + var pp = sr.makeAnyPP(name); + sr.pproviderSelRegistry.register(name, pp); }; -kukit.sr.SelectorTypeRegistry.prototype.get = function(name) { +this.get = function(name) { if (! name) { // if name is null or undefined or '', // we use the default type. @@ -118,8 +130,13 @@ ;;; } return result; }; +this.initialize.apply(this, arguments); +}; -kukit.selectorTypesGlobalRegistry = new kukit.sr.SelectorTypeRegistry(); +_SelectorTypeRegistry.prototype.defaultSelectorType = 'css'; + + +kukit.selectorTypesGlobalRegistry = new _SelectorTypeRegistry(); kukit.selectorTypesGlobalRegistry.register('htmlid', function(expr, node) { var nodes = []; @@ -166,3 +183,5 @@ } return results; }); + +}(); /// MODULE END Modified: kukit/kukit.js/trunk/kukit/serveraction.js ============================================================================== --- kukit/kukit.js/trunk/kukit/serveraction.js (original) +++ kukit/kukit.js/trunk/kukit/serveraction.js Thu Jan 10 13:53:49 2008 @@ -17,19 +17,23 @@ * 02111-1307, USA. */ -kukit.sa = {}; +kukit.sa = new function() { /// MODULE START -kukit.sa.ServerAction = function(name, oper) { +var sa = this; + +sa.ServerAction = function() { + +this.initialize = function(name, oper) { + this.oper = oper; this.url = oper.kssParms.kssUrl; if (typeof(this.url) == 'undefined') { this.url = name; } this.url = this.calculateAbsoluteURL(this.url); - this.oper = oper; this.notifyServer(); }; -kukit.sa.ServerAction.prototype.calculateAbsoluteURL = function(url) { +this.calculateAbsoluteURL = function(url) { // // If the url is an absolute path, it is used // @@ -50,7 +54,7 @@ }; // Backparameters can be used on command execution. -kukit.sa.ServerAction.prototype.notifyServer = function() { +this.notifyServer = function() { var self = this; var sendHook = function(queueItem) { // store the queue reception on the oper @@ -65,7 +69,7 @@ kukit.engine.requestManager.notifyServer(sendHook, this.url, timeoutHook); }; -kukit.sa.ServerAction.prototype.reallyNotifyServer = function() { +this.reallyNotifyServer = function() { // make a deferred callback var domDoc = new XMLHttpRequest(); var self = this; @@ -100,7 +104,7 @@ domDoc.send(encoded); }; -kukit.sa.ServerAction.prototype.notifyServer_done = function(domDoc) { +this.notifyServer_done = function(domDoc) { ;;; var msg = 'Request readyState = ' + domDoc.readyState + '.'; ;;; kukit.logDebug(msg); if (domDoc.readyState == 4) { @@ -133,7 +137,7 @@ } }; -kukit.sa.ServerAction.prototype.processResult = function(domDoc) { +this.processResult = function(domDoc) { // checking various dom process errors, and get the commands part var dom; var commandstags = []; @@ -193,10 +197,12 @@ // One or more valid commands to parse var command_processor = new kukit.cp.CommandProcessor(); command_processor.parseCommands(commands, domDoc); + kukit.engine.beginSetupEventsCollection(); command_processor.executeCommands(this.oper); + kukit.engine.finishSetupEventsCollection(); }; -kukit.sa.ServerAction.prototype.processError = function(errorcommand) { +this.processError = function(errorcommand) { var error_action = null; if (this.oper.eventRule) { var error_action = this.oper.eventRule.actions.getErrorActionFor( @@ -235,4 +241,7 @@ // TODO figure out something? } }; +this.initialize.apply(this, arguments); +}; +}(); /// MODULE END Modified: kukit/kukit.js/trunk/kukit/tokenizer.js ============================================================================== --- kukit/kukit.js/trunk/kukit/tokenizer.js (original) +++ kukit/kukit.js/trunk/kukit/tokenizer.js Thu Jan 10 13:53:49 2008 @@ -19,48 +19,50 @@ /* Simple but effective tokenizing parser engine */ -kukit.tk = {}; + +kukit.tk = new function() { /// MODULE START + +var tk = this; /* * class _TokenBase */ -kukit.tk._TokenBase = function() { -}; +tk._TokenBase = function() { -kukit.tk._TokenBase.prototype.emitError = function(msg) { +this.emitError = function(msg) { // Use the start position of the token for the error report. ;;; var marker = this.cursor.makeMarker(this.startpos); ;;; throw kukit.err.parsingError(msg, marker); throw new Error(kukit.E); }; -kukit.tk._TokenBase.prototype.updateFinished = function() { +this.updateFinished = function() { if (! this.finished && this.cursor.text.length == this.cursor.pos) { if (this.isTopLevelParser) { this.finished = true; } else { ;;; kukit.E = 'Unexpected EOF.'; this.emitError(kukit.E); - } - } + }; + }; +}; + }; /* * class _ParserBase */ -kukit.tk._ParserBase = function() { -}; +tk._ParserBase = function() { -kukit.tk._ParserBase.prototype = new kukit.tk._TokenBase; - -kukit.tk._ParserBase.prototype.emitAndReturn = function(token) { +this.emitAndReturn = function(token) { // handle return to the next level this.finished = true; return token; }; -kukit.tk._ParserBase.prototype.nextStep = function(table) { +this.nextStep = function() { + var table = this.table var cursor = this.cursor; // Search for symbol according to table. var best_pos = cursor.text.length; @@ -70,31 +72,31 @@ if (pos != -1 && pos < best_pos) { best_pos = pos; best_symbol = symbol; - } - } + }; + }; // eat up till the symbol found (of EOF) if (best_pos > cursor.pos) { - this.result.push(new kukit.tk.Fraction(cursor, best_pos)); + this.result.push(new tk.Fraction(cursor, best_pos)); cursor.pos = best_pos; - } + }; if (best_symbol) { // found a symbol, handle that // make the token and push it - var tokens = eval(table[best_symbol]); + var tokens = table[best_symbol].call(this); if (typeof(tokens) != 'undefined') { if (typeof(tokens.length) == 'undefined') { tokens = [tokens]; - } + }; for (var i=0; i b) { @@ -309,11 +315,11 @@ } }; -ut.SortedQueue.prototype.reset = function() { +this.reset = function() { this.elements = new Array(); }; -ut.SortedQueue.prototype.push = function(obj) { +this.push = function(obj) { // Find the position of the object. var i = 0; var length = this.elements.length; @@ -324,31 +330,33 @@ this.elements.splice(i, 0, obj); }; -ut.SortedQueue.prototype.pop = function() { +this.pop = function() { // takes minimal element return this.elements.shift(); }; -ut.SortedQueue.prototype.popn = function(n) { +this.popn = function(n) { // takes first n minimal element return this.elements.splice(0, n); }; -ut.SortedQueue.prototype.empty = function() { +this.empty = function() { return ! this.elements.length; }; -ut.SortedQueue.prototype.size = function() { +this.size = function() { return this.elements.length; }; -ut.SortedQueue.prototype.get = function(n) { +this.get = function(n) { return this.elements[n]; }; -ut.SortedQueue.prototype.front = function() { +this.front = function() { return this.elements[0]; }; +this.initialize.apply(this, arguments); +}; ut.evalBool = function(value, errname) { if (value == 'true' || value == 'True' || value == '1') { @@ -396,7 +404,9 @@ * * for repeating or one time timing */ -ut.TimerCounter = function(delay, func, restart) { +ut.TimerCounter = function() { + +this.initialize = function(delay, func, restart) { this.delay = delay; this.func = func; if (typeof(restart) == 'undefined') { @@ -406,7 +416,7 @@ this.timer = null; }; -ut.TimerCounter.prototype.start = function() { +this.start = function() { if (this.timer) { ;;; kukit.E = 'Timer already started.'; @@ -419,7 +429,7 @@ this.timer = setTimeout(func, this.delay); }; -ut.TimerCounter.prototype.timeout = function() { +this.timeout = function() { // Call the event action this.func(); // Restart the timer @@ -429,24 +439,28 @@ } }; -ut.TimerCounter.prototype.clear = function() { +this.clear = function() { if (this.timer) { window.clearTimeout(this.timer); this.timer = null; } this.restart = false; }; +this.initialize.apply(this, arguments); +}; /* * class Scheduler */ -ut.Scheduler = function(func) { +ut.Scheduler = function() { + +this.initialize = function(func) { this.func = func; this.timer = null; this.nextWake = null; }; -ut.Scheduler.prototype.setNextWake = function(ts) { +this.setNextWake = function(ts) { // Sets wakeup time, null clears if (this.nextWake) { this.clear(); @@ -468,7 +482,7 @@ } }; -ut.Scheduler.prototype.setNextWakeAtLeast = function(ts) { +this.setNextWakeAtLeast = function(ts) { // Sets wakeup time, unless it would wake up later than the // currently set timeout. Null clears the timer. if (! ts || ! this.nextWake || ts < this.nextWake) { @@ -479,7 +493,7 @@ } }; -ut.Scheduler.prototype.timeout = function() { +this.timeout = function() { // clear the timer this.timer = null; this.nextWake = null; @@ -487,14 +501,15 @@ this.func(); }; - -ut.Scheduler.prototype.clear = function() { +this.clear = function() { if (this.nextWake) { window.clearTimeout(this.timer); this.timer = null; this.nextWake = null; } }; +this.initialize.apply(this, arguments); +}; /* * class SerializeScheduler @@ -502,21 +517,23 @@ * Scheduler for serializing bind and load procedures */ ut.SerializeScheduler = function() { + +this.initialize = function() { this.items = []; this.lock = false; }; -ut.SerializeScheduler.prototype.addPre = function(func, remark) { +this.addPre = function(func, remark) { this.items.push({func: func, remark: remark}); this.execute(); }; -ut.SerializeScheduler.prototype.addPost = function(func, remark) { +this.addPost = function(func, remark) { this.items.unshift({func: func, remark: remark}); this.execute(); }; -ut.SerializeScheduler.prototype.execute = function() { +this.execute = function() { if (! this.lock) { this.lock = true; while (true) { @@ -540,6 +557,8 @@ this.lock = false; } }; +this.initialize.apply(this, arguments); +}; /* Browser event binding */ @@ -563,21 +582,35 @@ /* collecting keys-values into a dict or into a tuple list */ +/* +* class DictCollector +*/ ut.DictCollector = function() { + +this.initialize = function() { this.result = {}; }; -ut.DictCollector.prototype.add = function(key, value) { +this.add = function(key, value) { this.result[key] = value; }; +this.initialize.apply(this, arguments); +}; +/* +* class TupleCollector +*/ ut.TupleCollector = function() { + +this.initialize = function() { this.result = []; }; -ut.TupleCollector.prototype.add = function(key, value) { +this.add = function(key, value) { this.result.push([key, value]); }; +this.initialize.apply(this, arguments); +}; }(); /// MODULE END 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 Thu Jan 10 13:53:49 2008 @@ -45,14 +45,14 @@ expired.push(item); }; // 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); + q = new kukit.rm.TestTimerQueue(cbe); + var i1 = new kukit.rm.TestRequestItem(null, 1, null, 10000, 1000); q.push(i1); - var i2 = new kukit.rm.RequestItem(null, 2, null, 10000, 2000); + var i2 = new kukit.rm.TestRequestItem(null, 2, null, 10000, 2000); q.push(i2); - var i3 = new kukit.rm.RequestItem(null, 3, null, 10000, 3000); + var i3 = new kukit.rm.TestRequestItem(null, 3, null, 10000, 3000); q.push(i3); - var i4 = new kukit.rm.RequestItem(null, 4, null, 10000, 4000); + var i4 = new kukit.rm.TestRequestItem(null, 4, null, 10000, 4000); q.push(i4); this.assertEquals(q.count, 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(2, null, kukit.DummyScheduler); this.assertRmQueues(rm, 0, 0); // queues var sent = []; @@ -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(2, null, kukit.DummyScheduler); this.assertRmQueues(rm, 0, 0); // queues var sent = []; @@ -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(2, null, kukit.DummyScheduler); this.assertRmQueues(rm, 0, 0); // queues var sent = []; @@ -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(2, null, kukit.DummyScheduler); this.assertRmQueues(rm, 0, 0); // queues var sent = []; @@ -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(2, null, kukit.DummyScheduler); this.assertRmQueues(rm, 0, 0); // queues var sent = []; @@ -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(2, null, kukit.DummyScheduler); this.assertRmQueues(rm, 0, 0); // queues var sent = []; 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 Thu Jan 10 13:53:49 2008 @@ -77,6 +77,7 @@ this.name = 'kukit.TokenizerTestCase'; this.setUp = function() { + this.Dummy = function() {}; }; this.testException = function() { @@ -154,9 +155,11 @@ kukit.tk.openBracket = kukit.tk.mkToken('openBracket', '['); var pf = kukit.tk.mkParser('block', { - '[': 'this.emitAndReturn(new kukit.tk.openBracket(this.cursor))', - '{': 'new kukit.tk.openBrace(this.cursor)' - }); + '[': function() {return this.emitAndReturn(new kukit.tk.openBracket(this.cursor));}, + '{': function() {return new kukit.tk.openBrace(this.cursor);} + }, + this.Dummy + ); var parser = new pf(cursor, null, true); this.assertEquals(parser.finished, true); @@ -191,14 +194,18 @@ kukit.tk.wrappedBracket = kukit.tk.mkToken('wrappedBracket', '['); kukit.tk.global = kukit.tk.mkParser('global', { - '[': 'new kukit.tk.openBracket(this.cursor)', - '{': 'new kukit.tk.inside(this.cursor, kukit.tk.openBrace)' - }); + '[': function() {return new kukit.tk.openBracket(this.cursor);}, + '{': function() {return new kukit.tk.inside(this.cursor, kukit.tk.openBrace);} + }, + this.Dummy + ); kukit.tk.inside = kukit.tk.mkParser('inside', { - '[': 'new kukit.tk.wrappedBracket(this.cursor)', - '}': 'this.emitAndReturn(new kukit.tk.closeBrace(this.cursor))' - }); + '[': function() {return new kukit.tk.wrappedBracket(this.cursor);}, + '}': function() {return this.emitAndReturn(new kukit.tk.closeBrace(this.cursor));} + }, + this.Dummy + ); var parser = new kukit.tk.global(cursor, null, true); //this.printDebug(parser); @@ -258,37 +265,44 @@ kukit.tk.backslash = kukit.tk.mkToken('backslash', "\\"); kukit.tk.global = kukit.tk.mkParser('global', { - "'": 'new kukit.tk.string(this.cursor, kukit.tk.quote)' - }); - + "'": function() {return new kukit.tk.string(this.cursor, kukit.tk.quote);} + }, + this.Dummy + ); + var _String = function() { + this.process = function() { + // collect up the value of the string, omitting the quotes + this.txt = ''; + for (var i=1; i Author: gotcha Date: Thu Jan 10 18:40:10 2008 New Revision: 50489 Added: kukit/kss.core/branch/improve-demos/ - copied from r50488, kukit/kss.core/trunk/ Log: let's make demos we can be proud of From gotcha at codespeak.net Thu Jan 10 18:40:39 2008 From: gotcha at codespeak.net (gotcha at codespeak.net) Date: Thu, 10 Jan 2008 18:40:39 +0100 (CET) Subject: [KSS-checkins] r50490 - kukit/kss.demo/branch/improve-demos Message-ID: <20080110174039.0C4061684FC@codespeak.net> Author: gotcha Date: Thu Jan 10 18:40:38 2008 New Revision: 50490 Added: kukit/kss.demo/branch/improve-demos/ - copied from r50489, kukit/kss.demo/trunk/ Log: let's make demos we can be proud of From gotcha at codespeak.net Thu Jan 10 18:41:09 2008 From: gotcha at codespeak.net (gotcha at codespeak.net) Date: Thu, 10 Jan 2008 18:41:09 +0100 (CET) Subject: [KSS-checkins] r50491 - kukit/kukit.js/branch/improve-demos Message-ID: <20080110174109.73E15168506@codespeak.net> Author: gotcha Date: Thu Jan 10 18:41:09 2008 New Revision: 50491 Added: kukit/kukit.js/branch/improve-demos/ - copied from r50490, kukit/kukit.js/trunk/ Log: let's make demos we can be proud of From gotcha at codespeak.net Thu Jan 10 18:45:10 2008 From: gotcha at codespeak.net (gotcha at codespeak.net) Date: Thu, 10 Jan 2008 18:45:10 +0100 (CET) Subject: [KSS-checkins] r50492 - in kukit/kss.core/branch/improve-demos/kss/core: . tests Message-ID: <20080110174510.10B2C1684F4@codespeak.net> Author: gotcha Date: Thu Jan 10 18:45:09 2008 New Revision: 50492 Modified: kukit/kss.core/branch/improve-demos/kss/core/ (props changed) kukit/kss.core/branch/improve-demos/kss/core/EXTERNALS.TXT kukit/kss.core/branch/improve-demos/kss/core/tests/ecmaview.py Log: remove content type specification to make it compatible with macros Modified: kukit/kss.core/branch/improve-demos/kss/core/EXTERNALS.TXT ============================================================================== --- kukit/kss.core/branch/improve-demos/kss/core/EXTERNALS.TXT (original) +++ kukit/kss.core/branch/improve-demos/kss/core/EXTERNALS.TXT Thu Jan 10 18:45:09 2008 @@ -5,4 +5,4 @@ # You can update your working dir by: # svn propset svn:externals -F EXTERNALS.TXT . # -kukit http://codespeak.net/svn/kukit/kukit.js/trunk/ +kukit http://codespeak.net/svn/kukit/kukit.js/branch/improve-demos Modified: kukit/kss.core/branch/improve-demos/kss/core/tests/ecmaview.py ============================================================================== --- kukit/kss.core/branch/improve-demos/kss/core/tests/ecmaview.py (original) +++ kukit/kss.core/branch/improve-demos/kss/core/tests/ecmaview.py Thu Jan 10 18:45:09 2008 @@ -84,7 +84,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') # The next is only necessary on Zope (<=) 2.9, # provides a docstring to the method From gotcha at codespeak.net Thu Jan 10 18:46:11 2008 From: gotcha at codespeak.net (gotcha at codespeak.net) Date: Thu, 10 Jan 2008 18:46:11 +0100 (CET) Subject: [KSS-checkins] r50493 - kukit/kukit.js/branch/improve-demos/tests Message-ID: <20080110174611.959E71684F4@codespeak.net> Author: gotcha Date: Thu Jan 10 18:46:11 2008 New Revision: 50493 Modified: kukit/kukit.js/branch/improve-demos/tests/runner.html Log: use kss_mode macro Modified: kukit/kukit.js/branch/improve-demos/tests/runner.html ============================================================================== --- kukit/kukit.js/branch/improve-demos/tests/runner.html (original) +++ kukit/kukit.js/branch/improve-demos/tests/runner.html Thu Jan 10 18:46:11 2008 @@ -93,17 +93,7 @@ KSS ECMAScript Unit Tests -

    - Kss is in - development - production - - mode.
    -
    Control development mode -

    +

    header

    This page is the entry to the ECMAScript Unit Tests. From gotcha at codespeak.net Thu Jan 10 18:47:52 2008 From: gotcha at codespeak.net (gotcha at codespeak.net) Date: Thu, 10 Jan 2008 18:47:52 +0100 (CET) Subject: [KSS-checkins] r50494 - kukit/kss.demo/branch/improve-demos/kss/demo/browser Message-ID: <20080110174752.7856B1684F4@codespeak.net> Author: gotcha Date: Thu Jan 10 18:47:51 2008 New Revision: 50494 Modified: kukit/kss.demo/branch/improve-demos/kss/demo/browser/configure.zcml kukit/kss.demo/branch/improve-demos/kss/demo/browser/kss_demo_index.pt kukit/kss.demo/branch/improve-demos/kss/demo/browser/registry.py Log: search and find zuite object Modified: kukit/kss.demo/branch/improve-demos/kss/demo/browser/configure.zcml ============================================================================== --- kukit/kss.demo/branch/improve-demos/kss/demo/browser/configure.zcml (original) +++ kukit/kss.demo/branch/improve-demos/kss/demo/browser/configure.zcml Thu Jan 10 18:47:51 2008 @@ -58,7 +58,7 @@ for="kss.demo.interfaces.ISimpleContent" name="kss_demo_registry" class=".registry.KSSDemoRegistryView" - allowed_attributes="getSortedDemos getDemoGroups getSeleniumTests" + allowed_attributes="getSortedDemos getDemoGroups getSeleniumTests getZuite" permission="zope.View" /> KSS demos

    Kss mode

    Tests

    -
      -
    • Run all ECMA unittests
    • -
    • Link to Zelenium object: -
      - - -
      -
    • + -

      - Zelenium object link must be an absolute path from the domain root, - or a relative path from the demo SimpleContent's parent. -

      Core plugin

      Modified: kukit/kss.demo/branch/improve-demos/kss/demo/browser/registry.py ============================================================================== --- kukit/kss.demo/branch/improve-demos/kss/demo/browser/registry.py (original) +++ kukit/kss.demo/branch/improve-demos/kss/demo/browser/registry.py Thu Jan 10 18:47:51 2008 @@ -107,12 +107,22 @@ self.request.response.setHeader('Content-type', 'text/html;charset=utf-8') return file(filename).read() - def getZuiteHomePage(self, path): + def getZuiteHomePage(self): """Redirects to the Zuite home page, Zuite object is found from path.""" - zuite = self.context.aq_inner.aq_parent.restrictedTraverse(path) + zuite = self.getZuite() html = "%s/core/TestRunner.html?test=%s/suite.html" % (zuite.absolute_url(), self.context.absolute_url()) return self.request.response.redirect(html) + def getZuite(self): + """Finds a zuite in the same directory or under""" + if not hasattr(self, 'zuites'): + container = self.context.aq_inner.aq_parent + self.zuites = self.context.ZopeFind(container, obj_metatypes=['Zuite'], search_sub=1) + if self.zuites: + return self.zuites[0][1] + else: + return None + class KSSDemoRegistryAdminView(BrowserView): """Things that only admin should do""" implements(IBrowserPublisher) From gotcha at codespeak.net Thu Jan 10 18:49:55 2008 From: gotcha at codespeak.net (gotcha at codespeak.net) Date: Thu, 10 Jan 2008 18:49:55 +0100 (CET) Subject: [KSS-checkins] r50495 - kukit/kss.buildout/branch/improve-demos Message-ID: <20080110174955.075931684F1@codespeak.net> Author: gotcha Date: Thu Jan 10 18:49:54 2008 New Revision: 50495 Added: kukit/kss.buildout/branch/improve-demos/ - copied from r50494, kukit/kss.buildout/trunk/ Log: let's make demos we can be proud of From gotcha at codespeak.net Thu Jan 10 18:52:44 2008 From: gotcha at codespeak.net (gotcha at codespeak.net) Date: Thu, 10 Jan 2008 18:52:44 +0100 (CET) Subject: [KSS-checkins] r50496 - kukit/kss.buildout/branch/improve-demos/src Message-ID: <20080110175244.030A81684FC@codespeak.net> Author: gotcha Date: Thu Jan 10 18:52:44 2008 New Revision: 50496 Modified: kukit/kss.buildout/branch/improve-demos/src/ (props changed) kukit/kss.buildout/branch/improve-demos/src/EXTERNALS.txt Log: update externals Modified: kukit/kss.buildout/branch/improve-demos/src/EXTERNALS.txt ============================================================================== --- kukit/kss.buildout/branch/improve-demos/src/EXTERNALS.txt (original) +++ kukit/kss.buildout/branch/improve-demos/src/EXTERNALS.txt Thu Jan 10 18:52:44 2008 @@ -1,5 +1,5 @@ # created by: svn propset svn:externals -F ./EXTERNALS.TXT . -kss.core https://codespeak.net/svn/kukit/kss.core/trunk -kss.demo https://codespeak.net/svn/kukit/kss.demo/trunk +kss.core https://codespeak.net/svn/kukit/kss.core/branch/improve-demos +kss.demo https://codespeak.net/svn/kukit/kss.demo/branch/improve-demos From kukit-checkins at codespeak.net Sun Jan 13 12:42:54 2008 From: kukit-checkins at codespeak.net (kukit-checkins at codespeak.net) Date: Sun, 13 Jan 2008 12:42:54 +0100 (CET) Subject: [KSS-checkins] Save Up To %62 Message-ID: <20080113134250.5765.qmail@ew6wwhihi6.adsl.datanet.hu> An HTML attachment was scrubbed... URL: http://codespeak.net/pipermail/kukit-checkins/attachments/20080113/53d7b144/attachment.htm From gotcha at codespeak.net Sat Jan 19 10:31:44 2008 From: gotcha at codespeak.net (gotcha at codespeak.net) Date: Sat, 19 Jan 2008 10:31:44 +0100 (CET) Subject: [KSS-checkins] r50769 - kukit/kss.core/branch/improve-demos/kss/core/plugins/core/demo Message-ID: <20080119093144.C7628168576@codespeak.net> Author: gotcha Date: Sat Jan 19 10:31:42 2008 New Revision: 50769 Removed: kukit/kss.core/branch/improve-demos/kss/core/plugins/core/demo/config.py Log: remove unused file (left over from a previous merge ?) Deleted: /kukit/kss.core/branch/improve-demos/kss/core/plugins/core/demo/config.py ============================================================================== --- /kukit/kss.core/branch/improve-demos/kss/core/plugins/core/demo/config.py Sat Jan 19 10:31:42 2008 +++ (empty file) @@ -1,39 +0,0 @@ - -from kss.base.plugin import Plugin -from kss.demo.resource import ( - KSSDemo, - KSSSeleniumTestDirectory, - ) - -class CoreDemos(Plugin): - - zope_demos = ( - KSSDemo('', '', "basic_commands.html", "Change tag content"), - KSSDemo('', '', "two_selects.html", "Two selects"), - KSSDemo('', '', "autoupdate.html", "Auto update"), - KSSDemo('', '', "inline_edit.html", "Inline edit"), - KSSDemo('', '', "cancel_submit.html", "Cancel Submit Click"), - KSSDemo('', '', "tree.html", "Tree"), - KSSDemo('', '', "more_selectors.html", "More complex selectors"), - KSSDemo('', '', "two_select_revisited.html", "Master-slave selects revisited"), - KSSDemo('', '', "form_submit.html", "Form submit"), - KSSDemo('', '', "error_handling.html", "Error handling"), - KSSDemo('', '', "preventdefault.html", "Preventdefault (a.k.a. Safari workarounds)"), - KSSDemo('', '', "html_inserts.html", "HTML insertions (Change tag content returns)"), - KSSDemo('', '', "client-server-protocol", "Client server protocol"), - KSSDemo('', 'Parameter functions', 'pf_forms.html', 'Forms'), - KSSDemo('', 'Selectors', 'selectors.html', 'Parent node selector'), - KSSDemo('', 'Core syntax', "kss_selector_param.html", "Kss selector parameters"), - KSSDemo('', 'Core syntax', "kss_url_param.html", "Kss url parameters"), - KSSDemo('', 'Core events', "kss_evt_preventbubbling.html", "Prevent bubbling KSS event parameter"), - KSSDemo('', 'Core events', "kss_keyevents.html", "Key events"), - KSSDemo('', 'Commands/Actions', "ca_focus.html", "Focus"), - KSSDemo('', 'Commands/Actions', "actions.html", "Toggle case action"), - # XXX this should go to the other plugin wuth all its stuff - KSSDemo('Effects', '', "effects.html", "Effects"), - ) - - # directories are relative from the location of this .py file - zope_selenium_testsuites = ( - KSSSeleniumTestDirectory('selenium_tests'), - ) From gotcha at codespeak.net Sun Jan 20 10:31:14 2008 From: gotcha at codespeak.net (gotcha at codespeak.net) Date: Sun, 20 Jan 2008 10:31:14 +0100 (CET) Subject: [KSS-checkins] r50792 - kukit/kss.core/branch/improve-demos/kss/core/plugins/core/demo Message-ID: <20080120093114.3CA87168554@codespeak.net> Author: gotcha Date: Sun Jan 20 10:31:13 2008 New Revision: 50792 Added: kukit/kss.core/branch/improve-demos/kss/core/plugins/core/demo/config.py - copied, changed from r50768, kukit/kss.core/branch/improve-demos/kss/core/plugins/core/demo/config.py Log: put file back with comment why it should be kept Copied: kukit/kss.core/branch/improve-demos/kss/core/plugins/core/demo/config.py (from r50768, kukit/kss.core/branch/improve-demos/kss/core/plugins/core/demo/config.py) ============================================================================== --- kukit/kss.core/branch/improve-demos/kss/core/plugins/core/demo/config.py (original) +++ kukit/kss.core/branch/improve-demos/kss/core/plugins/core/demo/config.py Sun Jan 20 10:31:13 2008 @@ -5,6 +5,14 @@ KSSSeleniumTestDirectory, ) + +################## +# +# +# THIS MODULE IS USED BY KSS.ZOPE DURING TRANSITION FROM KSS.CORE TO KSS.ZOPE +# +# +################## class CoreDemos(Plugin): zope_demos = ( From jone at codespeak.net Sun Jan 20 10:46:33 2008 From: jone at codespeak.net (jone at codespeak.net) Date: Sun, 20 Jan 2008 10:46:33 +0100 (CET) Subject: [KSS-checkins] r50793 - kukit/kukit.js/branch/improve-demos/kukit Message-ID: <20080120094633.43FEB168554@codespeak.net> Author: jone Date: Sun Jan 20 10:46:31 2008 New Revision: 50793 Modified: kukit/kukit.js/branch/improve-demos/kukit/dom.js kukit/kukit.js/branch/improve-demos/kukit/plugin.js Log: Fix for tbody-insertion in firefox Modified: kukit/kukit.js/branch/improve-demos/kukit/dom.js ============================================================================== --- kukit/kukit.js/branch/improve-demos/kukit/dom.js (original) +++ kukit/kukit.js/branch/improve-demos/kukit/dom.js Sun Jan 20 10:46:31 2008 @@ -56,9 +56,16 @@ Sarissa.clearChildNodes(node); }; -dom.parseHTMLNodes = function(txt){ - var node = document.createElement('div'); - node.innerHTML = txt; +dom.parseHTMLNodes = function(txt, targetNode){ + var tagName = targetNode.tagName; + var tbody = false; + if(tagName.toLowerCase()=='tbody') { + // special treatment of tbody because of ff2 behaviour + var node = dom.parseHTMLNodesForTBody(txt); + }?else { + var node = document.createElement(tagName); + node.innerHTML = txt; + } var resultNodes = []; for (var i=0; i'; + } + return node.firstChild; +}; + /* * really the query should start from the document root, but * limited to inNodes subtrees! Modified: kukit/kukit.js/branch/improve-demos/kukit/plugin.js ============================================================================== --- kukit/kukit.js/branch/improve-demos/kukit/plugin.js (original) +++ kukit/kukit.js/branch/improve-demos/kukit/plugin.js Sun Jan 20 10:46:31 2008 @@ -685,11 +685,11 @@ oper.evaluateParameters(['html'], {'withKssSetup':true}); oper.evalBool('withKssSetup'); var node = oper.node; - var elements = kukit.dom.parseHTMLNodes(oper.parms.html); + var parentNode = node.parentNode; + var elements = kukit.dom.parseHTMLNodes(oper.parms.html, parentNode); var length = elements.length; ;;; kukit.logDebug(length + ' nodes inserted.'); if (length > 0) { - var parentNode = node.parentNode; var insertedNodes = []; // insert the last node var next = elements[length-1]; @@ -759,8 +759,8 @@ ;;; oper.componentName = '[insertHTMLAfter] action'; oper.evaluateParameters(['html'], {'withKssSetup':true}); oper.evalBool('withKssSetup'); - var content = kukit.dom.parseHTMLNodes(oper.parms.html); var parentNode = oper.node.parentNode; + var content = kukit.dom.parseHTMLNodes(oper.parms.html, parentNode); var toNode = kukit.dom.getNextSiblingTag(oper.node); if (toNode == null) { kukit.dom.appendChildren(content, parentNode); @@ -780,9 +780,9 @@ ;;; oper.componentName = '[insertHTMLBefore] action'; oper.evaluateParameters(['html'], {'withKssSetup':true}); oper.evalBool('withKssSetup'); - var content = kukit.dom.parseHTMLNodes(oper.parms.html); var toNode = oper.node; var parentNode = toNode.parentNode; + var content = kukit.dom.parseHTMLNodes(oper.parms.html, parentNode); kukit.dom.insertBefore(content, parentNode, toNode); ;;; kukit.logDebug(content.length + ' nodes inserted.'); // update the events for the new nodes @@ -797,7 +797,7 @@ ;;; oper.componentName = '[insertHTMLAsLastChild] action'; oper.evaluateParameters(['html'], {'withKssSetup':true}); oper.evalBool('withKssSetup'); - var content = kukit.dom.parseHTMLNodes(oper.parms.html); + var content = kukit.dom.parseHTMLNodes(oper.parms.html, oper.node); kukit.dom.appendChildren(content, oper.node); ;;; kukit.logDebug(content.length + ' nodes inserted.'); // update the events for the new nodes @@ -812,7 +812,7 @@ ;;; oper.componentName = '[insertHTMLAsFirstChild] action'; oper.evaluateParameters(['html'], {'withKssSetup':true}); oper.evalBool('withKssSetup'); - var content = kukit.dom.parseHTMLNodes(oper.parms.html); + var content = kukit.dom.parseHTMLNodes(oper.parms.html, oper.node); var parentNode = oper.node; var toNode = parentNode.firstChild; if (toNode == null) { From jone at codespeak.net Sun Jan 20 10:47:21 2008 From: jone at codespeak.net (jone at codespeak.net) Date: Sun, 20 Jan 2008 10:47:21 +0100 (CET) Subject: [KSS-checkins] r50794 - kukit/kss.core/branch/improve-demos/kss/core/plugins/core/demo Message-ID: <20080120094721.73690168554@codespeak.net> Author: jone Date: Sun Jan 20 10:47:20 2008 New Revision: 50794 Added: kukit/kss.core/branch/improve-demos/kss/core/plugins/core/demo/dynamic_table.kss kukit/kss.core/branch/improve-demos/kss/core/plugins/core/demo/dynamic_table.pt kukit/kss.core/branch/improve-demos/kss/core/plugins/core/demo/dynamic_table.py kukit/kss.core/branch/improve-demos/kss/core/plugins/core/demo/dynamic_table.zcml Modified: kukit/kss.core/branch/improve-demos/kss/core/plugins/core/demo/config.py kukit/kss.core/branch/improve-demos/kss/core/plugins/core/demo/configure.zcml kukit/kss.core/branch/improve-demos/kss/core/plugins/core/demo/tree.pt kukit/kss.core/branch/improve-demos/kss/core/plugins/core/demo/zopeconfig.py Log: Added dynamic table demo Modified: kukit/kss.core/branch/improve-demos/kss/core/plugins/core/demo/config.py ============================================================================== --- kukit/kss.core/branch/improve-demos/kss/core/plugins/core/demo/config.py (original) +++ kukit/kss.core/branch/improve-demos/kss/core/plugins/core/demo/config.py Sun Jan 20 10:47:20 2008 @@ -16,19 +16,8 @@ class CoreDemos(Plugin): zope_demos = ( - KSSDemo('', '', "basic_commands.html", "Change tag content"), - KSSDemo('', '', "two_selects.html", "Two selects"), - KSSDemo('', '', "autoupdate.html", "Auto update"), - KSSDemo('', '', "inline_edit.html", "Inline edit"), - KSSDemo('', '', "cancel_submit.html", "Cancel Submit Click"), - KSSDemo('', '', "tree.html", "Tree"), - KSSDemo('', '', "more_selectors.html", "More complex selectors"), - KSSDemo('', '', "two_select_revisited.html", "Master-slave selects revisited"), - KSSDemo('', '', "form_submit.html", "Form submit"), - KSSDemo('', '', "error_handling.html", "Error handling"), - KSSDemo('', '', "preventdefault.html", "Preventdefault (a.k.a. Safari workarounds)"), - KSSDemo('', '', "html_inserts.html", "HTML insertions (Change tag content returns)"), - KSSDemo('', '', "client-server-protocol", "Client server protocol"), + KSSDemo('', 'Applications', "dynamic_table.html", "Addressbook"), +## KSSDemo('', '', "draganddrop.html", "Scriptaculous drag and drop"), KSSDemo('', 'Parameter functions', 'pf_forms.html', 'Forms'), KSSDemo('', 'Selectors', 'selectors.html', 'Parent node selector'), KSSDemo('', 'Core syntax', "kss_selector_param.html", "Kss selector parameters"), @@ -37,6 +26,20 @@ KSSDemo('', 'Core events', "kss_keyevents.html", "Key events"), KSSDemo('', 'Commands/Actions', "ca_focus.html", "Focus"), KSSDemo('', 'Commands/Actions', "actions.html", "Toggle case action"), + KSSDemo('', 'History', "basic_commands.html", "Change tag content"), + KSSDemo('', 'History', "two_selects.html", "Two selects"), + KSSDemo('', 'History', "autoupdate.html", "Auto update"), + KSSDemo('', 'History', "inline_edit.html", "Inline edit"), + KSSDemo('', 'History', "cancel_submit.html", "Cancel Submit Click"), + KSSDemo('', 'History', "tree.html", "Tree"), + KSSDemo('', 'History', "more_selectors.html", "More complex selectors"), + KSSDemo('', 'History', "two_select_revisited.html", "Master-slave selects revisited"), + KSSDemo('', 'History', "form_submit.html", "Form submit"), + KSSDemo('', 'History', "effects.html", "Effects"), + KSSDemo('', 'History', "error_handling.html", "Error handling"), + KSSDemo('', 'History', "preventdefault.html", "Preventdefault (a.k.a. Safari workarounds)"), + KSSDemo('', 'History', "html_inserts.html", "HTML insertions (Change tag content returns)"), + KSSDemo('', 'History', "client-server-protocol", "Client server protocol"), # XXX this should go to the other plugin wuth all its stuff KSSDemo('Effects', '', "effects.html", "Effects"), ) Modified: kukit/kss.core/branch/improve-demos/kss/core/plugins/core/demo/configure.zcml ============================================================================== --- kukit/kss.core/branch/improve-demos/kss/core/plugins/core/demo/configure.zcml (original) +++ kukit/kss.core/branch/improve-demos/kss/core/plugins/core/demo/configure.zcml Sun Jan 20 10:47:20 2008 @@ -545,5 +545,8 @@ permission="zope.View" /> + + + Added: kukit/kss.core/branch/improve-demos/kss/core/plugins/core/demo/dynamic_table.kss ============================================================================== --- (empty file) +++ kukit/kss.core/branch/improve-demos/kss/core/plugins/core/demo/dynamic_table.kss Sun Jan 20 10:47:20 2008 @@ -0,0 +1,32 @@ +input#submit:click { + evt-click-preventdefault: true; + action-server: addPerson; + addPerson-name: currentFormVar(name); + addPerson-address: currentFormVar(address); + addPerson-city: currentFormVar(city); + addPerson-country: currentFormVar(country); + addPerson-telephone: currentFormVar(telephone); +} + +input#clean:click { + evt-click-preventdefault: true; + action-server: cleanPersons; +} + +input.moveUp:click { + evt-click-preventdefault: true; + action-server: moveUp; + moveUp-pid: kssAttr(pid); +} + +input.moveDown:click { + evt-click-preventdefault: true; + action-server: moveDown; + moveDown-pid: kssAttr(pid); +} + +input.remove:click { + evt-click-preventdefault: true; + action-server: removePerson; + removePerson-pid: kssAttr(pid); +} Added: kukit/kss.core/branch/improve-demos/kss/core/plugins/core/demo/dynamic_table.pt ============================================================================== --- (empty file) +++ kukit/kss.core/branch/improve-demos/kss/core/plugins/core/demo/dynamic_table.pt Sun Jan 20 10:47:20 2008 @@ -0,0 +1,78 @@ + + + + + + + + + + +

      header

      + +

      Dynamic Tables

      + +
      + +
      +
      + +
      + +
      +
      + +
      +
      +
      + +
      +
      +
      + +
      +
      +
      + +
      +
      + + +
      + +
      + + +
      + + + + +
      + + + + + + + + + + + + + + + + + +
      NameAddressCityCountryTelephone
      + + + + Added: kukit/kss.core/branch/improve-demos/kss/core/plugins/core/demo/dynamic_table.py ============================================================================== --- (empty file) +++ kukit/kss.core/branch/improve-demos/kss/core/plugins/core/demo/dynamic_table.py Sun Jan 20 10:47:20 2008 @@ -0,0 +1,118 @@ +# Copyright (c) 2005-2007 +# Authors: KSS Project Contributors (see docs/CREDITS.txt) +# +# 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. + +from kss.core import KSSView, force_unicode, KSSExplicitError, kssaction +from time import time +from persistent.list import PersistentList + +class KSSDynamicTableDemo(KSSView): + + def getPersons(self): + return self.context.getValue('persons', PersistentList()) + + def cleanPersons(self): + self.context.setValue('persons', PersistentList()) + self.getCommandSet('core').replaceHTML('table#personTable tbody', '') + return self.render() + + def addPerson(self, name, address, city, country, telephone): + """ adds a person""" + persons = self.getPersons() + person = { + 'pid' : str(time()).replace('.',''), + 'name' : name, + 'address' : address, + 'city' : city, + 'country' : country, + 'telephone' : telephone + } + persons.append(person) + html = self.renderPersonAsTr(person) + self.getCommandSet('core').insertHTMLAsLastChild('table#personTable tbody', html) + return self.render() + + + def removePerson(self, pid): + persons = self.getPersons() + for p in persons: + if p['pid'] == pid: + persons.remove(p) + self.getCommandSet('core').deleteNode('tr.pid%s' % pid) + return self.render() + + + def moveUp(self, pid): + persons = self.getPersons() + for i in range(1, len(persons)): + pid1 = persons[i]['pid'] + pid2 = persons[i-1]['pid'] + if pid==pid1: + self.switchPersons(pid1, pid2) + break + return self.render() + + def moveDown(self, pid): + persons = self.getPersons() + for i in range(0, len(persons)-1): + pid1 = persons[i]['pid'] + pid2 = persons[i+1]['pid'] + if pid==pid1: + self.switchPersons(pid1, pid2) + break + return self.render() + + def switchPersons(self, pid1, pid2): + persons = self.getPersons() + p1 = None + i1 = None + p2 = None + i2 = None + for i in range(0, len(persons)): + if persons[i]['pid'] == pid1: + p1 = persons[i] + i1 = i + if persons[i]['pid'] == pid2: + p2 = persons[i] + i2 = i + if p1 and p2: + self.getCommandSet('core').replaceHTML('tr.pid%s' % p2['pid'], '') + self.getCommandSet('core').replaceHTML('tr.pid%s' % p1['pid'], self.renderPersonAsTr(p2)) + self.getCommandSet('core').replaceHTML('tr.placeholder', self.renderPersonAsTr(p1)) + persons[i1] = p2 + persons[i2] = p1 + + + + def renderPersonAsTr(self, person): + pid = person['pid'] + buttons = ''' + + + + ''' % {'pid' : pid} + html = """%(name)s%(address)s%(city)s%(country)s%(telephone)s%(buttons)s""" % { + 'pid' : person['pid'], + 'name' : person['name'], + 'address' : person['address'], + 'city' : person['city'], + 'country' : person['country'], + 'telephone' : person['telephone'], + 'buttons' : buttons + } + return html + + Added: kukit/kss.core/branch/improve-demos/kss/core/plugins/core/demo/dynamic_table.zcml ============================================================================== --- (empty file) +++ kukit/kss.core/branch/improve-demos/kss/core/plugins/core/demo/dynamic_table.zcml Sun Jan 20 10:47:20 2008 @@ -0,0 +1,81 @@ + + + + + + + + + + + + + + + + + + + + + + + + Modified: kukit/kss.core/branch/improve-demos/kss/core/plugins/core/demo/tree.pt ============================================================================== --- kukit/kss.core/branch/improve-demos/kss/core/plugins/core/demo/tree.pt (original) +++ kukit/kss.core/branch/improve-demos/kss/core/plugins/core/demo/tree.pt Sun Jan 20 10:47:20 2008 @@ -1,4 +1,4 @@ - + Modified: kukit/kss.core/branch/improve-demos/kss/core/plugins/core/demo/zopeconfig.py ============================================================================== --- kukit/kss.core/branch/improve-demos/kss/core/plugins/core/demo/zopeconfig.py (original) +++ kukit/kss.core/branch/improve-demos/kss/core/plugins/core/demo/zopeconfig.py Sun Jan 20 10:47:20 2008 @@ -18,20 +18,7 @@ implements(IResource) demos = ( - KSSDemo('', '', "basic_commands.html", "Change tag content"), - KSSDemo('', '', "two_selects.html", "Two selects"), - KSSDemo('', '', "autoupdate.html", "Auto update"), - KSSDemo('', '', "inline_edit.html", "Inline edit"), - KSSDemo('', '', "cancel_submit.html", "Cancel Submit Click"), - KSSDemo('', '', "tree.html", "Tree"), - KSSDemo('', '', "more_selectors.html", "More complex selectors"), - KSSDemo('', '', "two_select_revisited.html", "Master-slave selects revisited"), - KSSDemo('', '', "form_submit.html", "Form submit"), - KSSDemo('', '', "effects.html", "Effects"), - KSSDemo('', '', "error_handling.html", "Error handling"), - KSSDemo('', '', "preventdefault.html", "Preventdefault (a.k.a. Safari workarounds)"), - KSSDemo('', '', "html_inserts.html", "HTML insertions (Change tag content returns)"), - KSSDemo('', '', "client-server-protocol", "Client server protocol"), + KSSDemo('', 'Applications', "dynamic_table.html", "Addressbook"), ## KSSDemo('', '', "draganddrop.html", "Scriptaculous drag and drop"), KSSDemo('', 'Parameter functions', 'pf_forms.html', 'Forms'), KSSDemo('', 'Selectors', 'selectors.html', 'Parent node selector'), @@ -41,6 +28,20 @@ KSSDemo('', 'Core events', "kss_keyevents.html", "Key events"), KSSDemo('', 'Commands/Actions', "ca_focus.html", "Focus"), KSSDemo('', 'Commands/Actions', "actions.html", "Toggle case action"), + KSSDemo('', 'History', "basic_commands.html", "Change tag content"), + KSSDemo('', 'History', "two_selects.html", "Two selects"), + KSSDemo('', 'History', "autoupdate.html", "Auto update"), + KSSDemo('', 'History', "inline_edit.html", "Inline edit"), + KSSDemo('', 'History', "cancel_submit.html", "Cancel Submit Click"), + KSSDemo('', 'History', "tree.html", "Tree"), + KSSDemo('', 'History', "more_selectors.html", "More complex selectors"), + KSSDemo('', 'History', "two_select_revisited.html", "Master-slave selects revisited"), + KSSDemo('', 'History', "form_submit.html", "Form submit"), + KSSDemo('', 'History', "effects.html", "Effects"), + KSSDemo('', 'History', "error_handling.html", "Error handling"), + KSSDemo('', 'History', "preventdefault.html", "Preventdefault (a.k.a. Safari workarounds)"), + KSSDemo('', 'History', "html_inserts.html", "HTML insertions (Change tag content returns)"), + KSSDemo('', 'History', "client-server-protocol", "Client server protocol"), ) # directories are relative from the location of this .py file From jone at codespeak.net Sun Jan 20 13:40:26 2008 From: jone at codespeak.net (jone at codespeak.net) Date: Sun, 20 Jan 2008 13:40:26 +0100 (CET) Subject: [KSS-checkins] r50797 - kukit/kss.demo/branch/improve-demos/kss/demo Message-ID: <20080120124026.6E0FF168504@codespeak.net> Author: jone Date: Sun Jan 20 13:40:24 2008 New Revision: 50797 Modified: kukit/kss.demo/branch/improve-demos/kss/demo/simplecontent.py Log: added storage functionality to simplecontent Modified: kukit/kss.demo/branch/improve-demos/kss/demo/simplecontent.py ============================================================================== --- kukit/kss.demo/branch/improve-demos/kss/demo/simplecontent.py (original) +++ kukit/kss.demo/branch/improve-demos/kss/demo/simplecontent.py Sun Jan 20 13:40:24 2008 @@ -29,6 +29,7 @@ from Products.PageTemplates.PageTemplateFile import PageTemplateFile from zope.interface import implements from interfaces import ISimpleContent +from persistent.mapping import PersistentMapping class SimpleContent(SimpleItem): implements(ISimpleContent) @@ -43,6 +44,17 @@ def __init__(self, id, title): self.id = id self.title = title + self.mapping = PersistentMapping() + + def getValue(self, name, default=None): + result = self.mapping.get(name, default) + if not result or result == default: + result = default + self.setValue(name, result) + return result + + def setValue(self, name, value): + self.mapping[name] = value security.declarePublic('direct') def direct(self): From gotcha at codespeak.net Sun Jan 20 14:51:00 2008 From: gotcha at codespeak.net (gotcha at codespeak.net) Date: Sun, 20 Jan 2008 14:51:00 +0100 (CET) Subject: [KSS-checkins] r50798 - kukit/kukit.js/trunk/kukit Message-ID: <20080120135100.D0C78168500@codespeak.net> Author: gotcha Date: Sun Jan 20 14:50:59 2008 New Revision: 50798 Modified: kukit/kukit.js/trunk/kukit/kukit.js kukit/kukit.js/trunk/kukit/serveraction.js Log: fix base URL calculation to fix bug found via Grok integration by Jeff Modified: kukit/kukit.js/trunk/kukit/kukit.js ============================================================================== --- kukit/kukit.js/trunk/kukit/kukit.js (original) +++ kukit/kukit.js/trunk/kukit/kukit.js Sun Jan 20 14:50:59 2008 @@ -79,6 +79,7 @@ this.calculateBase = function() { var base = ''; + // returns empty base when not in browser (cli tests) try { var _dummy = document; _dummy = window; @@ -86,29 +87,32 @@ // testing or what return base; } + // fetch base from specific link in case of ill situations + // like default pages in Plone var nodes = document.getElementsByTagName("link"); if (nodes.length > 0) { for (var i=0; i 0 && base.substring(baselen - 1) == '/') { - base = base.substring(0, baselen - 1); + // if no override, fetch as usual first from base tag + // then from page url if no base tag + if (!base) { + nodes = document.getElementsByTagName("base"); + if (nodes.length != 0) { + var base = nodes[0].href; + } else { + var base = window.location.href; } } + // remove last piece until '/' + var pieces = base.split('/'); + pieces.pop(); + // base url needs a trailing '/' + base = pieces.join('/') + '/'; return base; }; Modified: kukit/kukit.js/trunk/kukit/serveraction.js ============================================================================== --- kukit/kukit.js/trunk/kukit/serveraction.js (original) +++ kukit/kukit.js/trunk/kukit/serveraction.js Sun Jan 20 14:50:59 2008 @@ -48,7 +48,7 @@ if (url.match(RegExp('/^https?:\/\//'))) { return url; } else { - var result = kukit.engine.baseUrl + '/' + url; + var result = kukit.engine.baseUrl + url; return result; } }; From gotcha at codespeak.net Sun Jan 20 14:51:54 2008 From: gotcha at codespeak.net (gotcha at codespeak.net) Date: Sun, 20 Jan 2008 14:51:54 +0100 (CET) Subject: [KSS-checkins] r50799 - kukit/kukit.js/trunk/doc Message-ID: <20080120135154.DD586168500@codespeak.net> Author: gotcha Date: Sun Jan 20 14:51:53 2008 New Revision: 50799 Added: kukit/kukit.js/trunk/doc/draganddrop.kss.txt Log: some thoughts about how drag and drop should look in kss Added: kukit/kukit.js/trunk/doc/draganddrop.kss.txt ============================================================================== --- (empty file) +++ kukit/kukit.js/trunk/doc/draganddrop.kss.txt Sun Jan 20 14:51:53 2008 @@ -0,0 +1,32 @@ +div.portlet:startdrag(portlets) { + default-action: ghost; #keep, discard + action-server: lockContainer; +} + +div.portlet:dragsuccess(portlets) { + action-server: putInTarget; + putInTarget-source: nodeAttr(id); + putInTarget-target: nodeAttr(id, kssContext=dragTarget()); + putInTarget-target-kssContext: dragTarget(); +} + +div.portlet:dragfailure(portlets) { + action-server: unlockContainer; +} + +#toolbar div.portlet:startdrag(portlets) { + default-action: keep; +} + +#toolbar div.onlyInDashboard:startdrag(portlets) { + default-action: keep; + default-allowedTargets: css(#dashboard); +} + +#dashboard:drop(portlets), #column-two:drop(portlets), #column-one:drop(portlets) { + default-action: order; #fill, discard +} + +#waste-bin:drop(portlets) { + default-action: discard; +} From jone at codespeak.net Sun Jan 20 16:15:43 2008 From: jone at codespeak.net (jone at codespeak.net) Date: Sun, 20 Jan 2008 16:15:43 +0100 (CET) Subject: [KSS-checkins] r50800 - in kukit/kss.core/branch/improve-demos/kss/core/plugins/core/demo: . selenium_tests Message-ID: <20080120151543.A60B8168533@codespeak.net> Author: jone Date: Sun Jan 20 16:15:40 2008 New Revision: 50800 Added: kukit/kss.core/branch/improve-demos/kss/core/plugins/core/demo/dynamic_table.css kukit/kss.core/branch/improve-demos/kss/core/plugins/core/demo/selenium_tests/dynamic_table.html Modified: kukit/kss.core/branch/improve-demos/kss/core/plugins/core/demo/dynamic_table.kss kukit/kss.core/branch/improve-demos/kss/core/plugins/core/demo/dynamic_table.pt kukit/kss.core/branch/improve-demos/kss/core/plugins/core/demo/dynamic_table.py kukit/kss.core/branch/improve-demos/kss/core/plugins/core/demo/dynamic_table.zcml Log: added css and selenium test for dynamic_table Added: kukit/kss.core/branch/improve-demos/kss/core/plugins/core/demo/dynamic_table.css ============================================================================== --- (empty file) +++ kukit/kss.core/branch/improve-demos/kss/core/plugins/core/demo/dynamic_table.css Sun Jan 20 16:15:40 2008 @@ -0,0 +1,20 @@ +table#personTable { + margin-left: auto; + margin-right: auto; + border: 1px solid #f2ae8c; +} + +table#personTable th { + background-color: #f2ae8c; + padding-left: 5px; + padding-right: 5px; +} + +div.centered { + text-align: center; +} + +hr { + border: none; + border-top: 1px solid #FF4916; +} Modified: kukit/kss.core/branch/improve-demos/kss/core/plugins/core/demo/dynamic_table.kss ============================================================================== --- kukit/kss.core/branch/improve-demos/kss/core/plugins/core/demo/dynamic_table.kss (original) +++ kukit/kss.core/branch/improve-demos/kss/core/plugins/core/demo/dynamic_table.kss Sun Jan 20 16:15:40 2008 @@ -19,6 +19,18 @@ moveUp-pid: kssAttr(pid); } +input.toBottom:click { + evt-click-preventdefault: true; + action-server: toBottom; + toBottom-pid: kssAttr(pid); +} + +input.toTop:click { + evt-click-preventdefault: true; + action-server: toTop; + toTop-pid: kssAttr(pid); +} + input.moveDown:click { evt-click-preventdefault: true; action-server: moveDown; Modified: kukit/kss.core/branch/improve-demos/kss/core/plugins/core/demo/dynamic_table.pt ============================================================================== --- kukit/kss.core/branch/improve-demos/kss/core/plugins/core/demo/dynamic_table.pt (original) +++ kukit/kss.core/branch/improve-demos/kss/core/plugins/core/demo/dynamic_table.pt Sun Jan 20 16:15:40 2008 @@ -3,6 +3,9 @@ + @@ -10,7 +13,7 @@

      header

      -

      Dynamic Tables

      +

      Addressbook

      @@ -33,7 +36,7 @@ -
    @@ -48,31 +51,31 @@ -
    - - +
    + -
    + + + + + + + + + + + + + + + + +
    NameAddressCityCountryTelephone
    - - - - - - - - - - - - - - - - -
    NameAddressCityCountryTelephone
    +
    +
    Modified: kukit/kss.core/branch/improve-demos/kss/core/plugins/core/demo/dynamic_table.py ============================================================================== --- kukit/kss.core/branch/improve-demos/kss/core/plugins/core/demo/dynamic_table.py (original) +++ kukit/kss.core/branch/improve-demos/kss/core/plugins/core/demo/dynamic_table.py Sun Jan 20 16:15:40 2008 @@ -51,7 +51,7 @@ for p in persons: if p['pid'] == pid: persons.remove(p) - self.getCommandSet('core').deleteNode('tr.pid%s' % pid) + self.getCommandSet('core').deleteNode('tr#pid%s' % pid) return self.render() @@ -75,6 +75,33 @@ break return self.render() + def toTop(self, pid): + persons = self.getPersons() + firstPid = persons[0]['pid'] + if firstPid == pid: + return self.render() + self.getCommandSet('core').moveNodeBefore('tr#pid%s' % pid, 'pid%s' % firstPid) + for p in persons: + if p['pid'] == pid: + persons.remove(p) + persons.insert(0, p) + break + return self.render() + + def toBottom(self, pid): + persons = self.getPersons() + lastPid = persons[-1]['pid'] + if lastPid == pid: + return self.render() + self.getCommandSet('core').moveNodeAfter('tr#pid%s' % pid, 'pid%s' % lastPid) + for p in persons: + if p['pid'] == pid: + persons.remove(p) + persons.append(p) + break + return self.render() + + def switchPersons(self, pid1, pid2): persons = self.getPersons() p1 = None @@ -89,8 +116,8 @@ p2 = persons[i] i2 = i if p1 and p2: - self.getCommandSet('core').replaceHTML('tr.pid%s' % p2['pid'], '') - self.getCommandSet('core').replaceHTML('tr.pid%s' % p1['pid'], self.renderPersonAsTr(p2)) + self.getCommandSet('core').replaceHTML('tr#pid%s' % p2['pid'], '') + self.getCommandSet('core').replaceHTML('tr#pid%s' % p1['pid'], self.renderPersonAsTr(p2)) self.getCommandSet('core').replaceHTML('tr.placeholder', self.renderPersonAsTr(p1)) persons[i1] = p2 persons[i2] = p1 @@ -100,11 +127,13 @@ def renderPersonAsTr(self, person): pid = person['pid'] buttons = ''' + - + + ''' % {'pid' : pid} - html = """%(name)s%(address)s%(city)s%(country)s%(telephone)s%(buttons)s""" % { + html = """%(name)s%(address)s%(city)s%(country)s%(telephone)s%(buttons)s""" % { 'pid' : person['pid'], 'name' : person['name'], 'address' : person['address'], Modified: kukit/kss.core/branch/improve-demos/kss/core/plugins/core/demo/dynamic_table.zcml ============================================================================== --- kukit/kss.core/branch/improve-demos/kss/core/plugins/core/demo/dynamic_table.zcml (original) +++ kukit/kss.core/branch/improve-demos/kss/core/plugins/core/demo/dynamic_table.zcml Sun Jan 20 16:15:40 2008 @@ -41,6 +41,22 @@ + + + + + Added: kukit/kss.core/branch/improve-demos/kss/core/plugins/core/demo/selenium_tests/dynamic_table.html ============================================================================== --- (empty file) +++ kukit/kss.core/branch/improve-demos/kss/core/plugins/core/demo/selenium_tests/dynamic_table.html Sun Jan 20 16:15:40 2008 @@ -0,0 +1,224 @@ + + + +dynamic_table + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    dynamic_table
    open/demo/dynamic_table.html
    assertTextPresentAddressbook
    clickclean
    waitForElementNotPresent//tr[2]
    assertElementNotPresent//tr[2]
    typenameCarsten
    typecityAachen
    clicksubmit
    waitForText//td[1]Carsten
    assertText//td[1]Carsten
    assertText//td[3]Aachen
    typenameJonas
    typecityBern
    clicksubmit
    waitForText//tr[2]/td[1]Jonas
    assertText//tr[2]/td[1]Jonas
    assertText//tr[2]/td[3]Bern
    typenameGodefroid
    typecityLouvain-la-neuve
    clicksubmit
    waitForText//tr[3]/td[1]Godefroid
    assertText//tr[3]/td[1]Godefroid
    assertText//tr[3]/td[3]Louvain-la-neuve
    click//tr[3]/td[6]/input[@value='up']
    waitForText//tr[2]/td[1]Godefroid
    assertText//tr[2]/td[1]Godefroid
    assertText//tr[2]/td[3]Louvain-la-neuve
    assertText//tr[3]/td[1]Jonas
    assertText//tr[3]/td[3]Bern
    click//input[@value='down']
    waitForText//td[1]Godefroid
    assertText//td[1]Godefroid
    assertText//td[3]Louvain-la-neuve
    assertText//tr[2]/td[1]Carsten
    assertText//tr[2]/td[3]Aachen
    click//tr[2]/td[6]/input[@value='remove']
    waitForText//tr[2]/td[1]Jonas
    assertText//tr[2]/td[1]Jonas
    assertTextNotPresentCarsten
    clickclean
    waitForElementNotPresent//tr[2]
    assertElementNotPresent//tr[2]
    + + From jone at codespeak.net Sun Jan 20 16:45:26 2008 From: jone at codespeak.net (jone at codespeak.net) Date: Sun, 20 Jan 2008 16:45:26 +0100 (CET) Subject: [KSS-checkins] r50801 - kukit/kss.core/branch/improve-demos/kss/core/plugins/core/demo/selenium_tests Message-ID: <20080120154526.EF4D6168507@codespeak.net> Author: jone Date: Sun Jan 20 16:45:25 2008 New Revision: 50801 Modified: kukit/kss.core/branch/improve-demos/kss/core/plugins/core/demo/selenium_tests/dynamic_table.html Log: extended test dynamic_table with 'top' and 'bottom' tests. Modified: kukit/kss.core/branch/improve-demos/kss/core/plugins/core/demo/selenium_tests/dynamic_table.html ============================================================================== --- kukit/kss.core/branch/improve-demos/kss/core/plugins/core/demo/selenium_tests/dynamic_table.html (original) +++ kukit/kss.core/branch/improve-demos/kss/core/plugins/core/demo/selenium_tests/dynamic_table.html Sun Jan 20 16:45:25 2008 @@ -160,17 +160,17 @@ waitForText - //td[1] + //tr[1]/td[1] Godefroid assertText - //td[1] + //tr[1]/td[1] Godefroid assertText - //td[3] + //tr[1]/td[3] Louvain-la-neuve @@ -185,13 +185,43 @@ click - //tr[2]/td[6]/input[@value='remove'] + //tr[2]/td[6]/input[@value='top'] waitForText - //tr[2]/td[1] - Jonas + //tr[1]/td[1] + Carsten + + + assertText + //tr[1]/td[1] + Carsten + + + assertText + //tr[1]/td[3] + Aachen + + + click + //tr[2]/td[6]/input[@value='bottom'] + + + + waitForText + //tr[3]/td[1] + Godefroid + + + assertText + //tr[3]/td[1] + Godefroid + + + assertText + //tr[3]/td[3] + Louvain-la-neuve assertText @@ -199,11 +229,51 @@ Jonas - assertTextNotPresent - Carsten + assertText + //tr[2]/td[3] + Bern + + + assertText + //tr[3]/td[1] + Godefroid + + + assertText + //tr[3]/td[3] + Louvain-la-neuve + + + click + //tr[2]/td[6]/input[@value='remove'] + waitForText + //tr[1]/td[1] + Carsten + + + assertText + //tr[1]/td[1] + Carsten + + + assertText + //tr[1]/td[3] + Aachen + + + assertText + //tr[2]/td[1] + Godefroid + + + assertText + //tr[2]/td[3] + Louvain-la-neuve + + click clean From gotcha at codespeak.net Sun Jan 20 20:28:11 2008 From: gotcha at codespeak.net (gotcha at codespeak.net) Date: Sun, 20 Jan 2008 20:28:11 +0100 (CET) Subject: [KSS-checkins] r50810 - kukit/kss.demo/branch/improve-demos/kss/demo/browser Message-ID: <20080120192811.E25E41684FA@codespeak.net> Author: gotcha Date: Sun Jan 20 20:28:10 2008 New Revision: 50810 Modified: kukit/kss.demo/branch/improve-demos/kss/demo/browser/header_macros.pt Log: fix link type for safari debugger Modified: kukit/kss.demo/branch/improve-demos/kss/demo/browser/header_macros.pt ============================================================================== --- kukit/kss.demo/branch/improve-demos/kss/demo/browser/header_macros.pt (original) +++ kukit/kss.demo/branch/improve-demos/kss/demo/browser/header_macros.pt Sun Jan 20 20:28:10 2008 @@ -15,7 +15,7 @@ - Author: gotcha Date: Sun Jan 20 20:44:45 2008 New Revision: 50812 Modified: kukit/kss.core/trunk/kss/core/tests/configure-online.zcml Log: setup of dommer and dependencies Modified: kukit/kss.core/trunk/kss/core/tests/configure-online.zcml ============================================================================== --- kukit/kss.core/trunk/kss/core/tests/configure-online.zcml (original) +++ kukit/kss.core/trunk/kss/core/tests/configure-online.zcml Sun Jan 20 20:44:45 2008 @@ -12,4 +12,26 @@ permission="zope.Public" /> + + + + + + + + + + From gotcha at codespeak.net Sun Jan 20 20:46:34 2008 From: gotcha at codespeak.net (gotcha at codespeak.net) Date: Sun, 20 Jan 2008 20:46:34 +0100 (CET) Subject: [KSS-checkins] r50813 - kukit/kss.core/trunk/kss/core/plugins/core/demo/selenium_tests Message-ID: <20080120194634.37FFF1684F1@codespeak.net> Author: gotcha Date: Sun Jan 20 20:46:33 2008 New Revision: 50813 Modified: kukit/kss.core/trunk/kss/core/plugins/core/demo/selenium_tests/0_ecmaunit_tests.html Log: add new unit tests in selenium tests Modified: kukit/kss.core/trunk/kss/core/plugins/core/demo/selenium_tests/0_ecmaunit_tests.html ============================================================================== --- kukit/kss.core/trunk/kss/core/plugins/core/demo/selenium_tests/0_ecmaunit_tests.html (original) +++ kukit/kss.core/trunk/kss/core/plugins/core/demo/selenium_tests/0_ecmaunit_tests.html Sun Jan 20 20:46:33 2008 @@ -30,6 +30,11 @@ assertText + //div[@id='kukit.BaseURLTestCase']/div + OK! + + + assertText //div[@id='kukit.RequestManagerTestCase']/div OK! From gotcha at codespeak.net Sun Jan 20 20:43:20 2008 From: gotcha at codespeak.net (gotcha at codespeak.net) Date: Sun, 20 Jan 2008 20:43:20 +0100 (CET) Subject: [KSS-checkins] r50811 - in kukit/kukit.js/trunk: 3rd_party/johnnydebris.net 3rd_party/johnnydebris.net/dommer 3rd_party/johnnydebris.net/jsbase 3rd_party/johnnydebris.net/jsbase/testing 3rd_party/johnnydebris.net/minisax.js kukit tests Message-ID: <20080120194320.ED4951684FB@codespeak.net> Author: gotcha Date: Sun Jan 20 20:43:18 2008 New Revision: 50811 Added: kukit/kukit.js/trunk/3rd_party/johnnydebris.net/ kukit/kukit.js/trunk/3rd_party/johnnydebris.net/dommer/ kukit/kukit.js/trunk/3rd_party/johnnydebris.net/dommer/CHANGES.txt kukit/kukit.js/trunk/3rd_party/johnnydebris.net/dommer/LICENSE.txt kukit/kukit.js/trunk/3rd_party/johnnydebris.net/dommer/README.txt kukit/kukit.js/trunk/3rd_party/johnnydebris.net/dommer/conftest.py kukit/kukit.js/trunk/3rd_party/johnnydebris.net/dommer/dommer.js kukit/kukit.js/trunk/3rd_party/johnnydebris.net/dommer/example.html kukit/kukit.js/trunk/3rd_party/johnnydebris.net/dommer/run_tests.html kukit/kukit.js/trunk/3rd_party/johnnydebris.net/dommer/test_dommer.js kukit/kukit.js/trunk/3rd_party/johnnydebris.net/dommer/version.txt kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/ kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/LICENSE.txt kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/README.txt kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/__init__.py kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/array.js kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/conftest.py kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/exception.js kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/function.js kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/misclib.js kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/number.js kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/server.js kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/string.js kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/test_array.js kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/test_misclib.js kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/test_number.js kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/test_string.js kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/testing/ kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/testing.js kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/testing/findtests.js kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/testing/testbase.js kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/version.txt kukit/kukit.js/trunk/3rd_party/johnnydebris.net/minisax.js/ kukit/kukit.js/trunk/3rd_party/johnnydebris.net/minisax.js/LICENSE.txt kukit/kukit.js/trunk/3rd_party/johnnydebris.net/minisax.js/conftest.py kukit/kukit.js/trunk/3rd_party/johnnydebris.net/minisax.js/example.html kukit/kukit.js/trunk/3rd_party/johnnydebris.net/minisax.js/helpers.js kukit/kukit.js/trunk/3rd_party/johnnydebris.net/minisax.js/minisax.js kukit/kukit.js/trunk/3rd_party/johnnydebris.net/minisax.js/test_minisax.js kukit/kukit.js/trunk/3rd_party/johnnydebris.net/minisax.js/testhandler.js kukit/kukit.js/trunk/3rd_party/johnnydebris.net/minisax.js/version.txt Modified: kukit/kukit.js/trunk/kukit/kukit.js kukit/kukit.js/trunk/kukit/utils.js kukit/kukit.js/trunk/tests/runner.html kukit/kukit.js/trunk/tests/runtests.js kukit/kukit.js/trunk/tests/runtests.sh kukit/kukit.js/trunk/tests/test_utils.js Log: * add dommer.js code from Guido Wesdorp (johnnydebris) This will allow better unit testing of KSS as it implements DOM in js. * setup of that code in tests infrastructure * refactor base URL computation to allow unit testing * tests for base URL computation Added: kukit/kukit.js/trunk/3rd_party/johnnydebris.net/dommer/CHANGES.txt ============================================================================== --- (empty file) +++ kukit/kukit.js/trunk/3rd_party/johnnydebris.net/dommer/CHANGES.txt Sun Jan 20 20:43:18 2008 @@ -0,0 +1,17 @@ +Changes in the Dommer library +============================= + +Version 0.4 +----------- + + * Changed the unit tests so they can be ran from py.test (using some + new JSBase feature, currently this rules out browser testing but that + should be fixed later). + + * Fixed some bugs in comment handling. + + * Replaced my old helpers lib with a new one, which has a slightly different + way of defining methods (uses a module namespace). Note that this does not + change the dependencies, as the functionality required is copied to the + main lib on release creation. + Added: kukit/kukit.js/trunk/3rd_party/johnnydebris.net/dommer/LICENSE.txt ============================================================================== --- (empty file) +++ kukit/kukit.js/trunk/3rd_party/johnnydebris.net/dommer/LICENSE.txt Sun Jan 20 20:43:18 2008 @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + 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 + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. + Added: kukit/kukit.js/trunk/3rd_party/johnnydebris.net/dommer/README.txt ============================================================================== --- (empty file) +++ kukit/kukit.js/trunk/3rd_party/johnnydebris.net/dommer/README.txt Sun Jan 20 20:43:18 2008 @@ -0,0 +1,60 @@ +Dommer +====== + +What is it? +----------- + +Dommer is a DOM level 2 library (currently not complete, not sure if it ever +will either, but it's a usable subset) that is almost entirely compliant with +the DOM standard. This allows DOM developers to write proper XML parsing code +for all browsers that support core JavaScript. DOM for instance properly +supports namespaces, a feature which IE's DOM support lacks, thus allowing +XML to be parsed with proper namespace and prefix handling on that platform. + +What's missing? +--------------- + +Currently a number of features are missing, features marked with a * will most +probably be added in the near future, others are not certain to be implemented +at all. + +- CDATA* +- DTD processing +- HTML support +- some more exotic DOM functions such as isSupported() +- (there's probably more I can't remember right now ;) + +What's different from the standard? +----------------------------------- + +Since there's no proper way to update one property when another is set in IE, +all properties on a node should be considered read-only, they should never be +modified except with dedicated API calls. To allow setting the prefix of a +node without updating e.g. .nodeName, a new method was added to the Node +interface, called 'setPrefix'. If this library is used *solely* on platforms +that *do* support dynamic property updates (__defineGetter__ and +__defineSetter__), you can set the switch WARN_ON_PREFIX to false and set +.prefix the conventional way. + +Usage +----- + +For an example of how to use the library, see 'example.html'. For API +documentation, see any DOM level 2 reference. + +Note that this library depends on version 0.3 of the 'minisax.js' library, +and version 0.1 of the JSBase lib, both of which can be downloaded (under the +same GPL license) from http://johnnydebris.net/javascript/. + +Questions, remarks, bug reports, etc. +------------------------------------- + +If you have questions, remarks, bug reports, etc. you can send email to +johnny at johnnydebris.net. More information and newer versions of this library +can be found on http://johnnydebris.net. + +Note: this product contains some code written by the Kupu developers (some of +the functionality in helpers.js). Kupu is an HTML editor written in +JavaScript, released under a BSD-style license. See http://kupu.oscom.org for +more information about Kupu and its license. + Added: kukit/kukit.js/trunk/3rd_party/johnnydebris.net/dommer/conftest.py ============================================================================== --- (empty file) +++ kukit/kukit.js/trunk/3rd_party/johnnydebris.net/dommer/conftest.py Sun Jan 20 20:43:18 2008 @@ -0,0 +1,18 @@ +# JS unit test support for py.test - (c) 2007 Guido Wesdorp. All rights +# reserved +# +# This software is distributed under the terms of the JSBase +# License. See LICENSE.txt for license text. + +import py +here = py.magic.autopath().dirpath() + +from jsbase.conftest import JSTest, JSChecker, Directory as _Directory + +class Directory(_Directory): + def run(self): + if self.fspath == here: + return [p.basename for p in self.fspath.listdir('test_*') if + p.ext == '.js'] + return super(Directory, self).run() + Added: kukit/kukit.js/trunk/3rd_party/johnnydebris.net/dommer/dommer.js ============================================================================== --- (empty file) +++ kukit/kukit.js/trunk/3rd_party/johnnydebris.net/dommer/dommer.js Sun Jan 20 20:43:18 2008 @@ -0,0 +1,1213 @@ +/* dommer.js - a (mostly) compliant subset of DOM level 2 for JS + (c) Guido Wesdorp 2004-2007 + email johnny at debris.demon.nl + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + 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 + + dommer.js + + This library provides a mostly compliant subset of the DOM API in core + JavaScript. A number of methods aren't implemented, and there are a few + semantic differences between the standard and this implementations, but + it provides most of DOM level 2's features and is usable in almost all JS + environments (also stand-alone ones). + + I started writing this mainly because of IE's lack of proper namespace + support, and to have a portable, reliable DOM implementation. + + Non-standard are: + + - Whitespace is never ignored. + + - Because of JS doesn't (by default) allow computing attributes on request, + this API doesn't create Element.nodeName on setting element.prefix, + therefore a new method was added: Element.setPrefix (note that this + is not required if the library is not used on browsers that don't + support __defineGetter__ and __defineSetter__ (such as IE)). + + $Id: minisax.js,v 1.5 2004/07/31 00:10:15 johnny Exp $ + +*/ + +// If the following switch is set to true, setting Element.prefix +// will result in an exception. This serves to make sure scripts work +// cross-browser: IE does not support __defineSetter__, which is used +// to ensure Element.nodeName is updated if Element.prefix +// is changed (and also to ensure Element.nodeName and +// Element.localName can't be changed directly). The lack of this +// method on IE means that on that platform it is possible to break +// integrity (by setting .prefix directly, .nodeName will be out-of-date). +// Note that this means that if you intend to use this lib only on Mozilla +// (or other browsers that support dynamic properties), you can safely +// set this to false and set .prefix without breaking integrity. +var WARN_ON_PREFIX = true; + +// give this a namespace... +try { + var global = window; +} catch(e) { + var global = this; +}; +global.dommer = new function() { + /* Exceptions */ + function DOMException(errorcode, message) { + this.code = null; + this.error = null; + this.message = message + for (var attr in DOMException) { + if (DOMException[attr] == errorcode) { + this.error = attr; + break; + }; + }; + this.code = errorcode; + if (!this.error) { + this.error = 'Unknown'; + }; + this.stack = stack = createStack(); + this.lineNumber = getLineNo(stack); + this.fileName = getFileName(stack); + }; + + this.DOMException = DOMException; + + // error codes + // XXX should we make these global, like in the specs? + DOMException.INDEX_SIZE_ERR = 1, + DOMException.DOMSTRING_SIZE_ERR = 2; + DOMException.HIERARCHY_REQUEST_ERR = 3; + DOMException.WRONG_DOCUMENT_ERR = 4; + DOMException.INVALID_CHARACTER_ERR = 5; + DOMException.NO_DATA_ALLOWED_ERR = 6; + DOMException.NO_MODIFICATION_ALLOWED_ERR = 7; + DOMException.NOT_FOUND_ERR = 8; + DOMException.NOT_SUPPORTED_ERR = 9; + DOMException.INUSE_ATTRIBUTE_ERR = 10; + DOMException.INVALID_STATE_ERR = 11; + DOMException.SYNTAX_ERR = 12; + DOMException.INVALID_MODIFICATION_ERR = 13; + DOMException.NAMESPACE_ERR = 14; + DOMException.INVALID_ACCESS_ERR = 15; + + DOMException.prototype.toString = function() { + var ret = 'DOMException: ' + this.error + ' (' + this.code + ')'; + if (this.message) { + ret += ' - ' + this.message; + }; + return ret; + }; + + /* Node interface */ + function Node() { + this.ELEMENT_NODE = 1; + this.ATTRIBUTE_NODE = 2; + this.TEXT_NODE = 3; + this.CDATA_SECTION_NODE = 4; + this.ENTITY_REFERENCE_NODE = 5; + this.ENTITY_NODE = 6; + this.PROCESSING_INSTRUCTION_NODE = 7; + this.COMMENT_NODE = 8; + this.DOCUMENT_NODE = 9; + this.DOCUMENT_TYPE_NODE = 10; + this.DOCUMENT_FRAGMENT_NODE = 11; + this.NOTATION_NODE = 12; + + // These are defined in-line rather than on .prototype to allow using + // them below, too. This way we don't have to check whether attributes + // are already protected while this constructor is ran or not (in JS, + // when you set 'Foo.prototype = new Bar;', the Bar constructor is + // actually ran, in our case this means that the state of the + // superclass changes). + this._protectAttribute = function(attr) { + /* make an attribute read-only */ + this.__defineSetter__(attr, + function(value) { + throw( + (new DOMException( + DOMException.NO_MODIFICATION_ALLOWED_ERR, attr)) + ); + } + ); + this.__defineGetter__(attr, + function() { + return this['_' + attr]; + } + ); + }; + + this._setProtected = function(name, value) { + /* set a read-only attribute + + THIS IS AN INTERNAL METHOD that should not get used as part + of the API + */ + this['_' + name] = value; + if (!this.__defineSetter__) { + this[name] = value; + }; + }; + + this.nodeValue = null; + if (this.__defineSetter__) { + // on browsers that support __define[GS]etter__, perform integrity + // checks + // nodeValue should be settable on certain nodeTypes + this.__defineSetter__('nodeValue', + function(nodeValue) { + if (this.nodeType != this.TEXT_NODE && + this.nodeType != this.ATTRIBUTE_NODE && + this.nodeType != this.COMMENT_NODE) { + throw( + (new DOMException( + DOMException.NO_DATA_ALLOWED_ERR, + 'nodeValue')) + ); + }; + // XXX should check on allowed chars here, but not + // sure which? + this._nodeValue = nodeValue; + } + ); + // XXX not sure if we should protect reading .nodeValue + this.__defineGetter__('nodeValue', + function() { + if (this.nodeType != this.TEXT_NODE && + this.nodeType != this.ATTRIBUTE_NODE && + this.nodeType != this.COMMENT_NODE) { + throw( + (new DOMException( + DOMException.NO_DATA_ALLOWED_ERR, + 'nodeValue')) + ); + }; + return this._nodeValue; + } + ); + var toprotect = ['nodeType', 'nodeName', 'parentNode', + 'childNodes', 'firstChild', 'lastChild', + 'previousSibling', 'nextSibling', + 'attributes', 'ownerDocument', 'namespaceURI', + 'localName']; + for (var i=0; i < toprotect.length; i++) { + this._protectAttribute(toprotect[i]); + }; + }; + + this._setProtected('namespaceURI', null); + this._setProtected('prefix', null); + this._setProtected('nodeName', null); + this._setProtected('localName', null); + this._setProtected('parentNode', null); + // note that this is shared between subclass instances, so should be + // re-set in every .initialize() (so below is just for show) + this._setProtected('childNodes', []); + this._setProtected('firstChild', null); + this._setProtected('lastChild', null); + this._setProtected('previousSibling', null); + this._setProtected('nextSibling', null); + this._setProtected('ownerDocument', null); + }; + + this.Node = Node; + + var thrownotsupported = function() {throw('not supported');}; + + // XXX these should be implemented at some point... + Node.prototype.normalize = thrownotsupported; + Node.prototype.isSupported = thrownotsupported; // hehehe... + + // non-standard method, use this always instead of setting .prefix + // yourself, as this will update the .nodeName property too + Node.prototype.setPrefix = function(prefix) { + if (this.__defineSetter__) { + this._prefix = prefix; + this._nodeName = prefix + ':' + this.localName; + } else { + this.prefix = prefix; + this.nodeName = prefix + ':' + this.localName; + }; + }; + + Node.prototype.cloneNode = function() { + throw( + (new DOMException(DOMException.NOT_SUPPORTED_ERR)) + ); + }; + + Node.prototype.hasChildNodes = function() { + return (this.childNodes && this.childNodes.length > 0); + }; + + Node.prototype.hasAttributes = function() { + return (this.attributes !== undefined && this.attributes.length); + }; + + Node.prototype.appendChild = function(newChild) { + this._checkModificationAllowed(); + this._attach(newChild); + }; + + Node.prototype.removeChild = function(oldChild) { + this._checkModificationAllowed(); + this._checkIsChild(oldChild); + var newChildren = new NodeList(); + var found = false; + for (var i=0; i < this.childNodes.length; i++) { + if (this.childNodes[i] === oldChild) { + oldChild._setProtected('parentNode', null); + var previous = oldChild.previousSibling; + if (previous) { + oldChild._setProtected('previousSibling', null); + previous._setProtected('nextSibling', + oldChild.nextSibling); + }; + var next = oldChild.nextSibling; + if (next) { + next._setProtected('previousSibling', previous); + oldChild._setProtected('nextSibling', null); + }; + continue; + }; + newChildren.push(this.childNodes[i]); + }; + this._setProtected('childNodes', newChildren); + this._setProtected('firstChild', + (this.childNodes.length > 0 ? this.childNodes[0] : null)); + this._setProtected('lastChild', ( + this.childNodes.length > 0 ? + this.childNodes[this.childNodes.length - 1] : null)); + }; + + Node.prototype.replaceChild = function(newChild, refChild) { + this._checkModificationAllowed(); + this._checkIsChild(refChild); + this._attach(newChild, refChild, true); + }; + + Node.prototype.insertBefore = function(newChild, refChild) { + this._checkModificationAllowed(); + this._checkIsChild(refChild); + this._attach(newChild, refChild); + }; + + Node.prototype._attach = function(newChild, refChild, replace) { + // see if the child is in the same document + if (newChild.ownerDocument != this.ownerDocument) { + throw( + (new DOMException(DOMException.WRONG_DOCUMENT_ERR)) + ); + }; + // see if the child is of an allowed type + if (newChild.nodeType != newChild.ELEMENT_NODE && + newChild.nodeType != newChild.TEXT_NODE && + newChild.nodeType != newChild.CDATA_SECTION_NODE && + newChild.nodeType != newChild.COMMENT_NODE) { + throw( + (new DOMException(DOMException.HIERARCHY_REQUEST_ERR)) + ); + }; + // see if the child isn't a (grand)parent of ourselves + var currparent = this; + while (currparent && currparent.nodeType != newChild.DOCUMENT_NODE) { + if (currparent === newChild) { + throw( + (new DOMException(DOMException.HIERARCHY_REQUEST_ERR)) + ); + }; + currparent = currparent.parentNode; + }; + // seems to be okay, add it + newChild._setProtected('parentNode', this); + if (!refChild) { + if (this.childNodes.length) { + this.childNodes[this.childNodes.length - 1]._setProtected( + 'nextSibling', newChild); + newChild._setProtected('previousSibling', + this.childNodes[this.childNodes.length - 1]); + }; + this.childNodes.push(newChild); + } else { + var newchildren = []; + var found = false; + for (var i=0; i < this.childNodes.length; i++) { + var currChild = this.childNodes[i]; + if (currChild === refChild) { + newchildren.push(newChild); + var previous = this.childNodes[i - 1]; + if (previous) { + newChild._setProtected('previousSibling', previous); + previous._setProtected('nextSibling', newChild); + }; + if (!replace) { + newchildren.push(currChild); + currChild._setProtected('previousSibling', newChild); + newChild._setProtected('nextSibling', currChild); + } else { + currChild._setProtected('parentNode', null); + currChild._setProtected('previousSibling', null); + currChild._setProtected('nextSibling', null); + var next = this.childNodes[i + 1]; + newChild._setProtected('nextSibling', next); + next._setProtected('previousSibling', newChild); + }; + found = true; + } else { + newchildren.push(currChild); + }; + }; + if (!found) { + throw( + (new DOMException(DOMException.NOT_FOUND_ERR)) + ); + }; + this._setProtected('childNodes', newchildren); + }; + this._setProtected('firstChild', this.childNodes[0]); + this._setProtected('lastChild', + this.childNodes[this.childNodes.length - 1]); + }; + + Node.prototype._checkModificationAllowed = function() { + if (this.nodeType != this.ELEMENT_NODE && + this.nodeType != this.DOCUMENT_NODE && + this.nodeType != this.DOCUMENT_FRAGMENT_NODE) { + throw( + (new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR)) + ); + }; + }; + + Node.prototype._checkIsChild = function(refChild) { + if (refChild.parentNode !== this) { + throw( + (new DOMException(DOMException.NOT_FOUND_ERR)) + ); + }; + }; + + function DocumentFragment() { + this._setProtected('nodeType', 11); + }; + + DocumentFragment.prototype = new Node; + this.DocumentFragment = DocumentFragment; + + function Element() { + this._setProtected('nodeType', 1); + }; + + Element.prototype = new Node; + this.Element = Element; + + Element.prototype.initialize = function(namespaceURI, qname, + ownerDocument) { + // XXX the specs are very vague about an id, it says the DOM + // implementation must have info about which attributes are of the id + // type, I'll just use the property here for now... + this.id = ''; // empty string like in Mozilla, seems weird to me though + + this._setProtected('attributes', []); + this._setProtected('childNodes', []); + this._setProtected('ownerDocument', ownerDocument); + + // try to ensure integrity by defining getters and setters for certain + // properties, since this only works in certain browsers it makes sense to + // test your applications on one of those platforms, see also + // WARN_ON_PREFIX in the top of the document + if (this.__defineSetter__) { + this._nodeName = this.nodeName; + this.__defineSetter__('nodeName', function() { + throw( + (new DOMException( + DOMException.NO_MODIFICATION_ALLOWED_ERR))) + }); + this.__defineGetter__('nodeName', + function() {return this._nodeName}); + this.__defineSetter__('prefix', + function(value) { + if (WARN_ON_PREFIX) { + throw('Setting prefix directly ' + + 'breaks integrity of the ' + + 'XML DOM in Internet ' + + 'Explorer browsers!'); + }; + this._prefix = value; + this._nodeName = this._prefix + + this._localName; + }); + this.__defineGetter__('prefix', function() {return this._prefix}); + }; + // XXX both the ns and qname need integrity checks + this._setProtected('namespaceURI', namespaceURI); + if (qname.indexOf(':') > -1) { + var tup = qname.split(':'); + this.setPrefix(tup.shift()); + this._setProtected('localName', tup.join(':')); + } else { + this.setPrefix(null); + this._setProtected('localName', qname); + }; + if (this.prefix) { + this._setProtected('nodeName', this.prefix + ':' + this.localName); + } else { + this._setProtected('nodeName', this.localName); + }; + }; + + Element.prototype.toString = function() { + return ''; + }; + + Element.prototype.toXML = function(context) { + // context is used when toXML is called recursively + // marker + var no_prefix_id = '::no_prefix::'; + if (!context) { + context = { + namespace_stack: [] + }; + }; + var new_namespaces = {}; // any namespaces that weren't declared yet + var current_namespaces = {}; + var last_namespaces = context.namespace_stack[ + context.namespace_stack.length - 1]; + context.namespace_stack.push(current_namespaces); + if (last_namespaces) { + for (var prefix in last_namespaces) { + current_namespaces[prefix] = last_namespaces[prefix]; + }; + }; + var xml = '<' + this.nodeName; + var prefix = this.prefix || no_prefix_id; + if (this.namespaceURI && + (current_namespaces[prefix] != this.namespaceURI)) { + current_namespaces[prefix] = this.namespaceURI; + new_namespaces[prefix] = this.namespaceURI; + }; + for (var i=0; i < this.attributes.length; i++) { + var attr = this.attributes[i]; + var aprefix = attr.prefix || no_prefix_id; + if (attr.namespaceURI && + current_namespaces[aprefix] != attr.namespaceURI) { + current_namespaces[aprefix] = attr.namespaceURI; + new_namespaces[aprefix] = attr.namespaceURI; + }; + xml += ' ' + attr.nodeName + '="' + + string.entitize(attr.nodeValue) + '"'; + }; + + // take care of any new namespaces + for (var prefix in new_namespaces) { + xml += ' xmlns'; + if (prefix != no_prefix_id) { + xml += ':' + prefix; + }; + xml += '="' + string.entitize(new_namespaces[prefix]) + '"'; + }; + + if (this.childNodes.length) { + xml += '>'; + for (var i=0; i < this.childNodes.length; i++) { + xml += this.childNodes[i].toXML(context); + }; + xml += ''; + } else { + xml += ' />'; + }; + context.namespace_stack.pop(); + return xml; + }; + + Element.prototype.cloneNode = function(deep) { + var el = new Element(); + el.initialize(this.namespaceURI, this.nodeName, this.ownerDocument); + for (var i=0; i < this.attributes.length; i++) { + var clone = this.attributes[i].cloneNode(); + clone._setProtected('ownerElement', el); + el.attributes.push(clone); + }; + if (deep) { + for (var i=0; i < this.childNodes.length; i++) { + var clone = this.childNodes[i].cloneNode(true); + clone._setProtected('parentNode', el); + el.appendChild(clone); + }; + }; + return el; + }; + + Element.prototype.getAttributeNodeNS = function(namespaceURI, qname) { + for (var i=0; i < this.attributes.length; i++) { + var attr = this.attributes[i]; + if (attr.namespaceURI == namespaceURI && attr.nodeName == qname) { + return attr; + }; + }; + }; + + Element.prototype.getAttributeNode = function(name) { + return this.getAttributeNodeNS(undefined, name); + }; + + Element.prototype.getAttribute = function(name) { + var attr = this.getAttributeNode(name) + return (attr ? attr.nodeValue : null); + }; + + Element.prototype.getAttributeNS = function(namespaceURI, name) { + var attr = this.getAttributeNodeNS(namespaceURI, name); + return (attr ? attr.nodeValue : null); + }; + + Element.prototype.hasAttributeNS = function(namespaceURI, name) { + return !!(this.getAttributeNS(namespaceURI, name)); + }; + + Element.prototype.hasAttribute = function(name) { + return this.hasAttributeNS(this.namespaceURI, name); + }; + + Element.prototype.setAttributeNS = function(namespaceURI, name, value) { + for (var i=0; i < this.attributes.length; i++) { + var attr = this.attributes[i]; + if (attr.namespaceURI == namespaceURI && attr.nodeName == name) { + attr.nodeValue = value; + return; + }; + }; + var attr = new Attribute(); + attr.initialize(namespaceURI, name, value, this.ownerDocument); + attr._setProtected('ownerElement', this); + this.attributes.push(attr); + }; + + Element.prototype.setAttribute = function(name, value) { + this.setAttributeNS(undefined, name, value); + }; + + Element.prototype.setAttributeNodeNS = function(newAttr) { + for (var i=0; i < this.attributes.length; i++) { + var attr = this.attributes[i]; + if (attr.namespaceURI == newAttr.namespaceURI && + attr.nodeName == newAttr.nodeName) { + throw( + (new DOMException(DOMException.INUSE_ATTRIBUTE_ERR)) + ); + }; + }; + this.attributes.push(newAttr); + }; + + Element.prototype.setAttributeNode = function(newAttr) { + // XXX should this fail if no namespaceURI is available or something? + this.setAttributeNodeNS(newAttr); + }; + + Element.prototype.removeAttributeNS = function(namespaceURI, name) { + for (var i=0; i < this.attributes.length; i++) { + var attr = this.attributes[i]; + if (attr.namespaceURI == namespaceURI && attr.nodeName == name) { + delete this.attributes[i]; + return true; + }; + }; + return false; + }; + + Element.prototype.removeAttribute = function(name) { + return this.removeAttributeNS(this.namespaceURI, name); + }; + + Element.prototype.getElementsByTagNameNS = function(namespaceURI, + name, ret) { + // XXX *very* slow!!! + // needs to be optimized later on (probably by using some mapping) + if (!ret) { + ret = []; + }; + for (var i=0; i < this.childNodes.length; i++) { + var child = this.childNodes[i]; + if (name == child.nodeName || name == '*') { + if ((!namespaceURI && !child.namespaceURI) || + (namespaceURI == child.namespaceURI)) { + ret.push(child); + }; + }; + if (child.nodeType == 1) { + child.getElementsByTagNameNS(namespaceURI, name, ret); + }; + }; + return ret; + }; + + Element.prototype.getElementsByTagName = function(name) { + return this.getElementsByTagNameNS(this.namespaceURI, name); + }; + + Element.prototype.getElementById = function(id) { + // XXX *very* slow!!! + // needs to be optimized later on (probably by using some mapping) + if (this.id == id) { + return this; + }; + for (var i=0; i < this.childNodes.length; i++) { + var child = this.childNodes[i]; + if (child.id == id) { + return child; + }; + if (child.nodeType == 1) { + var found = this.childNodes[i].getElementById(id); + if (found) { + return found; + }; + }; + }; + }; + + function TextNode() { + this._setProtected('nodeType', 3); + this._setProtected('nodeName', '#text'); + }; + + TextNode.prototype = new Node; + this.TextNode = TextNode; + + TextNode.prototype.initialize = function(data, ownerDocument) { + this._setProtected('ownerDocument', ownerDocument); + this._setProtected('childNodes', new NodeList()); + // nodeValue is not protected + this.nodeValue = data; + }; + + TextNode.prototype.toXML = function() { + return string.entitize(this.nodeValue); + }; + + TextNode.prototype.cloneNode = function() { + var node = new TextNode(); + node.initialize(this.nodeValue, this.ownerDocument); + return node; + }; + + function CommentNode() { + /* a comment node */ + this._setProtected('nodeType', 8); + this._setProtected('nodeName', '#comment'); + }; + + CommentNode.prototype = new TextNode; + this.CommentNode = CommentNode; + + CommentNode.prototype.initialize = function(data, ownerDocument) { + this._setProtected('ownerDocument', ownerDocument); + this._setProtected('childNodes', []); + this._setProtected('nodeValue', data); + }; + + CommentNode.prototype.toXML = function() { + return ""; + }; + + // Attribute, subclass of TextNode because of the nice implementation + function Attribute() { + /* an attribute node */ + this._setProtected('nodeType', 2); + }; + + Attribute.prototype = new Node; + this.Attribute = Attribute; + + Attribute.prototype.initialize = function(namespaceURI, qname, value, + ownerDocument) { + // XXX some code duplication here... + if (qname.match(/[^a-zA-Z0-9_\-:]/g)) { + throw( + (new DOMException(DOMException.INVALID_CHARACTER_ERR)) + ); + }; + this._setProtected('ownerDocument', ownerDocument); + this._setProtected('namespaceURI', namespaceURI); + this._setProtected('nodeValue', value); + this._setProtected('childNodes', []); + + // try to ensure integrity by defining getters and setters for certain + // properties, since this only works in certain browsers it makes sense to + // test your applications on one of those platforms, see also + // WARN_ON_PREFIX in the top of the document + if (this.__defineSetter__) { + this._nodeName = this.nodeName; + this.__defineSetter__('nodeName', function() { + throw( + (new DOMException( + DOMException.NO_MODIFICATION_ALLOWED_ERR))) + }); + this.__defineGetter__('nodeName', + function() {return this._nodeName}); + this.__defineSetter__('prefix', + function(value) { + if (WARN_ON_PREFIX) { + throw('Setting prefix directly ' + + 'breaks integrity of the ' + + 'XML DOM in Internet ' + + 'Explorer browsers!'); + }; + this._prefix = value; + this._nodeName = this._prefix + + this._localName; + }); + this.__defineGetter__('prefix', function() {return this._prefix}); + this._protectAttribute('ownerElement'); + }; + this._setProtected('ownerElement', null); + if (qname.indexOf(':') > -1) { + var tup = qname.split(':'); + this.setPrefix(tup.shift()); + this._setProtected('localName', tup.join(':')); + } else { + this.setPrefix(null); + this._setProtected('localName', qname); + }; + if (this.prefix) { + this._setProtected('nodeName', this.prefix + ':' + this.localName); + } else { + this._setProtected('nodeName', this.localName); + }; + }; + + Attribute.prototype.toXML = function() { + ret = this.nodeName + '="' + string.entitize(this.nodeValue) + '"'; + return ret; + }; + + Attribute.prototype.cloneNode = function() { + var attr = new Attribute(); + attr.initialize(this.namespaceURI, this.nodeName, this.nodeValue, + this.ownerDocument); + return attr; + }; + + Attribute.prototype.toString = function() { + return this.nodeValue; + }; + + function Document() { + /* the document node */ + this._setProtected('nodeType', 9); + this._setProtected('nodeName', '#document'); + }; + + Document.prototype = new Element; + this.Document = Document; + + Document.prototype.initialize = function() { + this._setProtected('ownerDocument', this); + this._setProtected('childNodes', []); + this.documentElement = null; + this.namespaceToPrefix = {}; + }; + + Document.prototype.toXML = function() { + return this.documentElement.toXML(); + }; + + Document.prototype.appendChild = function(newChild) { + if (this.documentElement) { + throw( + (new DOMException(DOMException.HIERARCHY_REQUEST_ERR, + 'document already has a document element')) + ); + }; + this._checkModificationAllowed(); + this._attach(newChild); + this.documentElement = newChild; + }; + + + Document.prototype.createElement = function(nodeName) { + return this.createElementNS(this.namespaceURI, nodeName); + }; + + Document.prototype.createElementNS = function(namespaceURI, nodeName) { + var el = new Element(); + el.initialize(namespaceURI, nodeName, this); + return el; + }; + + Document.prototype.createTextNode = function(data) { + var el = new TextNode(); + el.initialize(string.deentitize(data), this); + return el; + }; + + Document.prototype.createAttributeNS = function(namespaceURI, nodeName) { + var el = new Attribute(); + el.initialize(namespaceURI, nodeName, null, this); + return el; + }; + + Document.prototype.createAttribute = function(nodeName) { + return this.createAttributeNS(undefined, nodeName); + }; + + Document.prototype.createComment = function(data) { + var el = new CommentNode(); + el.initialize(data, this); + return el; + }; + + Document.prototype.importNode = function(node) { + node._setProtected('ownerDocument', this); + }; + + function DOMHandler() { + /* SAX handler to convert a piece of XML to a DOM */ + }; + + this.DOMHandler = DOMHandler; + + DOMHandler.prototype.startDocument = function() { + this.document = new Document(); + this.document.initialize(); + this.current = null; + this.namespaces = new Array(); + this.namespaceToPrefix = {}; + }; + + DOMHandler.prototype.startElement = function(namespaceURI, nodename, + attrs) { + if (namespaceURI && !array.contains(this.namespaces, namespaceURI)) { + this.namespaces.push(namespaceURI); + // update the mapping on the document just to be sure, + // that one and the one on this handler should always be in + // sync if a start tag is encountered, since instantiating a + // Element will set the prefix on that element + // XXX ?? + this.document.namespaceToPrefix = this.namespaceToPrefix; + }; + var node = this.document.createElementNS(namespaceURI, nodename); + var prefix = undefined; + if (namespaceURI) { + prefix = this.namespaceToPrefix[namespaceURI]; + if (prefix) { + node.setPrefix(prefix); + }; + }; + for (var ans in attrs) { + // XXX can be optimized by using a dict and just setting the key + if (ans && ans != '' && !array.contains(this.namespaces, ans)) { + this.namespaces.push(ans); + }; + var nsattrs = attrs[ans]; + for (var aname in nsattrs) { + if (aname == 'prefix') { + continue; + }; + if (ans) { + var attr = this.document.createAttributeNS(ans, aname); + attr.setPrefix(this.namespaceToPrefix[ans]); + attr.nodeValue = nsattrs[aname]; + node.setAttributeNodeNS(attr); + } else { + var attr = this.document.createAttribute(aname); + attr.nodeValue = nsattrs[aname]; + node.setAttributeNode(attr); + }; + }; + }; + if (!this.current) { + this.document.documentElement = node; + this.document._setProtected('childNodes', [node]); + this.current = node; + this.current._setProtected('parentNode', this.document); + this.current._setProtected('ownerDocument', this.document); + } else { + this.current.appendChild(node); + this.current = node; + }; + }; + + DOMHandler.prototype.characters = function(data) { + if (!this.current && string.strip(data) == '') { + return; + }; + var node = this.document.createTextNode(data); + this.current.appendChild(node); + }; + + DOMHandler.prototype.comment = function(data) { + if (!this.current && string.strip(data) == '') { + return; + }; + var node = this.document.createComment(data); + if (this.current) { + this.current.appendChild(node); + } else { + this.document.comment = node; + }; + }; + + DOMHandler.prototype.endElement = function(namespaceURI, nodename) { + var prefix = this.namespaceToPrefix[namespaceURI]; + if (nodename != this.current.localName || + namespaceURI != this.current.namespaceURI) { + throw('non-matching end tag ' + namespaceURI + ':' + + prefix + ':' + nodename + ' for start tag ' + + this.current.namespaceURI + ':' + this.current.nodeName); + }; + this.current = this.current.parentNode; + }; + + DOMHandler.prototype.endDocument = function() { + }; + + function DOM() { + /* The DOM API + + Uses regular expressions to convert to a simple DOM + + Provides: + + DOM.parseXML(xml) + - parse the XML, return a document element + + DOM.createDocument() + - contains the document node of the DOM (which in turn contains + the documentElement) + + DOM.toXML() + - returns a serialized XML string + + DOM.buildFromHandler(handler) + - build and return a DOM document built from a MiniSAX handler + */ + }; + + this.DOM = DOM; + + DOM.prototype.createDocument = function() { + var document = new Document(); + document.initialize(); + return document; + }; + + DOM.prototype.toXML = function(docOrEl, encoding) { + /* serialize to XML */ + var xml = '\n'; + return xml + docOrEl.toXML(); + }; + + DOM.prototype.parseXML = function(xml) { + /* parse XML into a DOM + + returns a Document node + */ + var handler = new DOMHandler(); + var parser = new SAXParser(); + parser.initialize(xml, handler); + parser.parse(); + var document = handler.document; + this._copyNamespaceMapping(document, handler.namespaceToPrefix); + return document; + }; + + DOM.prototype.buildFromHandler = function(handler) { + /* create a DOM from a SAX handler */ + var document = handler.document; + this._copyNamespaceMapping(document, handler.namespaceToPrefix); + return document; + }; + + DOM.prototype._copyNamespaceMapping = function(document, namespaces) { + document.namespaceToPrefix = namespaces; + }; + + // an implementation of an array, exactly the same as the one in JS + // (although incomplete) itself, this because friggin' IE has problems + // using Array as prototype (it won't update .length on mutations) + function BaseArray() { + for (var i=0; i < arguments.length; i++) { + this[i] = arguments[i]; + }; + this.length = arguments.length; + }; + + BaseArray.prototype.concat = function() { + throw('Not supported'); + }; + + BaseArray.prototype.join = function() { + throw('Not supported'); + }; + + BaseArray.prototype.pop = function() { + var item = this[this.length - 1]; + delete this[this.length - 1]; + this.length = this.length - 1; + return item; + }; + + BaseArray.prototype.push = function(item) { + this[this.length] = item; + this.length = this.length + 1; + return item; + }; + + BaseArray.prototype.reverse = function() { + throw('Not supported'); + }; + + BaseArray.prototype.shift = function() { + var item = this[0]; + for (var i=1; i < this.length; i++) { + this[i-1] = this[i]; + }; + delete this[length - 1]; + this.length = this.length - 1; + return item; + }; + + BaseArray.prototype.unshift = function(item) { + for (var i=0; i < this.length; i++ ) { + this[this.length - i] = this[(this.length - i) - 1]; + }; + this[0] = item; + this.length = this.length + 1; + return ; + }; + + BaseArray.prototype.splice = function() { + // XXX we may want to support this later + throw('Not supported'); + }; + + BaseArray.prototype.toString = function() { + var ret = []; + for (var i=1; i < this.length; i++) { + ret.push(this[i].toString()); + }; + return ret.join(', '); + }; + + // for subclassing and such... + this.BaseArray = BaseArray; + + function NodeList() { + }; + + NodeList.prototype = new BaseArray; + this.NodeList = NodeList; + + NodeList.prototype.item = function(index) { + return this[index]; + }; + + function NamedNodeMap() { + }; + + NamedNodeMap.prototype = new BaseArray; + this.NamedNodeMap = NamedNodeMap; + + NamedNodeMap.prototype.item = function(index) { + return this[index]; + }; + + NamedNodeMap.prototype.getNamedItem = function(name) { + for (var i=0; i < this.length; i++) { + if (this[i].nodeName == name) { + return this[i]; + }; + }; + return undefined; + }; + + NamedNodeMap.prototype.setNamedItem = function(arg) { + // this should generate exceptions, but I'm not sure when... + // XXX how 'bout when arg is not the proper type?!? + for (var i=0; i < this.length; i++) { + if (this[i].nodeName == arg.nodeName) { + this[i] = arg; + return; + }; + }; + this.push(arg); + }; + + NamedNodeMap.prototype.removeNamedItem = function(name) { + // a bit nasty: deleting an element from an array will not actually + // free the index, instead something like undefined or null will end + // up in its place, so we walk the array here, move every element + // behind the item to remove one up, and pop the last item when + // we're done + var delete_mode = false; + for (var i=0; i < this.length; i++) { + if (this[i] === name) { + delete_mode = true; + }; + if (delete_mode) { + this[i] = this[i + 1]; + }; + }; + if (!delete_mode) { + throw( + (new DOMException(DOMException.NOT_FOUND_ERR)) + ); + }; + // the last element is now in the array twice + this.pop(); + }; +}(); + +// XXX shouldn't we make these local? +function createStack() { + // somewhat nasty trick to get a stack trace in Moz + var stack = undefined; + try {notdefined()} catch(e) {stack = e.stack}; + if (stack) { + stack = stack.split('\n'); + stack.shift(); + stack.shift(); + }; + return stack ? stack.join('\n') : ''; +}; + +function getLineNo(stack) { + /* tries to get the line no in Moz */ + if (!stack) { + return; + }; + stack = stack.toString().split('\n'); + var chunks = stack[0].split(':'); + var lineno = chunks[chunks.length - 1]; + if (lineno != '0') { + return lineno; + }; +}; + +function getFileName(stack) { + /* tries to get the filename in Moz */ + if (!stack) { + return; + }; + stack = stack.toString().split('\n'); + var chunks = stack[0].split(':'); + var filename = chunks[chunks.length - 2]; + return filename; +}; + Added: kukit/kukit.js/trunk/3rd_party/johnnydebris.net/dommer/example.html ============================================================================== --- (empty file) +++ kukit/kukit.js/trunk/3rd_party/johnnydebris.net/dommer/example.html Sun Jan 20 20:43:18 2008 @@ -0,0 +1,62 @@ + + + + Dommer example + + + + + + + +

    Start data:

    +
    
    +    

    Result:

    +
    
    +  
    +
    
    Added: kukit/kukit.js/trunk/3rd_party/johnnydebris.net/dommer/run_tests.html
    ==============================================================================
    --- (empty file)
    +++ kukit/kukit.js/trunk/3rd_party/johnnydebris.net/dommer/run_tests.html	Sun Jan 20 20:43:18 2008
    @@ -0,0 +1,53 @@
    +
    +
    +
    +Unit tests for Dommer
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    
    Added: kukit/kukit.js/trunk/3rd_party/johnnydebris.net/dommer/test_dommer.js
    ==============================================================================
    --- (empty file)
    +++ kukit/kukit.js/trunk/3rd_party/johnnydebris.net/dommer/test_dommer.js	Sun Jan 20 20:43:18 2008
    @@ -0,0 +1,366 @@
    +/*
    +    tests.js - unit tests for dommer.js
    +    Copyright (C) 2004-2005 Guido Wesdorp
    +    email johnny at debris.demon.nl
    +
    +    This program is free software; you can redistribute it and/or modify
    +    it under the terms of the GNU General Public License as published by
    +    the Free Software Foundation; either version 2 of the License, or
    +    (at your option) any later version.
    +
    +    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
    +
    +    $Id: dommer.js,v 1.5 2004/07/31 00:10:15 johnny Exp $
    +
    +*/
    +
    +load('../minisax.js/minisax.js');
    +load('../jsbase/string.js');
    +load('../jsbase/array.js');
    +load('dommer.js');
    +
    +var global = this;
    +function setup() {
    +    global.dom = new dommer.DOM();
    +    global.doc = global.dom.createDocument();
    +    global.docfrag = global.doc;
    +};
    +
    +function tearDown() {
    +    global.doc = null;
    +    delete global.dom;
    +};
    +
    +function test_property_access() {
    +    var doc = global.doc;
    +    var el = doc.createElement('foo');
    +    testing.assertThrows(undefined, function() {el.nodeName = 'foo'});
    +};
    +
    +function test_createElement() {
    +    var doc = global.doc;
    +    
    +    var el1 = doc.createElement('foo');
    +    testing.assertEquals(el1.nodeType, 1);
    +    testing.assertEquals(el1.nodeName.toLowerCase(), 'foo');
    +    testing.assertEquals(el1.namespaceURI, null);
    +    testing.assertEquals(el1.ownerDocument, doc);
    +
    +    var el2 = doc.createElementNS('foo:', 'bar');
    +    testing.assertEquals(el2.nodeType, 1);
    +    testing.assertEquals(el2.nodeName.toLowerCase(), 'bar');
    +    testing.assertEquals(el2.namespaceURI, 'foo:');
    +    testing.assertEquals(el2.ownerDocument, doc);
    +
    +    var attr1 = doc.createAttribute('foo');
    +    testing.assertEquals(attr1.nodeType, 2);
    +    testing.assertEquals(attr1.nodeName, 'foo');
    +    testing.assertEquals(attr1.namespaceURI, null);
    +};
    +
    +function test_appendChild() {
    +    var doc = global.doc;
    +    var docfrag = global.docfrag;
    +
    +    var el = doc.createElement('foo');
    +    docfrag.appendChild(el);
    +    if (docfrag == doc) {
    +        // not for browser dom
    +        testing.assertEquals(doc.documentElement, el);
    +    };
    +    testing.assertEquals(el.ownerDocument, doc);
    +    testing.assertEquals(el.parentNode, docfrag);
    +    testing.assertEquals(el.firstChild, null);
    +    testing.assertEquals(el.lastChild, null);
    +    testing.assertEquals(el.previousSibling, null);
    +    testing.assertEquals(el.nextSibling, null);
    +    testing.assertEquals(docfrag.childNodes[0], el);
    +
    +    var el2 = doc.createElement('foo');
    +    if (doc == docfrag) {
    +        testing.assertThrows(undefined, doc.appendChild, doc, el2);
    +    };
    +    el.appendChild(el2);
    +    testing.assertEquals(el2.parentNode, el);
    +    testing.assertEquals(el.childNodes[0], el2);
    +    testing.assertEquals(el.firstChild, el2);
    +    testing.assertEquals(el.lastChild, el2);
    +    testing.assertEquals(el2.previousSibling, null);
    +    testing.assertEquals(el2.nextSibling, null);
    +
    +    var el3 = doc.createElement('foo');
    +    el.appendChild(el3);
    +    testing.assertEquals(el3.parentNode, el);
    +    testing.assertEquals(el.childNodes[1], el3);
    +    testing.assertEquals(el.firstChild, el2);
    +    testing.assertEquals(el.lastChild, el3);
    +    testing.assertEquals(el2.previousSibling, null);
    +    testing.assertEquals(el2.nextSibling, el3);
    +    testing.assertEquals(el3.previousSibling, el2);
    +    testing.assertEquals(el3.nextSibling, null);
    +};
    +
    +function test_removeChild() {
    +    var doc = global.doc;
    +    var docfrag = global.docfrag;
    +
    +    var el = doc.createElement('foo');
    +    docfrag.appendChild(el);
    +
    +    var el2 = doc.createElement('bar');
    +    testing.assertEquals(el2.parentNode, null);
    +    testing.assertEquals(el.firstChild, null);
    +    testing.assertEquals(el.lastChild, null);
    +    if (doc == docfrag) {
    +        testing.assertThrows(dommer.DOMException, el.removeChild, el, el2);
    +    };
    +    
    +    el.appendChild(el2);
    +    testing.assertEquals(el2.parentNode, el);
    +    testing.assertEquals(el.firstChild, el2);
    +    testing.assertEquals(el.lastChild, el2);
    +    testing.assertEquals(el.childNodes[0], el2);
    +
    +    el3 = doc.createElement('baz');
    +    el.appendChild(el3);
    +    testing.assertEquals(el3.parentNode, el);
    +    testing.assertEquals(el.firstChild, el2);
    +    testing.assertEquals(el.lastChild, el3);
    +    testing.assertEquals(el2.nextSibling, el3);
    +    testing.assertEquals(el3.previousSibling, el2);
    +
    +    el.removeChild(el2);
    +    testing.assertEquals(el2.parentNode, null);
    +    testing.assertEquals(el.firstChild, el3);
    +    testing.assertEquals(el.lastChild, el3);
    +    testing.assertEquals(el.childNodes[0], el3);
    +    testing.assertEquals(el2.nextSibling, null);
    +    testing.assertEquals(el3.previousSibling, null);
    +};
    +
    +function test_replaceChild() {
    +    var doc = global.doc;
    +    var docfrag = global.docfrag;
    +
    +    var el = doc.createElement('foo');
    +    docfrag.appendChild(el);
    +
    +    var child1 = doc.createElement('bar');
    +    var child2 = doc.createElement('baz');
    +    var child3 = doc.createElement('qux');
    +    el.appendChild(child1);
    +
    +    testing.assertEquals(el.childNodes.length, 1);
    +    testing.assertEquals(el.childNodes[0], child1);
    +    testing.assertEquals(child1.parentNode, el);
    +
    +    el.appendChild(child3);
    +    testing.assertEquals(el.firstChild, child1);
    +    testing.assertEquals(el.lastChild, child3);
    +    testing.assertEquals(child1.nextSibling, child3);
    +    testing.assertEquals(child3.previousSibling, child1);
    +
    +    el.replaceChild(child2, child1);
    +    testing.assertEquals(child1.parentNode, null);
    +    testing.assertEquals(el.childNodes.length, 2);
    +    testing.assertEquals(el.firstChild, child2);
    +    testing.assertEquals(el.lastChild, child3);
    +    testing.assertEquals(child2.parentNode, el);
    +    testing.assertEquals(child1.nextSibling, null);
    +    testing.assertEquals(child2.nextSibling, child3);
    +    testing.assertEquals(child3.previousSibling, child2);
    +};
    +
    +function test_getAttribute() {
    +    var doc = global.doc;
    +
    +    var el = doc.createElement('foo');
    +    el.setAttribute('bar', 'baz');
    +    testing.assertFalse(el.getAttribute('foo'));
    +    var attr = el.getAttribute('bar');
    +    testing.assertEquals(el.getAttribute('bar'), 'baz');
    +    var attr = el.getAttributeNode('bar');
    +    testing.assertEquals(attr.nodeValue, 'baz');
    +    testing.assertEquals(attr.nodeType, 2);
    +    testing.assertEquals(attr.namespaceURI, null);
    +    testing.assertEquals(attr.ownerDocument, doc);
    +    testing.assertEquals(attr.parentNode, null);
    +    testing.assertEquals(attr.ownerElement, el);
    +
    +    el.setAttributeNS('foo:', 'bar', 'baz');
    +    var attr = el.getAttributeNodeNS('foo:', 'bar');
    +    testing.assertEquals(attr.nodeValue, 'baz');
    +    testing.assertEquals(attr.namespaceURI, 'foo:');
    +};
    +
    +function test_setAttribute() {
    +    var doc = global.doc;
    +    
    +    var el = doc.createElement('foo');
    +    testing.assertThrows(undefined, el.setAttribute, el, 'foo&bar');
    +};
    +
    +function test_toXML() {
    +    var doc = global.doc;
    +    
    +    var foo = doc.createElement('foo');
    +    testing.assertEquals(foo.toXML(), '');
    +    
    +    foo.setAttribute('bar', 'baz');
    +    testing.assertEquals(foo.getAttributeNode('bar').toXML(), 'bar="baz"');
    +    testing.assertEquals(foo.toXML(), '');
    +    
    +    var parent = doc.createElement('parent');
    +    parent.appendChild(foo);
    +    testing.assertEquals(parent.toXML(), '');
    +    
    +    doc.appendChild(parent);
    +    testing.assertEquals(doc.toXML(), '');
    +    // using DOM.toXML() adds an XML declaration
    +    testing.assertEquals(global.dom.toXML(global.doc), 
    +            '\n');
    +
    +    var elwithns = doc.createElementNS('foo:', 'bar');
    +    parent.appendChild(elwithns);
    +    testing.assertEquals(elwithns.toXML(), '');
    +    testing.assertEquals(doc.toXML(), '' +
    +                                    '');
    +
    +    var el1 = doc.createElementNS('foo:', 'bar');
    +    el1.setPrefix('foo');
    +    var el2 = doc.createElementNS('foo:', 'baz');
    +    el2.setPrefix('foo');
    +    el1.appendChild(el2);
    +    testing.assertEquals(el1.toXML(),
    +        '');
    +
    +    var el1 = doc.createElementNS('foo:', 'bar');
    +    el1.setPrefix('foo');
    +    var el2 = doc.createElementNS('baz:', 'qux');
    +    el2.setPrefix('foo');
    +    el1.appendChild(el2);
    +    testing.assertEquals(el1.toXML(), 
    +        '');
    +
    +    var el1 = doc.createElementNS('foo:', 'foo:bar');
    +    el1.setAttributeNS('baz:', 'baz:qux', 'quux');
    +    testing.assertEquals(el1.toXML(), 
    +            '');
    +};
    +
    +function test_namedNodeMap() {
    +    var nodemap = new dommer.NamedNodeMap();
    +
    +    var nodes = {};
    +    for (var i=0; i < 10; i++) {
    +        var node = global.doc.createElement('node-' + i);
    +        nodes[i] = node;
    +        nodemap.setNamedItem(node);
    +    };
    +
    +    testing.assertEquals(nodemap.length, 10);
    +    testing.assertEquals(nodemap[0].nodeName.toLowerCase(), 'node-0');
    +    testing.assertEquals(nodemap[0], nodemap.getNamedItem('node-0'));
    +    testing.assertEquals(nodemap[nodemap.length - 1], 
    +                         nodemap.getNamedItem('node-9'));
    +
    +    nodemap.removeNamedItem(nodemap[4]);
    +    testing.assertEquals(nodemap.length, 9);
    +    testing.assertEquals(nodemap[3], nodes[3]);
    +    testing.assertEquals(nodemap[4], nodes[5]);
    +    testing.assertEquals(nodemap[8], nodes[9]);
    +};
    +
    +function test_cloneNode() {
    +    var doc = global.doc;
    +
    +    var foo = doc.createElement('foo');
    +    foo.setAttribute('bar', 'bar');
    +    var baz = doc.createElement('baz');
    +    baz.appendChild(foo);
    +    
    +    var clone = baz.cloneNode(false);
    +    testing.assertEquals(clone.nodeName.toLowerCase(), 'baz');
    +    testing.assertFalse(clone.hasChildNodes());
    +    
    +    var clone = baz.cloneNode(true);
    +    testing.assertEquals(clone.nodeName.toLowerCase(), 'baz');
    +    testing.assert(clone.hasChildNodes());
    +    testing.assertEquals(clone.childNodes.length, 1);
    +    testing.assertEquals(clone.childNodes[0].nodeName.toLowerCase(), 'foo');
    +    testing.assertEquals(clone.childNodes[0].attributes.length, 1);
    +    testing.assertEquals(
    +        clone.childNodes[0].attributes[0].nodeName.toLowerCase(), 'bar');
    +    testing.assertEquals(clone.childNodes[0].getAttribute('bar'), 'bar');
    +};
    +
    +function test_parseXML() {
    +    var dom = new dommer.DOM();
    +
    +    var xml1 = '';
    +    var doc = dom.parseXML(xml1);
    +    testing.assertEquals(doc.documentElement.nodeName, 'foo');
    +    testing.assertEquals(doc.childNodes.length, 1);
    +    testing.assertEquals(doc.documentElement.childNodes.length, 0);
    +
    +    var xml2 = '';
    +    var doc = dom.parseXML(xml2);
    +    testing.assertEquals(doc.documentElement.nodeName, 'foo');
    +    testing.assertEquals(doc.documentElement.childNodes.length, 1);
    +    testing.assertEquals(doc.documentElement.childNodes[0].nodeName, 'bar');
    +
    +    var xml3 = '';
    +    var doc = dom.parseXML(xml3);
    +    var bar = doc.documentElement.childNodes[0];
    +    testing.assertEquals(bar.attributes.length, 1);
    +    testing.assertEquals(bar.attributes[0].nodeName, 'baz');
    +    testing.assertEquals(bar.attributes[0].nodeValue, 'baz');
    +
    +    var xml4 = '';
    +    var doc = dom.parseXML(xml4);
    +    testing.assertEquals(doc.documentElement.namespaceURI, 'bar:');
    +    testing.assertEquals(doc.documentElement.prefix, null);
    +
    +    var xml5 = '';
    +    var doc = dom.parseXML(xml5);
    +    testing.assertEquals(doc.documentElement.nodeName, 'foo:bar'); 
    +    testing.assertEquals(doc.documentElement.localName, 'bar');
    +    testing.assertEquals(doc.documentElement.prefix, 'foo');
    +    testing.assertEquals(doc.documentElement.namespaceURI, 'baz:');
    +
    +    var xml6 = 'bar';
    +    var doc = dom.parseXML(xml6);
    +    testing.assertEquals(doc.documentElement.childNodes.length, 1);
    +    testing.assertEquals(doc.documentElement.firstChild.nodeType, 3);
    +    testing.assertEquals(doc.documentElement.firstChild.nodeValue, 'bar');
    +
    +    var xml7 = '';
    +    var doc = dom.parseXML(xml7);
    +    testing.assertEquals(doc.documentElement.attributes.length, 1);
    +    testing.assertEquals(doc.documentElement.attributes[0].nodeName,
    +                         'bar:baz');
    +    testing.assertEquals(doc.documentElement.attributes[0].localName, 'baz');
    +    testing.assertEquals(doc.documentElement.attributes[0].nodeValue, 'qux');
    +    testing.assertEquals(doc.documentElement.attributes[0].namespaceURI,
    +                         'bar:');
    +    testing.assertEquals(doc.documentElement.attributes[0].prefix, 'bar');
    +
    +    var xml8 = '' +
    +               '';
    +    var doc = dom.parseXML(xml8);
    +    testing.assertEquals(doc.toXML(), xml8);
    +
    +    var xml9 = '' +
    +               '';
    +    var expected = '';
    +    var doc = dom.parseXML(xml9);
    +    testing.assertEquals(doc.toXML(), expected);
    +};
    +
    
    Added: kukit/kukit.js/trunk/3rd_party/johnnydebris.net/dommer/version.txt
    ==============================================================================
    --- (empty file)
    +++ kukit/kukit.js/trunk/3rd_party/johnnydebris.net/dommer/version.txt	Sun Jan 20 20:43:18 2008
    @@ -0,0 +1 @@
    +0.4
    
    Added: kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/LICENSE.txt
    ==============================================================================
    --- (empty file)
    +++ kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/LICENSE.txt	Sun Jan 20 20:43:18 2008
    @@ -0,0 +1,31 @@
    +JSBase - Copyright (c) 2004-2007, Guido Wesdorp
    +All rights reserved.
    +
    +Redistribution and use in source and binary forms, with or without
    +modification, are permitted provided that the following conditions are
    +met:
    +
    +
    +    * Redistributions of source code must retain the above copyright
    +      notice, this list of conditions and the following disclaimer.
    +
    +    * Redistributions in binary form must reproduce the above
    +      copyright notice, this list of conditions and the following
    +      disclaimer in the documentation and/or other materials provided
    +      with the distribution.
    +
    +    * Neither the name of JSBase nor the names of its contributors may
    +      be used to endorse or promote products derived from this
    +      software without specific prior written permission.
    +
    +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    
    Added: kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/README.txt
    ==============================================================================
    --- (empty file)
    +++ kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/README.txt	Sun Jan 20 20:43:18 2008
    @@ -0,0 +1,137 @@
    +JSBase
    +=======
    +
    +What is it?
    +------------
    +
    +This is a collection of bits of JavaScript helper functionality, to solve 
    +common problems encountered when programming JavaScript code. The library was
    +mostly written because I needed certain generic functionality available for
    +using in different JS projects, but will be valuable for anyone writing JS
    +code. The strenghts of this library are:
    +
    +  * everything is written in 'modules', which provide their own namespace and
    +    are seperately loadable (certain modules do depend on others, but I tried
    +    to keep this down to a minimum)
    +
    +  * care has been taken that it's possible to use this library *at any time, 
    +    on any platform*, by not depending on any variables being available, or 
    +    isolating the instances where a variable (for instance 'window') is 
    +    required
    +
    +  * the library should not clash with other libraries
    +    
    +  * no overriding or extending of built-in data types or functionality
    +
    +  * the library is light-weight, and has no impact on the way the JS is 
    +    written, although it shows some patterns to use concerning 'OO' programming
    +    in JS, it does not make the code harder to read or understand for people
    +    that don't know the library by using or enforcing complex patterns
    +
    +  * the functionality in this library can, with the exception of few very 
    +    browser-specific functions, can be used in any JS environment (e.g. the
    +    unit tests are ran using SpiderMonkey, see 'unit tests' below)
    +
    +  * the library is simple and self-explanatory (of course this is not an excuse
    +    for not providing documentation! my excuse for that is lack of time...)
    +
    +What kind of functionality should I expect?
    +--------------------------------------------
    +
    +This library provides solutions to problems in the core language (e.g.
    +functions to deal more easily with arrays and strings) and somewhat lower level
    +problems in JS environments (e.g. a cross-platform print() function to write to
    +stdout or the document in some way). There are some helpers to solve browser
    +incompatibility problems (e.g. a 'getXMLHttpRequest()' function and
    +cross-browser event handling) and wrappers for things that are just very badly
    +implemented in browsers (e.g.  a schedule() function which you can pass a
    +normal callable and additional arguments to, a wrapper to solve the problem
    +where 'this' in a method body refers to something else than the object a method
    +is implemented on and proper exception classes).
    +
    +More detailed description of the modules
    +------------------------------------------
    +
    +The modules, with a short description:
    +
    +  * array.js
    +
    +    a set of functions to help with arrays, basically stuff that the JS core 
    +    should have provided for
    +
    +  * exception.js
    +
    +    this provides the Exception base class and some subclasses, the excepsions
    +    raised by the library use these to allow distinguishing between different
    +    exceptions more easily, and also they provide a traceback if the platform
    +    allows that (mainly Mozilla-related platforms)
    +
    +  * function.js
    +
    +    this currently provides a single function, that helps fixing the 'this'
    +    problem, where 'this' inside methods points to something else than the
    +    object which the methods are defined on (happens e.g. on event handling
    +    in browsers)
    +
    +  * misclib.js
    +
    +    a set of miscellaneous functionality, such as a schedule() method for 
    +    scheduling function calls (to replace window.setTimeout), cross-browser
    +    event handling (also fixing memory leaks in IE), a repr() function to
    +    create string representations of objects (also recursively, if desired),
    +    a dir() function to view the attributes of objects, and a print() function
    +    that makes messages visible in different ways, depending on the platform
    +    you're on (allowing for presenting text to a user both in browsers and 
    +    command line environments)
    + 
    +  * number.js
    +
    +    number related functions
    +
    +  * server.js
    +
    +    cross-browser server interaction, some higher-level 'AJAX'-related 
    +    functions
    +
    +  * string.js
    +
    +    string related functions
    +
    +  * testing.js
    +
    +    functionality to help debugging and testing your applications, it both
    +    harbours a couple of helper functions you can call from your code, as
    +    functionality to unit-test that code (with py.test integration, see below)
    +    
    +Unit testing
    +-------------
    +
    +The 'testing.js' module contains some functions that can be used to write very
    +simple unit tests (see the module for more information for now). Also there's
    +a 'conftest.py' and some stuff in the 'testing' dir that allows you to run
    +JavaScript unit tests using the Python 'py.test' unit test runner, part of the
    +`py lib`_ library.
    +
    +.. _`py lib`: http://codespeak.net/py
    +
    +Other files
    +------------
    +
    +The other files in the directory are documentation and license information
    +and such, and unit tests for the package and related files.
    +
    +Note
    +----
    +
    +Note that the library is currently not in a state in which it can be considered
    +a complete solution: it merely provides me personally the stuff I needed the
    +period I used it... Hopefully at some point it will be complete enough to use
    +by others, but right now don't expect it to solve all your general JS problems
    +yet.
    +
    +Questions, bug reports, etc.
    +-----------------------------
    +
    +If you have questions, bug reports, patches or remarks, please send an email
    +to johnny at johnnydebris.net.
    +
    
    Added: kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/__init__.py
    ==============================================================================
    
    Added: kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/array.js
    ==============================================================================
    --- (empty file)
    +++ kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/array.js	Sun Jan 20 20:43:18 2008
    @@ -0,0 +1,114 @@
    +/*****************************************************************************
    + *
    + * Copyright (c) 2004-2007 Guido Wesdorp. All rights reserved.
    + *
    + * This software is distributed under the terms of the JSBase
    + * License. See LICENSE.txt for license text.
    + *
    + *****************************************************************************/
    +
    +var global = this;
    +global.array = new function() {
    +    var array = this;
    +    
    +    this.contains = function(a, element, objectequality) {
    +        /* see if some value is in a */
    +        // DEPRECATED!!! use array.indexOf instead
    +        return (this.indexOf(a, element, !objectequality) > -1);
    +    };
    +
    +    this.indexOf = function(a, element, compareValues) {
    +        for (var i=0; i < a.length; i++) {
    +            if (!compareValues) {
    +                if (element === a[i]) {
    +                    return i;
    +                };
    +            } else {
    +                if (element == a[i]) {
    +                    return i;
    +                };
    +            };
    +        };
    +        return -1;
    +    };
    +
    +    this.removeDoubles = function(a) {
    +        var ret = [];
    +        for (var i=0; i < a.length; i++) {
    +            if (!this.contains(ret, a[i])) {
    +                ret.push(a[i]);
    +            };
    +        };
    +        return ret;
    +    };
    +
    +    this.map = function(a, func) {
    +        /* apply 'func' to each element in the array (in-place!!) */
    +        for (var i=0; i < a.length; i++) {
    +            a[i] = func(a[i]);
    +        };
    +        return this;
    +    };
    +
    +    this.reversed = function(a) {
    +        var ret = [];
    +        for (var i = a.length; i > 0; i--) {
    +            ret.push(a[i - 1]);
    +        };
    +        return ret;
    +    };
    +
    +    this.StopIteration = function(message) {
    +        if (message !== undefined) {
    +            this._initialize('StopIteration', message);
    +        };
    +    };
    +
    +    if (global.exception) {
    +        StopIteration.prototype = global.exception.Exception;
    +    };
    +
    +    var Iterator = this.Iterator = function(a) {
    +        if (a) {
    +            this._initialize(a);
    +        };
    +    };
    +
    +    Iterator._initialize = function(a) {
    +        this._array = a;
    +        this._i = 0;
    +    };
    +
    +    Iterator.next = function() {
    +        if (this._i >= this._array.length) {
    +            this._i = 0;
    +            throw(StopIteration('no more items'));
    +        };
    +        return this._i++;
    +    };
    +
    +    this.iterate = function(a) {
    +        /*  iterate through array 'a'
    +
    +            this returns the n-th item of array 'a', where n is the number of
    +            times this function has been called on 'a' before
    +
    +            when the items are all visited, the function resets the counter and
    +            starts from the start
    +
    +            note that this annotates the array with information about iteration
    +            using the attribute '__iter_index__', remove this or set to 0 to
    +            reset
    +
    +            this does not work well with arrays that have 'undefined' as one of
    +            their values!!
    +        */
    +        if (!a.__iter_index__) {
    +            a.__iter_index__ = 0;
    +        } else if (a.__iter_index__ >= a.length) {
    +            a.__iter_index__ = undefined;
    +            return undefined;
    +        };
    +        return a[a.__iter_index__++];
    +    };
    +}();
    
    Added: kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/conftest.py
    ==============================================================================
    --- (empty file)
    +++ kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/conftest.py	Sun Jan 20 20:43:18 2008
    @@ -0,0 +1,166 @@
    +# JS unit test support for py.test - (c) 2007 Guido Wesdorp. All rights
    +# reserved
    +#
    +# This software is distributed under the terms of the JSBase
    +# License. See LICENSE.txt for license text.
    +
    +import py
    +
    +here = py.magic.autopath().dirpath()
    +
    +class JSTest(py.test.collect.Item):
    +    def run(self):
    +        path = self.fspath
    +        test = self.name.split('/')[-1]
    +        paths = [path.strpath, 
    +                    (here / 'exception.js').strpath,
    +                    (here / 'testing.js').strpath,
    +                    (here / 'misclib.js').strpath,
    +                ]
    +        testjs = (here / 'testing/testbase.js').read() % (
    +                    paths, test, '__main__')
    +        curdir = str(py.path.local('.'))
    +        py.std.os.chdir(str(self.fspath.dirpath()))
    +        try:
    +            jspath = self.fspath.new(basename='__testbase_temp.js')
    +            try:
    +                jspath.write(testjs)
    +                pipe = py.std.os.popen('js "%s"' % (jspath,))
    +                try:
    +                    data = {}
    +                    for line in pipe:
    +                        done = self._handle_line(line, data)
    +                        if done:
    +                            errdata = data[data['current']]
    +                            if errdata:
    +                                self.fail(errdata)
    +                finally:
    +                    pipe.close()
    +            finally:
    +                jspath.remove()
    +        finally:
    +            py.std.os.chdir(curdir)
    +
    +    def fail(self, errdata):
    +        py.test.fail(
    +        '\nJS traceback (most recent last): \n%s\n%s\n' % (
    +                (errdata[1:] and 
    +                    self._format_tb(errdata[1:-5]) or
    +                    'no traceback available'
    +                ),
    +                errdata[0], 
    +            )
    +        )
    +
    +    _handling_traceback = False
    +    def _handle_line(self, line, data):
    +        line = line[:-1]
    +        if line.startswith('end test'):
    +            return True
    +        if self._handling_traceback and line != 'end traceback':
    +            data[data['current']].append(line)
    +        if line.startswith('PRINTED: '):
    +            print line[9:]
    +        elif line.startswith('running test '):
    +            testname = line[13:]
    +            data['current'] = testname
    +            data[testname] = []
    +        elif line.startswith('success'):
    +            pass
    +        elif line.startswith('failure: '):
    +            data[data['current']].append(line[9:])
    +        elif line.startswith('traceback'):
    +            self._handling_traceback = True
    +        elif line.startswith('end traceback'):
    +            self._handling_traceback = False
    +
    +    def _format_tb(self, tb):
    +        tb.reverse()
    +        ret = []
    +        for line in tb:
    +            line = line.strip()
    +            if not line:
    +                continue
    +            funcsig, lineinfo = line.split('@', 1)
    +            fpath, lineno = lineinfo.rsplit(':', 1)
    +            fname = py.path.local(fpath).basename
    +            # XXX might filter out too much... but it's better than leaving it
    +            # all in (since it adds a couple of lines to the end of the tb,
    +            # making it harder to find the problem line)
    +            if fname in ['__testbase_temp.js', '__testbase_find.js',
    +                            'exception.js']: 
    +                continue
    +            lineno = int(lineno)
    +            if lineno == 0:
    +                fname = ""
    +            ret.append('File "%s", line %s, in %s' % (
    +                        fname, lineno, funcsig or '?'))
    +            if lineno > 0:
    +                line = py.path.local(fpath).readlines()[lineno - 1]
    +                ret.append('    %s' % (line.strip(),))
    +        return '\n'.join(['  %s' % (r,) for r in ret]) 
    +            
    +class JSChecker(py.test.collect.Module):
    +    def __repr__(self): 
    +        return py.test.collect.Collector.__repr__(self) 
    +
    +    def setup(self): 
    +        pass 
    +
    +    def teardown(self): 
    +        pass 
    +
    +    def run(self): 
    +        findjs = here.join('testing/findtests.js').read() % (
    +                    self.fspath.strpath, '__main__')
    +        curdir = str(py.path.local('.'))
    +        py.std.os.chdir(str(self.fspath.dirpath()))
    +        tests = []
    +        try:
    +            jspath = self.fspath.new(basename='__findtests.js')
    +            try:
    +                jspath.write(findjs)
    +                stdin, pipe, stderr = py.std.os.popen3('js "%s"' % (jspath,))
    +                try:
    +                    error = stderr.next()
    +                    print 'Error read:', error
    +                except StopIteration:
    +                    pass
    +                else:
    +                    if error.find('command not found') > -1:
    +                        py.test.skip(
    +                            'error running "js" (SpiderMonkey), which is '
    +                            'required to run JS tests')
    +                    else:
    +                        py.test.fail(error)
    +                    return
    +                try:
    +                    for line in pipe:
    +                        tests.append(line.strip())
    +                finally:
    +                    py.std.sys.stdout = py.std.sys.__stdout__
    +                    pipe.close()
    +            finally:
    +                jspath.remove()
    +        finally:
    +            py.std.os.chdir(curdir)
    +        return ['%s/%s' % (self.fspath.basename, test) for test in tests]
    +
    +    def join(self, name):
    +        if py.path.local(name).dirpath().strpath.endswith('.js'):
    +            return JSTest(name, self)
    +        return super(JSChecker, self).join(name)
    +
    +class Directory(py.test.collect.Directory):
    +    def run(self):
    +        if self.fspath == here:
    +            return [p.basename for p in self.fspath.listdir('test_*') if
    +                    p.ext in ['.py', '.js']]
    +        return super(Directory, self).run()
    +
    +    def join(self, name):
    +        if not name.endswith('.js'):
    +            return super(Directory, self).join(name)
    +        p = self.fspath.join(name)
    +        if p.check(file=1):
    +            return JSChecker(p, parent=self)
    
    Added: kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/exception.js
    ==============================================================================
    --- (empty file)
    +++ kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/exception.js	Sun Jan 20 20:43:18 2008
    @@ -0,0 +1,158 @@
    +/*****************************************************************************
    + *
    + * Copyright (c) 2004-2007 Guido Wesdorp. All rights reserved.
    + *
    + * This software is distributed under the terms of the JSBase
    + * License. See LICENSE.txt for license text.
    + *
    + *****************************************************************************/
    +
    +var global = this;
    +global.exception = new function() {
    +    /* Exception handling in a somewhat coherent manner */
    +
    +    var exception = this;
    +
    +    this.Exception = function(message) {
    +        /* base class of exceptions */
    +        if (message !== undefined) {
    +            this._initialize('Exception', message);
    +        };
    +    };
    +
    +    this.Exception.prototype._initialize = function(name, message) {
    +        this.name = name;
    +        this.message = message;
    +        var stack = this.stack = exception._createStack();
    +        this.lineNo = exception._getLineNo(stack);
    +        this.fileName = exception._getFileName(stack);
    +    };
    +
    +    this.Exception.prototype.toString = function() {
    +        var lineNo = this.lineNo;
    +        var fileName = this.fileName;
    +        var stack = this.stack;
    +        var exc = this.name + ': ' + this.message + '\n';
    +        if (lineNo || fileName || stack) {
    +            exc += '\n';
    +        };
    +        if (fileName) {
    +            exc += 'file: ' + fileName;
    +            if (lineNo) {
    +                exc += ', ';
    +            } else {
    +                exc += '\n';
    +            };
    +        };
    +        if (lineNo) {
    +            exc += 'line: ' + lineNo + '\n';
    +        };
    +        if (stack) {
    +            exc += '\n';
    +            var lines = stack.split('\n');
    +            for (var i=0; i < lines.length; i++) {
    +                var line = lines[i];
    +                if (line.charAt(0) == '(') {
    +                    line = 'function' + line;
    +                };
    +                exc += line + '\n';
    +            };
    +        };
    +        return exc;
    +    };
    +
    +    this.ValueError = function(message) {
    +        /* raised on providing invalid values */
    +        if (message !== undefined) {
    +            this._initialize('ValueError', message);
    +        };
    +    };
    +
    +    this.ValueError.prototype = new this.Exception;
    +
    +    this.AssertionError = function(message) {
    +        /* raised when an assertion fails */
    +        if (message !== undefined) {
    +            this._initialize('AssertionError', message);
    +        };
    +    };
    +
    +    this.AssertionError.prototype = new this.Exception;
    +
    +    // XXX need to define a load of useful exceptions here
    +    this.NotSupported = function(message) {
    +        /* raised when a feature is not supported on the running platform */
    +        if (message !== undefined) {
    +            this._initialize('NotSupported', message);
    +        };
    +    };
    +
    +    this.NotSupported.prototype = new this.Exception;
    +    
    +    this.NotFound = function(message) {
    +        /* raised when something is not found */
    +        if (message !== undefined) {
    +            this._initialize('NotFound', message);
    +        };
    +    };
    +
    +    this.NotFound.prototype = new this.Exception;
    +
    +    this.HTTPError = function(status) {
    +        if (status !== undefined) {
    +            // XXX need to get the message for the error here...
    +            this._initialize('HTTPError', status);
    +        };
    +    };
    +
    +    this.HTTPError.prototype = new this.Exception;
    +
    +    this.MissingDependency = function(missing, from) {
    +        /* raised when some dependency can not be resolved */
    +        if (missing !== undefined) {
    +            var message = missing;
    +            if (from) {
    +                message += ' (from ' + from + ')';
    +            };
    +            this._initialize('MissingDependency', message);
    +        };
    +    };
    +
    +    this.NotFound.prototype = new this.Exception;
    +
    +    this._createStack = function() {
    +        /* somewhat nasty trick to get a stack trace in (works only in Moz) */
    +        var stack = undefined;
    +        try {notdefined()} catch(e) {stack = e.stack};
    +        if (stack) {
    +            stack = stack.split('\n');
    +            stack.shift();
    +            stack.shift();
    +        };
    +        return stack ? stack.join('\n') : '';
    +    };
    +
    +    this._getLineNo = function(stack) {
    +        /* tries to get the line no in (works only in Moz) */
    +        if (!stack) {
    +            return;
    +        };
    +        stack = stack.toString().split('\n');
    +        var chunks = stack[0].split(':');
    +        var lineno = chunks[chunks.length - 1];
    +        if (lineno != '0') {
    +            return lineno;
    +        };
    +    };
    +
    +    this._getFileName = function(stack) {
    +        /* tries to get the filename in (works only in Moz) */
    +        if (!stack) {
    +            return;
    +        };
    +        stack = stack.toString().split('\n');
    +        var chunks = stack[0].split(':');
    +        var filename = chunks[chunks.length - 2];
    +        return filename;
    +    };
    +}();
    
    Added: kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/function.js
    ==============================================================================
    --- (empty file)
    +++ kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/function.js	Sun Jan 20 20:43:18 2008
    @@ -0,0 +1,83 @@
    +/*****************************************************************************
    + *
    + * Copyright (c) 2004-2007 Guido Wesdorp. All rights reserved.
    + *
    + * This software is distributed under the terms of the jsbase
    + * License. See LICENSE.txt for license text.
    + *
    + *****************************************************************************/
    +
    +var global = this;
    +global.func = new function() {
    +    this.fixContext = function(f, context) {
    +        /* Return a function wrapped, so that 'this' points to 'context'
    +            
    +            Under certain circumstances, methods get called with the 'this' 
    +            variable pointing to something else than the object the method is
    +            defined on. In that case, one can use some trick with nested scopes 
    +            and Function.apply() to get this to refer to the object again. This
    +            method provides a generic wrapper, that not only fixes 'this'
    +            but also allows passing additional arguments to handlers.
    +
    +            Example:
    +
    +            // create an object with a method that will serve as an event 
    +            // handler later on
    +            function Foo() {
    +                this.bar = 1;
    +                this.baz = function(event, some_arg) {
    +                    // if the following would be done when this method would not
    +                    // get wrapped, 'this' would point to the Event object rather
    +                    // than the Foo one, resulting in a name lookup problem
    +                    alert('this.bar: ' + this.bar + ', some_arg: ' + some_arg);
    +                };
    +            };
    +
    +            // create a Foo
    +            var foo = new Foo();
    +
    +            // get some element to register some event on
    +            var el = document.getElementById('some_element');
    +
    +            // now we're going to register the foo.baz method as an 
    +            // event handler for the 'onclick' event on the element,
    +            // but we're wrapping it first, and pass in some argument just
    +            // for show
    +            // using the Mozilla style of event registration, see 
    +            // event.js' registerEventHandler() for a cross-browser way
    +            el.addEventListener('click', func.fixContext(foo.bar, foo, 2), 
    +                                    false);
    +
    +            The method will be called with the following arguments:
    +
    +            - the object that 'this' would point to when the method would have
    +                been used unwrapped
    +
    +            - the additional arguments the fixContext method was called with
    +
    +            - the arguments the wrapped version was called with
    +
    +        */
    +        var orgargs = [];
    +        for (var i=0; i < arguments.length; i++) {
    +            if (i == 0 || (context && i == 1)) {
    +                continue;
    +            };
    +            orgargs.push(arguments[i]);
    +        };
    +        if (!context) {
    +            context = window;
    +        };
    +        var wrapper = function() {
    +            var funcargs = [this];
    +            for (var i=0; i < orgargs.length; i++) {
    +                funcargs.push(orgargs[i]);
    +            };
    +            for (var i=0; i < arguments.length; i++) {
    +                funcargs.push(arguments[i]);
    +            };
    +            return f.apply(context, funcargs);
    +        };
    +        return wrapper;
    +    };
    +}();
    
    Added: kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/misclib.js
    ==============================================================================
    --- (empty file)
    +++ kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/misclib.js	Sun Jan 20 20:43:18 2008
    @@ -0,0 +1,350 @@
    +/*****************************************************************************
    + *
    + * Copyright (c) 2004-2007 Guido Wesdorp. All rights reserved.
    + *
    + * This software is distributed under the terms of the JSBase
    + * License. See LICENSE.txt for license text.
    + *
    + *****************************************************************************/
    +
    +var global = this;
    +global.misclib = new function() {
    +    /* This lib mostly contains fixes for common problems in JS, additions to
    +        the core global functions and wrappers for fixing browser issues.
    +
    +        See the comments in the code for further explanations.
    +    */
    +
    +    // reference to the lib to reach it from the functions/classes
    +    var misclib = this;
    +
    +    var Timer = function() {
    +        /* Wrapper around window.setTimeout, to solve number of problems:
    +        
    +            * setTimeout gets a string rather than a function reference as an
    +                argument
    +
    +            * setTimeout can not handle arguments to the callable properly, 
    +                since it's evaluated in the window namespace, not in the current
    +                scope
    +
    +            Usage:
    +
    +                // call the global 'schedule' function to register a function
    +                // called 'foo' on the current (imaginary) object, passing in
    +                // a variable called 'bar' as an argument, so it gets called 
    +                // after 1000 msecs
    +                window.misclib.schedule(this, this.foo,  1000, bar);
    +
    +            Note that if you don't care about 'this' inside the function 
    +            you register, you can just pass in a ref to the 'window' object
    +            as the first argument. No lookup is done in the namespace, the
    +            first argument is only used as the 'this' variable inside the
    +            function.
    +        */
    +        this.lastid = 0;
    +        this.functions = {};
    +        
    +        this.registerCallable = function(object, func, timeout) {
    +            /* register a function to be called with a timeout
    +
    +                args: 
    +                    object - the context in which to call the function ('this')
    +                    func - the function
    +                    timeout - timeout in millisecs
    +                    
    +                all other args will be passed 1:1 to the function when called
    +            */
    +            var args = new Array();
    +            for (var i=3; i < arguments.length; i++) {
    +                args.push(arguments[i]);
    +            }
    +            var id = this._createUniqueId();
    +            this.functions[id] = new Array(object, func, args);
    +            // setTimeout will be called in the module namespace, where the 
    +            // timer_instance variable also resides (see below)
    +            setTimeout("window.misclib.timer_instance." +
    +                        "_handleFunction(" + id + ")", timeout);
    +        };
    +
    +        this._handleFunction = function(id) {
    +            /* private method that does the actual function call */
    +            var obj = this.functions[id][0];
    +            var func = this.functions[id][1];
    +            var args = this.functions[id][2];
    +            this.functions[id] = null;
    +            func.apply(obj, args);
    +        };
    +
    +        this._createUniqueId = function() {
    +            /* create a unique id to store the function by */
    +            while (this.lastid in this.functions && 
    +                        this.functions[this.lastid]) {
    +                this.lastid++;
    +                if (this.lastid > 100000) {
    +                    this.lastid = 0;
    +                }
    +            }
    +            return this.lastid;
    +        };
    +    };
    +
    +    // create a timer instance in the module namespace
    +    var timer_instance = this.timer_instance = new Timer();
    +
    +    // this is the function that should be called to register callables
    +    this.schedule = function() {
    +            timer_instance.registerCallable.apply(timer_instance, arguments)};
    +
    +    // cross-browser event registration
    +    var events_supported = true;
    +    try {
    +        window;
    +    } catch(e) {
    +        events_supported = false;
    +    };
    +    
    +    if (events_supported) {
    +        // first some privates
    +        
    +        // a registry for events so they can be unregistered on unload of the 
    +        // body
    +        var event_registry = {};
    +
    +        // an iterator for unique ids
    +        var currid = 0;
    +
    +        // just to make some guy on irc happy, store references to 
    +        // browser-specific wrappers so we don't have to find out the type of
    +        // browser on every registration (yeah, yeah, i admit it was quite a 
    +        // good tip... ;)
    +        var reg_handler = null;
    +        var unreg_handler = null;
    +        if (window.addEventListener) {
    +            reg_handler = function(element, eventname, handler) {
    +                // XXX not sure if anyone ever uses the last argument...
    +                element.addEventListener(eventname, handler, false);
    +            };
    +            unreg_handler = function(element, eventname, handler) {
    +                element.removeEventListener(eventname, handler, false);
    +            };
    +        } else if (window.attachEvent) {
    +            reg_handler = function(element, eventname, handler) {
    +                element.attachEvent('on' + eventname, handler);
    +            };
    +            dereg_handler = function(element, eventname, handler) {
    +                element.detachEvent('on' + eventname, handler);
    +            };
    +        } else {
    +            reg_handler = function(element, eventname, handler) {
    +                var message = 'Event registration not supported or not ' +
    +                                'understood on this platform';
    +                if (global.exception) {
    +                    throw(new exception.NotSupported(message));
    +                } else {
    +                    throw(message);
    +                };
    +            };
    +        };
    +
    +        this.addEventHandler = function(element, eventname, handler, context) {
    +            /* Method to register an event handler
    +
    +                Works in standards compliant browsers and IE, and solves a
    +                number of different problems. Most obviously it makes that 
    +                there's only a single function to use and memorize, but also 
    +                it makes that 'this' inside the function points to the context 
    +                (usually you'll want to pass in the object the method is 
    +                defined on), and it fixes memory leaks (IE is infamous for 
    +                leaking memory, which can lead to problems if you register a 
    +                lot of event handlers, especially since the memory leakage 
    +                doesn't disappear on page reloads, see e.g. 
    +                http://www.bazon.net/mishoo/articles.epl?art_id=824).
    +            
    +                Arguments:
    +                
    +                    * element - the object to register the event on
    +                    
    +                    * eventname - a string describing the event (Mozilla style, 
    +                        so without the 'on')
    +                    
    +                    * handler - a reference to the function to be called when 
    +                        the event occurs
    +
    +                    * context - the 'this' variable inside the function
    +
    +                The arguments passed to the handler:
    +
    +                    * event - a reference to the event fired
    +
    +                    * all arguments passed in to this function besides the ones
    +                        described
    +                        
    +            */
    +            var args = new Array();
    +            for (var i=4; i < arguments.length; i++) {
    +                args.push(arguments[i]);
    +            };
    +            var wrapper = function(event) {
    +                args = [event].concat(args);
    +                handler.apply(context, args)
    +                args.shift();
    +            };
    +            currid++;
    +            event_registry[currid] = [element, eventname, wrapper];
    +            reg_handler(element, eventname, wrapper);
    +            // return the wrapper so the event can be unregistered later on
    +            return currid;
    +        };
    +
    +        this.removeEventHandler = function(regid) {
    +            /* method to remove an event handler for both IE and Mozilla 
    +            
    +                pass in the id returned by addEventHandler
    +            */
    +            // remove the entry from the event_registry
    +            var args = event_registry[regid];
    +            if (!args) {
    +                var message = 'removeEventListener called with ' +
    +                                'unregistered id';
    +                if (global.exception) {
    +                    throw((new exception.NotFound(message)));
    +                } else {
    +                    throw(message);
    +                };
    +            };
    +            delete event_registry[regid];
    +            unreg_handler(args[0], args[1], args[2]);
    +        };
    +
    +        this.removeAllEventHandlers = function() {
    +            for (var id in event_registry) {
    +                try {
    +                    misclib.removeEventHandler(id);
    +                } catch(e) {
    +                    // element must have been discarded or something...
    +                };
    +            };
    +        };
    +    };
    +
    +    // string representation of objects
    +    this.safe_repr = function(o) {
    +        var visited = {}; 
    +        var ret = misclib._repr_helper(o, visited);
    +        delete visited;
    +        return ret;
    +    };
    +
    +    this.repr = function(o, dontfallback) {
    +        try {
    +            return misclib._repr_helper(o);
    +        } catch(e) {
    +            // when something fails here, we assume it's because of recursion
    +            // and fall back to safe_repr()
    +            if (dontfallback) {
    +                throw(e);
    +            };
    +            return misclib.safe_repr(o);
    +        };
    +    };
    +
    +    this._repr_helper = function(o, visited) {
    +        var newid = 0;
    +        if (visited) {
    +            // XXX oomph... :|
    +            for (var attr in visited) {
    +                if (visited[attr] === o) {
    +                    return '#' + attr + '#';
    +                };
    +                newid++;
    +            };
    +        };
    +        var ret = 'unknown?';
    +        var type = typeof o;
    +        switch (type) {
    +            case 'undefined':
    +                ret = 'undefined'
    +                break;
    +            case 'string':
    +                ret = '"' + string.escape(o) + '"';
    +                break;
    +            case 'object':
    +                if (o instanceof Array) {
    +                    if (visited) {
    +                        visited[newid] = o;
    +                    };
    +                    var r = [];
    +                    for (var i=0; i < o.length; i++) {
    +                        var newo = o[i];
    +                        r.push(misclib._repr_helper(newo, visited));
    +                    };
    +                    ret = ''
    +                    if (visited) {
    +                        ret += '#' + newid + '=';
    +                    };
    +                    ret += '[' + r.join(', ') + ']';
    +                } else if (o instanceof Date) {
    +                    ret = '(new Date(' + o.valueOf() + '))';
    +                } else {
    +                    if (visited) {
    +                        visited[newid] = o;
    +                    };
    +                    var r = [];
    +                    for (var attr in o) {
    +                        var newo = o[attr];
    +                        r.push(attr + ': ' + misclib._repr_helper(newo, 
    +                                                                visited));
    +                    };
    +                    ret = '';
    +                    if (visited) {
    +                        ret += '#' + newid + '=';
    +                    };
    +                    ret += '{' + r.join(', ') + '}';
    +                };
    +                break;
    +            default:
    +                ret = o.toString();
    +                break;
    +        };
    +        return ret;
    +    };
    +
    +    this.dir = function(obj) {
    +        /* list all the attributes of an object */
    +        var ret = [];
    +        for (var attr in obj) {
    +            ret.push(attr);
    +        };
    +        return ret;
    +    };
    +
    +    this.print = function(message, win) {
    +        /* write output in a way that the user can see it
    +
    +            creates a div in browsers, prints to stdout in spidermonkey
    +
    +            this is here not only as a convenient way to print output, but also
    +            so that it's possible to override, that way customizing prints
    +            from code
    +        */
    +        if (win === undefined) {
    +            win = window;
    +        };
    +        message = '' + message;
    +        var p = null;
    +        try {
    +          win.foo;
    +        } catch(e) {
    +          // no window, so we guess we're inside some JS console, assuming it
    +          // has a print() function... if there are situations in which this
    +          // doesn't suffice, please mail me (johnny at johnnydebris.net)
    +          print(message);
    +          return;
    +        };
    +        var div = document.createElement('div');
    +        div.className = 'printed';
    +        div.appendChild(document.createTextNode(message));
    +        document.getElementsByTagName('body')[0].appendChild(div);
    +    };
    +}();
    
    Added: kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/number.js
    ==============================================================================
    --- (empty file)
    +++ kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/number.js	Sun Jan 20 20:43:18 2008
    @@ -0,0 +1,43 @@
    +/*****************************************************************************
    + *
    + * Copyright (c) 2004-2007 Guido Wesdorp. All rights reserved.
    + *
    + * This software is distributed under the terms of the JSBase
    + * License. See LICENSE.txt for license text.
    + *
    + *****************************************************************************/
    +
    +var global = this;
    +global.number = new function() {
    +    this.toBase = function(number, base, padwidth, chars) {
    +        /* convert number to a base  number (string) */
    +        // XXX really not sure whether this algorithm is the best, there will
    +        // most probably be more optimal ways to achieve this...
    +        if (!chars) {
    +            chars = '0123456789abcdefghijklmnopqrstuvwxyz';
    +        };
    +        if (base > chars.length) {
    +            throw('not enough formatting characters for this base');
    +        };
    +        var ret = '';
    +        var i = 0;
    +        while (number) {
    +            var curr = Math.pow(base, i);
    +            var next = curr * base;
    +            var index = (number % next) / curr;
    +            ret = chars.charAt(index) + ret;
    +            number -= (index * curr);
    +            i++;
    +        };
    +        if (padwidth) {
    +            var add = (padwidth - ret.length);
    +            for (var i=0; i < add; i++) {
    +                ret = chars[0] + ret;
    +            };
    +        };
    +        if (ret == '') {
    +            ret = '0';
    +        };
    +        return ret;
    +    };
    +}();
    
    Added: kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/server.js
    ==============================================================================
    --- (empty file)
    +++ kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/server.js	Sun Jan 20 20:43:18 2008
    @@ -0,0 +1,110 @@
    +/*****************************************************************************
    + *
    + * Copyright (c) 2004-2007 Guido Wesdorp. All rights reserved.
    + *
    + * This software is distributed under the terms of the JSBase
    + * License. See LICENSE.txt for license text.
    + *
    + *****************************************************************************/
    +
    +if (!this.jsbase) {
    +    this.jsbase = {};
    +};
    +this.jsbase.server = this.server = new function() {
    +    /* helper functions to communicate with the server 
    +
    +        'AJAX' like helper stuff
    +    */
    +    
    +    var server = this;
    +    
    +    this.getXHR = this.getXMLHttpRequest = function() {
    +        try{
    +            return new XMLHttpRequest();
    +        } catch(e) {
    +            // not a Mozilla or Konqueror based browser
    +        };
    +        try {
    +            // XXX not sure if it's really better, but perhaps we should use
    +            // the more verbose way (with version numbers and all) for A-X
    +            // instantiation?
    +            return new ActiveXObject('Microsoft.XMLHTTP');
    +        } catch(e) {
    +            // not IE either...
    +        };
    +        return undefined;
    +    };
    +
    +    var Module = this._Module = function(name, code) {
    +        this.name = name;
    +        this._code = code;
    +        eval(code);
    +    };
    +
    +    Module.prototype.toString = function() {
    +        return "[Module '" + this.name + "']";
    +    };
    +
    +    Module.prototype.toSource = function() {
    +        return this._code;
    +    };
    +
    +    this.load_async = function(path, callback, errback) {
    +        /* load data from a path/url
    +
    +            on successful load  is called with arguments 'status',
    +            'content', on error , with the same arguments
    +        */
    +        if (!errback) {
    +            errback = callback;
    +        };
    +        var xhr = this.getXHR();
    +        xhr.open('GET', path, true);
    +        var handler = function() {
    +            if (xhr.readyState == 4) {
    +                if (xhr.status != 200 && xhr.status != 302) {
    +                    errback(xhr.status, xhr.responseText);
    +                    return;
    +                };
    +                callback(xhr.status, xhr.responseText);
    +            };
    +        };
    +        xhr.onreadystatechange = handler;
    +        xhr.send('');
    +    };
    +    
    +    this.load_sync = function(path) {
    +        var xhr = this.getXHR();
    +        xhr.open('GET', path, false);
    +        xhr.send('');
    +        if (xhr.status != 200 && xhr.status != 302) {
    +            if (global.exception) {
    +                throw(new exception.HTTPError(xhr.status));
    +            } else {
    +                throw(xhr.status);
    +            };
    +        };
    +        return xhr.responseText;
    +    };
    +    
    +    this.import_async = function(name, path, errback) {
    +        /* import a JS 'module' asynchronous
    +
    +            'name' is the name the module will be available under, 
    +            'path' is the path to the object (must be on the same server),
    +            'errback' is an (optional) error handling function
    +
    +            NOTE: in a module, only variables attached to 'this' on the module
    +            root level are exposed
    +        */
    +        var handler = function(status, data) {
    +            var module = new Module(name, data);
    +            window[name] = module;
    +        };
    +        this.load_data(path, handler, errback);
    +    };
    +
    +    this.import_sync = function(path) {
    +        return new Module('', this.load_sync(path));
    +    };
    +}();
    
    Added: kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/string.js
    ==============================================================================
    --- (empty file)
    +++ kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/string.js	Sun Jan 20 20:43:18 2008
    @@ -0,0 +1,152 @@
    +/*****************************************************************************
    + *
    + * Copyright (c) 2004-2007 Guido Wesdorp. All rights reserved.
    + *
    + * This software is distributed under the terms of the JSBase
    + * License. See LICENSE.txt for license text.
    + *
    + *****************************************************************************/
    +
    +/* Additions to the core String API */
    +
    +var global = this;
    +global.string = new function() {
    +    var string = this;
    +
    +    this.strip = function(s) {
    +        /* returns a string with all leading and trailing whitespace removed */
    +        var stripspace = /^\s*([\s\S]*?)\s*$/;
    +        return stripspace.exec(s)[1];
    +    };
    +
    +    this.reduceWhitespace = function(s) {
    +        /* returns a string in which all whitespace is reduced 
    +            to a single, plain space */
    +        s = s.replace(/\r/g, ' ');
    +        s = s.replace(/\t/g, ' ');
    +        s = s.replace(/\n/g, ' ');
    +        while (s.indexOf('  ') > -1) {
    +            s = s.replace('  ', ' ');
    +        };
    +        return s;
    +    };
    +
    +    this.entitize = function(s) {
    +        /* replace all standard XML entities */
    +        var ret = s.replace(/&/g, '&');
    +        ret = ret.replace(/"/g, '"');
    +        //ret = ret.replace(/'/g, ''');
    +        ret = ret.replace(//g, '>');
    +        return ret;
    +    };
    +
    +    this.deentitize = function(s) {
    +        /* convert all standard XML entities to the corresponding characters */
    +        var ret = s.replace(/>/g, '>');
    +        ret = ret.replace(/</g, '<');
    +        //ret = ret.replace(/'/g, "'");
    +        ret = ret.replace(/"/g, '"');
    +        ret = ret.replace(/&/g, '&');
    +        return ret;
    +    };
    +
    +    this.urldecode = function(s) {
    +        /* decode an URL-encoded string 
    +        
    +            reverts the effect of calling 'escape' on a string (see 
    +            'String.urlencode' below)
    +        */
    +        var reg = /%([a-fA-F0-9]{2})/g;
    +        var str = s;
    +        while (true) {
    +            var match = reg.exec(str);
    +            if (!match || !match.length) {
    +                break;
    +            };
    +            var repl = new RegExp(match[0], 'g');
    +            str = str.replace(repl, 
    +                    String.fromCharCode(parseInt(match[1], 16)));
    +        };
    +        // XXX should we indeed replace these?
    +        str = str.replace(/\+/g, ' ');
    +        return str;
    +    };
    +
    +    this.urlencode = function(s) {
    +        /* wrapper around the 'escape' core function
    +
    +            provided for consistency, since I also have a string.urldecode()
    +            defined
    +        */
    +        return escape(s);
    +    };
    +
    +    this.escape = function(s) {
    +        /* escapes quotes and special chars (\n, \a, \r, \t, etc.) 
    +        
    +            adds double slashes
    +        */
    +        // XXX any more that need escaping?
    +        s = s.replace(/\\/g, '\\\\');
    +        s = s.replace(/\n/g, '\\\n');
    +        s = s.replace(/\r/g, '\\\r');
    +        s = s.replace(/\t/g, '\\\t');
    +        s = s.replace(/'/g, "\\'");
    +        s = s.replace(/"/g, '\\"');
    +        return s;
    +    };
    +
    +    this.unescape = function(s) {
    +        /* remove double slashes */
    +        s = s.replace(/\\\n/g, '\n');
    +        s = s.replace(/\\\r/g, '\r');
    +        s = s.replace(/\\\t/g, '\t');
    +        s = s.replace(/\\'/g, '\'');
    +        s = s.replace(/\\"/g, '"');
    +        s = s.replace(/\\\\/g, '\\');
    +        return s;
    +    };
    +
    +    this.centerTruncate = function(s, maxlength) {
    +        if (s.length <= maxlength) {
    +            return s;
    +        };
    +        var chunklength = maxlength / 2 - 3;
    +        var start = s.substr(0, chunklength);
    +        var end = s.substr(s.length - chunklength);
    +        return start + ' ... ' + end;
    +    };
    +
    +    this.startsWith = function(s, start) {
    +        return s.substr(0, start.length) == start;
    +    };
    +
    +    this.endsWith = function(s, end) {
    +        return s.substr(s.length - end.length) == end;
    +    };
    +    
    +    this.format = function(s, indent, maxwidth) {
    +        /* perform simple formatting on the string */
    +        if (indent.length > maxwidth) {
    +            throw('Size of indent must be smaller than maxwidth');
    +        };
    +        s = string.reduceWhitespace(s);
    +        var words = s.split(' ');
    +        var lines = [];
    +        while (words.length) {
    +            var currline = indent;
    +            while (1) {
    +                var word = words.shift();
    +                if (!word || 
    +                        (currline.length > indent.length && 
    +                            currline.length + word.length > maxwidth)) {
    +                    break;
    +                };
    +                currline += word + ' ';
    +            };
    +            lines.push(currline);
    +        };
    +        return lines.join('\r\n');
    +    };
    +}();
    
    Added: kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/test_array.js
    ==============================================================================
    --- (empty file)
    +++ kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/test_array.js	Sun Jan 20 20:43:18 2008
    @@ -0,0 +1,59 @@
    +load('string.js');
    +load('array.js');
    +
    +function test_indexOf() {
    +    var a1 = ['foo', 'bar', 'baz'];
    +    testing.assertEquals(array.indexOf(a1, 'foo'), 0);
    +    testing.assertEquals(array.indexOf(a1, 'qux'), -1);
    +};
    +
    +function test_removeDoubles() {
    +    var a1 = ['foo', 'bar', 'baz'];
    +    testing.assertEquals(array.removeDoubles(a1), a1);
    +
    +    var a2 = ['foo', 'bar', 'foo', 'baz', 'bar', 'baz'];
    +    testing.assertEquals(array.removeDoubles(a2), a1);
    +
    +    var a3 = ['foo', 'foo', 'foo', 'foo'];
    +    testing.assertEquals(array.removeDoubles(a3), ['foo']);
    +
    +    var a4 = [];
    +    testing.assertEquals(array.removeDoubles(a4), []);
    +};
    +
    +function test_map() {
    +    var a1 = ['foo', 'bar', 'baz'];
    +    array.map(a1, function(x) {return x.charAt(0)});
    +    testing.assertEquals(a1, ['f', 'b', 'b']);
    +};
    +
    +function test_reversed() {
    +    var a1 = ['foo', 'bar', 'baz'];
    +    testing.assertEquals(array.reversed(a1), ['baz', 'bar', 'foo']);
    +};
    +
    +function test_iterate() {
    +    var a = ['foo', 'bar', 'baz'];
    +    var expected = ['foo', 'bar', 'baz', undefined];
    +    for (var n=0; n < 2; n++) {
    +        for (var i=0; i < expected.length; i++) {
    +            testing.assertEquals(array.iterate(a), expected[i]);
    +        };
    +    };
    +};
    +
    +function test_iterator() {
    +    var a = ['foo', 'bar', 'baz'];
    +    var expected = ['foo', 'bar', 'baz', undefined];
    +    for (var n=0; n < 2; n++) {
    +        for (var i=0; i < expected.length; i++) {
    +            if (i === undefined) {
    +                testing.assertThrows(array.StopIteration, array.iterate, array,
    +                                     a);
    +            } else {
    +                testing.assertEquals(expected[i], array.iterate(a));
    +            };
    +        };
    +    };
    +};
    +
    
    Added: kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/test_misclib.js
    ==============================================================================
    --- (empty file)
    +++ kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/test_misclib.js	Sun Jan 20 20:43:18 2008
    @@ -0,0 +1,50 @@
    +load('string.js');
    +load('misclib.js');
    +
    +function test_repr() {
    +    var b = true;
    +    testing.assertEquals(misclib.repr(b), 'true');
    +
    +    var n = 10;
    +    testing.assertEquals(misclib.repr(n), '10');
    +
    +    var s = 'foo';
    +    testing.assertEquals(misclib.repr(s), '"foo"');
    +
    +    var s2 = 'foo\\bar';
    +    testing.assertEquals(misclib.repr(s2), '"foo\\\\bar"');
    +
    +    var a = [false, 1, '2'];
    +    testing.assertEquals(misclib.repr(a), '[false, 1, "2"]');
    +
    +    var d = new Date(1234567);
    +    testing.assertEquals(misclib.repr(d), '(new Date(1234567))');
    +
    +    var o = {foo: [1,2,3],
    +                bar: {foo: true}};
    +    testing.assertEquals(misclib.repr(o), '{foo: [1, 2, 3], bar: {foo: true}}');
    +
    +    var f = {};
    +    f.f = f;
    +    testing.assertThrows(undefined, misclib.repr, misclib, f, true);
    +};
    +
    +function test_safe_repr() {
    +    var f = {};
    +    testing.assertEquals(misclib.safe_repr(f), '#0={}');
    +
    +    f.foo = f;
    +    testing.assertEquals(misclib.safe_repr(f), '#0={foo: #0#}');
    +
    +    f.bar = {};
    +    testing.assertEquals(misclib.safe_repr(f), '#0={foo: #0#, bar: #1={}}');
    +
    +    f.bar.f = f;
    +    testing.assertEquals(misclib.safe_repr(f), '#0={foo: #0#, bar: #1={f: #0#}}');
    +
    +    f.bar = [];
    +    testing.assertEquals(misclib.safe_repr(f), '#0={foo: #0#, bar: #1=[]}');
    +
    +    f.bar[0] = f;
    +    testing.assertEquals(misclib.safe_repr(f), '#0={foo: #0#, bar: #1=[#0#]}');
    +};
    
    Added: kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/test_number.js
    ==============================================================================
    --- (empty file)
    +++ kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/test_number.js	Sun Jan 20 20:43:18 2008
    @@ -0,0 +1,10 @@
    +load('string.js');
    +load('number.js');
    +
    +function test_toBase() {
    +    testing.assertEquals(number.toBase(5, 2), '101');
    +    testing.assertEquals(number.toBase(5, 3), '12');
    +    testing.assertEquals(number.toBase(255, 16), 'ff');
    +    testing.assertEquals(number.toBase(0, 16), '0');
    +    testing.assertEquals(number.toBase(438726438764873, 10), '438726438764873');
    +};
    
    Added: kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/test_string.js
    ==============================================================================
    --- (empty file)
    +++ kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/test_string.js	Sun Jan 20 20:43:18 2008
    @@ -0,0 +1,60 @@
    +load('string.js');
    +
    +function test_strip() {
    +    testing.assertEquals(string.strip(' foo '), 'foo');
    +    testing.assertEquals(string.strip('\tfoo'), 'foo');
    +    testing.assertEquals(string.strip('foo\r\n'), 'foo');
    +    testing.assertEquals(string.strip('\t\r\n \nfoo \t bar\r\n\t'), 'foo \t bar');
    +};
    +
    +function test_reduceWhitespace() {
    +    testing.assertEquals(string.reduceWhitespace('foo  bar'), 'foo bar');
    +    testing.assertEquals(string.reduceWhitespace('foo\r\nbar'), 'foo bar');
    +    testing.assertEquals(string.reduceWhitespace('foo\t\r\n \tbar'), 'foo bar');
    +};
    +
    +function test_entitize() {
    +    testing.assertEquals(string.entitize('foo>bar'), 'foo>bar');
    +    testing.assertEquals(string.entitize('foo<&>bar'), 'foo<&>bar');
    +    testing.assertEquals(string.entitize('foo"\'bar'), 'foo"\'bar'); //'foo"'bar');
    +};
    +
    +function test_deentitize() {
    +    testing.assertEquals(string.deentitize('foo&bar'), 'foo&bar');
    +    testing.assertEquals(string.deentitize('foo&gtbar'), 'foo>bar');
    +    testing.assertEquals(string.deentitize('foo"'bar'), 'foo"'bar'); //'foo"\'bar');
    +};
    +
    +function test_urldecode() {
    +    testing.assertEquals(string.urldecode('foo%20bar'), 'foo bar');
    +    testing.assertEquals(string.urldecode('foo+bar%40baz'), 'foo bar at baz');
    +};
    +
    +function test_urlencode() {
    +    testing.assertEquals(string.urlencode('foo bar+baz'), escape('foo bar+baz'));
    +};
    +
    +function test_escape() {
    +    testing.assertEquals(string.escape('foo\nbar\\baz'), 'foo\\\nbar\\\\baz');
    +};
    +
    +function test_unescape() {
    +    testing.assertEquals(string.unescape('foo\\\nbar\\\\baz'), 'foo\nbar\\baz');
    +};
    +
    +function test_centerTruncate() {
    +    testing.assertEquals(string.centerTruncate('foo', 10), 'foo');
    +    testing.assertEquals(string.centerTruncate('foo bar baz', 10), 'fo ... az');
    +};
    +
    +function test_startsWith() {
    +    testing.assert(string.startsWith('foo', 'f'));
    +    testing.assert(string.startsWith('foobarbaz', 'foo'));
    +    testing.assertFalse(string.startsWith('foo', 'b'));
    +};
    +
    +function test_endsWith() {
    +    testing.assert(string.endsWith('foo', 'o'));
    +    testing.assert(string.endsWith('foo bar baz', 'baz'));
    +    testing.assertFalse(string.endsWith('foo', 'z'));
    +};
    
    Added: kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/testing.js
    ==============================================================================
    --- (empty file)
    +++ kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/testing.js	Sun Jan 20 20:43:18 2008
    @@ -0,0 +1,135 @@
    +/*****************************************************************************
    + *
    + * Copyright (c) 2004-2007 Guido Wesdorp. All rights reserved.
    + *
    + * This software is distributed under the terms of the JSBase
    + * License. See LICENSE.txt for license text.
    + *
    + *****************************************************************************/
    +
    +var global = this;
    +global.testing = new function() {
    +    var testing = this;
    +
    +    this.DEBUG = true; // set to false to disable debug messages
    +    
    +    this.assert = function(expr, message) {
    +        /* raise an exception if expr resolves to false */
    +        if (!testing.DEBUG) {
    +            return;
    +        };
    +        if (!expr) {
    +            if (!message) {
    +                message = 'false assertion'
    +            } else {
    +                message = '' + message;
    +            };
    +            if (global.exception && global.exception.AssertionError) {
    +                throw(new exception.AssertionError(message));
    +            } else {
    +                throw(message);
    +            };
    +        };
    +    };
    +
    +    this.assertFalse = function(s) {
    +        if (s) {
    +            throw(new exception.AssertionError('!! ' + misclib.repr(s)));
    +        };
    +    };
    +
    +    this.assertEquals = function(var1, var2, message) {
    +        /* assert whether 2 vars have the same value */
    +        if (var1 != var2 &&
    +                (!(var1 instanceof Array && var2 instanceof Array) ||
    +                    misclib.repr(var1) != misclib.repr(var2)) &&
    +                (!(var1 instanceof Date && var2 instanceof Date) ||
    +                    var1.getTime() != var2.getTime())) {
    +            throw(new exception.AssertionError('' + misclib.repr(s1) + ' != ' + 
    +                                                misclib.repr(s2)));
    +        };
    +    };
    +
    +    this.assertThrows = function(exctype, callable, context) {
    +        /* assert whether a certain exception is raised */
    +        // we changed the argument order here, so an explicit check is the
    +        // least we can do ;)
    +        if (typeof callable != 'function') {
    +            var msg = 'wrong argument type for callable';
    +            if (global.exception) {
    +                throw(new exception.ValueError(msg));
    +            } else {
    +                throw(msg);
    +            };
    +        };
    +        if (!context) {
    +            context = null;
    +        };
    +        var exception_thrown = false;
    +        // remove the first three args, they're the function's normal args
    +        var args = [];
    +        for (var i=3; i < arguments.length; i++) {
    +            args.push(arguments[i]);
    +        };
    +        try {
    +            callable.apply(context, args);
    +        } catch(e) {
    +            // allow catching undefined exceptions too
    +            if (exctype === undefined) {
    +            } else if (exctype) {
    +                var isinstance = false;
    +                try {
    +                    if (e instanceof exctype) {
    +                        isinstance = true;
    +                    };
    +                } catch(f) {
    +                };
    +                if (!isinstance) {
    +                    if (exctype.toSource && e.toSource) {
    +                        exctype = exctype.toSource();
    +                        e = e.toSource();
    +                    };
    +                    if (exctype.toString && e.toString) {
    +                        exctype = exctype.toString();
    +                        e = e.toString();
    +                    };
    +                    if (e != exctype) {
    +                        throw(new exception.AssertionError(
    +                                        'exception ' + e + 
    +                                        ', while expecting ' + exctype));
    +                    };
    +                };
    +            };
    +            exception_thrown = true;
    +        };
    +        if (!exception_thrown) {
    +            if (exctype) {
    +                throw(new exception.AssertionError(
    +                        "function didn\'t raise exception \'" + 
    +                        exctype.toString() + "'"));
    +            } else {
    +                throw(new exception.AssertionError(
    +                        "function didn\'t raise exception"));
    +            };
    +        };
    +    };
    +
    +    this.debug = function(str) {
    +        /* append a message to the document with a string */
    +        if (!testing.DEBUG) {
    +            return;
    +        };
    +        try {
    +            var div = document.createElement('pre');
    +            div.appendChild(document.createTextNode('' + str));
    +            div.style.color = 'red';
    +            div.style.borderWidth = '1px';
    +            div.style.borderStyle = 'solid';
    +            div.style.borderColor = 'black';
    +            document.getElementsByTagName('body')[0].appendChild(div);
    +        } catch(e) {
    +            alert(str);
    +        };
    +    };
    +}();
    +
    
    Added: kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/testing/findtests.js
    ==============================================================================
    --- (empty file)
    +++ kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/testing/findtests.js	Sun Jan 20 20:43:18 2008
    @@ -0,0 +1,35 @@
    +var filepath = %r;
    +load(filepath);
    +
    +var global = this;
    +global.findtests = new function() {
    +    var findtests = this;
    +
    +    var Collector = this.Collector = function(module) {
    +        if (module !== undefined) {
    +            this.module = module;
    +        };
    +    };
    +
    +    Collector.prototype.collect = function() {
    +        var tests = [];
    +        for (var attr in this.module) {
    +            if (attr.indexOf('test_') == 0) {
    +                tests.push(attr);
    +            };
    +        };
    +        return tests;
    +    };
    +
    +    this.initialize = function() {
    +        var collector = new Collector(global);
    +        var tests = collector.collect();
    +        for (var i=0; i < tests.length; i++) {
    +            print(tests[i]);
    +        };
    +    };
    +}();
    +
    +if ('%s' == '__main__') {
    +    findtests.initialize();
    +};
    
    Added: kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/testing/testbase.js
    ==============================================================================
    --- (empty file)
    +++ kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/testing/testbase.js	Sun Jan 20 20:43:18 2008
    @@ -0,0 +1,60 @@
    +var paths = %r;
    +var testname = %r;
    +
    +// redirect normal prints
    +var global = this;
    +global.real_print = global.print;
    +global.print = function(l) {
    +    global.real_print('PRINTED: ' + l);
    +};
    +
    +// import paths
    +for (var i=0; i < paths.length; i++) {
    +    var path = paths[i];
    +    load(path);
    +};
    +
    +global.jstest = new function() {
    +    var jstest = this;
    +
    +    var Runner = this.Runner = function(module, testname) {
    +        if (module !== undefined) {
    +            this.module = module;
    +            this.testname = testname;
    +        };
    +    };
    +
    +    Runner.prototype.run = function() {
    +        var module = this.module;
    +        var ns = {};
    +        if (module.setup) {
    +            module.setup(ns);
    +        };
    +        var test = module[testname];
    +        real_print('running test ' + testname);
    +        try {
    +            test.call(ns);
    +            real_print('success');
    +        } catch(e) {
    +            real_print('failure: ' + (e.toString ? e.toString() : e));
    +            if (e.stack) {
    +                real_print('traceback');
    +                real_print(e.stack);
    +                real_print('end traceback');
    +            };
    +        };
    +        real_print('end test');
    +        if (module.teardown) {
    +            module.teardown(ns);
    +        };
    +    };
    +
    +    this.initialize = function() {
    +        var runner = new Runner(global, testname);
    +        runner.run();
    +    };
    +}();
    +
    +if ('%s' == '__main__') {
    +    jstest.initialize();
    +};
    
    Added: kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/version.txt
    ==============================================================================
    --- (empty file)
    +++ kukit/kukit.js/trunk/3rd_party/johnnydebris.net/jsbase/version.txt	Sun Jan 20 20:43:18 2008
    @@ -0,0 +1 @@
    +0.1
    
    Added: kukit/kukit.js/trunk/3rd_party/johnnydebris.net/minisax.js/LICENSE.txt
    ==============================================================================
    --- (empty file)
    +++ kukit/kukit.js/trunk/3rd_party/johnnydebris.net/minisax.js/LICENSE.txt	Sun Jan 20 20:43:18 2008
    @@ -0,0 +1,340 @@
    +                    GNU GENERAL PUBLIC LICENSE
    +                       Version 2, June 1991
    +
    + Copyright (C) 1989, 1991 Free Software Foundation, Inc.
    + 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    + Everyone is permitted to copy and distribute verbatim copies
    + of this license document, but changing it is not allowed.
    +
    +                            Preamble
    +
    +  The licenses for most software are designed to take away your
    +freedom to share and change it.  By contrast, the GNU General Public
    +License is intended to guarantee your freedom to share and change free
    +software--to make sure the software is free for all its users.  This
    +General Public License applies to most of the Free Software
    +Foundation's software and to any other program whose authors commit to
    +using it.  (Some other Free Software Foundation software is covered by
    +the GNU Library General Public License instead.)  You can apply it to
    +your programs, too.
    +
    +  When we speak of free software, we are referring to freedom, not
    +price.  Our General Public Licenses are designed to make sure that you
    +have the freedom to distribute copies of free software (and charge for
    +this service if you wish), that you receive source code or can get it
    +if you want it, that you can change the software or use pieces of it
    +in new free programs; and that you know you can do these things.
    +
    +  To protect your rights, we need to make restrictions that forbid
    +anyone to deny you these rights or to ask you to surrender the rights.
    +These restrictions translate to certain responsibilities for you if you
    +distribute copies of the software, or if you modify it.
    +
    +  For example, if you distribute copies of such a program, whether
    +gratis or for a fee, you must give the recipients all the rights that
    +you have.  You must make sure that they, too, receive or can get the
    +source code.  And you must show them these terms so they know their
    +rights.
    +
    +  We protect your rights with two steps: (1) copyright the software, and
    +(2) offer you this license which gives you legal permission to copy,
    +distribute and/or modify the software.
    +
    +  Also, for each author's protection and ours, we want to make certain
    +that everyone understands that there is no warranty for this free
    +software.  If the software is modified by someone else and passed on, we
    +want its recipients to know that what they have is not the original, so
    +that any problems introduced by others will not reflect on the original
    +authors' reputations.
    +
    +  Finally, any free program is threatened constantly by software
    +patents.  We wish to avoid the danger that redistributors of a free
    +program will individually obtain patent licenses, in effect making the
    +program proprietary.  To prevent this, we have made it clear that any
    +patent must be licensed for everyone's free use or not licensed at all.
    +
    +  The precise terms and conditions for copying, distribution and
    +modification follow.
    +
    +                    GNU GENERAL PUBLIC LICENSE
    +   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
    +
    +  0. This License applies to any program or other work which contains
    +a notice placed by the copyright holder saying it may be distributed
    +under the terms of this General Public License.  The "Program", below,
    +refers to any such program or work, and a "work based on the Program"
    +means either the Program or any derivative work under copyright law:
    +that is to say, a work containing the Program or a portion of it,
    +either verbatim or with modifications and/or translated into another
    +language.  (Hereinafter, translation is included without limitation in
    +the term "modification".)  Each licensee is addressed as "you".
    +
    +Activities other than copying, distribution and modification are not
    +covered by this License; they are outside its scope.  The act of
    +running the Program is not restricted, and the output from the Program
    +is covered only if its contents constitute a work based on the
    +Program (independent of having been made by running the Program).
    +Whether that is true depends on what the Program does.
    +
    +  1. You may copy and distribute verbatim copies of the Program's
    +source code as you receive it, in any medium, provided that you
    +conspicuously and appropriately publish on each copy an appropriate
    +copyright notice and disclaimer of warranty; keep intact all the
    +notices that refer to this License and to the absence of any warranty;
    +and give any other recipients of the Program a copy of this License
    +along with the Program.
    +
    +You may charge a fee for the physical act of transferring a copy, and
    +you may at your option offer warranty protection in exchange for a fee.
    +
    +  2. You may modify your copy or copies of the Program or any portion
    +of it, thus forming a work based on the Program, and copy and
    +distribute such modifications or work under the terms of Section 1
    +above, provided that you also meet all of these conditions:
    +
    +    a) You must cause the modified files to carry prominent notices
    +    stating that you changed the files and the date of any change.
    +
    +    b) You must cause any work that you distribute or publish, that in
    +    whole or in part contains or is derived from the Program or any
    +    part thereof, to be licensed as a whole at no charge to all third
    +    parties under the terms of this License.
    +
    +    c) If the modified program normally reads commands interactively
    +    when run, you must cause it, when started running for such
    +    interactive use in the most ordinary way, to print or display an
    +    announcement including an appropriate copyright notice and a
    +    notice that there is no warranty (or else, saying that you provide
    +    a warranty) and that users may redistribute the program under
    +    these conditions, and telling the user how to view a copy of this
    +    License.  (Exception: if the Program itself is interactive but
    +    does not normally print such an announcement, your work based on
    +    the Program is not required to print an announcement.)
    +
    +These requirements apply to the modified work as a whole.  If
    +identifiable sections of that work are not derived from the Program,
    +and can be reasonably considered independent and separate works in
    +themselves, then this License, and its terms, do not apply to those
    +sections when you distribute them as separate works.  But when you
    +distribute the same sections as part of a whole which is a work based
    +on the Program, the distribution of the whole must be on the terms of
    +this License, whose permissions for other licensees extend to the
    +entire whole, and thus to each and every part regardless of who wrote it.
    +
    +Thus, it is not the intent of this section to claim rights or contest
    +your rights to work written entirely by you; rather, the intent is to
    +exercise the right to control the distribution of derivative or
    +collective works based on the Program.
    +
    +In addition, mere aggregation of another work not based on the Program
    +with the Program (or with a work based on the Program) on a volume of
    +a storage or distribution medium does not bring the other work under
    +the scope of this License.
    +
    +  3. You may copy and distribute the Program (or a work based on it,
    +under Section 2) in object code or executable form under the terms of
    +Sections 1 and 2 above provided that you also do one of the following:
    +
    +    a) Accompany it with the complete corresponding machine-readable
    +    source code, which must be distributed under the terms of Sections
    +    1 and 2 above on a medium customarily used for software interchange; or,
    +
    +    b) Accompany it with a written offer, valid for at least three
    +    years, to give any third party, for a charge no more than your
    +    cost of physically performing source distribution, a complete
    +    machine-readable copy of the corresponding source code, to be
    +    distributed under the terms of Sections 1 and 2 above on a medium
    +    customarily used for software interchange; or,
    +
    +    c) Accompany it with the information you received as to the offer
    +    to distribute corresponding source code.  (This alternative is
    +    allowed only for noncommercial distribution and only if you
    +    received the program in object code or executable form with such
    +    an offer, in accord with Subsection b above.)
    +
    +The source code for a work means the preferred form of the work for
    +making modifications to it.  For an executable work, complete source
    +code means all the source code for all modules it contains, plus any
    +associated interface definition files, plus the scripts used to
    +control compilation and installation of the executable.  However, as a
    +special exception, the source code distributed need not include
    +anything that is normally distributed (in either source or binary
    +form) with the major components (compiler, kernel, and so on) of the
    +operating system on which the executable runs, unless that component
    +itself accompanies the executable.
    +
    +If distribution of executable or object code is made by offering
    +access to copy from a designated place, then offering equivalent
    +access to copy the source code from the same place counts as
    +distribution of the source code, even though third parties are not
    +compelled to copy the source along with the object code.
    +
    +  4. You may not copy, modify, sublicense, or distribute the Program
    +except as expressly provided under this License.  Any attempt
    +otherwise to copy, modify, sublicense or distribute the Program is
    +void, and will automatically terminate your rights under this License.
    +However, parties who have received copies, or rights, from you under
    +this License will not have their licenses terminated so long as such
    +parties remain in full compliance.
    +
    +  5. You are not required to accept this License, since you have not
    +signed it.  However, nothing else grants you permission to modify or
    +distribute the Program or its derivative works.  These actions are
    +prohibited by law if you do not accept this License.  Therefore, by
    +modifying or distributing the Program (or any work based on the
    +Program), you indicate your acceptance of this License to do so, and
    +all its terms and conditions for copying, distributing or modifying
    +the Program or works based on it.
    +
    +  6. Each time you redistribute the Program (or any work based on the
    +Program), the recipient automatically receives a license from the
    +original licensor to copy, distribute or modify the Program subject to
    +these terms and conditions.  You may not impose any further
    +restrictions on the recipients' exercise of the rights granted herein.
    +You are not responsible for enforcing compliance by third parties to
    +this License.
    +
    +  7. If, as a consequence of a court judgment or allegation of patent
    +infringement or for any other reason (not limited to patent issues),
    +conditions are imposed on you (whether by court order, agreement or
    +otherwise) that contradict the conditions of this License, they do not
    +excuse you from the conditions of this License.  If you cannot
    +distribute so as to satisfy simultaneously your obligations under this
    +License and any other pertinent obligations, then as a consequence you
    +may not distribute the Program at all.  For example, if a patent
    +license would not permit royalty-free redistribution of the Program by
    +all those who receive copies directly or indirectly through you, then
    +the only way you could satisfy both it and this License would be to
    +refrain entirely from distribution of the Program.
    +
    +If any portion of this section is held invalid or unenforceable under
    +any particular circumstance, the balance of the section is intended to
    +apply and the section as a whole is intended to apply in other
    +circumstances.
    +
    +It is not the purpose of this section to induce you to infringe any
    +patents or other property right claims or to contest validity of any
    +such claims; this section has the sole purpose of protecting the
    +integrity of the free software distribution system, which is
    +implemented by public license practices.  Many people have made
    +generous contributions to the wide range of software distributed
    +through that system in reliance on consistent application of that
    +system; it is up to the author/donor to decide if he or she is willing
    +to distribute software through any other system and a licensee cannot
    +impose that choice.
    +
    +This section is intended to make thoroughly clear what is believed to
    +be a consequence of the rest of this License.
    +
    +  8. If the distribution and/or use of the Program is restricted in
    +certain countries either by patents or by copyrighted interfaces, the
    +original copyright holder who places the Program under this License
    +may add an explicit geographical distribution limitation excluding
    +those countries, so that distribution is permitted only in or among
    +countries not thus excluded.  In such case, this License incorporates
    +the limitation as if written in the body of this License.
    +
    +  9. The Free Software Foundation may publish revised and/or new versions
    +of the General Public License from time to time.  Such new versions will
    +be similar in spirit to the present version, but may differ in detail to
    +address new problems or concerns.
    +
    +Each version is given a distinguishing version number.  If the Program
    +specifies a version number of this License which applies to it and "any
    +later version", you have the option of following the terms and conditions
    +either of that version or of any later version published by the Free
    +Software Foundation.  If the Program does not specify a version number of
    +this License, you may choose any version ever published by the Free Software
    +Foundation.
    +
    +  10. If you wish to incorporate parts of the Program into other free
    +programs whose distribution conditions are different, write to the author
    +to ask for permission.  For software which is copyrighted by the Free
    +Software Foundation, write to the Free Software Foundation; we sometimes
    +make exceptions for this.  Our decision will be guided by the two goals
    +of preserving the free status of all derivatives of our free software and
    +of promoting the sharing and reuse of software generally.
    +
    +                            NO WARRANTY
    +
    +  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
    +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
    +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
    +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
    +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
    +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
    +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
    +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
    +REPAIR OR CORRECTION.
    +
    +  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
    +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
    +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
    +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
    +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
    +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
    +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
    +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
    +POSSIBILITY OF SUCH DAMAGES.
    +
    +                     END OF TERMS AND CONDITIONS
    +
    +            How to Apply These Terms to Your New Programs
    +
    +  If you develop a new program, and you want it to be of the greatest
    +possible use to the public, the best way to achieve this is to make it
    +free software which everyone can redistribute and change under these terms.
    +
    +  To do so, attach the following notices to the program.  It is safest
    +to attach them to the start of each source file to most effectively
    +convey the exclusion of warranty; and each file should have at least
    +the "copyright" line and a pointer to where the full notice is found.
    +
    +    
    +    Copyright (C)   
    +
    +    This program is free software; you can redistribute it and/or modify
    +    it under the terms of the GNU General Public License as published by
    +    the Free Software Foundation; either version 2 of the License, or
    +    (at your option) any later version.
    +
    +    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
    +
    +Also add information on how to contact you by electronic and paper mail.
    +
    +If the program is interactive, make it output a short notice like this
    +when it starts in an interactive mode:
    +
    +    Gnomovision version 69, Copyright (C) year name of author
    +    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
    +    This is free software, and you are welcome to redistribute it
    +    under certain conditions; type `show c' for details.
    +
    +The hypothetical commands `show w' and `show c' should show the appropriate
    +parts of the General Public License.  Of course, the commands you use may
    +be called something other than `show w' and `show c'; they could even be
    +mouse-clicks or menu items--whatever suits your program.
    +
    +You should also get your employer (if you work as a programmer) or your
    +school, if any, to sign a "copyright disclaimer" for the program, if
    +necessary.  Here is a sample; alter the names:
    +
    +  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
    +  `Gnomovision' (which makes passes at compilers) written by James Hacker.
    +
    +  , 1 April 1989
    +  Ty Coon, President of Vice
    +
    +This General Public License does not permit incorporating your program into
    +proprietary programs.  If your program is a subroutine library, you may
    +consider it more useful to permit linking proprietary applications with the
    +library.  If this is what you want to do, use the GNU Library General
    +Public License instead of this License.
    +
    
    Added: kukit/kukit.js/trunk/3rd_party/johnnydebris.net/minisax.js/conftest.py
    ==============================================================================
    --- (empty file)
    +++ kukit/kukit.js/trunk/3rd_party/johnnydebris.net/minisax.js/conftest.py	Sun Jan 20 20:43:18 2008
    @@ -0,0 +1,18 @@
    +# JS unit test support for py.test - (c) 2007 Guido Wesdorp. All rights
    +# reserved
    +#
    +# This software is distributed under the terms of the JSBase
    +# License. See LICENSE.txt for license text.
    +
    +import py
    +here = py.magic.autopath().dirpath()
    +
    +from jsbase.conftest import JSTest, JSChecker, Directory as _Directory
    +
    +class Directory(_Directory):
    +    def run(self):
    +        if self.fspath == here:
    +            return [p.basename for p in self.fspath.listdir('test_*') if
    +                    p.ext == '.js']
    +        return super(Directory, self).run()
    +
    
    Added: kukit/kukit.js/trunk/3rd_party/johnnydebris.net/minisax.js/example.html
    ==============================================================================
    --- (empty file)
    +++ kukit/kukit.js/trunk/3rd_party/johnnydebris.net/minisax.js/example.html	Sun Jan 20 20:43:18 2008
    @@ -0,0 +1,69 @@
    +
    +
    +  
    +    MiniSAX test
    +    
    +    
    +    
    +    
    +  
    +  
    +    

    Start data:

    +
    
    +    

    Result:

    +
    
    +  
    +
    
    Added: kukit/kukit.js/trunk/3rd_party/johnnydebris.net/minisax.js/helpers.js
    ==============================================================================
    --- (empty file)
    +++ kukit/kukit.js/trunk/3rd_party/johnnydebris.net/minisax.js/helpers.js	Sun Jan 20 20:43:18 2008
    @@ -0,0 +1,64 @@
    +/*
    +    minisax.js - Simple API for XML (SAX) library for JavaScript
    +    Copyright (C) 2004-2005 Guido Wesdorp
    +    email johnny at debris.demon.nl
    +
    +    This program is free software; you can redistribute it and/or modify
    +    it under the terms of the GNU General Public License as published by
    +    the Free Software Foundation; either version 2 of the License, or
    +    (at your option) any later version.
    +
    +    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
    +
    +    Note:
    +    
    +    This file contains some code written by several Kupu developers. Kupu is an 
    +    HTML editor written in JavaScript, released under a BSD-style license. See
    +    http://kupu.oscom.org for more information about Kupu and the license.
    +    
    +*/
    +
    +Array.prototype.map = function(func) {
    +    /* apply 'func' to each element in the array */
    +    for (var i=0; i < this.length; i++) {
    +        this[i] = func(this[i]);
    +    };
    +};
    +
    +Array.prototype.reversed = function() {
    +    var ret = [];
    +    for (var i = this.length; i > 0; i--) {
    +        ret.push(this[i - 1]);
    +    };
    +    return ret;
    +};
    +
    +// JavaScript has a friggin' blink() function, but not for string stripping...
    +String.prototype.strip = function() {
    +    var stripspace = /^\s*([\s\S]*?)\s*$/;
    +    return stripspace.exec(this)[1];
    +};
    +
    +String.prototype.entitize = function() {
    +    var ret = this.replace(/&/g, '&');
    +    ret = ret.replace(/"/g, '"');
    +    ret = ret.replace(//g, '>');
    +    return ret;
    +};
    +
    +String.prototype.deentitize = function() {
    +    var ret = this.replace(/>/g, '>');
    +    ret = ret.replace(/</g, '<');
    +    ret = ret.replace(/"/g, '"');
    +    ret = ret.replace(/&/g, '&');
    +    return ret;
    +};
    +
    
    Added: kukit/kukit.js/trunk/3rd_party/johnnydebris.net/minisax.js/minisax.js
    ==============================================================================
    --- (empty file)
    +++ kukit/kukit.js/trunk/3rd_party/johnnydebris.net/minisax.js/minisax.js	Sun Jan 20 20:43:18 2008
    @@ -0,0 +1,349 @@
    +/*
    +    minisax.js - Simple API for XML (SAX) library for JavaScript
    +    Copyright (C) 2004-2007 Guido Wesdorp
    +    email johnny at johnnydebris.net
    +
    +    This program is free software; you can redistribute it and/or modify
    +    it under the terms of the GNU General Public License as published by
    +    the Free Software Foundation; either version 2 of the License, or
    +    (at your option) any later version.
    +
    +    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
    +
    +    $Id: minisax.js,v 1.5 2004/07/31 00:10:15 johnny Exp $
    +
    +*/
    +
    +function SAXParser() {
    +    /* Simple SAX library
    +
    +        Uses a couple of regular expressions to parse XML, supports only
    +        a subset of XML (no DTDs and CDATA sections, no entities) but it's
    +        fast and has proper support for namespaces.
    +    */
    +};
    +
    +SAXParser.prototype.initialize = function(xml, handler) {
    +    /* initialization
    +
    +        this method *must* be called directly after initialization,
    +        and can be used afterwards to re-use the parser object for
    +        parsing a new stream
    +    */
    +    this.xml = xml;
    +    this.handler = handler;
    +    this.handler.namespaceToPrefix = {};
    +
    +    this.starttagreg = /\<([^: \t\n]+:)?([a-zA-Z0-9\-_]+)([^\>]*?)(\/?)\>/m;
    +    this.endtagreg = /\<\/([^: \t\n]+:)?([a-zA-Z0-9\-_]+)[^\>]*\>/m;
    +    this.attrstringreg = /(([^:=]+:)?[^=]+=\"[^\"]*\")/m;
    +    this.attrreg = /([^=]*)=\"([^\"]*)\"/m;
    +
    +    // this is a bit nasty: we need to record a stack of namespace
    +    // mappings, each level can override existing namespace ids 
    +    // so we create a new copy of all existing namespaces first, then
    +    // we can override prefixes on that level downward, popping when
    +    // moving up a level
    +    this._namespace_stack = [];
    +
    +    this._current_nodename_stack = [];
    +    this._current_namespace_stack = [];
    +};
    +
    +SAXParser.prototype.parse = function() {
    +    /* parses the XML and generates SAX events */
    +    var xml = this._removeXMLdeclaration(this.xml);
    +    this.handler.startDocument();
    +    while (1) {
    +        var chunk = this._getNextChunk(xml);
    +        if (chunk == '') {
    +            break;
    +        };
    +        xml = xml.substr(chunk.length);
    +        if (chunk.charAt(0) == '<') {
    +            if (chunk.charAt(1) == '/') {
    +                // end tag
    +                this.handleEndTag(chunk);
    +                this._namespace_stack.pop();
    +            } else if (chunk.charAt(1) == '!') {
    +                // XXX note that we don't support DTDs and CDATA yet
    +                chunk = string.deentitize(chunk);
    +                if (!chunk.indexOf('-->') == chunk.length - 3) {
    +                    var more = xml.substr(0, xml.indexOf('-->'));
    +                    xml = xml.substr(more.length);
    +                    chunk += more;
    +                };
    +                chunk = chunk.substr(4, chunk.length - 7);
    +                this.handler.comment(chunk);
    +            } else {
    +                // start tag
    +                var singleton = false;
    +                if (chunk.charAt(chunk.length - 2) == '/') {
    +                    singleton = true;
    +                };
    +                this._pushNamespacesToStack();
    +                this.handleStartTag(chunk, singleton);
    +                if (singleton) {
    +                    this._namespace_stack.pop();
    +                };
    +            };
    +        } else {
    +            chunk = string.deentitize(chunk);
    +            this.handler.characters(chunk);
    +        };
    +    };
    +    this.handler.endDocument();
    +};
    +
    +SAXParser.prototype.handleStartTag = function(tag, is_singleton) {
    +    /* parse the starttag and send events */
    +    
    +    // parse the tag into chunks
    +    var match = this.starttagreg.exec(tag);
    +    if (!match) {
    +        throw('Broken start tag: ' + tag);
    +    };
    +    
    +    // parse the tagname
    +    var prefix = match[1];
    +    var nodename = match[2];
    +    if (prefix) {
    +        prefix = prefix.substr(0, prefix.length - 1);
    +    } else {
    +        prefix = '';
    +    };
    +    
    +    // first split the attributes and check for namespace declarations
    +    var attrs = this._splitAttributes(match[3]);
    +    attrs = this._getAndHandleNamespaceDeclarations(attrs);
    +    
    +    // now handle the attributes
    +    var attributes = {};
    +    for (var i=0; i < attrs.length; i++) {
    +        this.handleAttribute(attrs[i], attributes);
    +    };
    +    
    +    var namespace = this._namespace_stack[
    +                    this._namespace_stack.length - 1
    +                ][prefix];
    +
    +    this.handler.startElement(namespace, nodename, attributes);
    +    if (is_singleton) {
    +        this.handler.endElement(namespace, nodename);
    +    } else {
    +        // store the nodename and namespace for validation on close tag
    +        this._current_nodename_stack.push(nodename);
    +        this._current_namespace_stack.push(namespace);
    +    };
    +};
    +
    +SAXParser.prototype.handleEndTag = function(tag) {
    +    /* handle an end tag */
    +    var match = this.endtagreg.exec(tag);
    +    if (!match) {
    +        throw('Broken end tag: ' + tag);
    +    };
    +    var prefix = match[1];
    +    var nodename = match[2];
    +    if (prefix) {
    +        prefix = prefix.substr(0, prefix.length - 1);
    +    } else {
    +        prefix = '';
    +    };
    +    namespace = this._namespace_stack[
    +                        this._namespace_stack.length - 1
    +                    ][prefix];
    +
    +    // validate, if the name or namespace of the end tag do not match
    +    // the ones of the start tag, throw an exception
    +    var current_nodename = this._current_nodename_stack.pop();
    +    var current_namespace = this._current_namespace_stack.pop();
    +    if (nodename != current_nodename || 
    +            namespace != current_namespace) {
    +        var exc = 'Ending ';
    +        if (namespace != '') {
    +            exc += namespace + ':';
    +        };
    +        exc += nodename + ' doesn\'t match opening ';
    +        if (current_namespace != '') {
    +            exc += current_namespace + ':';
    +        };
    +        exc += current_nodename;
    +        throw(exc); 
    +    }
    +    this.handler.endElement(namespace, nodename);
    +};
    +
    +SAXParser.prototype.handleAttribute = function(attr, attributemapping) {
    +    /* parse an attribute */
    +    var match = this.attrreg.exec(attr);
    +    if (!match) {
    +        throw('Broken attribute: ' + attr);
    +    };
    +    var prefix = '';
    +    var name = match[1];
    +    var lname = match[1];
    +    var value = string.deentitize(match[2]);
    +    if (name.indexOf(':') > -1) {
    +        var tuple = name.split(':');
    +        prefix = tuple[0];
    +        lname = tuple[1];
    +    };
    +    var namespace = '';
    +    if (prefix == 'xml') {
    +        namespace = 'http://www.w3.org/XML/1998/namespace';
    +        if (!this.handler.namespaceToPrefix[namespace]) {
    +            this.handler.namespaceToPrefix[namespace] = prefix;
    +        };
    +    } else if (prefix != '') {
    +        namespace = this._namespace_stack[
    +                            this._namespace_stack.length - 1
    +                        ][prefix];
    +    };
    +    // now place the attr in the mapping
    +    if (!attributemapping[namespace]) {
    +        attributemapping[namespace] = {};
    +    };
    +    attributemapping[namespace][lname] = value;
    +};
    +
    +SAXParser.prototype._removeXMLdeclaration = function(xml) {
    +    /* removes the xml declaration and/or processing instructions */
    +    var declreg = /\<\?[^>]*\?\>/g;
    +    xml = xml.replace(declreg, '');
    +    return xml;
    +};
    +
    +SAXParser.prototype._getNextChunk = function(xml) {
    +    /* get the next chunk 
    +    
    +        up to the opening < of the next tag or the < of the current 
    +    */
    +    if (xml.charAt(0) == '<') {
    +        return xml.substr(0, xml.indexOf('>') + 1);
    +    } else {
    +        return xml.substr(0, xml.indexOf('<'));
    +    };
    +};
    +
    +SAXParser.prototype._splitAttributes = function(attrstring) {
    +    /* split the attributes in the end part of an opening tag */
    +    var attrs = string.strip(attrstring);
    +    var attrlist = [];
    +    while (1) {
    +        var match = this.attrstringreg.exec(attrstring);
    +        if (!match) {
    +            break;
    +        };
    +        attrlist.push(string.strip(match[1]));
    +        attrstring = attrstring.replace(match[0], '');
    +    };
    +    return attrlist;
    +};
    +
    +SAXParser.prototype._getAndHandleNamespaceDeclarations = function(attrarray) {
    +    /* get namespace declarations (if any) and handle them */
    +    var leftover = [];
    +    for (var i=0; i < attrarray.length; i++) {
    +        var attr = attrarray[i];
    +        var match = this.attrreg.exec(attr);
    +        if (!match) {
    +            throw('Broken attribute: ' + attr);
    +        };
    +        if (match[1].indexOf('xmlns') == -1) {
    +            leftover.push(attr);
    +            continue;
    +        };
    +        var nsname = match[1];
    +        var value = string.deentitize(match[2]);
    +        if (nsname.indexOf(':') > -1) {
    +            nsname = nsname.split(':')[1];
    +            this._registerNamespace(value, nsname);
    +        } else {
    +            this._registerNamespace(value);
    +        };
    +    };
    +    return leftover;
    +};
    +
    +SAXParser.prototype._registerNamespace = function(namespace, prefix) {
    +    /* maintain a namespace to id mapping */
    +    if (!prefix) {
    +        prefix = '';
    +    };
    +    if (!this.handler.namespaceToPrefix[namespace]) {
    +        this.handler.namespaceToPrefix[namespace] = prefix;
    +    };
    +    this._namespace_stack[this._namespace_stack.length - 1][prefix] = 
    +                                                            namespace;
    +};
    +
    +SAXParser.prototype._pushNamespacesToStack = function() {
    +    /* maintains a namespace stack */
    +    var newnss = {};
    +    for (var prefix in 
    +            this._namespace_stack[this._namespace_stack.length - 1]) {
    +        newnss[prefix] = this._namespace_stack[
    +                                this._namespace_stack.length - 1
    +                            ][prefix];
    +    };
    +    this._namespace_stack.push(newnss);
    +};
    +
    +function SAXHandler() {
    +    /* base-class and 'interface' for SAX handlers
    +
    +        serves as documentation and base class so subclasses don't need
    +        to provide all methods themselves, but doesn't do anything
    +    */
    +};
    +
    +SAXHandler.prototype.startDocument = function() {
    +    /* is called before the tree is parsed */
    +};
    +
    +SAXHandler.prototype.startElement = function(namespaceURI, nodeName, 
    +                                                attributes) {
    +    /* is called on encountering a new node
    +
    +        namespace is the namespace of the node (URI, undefined if the node
    +        is not in a namespace), nodeName is the localName of the node,
    +        attributes is a mapping from namespace name to a mapping
    +        {name: value, ...}
    +    */
    +};
    +
    +SAXHandler.prototype.endElement = function(namespaceURI, nodeName) {
    +    /* is called on leaving a node 
    +    
    +        namespace is the namespace of the node (URI, undefined if the node 
    +        is not defined inside a namespace), nodeName is the localName of 
    +        the node
    +    */
    +};
    +
    +SAXHandler.prototype.characters = function(chars) {
    +    /* is called on encountering a textnode
    +
    +        chars is the node's nodeValue
    +    */
    +};
    +
    +SAXHandler.prototype.comment = function(comment) {
    +    /* is called when encountering a comment node
    +
    +        comment is the node's nodeValue
    +    */
    +};
    +
    +SAXHandler.prototype.endDocument = function() {
    +    /* is called after all nodes were visited */
    +};
    +
    
    Added: kukit/kukit.js/trunk/3rd_party/johnnydebris.net/minisax.js/test_minisax.js
    ==============================================================================
    --- (empty file)
    +++ kukit/kukit.js/trunk/3rd_party/johnnydebris.net/minisax.js/test_minisax.js	Sun Jan 20 20:43:18 2008
    @@ -0,0 +1,134 @@
    +/*
    +    tests.js - unit tests for minisax.js
    +    Copyright (C) 2004-2005 Guido Wesdorp
    +    email johnny at debris.demon.nl
    +
    +    This program is free software; you can redistribute it and/or modify
    +    it under the terms of the GNU General Public License as published by
    +    the Free Software Foundation; either version 2 of the License, or
    +    (at your option) any later version.
    +
    +    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
    +
    +    $Id: minisax.js,v 1.5 2004/07/31 00:10:15 johnny Exp $
    +
    +*/
    +
    +load('../jsbase/string.js');
    +load('../jsbase/array.js');
    +load('minisax.js');
    +
    +var global = this;
    +global.parser = undefined;
    +global.handler = undefined;
    +function setup() {
    +    global.parser = new SAXParser();
    +    global.handler = new TestHandler(); // see below
    +};
    +
    +function test_regs() {
    +    global.parser.initialize('', global.handler);
    +    var reg = global.parser.starttagreg;
    +    var xml = '';
    +    testing.assertEquals(xml.match(reg).slice(1).toString(), 
    +                        ['', 'foo', '', ''].toString());
    +    var xml = '  ';
    +    testing.assertEquals(xml.match(reg).slice(1).toString(), 
    +                        ['', 'foo', '', '/'].toString());
    +    var xml = 'foo:bar foo="bar"/>sdhfsjkhffsjk';
    +    testing.assertEquals(xml.match(reg).slice(1).toString(),
    +                        ['tal:', 'block', ' define="foobar" ', '/'].toString());
    +};
    +
    +function test_events() {
    +    var handler = new TestHandler();
    +    var xml = 'baz';
    +    global.parser.initialize(xml, handler);
    +    global.parser.parse();
    +    
    +    testing.assert(handler.document_started);
    +    testing.assert(handler.document_ended);
    +    
    +    var starttuples = handler.start_elements;
    +    array.map(starttuples, function(t) {return t[1];});
    +    endtuples = handler.end_elements;
    +    array.map(endtuples, function(t) {return t[1];});
    +    testing.assertEquals(starttuples.toString(), 
    +                        ['foo', 'bar'].toString());
    +    testing.assertEquals(array.reversed(starttuples).toString(),
    +                        endtuples.toString());
    +    testing.assertEquals(handler.characterstrings.toString(),
    +                        ['baz'].toString());
    +};
    +
    +function test_namespaces() {
    +    var handler = new TestHandler();
    +    var xml = '\n' +
    +                '\n' +
    +                '\n' + 
    +                '\n' + 
    +                'baz\n' +
    +                '\n' +
    +                '';
    +    global.parser.initialize(xml, handler);
    +    global.parser.parse();
    +
    +    testing.assertEquals(handler.start_elements[0][0], 'foo');
    +    testing.assertEquals(handler.start_elements[1][0], 'bar');
    +    testing.assertEquals(handler.start_elements[2][0], 'foo');
    +    testing.assertEquals(handler.end_elements[0][0], 'foo');
    +    testing.assertEquals(handler.end_elements[1][0], 'bar');
    +    testing.assertEquals(handler.end_elements[2][0], 'foo');
    +    testing.assertEquals(handler.start_elements[0][2]['']['foo'], 'bar');
    +    testing.assertEquals(handler.start_elements[0][2][
    +                        'http://www.w3.org/XML/1998/namespace']['lang'], 'en');
    +    testing.assertEquals(handler.start_elements[0][2]['bar']['quux'], 'quux');
    +    testing.assertEquals(handler.start_elements[1][2]['qux']['foo'], 'bar');
    +    testing.assertEquals(handler.start_elements[2][2]['']['quux'], 'quux');
    +    testing.assertEquals(handler.start_elements[2][2]['bar']['qux'], 'qux');
    +
    +    testing.assertEquals(handler.characterstrings.toString(),
    +                        ['\n', '\n', '\n', '\nbaz\n', '\n'].toString());
    +};
    +
    +function TestHandler() {
    +    this.document_started = false;
    +    this.document_ended = false;
    +    this.start_elements = []; // tuples [ns, name, attrs]
    +    this.end_elements = []; // tuples [ns, name]
    +    this.characterstrings = [];
    +};
    +
    +TestHandler.prototype = new SAXHandler;
    +
    +TestHandler.prototype.startDocument = function() {
    +    this.document_started = true;
    +};
    +
    +TestHandler.prototype.endDocument = function() {
    +    this.document_ended = true;
    +};
    +
    +TestHandler.prototype.startElement = function(namespace, nodename, attrs) {
    +    this.start_elements.push([namespace, nodename, attrs]);
    +};
    +
    +TestHandler.prototype.endElement = function(namespace, nodename) {
    +    this.end_elements.push([namespace, nodename]);
    +};
    +
    +TestHandler.prototype.characters = function(chars) {
    +    this.characterstrings.push(chars);
    +};
    +
    +TestHandler.prototype.comment = function(comment) {
    +    this.comments.push(comment);
    +};
    
    Added: kukit/kukit.js/trunk/3rd_party/johnnydebris.net/minisax.js/testhandler.js
    ==============================================================================
    --- (empty file)
    +++ kukit/kukit.js/trunk/3rd_party/johnnydebris.net/minisax.js/testhandler.js	Sun Jan 20 20:43:18 2008
    @@ -0,0 +1,113 @@
    +/*
    +    testhandler.js - SAX handler for example and tests of minisax.js
    +    Copyright (C) 2004-2005 Guido Wesdorp
    +    email johnny at debris.demon.nl
    +
    +    This program is free software; you can redistribute it and/or modify
    +    it under the terms of the GNU General Public License as published by
    +    the Free Software Foundation; either version 2 of the License, or
    +    (at your option) any later version.
    +
    +    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
    +
    +    $Id: minisax.js,v 1.5 2004/07/31 00:10:15 johnny Exp $
    +
    +*/
    +
    +function TestHandler() {
    +    /* generates XML from XML
    +
    +        test code (and an example, although there's a bit much
    +        cruft to get the result nice-looking) for the SAX parser
    +    */
    +
    +    this.startDocument = function() {
    +        this.xml = '';
    +        this.namespaces = {};
    +        this.lastns = 0;
    +        this.firstelement = '';
    +    };
    +    
    +    this.startElement = function(namespace, nodename, attributes) {
    +        var xml = '<';
    +        if (namespace != '') {
    +            var nsname;
    +            if (namespace in this.namespaces) {
    +                nsname = this.namespaces[namespace];
    +            } else {
    +                nsname = this._createNamespaceName();
    +                this.namespaces[namespace] = nsname;
    +            };
    +            if (nsname != 'ns0') {
    +                xml += nsname + ':';
    +            };
    +        };
    +        xml += nodename;
    +        for (anamespace in attributes) {
    +            var attrdict = attributes[anamespace];
    +            var nsname = null;
    +            if (anamespace != "") {
    +                if (anamespace in this.namespaces) {
    +                    nsname = this.namespaces[anamespace];
    +                } else {
    +                    nsname = this._createNamespaceName();
    +                    this.namespaces[anamespace] = nsname;
    +                };
    +            };
    +            for (var aname in attrdict) {
    +                xml += ' ';
    +                if (nsname) {
    +                    xml += nsname + ':';
    +                };
    +                xml += aname + '="' + string.entitize(attrdict[aname]) + '"';
    +            };
    +        };
    +        if (this.firstelement == '') {
    +            this.firstelement = xml;
    +        } else {
    +            this.xml += xml + '>';
    +        };
    +    };
    +
    +    this.endElement = function(namespace, nodename) {
    +        this.xml += '';
    +    };
    +
    +    this.characters = function(content) {
    +        this.xml += string.entitize(content);
    +    };
    +
    +    this.endDocument = function() {
    +        var xml = this.firstelement;
    +        for (namespace in this.namespaces) {
    +            xml += ' xmlns';
    +            if (this.namespaces[namespace] != 'ns0') {
    +                xml += ':' + this.namespaces[namespace];
    +            };
    +            xml += '="' + namespace + '"';
    +        };
    +        xml += '>' + this.xml;
    +        this.xml = xml;
    +    };
    +
    +    this._createNamespaceName = function() {
    +        var name = 'ns' + this.lastns;
    +        this.lastns++;
    +        return name;
    +    };
    +};
    +
    +TestHandler.prototype = new SAXHandler;
    +
    +
    
    Added: kukit/kukit.js/trunk/3rd_party/johnnydebris.net/minisax.js/version.txt
    ==============================================================================
    --- (empty file)
    +++ kukit/kukit.js/trunk/3rd_party/johnnydebris.net/minisax.js/version.txt	Sun Jan 20 20:43:18 2008
    @@ -0,0 +1 @@
    +0.3
    
    Modified: kukit/kukit.js/trunk/kukit/kukit.js
    ==============================================================================
    --- kukit/kukit.js/trunk/kukit/kukit.js	(original)
    +++ kukit/kukit.js/trunk/kukit/kukit.js	Sun Jan 20 20:43:18 2008
    @@ -87,32 +87,7 @@
             // testing or what
             return base;
         }
    -    // fetch base from specific link in case of ill situations
    -    // like default pages in Plone 
    -    var nodes = document.getElementsByTagName("link");
    -    if (nodes.length > 0) {
    -        for (var i=0; i 0) {
    +        for (var i=0; i 
             
    +        
    +        
    +
    +        
    +
    +        
    +
    +        
    +