From reebalazs at codespeak.net Fri Apr 4 22:43:39 2008 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Fri, 4 Apr 2008 22:43:39 +0200 (CEST) Subject: [KSS-checkins] r53362 - in kukit/kss.demo/branch/1.4-kss-test/kss/demo: . browser selenium_utils tests Message-ID: <20080404204339.2BEF416AA89@codespeak.net> Author: reebalazs Date: Fri Apr 4 22:43:37 2008 New Revision: 53362 Added: kukit/kss.demo/branch/1.4-kss-test/kss/demo/selenium_layer.py (contents, props changed) kukit/kss.demo/branch/1.4-kss-test/kss/demo/selenium_layers.txt (contents, props changed) kukit/kss.demo/branch/1.4-kss-test/kss/demo/selenium_suite.py (contents, props changed) kukit/kss.demo/branch/1.4-kss-test/kss/demo/tests/base.py (contents, props changed) kukit/kss.demo/branch/1.4-kss-test/kss/demo/tests/test_doc.py (contents, props changed) Modified: kukit/kss.demo/branch/1.4-kss-test/kss/demo/__init__.py kukit/kss.demo/branch/1.4-kss-test/kss/demo/browser/registry.py kukit/kss.demo/branch/1.4-kss-test/kss/demo/browser/setDevMode.html kukit/kss.demo/branch/1.4-kss-test/kss/demo/browser/setProdMode.html kukit/kss.demo/branch/1.4-kss-test/kss/demo/registry.py kukit/kss.demo/branch/1.4-kss-test/kss/demo/resource.py kukit/kss.demo/branch/1.4-kss-test/kss/demo/selenium_utils/builder.py kukit/kss.demo/branch/1.4-kss-test/kss/demo/tests/test_demoview.py Log: Implement selenium layers properly. Modified: kukit/kss.demo/branch/1.4-kss-test/kss/demo/__init__.py ============================================================================== --- kukit/kss.demo/branch/1.4-kss-test/kss/demo/__init__.py (original) +++ kukit/kss.demo/branch/1.4-kss-test/kss/demo/__init__.py Fri Apr 4 22:43:37 2008 @@ -1,4 +1,15 @@ +from resource import ( + KSSSeleniumTestCase, + KSSSeleniumTestDirectory, + KSSSeleniumTestCaseList, + KSSSeleniumEmptyTestCase, + KSSSeleniumSandboxCreationTestCase, + KSSDemo, + ) +from selenium_layer import KSSSeleniumTestLayerBase +from selenium_suite import KSSSeleniumTestSuite + try: import Products.Five except ImportError: Modified: kukit/kss.demo/branch/1.4-kss-test/kss/demo/browser/registry.py ============================================================================== --- kukit/kss.demo/branch/1.4-kss-test/kss/demo/browser/registry.py (original) +++ kukit/kss.demo/branch/1.4-kss-test/kss/demo/browser/registry.py Fri Apr 4 22:43:37 2008 @@ -5,6 +5,7 @@ from zope.component import getUtility from zope.interface import implements from kss.demo.selenium_utils.builder import cookSeleniumTests +from kss.demo.selenium_layer import LayerTree import os.path import re import urllib @@ -71,16 +72,15 @@ """Get selenium tests annotated with title and href.""" registry = getUtility(IKSSDemoRegistry) results = [] - for suite in registry.test_suites: - if not suite.application.lower() == application.strip().lower(): - continue - relative_urls = suite.get_relative_urls(self) - for relative_url in relative_urls: - results.append(dict( - href = relative_url, - title = self._url_to_title(relative_url), - )) - return results + # Filter suites that we need. + suites = [suite for suite in registry.test_suites + if suite.application.lower() == application.strip().lower()] + # Build a tree with the suite, to find the optimal setup / teardown sequence. + tree = LayerTree(suites) + return [dict( + href = relative_url, + title = self._url_to_title(relative_url), + ) for relative_url in tree.get_relative_urls(self)] @staticmethod def _url_to_title(url): Modified: kukit/kss.demo/branch/1.4-kss-test/kss/demo/browser/setDevMode.html ============================================================================== --- kukit/kss.demo/branch/1.4-kss-test/kss/demo/browser/setDevMode.html (original) +++ kukit/kss.demo/branch/1.4-kss-test/kss/demo/browser/setDevMode.html Fri Apr 4 22:43:37 2008 @@ -1,7 +1,7 @@ -basic_commands +Set development mode Modified: kukit/kss.demo/branch/1.4-kss-test/kss/demo/browser/setProdMode.html ============================================================================== --- kukit/kss.demo/branch/1.4-kss-test/kss/demo/browser/setProdMode.html (original) +++ kukit/kss.demo/branch/1.4-kss-test/kss/demo/browser/setProdMode.html Fri Apr 4 22:43:37 2008 @@ -1,7 +1,7 @@ -basic_commands +Set production mode
Modified: kukit/kss.demo/branch/1.4-kss-test/kss/demo/registry.py ============================================================================== --- kukit/kss.demo/branch/1.4-kss-test/kss/demo/registry.py (original) +++ kukit/kss.demo/branch/1.4-kss-test/kss/demo/registry.py Fri Apr 4 22:43:37 2008 @@ -12,7 +12,7 @@ IKSSDemoRegistryEvent, IKSSSeleniumTestSuite ) -from resource import KSSSeleniumTestSuite +from selenium_suite import KSSSeleniumTestSuite from zope.component.interfaces import ( IUtilityRegistration, IRegistered, Modified: kukit/kss.demo/branch/1.4-kss-test/kss/demo/resource.py ============================================================================== --- kukit/kss.demo/branch/1.4-kss-test/kss/demo/resource.py (original) +++ kukit/kss.demo/branch/1.4-kss-test/kss/demo/resource.py Fri Apr 4 22:43:37 2008 @@ -2,7 +2,6 @@ from interfaces import ( IKSSDemo, IKSSSeleniumTestCaseCollection, - IKSSSeleniumTestSuite, ) import itertools import sys, os.path @@ -36,18 +35,15 @@ "Abstract base class to help collection implementation" def find_test_root_dir(self): - # XXX This must be called directly from the __init__ of the class - # and it is able to find out the directory where the class - # was defined from. # # Zope CA magic used to find where the class is defined from frame = sys._getframe(2) - locals = frame.f_locals + f_locals = frame.f_locals # Try to make sure we were called from a class def - if (locals is frame.f_globals) or ('__module__' not in locals): - raise TypeError("classProvides can be used only from a class definition.") + if (f_locals is frame.f_globals) or ('__module__' not in f_locals): + raise TypeError("The %r suite class can be used only from inside a class definition." % (self.__class__, )) # store it - self.test_root_dir = getRootDirOfModule(locals['__module__']) + self.test_root_dir = getRootDirOfModule(f_locals['__module__']) def find_absolute_path(self, filename): "Returns the absolute path of the filename based on the test root directory." @@ -70,7 +66,7 @@ test_filename = self.find_absolute_path(self.test_filename) return [test_filename] - def get_relative_urls(self, view): + def get_relative_urls(self, view, tree=None): return self.make_relative_urls_from_paths(self.get_testcase_paths()) class KSSSeleniumTestDirectory(KSSSeleniumTestCaseCollectionBase): @@ -96,7 +92,7 @@ test_filenames = (filename[1] for filename in test_filenames) return test_filenames - def get_relative_urls(self, view): + def get_relative_urls(self, view, tree=None): return self.make_relative_urls_from_paths(self.get_testcase_paths()) class KSSSeleniumTestCaseList(KSSSeleniumTestCaseCollectionBase): @@ -111,8 +107,8 @@ def get_testcase_paths(self): return itertools.chain(*[case.get_testcase_paths() for case in self.cases]) - def get_relative_urls(self, view): - return itertools.chain(*[case.get_relative_urls(view) for case in self.cases]) + def get_relative_urls(self, view, tree=None): + return itertools.chain(*(case.get_relative_urls(view, tree) for case in self.cases)) class KSSSeleniumEmptyTestCase(KSSSeleniumTestCaseCollectionBase): """An empty test case.""" @@ -121,11 +117,11 @@ def get_testcase_paths(self): return () - def get_relative_urls(self, view): + def get_relative_urls(self, view, tree=None): return () -class KSSSandboxCreationTestCase(KSSSeleniumTestCaseCollectionBase): +class KSSSeleniumSandboxCreationTestCase(KSSSeleniumTestCaseCollectionBase): """A method that can be used for sandbox creation. It is a factory-generated test. It visits a page with a button @@ -148,93 +144,10 @@ def get_testcase_paths(self): return () - def get_relative_urls(self, view): + def get_relative_urls(self, view, tree=None): relative_url = "@@kss-selenium-create-sandbox-test.html?method_name=%s&admin_username=%s&admin_password=%s" % ( self.method_name, view.request.get('admin_username', ''), view.request.get('admin_password', '')) return (relative_url, ) -# -- -# The Suite itself is a collection, but provides a way to use layers with setup and -# tesrdown from the registry. -# -- - -class KSSSeleniumTestLayerBase(object): - setup = KSSSeleniumEmptyTestCase() - teardown = KSSSeleniumEmptyTestCase() - - -# XXX TODO Currently the tuest suite handles the setup and teardown -# of the layer. The suites with the same layer should have a common -# setup. Very easy to implement. -class KSSSeleniumTestSuite(KSSSeleniumTestCaseCollectionBase): - """Represents a selenium suite, - that makes part of an applicaion and a component, - as well as an optional (test) layer. - """ - implements(IKSSSeleniumTestSuite) - - # convenience access for page templates - __allow_access_to_unprotected_subobjects__ = 1 - - tests = KSSSeleniumEmptyTestCase() - component = u'' - application = u'' - # default is an empty layer. - layer = KSSSeleniumTestLayerBase - dual_mode = True - - # resources we use for dual mode - set_devel_mode = KSSSeleniumTestCase('browser/setDevMode.html') - set_prod_mode = KSSSeleniumTestCase('browser/setProdMode.html') - - def __init__(self, tests=None, component=u'', application=u'', layer=None, dual_mode=None): - if tests is not None: - self.tests = tests - self.test_root_dir = self.tests.test_root_dir - if component: - self.component = component - if application: - self.application = application - if layer is not None: - self.layer = layer - if dual_mode is not None: - self.dual_mode = dual_mode - - def get_testcase_paths(self): - return itertools.chain( - * (case.get_testcase_paths() for case in self.iterables) - ) - - def get_relative_urls(self, view): - return itertools.chain( - * (case.get_relative_urls(view) for case in self.iterables) - ) - - @property - def iterables(self): - # Check if we have tests at all. If no, we don't need the - # setup/teardown. - # - # The next expression decided if the iterator yields any resuls - # TODO make an empty() on the interface ? - if tuple(itertools.islice(self.tests.get_relative_urls(self), 0, 1)): - if self.dual_mode: - return ( - self.layer.setup, - self.set_devel_mode, - self.tests, - self.set_prod_mode, - self.tests, - self.layer.teardown, - ) - else: - return ( - self.layer.setup, - self.tests, - self.layer.teardown, - ) - else: - # No tests, nothing to do. - return () Added: kukit/kss.demo/branch/1.4-kss-test/kss/demo/selenium_layer.py ============================================================================== --- (empty file) +++ kukit/kss.demo/branch/1.4-kss-test/kss/demo/selenium_layer.py Fri Apr 4 22:43:37 2008 @@ -0,0 +1,202 @@ +"""\ +Layers for Selenium tests + +The goal of this structures to allow to generate the setup / teardown +sequence in an optimal way. Since we have to group tests to be +executed in the same layer, and trim away layers with no tests, +this must be done for each list of selected testcases. +""" + +import itertools +from resource import KSSSeleniumEmptyTestCase, KSSSeleniumTestCase + +class metalayer(type): + def __init__(cls, name, bases, attrs): + # If setup or teardown are not declared, we consider + # them as empty. + if 'setup' not in attrs: + attrs['setup'] = KSSSeleniumEmptyTestCase() + if 'teardown' not in attrs: + attrs['teardown'] = KSSSeleniumEmptyTestCase() + # Set up the class + super(metalayer, cls).__init__(name, bases, attrs) + +class KSSSeleniumTestLayerBase(object): + __metaclass__ = metalayer + setup = KSSSeleniumEmptyTestCase() + teardown = KSSSeleniumEmptyTestCase() + +class LayerTreeNode(object): + """An active tree node + + It participates in a Tree, it contains a list of suites. + If the list of suites is empty, that means this layer + is "inactive" in the tree: it is needed for the setup / teardown + sequence, but contains no tests itself. + """ + + # resources we use for dual mode + set_devel_mode = KSSSeleniumTestCase('browser/setDevMode.html') + set_prod_mode = KSSSeleniumTestCase('browser/setProdMode.html') + + def __init__(self, tree, layer): + self.tree = tree + self.suites = [] + self.layer = layer + self.base_layer = None + self.child_nodes = [] + + def add_suite(self, suite): + assert suite.layer == self.layer, "Suite must have the same layer." + self.suites.append(suite) + + def add_parents(self): + layer = self.layer + # A layer must be a subclass of the base class. + assert issubclass(layer, KSSSeleniumTestLayerBase), \ + "Layers must be classes inheriting from KSSSeleniumTestLayerBase." + # Find out the bases. We only consider bases + # that inherit from the base class. + try: + bases = layer.__bases__ + except AttributeError: + raise Exception, "Layers must be classes." + bases = (base for base in bases if issubclass(base, KSSSeleniumTestLayerBase)) + # We are only interested in the first base. + # (In case of multi inheritence we could have more bases, + # and although this is hardly imaginable as use case, it is supported anyway.) + bases = tuple(itertools.islice(bases, 0, 1)) + # There must be one base, + # unless we are at the root node. + if not bases: + # We found the root. + assert layer == KSSSeleniumTestLayerBase, "This should not happen." + self.tree.root = self + else: + if len(bases) > 1: + raise Exception, "Double inheritence of layers is not supported." + base_layer = bases[0] + # Add this layer to the tree as well, and remember it. + base_node = self.tree.add_layer(base_layer) + # Mark ourselves as a child node. + self.base_node = base_node + base_node.child_nodes.append(self) + + def get_testcase_paths_for_layer(self): + """Give the absolute paths "owned" for the layer itself.""" + # order does not matter here. + # Just needed to enable these resources. + # Also: enable the set devel / prod resources always. + if self.base_layer is not None: + base_layer_tests = self.tree.lookup_layer(self.base_layer).get_testcase_paths_for_layer(), + else: + # We are at the root. + base_layer_tests = () + # Compose all paths + return itertools.chain( + base_layer_tests, + self.layer.setup.get_testcase_paths(), + self.layer.teardown.get_testcase_paths(), + self.set_devel_mode.get_testcase_paths(), + self.set_prod_mode.get_testcase_paths(), + ) + + def get_relative_urls_for_own_tests(self, view): + """Generate the tests in all suites in this layer subtree. No setup or teardown. + + This is needed to decide if we can prune a part of the tree (if there are no tests, + setup and teardown are not needed either.) + """ + return itertools.chain( + # Our own tests + itertools.chain(*(suite.tests.get_relative_urls(view, self.tree) for suite in self.suites)), + # Tests from the child layers + itertools.chain(*(node.get_relative_urls_for_own_tests(view) for node in self.child_nodes)), + ) + + def get_relative_urls(self, view): + """Generate the walking order for the node and its subtree.""" + # Look ahead check if we have any tests at all. + suite_tests_lookahead = self.get_relative_urls_for_own_tests(view) + # Do we have tests at all? + # If not, we just don't want to emit setup and teardown at all. + if tuple(itertools.islice(suite_tests_lookahead, 0, 1)): + # Does any of our suites have dual mode? + suites_by_duality = {True: [], False: []} + for suite in self.suites: + suites_by_duality[suite.dual_mode].append(suite) + # Create the tests for suites. + # Look ahead check if we have any dual tests at all. + dual_tests_lookahead = itertools.chain(*(suite.tests.get_relative_urls(view, self.tree) for suite in suites_by_duality[True])) + if tuple(itertools.islice(dual_tests_lookahead, 0, 1)): + # We do have some dual tests. So we need to run them twice and set + # development and production modes for this. + dual_tests = itertools.chain( + # Dual mode tests from the suites in this layer, in Development mode + self.set_devel_mode.get_relative_urls(view, self.tree), + itertools.chain(*(suite.tests.get_relative_urls(view, self.tree) for suite in suites_by_duality[True])), + # Dual mode tests from the suites in this layer, in Production mode + self.set_prod_mode.get_relative_urls(view, self.tree), + itertools.chain(*(suite.tests.get_relative_urls(view, self.tree) for suite in suites_by_duality[True])), + ) + else: + # No dual mode tests + dual_tests = () + # Now put them together with setup and teardown + return itertools.chain( + # Setup from parent layer + self.layer.setup.get_relative_urls(view, self.tree), + # Dual mode tests from the suites in this layer + dual_tests, + # Single mode tests from the suites in this layer + itertools.chain(*(suite.tests.get_relative_urls(view, self.tree) for suite in suites_by_duality[False])), + # Add tests recursively from contained layers + itertools.chain(*(node.get_relative_urls(view) for node in self.child_nodes)), + # Teardown to parent layer + self.layer.teardown.get_relative_urls(view, self.tree), + ) + else: + # No tests at all. + return () + +class LayerTree(object): + """Builds an inheritence tree from the suites passed in. + """ + def __init__(self, suites=()): + self.suites = [] + self.nodes = {} + self.root = None + self.add_suites(suites) + + def add_suites(self, suites): + for suite in suites: + self.add_suite(suite) + + def add_suite(self, suite): + # make sure we have the layer + node = self.add_layer(suite.layer) + # Add the suite to the node. + node.add_suite(suite) + + def add_layer(self, layer): + # We must fetch the layer node from the tree, + # or create it and its inheritence path to the root layer. + try: + node = self.nodes[layer] + except KeyError: + # create and remember the tree node + node = self.nodes[layer] = LayerTreeNode(self, layer) + # Recursively process parents of the node + node.add_parents() + # caller may access the node + return node + + def lookup_layer(self, layer): + return self.nodes[layer] + + def get_relative_urls(self, view): + """Generate all tests in the tree.""" + if not self.root: + # no root, no tests. + return () + return self.root.get_relative_urls(view) Added: kukit/kss.demo/branch/1.4-kss-test/kss/demo/selenium_layers.txt ============================================================================== --- (empty file) +++ kukit/kss.demo/branch/1.4-kss-test/kss/demo/selenium_layers.txt Fri Apr 4 22:43:37 2008 @@ -0,0 +1,282 @@ +==================== +Selenium test layers +==================== + +We can make our own layer by inheritance from the base class. + + >>> from kss.demo import KSSSeleniumTestLayerBase + +Create the class: + + >>> class aLayer(KSSSeleniumTestLayerBase): + ... pass + +Since we did not overwrite setup and teardown, they must be emtpy. + + >>> aLayer.setup + + >>> aLayer.teardown + + + +Specifying setup and teardown for a layer +----------------------------------------- + +A more sensible use case is to create some setup and teardown for +ourselves. We will create test cases that refer to non-existent +files, now. + + >>> from kss.demo import KSSSeleniumTestCase + + >>> class aLayer(KSSSeleniumTestLayerBase): + ... setup = KSSSeleniumTestCase('1') + ... teardown = KSSSeleniumTestCase('2') + + >>> aLayer.setup + + >>> aLayer.teardown + + +We also check the actual urls that will result the testing +sequence. Note that get_relative_urls would take the view +in normal use, but it is not important for this test. + + >>> tuple(aLayer.setup.get_relative_urls(None)) + ('@@resource?path=1',) + >>> tuple(aLayer.teardown.get_relative_urls(None)) + ('@@resource?path=2',) + +If I inherit from this layer, and I do not overwrite setup +or teardown, it still gets an empty value. + + >>> class zLayer(KSSSeleniumTestLayerBase): + ... setup = KSSSeleniumTestCase('3') + + >>> zLayer.setup + + >>> tuple(zLayer.setup.get_relative_urls(None)) + ('@@resource?path=3',) + + >>> zLayer.teardown + + + +Inheriting layers +----------------- + +Now, let us inherit a layer from another layer. + + >>> class bLayer(aLayer): + ... setup = KSSSeleniumTestCase('5') + ... teardown = KSSSeleniumTestCase('6') + +And another one. + + >>> class cLayer(aLayer): + ... setup = KSSSeleniumTestCase('7') + ... teardown = KSSSeleniumTestCase('8') + +Even we inherit more. + + >>> class dLayer(cLayer): + ... setup = KSSSeleniumTestCase('9') + ... teardown = KSSSeleniumTestCase('10') + + >>> class eLayer(cLayer): + ... setup = KSSSeleniumTestCase('11') + ... teardown = KSSSeleniumTestCase('12') + + +This results in the following inheritence structure:: + + a + | + ------ + | | + b c + | + ------ + | | + d e + + +Using layers from suites +======================== + +We define suites that use the above layers. + + >>> from kss.demo import KSSSeleniumTestSuite + +The following definition to define a suite would fail: + + >>> aSuite = KSSSeleniumTestSuite( + ... tests = KSSSeleniumTestCase('ta'), + ... layer = aLayer, + ... ) + Traceback (most recent call last): + ... + TypeError: The suite class can be used only from inside a class definition. + +As the error message says, we must define the class from inside another +class. This is used to locate files relatively from the module where the +definition is. So we have to define them from a dummy plugin (however the plugin +itself play no role in testing). + + >>> class DummyPlugin(object): + ... + ... aSuite = KSSSeleniumTestSuite( + ... tests = KSSSeleniumTestCase('ta'), + ... layer = aLayer, + ... ) + >>> aSuite = DummyPlugin.aSuite + +The layers whose tests are active, will build a tree to compute the +optimal setup-teardown order. + + >>> from kss.demo.selenium_layer import LayerTree + + >>> tree = LayerTree((aSuite, )) + >>> tuple(tree.get_relative_urls(None)) + ('@@resource?path=1', '@@resource?path=...setDevMode.html', '@@resource?path=ta', '@@resource?path=...setProdMode.html', '@@resource?path=ta', '@@resource?path=2') + +As we can see in the above results, the tests are generated properly with setup and teardown. + +If more cases use the same layer, they are grouped. They also just need to change +the production mode twice: + + >>> class DummyPlugin2(object): + ... + ... a2Suite = KSSSeleniumTestSuite( + ... tests = KSSSeleniumTestCase('ta2'), + ... layer = aLayer, + ... ) + >>> a2Suite = DummyPlugin2.a2Suite + + >>> tree = LayerTree((aSuite, a2Suite)) + >>> tuple(tree.get_relative_urls(None)) + ('@@resource?path=1', '@@resource?path=...setDevMode.html', '@@resource?path=ta', '@@resource?path=ta2', '@@resource?path=...setProdMode.html', '@@resource?path=ta', '@@resource?path=ta2', '@@resource?path=2') + +Now, let's see the tests for the other suites: + + >>> class DummyPlugin3(object): + ... + ... bSuite = KSSSeleniumTestSuite( + ... tests = KSSSeleniumTestCase('tb'), + ... layer = bLayer, + ... ) + ... + ... cSuite = KSSSeleniumTestSuite( + ... tests = KSSSeleniumTestCase('tc'), + ... layer = cLayer, + ... ) + ... + ... dSuite = KSSSeleniumTestSuite( + ... tests = KSSSeleniumTestCase('td'), + ... layer = dLayer, + ... ) + ... + ... d2Suite = KSSSeleniumTestSuite( + ... tests = KSSSeleniumTestCase('td2'), + ... layer = dLayer, + ... ) + ... eSuite = KSSSeleniumTestSuite( + ... tests = KSSSeleniumTestCase('te'), + ... layer = eLayer, + ... ) + ... + >>> bSuite = DummyPlugin3.bSuite + >>> cSuite = DummyPlugin3.cSuite + >>> dSuite = DummyPlugin3.dSuite + >>> d2Suite = DummyPlugin3.d2Suite + >>> eSuite = DummyPlugin3.eSuite + +And see what happens if only suite "d" is selected. We can see that the setup and teardown sequence is correct. + + >>> tree = LayerTree((dSuite, )) + >>> tuple(tree.get_relative_urls(None)) + ('@@resource?path=1', '@@resource?path=7', '@@resource?path=9', '@@resource?path=...setDevMode.html', '@@resource?path=td', '@@resource?path=...setProdMode.html', '@@resource?path=td', '@@resource?path=10', '@@resource?path=8', '@@resource?path=2') + + +Replay this with a bunch of other tests added. Setup and teardown is executed ideally. +In this case we have more dev / prod mode changes, since these are the fastest +they are wrapped inside the layer. + + >>> tree = LayerTree((cSuite, dSuite, d2Suite)) + >>> tuple(tree.get_relative_urls(None)) + ('@@resource?path=1', '@@resource?path=7', '@@resource?path=...setDevMode.html', '@@resource?path=tc', '@@resource?path=...setProdMode.html', '@@resource?path=tc', '@@resource?path=9', '@@resource?path=...setDevMode.html', '@@resource?path=td', '@@resource?path=td2', '@@resource?path=...setProdMode.html', '@@resource?path=td', '@@resource?path=td2', '@@resource?path=10', '@@resource?path=8', '@@resource?path=2') + +So far we have only tried single path setups. Let's now try a split route. +The setup and teardown work correctly in one level. + + >>> tree = LayerTree((aSuite, bSuite, cSuite)) + >>> tuple(tree.get_relative_urls(None)) + ('@@resource?path=1', '@@resource?path=...setDevMode.html', '@@resource?path=ta', '@@resource?path=...setProdMode.html', '@@resource?path=ta', '@@resource?path=5', '@@resource?path=...setDevMode.html', '@@resource?path=tb', '@@resource?path=...setProdMode.html', '@@resource?path=tb', '@@resource?path=6', '@@resource?path=7', '@@resource?path=...setDevMode.html', '@@resource?path=tc', '@@resource?path=...setProdMode.html', '@@resource?path=tc', '@@resource?path=8', '@@resource?path=2') + + +Another functionality is that certain tests may mark that they don't want +to be in dual mode: + + >>> class DummyPlugin4(object): + ... + ... b2Suite = KSSSeleniumTestSuite( + ... tests = KSSSeleniumTestCase('tb2'), + ... layer = bLayer, + ... dual_mode = False, + ... ) + >>> b2Suite = DummyPlugin4.b2Suite + + >>> tree = LayerTree((b2Suite, )) + >>> tuple(tree.get_relative_urls(None)) + ('@@resource?path=1', '@@resource?path=5', '@@resource?path=tb2', '@@resource?path=6', '@@resource?path=2') + +This is also true if both dual and single mode tests are in the same layer. In this case +the tests will wun in the end, which in practice means Production mode. + + >>> tree = LayerTree((bSuite, b2Suite)) + >>> tuple(tree.get_relative_urls(None)) + ('@@resource?path=1', '@@resource?path=5', '@@resource?path=...setDevMode.html', '@@resource?path=tb', '@@resource?path=...setProdMode.html', '@@resource?path=tb', '@@resource?path=tb2', '@@resource?path=6', '@@resource?path=2') + +Now let's add a bunch of suites: + + >>> tree = LayerTree((aSuite, a2Suite, bSuite, b2Suite, cSuite, dSuite, d2Suite, eSuite)) + >>> tuple(tree.get_relative_urls(None)) + ('@@resource?path=1', '@@resource?path=...setDevMode.html', '@@resource?path=ta', '@@resource?path=ta2', '@@resource?path=...setProdMode.html', '@@resource?path=ta', '@@resource?path=ta2', '@@resource?path=5', '@@resource?path=...setDevMode.html', '@@resource?path=tb', '@@resource?path=...setProdMode.html', '@@resource?path=tb', '@@resource?path=tb2', '@@resource?path=6', '@@resource?path=7', '@@resource?path=...setDevMode.html', '@@resource?path=tc', '@@resource?path=...setProdMode.html', '@@resource?path=tc', '@@resource?path=9', '@@resource?path=...setDevMode.html', '@@resource?path=td', '@@resource?path=td2', '@@resource?path=...setProdMode.html', '@@resource?path=td', '@@resource?path=td2', '@@resource?path=10', '@@resource?path=11', '@@resource?path=...setDevMode.html', '@@resource?path=te', '@@resource?path=...setProdMode.html', '@@resource?path=te', '@@resource?path=12', '@@resource?path=8', '@@resource?path=2') + + +Finally, we still need to check the following: +Suites that are empty are skipped, and no setup teardown or devel / prod mode is generated for them. + + >>> class DummyPlugin5(object): + ... + ... a3Suite = KSSSeleniumTestSuite( + ... + ... ) + ... + ... b3Suite = KSSSeleniumTestSuite( + ... ) + >>> a3Suite = DummyPlugin5.a3Suite + >>> b3Suite = DummyPlugin5.b3Suite + + >>> tree = LayerTree((a3Suite, )) + >>> tuple(tree.get_relative_urls(None)) + () + + >>> tree = LayerTree((a3Suite, aSuite)) + >>> tuple(tree.get_relative_urls(None)) + ('@@resource?path=1', '@@resource?path=...setDevMode.html', '@@resource?path=ta', '@@resource?path=...setProdMode.html', '@@resource?path=ta', '@@resource?path=2') + + >>> tree = LayerTree((a3Suite, b3Suite)) + >>> tuple(tree.get_relative_urls(None)) + () + + >>> tree = LayerTree((a3Suite, b3Suite, bSuite)) + >>> tuple(tree.get_relative_urls(None)) + ('@@resource?path=1', '@@resource?path=5', '@@resource?path=...setDevMode.html', '@@resource?path=tb', '@@resource?path=...setProdMode.html', '@@resource?path=tb', '@@resource?path=6', '@@resource?path=2') + + >>> tree = LayerTree((aSuite, a3Suite, b3Suite, bSuite)) + >>> tuple(tree.get_relative_urls(None)) + ('@@resource?path=1', '@@resource?path=...setDevMode.html', '@@resource?path=ta', '@@resource?path=...setProdMode.html', '@@resource?path=ta', '@@resource?path=5', '@@resource?path=...setDevMode.html', '@@resource?path=tb', '@@resource?path=...setProdMode.html', '@@resource?path=tb', '@@resource?path=6', '@@resource?path=2') + + +And this concludes the layer tests. + Added: kukit/kss.demo/branch/1.4-kss-test/kss/demo/selenium_suite.py ============================================================================== --- (empty file) +++ kukit/kss.demo/branch/1.4-kss-test/kss/demo/selenium_suite.py Fri Apr 4 22:43:37 2008 @@ -0,0 +1,65 @@ + +import itertools +from resource import ( + KSSSeleniumTestCaseCollectionBase, + KSSSeleniumEmptyTestCase, + ) +from interfaces import IKSSSeleniumTestSuite +from selenium_layer import LayerTree, KSSSeleniumTestLayerBase +from zope.interface import implements + +# -- +# The Suite itself is a collection, but provides a way to use layers with setup and +# tesrdown from the registry. +# -- + +class KSSSeleniumTestSuite(KSSSeleniumTestCaseCollectionBase): + """Represents a selenium suite, + that makes part of an applicaion and a component, + as well as an optional (test) layer. + """ + implements(IKSSSeleniumTestSuite) + + # convenience access for page templates + __allow_access_to_unprotected_subobjects__ = 1 + + tests = KSSSeleniumEmptyTestCase() + component = u'' + application = u'' + # default is an empty layer. + layer = KSSSeleniumTestLayerBase + dual_mode = True + + def __init__(self, tests=None, component=u'', application=u'', layer=None, dual_mode=None): + if tests is not None: + self.tests = tests + if component: + self.component = component + if application: + self.application = application + if layer is not None: + self.layer = layer + if dual_mode is not None: + self.dual_mode = dual_mode + + def get_testcase_paths(self, tree=None): + # No need to care for order. We only need to give + # access to resources that we "own": + # from our setup, own tests, and + # teardown. + # + if not tree: + # Just handle this suite individually. + tree = LayerTree() + tree.add_suites((self, )) + return itertools.chain( + self.tests.get_testcase_paths(), + tree.lookup_layer(self.layer).get_testcase_paths_for_layer() + ) + + def get_relative_urls(self, view, tree=None): + # Just handle this suite individually, + # even if we had a tree passed in. + tree = LayerTree() + tree.add_suites((self, )) + return tree.get_relative_urls(view) Modified: kukit/kss.demo/branch/1.4-kss-test/kss/demo/selenium_utils/builder.py ============================================================================== --- kukit/kss.demo/branch/1.4-kss-test/kss/demo/selenium_utils/builder.py (original) +++ kukit/kss.demo/branch/1.4-kss-test/kss/demo/selenium_utils/builder.py Fri Apr 4 22:43:37 2008 @@ -8,7 +8,12 @@ # root directory finding code def getRootDirOfModule(module_name): - return os.path.dirname(sys.modules[module_name].__file__) + if module_name == '__builtin__': + # This may happen in tests and interactively, + # and it's sensible to use an absolute path in this case. + return '' + else: + return os.path.dirname(sys.modules[module_name].__file__) def getRootDirOfClass(cls): return getRootDirOfModule(cls.__module__) Added: kukit/kss.demo/branch/1.4-kss-test/kss/demo/tests/base.py ============================================================================== --- (empty file) +++ kukit/kss.demo/branch/1.4-kss-test/kss/demo/tests/base.py Fri Apr 4 22:43:37 2008 @@ -0,0 +1,13 @@ + +from Products.Five.zcml import load_config +from kss.core.tests.base import KSSViewTestCase +import kss.demo + +class KSSDemoTestLayer(KSSViewTestCase.layer): + @classmethod + def setUp(cls): + load_config('meta.zcml', package=kss.demo) + load_config('configure.zcml', package=kss.demo) + +class KSSDemoTestCaseBase(KSSViewTestCase): + layer = KSSDemoTestLayer Modified: kukit/kss.demo/branch/1.4-kss-test/kss/demo/tests/test_demoview.py ============================================================================== --- kukit/kss.demo/branch/1.4-kss-test/kss/demo/tests/test_demoview.py (original) +++ kukit/kss.demo/branch/1.4-kss-test/kss/demo/tests/test_demoview.py Fri Apr 4 22:43:37 2008 @@ -17,30 +17,22 @@ # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA # 02111-1307, USA. # -import unittest, os -from zope.testing import doctest -from Testing.ZopeTestCase import ZopeTestCase -from kss.core.tests.base import KSSViewTestCase -from Products.Five.zcml import load_string, load_config -import kss.demo +import unittest +from base import KSSDemoTestCaseBase try: import Products.Five + Products = Products # to satisfy pyflakes except AttributeError: from kss.demo.simplecontent_z3 import SimpleContent + SimpleContent = SimpleContent # to satisfy pyflakes else: from kss.demo.simplecontent import SimpleContent -class KSSDemoTestCase(KSSViewTestCase): - - class layer(KSSViewTestCase.layer): - @classmethod - def setUp(cls): - load_config('meta.zcml', package=kss.demo) - load_config('configure.zcml', package=kss.demo) +class KSSDemoTestCase(KSSDemoTestCaseBase): def afterSetUp(self): - KSSViewTestCase.afterSetUp(self) + KSSDemoTestCaseBase.afterSetUp(self) self.setDebugRequest() self.folder._setObject('demo', SimpleContent('Demo', 'Demo')) self.view = self.folder.demo.restrictedTraverse('getDivContent') Added: kukit/kss.demo/branch/1.4-kss-test/kss/demo/tests/test_doc.py ============================================================================== --- (empty file) +++ kukit/kss.demo/branch/1.4-kss-test/kss/demo/tests/test_doc.py Fri Apr 4 22:43:37 2008 @@ -0,0 +1,28 @@ +# Copyright (c) 2008 +# Authors: +# +# 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. +# +import unittest +import doctest +from zope.testing.doctestunit import DocFileSuite + +def test_suite(): + return unittest.TestSuite(( + DocFileSuite('selenium_layers.txt', + package = 'kss.demo', + optionflags = doctest.ELLIPSIS, + ), + )) From reebalazs at codespeak.net Fri Apr 4 23:29:03 2008 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Fri, 4 Apr 2008 23:29:03 +0200 (CEST) Subject: [KSS-checkins] r53364 - in kukit/kss.demo/branch/1.4-kss-test/kss/demo: . tests Message-ID: <20080404212903.B57B116AAE6@codespeak.net> Author: reebalazs Date: Fri Apr 4 23:29:01 2008 New Revision: 53364 Added: kukit/kss.demo/branch/1.4-kss-test/kss/demo/selenium_suites.txt (contents, props changed) Modified: kukit/kss.demo/branch/1.4-kss-test/kss/demo/tests/test_doc.py Log: Add more tests Added: kukit/kss.demo/branch/1.4-kss-test/kss/demo/selenium_suites.txt ============================================================================== --- (empty file) +++ kukit/kss.demo/branch/1.4-kss-test/kss/demo/selenium_suites.txt Fri Apr 4 23:29:01 2008 @@ -0,0 +1,145 @@ + +==================== +Selenium test suites +==================== + +Selenium test suites can be set up from plugin resource definitions. + + >>> from kss.demo import ( + ... KSSSeleniumTestSuite, + ... KSSSeleniumTestCase, + ... ) + + >>> class Plugin(object): + ... + ... selenium_tests = ( + ... KSSSeleniumTestSuite( + ... tests = KSSSeleniumTestCase('1'), + ... ), + ... ) + >>> suite1 = Plugin.selenium_tests[0] + +A suite is like a testcase collection, so it provides its allowed +resource filenames. These are used to secure the resource handling +(to select which files can be served from the filesystem). + + >>> tuple(suite1.get_testcase_paths()) + ('1', '...setDevMode.html', '...setProdMode.html') + +(Normally we would see an absolute path in place of '1', but the module +finder does not work from within doctests.) + +And the list of test urls as well. (We use in place of the view which +is not important in this case.) + + >>> tuple(suite1.get_relative_urls(None)) + ('@@resource?path=...setDevMode.html', '@@resource?path=1', '@@resource?path=...setProdMode.html', '@@resource?path=1') + + +Dual and single mode +-------------------- + +The `suite1` suite also executes the tests twice, both in development and production mode. +If we want single mode for a given suite, we can set it with setting the `dual_mode` +parameter of the suite to False. + + >>> class Plugin2(object): + ... + ... selenium_tests = ( + ... KSSSeleniumTestSuite( + ... tests = KSSSeleniumTestCase('2'), + ... dual_mode = False, + ... ), + ... ) + >>> suite2 = Plugin2.selenium_tests[0] + + >>> tuple(suite2.get_relative_urls(None)) + ('@@resource?path=2',) + + +Using test layers +----------------- + +We can define a layer to the suite, with its own setup and teardown. + + >>> from kss.demo import KSSSeleniumTestLayerBase + + >>> class aLayer(KSSSeleniumTestLayerBase): + ... setup = KSSSeleniumTestCase('sa') + ... teardown = KSSSeleniumTestCase('ta') + +Now we add a suite with this layer. + + >>> class Plugin3(object): + ... + ... selenium_tests = ( + ... KSSSeleniumTestSuite( + ... tests = KSSSeleniumTestCase('3'), + ... layer = aLayer, + ... ), + ... ) + >>> suite3 = Plugin3.selenium_tests[0] + +Check the results: + + >>> tuple(suite3.get_testcase_paths()) + ('3', 'sa', 'ta', '...setDevMode.html', '...setProdMode.html') + + >>> tuple(suite3.get_relative_urls(None)) + ('@@resource?path=sa', '@@resource?path=...setDevMode.html', '@@resource?path=3', '@@resource?path=...setProdMode.html', '@@resource?path=3', '@@resource?path=ta') + + +Inheritence of layers +--------------------- + +Layers can inherit from each other. + + >>> class bLayer(aLayer): + ... setup = KSSSeleniumTestCase('sb') + ... teardown = KSSSeleniumTestCase('tb') + + >>> class Plugin4(object): + ... + ... selenium_tests = ( + ... KSSSeleniumTestSuite( + ... tests = KSSSeleniumTestCase('4'), + ... layer = bLayer, + ... ), + ... ) + >>> suite4 = Plugin4.selenium_tests[0] + + >>> tuple(suite4.get_testcase_paths()) + ('4', 'sb', 'tb', '...setDevMode.html', '...setProdMode.html') + + >>> tuple(suite4.get_relative_urls(None)) + ('@@resource?path=sa', '@@resource?path=sb', '@@resource?path=...setDevMode.html', '@@resource?path=4', '@@resource?path=...setProdMode.html', '@@resource?path=4', '@@resource?path=tb', '@@resource?path=ta') + + +Generating tests for a set of resources +--------------------------------------- + +Normally, the tests are not collected from suites individually, but a tree is built from a set +of suites providing an optimal setup and teardown sequence. This is done by the demo utility itself. +The list of suites is originating from various different plugins. + + >>> class Plugin5(object): + ... + ... selenium_tests = ( + ... KSSSeleniumTestSuite( + ... tests = KSSSeleniumTestCase('5a'), + ... layer = aLayer, + ... ), + ... KSSSeleniumTestSuite( + ... tests = KSSSeleniumTestCase('5b'), + ... layer = bLayer, + ... ), + ... ) + + >>> from kss.demo.selenium_layer import LayerTree + >>> tree = LayerTree(Plugin5.selenium_tests + (suite2, )) + >>> tuple(tree.get_relative_urls(None)) + ('@@resource?path=2', '@@resource?path=sa', '@@resource?path=...setDevMode.html', '@@resource?path=5a', '@@resource?path=...setProdMode.html', '@@resource?path=5a', '@@resource?path=sb', '@@resource?path=...setDevMode.html', '@@resource?path=5b', '@@resource?path=...setProdMode.html', '@@resource?path=5b', '@@resource?path=tb', '@@resource?path=ta') + +More testing of the layers can be found in the selenium_layers.txt file. + + Modified: kukit/kss.demo/branch/1.4-kss-test/kss/demo/tests/test_doc.py ============================================================================== --- kukit/kss.demo/branch/1.4-kss-test/kss/demo/tests/test_doc.py (original) +++ kukit/kss.demo/branch/1.4-kss-test/kss/demo/tests/test_doc.py Fri Apr 4 23:29:01 2008 @@ -25,4 +25,8 @@ package = 'kss.demo', optionflags = doctest.ELLIPSIS, ), + DocFileSuite('selenium_suites.txt', + package = 'kss.demo', + optionflags = doctest.ELLIPSIS, + ), )) From reebalazs at codespeak.net Fri Apr 4 23:49:36 2008 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Fri, 4 Apr 2008 23:49:36 +0200 (CEST) Subject: [KSS-checkins] r53366 - kukit/kss.demo/branch/1.4-kss-test/kss/demo/browser Message-ID: <20080404214936.B614A16AB10@codespeak.net> Author: reebalazs Date: Fri Apr 4 23:49:36 2008 New Revision: 53366 Modified: kukit/kss.demo/branch/1.4-kss-test/kss/demo/browser/setDevMode.html kukit/kss.demo/branch/1.4-kss-test/kss/demo/browser/setProdMode.html Log: change titles in devel / prod mode suite Modified: kukit/kss.demo/branch/1.4-kss-test/kss/demo/browser/setDevMode.html ============================================================================== --- kukit/kss.demo/branch/1.4-kss-test/kss/demo/browser/setDevMode.html (original) +++ kukit/kss.demo/branch/1.4-kss-test/kss/demo/browser/setDevMode.html Fri Apr 4 23:49:36 2008 @@ -6,7 +6,7 @@
- + Modified: kukit/kss.demo/branch/1.4-kss-test/kss/demo/browser/setProdMode.html ============================================================================== --- kukit/kss.demo/branch/1.4-kss-test/kss/demo/browser/setProdMode.html (original) +++ kukit/kss.demo/branch/1.4-kss-test/kss/demo/browser/setProdMode.html Fri Apr 4 23:49:36 2008 @@ -6,7 +6,7 @@
basic_commands
Set development mode
open
- + From reebalazs at codespeak.net Sat Apr 5 00:07:51 2008 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Sat, 5 Apr 2008 00:07:51 +0200 (CEST) Subject: [KSS-checkins] r53368 - kukit/kss.demo/branch/1.4-kss-test/kss/demo Message-ID: <20080404220751.6E31116AAFE@codespeak.net> Author: reebalazs Date: Sat Apr 5 00:07:50 2008 New Revision: 53368 Modified: kukit/kss.demo/branch/1.4-kss-test/kss/demo/selenium_suites.txt Log: Add more tests Modified: kukit/kss.demo/branch/1.4-kss-test/kss/demo/selenium_suites.txt ============================================================================== --- kukit/kss.demo/branch/1.4-kss-test/kss/demo/selenium_suites.txt (original) +++ kukit/kss.demo/branch/1.4-kss-test/kss/demo/selenium_suites.txt Sat Apr 5 00:07:50 2008 @@ -88,6 +88,41 @@ >>> tuple(suite3.get_relative_urls(None)) ('@@resource?path=sa', '@@resource?path=...setDevMode.html', '@@resource?path=3', '@@resource?path=...setProdMode.html', '@@resource?path=3', '@@resource?path=ta') +To use more tests in the setup of a layer, no extra effort is needed +since the testcase resource already provide KSSSeleniumTestCaseList +to construct collection from other testcases. + + >>> from kss.demo import KSSSeleniumTestCaseList + + >>> class a2Layer(KSSSeleniumTestLayerBase): + ... setup = KSSSeleniumTestCaseList( + ... KSSSeleniumTestCase('sa1'), + ... KSSSeleniumTestCase('sa2'), + ... ) + ... teardown = KSSSeleniumTestCaseList( + ... KSSSeleniumTestCase('ta1'), + ... KSSSeleniumTestCase('ta2'), + ... ) + + + >>> class Plugin3b(object): + ... + ... selenium_tests = ( + ... KSSSeleniumTestSuite( + ... tests = KSSSeleniumTestCase('3b'), + ... layer = a2Layer, + ... ), + ... ) + >>> suite3b = Plugin3b.selenium_tests[0] + +Check the results: + + >>> tuple(suite3b.get_testcase_paths()) + ('3b', 'sa1', 'sa2', 'ta1', 'ta2', '...setDevMode.html', '...setProdMode.html') + + >>> tuple(suite3b.get_relative_urls(None)) + ('@@resource?path=sa1', '@@resource?path=sa2', '@@resource?path=...setDevMode.html', '@@resource?path=3b', '@@resource?path=...setProdMode.html', '@@resource?path=3b', '@@resource?path=ta1', '@@resource?path=ta2') + Inheritence of layers --------------------- From reebalazs at codespeak.net Sat Apr 5 12:02:52 2008 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Sat, 5 Apr 2008 12:02:52 +0200 (CEST) Subject: [KSS-checkins] r53380 - in kukit/kss.demo/branch/1.4-kss-test/kss/demo: . tests Message-ID: <20080405100252.D7A7F16ABA0@codespeak.net> Author: reebalazs Date: Sat Apr 5 12:02:49 2008 New Revision: 53380 Added: kukit/kss.demo/branch/1.4-kss-test/kss/demo/selenium_testcases.txt (contents, props changed) Modified: kukit/kss.demo/branch/1.4-kss-test/kss/demo/selenium_suites.txt kukit/kss.demo/branch/1.4-kss-test/kss/demo/tests/test_doc.py Log: And add more tests. Modified: kukit/kss.demo/branch/1.4-kss-test/kss/demo/selenium_suites.txt ============================================================================== --- kukit/kss.demo/branch/1.4-kss-test/kss/demo/selenium_suites.txt (original) +++ kukit/kss.demo/branch/1.4-kss-test/kss/demo/selenium_suites.txt Sat Apr 5 12:02:49 2008 @@ -178,3 +178,42 @@ More testing of the layers can be found in the selenium_layers.txt file. +Filtering of testcases +---------------------- + +Test suites can be given a ``component`` and ``application`` property. They are +both strings. + +``component`` should be the dotted component name of the owner of this test. +For example, ``plone.app.fancylib`` or ``kss.plugins.superplugin``. + +``application`` identified the application that tests for the usage of this +component. For example, ``Plone``. This is usually a bigger category then the +component, as an application consists of many components. + +If the application property is not specified, this means that the test does not +belong to a specific application, so it is either a kss core or a +plugin test. + +Filtering at the moment is only implemented by the ``application`` property. +This means all the tests of an application can be executed together. + + >>> class Plugin6(object): + ... + ... selenium_tests = ( + ... KSSSeleniumTestSuite( + ... tests = KSSSeleniumTestCase('6a'), + ... component = 'kss.plugins.superplugin', + ... ), + ... KSSSeleniumTestSuite( + ... tests = KSSSeleniumTestCase('6b'), + ... component = 'plone.app.fancylib', + ... application = 'Plone', + ... ), + ... ) + +The filtering is done from the resource registry. How the test sequence is +actually constructed from a selection of suites, is demonstrated in the +``selenium_layers.txt`` document. + + Added: kukit/kss.demo/branch/1.4-kss-test/kss/demo/selenium_testcases.txt ============================================================================== --- (empty file) +++ kukit/kss.demo/branch/1.4-kss-test/kss/demo/selenium_testcases.txt Sat Apr 5 12:02:49 2008 @@ -0,0 +1,238 @@ + +=================== +Selenium test cases +=================== + +Selenium test cases in kss.demo are defined by "test collections". +A collection selects a number of tests. This is why they are called collections, +although in reality they are testcases which however can be constructed +from other collections. + +There are two methods that every collection has, and they are executed +during the creation of the test suite. + +Every collection implements an ``get_resolve_urls``. This returns +an iterator that yields a list of relative test urls. If resolved, +they should render a selenium test case in html format. The order +of the resources specifies their execution order. The method +needs to be called with the rendering view as a parameter. + +In addition, they also implement a ``get_testcase_paths`` method. +This, unlike the previous one, returns an iterator to a list of +absolute filenames. The order of these is not important. It must +contain all the filenames that the collection wants to publish +via the ``@@resource?path=...`` view provided by kss.demo. So, +each item in this list corresponds to an item in the ``get_resolve_urls`` +results. + +New collection types can be implemented by classes, as long as they +implement the ``ISeleniumTestCollection`` interface, in the way specified +below. kss.demo supplies the following collection types, that +allow to specify a set of testcases in a flexible way. + + +Creation of testcase collections +-------------------------------- + +The collections use implicit magic (the same one used by the +Zope CA for the ``implements``) to locate the directory of the +python file that instantiates the collection. This allows that +filenames that are used as parameters, will be expanded to their +absolute class automatically. If we create a collection in itself, +we will get an error: + + >>> from kss.demo import KSSSeleniumTestCase + + >>> tests = KSSSeleniumTestCase('my_testcase.html') + Traceback (most recent call last): + ... + TypeError: The suite class can be used only from inside a class definition. + + The correct way is to use it from inside a class definition. This way + the html file will be located relative to this directory: + + >>> from kss.demo import KSSSeleniumTestSuite + + >>> class Plugin(object): + ... + ... selenium_tests = ( + ... KSSSeleniumTestSuite( + ... tests = KSSSeleniumTestCase('my_testcase.html'), + ... ), + ... ) + + +Test cases by filename +---------------------- + +This collection will contain a single test that we specify by filepath. +The path will be applied relatively to the directory where the file +containing the instantiation resides. + + >>> class Suite: + ... tests = KSSSeleniumTestCase('my_testcase.html') + >>> case1 = Suite.tests + +The ``get_relative_url`` will only return a single resource url: + + >>> tuple(case1.get_relative_urls(None)) + ('@@resource?path=...my_testcase.html',) + +Note that we gave ``None`` as a parameter. This should be normally +the view that does the rendering, needed to be passed to each collection. +We will see a case later when this will be important. + +The ``get_testcase_paths`` method also just returns a single absolute +filepath. (In the case of the test they will really not be absolute, +because the locator magic does not work well with doctests.) + + >>> tuple(case1.get_testcase_paths()) + ('...my_testcase.html',) + + +Test cases by directory +----------------------- + +This is the usual way of working with tests. We specify a directory, +and every ``*.html`` file in that directory is picked into the testcase +collection. + + >>> from kss.demo import KSSSeleniumTestDirectory + + >>> class Suite2: + ... tests = KSSSeleniumTestDirectory('selenium_tests') + >>> case2 = Suite2.tests + + We don't have this directory here. So in both cases we get an error. + + >>> tuple(case2.get_relative_urls(None)) + Traceback (most recent call last): + ... + OSError: [Errno 2] No such file or directory: 'selenium_tests' + + >>> tuple(case2.get_testcase_paths()) + Traceback (most recent call last): + ... + OSError: [Errno 2] No such file or directory: 'selenium_tests' + + For the sake of the test, we will find a testcase directory + from kss.core. Note this would not be needed from real code, + you'd just need to use the directory name. + + >>> import sys, os.path, kss.core.plugins.core.demo + >>> rootdir = os.path.dirname(sys.modules['kss.core.plugins.core.demo'].__file__) + >>> dirpath = os.path.join(rootdir, 'selenium_tests') + + >>> class Suite2: + ... tests = KSSSeleniumTestDirectory(dirpath) + >>> case2 = Suite2.tests + + There are many tests in this list. (These are the tests for the kss core plugin.) + + >>> tuple(case2.get_relative_urls(None)) + ('@@resource?path=...0_ecmaunit_tests.html', ...) + + >>> tuple(case2.get_testcase_paths()) + ('...0_ecmaunit_tests.html', ...) + + +Empty test cases +---------------- + +These are used for default values. + + >>> from kss.demo import KSSSeleniumEmptyTestCase + + >>> class Suite3: + ... tests = KSSSeleniumEmptyTestCase() + >>> case3 = Suite3.tests + + >>> tuple(case3.get_relative_urls(None)) + () + + >>> tuple(case3.get_testcase_paths()) + () + + +Test case lists +--------------- + +These can be used to compose collections from other collections. + + >>> from kss.demo import KSSSeleniumTestCaseList + + >>> class Suite4: + ... tests = KSSSeleniumTestCaseList( + ... KSSSeleniumTestCase('testcase1.html'), + ... KSSSeleniumTestCase('testcase2.html'), + ... ) + >>> case4 = Suite4.tests + + >>> tuple(case4.get_relative_urls(None)) + ('@@resource?path=...testcase1.html', '@@resource?path=...testcase2.html') + + >>> tuple(case4.get_testcase_paths()) + ('...testcase1.html', '...testcase2.html') + +Of course, they can also resurse. + + >>> class Suite5: + ... tests = KSSSeleniumTestCaseList( + ... KSSSeleniumTestCase('testcase1.html'), + ... KSSSeleniumTestCaseList( + ... KSSSeleniumTestCase('testcase2.html'), + ... KSSSeleniumTestCase('testcase3.html'), + ... ), + ... ) + >>> case5 = Suite5.tests + + >>> tuple(case5.get_relative_urls(None)) + ('@@resource?path=...testcase1.html', '@@resource?path=...testcase2.html', '@@resource?path=...testcase3.html') + + >>> tuple(case5.get_testcase_paths()) + ('...testcase1.html', '...testcase2.html', '...testcase3.html') + + +Support for sandbox creation +---------------------------- + +A more special testcase is used to create a sandbox (a site with some content, or +some initial data that each tests need). This test suite +will be rendered by the browser view and take parameters. These are used as +credentials for the content creation (as normal login to Zope could not be used +from the setup), and to specify the url of the view that will carry out the +creation. + +For this test, we will need a real (although fake) view. + + >>> class FakeRequest(object): + ... admin_username = 'admin' + ... admin_password = 'admin' + ... def get(self, key, default=None): + ... return getattr(self, key, default) + >>> class FakeView(object): + ... content = None + ... request = FakeRequest() + >>> fake_view = FakeView() + + >>> from kss.demo import KSSSeleniumSandboxCreationTestCase + + >>> class Suite6: + ... tests = KSSSeleniumSandboxCreationTestCase('@@kss_create_my_sandbox') + >>> case6 = Suite6.tests + + >>> tuple(case6.get_relative_urls(fake_view)) + ('@@kss-selenium-create-sandbox-test.html?method_name=@@kss_create_my_sandbox&admin_username=admin&admin_password=admin',) + +This view will generate a testcase which is an informational form with a button. If +this button is pressed, the view specified with ``method_name`` will be executed. +This will receive the credentials, and it will check them against the Zope +authentication information, before acting as Administrator. + +The collection does not return paths, since it does not use the ```@@resource?path=...``` +view. + + >>> tuple(case6.get_testcase_paths()) + () + + Modified: kukit/kss.demo/branch/1.4-kss-test/kss/demo/tests/test_doc.py ============================================================================== --- kukit/kss.demo/branch/1.4-kss-test/kss/demo/tests/test_doc.py (original) +++ kukit/kss.demo/branch/1.4-kss-test/kss/demo/tests/test_doc.py Sat Apr 5 12:02:49 2008 @@ -21,6 +21,10 @@ def test_suite(): return unittest.TestSuite(( + DocFileSuite('selenium_testcases.txt', + package = 'kss.demo', + optionflags = doctest.ELLIPSIS, + ), DocFileSuite('selenium_layers.txt', package = 'kss.demo', optionflags = doctest.ELLIPSIS, From reebalazs at codespeak.net Sun Apr 6 11:00:02 2008 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Sun, 6 Apr 2008 11:00:02 +0200 (CEST) Subject: [KSS-checkins] r53419 - kukit/kss.demo/branch/1.4-kss-test/kss/demo Message-ID: <20080406090002.45BCE16A6B4@codespeak.net> Author: reebalazs Date: Sun Apr 6 11:00:00 2008 New Revision: 53419 Modified: kukit/kss.demo/branch/1.4-kss-test/kss/demo/selenium_testcases.txt Log: Fix a typo. Modified: kukit/kss.demo/branch/1.4-kss-test/kss/demo/selenium_testcases.txt ============================================================================== --- kukit/kss.demo/branch/1.4-kss-test/kss/demo/selenium_testcases.txt (original) +++ kukit/kss.demo/branch/1.4-kss-test/kss/demo/selenium_testcases.txt Sun Apr 6 11:00:00 2008 @@ -174,7 +174,7 @@ >>> tuple(case4.get_testcase_paths()) ('...testcase1.html', '...testcase2.html') -Of course, they can also resurse. +Of course, they can also recurse. >>> class Suite5: ... tests = KSSSeleniumTestCaseList( From reebalazs at codespeak.net Sun Apr 6 11:00:49 2008 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Sun, 6 Apr 2008 11:00:49 +0200 (CEST) Subject: [KSS-checkins] r53420 - kukit/kss.demo/branch/1.4-kss-test/kss/demo Message-ID: <20080406090049.96CEA16A6B4@codespeak.net> Author: reebalazs Date: Sun Apr 6 11:00:48 2008 New Revision: 53420 Modified: kukit/kss.demo/branch/1.4-kss-test/kss/demo/selenium_testcases.txt Log: Fix some grammar. Modified: kukit/kss.demo/branch/1.4-kss-test/kss/demo/selenium_testcases.txt ============================================================================== --- kukit/kss.demo/branch/1.4-kss-test/kss/demo/selenium_testcases.txt (original) +++ kukit/kss.demo/branch/1.4-kss-test/kss/demo/selenium_testcases.txt Sun Apr 6 11:00:48 2008 @@ -197,7 +197,7 @@ ---------------------------- A more special testcase is used to create a sandbox (a site with some content, or -some initial data that each tests need). This test suite +some initial data that each test needs). This test suite will be rendered by the browser view and take parameters. These are used as credentials for the content creation (as normal login to Zope could not be used from the setup), and to specify the url of the view that will carry out the From reebalazs at codespeak.net Sun Apr 6 11:07:42 2008 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Sun, 6 Apr 2008 11:07:42 +0200 (CEST) Subject: [KSS-checkins] r53421 - kukit/kss.demo/branch/1.4-kss-test/kss/demo Message-ID: <20080406090742.6758416A6C3@codespeak.net> Author: reebalazs Date: Sun Apr 6 11:07:41 2008 New Revision: 53421 Modified: kukit/kss.demo/branch/1.4-kss-test/kss/demo/selenium_layers.txt kukit/kss.demo/branch/1.4-kss-test/kss/demo/selenium_suites.txt kukit/kss.demo/branch/1.4-kss-test/kss/demo/selenium_testcases.txt Log: Reformat paragraphs Modified: kukit/kss.demo/branch/1.4-kss-test/kss/demo/selenium_layers.txt ============================================================================== --- kukit/kss.demo/branch/1.4-kss-test/kss/demo/selenium_layers.txt (original) +++ kukit/kss.demo/branch/1.4-kss-test/kss/demo/selenium_layers.txt Sun Apr 6 11:07:41 2008 @@ -117,10 +117,10 @@ ... TypeError: The suite class can be used only from inside a class definition. -As the error message says, we must define the class from inside another -class. This is used to locate files relatively from the module where the -definition is. So we have to define them from a dummy plugin (however the plugin -itself play no role in testing). +As the error message says, we must define the class from inside +another class. This is used to locate files relatively from the +module where the definition is. So we have to define them from a +dummy plugin (however the plugin itself play no role in testing). >>> class DummyPlugin(object): ... @@ -130,8 +130,8 @@ ... ) >>> aSuite = DummyPlugin.aSuite -The layers whose tests are active, will build a tree to compute the -optimal setup-teardown order. +The layers whose tests are active, will build a tree to compute +the optimal setup-teardown order. >>> from kss.demo.selenium_layer import LayerTree @@ -139,10 +139,11 @@ >>> tuple(tree.get_relative_urls(None)) ('@@resource?path=1', '@@resource?path=...setDevMode.html', '@@resource?path=ta', '@@resource?path=...setProdMode.html', '@@resource?path=ta', '@@resource?path=2') -As we can see in the above results, the tests are generated properly with setup and teardown. +As we can see in the above results, the tests are generated +properly with setup and teardown. -If more cases use the same layer, they are grouped. They also just need to change -the production mode twice: +If more cases use the same layer, they are grouped. They also +just need to change the production mode twice: >>> class DummyPlugin2(object): ... @@ -190,31 +191,33 @@ >>> d2Suite = DummyPlugin3.d2Suite >>> eSuite = DummyPlugin3.eSuite -And see what happens if only suite "d" is selected. We can see that the setup and teardown sequence is correct. +And see what happens if only suite "d" is selected. We can see +that the setup and teardown sequence is correct. >>> tree = LayerTree((dSuite, )) >>> tuple(tree.get_relative_urls(None)) ('@@resource?path=1', '@@resource?path=7', '@@resource?path=9', '@@resource?path=...setDevMode.html', '@@resource?path=td', '@@resource?path=...setProdMode.html', '@@resource?path=td', '@@resource?path=10', '@@resource?path=8', '@@resource?path=2') -Replay this with a bunch of other tests added. Setup and teardown is executed ideally. -In this case we have more dev / prod mode changes, since these are the fastest -they are wrapped inside the layer. +Replay this with a bunch of other tests added. Setup and teardown +is executed ideally. In this case we have more dev / prod mode +changes, since these are the fastest they are wrapped inside the +layer. >>> tree = LayerTree((cSuite, dSuite, d2Suite)) >>> tuple(tree.get_relative_urls(None)) ('@@resource?path=1', '@@resource?path=7', '@@resource?path=...setDevMode.html', '@@resource?path=tc', '@@resource?path=...setProdMode.html', '@@resource?path=tc', '@@resource?path=9', '@@resource?path=...setDevMode.html', '@@resource?path=td', '@@resource?path=td2', '@@resource?path=...setProdMode.html', '@@resource?path=td', '@@resource?path=td2', '@@resource?path=10', '@@resource?path=8', '@@resource?path=2') -So far we have only tried single path setups. Let's now try a split route. -The setup and teardown work correctly in one level. +So far we have only tried single path setups. Let's now try a +split route. The setup and teardown work correctly in one level. >>> tree = LayerTree((aSuite, bSuite, cSuite)) >>> tuple(tree.get_relative_urls(None)) ('@@resource?path=1', '@@resource?path=...setDevMode.html', '@@resource?path=ta', '@@resource?path=...setProdMode.html', '@@resource?path=ta', '@@resource?path=5', '@@resource?path=...setDevMode.html', '@@resource?path=tb', '@@resource?path=...setProdMode.html', '@@resource?path=tb', '@@resource?path=6', '@@resource?path=7', '@@resource?path=...setDevMode.html', '@@resource?path=tc', '@@resource?path=...setProdMode.html', '@@resource?path=tc', '@@resource?path=8', '@@resource?path=2') -Another functionality is that certain tests may mark that they don't want -to be in dual mode: +Another functionality is that certain tests may mark that they +don't want to be in dual mode: >>> class DummyPlugin4(object): ... @@ -229,8 +232,9 @@ >>> tuple(tree.get_relative_urls(None)) ('@@resource?path=1', '@@resource?path=5', '@@resource?path=tb2', '@@resource?path=6', '@@resource?path=2') -This is also true if both dual and single mode tests are in the same layer. In this case -the tests will wun in the end, which in practice means Production mode. +This is also true if both dual and single mode tests are in the +same layer. In this case the tests will wun in the end, which in +practice means Production mode. >>> tree = LayerTree((bSuite, b2Suite)) >>> tuple(tree.get_relative_urls(None)) @@ -243,8 +247,9 @@ ('@@resource?path=1', '@@resource?path=...setDevMode.html', '@@resource?path=ta', '@@resource?path=ta2', '@@resource?path=...setProdMode.html', '@@resource?path=ta', '@@resource?path=ta2', '@@resource?path=5', '@@resource?path=...setDevMode.html', '@@resource?path=tb', '@@resource?path=...setProdMode.html', '@@resource?path=tb', '@@resource?path=tb2', '@@resource?path=6', '@@resource?path=7', '@@resource?path=...setDevMode.html', '@@resource?path=tc', '@@resource?path=...setProdMode.html', '@@resource?path=tc', '@@resource?path=9', '@@resource?path=...setDevMode.html', '@@resource?path=td', '@@resource?path=td2', '@@resource?path=...setProdMode.html', '@@resource?path=td', '@@resource?path=td2', '@@resource?path=10', '@@resource?path=11', '@@resource?path=...setDevMode.html', '@@resource?path=te', '@@resource?path=...setProdMode.html', '@@resource?path=te', '@@resource?path=12', '@@resource?path=8', '@@resource?path=2') -Finally, we still need to check the following: -Suites that are empty are skipped, and no setup teardown or devel / prod mode is generated for them. +Finally, we still need to check the following: Suites that are +empty are skipped, and no setup teardown or devel / prod mode is +generated for them. >>> class DummyPlugin5(object): ... Modified: kukit/kss.demo/branch/1.4-kss-test/kss/demo/selenium_suites.txt ============================================================================== --- kukit/kss.demo/branch/1.4-kss-test/kss/demo/selenium_suites.txt (original) +++ kukit/kss.demo/branch/1.4-kss-test/kss/demo/selenium_suites.txt Sun Apr 6 11:07:41 2008 @@ -3,7 +3,8 @@ Selenium test suites ==================== -Selenium test suites can be set up from plugin resource definitions. +Selenium test suites can be set up from plugin resource +definitions. >>> from kss.demo import ( ... KSSSeleniumTestSuite, @@ -20,17 +21,18 @@ >>> suite1 = Plugin.selenium_tests[0] A suite is like a testcase collection, so it provides its allowed -resource filenames. These are used to secure the resource handling -(to select which files can be served from the filesystem). +resource filenames. These are used to secure the resource +handling (to select which files can be served from the +filesystem). >>> tuple(suite1.get_testcase_paths()) ('1', '...setDevMode.html', '...setProdMode.html') -(Normally we would see an absolute path in place of '1', but the module -finder does not work from within doctests.) +(Normally we would see an absolute path in place of '1', but the +module finder does not work from within doctests.) -And the list of test urls as well. (We use in place of the view which -is not important in this case.) +And the list of test urls as well. (We use in place of the view +which is not important in this case.) >>> tuple(suite1.get_relative_urls(None)) ('@@resource?path=...setDevMode.html', '@@resource?path=1', '@@resource?path=...setProdMode.html', '@@resource?path=1') @@ -39,9 +41,10 @@ Dual and single mode -------------------- -The `suite1` suite also executes the tests twice, both in development and production mode. -If we want single mode for a given suite, we can set it with setting the `dual_mode` -parameter of the suite to False. +The `suite1` suite also executes the tests twice, both in +development and production mode. If we want single mode for a +given suite, we can set it with setting the `dual_mode` parameter +of the suite to False. >>> class Plugin2(object): ... @@ -60,7 +63,8 @@ Using test layers ----------------- -We can define a layer to the suite, with its own setup and teardown. +We can define a layer to the suite, with its own setup and +teardown. >>> from kss.demo import KSSSeleniumTestLayerBase @@ -88,9 +92,10 @@ >>> tuple(suite3.get_relative_urls(None)) ('@@resource?path=sa', '@@resource?path=...setDevMode.html', '@@resource?path=3', '@@resource?path=...setProdMode.html', '@@resource?path=3', '@@resource?path=ta') -To use more tests in the setup of a layer, no extra effort is needed -since the testcase resource already provide KSSSeleniumTestCaseList -to construct collection from other testcases. +To use more tests in the setup of a layer, no extra effort is +needed since the testcase resource already provide +KSSSeleniumTestCaseList to construct collection from other +testcases. >>> from kss.demo import KSSSeleniumTestCaseList @@ -153,9 +158,11 @@ Generating tests for a set of resources --------------------------------------- -Normally, the tests are not collected from suites individually, but a tree is built from a set -of suites providing an optimal setup and teardown sequence. This is done by the demo utility itself. -The list of suites is originating from various different plugins. +Normally, the tests are not collected from suites individually, +but a tree is built from a set of suites providing an optimal +setup and teardown sequence. This is done by the demo utility +itself. The list of suites is originating from various different +plugins. >>> class Plugin5(object): ... @@ -175,28 +182,32 @@ >>> tuple(tree.get_relative_urls(None)) ('@@resource?path=2', '@@resource?path=sa', '@@resource?path=...setDevMode.html', '@@resource?path=5a', '@@resource?path=...setProdMode.html', '@@resource?path=5a', '@@resource?path=sb', '@@resource?path=...setDevMode.html', '@@resource?path=5b', '@@resource?path=...setProdMode.html', '@@resource?path=5b', '@@resource?path=tb', '@@resource?path=ta') -More testing of the layers can be found in the selenium_layers.txt file. +More testing of the layers can be found in the +selenium_layers.txt file. Filtering of testcases ---------------------- -Test suites can be given a ``component`` and ``application`` property. They are -both strings. +Test suites can be given a ``component`` and ``application`` +property. They are both strings. -``component`` should be the dotted component name of the owner of this test. -For example, ``plone.app.fancylib`` or ``kss.plugins.superplugin``. - -``application`` identified the application that tests for the usage of this -component. For example, ``Plone``. This is usually a bigger category then the -component, as an application consists of many components. - -If the application property is not specified, this means that the test does not -belong to a specific application, so it is either a kss core or a -plugin test. - -Filtering at the moment is only implemented by the ``application`` property. -This means all the tests of an application can be executed together. +``component`` should be the dotted component name of the owner of +this test. For example, ``plone.app.fancylib`` or +``kss.plugins.superplugin``. + +``application`` identified the application that tests for the +usage of this component. For example, ``Plone``. This is usually +a bigger category then the component, as an application consists +of many components. + +If the application property is not specified, this means that the +test does not belong to a specific application, so it is either a +kss core or a plugin test. + +Filtering at the moment is only implemented by the +``application`` property. This means all the tests of an +application can be executed together. >>> class Plugin6(object): ... @@ -212,8 +223,8 @@ ... ), ... ) -The filtering is done from the resource registry. How the test sequence is -actually constructed from a selection of suites, is demonstrated in the -``selenium_layers.txt`` document. +The filtering is done from the resource registry. How the test +sequence is actually constructed from a selection of suites, is +demonstrated in the ``selenium_layers.txt`` document. Modified: kukit/kss.demo/branch/1.4-kss-test/kss/demo/selenium_testcases.txt ============================================================================== --- kukit/kss.demo/branch/1.4-kss-test/kss/demo/selenium_testcases.txt (original) +++ kukit/kss.demo/branch/1.4-kss-test/kss/demo/selenium_testcases.txt Sun Apr 6 11:07:41 2008 @@ -3,43 +3,45 @@ Selenium test cases =================== -Selenium test cases in kss.demo are defined by "test collections". -A collection selects a number of tests. This is why they are called collections, -although in reality they are testcases which however can be constructed -from other collections. +Selenium test cases in kss.demo are defined by "test +collections". A collection selects a number of tests. This is +why they are called collections, although in reality they are +testcases which however can be constructed from other +collections. -There are two methods that every collection has, and they are executed -during the creation of the test suite. +There are two methods that every collection has, and they are +executed during the creation of the test suite. Every collection implements an ``get_resolve_urls``. This returns -an iterator that yields a list of relative test urls. If resolved, -they should render a selenium test case in html format. The order -of the resources specifies their execution order. The method -needs to be called with the rendering view as a parameter. +an iterator that yields a list of relative test urls. If +resolved, they should render a selenium test case in html format. +The order of the resources specifies their execution order. The +method needs to be called with the rendering view as a parameter. In addition, they also implement a ``get_testcase_paths`` method. This, unlike the previous one, returns an iterator to a list of absolute filenames. The order of these is not important. It must contain all the filenames that the collection wants to publish via the ``@@resource?path=...`` view provided by kss.demo. So, -each item in this list corresponds to an item in the ``get_resolve_urls`` -results. +each item in this list corresponds to an item in the +``get_resolve_urls`` results. -New collection types can be implemented by classes, as long as they -implement the ``ISeleniumTestCollection`` interface, in the way specified -below. kss.demo supplies the following collection types, that -allow to specify a set of testcases in a flexible way. +New collection types can be implemented by classes, as long as +they implement the ``ISeleniumTestCollection`` interface, in the +way specified below. kss.demo supplies the following collection +types, that allow to specify a set of testcases in a flexible +way. Creation of testcase collections -------------------------------- -The collections use implicit magic (the same one used by the -Zope CA for the ``implements``) to locate the directory of the -python file that instantiates the collection. This allows that -filenames that are used as parameters, will be expanded to their -absolute class automatically. If we create a collection in itself, -we will get an error: +The collections use implicit magic (the same one used by the Zope +CA for the ``implements``) to locate the directory of the python +file that instantiates the collection. This allows that filenames +that are used as parameters, will be expanded to their absolute +class automatically. If we create a collection in itself, we will +get an error: >>> from kss.demo import KSSSeleniumTestCase @@ -48,8 +50,8 @@ ... TypeError: The suite class can be used only from inside a class definition. - The correct way is to use it from inside a class definition. This way - the html file will be located relative to this directory: +The correct way is to use it from inside a class definition. This +way the html file will be located relative to this directory: >>> from kss.demo import KSSSeleniumTestSuite @@ -65,9 +67,9 @@ Test cases by filename ---------------------- -This collection will contain a single test that we specify by filepath. -The path will be applied relatively to the directory where the file -containing the instantiation resides. +This collection will contain a single test that we specify by +filepath. The path will be applied relatively to the directory +where the file containing the instantiation resides. >>> class Suite: ... tests = KSSSeleniumTestCase('my_testcase.html') @@ -78,13 +80,15 @@ >>> tuple(case1.get_relative_urls(None)) ('@@resource?path=...my_testcase.html',) -Note that we gave ``None`` as a parameter. This should be normally -the view that does the rendering, needed to be passed to each collection. -We will see a case later when this will be important. - -The ``get_testcase_paths`` method also just returns a single absolute -filepath. (In the case of the test they will really not be absolute, -because the locator magic does not work well with doctests.) +Note that we gave ``None`` as a parameter. This should be +normally the view that does the rendering, needed to be passed to +each collection. We will see a case later when this will be +important. + +The ``get_testcase_paths`` method also just returns a single +absolute filepath. (In the case of the test they will really not +be absolute, because the locator magic does not work well with +doctests.) >>> tuple(case1.get_testcase_paths()) ('...my_testcase.html',) @@ -93,9 +97,9 @@ Test cases by directory ----------------------- -This is the usual way of working with tests. We specify a directory, -and every ``*.html`` file in that directory is picked into the testcase -collection. +This is the usual way of working with tests. We specify a +directory, and every ``*.html`` file in that directory is picked +into the testcase collection. >>> from kss.demo import KSSSeleniumTestDirectory @@ -103,7 +107,8 @@ ... tests = KSSSeleniumTestDirectory('selenium_tests') >>> case2 = Suite2.tests - We don't have this directory here. So in both cases we get an error. +We don't have this directory here. So in both cases we get an +error. >>> tuple(case2.get_relative_urls(None)) Traceback (most recent call last): @@ -115,9 +120,9 @@ ... OSError: [Errno 2] No such file or directory: 'selenium_tests' - For the sake of the test, we will find a testcase directory - from kss.core. Note this would not be needed from real code, - you'd just need to use the directory name. +For the sake of the test, we will find a testcase directory from +kss.core. Note this would not be needed from real code, you'd +just need to use the directory name. >>> import sys, os.path, kss.core.plugins.core.demo >>> rootdir = os.path.dirname(sys.modules['kss.core.plugins.core.demo'].__file__) @@ -127,7 +132,8 @@ ... tests = KSSSeleniumTestDirectory(dirpath) >>> case2 = Suite2.tests - There are many tests in this list. (These are the tests for the kss core plugin.) +There are many tests in this list. (These are the tests for the +kss core plugin.) >>> tuple(case2.get_relative_urls(None)) ('@@resource?path=...0_ecmaunit_tests.html', ...) @@ -196,12 +202,13 @@ Support for sandbox creation ---------------------------- -A more special testcase is used to create a sandbox (a site with some content, or -some initial data that each test needs). This test suite -will be rendered by the browser view and take parameters. These are used as -credentials for the content creation (as normal login to Zope could not be used -from the setup), and to specify the url of the view that will carry out the -creation. +A more special testcase is used to create a sandbox (a site with +some content, or some initial data that each test needs). This +test suite will be rendered by the browser view and take +parameters. These are used as credentials for the content +creation (as normal login to Zope could not be used from the +setup), and to specify the url of the view that will carry out +the creation. For this test, we will need a real (although fake) view. @@ -224,13 +231,14 @@ >>> tuple(case6.get_relative_urls(fake_view)) ('@@kss-selenium-create-sandbox-test.html?method_name=@@kss_create_my_sandbox&admin_username=admin&admin_password=admin',) -This view will generate a testcase which is an informational form with a button. If -this button is pressed, the view specified with ``method_name`` will be executed. -This will receive the credentials, and it will check them against the Zope +This view will generate a testcase which is an informational form +with a button. If this button is pressed, the view specified with +``method_name`` will be executed. This will receive the +credentials, and it will check them against the Zope authentication information, before acting as Administrator. -The collection does not return paths, since it does not use the ```@@resource?path=...``` -view. +The collection does not return paths, since it does not use the +``@@resource?path=...`` view. >>> tuple(case6.get_testcase_paths()) () From reebalazs at codespeak.net Sun Apr 6 11:19:30 2008 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Sun, 6 Apr 2008 11:19:30 +0200 (CEST) Subject: [KSS-checkins] r53422 - kukit/kss.demo/branch/1.4-kss-test/kss/demo Message-ID: <20080406091930.C652C16A710@codespeak.net> Author: reebalazs Date: Sun Apr 6 11:19:28 2008 New Revision: 53422 Modified: kukit/kss.demo/branch/1.4-kss-test/kss/demo/selenium_layers.txt kukit/kss.demo/branch/1.4-kss-test/kss/demo/selenium_suites.txt kukit/kss.demo/branch/1.4-kss-test/kss/demo/selenium_testcases.txt Log: Minor changes in tests Modified: kukit/kss.demo/branch/1.4-kss-test/kss/demo/selenium_layers.txt ============================================================================== --- kukit/kss.demo/branch/1.4-kss-test/kss/demo/selenium_layers.txt (original) +++ kukit/kss.demo/branch/1.4-kss-test/kss/demo/selenium_layers.txt Sun Apr 6 11:19:28 2008 @@ -233,7 +233,7 @@ ('@@resource?path=1', '@@resource?path=5', '@@resource?path=tb2', '@@resource?path=6', '@@resource?path=2') This is also true if both dual and single mode tests are in the -same layer. In this case the tests will wun in the end, which in +same layer. In this case the tests will run in the end, which in practice means Production mode. >>> tree = LayerTree((bSuite, b2Suite)) Modified: kukit/kss.demo/branch/1.4-kss-test/kss/demo/selenium_suites.txt ============================================================================== --- kukit/kss.demo/branch/1.4-kss-test/kss/demo/selenium_suites.txt (original) +++ kukit/kss.demo/branch/1.4-kss-test/kss/demo/selenium_suites.txt Sun Apr 6 11:19:28 2008 @@ -26,7 +26,7 @@ filesystem). >>> tuple(suite1.get_testcase_paths()) - ('1', '...setDevMode.html', '...setProdMode.html') + ('...1', '...setDevMode.html', '...setProdMode.html') (Normally we would see an absolute path in place of '1', but the module finder does not work from within doctests.) @@ -35,7 +35,7 @@ which is not important in this case.) >>> tuple(suite1.get_relative_urls(None)) - ('@@resource?path=...setDevMode.html', '@@resource?path=1', '@@resource?path=...setProdMode.html', '@@resource?path=1') + ('@@resource?path=...setDevMode.html', '@@resource?path=...1', '@@resource?path=...setProdMode.html', '@@resource?path=1') Dual and single mode @@ -57,7 +57,7 @@ >>> suite2 = Plugin2.selenium_tests[0] >>> tuple(suite2.get_relative_urls(None)) - ('@@resource?path=2',) + ('@@resource?path=...2',) Using test layers @@ -87,10 +87,10 @@ Check the results: >>> tuple(suite3.get_testcase_paths()) - ('3', 'sa', 'ta', '...setDevMode.html', '...setProdMode.html') + ('...3', '...sa', '...ta', '...setDevMode.html', '...setProdMode.html') >>> tuple(suite3.get_relative_urls(None)) - ('@@resource?path=sa', '@@resource?path=...setDevMode.html', '@@resource?path=3', '@@resource?path=...setProdMode.html', '@@resource?path=3', '@@resource?path=ta') + ('@@resource?path=...sa', '@@resource?path=...setDevMode.html', '@@resource?path=...3', '@@resource?path=...setProdMode.html', '@@resource?path=...3', '@@resource?path=...ta') To use more tests in the setup of a layer, no extra effort is needed since the testcase resource already provide @@ -123,10 +123,10 @@ Check the results: >>> tuple(suite3b.get_testcase_paths()) - ('3b', 'sa1', 'sa2', 'ta1', 'ta2', '...setDevMode.html', '...setProdMode.html') + ('...3b', '...sa1', '...sa2', '...ta1', '...ta2', '...setDevMode.html', '...setProdMode.html') >>> tuple(suite3b.get_relative_urls(None)) - ('@@resource?path=sa1', '@@resource?path=sa2', '@@resource?path=...setDevMode.html', '@@resource?path=3b', '@@resource?path=...setProdMode.html', '@@resource?path=3b', '@@resource?path=ta1', '@@resource?path=ta2') + ('@@resource?path=...sa1', '@@resource?path=...sa2', '@@resource?path=...setDevMode.html', '@@resource?path=...3b', '@@resource?path=...setProdMode.html', '@@resource?path=...3b', '@@resource?path=...ta1', '@@resource?path=...ta2') Inheritence of layers @@ -149,10 +149,10 @@ >>> suite4 = Plugin4.selenium_tests[0] >>> tuple(suite4.get_testcase_paths()) - ('4', 'sb', 'tb', '...setDevMode.html', '...setProdMode.html') + ('...4', '...sb', '...tb', '...setDevMode.html', '...setProdMode.html') >>> tuple(suite4.get_relative_urls(None)) - ('@@resource?path=sa', '@@resource?path=sb', '@@resource?path=...setDevMode.html', '@@resource?path=4', '@@resource?path=...setProdMode.html', '@@resource?path=4', '@@resource?path=tb', '@@resource?path=ta') + ('@@resource?path=...sa', '@@resource?path=...sb', '@@resource?path=...setDevMode.html', '@@resource?path=...4', '@@resource?path=...setProdMode.html', '@@resource?path=...4', '@@resource?path=...tb', '@@resource?path=...ta') Generating tests for a set of resources @@ -180,7 +180,7 @@ >>> from kss.demo.selenium_layer import LayerTree >>> tree = LayerTree(Plugin5.selenium_tests + (suite2, )) >>> tuple(tree.get_relative_urls(None)) - ('@@resource?path=2', '@@resource?path=sa', '@@resource?path=...setDevMode.html', '@@resource?path=5a', '@@resource?path=...setProdMode.html', '@@resource?path=5a', '@@resource?path=sb', '@@resource?path=...setDevMode.html', '@@resource?path=5b', '@@resource?path=...setProdMode.html', '@@resource?path=5b', '@@resource?path=tb', '@@resource?path=ta') + ('@@resource?path=...2', '@@resource?path=...sa', '@@resource?path=...setDevMode.html', '@@resource?path=...5a', '@@resource?path=...setProdMode.html', '@@resource?path=...5a', '@@resource?path=...sb', '@@resource?path=...setDevMode.html', '@@resource?path=...5b', '@@resource?path=...setProdMode.html', '@@resource?path=...5b', '@@resource?path=...tb', '@@resource?path=...ta') More testing of the layers can be found in the selenium_layers.txt file. Modified: kukit/kss.demo/branch/1.4-kss-test/kss/demo/selenium_testcases.txt ============================================================================== --- kukit/kss.demo/branch/1.4-kss-test/kss/demo/selenium_testcases.txt (original) +++ kukit/kss.demo/branch/1.4-kss-test/kss/demo/selenium_testcases.txt Sun Apr 6 11:19:28 2008 @@ -40,7 +40,7 @@ CA for the ``implements``) to locate the directory of the python file that instantiates the collection. This allows that filenames that are used as parameters, will be expanded to their absolute -class automatically. If we create a collection in itself, we will +path automatically. If we create a collection in itself, we will get an error: >>> from kss.demo import KSSSeleniumTestCase @@ -122,7 +122,7 @@ For the sake of the test, we will find a testcase directory from kss.core. Note this would not be needed from real code, you'd -just need to use the directory name. +just need to use the relative directory name. >>> import sys, os.path, kss.core.plugins.core.demo >>> rootdir = os.path.dirname(sys.modules['kss.core.plugins.core.demo'].__file__) From gotcha at codespeak.net Sun Apr 6 11:44:45 2008 From: gotcha at codespeak.net (gotcha at codespeak.net) Date: Sun, 6 Apr 2008 11:44:45 +0200 (CEST) Subject: [KSS-checkins] r53425 - kukit/kss.buildout/branch/jscoverage Message-ID: <20080406094445.DBF1B16A69E@codespeak.net> Author: gotcha Date: Sun Apr 6 11:44:45 2008 New Revision: 53425 Added: kukit/kss.buildout/branch/jscoverage/ - copied from r53424, kukit/kss.buildout/trunk/ Log: jscoverage support From gotcha at codespeak.net Sun Apr 6 11:45:17 2008 From: gotcha at codespeak.net (gotcha at codespeak.net) Date: Sun, 6 Apr 2008 11:45:17 +0200 (CEST) Subject: [KSS-checkins] r53426 - kukit/kss.core/branch/jscoverage Message-ID: <20080406094517.7BD2216A69E@codespeak.net> Author: gotcha Date: Sun Apr 6 11:45:17 2008 New Revision: 53426 Added: kukit/kss.core/branch/jscoverage/ - copied from r53425, kukit/kss.core/trunk/ Log: jscoverage support From gotcha at codespeak.net Sun Apr 6 11:45:39 2008 From: gotcha at codespeak.net (gotcha at codespeak.net) Date: Sun, 6 Apr 2008 11:45:39 +0200 (CEST) Subject: [KSS-checkins] r53427 - kukit/kss.demo/branch/jscoverage Message-ID: <20080406094539.7457316A69E@codespeak.net> Author: gotcha Date: Sun Apr 6 11:45:39 2008 New Revision: 53427 Added: kukit/kss.demo/branch/jscoverage/ - copied from r53426, kukit/kss.demo/trunk/ Log: jscoverage support From gotcha at codespeak.net Sun Apr 6 11:46:08 2008 From: gotcha at codespeak.net (gotcha at codespeak.net) Date: Sun, 6 Apr 2008 11:46:08 +0200 (CEST) Subject: [KSS-checkins] r53428 - kukit/kukit.js/branch/jscoverage Message-ID: <20080406094608.F357416A69E@codespeak.net> Author: gotcha Date: Sun Apr 6 11:46:08 2008 New Revision: 53428 Added: kukit/kukit.js/branch/jscoverage/ - copied from r53427, kukit/kukit.js/trunk/ Log: jscoverage support From gotcha at codespeak.net Sun Apr 6 13:35:15 2008 From: gotcha at codespeak.net (gotcha at codespeak.net) Date: Sun, 6 Apr 2008 13:35:15 +0200 (CEST) Subject: [KSS-checkins] r53436 - kukit/kss.buildout/branch/jscoverage/src Message-ID: <20080406113515.A8C3D16A69C@codespeak.net> Author: gotcha Date: Sun Apr 6 13:35:12 2008 New Revision: 53436 Modified: kukit/kss.buildout/branch/jscoverage/src/ (props changed) kukit/kss.buildout/branch/jscoverage/src/EXTERNALS.txt Log: jscoverage support Modified: kukit/kss.buildout/branch/jscoverage/src/EXTERNALS.txt ============================================================================== --- kukit/kss.buildout/branch/jscoverage/src/EXTERNALS.txt (original) +++ kukit/kss.buildout/branch/jscoverage/src/EXTERNALS.txt Sun Apr 6 13:35:12 2008 @@ -1,5 +0,0 @@ -# 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 - From gotcha at codespeak.net Sun Apr 6 13:36:33 2008 From: gotcha at codespeak.net (gotcha at codespeak.net) Date: Sun, 6 Apr 2008 13:36:33 +0200 (CEST) Subject: [KSS-checkins] r53437 - in kukit/kss.core/trunk/kss/core: . pluginregistry/browser plugins/core/demo Message-ID: <20080406113633.E068916A69C@codespeak.net> Author: gotcha Date: Sun Apr 6 13:36:32 2008 New Revision: 53437 Modified: kukit/kss.core/trunk/kss/core/ (props changed) kukit/kss.core/trunk/kss/core/EXTERNALS.TXT kukit/kss.core/trunk/kss/core/pluginregistry/browser/develui.pt kukit/kss.core/trunk/kss/core/plugins/core/demo/zopeconfig.py Log: jscoverage support Modified: kukit/kss.core/trunk/kss/core/EXTERNALS.TXT ============================================================================== --- kukit/kss.core/trunk/kss/core/EXTERNALS.TXT (original) +++ kukit/kss.core/trunk/kss/core/EXTERNALS.TXT Sun Apr 6 13:36:32 2008 @@ -1,8 +0,0 @@ -# -# results of svn propget svn:externals -# http://codespeak.net/svn/kukit/kss.core/trunk -# -# You can update your working dir by: -# svn propset svn:externals -F EXTERNALS.TXT . -# -kukit http://codespeak.net/svn/kukit/kukit.js/trunk/ Modified: kukit/kss.core/trunk/kss/core/pluginregistry/browser/develui.pt ============================================================================== --- kukit/kss.core/trunk/kss/core/pluginregistry/browser/develui.pt (original) +++ kukit/kss.core/trunk/kss/core/pluginregistry/browser/develui.pt Sun Apr 6 13:36:32 2008 @@ -106,7 +106,8 @@

Current KSS log level is - DEBUG.

Modified: kukit/kss.core/trunk/kss/core/plugins/core/demo/zopeconfig.py ============================================================================== --- kukit/kss.core/trunk/kss/core/plugins/core/demo/zopeconfig.py (original) +++ kukit/kss.core/trunk/kss/core/plugins/core/demo/zopeconfig.py Sun Apr 6 13:36:32 2008 @@ -18,6 +18,7 @@ implements(IResource) demos = ( + KSSDemo('', '', "loglevel.html", "Log Level"), KSSDemo('', '', "basic_commands.html", "Change tag content"), KSSDemo('', '', "two_selects.html", "Two selects"), KSSDemo('', '', "autoupdate.html", "Auto update"), From gotcha at codespeak.net Sun Apr 6 14:10:43 2008 From: gotcha at codespeak.net (gotcha at codespeak.net) Date: Sun, 6 Apr 2008 14:10:43 +0200 (CEST) Subject: [KSS-checkins] r53439 - kukit/kss.core/trunk/kss/core Message-ID: <20080406121043.20EB116A70A@codespeak.net> Author: gotcha Date: Sun Apr 6 14:10:42 2008 New Revision: 53439 Modified: kukit/kss.core/trunk/kss/core/ (props changed) kukit/kss.core/trunk/kss/core/EXTERNALS.TXT Log: fix externals Modified: kukit/kss.core/trunk/kss/core/EXTERNALS.TXT ============================================================================== --- kukit/kss.core/trunk/kss/core/EXTERNALS.TXT (original) +++ kukit/kss.core/trunk/kss/core/EXTERNALS.TXT Sun Apr 6 14:10:42 2008 @@ -0,0 +1,10 @@ +# You can check externals by issuing: +# +# svn propget svn:externals . +# +# You can update your working dir by issuing: +# +# svn propset svn:externals -F EXTERNALS.TXT . +# +kukit http://codespeak.net/svn/kukit/kukit.js/branch/jscoverage/ + From gotcha at codespeak.net Sun Apr 6 14:12:47 2008 From: gotcha at codespeak.net (gotcha at codespeak.net) Date: Sun, 6 Apr 2008 14:12:47 +0200 (CEST) Subject: [KSS-checkins] r53440 - in kukit/kss.buildout/branch/jscoverage: . src Message-ID: <20080406121247.B0FCB16A725@codespeak.net> Author: gotcha Date: Sun Apr 6 14:12:46 2008 New Revision: 53440 Added: kukit/kss.buildout/branch/jscoverage/IGNORE.txt Modified: kukit/kss.buildout/branch/jscoverage/src/ (props changed) kukit/kss.buildout/branch/jscoverage/src/EXTERNALS.txt Log: fix externals and ignore Added: kukit/kss.buildout/branch/jscoverage/IGNORE.txt ============================================================================== --- (empty file) +++ kukit/kss.buildout/branch/jscoverage/IGNORE.txt Sun Apr 6 14:12:46 2008 @@ -0,0 +1,16 @@ +# You can check svn:ignore by issuing: +# +# svn propget svn:ignore . +# +# You can update your working dir by issuing: +# +# svn propset svn:ignore -F IGNORE.txt . +# +develop-eggs +var +parts +downloads +.installed.cfg +tags +bin + Modified: kukit/kss.buildout/branch/jscoverage/src/EXTERNALS.txt ============================================================================== --- kukit/kss.buildout/branch/jscoverage/src/EXTERNALS.txt (original) +++ kukit/kss.buildout/branch/jscoverage/src/EXTERNALS.txt Sun Apr 6 14:12:46 2008 @@ -0,0 +1,11 @@ +# You can check externals by issuing: +# +# svn propget svn:externals . +# +# You can update your working dir by issuing: +# +# svn propset svn:externals -F EXTERNALS.txt . +# +kss.core https://codespeak.net/svn/kukit/kss.core/branch/jscoverage +kss.demo https://codespeak.net/svn/kukit/kss.demo/branch/jscoverage + From gotcha at codespeak.net Sun Apr 6 14:14:19 2008 From: gotcha at codespeak.net (gotcha at codespeak.net) Date: Sun, 6 Apr 2008 14:14:19 +0200 (CEST) Subject: [KSS-checkins] r53441 - kukit/kss.buildout/branch/jscoverage Message-ID: <20080406121419.654F416A70A@codespeak.net> Author: gotcha Date: Sun Apr 6 14:14:18 2008 New Revision: 53441 Added: kukit/kss.buildout/branch/jscoverage/mkbranch.sh (contents, props changed) Log: first attempt for a branching script Added: kukit/kss.buildout/branch/jscoverage/mkbranch.sh ============================================================================== --- (empty file) +++ kukit/kss.buildout/branch/jscoverage/mkbranch.sh Sun Apr 6 14:14:18 2008 @@ -0,0 +1,20 @@ +#!/bin/sh +NAME="jscoverage" +LOGMSG="jscoverage support" + +#svn cp http://codespeak.net/svn/kukit/kss.buildout/trunk http://codespeak.net/svn/kukit/kss.buildout/branch/$NAME -m "$LOGMSG" +#svn cp http://codespeak.net/svn/kukit/kss.core/trunk http://codespeak.net/svn/kukit/kss.core/branch/$NAME -m "$LOGMSG" +#svn cp http://codespeak.net/svn/kukit/kss.demo/trunk http://codespeak.net/svn/kukit/kss.demo/branch/$NAME -m "$LOGMSG" +#svn cp http://codespeak.net/svn/kukit/kukit.js/trunk http://codespeak.net/svn/kukit/kukit.js/branch/$NAME -m "$LOGMSG" +#svn sw http://codespeak.net/svn/kukit/kss.buildout/branch/$NAME . +#svn sw https://codespeak.net/svn/kukit/kss.core/branch/$NAME src/kss.core +#svn sw https://codespeak.net/svn/kukit/kss.demo/branch/$NAME src/kss.demo +#svn sw https://codespeak.net/svn/kukit/kukit.js/branch/$NAME src/kss.core/kss/core +EXTERNALS="src/EXTERNALS.txt" +sed "s/trunk/branch\/$NAME/" $EXTERNALS >$EXTERNALS.out +mv $EXTERNALS.out $EXTERNALS +svn propset svn:externals -F $EXTERNALS src +EXTERNALS="src/kss.core/kss/core/EXTERNALS.TXT" +sed "s/trunk/branch\/$NAME/" $EXTERNALS >$EXTERNALS.out +mv $EXTERNALS.out $EXTERNALS +svn propset svn:externals -F $EXTERNALS src/kss.core/kss/core From gotcha at codespeak.net Sun Apr 6 14:31:33 2008 From: gotcha at codespeak.net (gotcha at codespeak.net) Date: Sun, 6 Apr 2008 14:31:33 +0200 (CEST) Subject: [KSS-checkins] r53442 - in kukit/kss.demo/trunk/kss/demo: . browser jscoverage jscoverage/browser Message-ID: <20080406123133.2437616A641@codespeak.net> Author: gotcha Date: Sun Apr 6 14:31:31 2008 New Revision: 53442 Added: kukit/kss.demo/trunk/kss/demo/jscoverage/ (props changed) kukit/kss.demo/trunk/kss/demo/jscoverage/IGNORE.txt kukit/kss.demo/trunk/kss/demo/jscoverage/__init__.py kukit/kss.demo/trunk/kss/demo/jscoverage/browser/ kukit/kss.demo/trunk/kss/demo/jscoverage/browser/__init__.py kukit/kss.demo/trunk/kss/demo/jscoverage/browser/backToIndex.html kukit/kss.demo/trunk/kss/demo/jscoverage/browser/configure.zcml kukit/kss.demo/trunk/kss/demo/jscoverage/browser/coverage.py kukit/kss.demo/trunk/kss/demo/jscoverage/browser/interfaces.py kukit/kss.demo/trunk/kss/demo/jscoverage/browser/kss_demo_suite_jscoverage.pt kukit/kss.demo/trunk/kss/demo/jscoverage/browser/setJscoverage.html kukit/kss.demo/trunk/kss/demo/jscoverage/browser/unsetJscoverage.html kukit/kss.demo/trunk/kss/demo/jscoverage/configure.zcml Modified: kukit/kss.demo/trunk/kss/demo/browser/header_macros.pt kukit/kss.demo/trunk/kss/demo/browser/kss_demo_index.pt kukit/kss.demo/trunk/kss/demo/configure.zcml Log: add jscoverage support Modified: kukit/kss.demo/trunk/kss/demo/browser/header_macros.pt ============================================================================== --- kukit/kss.demo/trunk/kss/demo/browser/header_macros.pt (original) +++ kukit/kss.demo/trunk/kss/demo/browser/header_macros.pt Sun Apr 6 14:31:31 2008 @@ -49,14 +49,23 @@ - + + + - - 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 Sun Apr 6 14:31:31 2008 @@ -1,5 +1,6 @@ + KSS demos and tests @@ -16,6 +17,19 @@ +

Coverage

+
    +
  • Link to Zelenium object (instrumented): +
    + + + +
  • +
  • + Coverage report +
  • +

Zelenium object link must be an absolute path from the domain root, or a relative path from the demo SimpleContent's parent. Modified: kukit/kss.demo/trunk/kss/demo/configure.zcml ============================================================================== --- kukit/kss.demo/trunk/kss/demo/configure.zcml (original) +++ kukit/kss.demo/trunk/kss/demo/configure.zcml Sun Apr 6 14:31:31 2008 @@ -7,7 +7,7 @@ > - + @@ -93,4 +93,6 @@ permission="zope.Public" /> + + Added: kukit/kss.demo/trunk/kss/demo/jscoverage/IGNORE.txt ============================================================================== --- (empty file) +++ kukit/kss.demo/trunk/kss/demo/jscoverage/IGNORE.txt Sun Apr 6 14:31:31 2008 @@ -0,0 +1,10 @@ +# You can check svn:ignore by issuing: +# +# svn propget svn:ignore . +# +# You can update your working dir by issuing: +# +# svn propset svn:ignore -F IGNORE.txt . +# +js + Added: kukit/kss.demo/trunk/kss/demo/jscoverage/__init__.py ============================================================================== --- (empty file) +++ kukit/kss.demo/trunk/kss/demo/jscoverage/__init__.py Sun Apr 6 14:31:31 2008 @@ -0,0 +1 @@ +#package Added: kukit/kss.demo/trunk/kss/demo/jscoverage/browser/__init__.py ============================================================================== --- (empty file) +++ kukit/kss.demo/trunk/kss/demo/jscoverage/browser/__init__.py Sun Apr 6 14:31:31 2008 @@ -0,0 +1 @@ +#package Added: kukit/kss.demo/trunk/kss/demo/jscoverage/browser/backToIndex.html ============================================================================== --- (empty file) +++ kukit/kss.demo/trunk/kss/demo/jscoverage/browser/backToIndex.html Sun Apr 6 14:31:31 2008 @@ -0,0 +1,23 @@ + + + +basic_commands + + +

basic_commands
Set production mode
open
+ + + + + + + + + + + + + +
Back to index
openindex.html
assertTextPresentKSS demos
+ + Added: kukit/kss.demo/trunk/kss/demo/jscoverage/browser/configure.zcml ============================================================================== --- (empty file) +++ kukit/kss.demo/trunk/kss/demo/jscoverage/browser/configure.zcml Sun Apr 6 14:31:31 2008 @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + Added: kukit/kss.demo/trunk/kss/demo/jscoverage/browser/coverage.py ============================================================================== --- (empty file) +++ kukit/kss.demo/trunk/kss/demo/jscoverage/browser/coverage.py Sun Apr 6 14:31:31 2008 @@ -0,0 +1,57 @@ + +try: + from Products.Five import BrowserView + BrowserView +except ImportError: + from zope.publisher.browser import BrowserView + +from zope.publisher.interfaces import NotFound + +COOKIE_JSCMODE = '__kss_jscoverage' + +class JscoverageView(BrowserView): + + # Zope3 requires the implementation of + # IBrowserPublisher, in order for the methods + # to be traversable. + # + # An alternative would be: + # + # + # + # + + def publishTraverse(self, request, name): + try: + return getattr(self, name) + except AttributeError: + raise NotFound(self.context, name, request) + + def browserDefault(self, request): + # make ui the default method + return self, ('isJscoverage', ) + + # -- + # Methods for jscoverage mode + # -- + + def setJscoverage(self): + 'Sets jscoverage mode cookie' + self.request.response.setCookie(COOKIE_JSCMODE, '1', path='/') + return 'jscoverage cookie on' + + def unsetJscoverage(self): + 'Unsets jscoverage mode cookie' + self.request.response.expireCookie(COOKIE_JSCMODE, path='/') + return 'jscoverage cookie off' + + def isJscoverage(self): + 'Queries jscoverage mode cookie' + return bool(COOKIE_JSCMODE in self.request.cookies) + + def getZuite(self, path): + """Redirects to the Zuite page, Zuite object is found from path.""" + zuite = self.context.aq_inner.aq_parent.restrictedTraverse(path) + html = "%s/core/TestRunner.html?test=%s/suite_jscoverage.html" % (zuite.absolute_url(), self.context.absolute_url()) + return self.request.response.redirect(html) + Added: kukit/kss.demo/trunk/kss/demo/jscoverage/browser/interfaces.py ============================================================================== --- (empty file) +++ kukit/kss.demo/trunk/kss/demo/jscoverage/browser/interfaces.py Sun Apr 6 14:31:31 2008 @@ -0,0 +1,14 @@ + +from zope.publisher.interfaces.browser import IBrowserPublisher + +class IJscoverageView(IBrowserPublisher): + + def setJscoverage(): + 'Sets jscoverage mode cookie' + + def unsetJscoverage(): + 'Unsets jscoverage mode cookie' + + def isJscoverage(): + 'Queries jscoverage mode cookie' + Added: kukit/kss.demo/trunk/kss/demo/jscoverage/browser/kss_demo_suite_jscoverage.pt ============================================================================== --- (empty file) +++ kukit/kss.demo/trunk/kss/demo/jscoverage/browser/kss_demo_suite_jscoverage.pt Sun Apr 6 14:31:31 2008 @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + +
Test Suite
+

+ Jscoverage mode +

+
Title
+

+ Development mode +

+
+

+ Back to all demos +

+
+ + Added: kukit/kss.demo/trunk/kss/demo/jscoverage/browser/setJscoverage.html ============================================================================== --- (empty file) +++ kukit/kss.demo/trunk/kss/demo/jscoverage/browser/setJscoverage.html Sun Apr 6 14:31:31 2008 @@ -0,0 +1,23 @@ + + + +basic_commands + + + + + + + + + + + + + + + + +
setJscoverage
opendemo/@@kss_jscoverage/setJscoverage
assertTextPresentjscoverage cookie on
+ + Added: kukit/kss.demo/trunk/kss/demo/jscoverage/browser/unsetJscoverage.html ============================================================================== --- (empty file) +++ kukit/kss.demo/trunk/kss/demo/jscoverage/browser/unsetJscoverage.html Sun Apr 6 14:31:31 2008 @@ -0,0 +1,23 @@ + + + +basic_commands + + + + + + + + + + + + + + + + +
unsetJscoverage
opendemo/@@kss_jscoverage/unsetJscoverage
assertTextPresentjscoverage cookie off
+ + Added: kukit/kss.demo/trunk/kss/demo/jscoverage/configure.zcml ============================================================================== --- (empty file) +++ kukit/kss.demo/trunk/kss/demo/jscoverage/configure.zcml Sun Apr 6 14:31:31 2008 @@ -0,0 +1,52 @@ + + + + + + + + + + + + + From gotcha at codespeak.net Sun Apr 6 14:32:42 2008 From: gotcha at codespeak.net (gotcha at codespeak.net) Date: Sun, 6 Apr 2008 14:32:42 +0200 (CEST) Subject: [KSS-checkins] r53443 - kukit/kss.core/trunk/kss/core Message-ID: <20080406123242.2259516A641@codespeak.net> Author: gotcha Date: Sun Apr 6 14:32:41 2008 New Revision: 53443 Modified: kukit/kss.core/trunk/kss/core/ (props changed) Log: fix externals From gotcha at codespeak.net Sun Apr 6 14:33:55 2008 From: gotcha at codespeak.net (gotcha at codespeak.net) Date: Sun, 6 Apr 2008 14:33:55 +0200 (CEST) Subject: [KSS-checkins] r53444 - kukit/kss.core/trunk/kss/core/plugins/core/demo/selenium_tests Message-ID: <20080406123355.5EDFD16A641@codespeak.net> Author: gotcha Date: Sun Apr 6 14:33:54 2008 New Revision: 53444 Added: kukit/kss.core/trunk/kss/core/plugins/core/demo/selenium_tests/log_level.html Log: add jscoverage support Added: kukit/kss.core/trunk/kss/core/plugins/core/demo/selenium_tests/log_level.html ============================================================================== --- (empty file) +++ kukit/kss.core/trunk/kss/core/plugins/core/demo/selenium_tests/log_level.html Sun Apr 6 14:33:54 2008 @@ -0,0 +1,134 @@ + + + +log_level + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
log_level
openhttp://localhost:8080/demo/basic_commands.html
open/demo/@@kss_devel_mode/ui
clickdocument.loglevel.loglevel[1]
clickAndWaitbutton_loglevel
assertTextloglevelINFO
openhttp://localhost:8080/demo/basic_commands.html
open/demo/@@kss_devel_mode/ui
assertTextloglevelINFO
clickdocument.loglevel.loglevel[2]
clickAndWaitbutton_loglevel
assertTextloglevelWARNING
openhttp://localhost:8080/demo/basic_commands.html
open/demo/@@kss_devel_mode/ui
assertTextloglevelWARNING
clickdocument.loglevel.loglevel[3]
clickAndWaitbutton_loglevel
assertTextloglevelERROR
openhttp://localhost:8080/demo/basic_commands.html
open/demo/@@kss_devel_mode/ui
assertTextloglevelERROR
clickdocument.loglevel.loglevel[0]
clickAndWaitbutton_loglevel
assertTextloglevelDEBUG
openhttp://localhost:8080/demo/basic_commands.html
+ + From gotcha at codespeak.net Sun Apr 6 14:39:52 2008 From: gotcha at codespeak.net (gotcha at codespeak.net) Date: Sun, 6 Apr 2008 14:39:52 +0200 (CEST) Subject: [KSS-checkins] r53446 - kukit/kss.buildout/branch/jscoverage Message-ID: <20080406123952.62EFA16A438@codespeak.net> Author: gotcha Date: Sun Apr 6 14:39:51 2008 New Revision: 53446 Modified: kukit/kss.buildout/branch/jscoverage/ (props changed) kukit/kss.buildout/branch/jscoverage/buildout.cfg kukit/kss.buildout/branch/jscoverage/mkbranch.sh Log: add jscoverage Modified: kukit/kss.buildout/branch/jscoverage/buildout.cfg ============================================================================== --- kukit/kss.buildout/branch/jscoverage/buildout.cfg (original) +++ kukit/kss.buildout/branch/jscoverage/buildout.cfg Sun Apr 6 14:39:51 2008 @@ -4,6 +4,7 @@ instance extraproducts ksspy + coverage develop = src/kss.core @@ -45,3 +46,7 @@ interpreter = ksspy extra-paths = ${zope2:location}/lib/python scripts = ksspy + +[coverage] +recipe = zc.recipe.cmmi +url = http://siliconforks.com/jscoverage/download/jscoverage-0.3.1.tar.bz2 Modified: kukit/kss.buildout/branch/jscoverage/mkbranch.sh ============================================================================== --- kukit/kss.buildout/branch/jscoverage/mkbranch.sh (original) +++ kukit/kss.buildout/branch/jscoverage/mkbranch.sh Sun Apr 6 14:39:51 2008 @@ -1,15 +1,15 @@ #!/bin/sh -NAME="jscoverage" -LOGMSG="jscoverage support" +NAME=$ARGV[1] +LOGMSG=$ARGV[2] -#svn cp http://codespeak.net/svn/kukit/kss.buildout/trunk http://codespeak.net/svn/kukit/kss.buildout/branch/$NAME -m "$LOGMSG" -#svn cp http://codespeak.net/svn/kukit/kss.core/trunk http://codespeak.net/svn/kukit/kss.core/branch/$NAME -m "$LOGMSG" -#svn cp http://codespeak.net/svn/kukit/kss.demo/trunk http://codespeak.net/svn/kukit/kss.demo/branch/$NAME -m "$LOGMSG" -#svn cp http://codespeak.net/svn/kukit/kukit.js/trunk http://codespeak.net/svn/kukit/kukit.js/branch/$NAME -m "$LOGMSG" -#svn sw http://codespeak.net/svn/kukit/kss.buildout/branch/$NAME . -#svn sw https://codespeak.net/svn/kukit/kss.core/branch/$NAME src/kss.core -#svn sw https://codespeak.net/svn/kukit/kss.demo/branch/$NAME src/kss.demo -#svn sw https://codespeak.net/svn/kukit/kukit.js/branch/$NAME src/kss.core/kss/core +svn cp http://codespeak.net/svn/kukit/kss.buildout/trunk http://codespeak.net/svn/kukit/kss.buildout/branch/$NAME -m "$LOGMSG" +svn cp http://codespeak.net/svn/kukit/kss.core/trunk http://codespeak.net/svn/kukit/kss.core/branch/$NAME -m "$LOGMSG" +svn cp http://codespeak.net/svn/kukit/kss.demo/trunk http://codespeak.net/svn/kukit/kss.demo/branch/$NAME -m "$LOGMSG" +svn cp http://codespeak.net/svn/kukit/kukit.js/trunk http://codespeak.net/svn/kukit/kukit.js/branch/$NAME -m "$LOGMSG" +svn sw http://codespeak.net/svn/kukit/kss.buildout/branch/$NAME . +svn sw https://codespeak.net/svn/kukit/kss.core/branch/$NAME src/kss.core +svn sw https://codespeak.net/svn/kukit/kss.demo/branch/$NAME src/kss.demo +svn sw https://codespeak.net/svn/kukit/kukit.js/branch/$NAME src/kss.core/kss/core EXTERNALS="src/EXTERNALS.txt" sed "s/trunk/branch\/$NAME/" $EXTERNALS >$EXTERNALS.out mv $EXTERNALS.out $EXTERNALS From gotcha at codespeak.net Sun Apr 6 14:45:44 2008 From: gotcha at codespeak.net (gotcha at codespeak.net) Date: Sun, 6 Apr 2008 14:45:44 +0200 (CEST) Subject: [KSS-checkins] r53447 - in kukit/kss.demo/branch/jscoverage/kss/demo: . browser jscoverage jscoverage/browser Message-ID: <20080406124544.C4B9C16A70A@codespeak.net> Author: gotcha Date: Sun Apr 6 14:45:44 2008 New Revision: 53447 Added: kukit/kss.demo/branch/jscoverage/kss/demo/jscoverage/ (props changed) - copied from r53442, kukit/kss.demo/trunk/kss/demo/jscoverage/ kukit/kss.demo/branch/jscoverage/kss/demo/jscoverage/IGNORE.txt - copied unchanged from r53442, kukit/kss.demo/trunk/kss/demo/jscoverage/IGNORE.txt kukit/kss.demo/branch/jscoverage/kss/demo/jscoverage/__init__.py - copied unchanged from r53442, kukit/kss.demo/trunk/kss/demo/jscoverage/__init__.py kukit/kss.demo/branch/jscoverage/kss/demo/jscoverage/browser/ - copied from r53442, kukit/kss.demo/trunk/kss/demo/jscoverage/browser/ kukit/kss.demo/branch/jscoverage/kss/demo/jscoverage/browser/__init__.py - copied unchanged from r53442, kukit/kss.demo/trunk/kss/demo/jscoverage/browser/__init__.py kukit/kss.demo/branch/jscoverage/kss/demo/jscoverage/browser/backToIndex.html - copied unchanged from r53442, kukit/kss.demo/trunk/kss/demo/jscoverage/browser/backToIndex.html kukit/kss.demo/branch/jscoverage/kss/demo/jscoverage/browser/configure.zcml - copied unchanged from r53442, kukit/kss.demo/trunk/kss/demo/jscoverage/browser/configure.zcml kukit/kss.demo/branch/jscoverage/kss/demo/jscoverage/browser/coverage.py - copied unchanged from r53442, kukit/kss.demo/trunk/kss/demo/jscoverage/browser/coverage.py kukit/kss.demo/branch/jscoverage/kss/demo/jscoverage/browser/interfaces.py - copied unchanged from r53442, kukit/kss.demo/trunk/kss/demo/jscoverage/browser/interfaces.py kukit/kss.demo/branch/jscoverage/kss/demo/jscoverage/browser/kss_demo_suite_jscoverage.pt - copied unchanged from r53442, kukit/kss.demo/trunk/kss/demo/jscoverage/browser/kss_demo_suite_jscoverage.pt kukit/kss.demo/branch/jscoverage/kss/demo/jscoverage/browser/setJscoverage.html - copied unchanged from r53442, kukit/kss.demo/trunk/kss/demo/jscoverage/browser/setJscoverage.html kukit/kss.demo/branch/jscoverage/kss/demo/jscoverage/browser/unsetJscoverage.html - copied unchanged from r53442, kukit/kss.demo/trunk/kss/demo/jscoverage/browser/unsetJscoverage.html kukit/kss.demo/branch/jscoverage/kss/demo/jscoverage/configure.zcml - copied unchanged from r53442, kukit/kss.demo/trunk/kss/demo/jscoverage/configure.zcml Modified: kukit/kss.demo/branch/jscoverage/kss/demo/browser/header_macros.pt kukit/kss.demo/branch/jscoverage/kss/demo/browser/kss_demo_index.pt kukit/kss.demo/branch/jscoverage/kss/demo/configure.zcml Log: add jscoverage support Modified: kukit/kss.demo/branch/jscoverage/kss/demo/browser/header_macros.pt ============================================================================== --- kukit/kss.demo/branch/jscoverage/kss/demo/browser/header_macros.pt (original) +++ kukit/kss.demo/branch/jscoverage/kss/demo/browser/header_macros.pt Sun Apr 6 14:45:44 2008 @@ -49,14 +49,23 @@ - + + + - - Modified: kukit/kss.demo/branch/jscoverage/kss/demo/browser/kss_demo_index.pt ============================================================================== --- kukit/kss.demo/branch/jscoverage/kss/demo/browser/kss_demo_index.pt (original) +++ kukit/kss.demo/branch/jscoverage/kss/demo/browser/kss_demo_index.pt Sun Apr 6 14:45:44 2008 @@ -1,5 +1,6 @@ + KSS demos and tests @@ -16,6 +17,19 @@ +

Coverage

+
    +
  • Link to Zelenium object (instrumented): +
    + + +
    +
  • +
  • + Coverage report +
  • +

Zelenium object link must be an absolute path from the domain root, or a relative path from the demo SimpleContent's parent. Modified: kukit/kss.demo/branch/jscoverage/kss/demo/configure.zcml ============================================================================== --- kukit/kss.demo/branch/jscoverage/kss/demo/configure.zcml (original) +++ kukit/kss.demo/branch/jscoverage/kss/demo/configure.zcml Sun Apr 6 14:45:44 2008 @@ -7,7 +7,7 @@ > - + @@ -93,4 +93,6 @@ permission="zope.Public" /> + + From gotcha at codespeak.net Sun Apr 6 16:27:42 2008 From: gotcha at codespeak.net (gotcha at codespeak.net) Date: Sun, 6 Apr 2008 16:27:42 +0200 (CEST) Subject: [KSS-checkins] r53452 - in kukit/kss.demo/trunk/kss/demo: . browser jscoverage Message-ID: <20080406142742.6EC7416A711@codespeak.net> Author: gotcha Date: Sun Apr 6 16:27:41 2008 New Revision: 53452 Removed: kukit/kss.demo/trunk/kss/demo/jscoverage/ Modified: kukit/kss.demo/trunk/kss/demo/browser/header_macros.pt kukit/kss.demo/trunk/kss/demo/browser/kss_demo_index.pt kukit/kss.demo/trunk/kss/demo/configure.zcml Log: undo checkin made on wrong branch Modified: kukit/kss.demo/trunk/kss/demo/browser/header_macros.pt ============================================================================== --- kukit/kss.demo/trunk/kss/demo/browser/header_macros.pt (original) +++ kukit/kss.demo/trunk/kss/demo/browser/header_macros.pt Sun Apr 6 16:27:41 2008 @@ -49,23 +49,14 @@ - - - + - - 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 Sun Apr 6 16:27:41 2008 @@ -1,6 +1,5 @@ - KSS demos and tests @@ -17,19 +16,6 @@ -

Coverage

-
    -
  • Link to Zelenium object (instrumented): -
    - - -
    -
  • -
  • - Coverage report -
  • -

Zelenium object link must be an absolute path from the domain root, or a relative path from the demo SimpleContent's parent. Modified: kukit/kss.demo/trunk/kss/demo/configure.zcml ============================================================================== --- kukit/kss.demo/trunk/kss/demo/configure.zcml (original) +++ kukit/kss.demo/trunk/kss/demo/configure.zcml Sun Apr 6 16:27:41 2008 @@ -7,7 +7,7 @@ > - + @@ -93,6 +93,4 @@ permission="zope.Public" /> - - From gotcha at codespeak.net Sun Apr 6 16:35:24 2008 From: gotcha at codespeak.net (gotcha at codespeak.net) Date: Sun, 6 Apr 2008 16:35:24 +0200 (CEST) Subject: [KSS-checkins] r53455 - in kukit/kss.core/branch/jscoverage/kss/core: . plugins/core/demo/selenium_tests Message-ID: <20080406143524.8318316A6B5@codespeak.net> Author: gotcha Date: Sun Apr 6 16:35:23 2008 New Revision: 53455 Added: kukit/kss.core/branch/jscoverage/kss/core/plugins/core/demo/selenium_tests/log_level.html - copied unchanged from r53444, kukit/kss.core/trunk/kss/core/plugins/core/demo/selenium_tests/log_level.html Modified: kukit/kss.core/branch/jscoverage/kss/core/ (props changed) kukit/kss.core/branch/jscoverage/kss/core/EXTERNALS.TXT Log: jscoverage support Modified: kukit/kss.core/branch/jscoverage/kss/core/EXTERNALS.TXT ============================================================================== --- kukit/kss.core/branch/jscoverage/kss/core/EXTERNALS.TXT (original) +++ kukit/kss.core/branch/jscoverage/kss/core/EXTERNALS.TXT Sun Apr 6 16:35:23 2008 @@ -1,8 +1,9 @@ +# You can check externals by issuing: # -# results of svn propget svn:externals -# http://codespeak.net/svn/kukit/kss.core/trunk +# svn propget svn:externals . +# +# You can update your working dir by issuing: # -# 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/jscoverage From gotcha at codespeak.net Sun Apr 6 16:37:39 2008 From: gotcha at codespeak.net (gotcha at codespeak.net) Date: Sun, 6 Apr 2008 16:37:39 +0200 (CEST) Subject: [KSS-checkins] r53457 - in kukit/kss.core/trunk/kss/core: . plugins/core/demo/selenium_tests Message-ID: <20080406143739.961B616A725@codespeak.net> Author: gotcha Date: Sun Apr 6 16:37:39 2008 New Revision: 53457 Removed: kukit/kss.core/trunk/kss/core/plugins/core/demo/selenium_tests/log_level.html Modified: kukit/kss.core/trunk/kss/core/ (props changed) Log: undo checkin made on wrong branch Deleted: /kukit/kss.core/trunk/kss/core/plugins/core/demo/selenium_tests/log_level.html ============================================================================== --- /kukit/kss.core/trunk/kss/core/plugins/core/demo/selenium_tests/log_level.html Sun Apr 6 16:37:39 2008 +++ (empty file) @@ -1,134 +0,0 @@ - - - -log_level - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
log_level
openhttp://localhost:8080/demo/basic_commands.html
open/demo/@@kss_devel_mode/ui
clickdocument.loglevel.loglevel[1]
clickAndWaitbutton_loglevel
assertTextloglevelINFO
openhttp://localhost:8080/demo/basic_commands.html
open/demo/@@kss_devel_mode/ui
assertTextloglevelINFO
clickdocument.loglevel.loglevel[2]
clickAndWaitbutton_loglevel
assertTextloglevelWARNING
openhttp://localhost:8080/demo/basic_commands.html
open/demo/@@kss_devel_mode/ui
assertTextloglevelWARNING
clickdocument.loglevel.loglevel[3]
clickAndWaitbutton_loglevel
assertTextloglevelERROR
openhttp://localhost:8080/demo/basic_commands.html
open/demo/@@kss_devel_mode/ui
assertTextloglevelERROR
clickdocument.loglevel.loglevel[0]
clickAndWaitbutton_loglevel
assertTextloglevelDEBUG
openhttp://localhost:8080/demo/basic_commands.html
- - From gotcha at codespeak.net Sun Apr 6 16:42:41 2008 From: gotcha at codespeak.net (gotcha at codespeak.net) Date: Sun, 6 Apr 2008 16:42:41 +0200 (CEST) Subject: [KSS-checkins] r53458 - kukit/kss.core/trunk/kss/core Message-ID: <20080406144241.2E35716A72D@codespeak.net> Author: gotcha Date: Sun Apr 6 16:42:40 2008 New Revision: 53458 Modified: kukit/kss.core/trunk/kss/core/ (props changed) kukit/kss.core/trunk/kss/core/EXTERNALS.TXT Log: hopefully fix this time :-S Modified: kukit/kss.core/trunk/kss/core/EXTERNALS.TXT ============================================================================== --- kukit/kss.core/trunk/kss/core/EXTERNALS.TXT (original) +++ kukit/kss.core/trunk/kss/core/EXTERNALS.TXT Sun Apr 6 16:42:40 2008 @@ -6,5 +6,5 @@ # # svn propset svn:externals -F EXTERNALS.TXT . # -kukit http://codespeak.net/svn/kukit/kukit.js/branch/jscoverage/ +kukit http://codespeak.net/svn/kukit/kukit.js/trunk From kukit-checkins at codespeak.net Sun Apr 6 16:52:16 2008 From: kukit-checkins at codespeak.net (DealerAdvisor Admin 5547 ® Official Site) Date: Sun, 6 Apr 2008 16:52:16 +0200 (CEST) Subject: [KSS-checkins] April %70 OFF Message-ID: <20080406085112.7264.qmail@bd21b92f.virtua.com.br> An HTML attachment was scrubbed... URL: http://codespeak.net/pipermail/kukit-checkins/attachments/20080406/05789d15/attachment-0001.htm From gotcha at codespeak.net Sun Apr 6 17:15:42 2008 From: gotcha at codespeak.net (gotcha at codespeak.net) Date: Sun, 6 Apr 2008 17:15:42 +0200 (CEST) Subject: [KSS-checkins] r53459 - kukit/kss.buildout/branch/jscoverage Message-ID: <20080406151542.7F0AC16A750@codespeak.net> Author: gotcha Date: Sun Apr 6 17:15:38 2008 New Revision: 53459 Modified: kukit/kss.buildout/branch/jscoverage/buildout.cfg Log: put jscoverage scripts in bin directory Modified: kukit/kss.buildout/branch/jscoverage/buildout.cfg ============================================================================== --- kukit/kss.buildout/branch/jscoverage/buildout.cfg (original) +++ kukit/kss.buildout/branch/jscoverage/buildout.cfg Sun Apr 6 17:15:38 2008 @@ -50,3 +50,4 @@ [coverage] recipe = zc.recipe.cmmi url = http://siliconforks.com/jscoverage/download/jscoverage-0.3.1.tar.bz2 +extra_options = --bindir=${buildout:directory}/bin From gotcha at codespeak.net Sun Apr 6 17:15:58 2008 From: gotcha at codespeak.net (gotcha at codespeak.net) Date: Sun, 6 Apr 2008 17:15:58 +0200 (CEST) Subject: [KSS-checkins] r53460 - kukit/kss.demo/branch/jscoverage/kss/demo/jscoverage Message-ID: <20080406151558.B76E016A750@codespeak.net> Author: gotcha Date: Sun Apr 6 17:15:57 2008 New Revision: 53460 Modified: kukit/kss.demo/branch/jscoverage/kss/demo/jscoverage/configure.zcml Log: better comments Modified: kukit/kss.demo/branch/jscoverage/kss/demo/jscoverage/configure.zcml ============================================================================== --- kukit/kss.demo/branch/jscoverage/kss/demo/jscoverage/configure.zcml (original) +++ kukit/kss.demo/branch/jscoverage/kss/demo/jscoverage/configure.zcml Sun Apr 6 17:15:57 2008 @@ -5,14 +5,21 @@ - + + - - Author: gotcha Date: Sun Apr 6 17:17:03 2008 New Revision: 53461 Modified: kukit/kss.demo/branch/jscoverage/kss/demo/jscoverage/configure.zcml Log: one slash too much Modified: kukit/kss.demo/branch/jscoverage/kss/demo/jscoverage/configure.zcml ============================================================================== --- kukit/kss.demo/branch/jscoverage/kss/demo/jscoverage/configure.zcml (original) +++ kukit/kss.demo/branch/jscoverage/kss/demo/jscoverage/configure.zcml Sun Apr 6 17:17:03 2008 @@ -11,7 +11,7 @@ the instrumented code in src/kss.demo/kss/demo/jscoverage/js can be generated by issuing the following shell command : - /bin/jscoverage src/kss.core/kss/core/kukit/kukit/ src/kss.demo/kss/demo/jscoverage/js + bin/jscoverage src/kss.core/kss/core/kukit/kukit/ src/kss.demo/kss/demo/jscoverage/js --> From gotcha at codespeak.net Sun Apr 6 17:24:26 2008 From: gotcha at codespeak.net (gotcha at codespeak.net) Date: Sun, 6 Apr 2008 17:24:26 +0200 (CEST) Subject: [KSS-checkins] r53462 - kukit/kss.core/branch/jscoverage/kss/core/plugins/core/demo Message-ID: <20080406152426.1F21416A4DE@codespeak.net> Author: gotcha Date: Sun Apr 6 17:24:25 2008 New Revision: 53462 Modified: kukit/kss.core/branch/jscoverage/kss/core/plugins/core/demo/config.py Log: update externals Modified: kukit/kss.core/branch/jscoverage/kss/core/plugins/core/demo/config.py ============================================================================== --- kukit/kss.core/branch/jscoverage/kss/core/plugins/core/demo/config.py (original) +++ kukit/kss.core/branch/jscoverage/kss/core/plugins/core/demo/config.py Sun Apr 6 17:24:25 2008 @@ -13,6 +13,7 @@ class CoreDemos(Plugin): zope_demos = ( + KSSDemo('', '', "loglevel.html", "Log level"), KSSDemo('', '', "basic_commands.html", "Change tag content"), KSSDemo('', '', "two_selects.html", "Two selects"), KSSDemo('', '', "autoupdate.html", "Auto update"), From gotcha at codespeak.net Sun Apr 6 17:51:12 2008 From: gotcha at codespeak.net (gotcha at codespeak.net) Date: Sun, 6 Apr 2008 17:51:12 +0200 (CEST) Subject: [KSS-checkins] r53467 - kukit/kss.demo/branch/jscoverage/kss/demo/jscoverage/browser Message-ID: <20080406155112.6589E16A6EE@codespeak.net> Author: gotcha Date: Sun Apr 6 17:51:11 2008 New Revision: 53467 Modified: kukit/kss.demo/branch/jscoverage/kss/demo/jscoverage/browser/kss_demo_suite_jscoverage.pt Log: fix title Modified: kukit/kss.demo/branch/jscoverage/kss/demo/jscoverage/browser/kss_demo_suite_jscoverage.pt ============================================================================== --- kukit/kss.demo/branch/jscoverage/kss/demo/jscoverage/browser/kss_demo_suite_jscoverage.pt (original) +++ kukit/kss.demo/branch/jscoverage/kss/demo/jscoverage/browser/kss_demo_suite_jscoverage.pt Sun Apr 6 17:51:11 2008 @@ -10,7 +10,7 @@

- Jscoverage mode + Set jscoverage mode

@@ -25,7 +25,7 @@

- Development mode + Reset jscoverage mode

From gotcha at codespeak.net Sun Apr 6 17:52:02 2008 From: gotcha at codespeak.net (gotcha at codespeak.net) Date: Sun, 6 Apr 2008 17:52:02 +0200 (CEST) Subject: [KSS-checkins] r53468 - in kukit/kss.core/branch/jscoverage/kss/core: pluginregistry/browser plugins/core/demo Message-ID: <20080406155202.C0DEC16A6F6@codespeak.net> Author: gotcha Date: Sun Apr 6 17:52:02 2008 New Revision: 53468 Modified: kukit/kss.core/branch/jscoverage/kss/core/pluginregistry/browser/develui.pt kukit/kss.core/branch/jscoverage/kss/core/plugins/core/demo/config.py kukit/kss.core/branch/jscoverage/kss/core/plugins/core/demo/zopeconfig.py Log: fix test that covers log levels Modified: kukit/kss.core/branch/jscoverage/kss/core/pluginregistry/browser/develui.pt ============================================================================== --- kukit/kss.core/branch/jscoverage/kss/core/pluginregistry/browser/develui.pt (original) +++ kukit/kss.core/branch/jscoverage/kss/core/pluginregistry/browser/develui.pt Sun Apr 6 17:52:02 2008 @@ -106,7 +106,8 @@

Current KSS log level is - DEBUG.

Modified: kukit/kss.core/branch/jscoverage/kss/core/plugins/core/demo/config.py ============================================================================== --- kukit/kss.core/branch/jscoverage/kss/core/plugins/core/demo/config.py (original) +++ kukit/kss.core/branch/jscoverage/kss/core/plugins/core/demo/config.py Sun Apr 6 17:52:02 2008 @@ -13,7 +13,7 @@ class CoreDemos(Plugin): zope_demos = ( - KSSDemo('', '', "loglevel.html", "Log level"), + KSSDemo('', '', "log_level.html", "Log level"), KSSDemo('', '', "basic_commands.html", "Change tag content"), KSSDemo('', '', "two_selects.html", "Two selects"), KSSDemo('', '', "autoupdate.html", "Auto update"), Modified: kukit/kss.core/branch/jscoverage/kss/core/plugins/core/demo/zopeconfig.py ============================================================================== --- kukit/kss.core/branch/jscoverage/kss/core/plugins/core/demo/zopeconfig.py (original) +++ kukit/kss.core/branch/jscoverage/kss/core/plugins/core/demo/zopeconfig.py Sun Apr 6 17:52:02 2008 @@ -18,6 +18,7 @@ implements(IResource) demos = ( + KSSDemo('', '', "log_level.html", "Log level"), KSSDemo('', '', "basic_commands.html", "Change tag content"), KSSDemo('', '', "two_selects.html", "Two selects"), KSSDemo('', '', "autoupdate.html", "Auto update"), From gotcha at codespeak.net Sun Apr 6 18:13:00 2008 From: gotcha at codespeak.net (gotcha at codespeak.net) Date: Sun, 6 Apr 2008 18:13:00 +0200 (CEST) Subject: [KSS-checkins] r53470 - kukit/kss.buildout/branch/with-Zelenium-dev Message-ID: <20080406161300.30BF816A41A@codespeak.net> Author: gotcha Date: Sun Apr 6 18:12:59 2008 New Revision: 53470 Removed: kukit/kss.buildout/branch/with-Zelenium-dev/ Log: not needed anymore From wiggy at codespeak.net Wed Apr 9 11:54:52 2008 From: wiggy at codespeak.net (wiggy at codespeak.net) Date: Wed, 9 Apr 2008 11:54:52 +0200 (CEST) Subject: [KSS-checkins] r53604 - in kukit/kss.core/branch/1.4/kss/core/plugins/core/demo: coreplugin selenium_tests Message-ID: <20080409095452.136B8169F9A@codespeak.net> Author: wiggy Date: Wed Apr 9 11:54:51 2008 New Revision: 53604 Modified: kukit/kss.core/branch/1.4/kss/core/plugins/core/demo/coreplugin/__init__.py (props changed) kukit/kss.core/branch/1.4/kss/core/plugins/core/demo/coreplugin/configure.zcml (props changed) kukit/kss.core/branch/1.4/kss/core/plugins/core/demo/coreplugin/demoview.py (props changed) kukit/kss.core/branch/1.4/kss/core/plugins/core/demo/coreplugin/kss_evt_preventbubbling.kss (props changed) kukit/kss.core/branch/1.4/kss/core/plugins/core/demo/coreplugin/kss_evt_preventbubbling.pt (props changed) kukit/kss.core/branch/1.4/kss/core/plugins/core/demo/selenium_tests/kss_prevent_bubbling.html (props changed) Log: Remove bogus executable flags From hannosch at codespeak.net Fri Apr 11 22:57:56 2008 From: hannosch at codespeak.net (hannosch at codespeak.net) Date: Fri, 11 Apr 2008 22:57:56 +0200 (CEST) Subject: [KSS-checkins] r53707 - kukit/kss.demo/trunk/kss/demo Message-ID: <20080411205756.01BD92A01B1@codespeak.net> Author: hannosch Date: Fri Apr 11 22:57:54 2008 New Revision: 53707 Modified: kukit/kss.demo/trunk/kss/demo/configure.zcml Log: Removed deprecated declarations Modified: kukit/kss.demo/trunk/kss/demo/configure.zcml ============================================================================== --- kukit/kss.demo/trunk/kss/demo/configure.zcml (original) +++ kukit/kss.demo/trunk/kss/demo/configure.zcml Fri Apr 11 22:57:54 2008 @@ -16,11 +16,6 @@ type="zope.app.content.interfaces.IContentType" /> - - - - - Our Chemists� presents all medications that you need to recover your health at low price. We work all over the world with clients from America, Europe and Asia. Now you don't have to look for chemists� at your region. We deliver high-quality pills worldwide. Visit our site and get all your needs delivered instantly direct to your home. We are verified by VeriSign and VISA so we provide secure and confidential purchase. http://www.google.com/pagead/iclk?sa=l&ai=fzjea&num=1131952&adurl=http://edogalkozmetik.com/offer From kukit-checkins at codespeak.net Mon Apr 14 19:46:13 2008 From: kukit-checkins at codespeak.net (kukit-checkins at codespeak.net) Date: Mon, 14 Apr 2008 19:46:13 +0200 (CEST) Subject: [KSS-checkins] MensHealth 592969 Message-ID: <20080414124502.3042.qmail@ppp85-141-200-187.pppoe.mtu-net.ru> Visit Canadian Health&Care Mall and you won't regret! _LET http://www.google.com/pagead/iclk?sa=l&ai=wuktb&num=430&adurl=http://www.leavestand.com From reebalazs at codespeak.net Tue Apr 15 04:07:02 2008 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Tue, 15 Apr 2008 04:07:02 +0200 (CEST) Subject: [KSS-checkins] r53765 - kukit/kukit.js/branch/ree-service-layer-and-refactoring-ORIGINAL Message-ID: <20080415020702.DB4BD39B594@codespeak.net> Author: reebalazs Date: Tue Apr 15 04:07:01 2008 New Revision: 53765 Added: kukit/kukit.js/branch/ree-service-layer-and-refactoring-ORIGINAL/ - copied from r53764, kukit/kukit.js/branch/ree-service-layer-and-refactoring/ Log: Save original branch From reebalazs at codespeak.net Tue Apr 15 04:08:22 2008 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Tue, 15 Apr 2008 04:08:22 +0200 (CEST) Subject: [KSS-checkins] r53766 - kukit/kukit.js/branch/ree-service-layer-and-refactoring-ORIGINAL Message-ID: <20080415020822.D864D39B594@codespeak.net> Author: reebalazs Date: Tue Apr 15 04:08:22 2008 New Revision: 53766 Removed: kukit/kukit.js/branch/ree-service-layer-and-refactoring-ORIGINAL/ Log: Undo From reebalazs at codespeak.net Tue Apr 15 04:08:58 2008 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Tue, 15 Apr 2008 04:08:58 +0200 (CEST) Subject: [KSS-checkins] r53767 - in kukit/kukit.js/branch: ree-service-layer-and-refactoring ree-service-layer-and-refactoring-ORIGINAL Message-ID: <20080415020858.1D8FD1683CE@codespeak.net> Author: reebalazs Date: Tue Apr 15 04:08:58 2008 New Revision: 53767 Added: kukit/kukit.js/branch/ree-service-layer-and-refactoring-ORIGINAL/ - copied from r53766, kukit/kukit.js/branch/ree-service-layer-and-refactoring/ Removed: kukit/kukit.js/branch/ree-service-layer-and-refactoring/ Log: Save original branch From reebalazs at codespeak.net Tue Apr 15 04:09:49 2008 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Tue, 15 Apr 2008 04:09:49 +0200 (CEST) Subject: [KSS-checkins] r53768 - kukit/kukit.js/branch/ree-service-layer-and-refactoring Message-ID: <20080415020949.4667B39B594@codespeak.net> Author: reebalazs Date: Tue Apr 15 04:09:48 2008 New Revision: 53768 Added: kukit/kukit.js/branch/ree-service-layer-and-refactoring/ - copied from r53767, kukit/kukit.js/trunk/ Log: Copy for rebasing branch From reebalazs at codespeak.net Tue Apr 15 10:00:05 2008 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Tue, 15 Apr 2008 10:00:05 +0200 (CEST) Subject: [KSS-checkins] r53772 - kukit/kukit.js/branch/ree-service-layer-and-refactoring Message-ID: <20080415080005.881D7169E78@codespeak.net> Author: reebalazs Date: Tue Apr 15 10:00:02 2008 New Revision: 53772 Added: kukit/kukit.js/branch/ree-service-layer-and-refactoring/ (props changed) - copied from r52602, kukit/kukit.js/trunk/ Log: Branch off From reebalazs at codespeak.net Tue Apr 15 10:50:07 2008 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Tue, 15 Apr 2008 10:50:07 +0200 (CEST) Subject: [KSS-checkins] r53773 - kukit/kukit.js/branch/ree-service-layer-and-refactoring Message-ID: <20080415085007.63B06168513@codespeak.net> Author: reebalazs Date: Tue Apr 15 10:50:05 2008 New Revision: 53773 Removed: kukit/kukit.js/branch/ree-service-layer-and-refactoring/ Log: Fix up From reebalazs at codespeak.net Tue Apr 15 10:50:44 2008 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Tue, 15 Apr 2008 10:50:44 +0200 (CEST) Subject: [KSS-checkins] r53774 - in kukit/kukit.js/branch: ree-service-layer-and-refactoring ree-service-layer-and-refactoring-ORIGINAL Message-ID: <20080415085044.290D6168513@codespeak.net> Author: reebalazs Date: Tue Apr 15 10:50:43 2008 New Revision: 53774 Added: kukit/kukit.js/branch/ree-service-layer-and-refactoring/ - copied from r53773, kukit/kukit.js/branch/ree-service-layer-and-refactoring-ORIGINAL/ Removed: kukit/kukit.js/branch/ree-service-layer-and-refactoring-ORIGINAL/ Log: Fix up From reebalazs at codespeak.net Tue Apr 15 10:55:47 2008 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Tue, 15 Apr 2008 10:55:47 +0200 (CEST) Subject: [KSS-checkins] r53775 - kukit/kukit.js/branch/ree-service-layer-and-refactoring-final Message-ID: <20080415085547.CF995168515@codespeak.net> Author: reebalazs Date: Tue Apr 15 10:55:47 2008 New Revision: 53775 Added: kukit/kukit.js/branch/ree-service-layer-and-refactoring-final/ (props changed) - copied from r52602, kukit/kukit.js/trunk/ Log: Branch off From reebalazs at codespeak.net Tue Apr 15 11:09:28 2008 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Tue, 15 Apr 2008 11:09:28 +0200 (CEST) Subject: [KSS-checkins] r53776 - kukit/kukit.js/branch/ree-service-layer-and-refactoring-new Message-ID: <20080415090928.1F64E39B5B0@codespeak.net> Author: reebalazs Date: Tue Apr 15 11:09:27 2008 New Revision: 53776 Added: kukit/kukit.js/branch/ree-service-layer-and-refactoring-new/ - copied from r53775, kukit/kukit.js/trunk/ Log: branch off From reebalazs at codespeak.net Tue Apr 15 11:36:41 2008 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Tue, 15 Apr 2008 11:36:41 +0200 (CEST) Subject: [KSS-checkins] r53778 - in kukit/kss.core/branch/ree-service-layer-and-refactoring: . docs kss/core kss/core/browser kss/core/docs kss/core/pluginregistry/browser kss/core/plugins/core kss/core/plugins/core/demo kss/core/plugins/core/demo/binderclasses kss/core/plugins/core/demo/binderclasses/selenium_tests kss/core/plugins/core/demo/binderids kss/core/plugins/core/demo/binderids/selenium_tests kss/core/plugins/core/demo/coreplugin kss/core/plugins/core/demo/coresyntax kss/core/plugins/core/demo/coresyntax/selenium_tests kss/core/plugins/core/demo/parameterfunction kss/core/plugins/core/demo/parameterfunction/selenium_tests kss/core/plugins/core/demo/selenium_tests kss/core/tests Message-ID: <20080415093641.5CC5C39B5B7@codespeak.net> Author: reebalazs Date: Tue Apr 15 11:36:37 2008 New Revision: 53778 Added: kukit/kss.core/branch/ree-service-layer-and-refactoring/docs/ - copied from r53709, kukit/kss.core/trunk/docs/ kukit/kss.core/branch/ree-service-layer-and-refactoring/docs/HISTORY.txt - copied unchanged from r53709, kukit/kss.core/trunk/docs/HISTORY.txt kukit/kss.core/branch/ree-service-layer-and-refactoring/docs/INSTALL.txt - copied unchanged from r53709, kukit/kss.core/trunk/docs/INSTALL.txt kukit/kss.core/branch/ree-service-layer-and-refactoring/docs/LICENSE.GPL - copied unchanged from r53709, kukit/kss.core/trunk/docs/LICENSE.GPL kukit/kss.core/branch/ree-service-layer-and-refactoring/docs/LICENSE.txt - copied unchanged from r53709, kukit/kss.core/trunk/docs/LICENSE.txt kukit/kss.core/branch/ree-service-layer-and-refactoring/docs/NEWS.txt - copied unchanged from r53709, kukit/kss.core/trunk/docs/NEWS.txt kukit/kss.core/branch/ree-service-layer-and-refactoring/docs/TODO.txt - copied unchanged from r53709, kukit/kss.core/trunk/docs/TODO.txt kukit/kss.core/branch/ree-service-layer-and-refactoring/docs/tutorial_part2.rst - copied unchanged from r53709, kukit/kss.core/trunk/docs/tutorial_part2.rst kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/binderclasses/ - copied from r53709, kukit/kss.core/trunk/kss/core/plugins/core/demo/binderclasses/ kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/binderclasses/README - copied unchanged from r53709, kukit/kss.core/trunk/kss/core/plugins/core/demo/binderclasses/README kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/binderclasses/__init__.py - copied unchanged from r53709, kukit/kss.core/trunk/kss/core/plugins/core/demo/binderclasses/__init__.py kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/binderclasses/configure.zcml - copied unchanged from r53709, kukit/kss.core/trunk/kss/core/plugins/core/demo/binderclasses/configure.zcml kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/binderclasses/kss_binder_classes.js - copied unchanged from r53709, kukit/kss.core/trunk/kss/core/plugins/core/demo/binderclasses/kss_binder_classes.js kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/binderclasses/kss_binder_classes.kss - copied unchanged from r53709, kukit/kss.core/trunk/kss/core/plugins/core/demo/binderclasses/kss_binder_classes.kss kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/binderclasses/kss_binder_classes.pt - copied unchanged from r53709, kukit/kss.core/trunk/kss/core/plugins/core/demo/binderclasses/kss_binder_classes.pt kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/binderclasses/selenium_tests/ - copied from r53709, kukit/kss.core/trunk/kss/core/plugins/core/demo/binderclasses/selenium_tests/ kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/binderclasses/selenium_tests/README.txt - copied unchanged from r53709, kukit/kss.core/trunk/kss/core/plugins/core/demo/binderclasses/selenium_tests/README.txt kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/binderclasses/selenium_tests/binderclasses.html - copied unchanged from r53709, kukit/kss.core/trunk/kss/core/plugins/core/demo/binderclasses/selenium_tests/binderclasses.html kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/binderclasses/zopeconfig.py - copied unchanged from r53709, kukit/kss.core/trunk/kss/core/plugins/core/demo/binderclasses/zopeconfig.py kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/binderids/selenium_tests/binderids.html - copied unchanged from r53709, kukit/kss.core/trunk/kss/core/plugins/core/demo/binderids/selenium_tests/binderids.html kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/coresyntax/config.py - copied unchanged from r53709, kukit/kss.core/trunk/kss/core/plugins/core/demo/coresyntax/config.py kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/coresyntax/kss_client_action_alias.kss - copied unchanged from r53709, kukit/kss.core/trunk/kss/core/plugins/core/demo/coresyntax/kss_client_action_alias.kss kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/coresyntax/kss_client_action_alias.pt - copied unchanged from r53709, kukit/kss.core/trunk/kss/core/plugins/core/demo/coresyntax/kss_client_action_alias.pt kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/coresyntax/kss_selector_param_multiprop.kss - copied unchanged from r53709, kukit/kss.core/trunk/kss/core/plugins/core/demo/coresyntax/kss_selector_param_multiprop.kss kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/coresyntax/kss_selector_param_multiprop.pt - copied unchanged from r53709, kukit/kss.core/trunk/kss/core/plugins/core/demo/coresyntax/kss_selector_param_multiprop.pt kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/coresyntax/kss_url_param_multiprop.kss - copied unchanged from r53709, kukit/kss.core/trunk/kss/core/plugins/core/demo/coresyntax/kss_url_param_multiprop.kss kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/coresyntax/kss_url_param_multiprop.pt - copied unchanged from r53709, kukit/kss.core/trunk/kss/core/plugins/core/demo/coresyntax/kss_url_param_multiprop.pt kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/coresyntax/selenium_tests/ - copied from r53709, kukit/kss.core/trunk/kss/core/plugins/core/demo/coresyntax/selenium_tests/ kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/coresyntax/selenium_tests/README.txt - copied unchanged from r53709, kukit/kss.core/trunk/kss/core/plugins/core/demo/coresyntax/selenium_tests/README.txt kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/coresyntax/selenium_tests/kss_client_action_alias.html - copied unchanged from r53709, kukit/kss.core/trunk/kss/core/plugins/core/demo/coresyntax/selenium_tests/kss_client_action_alias.html kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/coresyntax/selenium_tests/kss_selector_param.html - copied unchanged from r53709, kukit/kss.core/trunk/kss/core/plugins/core/demo/coresyntax/selenium_tests/kss_selector_param.html kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/coresyntax/selenium_tests/kss_selector_param_multiprop.html - copied unchanged from r53709, kukit/kss.core/trunk/kss/core/plugins/core/demo/coresyntax/selenium_tests/kss_selector_param_multiprop.html kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/coresyntax/selenium_tests/kss_url_param_multiprop.html - copied unchanged from r53709, kukit/kss.core/trunk/kss/core/plugins/core/demo/coresyntax/selenium_tests/kss_url_param_multiprop.html kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/coresyntax/selenium_tests/urlparam.html - copied unchanged from r53709, kukit/kss.core/trunk/kss/core/plugins/core/demo/coresyntax/selenium_tests/urlparam.html kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/coresyntax/zopeconfig.py - copied unchanged from r53709, kukit/kss.core/trunk/kss/core/plugins/core/demo/coresyntax/zopeconfig.py kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/parameterfunction/config.py - copied unchanged from r53709, kukit/kss.core/trunk/kss/core/plugins/core/demo/parameterfunction/config.py kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/parameterfunction/kss_form_submit_multiprop.kss - copied unchanged from r53709, kukit/kss.core/trunk/kss/core/plugins/core/demo/parameterfunction/kss_form_submit_multiprop.kss kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/parameterfunction/kss_form_submit_multiprop.pt - copied unchanged from r53709, kukit/kss.core/trunk/kss/core/plugins/core/demo/parameterfunction/kss_form_submit_multiprop.pt kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/parameterfunction/kssid-UNUSED.kss - copied unchanged from r53709, kukit/kss.core/trunk/kss/core/plugins/core/demo/parameterfunction/kssid-UNUSED.kss kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/parameterfunction/kssid-UNUSED.pt - copied unchanged from r53709, kukit/kss.core/trunk/kss/core/plugins/core/demo/parameterfunction/kssid-UNUSED.pt kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/parameterfunction/selenium_tests/ - copied from r53709, kukit/kss.core/trunk/kss/core/plugins/core/demo/parameterfunction/selenium_tests/ kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/parameterfunction/selenium_tests/README.txt - copied unchanged from r53709, kukit/kss.core/trunk/kss/core/plugins/core/demo/parameterfunction/selenium_tests/README.txt kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/parameterfunction/selenium_tests/kss_form_submit_multiprop.html - copied unchanged from r53709, kukit/kss.core/trunk/kss/core/plugins/core/demo/parameterfunction/selenium_tests/kss_form_submit_multiprop.html kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/parameterfunction/selenium_tests/pf_forms.html - copied unchanged from r53709, kukit/kss.core/trunk/kss/core/plugins/core/demo/parameterfunction/selenium_tests/pf_forms.html kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/parameterfunction/zopeconfig.py - copied unchanged from r53709, kukit/kss.core/trunk/kss/core/plugins/core/demo/parameterfunction/zopeconfig.py kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/selenium_tests/0_ecmaunit_tests.html - copied, changed from r53709, kukit/kss.core/trunk/kss/core/plugins/core/demo/selenium_tests/0_ecmaunit_tests.html kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/selenium_tests/protocol.html - copied unchanged from r53709, kukit/kss.core/trunk/kss/core/plugins/core/demo/selenium_tests/protocol.html Removed: kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/docs/ kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/parameterfunction/kssid.kss kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/parameterfunction/kssid.pt kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/selenium_tests/kss_selector_param.html kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/selenium_tests/pf_forms.html kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/selenium_tests/urlparam.html Modified: kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/browser/errorresponse.pt kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/commands.py kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/concatresource.zcml kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/pluginregistry/browser/develui.css kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/pluginregistry/browser/develui.pt kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/commands.py kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/configure.zcml kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/binderids/binderids.kss kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/binderids/binderids.pt kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/binderids/config.py kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/config.py kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/configure.zcml kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/coreplugin/kss_evt_preventbubbling.kss kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/coreplugin/kss_evt_preventbubbling.pt kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/coresyntax/configure.zcml kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/demoview.py kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/error_handling.kss kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/error_handling.pt kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/form_submit.kss kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/more_selectors.js kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/more_selectors.kss kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/more_selectors.pt kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/parameterfunction/configure.zcml kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/parameterfunction/forms.kss kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/parameterfunction/forms.pt kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/protocol.pt kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/selenium_tests/error_handling.html kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/selenium_tests/html_inserts.html kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/selenium_tests/more_selectors.html kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/zopeconfig.py kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/interfaces.py kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/tests/configure-online.zcml kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/tests/kukitresponse_test.pt kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/tests/test_browserview.py kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/tests/test_kssview_core.py kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/version.txt kukit/kss.core/branch/ree-service-layer-and-refactoring/setup.py Log: Rebase on current trunk. Modified: kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/browser/errorresponse.pt ============================================================================== --- kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/browser/errorresponse.pt (original) +++ kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/browser/errorresponse.pt Tue Apr 15 11:36:37 2008 @@ -1,5 +1,5 @@ - Modified: kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/commands.py ============================================================================== --- kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/commands.py (original) +++ kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/commands.py Tue Apr 15 11:36:37 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/branch/ree-service-layer-and-refactoring/kss/core/concatresource.zcml ============================================================================== --- kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/concatresource.zcml (original) +++ kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/concatresource.zcml Tue Apr 15 11:36:37 2008 @@ -32,6 +32,7 @@ kukit/kukit/oper.js kukit/kukit/tokenizer.js kukit/kukit/providerreg.js + kukit/kukit/values.js kukit/kukit/resourcedata.js kukit/kukit/kssparser.js kukit/kukit/eventreg.js @@ -47,6 +48,8 @@ kukit/kukit/plugin.js" name="kukit.js" compress_level="safe" + caching="memory" + lmt_check_period="300" /> @@ -59,6 +62,7 @@ kukit/kukit/oper.js kukit/kukit/tokenizer.js kukit/kukit/providerreg.js + kukit/kukit/values.js kukit/kukit/resourcedata.js kukit/kukit/kssparser.js kukit/kukit/eventreg.js @@ -75,7 +79,7 @@ name="kukit-devel.js" compress_level="devel" caching="memory" - lmt_check_period="5" + lmt_check_period="0" /> Modified: kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/pluginregistry/browser/develui.css ============================================================================== --- kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/pluginregistry/browser/develui.css (original) +++ kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/pluginregistry/browser/develui.css Tue Apr 15 11:36:37 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/branch/ree-service-layer-and-refactoring/kss/core/pluginregistry/browser/develui.pt ============================================================================== --- kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/pluginregistry/browser/develui.pt (original) +++ kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/pluginregistry/browser/develui.pt Tue Apr 15 11:36:37 2008 @@ -106,7 +106,8 @@

Current KSS log level is - DEBUG.

Modified: kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/commands.py ============================================================================== --- kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/commands.py (original) +++ kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/commands.py Tue Apr 15 11:36:37 2008 @@ -117,10 +117,11 @@ command.addParam('varname', varname) command.addParam('value', value) - def triggerEvent(self, name, **kw): + def continueEvent(self, name, allnodes=False, **kw): """ see interfaces.py """ - command = self.commands.addCommand('triggerEvent') + command = self.commands.addCommand('continueEvent') command.addParam('name', name) + command.addParam('allnodes', allnodes and 'true' or 'false') for key, value in kw.iteritems(): command.addParam(key, value) Modified: kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/configure.zcml ============================================================================== --- kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/configure.zcml (original) +++ kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/configure.zcml Tue Apr 15 11:36:37 2008 @@ -282,10 +282,10 @@ /> + +

Two loggers are used, because the order in which the events trigger + is undefined and browser dependant.


@@ -28,6 +32,16 @@ value="button3">
+ +
+ +

logger

+ +
+

Log 2

+

Reset

+
+

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/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/binderids/config.py ============================================================================== --- kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/binderids/config.py (original) +++ kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/binderids/config.py Tue Apr 15 11:36:37 2008 @@ -1,22 +1,28 @@ - from kss.base.plugin import Plugin -from kss.demo.resource import ( - KSSDemo, - KSSSeleniumTestDirectory, - ) - -class CoreDemos(Plugin): - - zope_demos = ( - # List your demos here. - # (Second parameter can be a subcategory within the demo if needed.) - KSSDemo('', 'Core syntax', 'binderids.html', 'Binder ids'), - - ) - - # directories are relative from the location of this .py file - zope_selenium_testsuites = ( - # if you only have one test directory, you - # need not change anything here. - KSSSeleniumTestDirectory('selenium_tests'), - ) + +def core_demos(): + try: + from kss.demo.resource import ( + KSSDemo, + KSSSeleniumTestDirectory, + ) + except ImportError: # no demo package installed + return Plugin() + + + class CoreDemos(Plugin): + + zope_demos = ( + # List your demos here. + # (Second parameter can be a subcategory within the demo if needed.) + KSSDemo('', 'Core syntax', 'binderids.html', 'Binder ids'), + ) + + # directories are relative from the location of this .py file + zope_selenium_testsuites = ( + # if you only have one test directory, you + # need not change anything here. + KSSSeleniumTestDirectory('selenium_tests'), + ) + return CoreDemos() + Modified: kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/config.py ============================================================================== --- kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/config.py (original) +++ kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/config.py Tue Apr 15 11:36:37 2008 @@ -1,39 +1,42 @@ - from kss.base.plugin import Plugin -from kss.demo.resource import ( - KSSDemo, - KSSSeleniumTestDirectory, - ) -class CoreDemos(Plugin): +def core_demos(): + try: + from kss.demo.resource import ( + KSSDemo, + KSSSeleniumTestDirectory, + ) + except ImportError: # no demo package installed + return Plugin() + + + 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"), - ) + 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('', 'Selectors', 'selectors.html', 'Parent node selector'), + 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'), - ) + # directories are relative from the location of this .py file + zope_selenium_testsuites = ( + KSSSeleniumTestDirectory('selenium_tests'), + ) + return CoreDemos() Modified: kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/configure.zcml ============================================================================== --- kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/configure.zcml (original) +++ kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/configure.zcml Tue Apr 15 11:36:37 2008 @@ -15,6 +15,7 @@ + + + + + + + + + + + + + + + + + + + + + + + + Modified: kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/demoview.py ============================================================================== --- kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/demoview.py (original) +++ kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/demoview.py Tue Apr 15 11:36:37 2008 @@ -136,9 +136,9 @@ self.getCommandSet('core').replaceHTML('select#%s' % slaveid, ' '.join(result)) return self.render() - def formSubmitSave(self, data): + def formSubmitSave(self): result = ['

Async saved:

'] - for key, value in data.items(): + for key, value in self.request.form.items(): result.append('' % (key, value)) result.append('
Name:Value:
%s%s
') # We need to make unicode. But on Z2 we receive utf-8, on Z3 unicode Modified: kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/error_handling.kss ============================================================================== --- kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/error_handling.kss (original) +++ kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/error_handling.kss Tue Apr 15 11:36:37 2008 @@ -13,9 +13,9 @@ .handled:click { - errTest-error: insertHTMLBefore; - insertHTMLBefore-kssSelector: #log-end; - insertHTMLBefore-html: "Error handler activated."; + errTest-error: insertHTMLAsLastChild; + insertHTMLAsLastChild-kssSelector: #logger; + insertHTMLAsLastChild-html: "Error handler activated."; } /* Spinner control @@ -41,7 +41,4 @@ #log-reset a:click, #log-reset:click { action-client: clearChildNodes; clearChildNodes-kssSelector: #logger; - action-client: insertHTMLAsLastChild; - insertHTMLAsLastChild-kssSelector: #logger; - insertHTMLAsLastChild-html: "

"; } Modified: kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/error_handling.pt ============================================================================== --- kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/error_handling.pt (original) +++ kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/error_handling.pt Tue Apr 15 11:36:37 2008 @@ -64,12 +64,6 @@ their number (currently in 4): click like crazy on the buttons and you will see that your server will not get hogged. More will be told about this topic in the upcoming documentation.

-

Log

-

Reset log

-

Error log :

-
-

-
- +

logger

Modified: kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/form_submit.kss ============================================================================== --- kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/form_submit.kss (original) +++ kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/form_submit.kss Tue Apr 15 11:36:37 2008 @@ -1,5 +1,5 @@ input#submit:click { evt-click-preventdefault: true; action-server: formSave; - formSave-data: currentForm(); + formSave-kssSubmitForm: currentForm(); } Modified: kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/more_selectors.js ============================================================================== --- kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/more_selectors.js (original) +++ kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/more_selectors.js Tue Apr 15 11:36:37 2008 @@ -3,9 +3,8 @@ kukit.more_selectors = {}; kukit.more_selectors.AnnoyClickerEvent = function() { -}; -kukit.more_selectors.AnnoyClickerEvent.prototype.__bind_click__ = function(oper) { +this.__bind_click__ = function(oper) { // validate and set parameters oper.evaluateParameters([], {'count': '3'}, 'annoyClicker event binding'); oper.evalInt('count', 'annoyClicker event binding'); @@ -19,18 +18,19 @@ kukit.pl.registerBrowserEvent(oper, null, 'click'); }; -kukit.more_selectors.AnnoyClickerEvent.prototype.__default_click__ = function(name, oper) { +this.__default_click__ = function(name, oper) { oper.evaluateParameters([], {}, 'annoyClicker event binding'); this.count -= 1; if (this.count == 0) { // Continue with the real action. this.count = this.countsomuch; - this.__continueEvent__('annoyclicker-doit', oper.node, {}); + this.continueEvent('annoyclicker-doit', oper.node, {}); } else { - this.__continueEvent__('annoyclicker-annoy', oper.node, {}); + this.continueEvent('annoyclicker-annoy', oper.node, {}); } }; +}; kukit.eventsGlobalRegistry.registerForAllEvents('annoyclicker', 'click', kukit.more_selectors.AnnoyClickerEvent, '__bind_click__', '__default_click__', 'Each'); kukit.eventsGlobalRegistry.registerForAllEvents('annoyclicker', 'annoy', kukit.more_selectors.AnnoyClickerEvent, null, null, 'Each'); kukit.eventsGlobalRegistry.registerForAllEvents('annoyclicker', 'doit', kukit.more_selectors.AnnoyClickerEvent, null, null, 'Each'); Modified: kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/more_selectors.kss ============================================================================== --- kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/more_selectors.kss (original) +++ kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/more_selectors.kss Tue Apr 15 11:36:37 2008 @@ -1,9 +1,6 @@ #log-reset a:click, #log-reset:click { action-client: clearChildNodes; clearChildNodes-kssSelector: #logger; - action-client: insertHTMLAsLastChild; - insertHTMLAsLastChild-kssSelector: #logger; - insertHTMLAsLastChild-html: "

"; } #button-one:annoyclicker-click(annoyMe) { @@ -17,9 +14,9 @@ } behaviour:annoyclicker-annoy(annoyMe) { - action-client: insertHTMLBefore; - insertHTMLBefore-kssSelector: #log-end; - insertHTMLBefore-html: "Keep trying until you get there. "; + action-client: insertHTMLAsLastChild; + insertHTMLAsLastChild-kssSelector: #logger; + insertHTMLAsLastChild-html: "Keep trying until you get there. "; } #button-two:annoyclicker-click(annoyYou) { @@ -32,7 +29,7 @@ } behaviour:annoyclicker-annoy(annoyYou) { - action-client: insertHTMLBefore; - insertHTMLBefore-kssSelector: #log-end; - insertHTMLBefore-html: "Keep trying until you get there, from the second button. "; + action-client: insertHTMLAsLastChild; + insertHTMLAsLastChild-kssSelector: #logger; + insertHTMLAsLastChild-html: "Keep trying until you get there, from the second button. "; } Modified: kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/more_selectors.pt ============================================================================== --- kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/more_selectors.pt (original) +++ kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/more_selectors.pt Tue Apr 15 11:36:37 2008 @@ -39,11 +39,6 @@ -

Log

-

Reset log

-

You clicked :

-
-

-
+

logger

Modified: kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/parameterfunction/configure.zcml ============================================================================== --- kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/parameterfunction/configure.zcml (original) +++ kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/parameterfunction/configure.zcml Tue Apr 15 11:36:37 2008 @@ -1,8 +1,20 @@ + + + + + + + + + + + + Modified: kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/parameterfunction/forms.kss ============================================================================== --- kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/parameterfunction/forms.kss (original) +++ kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/parameterfunction/forms.kss Tue Apr 15 11:36:37 2008 @@ -1,69 +1,60 @@ #text:click { - action-client: executeCommand; - executeCommand-name: replaceInnerHTML; - executeCommand-selector: "#target"; - executeCommand-html: currentFormVar(); + action-client: replaceInnerHTML; + replaceInnerHTML-kssSelector: "#target"; + replaceInnerHTML-html: currentFormVar(); } #text-by-name:click { - action-client: executeCommand; - executeCommand-name: replaceInnerHTML; - executeCommand-selector: "#target"; - executeCommand-html: currentFormVar(text-by-name); + action-client: replaceInnerHTML; + replaceInnerHTML-kssSelector: "#target"; + replaceInnerHTML-html: currentFormVar(text-by-name); } #text-by-kssname:click { - action-client: executeCommand; - executeCommand-name: replaceInnerHTML; - executeCommand-selector: "#target"; - executeCommand-html: currentFormVar(kssAttr(key1, true)); + action-client: replaceInnerHTML; + replaceInnerHTML-kssSelector: "#target"; + replaceInnerHTML-html: currentFormVar(kssAttr(key1, true)); } #textarea:click { - action-client: executeCommand; - executeCommand-name: replaceInnerHTML; - executeCommand-selector: "#target"; - executeCommand-html: currentFormVar(); + action-client: replaceInnerHTML; + replaceInnerHTML-kssSelector: "#target"; + replaceInnerHTML-html: currentFormVar(); } #textarea-by-name:click { - action-client: executeCommand; - executeCommand-name: replaceInnerHTML; - executeCommand-selector: "#target"; - executeCommand-html: currentFormVar("textarea-by-name"); + action-client: replaceInnerHTML; + replaceInnerHTML-kssSelector: "#target"; + replaceInnerHTML-html: currentFormVar("textarea-by-name"); } #radio1:click { - action-client: executeCommand; - executeCommand-name: replaceInnerHTML; - executeCommand-selector: "#target"; - executeCommand-html: currentFormVar(); + action-client: replaceInnerHTML; + replaceInnerHTML-kssSelector: "#target"; + replaceInnerHTML-html: currentFormVar(); } #radio2:click { - action-client: executeCommand; - executeCommand-name: replaceInnerHTML; - executeCommand-selector: "#target"; - executeCommand-html: currentFormVar(); + action-client: replaceInnerHTML; + replaceInnerHTML-kssSelector: "#target"; + replaceInnerHTML-html: currentFormVar(); } #radio-by-name:click { - action-client: executeCommand; - executeCommand-name: replaceInnerHTML; - executeCommand-selector: "#target"; - executeCommand-html: currentFormVar(radio-by-name); + action-client: replaceInnerHTML; + replaceInnerHTML-kssSelector: "#target"; + replaceInnerHTML-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-current:click { +#fullform-disabled:click { + action-client: setAttribute; + setAttribute-kssSelector: "#value1"; + setAttribute-name: disabled; + setAttribute-value: true; action-server: submitFullFormIntoRequest; submitFullFormIntoRequest-kssSubmitForm: currentForm(); } @@ -79,10 +70,9 @@ } #single-select:click { - action-client: executeCommand; - executeCommand-name: replaceInnerHTML; - executeCommand-selector: "#target"; - executeCommand-html: currentFormVar(single-select); + action-client: replaceInnerHTML; + replaceInnerHTML-kssSelector: "#target"; + replaceInnerHTML-html: currentFormVar(single-select); } #multiple-select:click { Modified: kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/parameterfunction/forms.pt ============================================================================== --- kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/parameterfunction/forms.pt (original) +++ kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/parameterfunction/forms.pt Tue Apr 15 11:36:37 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

@@ -169,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. @@ -183,19 +173,16 @@ Click the button.
Click me ! + Click me !
value1: - + value2: - +
listval: - - + +
listval with multiselect: recordval: - - + +
recordsval: - - - - + + + +
Deleted: /kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/parameterfunction/kssid.kss ============================================================================== --- /kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/parameterfunction/kssid.kss Tue Apr 15 11:36:37 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-service-layer-and-refactoring/kss/core/plugins/core/demo/parameterfunction/kssid.pt ============================================================================== --- /kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/parameterfunction/kssid.pt Tue Apr 15 11:36:37 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: - - - - -
-
- - - - Modified: kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/protocol.pt ============================================================================== --- kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/protocol.pt (original) +++ kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/protocol.pt Tue Apr 15 11:36:37 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 Copied: kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/selenium_tests/0_ecmaunit_tests.html (from r53709, 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/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/selenium_tests/0_ecmaunit_tests.html Tue Apr 15 11:36:37 2008 @@ -63,6 +63,26 @@ //div[@id='kukit.KssParserSelectorsTestCase']/div OK! + + assertText + //div[@id='kukit.InterfacesTestCase']/div + OK! + + + assertText + //div[@id='kukit.ServiceInterfacesTestCase']/div + OK! + + + assertText + //div[@id='kukit.PluginInterfacesTestCase']/div + OK! + + + assertText + //div[@id='kukit.ErrorsTestCase']/div + OK! + Modified: kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/selenium_tests/error_handling.html ============================================================================== --- kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/selenium_tests/error_handling.html (original) +++ kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/selenium_tests/error_handling.html Tue Apr 15 11:36:37 2008 @@ -29,6 +29,11 @@ Error handler activated + assertTextNotPresent + logger + Error handler activated + + click no_error_handler_empty_response @@ -39,6 +44,11 @@ Error handler activated + assertTextNotPresent + logger + Error handler activated + + click no_error_handler_error @@ -49,6 +59,11 @@ Error handler activated + assertTextNotPresent + logger + Error handler activated + + click no_error_handler_explicit_error @@ -59,6 +74,11 @@ Error handler activated. + assertTextNotPresent + logger + Error handler activated. + + click with_error_handler_no_error @@ -69,6 +89,11 @@ Error handler activated + assertTextNotPresent + logger + Error handler activated + + click css=#log-reset @@ -84,6 +109,11 @@ Error handler activated + assertTextNotPresent + logger + Error handler activated + + click css=#log-reset @@ -99,6 +129,11 @@ Error handler activated. + assertText + logger + Error handler activated. + + click css=#log-reset @@ -113,6 +148,11 @@ logger Error handler activated. + + assertText + logger + Error handler activated. + Modified: kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/selenium_tests/html_inserts.html ============================================================================== --- kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/selenium_tests/html_inserts.html (original) +++ kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/selenium_tests/html_inserts.html Tue Apr 15 11:36:37 2008 @@ -29,6 +29,11 @@ first: KSS for a life. + assertText + frame + first: KSS for a life. + + click insertAsLastChild @@ -39,6 +44,11 @@ first: KSS for a life.last: + assertText + frame + first: KSS for a life.last: + + click insert @@ -49,6 +59,11 @@ KSS for a life. + assertText + frame + KSS for a life. + + type text-to-insert before 1 @@ -64,6 +79,11 @@ KSS for a life. before 1 + assertText + css=h4+div + KSS for a life. before 1 + + type text-to-insert after 1 @@ -78,6 +98,11 @@ css=#frame+div KSS for a life. after 1 + + assertText + css=#frame+div + KSS for a life. after 1 + Deleted: /kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/selenium_tests/kss_selector_param.html ============================================================================== --- /kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/selenium_tests/kss_selector_param.html Tue Apr 15 11:36:37 2008 +++ (empty file) @@ -1,109 +0,0 @@ - - - -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
    - - Modified: kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/selenium_tests/more_selectors.html ============================================================================== --- kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/selenium_tests/more_selectors.html (original) +++ kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/selenium_tests/more_selectors.html Tue Apr 15 11:36:37 2008 @@ -25,7 +25,12 @@ waitForText - logger + logger + Keep trying until you get there. + + + assertText + logger Keep trying until you get there. @@ -35,7 +40,7 @@ assertText - logger + logger @@ -45,7 +50,12 @@ waitForText - logger + logger + Keep trying until you get there. + + + assertText + logger Keep trying until you get there. @@ -59,13 +69,23 @@ + assertTextPresent + Button button-one clicked. + + + click log-reset + waitForText + logger + + + assertText - logger + logger @@ -75,7 +95,12 @@ waitForText - logger + logger + Keep trying until you get there, from the second button. + + + assertText + logger Keep trying until you get there, from the second button. @@ -88,6 +113,11 @@ Button button-two clicked. + + assertTextPresent + Button button-two clicked. + + Deleted: /kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/selenium_tests/pf_forms.html ============================================================================== --- /kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/selenium_tests/pf_forms.html Tue Apr 15 11:36:37 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-service-layer-and-refactoring/kss/core/plugins/core/demo/selenium_tests/urlparam.html ============================================================================== --- /kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/selenium_tests/urlparam.html Tue Apr 15 11:36:37 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-service-layer-and-refactoring/kss/core/plugins/core/demo/zopeconfig.py ============================================================================== --- kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/zopeconfig.py (original) +++ kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/demo/zopeconfig.py Tue Apr 15 11:36:37 2008 @@ -18,6 +18,7 @@ implements(IResource) demos = ( + KSSDemo('', '', "loglevel.html", "Log Level"), KSSDemo('', '', "basic_commands.html", "Change tag content"), KSSDemo('', '', "two_selects.html", "Two selects"), KSSDemo('', '', "autoupdate.html", "Auto update"), @@ -33,10 +34,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('', '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"), Modified: kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/interfaces.py ============================================================================== --- kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/interfaces.py (original) +++ kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/plugins/core/interfaces.py Tue Apr 15 11:36:37 2008 @@ -76,7 +76,7 @@ def setStateVar(varname, value): """Set a client side kukit variable""" - def triggerEvent(name, **kw): + def continueEvent(name, allnodes=False, **kw): """Trigger an event on the client """ # TODO: explain a bit better what this does Modified: kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/tests/configure-online.zcml ============================================================================== --- kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/tests/configure-online.zcml (original) +++ kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/tests/configure-online.zcml Tue Apr 15 11:36:37 2008 @@ -12,4 +12,26 @@ permission="zope.Public" /> + + + + + + + + + + Modified: kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/tests/kukitresponse_test.pt ============================================================================== --- kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/tests/kukitresponse_test.pt (original) +++ kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/tests/kukitresponse_test.pt Tue Apr 15 11:36:37 2008 @@ -1,5 +1,5 @@ - Modified: kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/tests/test_browserview.py ============================================================================== --- kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/tests/test_browserview.py (original) +++ kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/tests/test_browserview.py Tue Apr 15 11:36:37 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/branch/ree-service-layer-and-refactoring/kss/core/tests/test_kssview_core.py ============================================================================== --- kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/tests/test_kssview_core.py (original) +++ kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/tests/test_kssview_core.py Tue Apr 15 11:36:37 2008 @@ -100,7 +100,7 @@ def _wrapped_commands(self, inline): header = textwrap.dedent(u'''\ - + ''') footer = textwrap.dedent('''\ Modified: kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/version.txt ============================================================================== --- kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/version.txt (original) +++ kukit/kss.core/branch/ree-service-layer-and-refactoring/kss/core/version.txt Tue Apr 15 11:36:37 2008 @@ -1 +1 @@ -1.4dev unreleased +1.5dev unreleased Modified: kukit/kss.core/branch/ree-service-layer-and-refactoring/setup.py ============================================================================== --- kukit/kss.core/branch/ree-service-layer-and-refactoring/setup.py (original) +++ kukit/kss.core/branch/ree-service-layer-and-refactoring/setup.py Tue Apr 15 11:36:37 2008 @@ -1,7 +1,7 @@ from setuptools import setup, find_packages import sys, os -version = '1.4' +version = '1.5' setup(name='kss.core', version=version, From reebalazs at codespeak.net Tue Apr 15 11:35:26 2008 From: reebalazs at codespeak.net (reebalazs at codespeak.net) Date: Tue, 15 Apr 2008 11:35:26 +0200 (CEST) Subject: [KSS-checkins] r53777 - in kukit/kukit.js/branch/ree-service-layer-and-refactoring: . 3rd_party 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 doc kukit tests Message-ID: <20080415093526.B425139B5B7@codespeak.net> Author: reebalazs Date: Tue Apr 15 11:35:22 2008 New Revision: 53777 Added: kukit/kukit.js/branch/ree-service-layer-and-refactoring/3rd_party/base2-dom-fp-20070816.js (contents, props changed) kukit/kukit.js/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/ kukit/kukit.js/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/dommer/ kukit/kukit.js/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/dommer/CHANGES.txt (contents, props changed) kukit/kukit.js/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/dommer/LICENSE.txt (contents, props changed) kukit/kukit.js/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/dommer/README.txt (contents, props changed) kukit/kukit.js/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/dommer/conftest.py (contents, props changed) kukit/kukit.js/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/dommer/dommer.js (contents, props changed) kukit/kukit.js/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/dommer/example.html (contents, props changed) kukit/kukit.js/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/dommer/run_tests.html (contents, props changed) kukit/kukit.js/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/dommer/test_dommer.js (contents, props changed) kukit/kukit.js/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/dommer/version.txt (contents, props changed) kukit/kukit.js/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/jsbase/ kukit/kukit.js/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/jsbase/LICENSE.txt (contents, props changed) kukit/kukit.js/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/jsbase/README.txt (contents, props changed) kukit/kukit.js/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/jsbase/__init__.py (contents, props changed) kukit/kukit.js/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/jsbase/array.js (contents, props changed) kukit/kukit.js/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/jsbase/conftest.py (contents, props changed) kukit/kukit.js/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/jsbase/exception.js (contents, props changed) kukit/kukit.js/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/jsbase/function.js (contents, props changed) kukit/kukit.js/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/jsbase/misclib.js (contents, props changed) kukit/kukit.js/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/jsbase/number.js (contents, props changed) kukit/kukit.js/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/jsbase/server.js (contents, props changed) kukit/kukit.js/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/jsbase/string.js (contents, props changed) kukit/kukit.js/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/jsbase/test_array.js (contents, props changed) kukit/kukit.js/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/jsbase/test_misclib.js (contents, props changed) kukit/kukit.js/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/jsbase/test_number.js (contents, props changed) kukit/kukit.js/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/jsbase/test_string.js (contents, props changed) kukit/kukit.js/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/jsbase/testing/ kukit/kukit.js/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/jsbase/testing.js (contents, props changed) kukit/kukit.js/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/jsbase/testing/findtests.js (contents, props changed) kukit/kukit.js/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/jsbase/testing/testbase.js (contents, props changed) kukit/kukit.js/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/jsbase/version.txt (contents, props changed) kukit/kukit.js/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/minisax.js/ kukit/kukit.js/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/minisax.js/LICENSE.txt (contents, props changed) kukit/kukit.js/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/minisax.js/conftest.py (contents, props changed) kukit/kukit.js/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/minisax.js/example.html (contents, props changed) kukit/kukit.js/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/minisax.js/helpers.js (contents, props changed) kukit/kukit.js/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/minisax.js/minisax.js (contents, props changed) kukit/kukit.js/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/minisax.js/test_minisax.js (contents, props changed) kukit/kukit.js/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/minisax.js/testhandler.js (contents, props changed) kukit/kukit.js/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/minisax.js/version.txt (contents, props changed) kukit/kukit.js/branch/ree-service-layer-and-refactoring/doc/draganddrop.kss.txt (contents, props changed) kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/values.js (contents, props changed) Modified: kukit/kukit.js/branch/ree-service-layer-and-refactoring/3rd_party/base2-dom-fp.js kukit/kukit.js/branch/ree-service-layer-and-refactoring/doc/HISTORY.txt kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/actionreg.js kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/commandprocessor.js kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/commandreg.js kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/dom.js kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/errors.js kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/eventreg.js kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/forms.js kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/interfaces.js kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/kssparser.js kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/kukit.js kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/oper.js kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/plugin.js kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/providerreg.js kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/requestmanager.js kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/resourcedata.js kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/selectorreg.js kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/serveraction.js kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/service.js kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/tokenizer.js kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/utils.js kukit/kukit.js/branch/ree-service-layer-and-refactoring/tests/runner.html kukit/kukit.js/branch/ree-service-layer-and-refactoring/tests/runtests.js kukit/kukit.js/branch/ree-service-layer-and-refactoring/tests/runtests.sh kukit/kukit.js/branch/ree-service-layer-and-refactoring/tests/test_interfaces.js kukit/kukit.js/branch/ree-service-layer-and-refactoring/tests/test_kssparser.js kukit/kukit.js/branch/ree-service-layer-and-refactoring/tests/test_requestmanager.js kukit/kukit.js/branch/ree-service-layer-and-refactoring/tests/test_tokenizer.js kukit/kukit.js/branch/ree-service-layer-and-refactoring/tests/test_utils.js kukit/kukit.js/branch/ree-service-layer-and-refactoring/tests/unittestUtilities.js kukit/kukit.js/branch/ree-service-layer-and-refactoring/version.txt Log: Rebase on current trunk. Added: kukit/kukit.js/branch/ree-service-layer-and-refactoring/3rd_party/base2-dom-fp-20070816.js ============================================================================== --- (empty file) +++ kukit/kukit.js/branch/ree-service-layer-and-refactoring/3rd_party/base2-dom-fp-20070816.js Tue Apr 15 11:35:22 2008 @@ -0,0 +1 @@ +eval(function(p,a,c,k,e,r){var b,e=function(c){return(c<62?'':e(parseInt(c/62)))+((c=c%62)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)a[c]=(r[b=e(c)]=k[c])?b:'\\x0';e=function(){return a.join('|')||'^'};k=[function(e){return r[e]}];c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b('+e(c)+')\\b','g'),k[c]);return p}('u U={1v:"U",4I:"0.9 (4J)",2c:q,1h:C o(1w){u 2c=1w;u 4K/*@3S=@3T@*/;u 30=1w.30;v(1w.31){u 1l=10.3U("span");u 1U=31.1U+" "+31.userAgent;v(!4K)1U=1U.D(/1m\\s[\\d.]+/,"");1U=1U.D(/([a-z])[\\s\\/](\\d)/4L,"$1$2");30=31.javaEnabled()&&30}t o(a){u r=L;u b=a.1V(0)=="!";v(b)a=a.J(1);a=a.D(/^([^\\(].*)$/,"/($1)/i.P(1U)");32{1W("r=!!"+a)}33(2d){}t!!(b^r)}}(q)};C o(1w){u 1h=U.1h;u J=2e.J||o(a){t 3V.X(a,3V.15(A,1))};u 34=1;u 3W=/^[1w$]/;u _3=/%([1-9])/g;u 4M=/^\\s\\s*/;u 4N=/\\s\\s*$/;u 4O=/([\\/()[\\]{}|*+-.,^$?\\\\])/g;u 3X=/1W/.P(1h)?/\\bbase\\b/:/./;u 4P=["V","1X","35"];u 4Q=R(C 19);u 3V=2e.M.J;u 2x=4R();o N(){v(q.V==N){q.x(A[0])}E{t x(A[0],N.M)}};N.M={V:N,y:o(){},x:1F(x)};N.2f=2g;N.36=1F(3Y);N.y=N.M.y;N.x=o(a,b){U.37=11;u c=C q;x(c,a);2y U.37;u d=c.V;o 1p(){v(!U.37){v(q.V==A.1G||q.3Z){q.3Z=11;d.X(q,A);2y q.3Z}E{t x(A[0],c)}}};c.V=1p;13(u i 1Y N)1p[i]=q[i];1p.2f=q;1p.y=1Z;1p.14=1Z;1p.M=c;x(1p,b);1p.14();t 1p};N.F=1F(2x),N.1a=o(a){v(1b(a,1H)){v(N.36(a)){a(q.M)}}E{x(q.M,a)}t q};N.14=1Z;u 2z=N.x({V:o(c,d){q.x(d);v(G q.14=="o")q.14();v(q.1v!="U"){U.40(q.1v,q);q.2h=H("u %1=U.%1;",q.1v)}u e=/[^\\s,]+/g;c.38=20.2A(q.38.1I(e),o(a,b){21(U[b],H("2z 18 found: \'%1\'.",b));t a+=U[b].2h},U.2h);c.1J=20.2A(q.1J.1I(e),o(a,b){q.2h+=H("u %2=%1.%2;",q.1v,b);t a+=H("v(!%1.%2)%1.%2=%2;",q.1v,b)},"",q)},1J:"",38:"",2h:"",1v:"",40:o(a,b){q[a]=b;q.1J+=","+a;q.2h+=H("u %1=%2.%1;",a,q.1v)}});u 41=N.x({V:o(){1K C 4S("Class cannot be instantiated.");}});u 1i=41.x(I,{x:o(c,d){u e=q.y();F(q,o(a,b){v(!1i[b]&&G a=="o"&&!3W.P(b)){x(e,b,a)}});e.1a(c);x(e,d);e.14();t e},1a:o(c){u d=q;v(G c=="o"){d.y(c);v(1i.36(c)){F(c,o(a,b){v(!1i[b]&&G a=="o"&&!3W.P(b)){x(d,b,a)}})}}E{2x(2g,c,o(a,b){v(b.1V(0)=="@"){v(1h(b.J(1))){F(a,A.1G)}}E v(!1i[b]&&G a=="o"){o 42(){t d[b].X(d,[q].1n(J(A)))};42.39=3X.P(a);x(d.M,b,42)}});x(d,c)}t d}});u 22=1i.x({4T:o(c,d,e){u f=11;32{q.F(c,o(a,b){f=d.15(e,a,b,c);v(!f)1K 2B;})}33(2d){v(2d!=2B)1K 2d;}t!!f},filter:o(d,e,f){u i=0;t q.2A(d,o(a,b,c){v(e.15(f,b,c,d)){a[i++]=b}t a},[])},invoke:o(b,c){u d=J(A,2);t q.2C(b,(G c=="o")?o(a){v(a!=I)t c.X(a,d)}:o(a){v(a!=I)t a[c].X(a,d)})},2C:o(c,d,e){u f=[],i=0;q.F(c,o(a,b){f[i++]=d.15(e,a,b,c)});t f},pluck:o(b,c){t q.2C(b,o(a){v(a!=I)t a[c]})},2A:o(c,d,e,f){u g=A.B>2;q.F(c,o(a,b){v(g){e=d.15(f,e,a,b,c)}E{e=a;g=11}});t e},some:o(c,d,e){t!q.4T(c,o(a,b){t!d.15(e,a,b,c)})}},{F:F});u 1c="#";u 3a=N.x({V:o(a){q.43(a)},1x:1F(1x),23:o(a){/*@3S@*//*@v(@3T<5.5)t $4U.23(q,1c+a);@E@*/t 1c+a 1Y q;/*@4V@*/},4W:o(a){t q[1c+a]},F:o(a,b){13(u c 1Y q)v(c.1V(0)==1c){a.15(b,q[c],c.J(1),q)}},43:o(d){F(A,o(c){F(c,o(a,b){q.24(b,a)},q)},q);t q},2i:o(a){u b=q[1c+a];2y q[1c+a];t b},24:o(a,b){v(A.B==1)b=a;t q[1c+a]=b},union:o(a){t q.43.X(q.1x(),A)}});3a.1a(22);u S="~";u 44=3a.x({V:o(a){q[S]=C 20;q.y(a)},3b:o(a,b){21(!q.23(a),"4X 4Y \'"+a+"\'.");t q.24.X(q,A)},1x:o(){u a=q.y();a[S]=q[S].1x();t a},2j:o(){t q[S].B},4Z:o(a){v(a<0)a+=q[S].B;u b=q[S][a];v(b!==1j)t q[1c+b]},F:o(a,b){u c=q[S];u d=c.B,i;13(i=0;i=0;i--){v(a[i]===b)t i}t-1},2C:o(c,d,e){u f=[];q.F(c,o(a,b){f[b]=d.15(e,a,b,c)});t f},2i:o(a,b){u c=q.25(a,b);v(c!=-1)q.3e(a,c);t b},3e:o(a,b){t q.3l(a,b,1)}}]);20.M.F=1F(3m);u String2=4b(R,"1V,charCodeAt,1n,25,5d,1I,D,search,J,1y,substr,5e,4c,3n",[{2k:2k}]);o 4b(c,d,e){u f=1i.x();F(d.1y(","),o(a){f[a]=3o(c.M[a])});F(e,f.1a,f);u g=o(){t f(q.V==f?c.X(c,A):A[0])};g.M=f.M;F(f,o(a,b){v(c[b]){f[b]=c[b];2y f.M[b]}g[b]=f[b]});t g};o y(a,b){t a.y.X(a,b)};o x(c,d){u e=A.1G;v(c!=I){v(A.B>2){u f=R(d);u g=A[2];v(f.1V(0)=="@"){t 1h(f.J(1))?e(c,g):c}v(c.x==e&&/^(y|x)$/.P(f)){t c}v(G g=="o"){u h=c[f];v(g!=h&&!3Y(g,h)){v(g.39||3X.P(g)){u i=g;o 39(){u a=q.y;q.y=h;u b=i.X(q,A);q.y=a;t b};g=39;g.method=i;g.2f=h}c[f]=g}}E{c[f]=g}}E v(d){u j=1b(d,1H)?1H:2g;v(U.37){F(4P,o(a){v(d[a]!=j.M[a]){e(c,a,d[a])}})}E{v(G c.x=="o"&&G c!="o"&&c.x!=e){e=3o(c.x)}}2x(j,d,o(a,b){e(c,b,a)})}}t c};o 3Y(a,b){1o(b&&b.2f!=a)b=b.2f;t!!b};v(G 2B=="1j"){2B=C 5f("2B")}o F(a,b,c,d){v(a==I)t;v(!d){v(1b(a,1H)){d=1H}E v(G a.F=="o"&&a.F!=A.1G){a.F(b,c);t}E v(G a.B=="49"){3m(a,b,c);t}}2x(d||2g,a,b,c)};o 3m(a,b,c){v(a==I)t;u d=a.B,i;v(G a=="27"){13(i=0;i1)?o(a,b,c,d){u e={};13(u f 1Y b){v(!e[f]&&a.M[f]===1j){e[f]=11;c.15(d,b[f],f,b)}}}:o(a,b,c,d){13(u e 1Y b){v(a.M[e]===1j){c.15(d,b[e],e,b)}}}};o 1b(a,b){4d(b,"o","5g \'1b\' operand.");/*@3S@*//*@v(@3T<5.1)v($4U.1b(a,b))t 11;@E@*/v(a instanceof b)t 11;/*@4V@*/v(4e(b))t L;v(4e(a.V))t b==2g;v(a!=I)3d(b){1d 2e:t!!(G a=="3i"&&a.2E&&a.3l);1d 1H:t!!(G a=="o"&&a.15);1d 19:t a.V.M.1X()==4Q;1d Date:t!!a.getTimezoneOffset;1d R:1d 57:1d Boolean:t G a==G b.M.35();1d 2g:t G a=="3i"&&G a.V=="o"}t L};o 4e(a){t a==N||N.36(a)};o 21(a,b,c){v(!a){1K C(c||5f)(b||"Assertion failed.");}};o 5h(a,b,c){v(b==I)b=a.1G.B;v(a.B<\\/5y>");10.1B.5z.onreadystatechange=o(){v(q.5A=="5B"){q.removeNode();1S.2t()}}}},"@4w":{14:o(){q.y();u a=setInterval(o(){v(/loaded|5B/.P(10.5A)){clearInterval(a);1S.2t()}},100)}}});u 4j=2p.x({"@!(10.2I.5C)":{5C:o(a,b,c){t b.currentStyle}}},{toCamelCase:o(c){t R(c).D(/\\-([a-z])/g,o(a,b){t b.3n()})}});u 3E=2p.x({"@!(1l.5D)":{5D:o(a,b){v(1b(b,2e)){b=b.2E(".")}t q.4x(a,"."+b)}},"@!(1l.4y)":{4x:o(a,b){t C Y(b).1e(a)},4y:o(a,b){t C Y(b).1e(a,1)}}});x(3E.M,{4x:o(b){t x(q.y(b),"1q",o(a){t 1N.O(q.y(a))})},4y:o(a){t 1N.O(q.y(a))}});u 4h=3E.x();u 4i=3E.x({"@!(1l.5E)":{5E:o(a,b){t C Y(b).P(a)}}});u 3s=N.x({V:o(b){b=b||[];q.B=b.B;q.1q=o(a){t b[a]}},B:0,F:o(a,b){u c=q.B;13(u i=0;i](\\*|[\\w-]+))([^: >+~]*)(:\\w+-Z(\\([^)]+\\))?)([^: >+~]*)/,"$1$3$6$4")},3G:I,3h:11,3H:o(b){u c=/\'/g;u d=q.5I=[];t q.5J(q.H(R(b).D(1s.5K,o(a){d.2D(a.J(1,-1).D(c,"\\\\\'"));t"\\5L"+d.B})))},H:o(a){t a.D(1s.5M,"$1").D(1s.5N,"$1 $2").D(1s.5O,"$1*$2")},5J:o(a){t q.2O.1e(a.D(1s.5P,">* "))},3F:o(a){t q.3G[a]||(q.3G[a]=q.2u(q.1e(q.3H(a))))},2u:o(c){u d=q.5I;t c.D(/\\5L(\\d+)/g,o(a,b){t d[b-1]})}},{5K:/(["\'])[^\\1]*\\1/g,5O:/([\\s>+~,]|[^(]\\+|^)([#.:@])/g,5N:/(^|,)([^\\s>+~])/g,5M:/\\s*([\\s>+~(),]|^|$)\\s*/g,5P:/\\s\\*\\s/g,2a:o(c,d,e,f,g,h,i,j){f=/1k/i.P(c)?f+"+1-":"";v(!isNaN(d))d="0n+"+d;E v(d=="even")d="2n";E v(d=="odd")d="2n+1";d=d.1y(/n\\+?/);u a=d[0]?(d[0]=="-")?-1:4a(d[0]):1;u b=4a(d[1])||0;u g=a<0;v(g){a=-a;v(a==1)b++}u l=H(a==0?"%3%7"+(f+b):"(%4%3-%2)%6%1%70%5%4%3>=%2",a,b,e,f,h,i,j);v(g)l=g+"("+l+")";t l}});Y.4A={"=":"%1==\'%2\'","!=":"%1!=\'%2\'","~=":/(^| )%1( |$)/,"|=":/^%1(-|$)/,"^=":/^%1/,"$=":/%1$/,"*=":/%1/};Y.4A[""]="%1!=I";Y.1t={"3I":"e%1.3I","17":"e%1[T.$2K].25(\'%2\')!=-1","2P":"e%1.2P","5Q":"T.5o(e%1)","4B":"e%1.2P===L","4C-Z":"!T.4o(e%1)","1k-Z":"!T.3w(e%1)","2Q-Z":"!T.4o(e%1)&&!T.3w(e%1)","4D":"e%1==T.2q(e%1).4q"};C o(1w){u 2b=1h("2b");u 2R=1h("2R");u 5R=1h("(1l.3J)");u 4E="u p%2=0,i%2,e%2,n%2=e%1.";u 34=5R?"e%1.3J":"1M(e%1)";u 5S="u g="+34+";v(!p[g]){p[g]=1;";u 5T="r[r.B]=e%1;v(s)t e%1;";u 5U="1Q=o(5V,s){2v++;u r=[],p={},1u=[%1],"+"d=T.2q(5V),c=d.body?\'3n\':\'1X\';";u 5W=2b?o(a,b){u c=a.1B[b]||I;v(!c||c.2M==b)t c;13(u i=0;i(\\\\*|[\\\\w-]+)":o(a,b){u c=2b&&1D;12=b=="*";u d=4E;d+=c?"children":"childNodes";v(!12&&c)d+=".4F(\'%3\')";d+=";13(i%2=0;(e%2=n%2[i%2]);i%2++){";v(12){d+="v(e%2.1A==1){";12=2R}E{v(!c)d+="v(e%2.2T==\'%3\'[c]()){"}t H(d,W++,1D=W,b)},"\\\\+(\\\\*|[\\\\w-]+)":o(a,b){u c="";v(12&&2b)c+="v(e%1.29!=\'!\'){";12=L;c+="e%1=T.3w(e%1);v(e%1";v(b!="*")c+="&&e%1.2T==\'%2\'[c]()";c+="){";t H(c,W,b)},"~(\\\\*|[\\\\w-]+)":o(a,b){u c="";v(12&&2b)c+="v(e%1.29!=\'!\'){";12=L;2S=2;c+="1o(e%1=e%1.3x){v(e%1.61==2v)2F;e%1.61=2v;v(";v(b=="*"){c+="e%1.1A==1";v(2R)c+="&&e%1.29!=\'!\'"}E c+="e%1.2T==\'%2\'[c]()";c+="){";t H(c,W,b)},"#([\\\\w-]+)":o(a,b){12=L;u c="v(e%1.2M==\'%2\'){";v(1D)c+=H("i%1=n%1.B;",1D);t H(c,W,b)},"\\\\.([\\\\w-]+)":o(a,b){12=L;1u.2D(C 19("(^|\\\\s)"+1L(b)+"(\\\\s|$)"));t H("v(1u[%2].P(e%1.1r)){",W,1u.B-1)},":18\\\\((\\\\*|[\\\\w-]+)?([^)]*)\\\\)":o(a,b,c){u d=(b&&b!="*")?H("v(e%1.2T==\'%2\'[c]()){",W,b):"";d+=2w.1e(c);t"v(!"+d.J(2,-1).D(/\\)\\{v\\(/g,"&&")+"){"},":2U(-1k)?-Z\\\\(([^)]+)\\\\)":o(a,b,c){12=L;b=H("e%1.2L.60",W);u d="v(p%1!==e%1.2L)";d+="p%1=5X(e%1.2L);u i=e%1.5Z;v(";t H(d,W)+1s.2a(a,c,"i",b,"!","&&","%","==")+"){"},":([\\\\w-]+)(\\\\(([^)]+)\\\\))?":o(a,b,c,d){t"v("+H(Y.1t[b],W,d||"")+"){"},"\\\\[([\\\\w-]+)\\\\s*([^=]?=)?\\\\s*([^\\\\]]*)\\\\]":o(a,b,c,d){u e=1z.$1T[b]||b;v(b=="62")e="1r";E v(b=="13")e="htmlFor";v(c){b=H("(e%1.%3||e%1.3L(\'%2\'))",W,b,e)}E{b=H("1z.3L(e%1,\'%2\')",W,b)}u f=Y.4A[c||""];v(1b(f,19)){1u.2D(C 19(H(f.3j,1L(2w.2u(d)))));f="1u[%2].P(%1)";d=1u.B-1}t"v("+H(f,b,d)+"){"}});Y.3F=o(a){v(!3K[a]){1u=[];1Q="";u b=2w.3H(a).1y(",");13(u i=0;i1?2:0;u c=2w.1e(b[i])||"1K;";v(12&&2b){c+=H("v(e%1.29!=\'!\'){",W)}u d=(2S>1)?5S:"";c+=H(d+5T,W);c+=2e(1I(c,/\\{/g).B+1).2E("}");1Q+=c}1W(H(5U,1u)+2w.2u(1Q)+"t s?I:r}");3K[a]=1Q}t 3K[a]}};u 2o=1s.x({V:o(){q.y(2o.4G);q.2O.55(1,"$1$4$3$6")},3H:o(a){t q.y(a).D(/,/g,"\\3M")},2u:o(a){t q.y(a.D(/\\[2V::\\*\\]/g,"").D(/(^|\\3M)\\//g,"$1./").D(/\\3M/g," | "))},"@63":{2u:o(a){t q.y(a.D(/1k\\(\\)/g,"2j(3N-1E::*)+2j(2W-1E::*)+1"))}}},{14:o(){q.2X.1T[""]="[@$1]";F(q.64,o(a,b){F(q.2X[b],a,q.4G)},q)},3O:{1t:{"4C-Z":"[1]","1k-Z":"[1k()]","2Q-Z":"[1k()=1]"}},4G:x({},{"@!4w":{"(^|\\\\3M) (\\\\*|[\\\\w-]+)#([\\\\w-]+)":"$1id(\'$3\')[2V::$2]","([ >])(\\\\*|[\\\\w-]+):([\\\\w-]+-Z(\\\\(([^)]+)\\\\))?)":o(a,b,c,d,e,f){u g=(b==" ")?"//*":"/*";v(/^2U/i.P(d)){g+=2a(d,f,"position()")}E{g+=2o.3O.1t[d]}t g+"[2V::"+c+"]"}}}),64:{65:o(a,b){q[1L(b)+"([\\\\w-]+)"]=a},66:o(a,b){q[1L(b)+"(\\\\*|[\\\\w-]+)"]=a},1T:o(a,b){q["\\\\[([\\\\w-]+)\\\\s*"+1L(b)+"\\\\s*([^\\\\]]*)\\\\]"]=a},1t:o(a,b){q[":"+b.D(/\\(\\)$/,"\\\\(([^)]+)\\\\)")]=a}},2X:{65:{"#":"[@2M=\'$1\'][1]",".":"[17(1n(\' \', at 62,\' \'),\' $1 \')]"},66:{" ":"/descendant::$1",">":"/Z::$1","+":"/2W-1E::*[1][2V::$1]","~":"/2W-1E::$1"},1T:{"*=":"[17(@$1,\'$2\')]","^=":"[starts-with(@$1,\'$2\')]","$=":"[5e(@$1,27-B(@$1)-27-B(\'$2\')+1)=\'$2\']","~=":"[17(1n(\' \',@$1,\' \'),\' $2 \')]","|=":"[17(1n(\'-\',@$1,\'-\'),\'-$2-\')]","!=":"[18(@$1=\'$2\')]","=":"[@$1=\'$2\']"},1t:{"5Q":"[18(Z::*) 3P 18(text())]","4C-Z":"[18(3N-1E::*)]","1k-Z":"[18(2W-1E::*)]","18()":68,"2U-Z()":2a,"2U-1k-Z()":2a,"2Q-Z":"[18(3N-1E::*) 3P 18(2W-1E::*)]","4D":"[18(parent::*)]"}},"@63":{14:o(){q.3O.1t["1k-Z"]=q.2X.1t["1k-Z"];q.3O.1t["2Q-Z"]=q.2X.1t["2Q-Z"];q.y()}}});o 68(a,b){u c=C 2o;t"[18("+c.1e(2k(b)).D(/\\[1\\]/g,"").D(/^(\\*|[\\w-]+)/,"[2V::$1]").D(/\\]\\[/g," 3P ").J(1,-1)+")]"};o 2a(a,b,c){t"["+1s.2a(a,b,c||"2j(3N-1E::*)+1","1k()","18"," 3P "," mod ","=")+"]"};Y.1a({2Y:o(){t Y.2Y(q)},"@(5F)":{$2N:o(a,b){v(Y.$2Z.P(q)){t q.y(a,b)}u c=T.2q(a);u d=b?9:7;u e=c.2N(q.2Y(),a,I,d,I);t b?e.singleNodeValue:e}},"@1m":{$2N:o(a,b){v(G a.69!="1j"&&!Y.$2Z.P(q)){u c=b?"selectSingleNode":"69";t a[c](q.2Y())}t q.y(a,b)}}});x(Y,{3Q:I,2Y:o(a){v(!q.3Q)q.3Q=C 2o;t q.3Q.3F(a)},$2Z:/:(3I|2P|4B|17)|^(#[\\w-]+\\s*)?\\w+$/,"@4w":{$2Z:/:(3I|2P|4B|17)|^(#[\\w-]+\\s*)?\\w+$|2U\\-/,"@!WebKit5":{$2Z:/./}}});u 28=3u.x({"@!(1l.6a)":{6a:o(a,b){v(T.17(a,b)){t 4|16}E v(T.17(b,a)){t 2|8}u c=28.3R(a);u d=28.3R(b);v(cd){t 2}t 0}}},{3R:o(a){u b=0;1o(a){b=T.5m(a)+"."+b;a=a.2L}t b},"@(1l.3J)":{3R:o(a){t a.3J}}});u 1O=28.x(I,{O:o(b){q.y(b);x(b,"3U",o(a){t 1N.O(q.y(a))});3q.O(b.2I);t b},"@!(10.2I)":{O:o(a){a.2I=T.3v(a);t q.y(a)}}});1O.3t("3U",2);u 1z=28.x({"@1m[67]":{3L:o(a,b,c){v(a.1r===1j||b=="6b"||b=="4v"){t q.y(a,b,2)}u d=a.getAttributeNode(b);t d&&d.6c?d.6d:I}},"@3z.+2H":{3L:o(a,b,c){v(a.1r===1j||b=="6b"||b=="4v"){t q.y(a,b,2)}u d=a.1T[q.$1T[b.4c()]||b];t d?d.6c?d.6d:I:q.y(a,b)}}},{$1T:{},"@3z.+2H":{14:o(){u a="colSpan,rowSpan,vAlign,dateTime,accessKey,tabIndex,encType,maxLength,readOnly,longDesc";u b=a.4c().1y(",");u c=a.1y(",");q.$1T=20.5b(b,c)}}});1z.3t("5H",3);3q.1a(4j);1O.1a(4h);1O.1a(3r);1O.1a(1g);1z.1a(4i);1z.1a(1g);u 4k=1O.x(I,{"@(10.4H===1j)":{O:o(b){q.y(b);b.4H=I;b.1C("focus",o(a){b.4H=a.3A},L);t b}}});u 2G=1z.x({addClass:o(a,b){v(!q.6e(a,b)){a.1r+=(a.1r?" ":"")+b;t b}},6e:o(a,b){u c=C 19("(^|\\\\s)"+b+"(\\\\s|$)");t c.P(a.1r)},removeClass:o(a,b){u c=C 19("(^|\\\\s)"+b+"(\\\\s|$)");a.1r=a.1r.D(c,"$2");t b}},{4l:{},4F:"*",x:o(){u b=y(q,A);u c=(b.4F||"").3n().1y(",");F(c,o(a){2G.4l[a]=b});t b},"@!(1l.3y)":{O:o(a){q.y(a);a.3y=T.2r(a);t a}}});1N.$=o(a,b){t C Y(a).1e(b,1)};1N.$$=o(a,b){t C Y(a).1e(b)};1W(q.1J)};',[],494,'||||||||||||||||||||||||function||this|||return|var|if||extend|base||arguments|length|new|replace|else|forEach|typeof|format|null|slice||false|prototype|Base|bind|test||String|_16|Traversal|base2|constructor|_35|apply|Selector|child|document|true|_36|for|init|call||contains|not|RegExp|implement|instanceOf|_15|case|exec|Item|EventTarget|detect|Module|undefined|last|element|MSIE|concat|while|klass|item|className|Parser|pseudoClasses|reg|name|_|copy|split|Element|nodeType|all|addEventListener|_37|sibling|delegate|callee|Function|match|exports|throw|rescape|assignID|DOM|Document|closures|fn|createEvent|DOMContentLoaded|attributes|platform|charAt|eval|toString|in|Undefined|Array2|assert|Enumerable|exists|store|indexOf|RegGrp|string|Node|tagName|_27|_28|global|error|Array|ancestor|Object|namespace|remove|count|trim|base2ID|Event||XPathParser|Interface|getDocument|getOwnerDocument|handleEvent|fire|unescape|indexed|parser|_10|delete|Namespace|reduce|StopIteration|map|push|join|break|HTMLElement|win|defaultView|isElement|TEXT|parentNode|id|evaluate|sorter|disabled|only|_29|_38|nodeName|nth|self|following|values|toXPath|NOT_XPATH|java|navigator|try|catch|_1|valueOf|ancestorOf|__prototyping|imports|_14|Hash|add|Math|switch|removeAt|sort|create|ignoreCase|object|source|partial|splice|_19|toUpperCase|unbind|type|AbstractView|DocumentEvent|StaticNodeList|createDelegate|Binding|getDefaultView|getNextElementSibling|nextSibling|ownerDocument|MSIE5|target|dispatchEvent|listener|fired|NodeSelector|parse|cache|escape|checked|sourceIndex|_39|getAttribute|x02|preceding|optimised|and|xpathParser|_41|cc_on|_jscript_version|createElement|_0|_2|_7|_12|__constructing|addName|Abstract|_13|merge|Collection|insertAt|default|reverse|replacement|number|parseInt|_18|toLowerCase|assertType|_20|_21|_22|DocumentSelector|ElementSelector|ViewCSS|HTMLDocument|bindings|attachEvent|continue|getPreviousElementSibling|isDocument|documentElement|initEvent|cancelable|returnValue|Events|src|KHTML|matchAll|matchSingle|b2_test|operators|enabled|first|root|_31|tags|rules|activeElement|version|alpha|jscript|gi|_4|_5|_6|_8|_9|_11|TypeError|every|Legacy|end|fetch|Duplicate|key|fetchAt|abs|Index|out|of|bounds|storeAt||Number|IGNORE|_17|index|combine|max|lastIndexOf|substring|Error|Invalid|assertArity|SyntaxError|_23|_24|_25|getNodeIndex|previousSibling|isEmpty|firstChild|parentWindow|bubbles|cancelBubble|preventDefault|on|event|createEventObject|load|script|__ready|readyState|complete|getComputedStyle|getElementsByClassName|matchesSelector|XPathResult|snapshotItem|setAttribute|_26|optimise|ESCAPE|x01|WHITESPACE|IMPLIED_SPACE|IMPLIED_ASTERISK|WILD_CARD|empty|_30|_32|_33|_34|e0|byId|register|b2_indexed|b2_index|b2_length|b2_adjacent|class|opera|types|identifiers|combinators||_40|selectNodes|compareDocumentPosition|href|specified|nodeValue|hasClass'.split('|'),0,{})); \ No newline at end of file Modified: kukit/kukit.js/branch/ree-service-layer-and-refactoring/3rd_party/base2-dom-fp.js ============================================================================== --- kukit/kukit.js/branch/ree-service-layer-and-refactoring/3rd_party/base2-dom-fp.js (original) +++ kukit/kukit.js/branch/ree-service-layer-and-refactoring/3rd_party/base2-dom-fp.js Tue Apr 15 11:35:22 2008 @@ -1 +1 @@ -eval(function(p,a,c,k,e,r){var b,e=function(c){return(c<62?'':e(parseInt(c/62)))+((c=c%62)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)a[c]=(r[b=e(c)]=k[c])?b:'\\x0';e=function(){return a.join('|')||'^'};k=[function(e){return r[e]}];c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b('+e(c)+')\\b','g'),k[c]);return p}('u U={1v:"U",4I:"0.9 (4J)",2c:q,1h:C o(1w){u 2c=1w;u 4K/*@3S=@3T@*/;u 30=1w.30;v(1w.31){u 1l=10.3U("span");u 1U=31.1U+" "+31.userAgent;v(!4K)1U=1U.D(/1m\\s[\\d.]+/,"");1U=1U.D(/([a-z])[\\s\\/](\\d)/4L,"$1$2");30=31.javaEnabled()&&30}t o(a){u r=L;u b=a.1V(0)=="!";v(b)a=a.J(1);a=a.D(/^([^\\(].*)$/,"/($1)/i.P(1U)");32{1W("r=!!"+a)}33(2d){}t!!(b^r)}}(q)};C o(1w){u 1h=U.1h;u J=2e.J||o(a){t 3V.X(a,3V.15(A,1))};u 34=1;u 3W=/^[1w$]/;u _3=/%([1-9])/g;u 4M=/^\\s\\s*/;u 4N=/\\s\\s*$/;u 4O=/([\\/()[\\]{}|*+-.,^$?\\\\])/g;u 3X=/1W/.P(1h)?/\\bbase\\b/:/./;u 4P=["V","1X","35"];u 4Q=R(C 19);u 3V=2e.M.J;u 2x=4R();o N(){v(q.V==N){q.x(A[0])}E{t x(A[0],N.M)}};N.M={V:N,y:o(){},x:1F(x)};N.2f=2g;N.36=1F(3Y);N.y=N.M.y;N.x=o(a,b){U.37=11;u c=C q;x(c,a);2y U.37;u d=c.V;o 1p(){v(!U.37){v(q.V==A.1G||q.3Z){q.3Z=11;d.X(q,A);2y q.3Z}E{t x(A[0],c)}}};c.V=1p;13(u i 1Y N)1p[i]=q[i];1p.2f=q;1p.y=1Z;1p.14=1Z;1p.M=c;x(1p,b);1p.14();t 1p};N.F=1F(2x),N.1a=o(a){v(1b(a,1H)){v(N.36(a)){a(q.M)}}E{x(q.M,a)}t q};N.14=1Z;u 2z=N.x({V:o(c,d){q.x(d);v(G q.14=="o")q.14();v(q.1v!="U"){U.40(q.1v,q);q.2h=H("u %1=U.%1;",q.1v)}u e=/[^\\s,]+/g;c.38=20.2A(q.38.1I(e),o(a,b){21(U[b],H("2z 18 found: \'%1\'.",b));t a+=U[b].2h},U.2h);c.1J=20.2A(q.1J.1I(e),o(a,b){q.2h+=H("u %2=%1.%2;",q.1v,b);t a+=H("v(!%1.%2)%1.%2=%2;",q.1v,b)},"",q)},1J:"",38:"",2h:"",1v:"",40:o(a,b){q[a]=b;q.1J+=","+a;q.2h+=H("u %1=%2.%1;",a,q.1v)}});u 41=N.x({V:o(){1K C 4S("Class cannot be instantiated.");}});u 1i=41.x(I,{x:o(c,d){u e=q.y();F(q,o(a,b){v(!1i[b]&&G a=="o"&&!3W.P(b)){x(e,b,a)}});e.1a(c);x(e,d);e.14();t e},1a:o(c){u d=q;v(G c=="o"){d.y(c);v(1i.36(c)){F(c,o(a,b){v(!1i[b]&&G a=="o"&&!3W.P(b)){x(d,b,a)}})}}E{2x(2g,c,o(a,b){v(b.1V(0)=="@"){v(1h(b.J(1))){F(a,A.1G)}}E v(!1i[b]&&G a=="o"){o 42(){t d[b].X(d,[q].1n(J(A)))};42.39=3X.P(a);x(d.M,b,42)}});x(d,c)}t d}});u 22=1i.x({4T:o(c,d,e){u f=11;32{q.F(c,o(a,b){f=d.15(e,a,b,c);v(!f)1K 2B;})}33(2d){v(2d!=2B)1K 2d;}t!!f},filter:o(d,e,f){u i=0;t q.2A(d,o(a,b,c){v(e.15(f,b,c,d)){a[i++]=b}t a},[])},invoke:o(b,c){u d=J(A,2);t q.2C(b,(G c=="o")?o(a){v(a!=I)t c.X(a,d)}:o(a){v(a!=I)t a[c].X(a,d)})},2C:o(c,d,e){u f=[],i=0;q.F(c,o(a,b){f[i++]=d.15(e,a,b,c)});t f},pluck:o(b,c){t q.2C(b,o(a){v(a!=I)t a[c]})},2A:o(c,d,e,f){u g=A.B>2;q.F(c,o(a,b){v(g){e=d.15(f,e,a,b,c)}E{e=a;g=11}});t e},some:o(c,d,e){t!q.4T(c,o(a,b){t!d.15(e,a,b,c)})}},{F:F});u 1c="#";u 3a=N.x({V:o(a){q.43(a)},1x:1F(1x),23:o(a){/*@3S@*//*@v(@3T<5.5)t $4U.23(q,1c+a);@E@*/t 1c+a 1Y q;/*@4V@*/},4W:o(a){t q[1c+a]},F:o(a,b){13(u c 1Y q)v(c.1V(0)==1c){a.15(b,q[c],c.J(1),q)}},43:o(d){F(A,o(c){F(c,o(a,b){q.24(b,a)},q)},q);t q},2i:o(a){u b=q[1c+a];2y q[1c+a];t b},24:o(a,b){v(A.B==1)b=a;t q[1c+a]=b},union:o(a){t q.43.X(q.1x(),A)}});3a.1a(22);u S="~";u 44=3a.x({V:o(a){q[S]=C 20;q.y(a)},3b:o(a,b){21(!q.23(a),"4X 4Y \'"+a+"\'.");t q.24.X(q,A)},1x:o(){u a=q.y();a[S]=q[S].1x();t a},2j:o(){t q[S].B},4Z:o(a){v(a<0)a+=q[S].B;u b=q[S][a];v(b!==1j)t q[1c+b]},F:o(a,b){u c=q[S];u d=c.B,i;13(i=0;i=0;i--){v(a[i]===b)t i}t-1},2C:o(c,d,e){u f=[];q.F(c,o(a,b){f[b]=d.15(e,a,b,c)});t f},2i:o(a,b){u c=q.25(a,b);v(c!=-1)q.3e(a,c);t b},3e:o(a,b){t q.3l(a,b,1)}}]);20.M.F=1F(3m);u String2=4b(R,"1V,charCodeAt,1n,25,5d,1I,D,search,J,1y,substr,5e,4c,3n",[{2k:2k}]);o 4b(c,d,e){u f=1i.x();F(d.1y(","),o(a){f[a]=3o(c.M[a])});F(e,f.1a,f);u g=o(){t f(q.V==f?c.X(c,A):A[0])};g.M=f.M;F(f,o(a,b){v(c[b]){f[b]=c[b];2y f.M[b]}g[b]=f[b]});t g};o y(a,b){t a.y.X(a,b)};o x(c,d){u e=A.1G;v(c!=I){v(A.B>2){u f=R(d);u g=A[2];v(f.1V(0)=="@"){t 1h(f.J(1))?e(c,g):c}v(c.x==e&&/^(y|x)$/.P(f)){t c}v(G g=="o"){u h=c[f];v(g!=h&&!3Y(g,h)){v(g.39||3X.P(g)){u i=g;o 39(){u a=q.y;q.y=h;u b=i.X(q,A);q.y=a;t b};g=39;g.method=i;g.2f=h}c[f]=g}}E{c[f]=g}}E v(d){u j=1b(d,1H)?1H:2g;v(U.37){F(4P,o(a){v(d[a]!=j.M[a]){e(c,a,d[a])}})}E{v(G c.x=="o"&&G c!="o"&&c.x!=e){e=3o(c.x)}}2x(j,d,o(a,b){e(c,b,a)})}}t c};o 3Y(a,b){1o(b&&b.2f!=a)b=b.2f;t!!b};v(G 2B=="1j"){2B=C 5f("2B")}o F(a,b,c,d){v(a==I)t;v(!d){v(1b(a,1H)){d=1H}E v(G a.F=="o"&&a.F!=A.1G){a.F(b,c);t}E v(G a.B=="49"){3m(a,b,c);t}}2x(d||2g,a,b,c)};o 3m(a,b,c){v(a==I)t;u d=a.B,i;v(G a=="27"){13(i=0;i1)?o(a,b,c,d){u e={};13(u f 1Y b){v(!e[f]&&a.M[f]===1j){e[f]=11;c.15(d,b[f],f,b)}}}:o(a,b,c,d){13(u e 1Y b){v(a.M[e]===1j){c.15(d,b[e],e,b)}}}};o 1b(a,b){4d(b,"o","5g \'1b\' operand.");/*@3S@*//*@v(@3T<5.1)v($4U.1b(a,b))t 11;@E@*/v(a instanceof b)t 11;/*@4V@*/v(4e(b))t L;v(4e(a.V))t b==2g;v(a!=I)3d(b){1d 2e:t!!(G a=="3i"&&a.2E&&a.3l);1d 1H:t!!(G a=="o"&&a.15);1d 19:t a.V.M.1X()==4Q;1d Date:t!!a.getTimezoneOffset;1d R:1d 57:1d Boolean:t G a==G b.M.35();1d 2g:t G a=="3i"&&G a.V=="o"}t L};o 4e(a){t a==N||N.36(a)};o 21(a,b,c){v(!a){1K C(c||5f)(b||"Assertion failed.");}};o 5h(a,b,c){v(b==I)b=a.1G.B;v(a.B<\\/5y>");10.1B.5z.onreadystatechange=o(){v(q.5A=="5B"){q.removeNode();1S.2t()}}}},"@4w":{14:o(){q.y();u a=setInterval(o(){v(/loaded|5B/.P(10.5A)){clearInterval(a);1S.2t()}},100)}}});u 4j=2p.x({"@!(10.2I.5C)":{5C:o(a,b,c){t b.currentStyle}}},{toCamelCase:o(c){t R(c).D(/\\-([a-z])/g,o(a,b){t b.3n()})}});u 3E=2p.x({"@!(1l.5D)":{5D:o(a,b){v(1b(b,2e)){b=b.2E(".")}t q.4x(a,"."+b)}},"@!(1l.4y)":{4x:o(a,b){t C Y(b).1e(a)},4y:o(a,b){t C Y(b).1e(a,1)}}});x(3E.M,{4x:o(b){t x(q.y(b),"1q",o(a){t 1N.O(q.y(a))})},4y:o(a){t 1N.O(q.y(a))}});u 4h=3E.x();u 4i=3E.x({"@!(1l.5E)":{5E:o(a,b){t C Y(b).P(a)}}});u 3s=N.x({V:o(b){b=b||[];q.B=b.B;q.1q=o(a){t b[a]}},B:0,F:o(a,b){u c=q.B;13(u i=0;i](\\*|[\\w-]+))([^: >+~]*)(:\\w+-Z(\\([^)]+\\))?)([^: >+~]*)/,"$1$3$6$4")},3G:I,3h:11,3H:o(b){u c=/\'/g;u d=q.5I=[];t q.5J(q.H(R(b).D(1s.5K,o(a){d.2D(a.J(1,-1).D(c,"\\\\\'"));t"\\5L"+d.B})))},H:o(a){t a.D(1s.5M,"$1").D(1s.5N,"$1 $2").D(1s.5O,"$1*$2")},5J:o(a){t q.2O.1e(a.D(1s.5P,">* "))},3F:o(a){t q.3G[a]||(q.3G[a]=q.2u(q.1e(q.3H(a))))},2u:o(c){u d=q.5I;t c.D(/\\5L(\\d+)/g,o(a,b){t d[b-1]})}},{5K:/(["\'])[^\\1]*\\1/g,5O:/([\\s>+~,]|[^(]\\+|^)([#.:@])/g,5N:/(^|,)([^\\s>+~])/g,5M:/\\s*([\\s>+~(),]|^|$)\\s*/g,5P:/\\s\\*\\s/g,2a:o(c,d,e,f,g,h,i,j){f=/1k/i.P(c)?f+"+1-":"";v(!isNaN(d))d="0n+"+d;E v(d=="even")d="2n";E v(d=="odd")d="2n+1";d=d.1y(/n\\+?/);u a=d[0]?(d[0]=="-")?-1:4a(d[0]):1;u b=4a(d[1])||0;u g=a<0;v(g){a=-a;v(a==1)b++}u l=H(a==0?"%3%7"+(f+b):"(%4%3-%2)%6%1%70%5%4%3>=%2",a,b,e,f,h,i,j);v(g)l=g+"("+l+")";t l}});Y.4A={"=":"%1==\'%2\'","!=":"%1!=\'%2\'","~=":/(^| )%1( |$)/,"|=":/^%1(-|$)/,"^=":/^%1/,"$=":/%1$/,"*=":/%1/};Y.4A[""]="%1!=I";Y.1t={"3I":"e%1.3I","17":"e%1[T.$2K].25(\'%2\')!=-1","2P":"e%1.2P","5Q":"T.5o(e%1)","4B":"e%1.2P===L","4C-Z":"!T.4o(e%1)","1k-Z":"!T.3w(e%1)","2Q-Z":"!T.4o(e%1)&&!T.3w(e%1)","4D":"e%1==T.2q(e%1).4q"};C o(1w){u 2b=1h("2b");u 2R=1h("2R");u 5R=1h("(1l.3J)");u 4E="u p%2=0,i%2,e%2,n%2=e%1.";u 34=5R?"e%1.3J":"1M(e%1)";u 5S="u g="+34+";v(!p[g]){p[g]=1;";u 5T="r[r.B]=e%1;v(s)t e%1;";u 5U="1Q=o(5V,s){2v++;u r=[],p={},1u=[%1],"+"d=T.2q(5V),c=d.body?\'3n\':\'1X\';";u 5W=2b?o(a,b){u c=a.1B[b]||I;v(!c||c.2M==b)t c;13(u i=0;i(\\\\*|[\\\\w-]+)":o(a,b){u c=2b&&1D;12=b=="*";u d=4E;d+=c?"children":"childNodes";v(!12&&c)d+=".4F(\'%3\')";d+=";13(i%2=0;(e%2=n%2[i%2]);i%2++){";v(12){d+="v(e%2.1A==1){";12=2R}E{v(!c)d+="v(e%2.2T==\'%3\'[c]()){"}t H(d,W++,1D=W,b)},"\\\\+(\\\\*|[\\\\w-]+)":o(a,b){u c="";v(12&&2b)c+="v(e%1.29!=\'!\'){";12=L;c+="e%1=T.3w(e%1);v(e%1";v(b!="*")c+="&&e%1.2T==\'%2\'[c]()";c+="){";t H(c,W,b)},"~(\\\\*|[\\\\w-]+)":o(a,b){u c="";v(12&&2b)c+="v(e%1.29!=\'!\'){";12=L;2S=2;c+="1o(e%1=e%1.3x){v(e%1.61==2v)2F;e%1.61=2v;v(";v(b=="*"){c+="e%1.1A==1";v(2R)c+="&&e%1.29!=\'!\'"}E c+="e%1.2T==\'%2\'[c]()";c+="){";t H(c,W,b)},"#([\\\\w-]+)":o(a,b){12=L;u c="v(e%1.2M==\'%2\'){";v(1D)c+=H("i%1=n%1.B;",1D);t H(c,W,b)},"\\\\.([\\\\w-]+)":o(a,b){12=L;1u.2D(C 19("(^|\\\\s)"+1L(b)+"(\\\\s|$)"));t H("v(1u[%2].P(e%1.1r)){",W,1u.B-1)},":18\\\\((\\\\*|[\\\\w-]+)?([^)]*)\\\\)":o(a,b,c){u d=(b&&b!="*")?H("v(e%1.2T==\'%2\'[c]()){",W,b):"";d+=2w.1e(c);t"v(!"+d.J(2,-1).D(/\\)\\{v\\(/g,"&&")+"){"},":2U(-1k)?-Z\\\\(([^)]+)\\\\)":o(a,b,c){12=L;b=H("e%1.2L.60",W);u d="v(p%1!==e%1.2L)";d+="p%1=5X(e%1.2L);u i=e%1.5Z;v(";t H(d,W)+1s.2a(a,c,"i",b,"!","&&","%","==")+"){"},":([\\\\w-]+)(\\\\(([^)]+)\\\\))?":o(a,b,c,d){t"v("+H(Y.1t[b],W,d||"")+"){"},"\\\\[([\\\\w-]+)\\\\s*([^=]?=)?\\\\s*([^\\\\]]*)\\\\]":o(a,b,c,d){u e=1z.$1T[b]||b;v(b=="62")e="1r";E v(b=="13")e="htmlFor";v(c){b=H("(e%1.%3||e%1.3L(\'%2\'))",W,b,e)}E{b=H("1z.3L(e%1,\'%2\')",W,b)}u f=Y.4A[c||""];v(1b(f,19)){1u.2D(C 19(H(f.3j,1L(2w.2u(d)))));f="1u[%2].P(%1)";d=1u.B-1}t"v("+H(f,b,d)+"){"}});Y.3F=o(a){v(!3K[a]){1u=[];1Q="";u b=2w.3H(a).1y(",");13(u i=0;i1?2:0;u c=2w.1e(b[i])||"1K;";v(12&&2b){c+=H("v(e%1.29!=\'!\'){",W)}u d=(2S>1)?5S:"";c+=H(d+5T,W);c+=2e(1I(c,/\\{/g).B+1).2E("}");1Q+=c}1W(H(5U,1u)+2w.2u(1Q)+"t s?I:r}");3K[a]=1Q}t 3K[a]}};u 2o=1s.x({V:o(){q.y(2o.4G);q.2O.55(1,"$1$4$3$6")},3H:o(a){t q.y(a).D(/,/g,"\\3M")},2u:o(a){t q.y(a.D(/\\[2V::\\*\\]/g,"").D(/(^|\\3M)\\//g,"$1./").D(/\\3M/g," | "))},"@63":{2u:o(a){t q.y(a.D(/1k\\(\\)/g,"2j(3N-1E::*)+2j(2W-1E::*)+1"))}}},{14:o(){q.2X.1T[""]="[@$1]";F(q.64,o(a,b){F(q.2X[b],a,q.4G)},q)},3O:{1t:{"4C-Z":"[1]","1k-Z":"[1k()]","2Q-Z":"[1k()=1]"}},4G:x({},{"@!4w":{"(^|\\\\3M) (\\\\*|[\\\\w-]+)#([\\\\w-]+)":"$1id(\'$3\')[2V::$2]","([ >])(\\\\*|[\\\\w-]+):([\\\\w-]+-Z(\\\\(([^)]+)\\\\))?)":o(a,b,c,d,e,f){u g=(b==" ")?"//*":"/*";v(/^2U/i.P(d)){g+=2a(d,f,"position()")}E{g+=2o.3O.1t[d]}t g+"[2V::"+c+"]"}}}),64:{65:o(a,b){q[1L(b)+"([\\\\w-]+)"]=a},66:o(a,b){q[1L(b)+"(\\\\*|[\\\\w-]+)"]=a},1T:o(a,b){q["\\\\[([\\\\w-]+)\\\\s*"+1L(b)+"\\\\s*([^\\\\]]*)\\\\]"]=a},1t:o(a,b){q[":"+b.D(/\\(\\)$/,"\\\\(([^)]+)\\\\)")]=a}},2X:{65:{"#":"[@2M=\'$1\'][1]",".":"[17(1n(\' \', at 62,\' \'),\' $1 \')]"},66:{" ":"/descendant::$1",">":"/Z::$1","+":"/2W-1E::*[1][2V::$1]","~":"/2W-1E::$1"},1T:{"*=":"[17(@$1,\'$2\')]","^=":"[starts-with(@$1,\'$2\')]","$=":"[5e(@$1,27-B(@$1)-27-B(\'$2\')+1)=\'$2\']","~=":"[17(1n(\' \',@$1,\' \'),\' $2 \')]","|=":"[17(1n(\'-\',@$1,\'-\'),\'-$2-\')]","!=":"[18(@$1=\'$2\')]","=":"[@$1=\'$2\']"},1t:{"5Q":"[18(Z::*) 3P 18(text())]","4C-Z":"[18(3N-1E::*)]","1k-Z":"[18(2W-1E::*)]","18()":68,"2U-Z()":2a,"2U-1k-Z()":2a,"2Q-Z":"[18(3N-1E::*) 3P 18(2W-1E::*)]","4D":"[18(parent::*)]"}},"@63":{14:o(){q.3O.1t["1k-Z"]=q.2X.1t["1k-Z"];q.3O.1t["2Q-Z"]=q.2X.1t["2Q-Z"];q.y()}}});o 68(a,b){u c=C 2o;t"[18("+c.1e(2k(b)).D(/\\[1\\]/g,"").D(/^(\\*|[\\w-]+)/,"[2V::$1]").D(/\\]\\[/g," 3P ").J(1,-1)+")]"};o 2a(a,b,c){t"["+1s.2a(a,b,c||"2j(3N-1E::*)+1","1k()","18"," 3P "," mod ","=")+"]"};Y.1a({2Y:o(){t Y.2Y(q)},"@(5F)":{$2N:o(a,b){v(Y.$2Z.P(q)){t q.y(a,b)}u c=T.2q(a);u d=b?9:7;u e=c.2N(q.2Y(),a,I,d,I);t b?e.singleNodeValue:e}},"@1m":{$2N:o(a,b){v(G a.69!="1j"&&!Y.$2Z.P(q)){u c=b?"selectSingleNode":"69";t a[c](q.2Y())}t q.y(a,b)}}});x(Y,{3Q:I,2Y:o(a){v(!q.3Q)q.3Q=C 2o;t q.3Q.3F(a)},$2Z:/:(3I|2P|4B|17)|^(#[\\w-]+\\s*)?\\w+$/,"@4w":{$2Z:/:(3I|2P|4B|17)|^(#[\\w-]+\\s*)?\\w+$|2U\\-/,"@!WebKit5":{$2Z:/./}}});u 28=3u.x({"@!(1l.6a)":{6a:o(a,b){v(T.17(a,b)){t 4|16}E v(T.17(b,a)){t 2|8}u c=28.3R(a);u d=28.3R(b);v(cd){t 2}t 0}}},{3R:o(a){u b=0;1o(a){b=T.5m(a)+"."+b;a=a.2L}t b},"@(1l.3J)":{3R:o(a){t a.3J}}});u 1O=28.x(I,{O:o(b){q.y(b);x(b,"3U",o(a){t 1N.O(q.y(a))});3q.O(b.2I);t b},"@!(10.2I)":{O:o(a){a.2I=T.3v(a);t q.y(a)}}});1O.3t("3U",2);u 1z=28.x({"@1m[67]":{3L:o(a,b,c){v(a.1r===1j||b=="6b"||b=="4v"){t q.y(a,b,2)}u d=a.getAttributeNode(b);t d&&d.6c?d.6d:I}},"@3z.+2H":{3L:o(a,b,c){v(a.1r===1j||b=="6b"||b=="4v"){t q.y(a,b,2)}u d=a.1T[q.$1T[b.4c()]||b];t d?d.6c?d.6d:I:q.y(a,b)}}},{$1T:{},"@3z.+2H":{14:o(){u a="colSpan,rowSpan,vAlign,dateTime,accessKey,tabIndex,encType,maxLength,readOnly,longDesc";u b=a.4c().1y(",");u c=a.1y(",");q.$1T=20.5b(b,c)}}});1z.3t("5H",3);3q.1a(4j);1O.1a(4h);1O.1a(3r);1O.1a(1g);1z.1a(4i);1z.1a(1g);u 4k=1O.x(I,{"@(10.4H===1j)":{O:o(b){q.y(b);b.4H=I;b.1C("focus",o(a){b.4H=a.3A},L);t b}}});u 2G=1z.x({addClass:o(a,b){v(!q.6e(a,b)){a.1r+=(a.1r?" ":"")+b;t b}},6e:o(a,b){u c=C 19("(^|\\\\s)"+b+"(\\\\s|$)");t c.P(a.1r)},removeClass:o(a,b){u c=C 19("(^|\\\\s)"+b+"(\\\\s|$)");a.1r=a.1r.D(c,"$2");t b}},{4l:{},4F:"*",x:o(){u b=y(q,A);u c=(b.4F||"").3n().1y(",");F(c,o(a){2G.4l[a]=b});t b},"@!(1l.3y)":{O:o(a){q.y(a);a.3y=T.2r(a);t a}}});1N.$=o(a,b){t C Y(a).1e(b,1)};1N.$$=o(a,b){t C Y(a).1e(b)};1W(q.1J)};',[],494,'||||||||||||||||||||||||function||this|||return|var|if||extend|base||arguments|length|new|replace|else|forEach|typeof|format|null|slice||false|prototype|Base|bind|test||String|_16|Traversal|base2|constructor|_35|apply|Selector|child|document|true|_36|for|init|call||contains|not|RegExp|implement|instanceOf|_15|case|exec|Item|EventTarget|detect|Module|undefined|last|element|MSIE|concat|while|klass|item|className|Parser|pseudoClasses|reg|name|_|copy|split|Element|nodeType|all|addEventListener|_37|sibling|delegate|callee|Function|match|exports|throw|rescape|assignID|DOM|Document|closures|fn|createEvent|DOMContentLoaded|attributes|platform|charAt|eval|toString|in|Undefined|Array2|assert|Enumerable|exists|store|indexOf|RegGrp|string|Node|tagName|_27|_28|global|error|Array|ancestor|Object|namespace|remove|count|trim|base2ID|Event||XPathParser|Interface|getDocument|getOwnerDocument|handleEvent|fire|unescape|indexed|parser|_10|delete|Namespace|reduce|StopIteration|map|push|join|break|HTMLElement|win|defaultView|isElement|TEXT|parentNode|id|evaluate|sorter|disabled|only|_29|_38|nodeName|nth|self|following|values|toXPath|NOT_XPATH|java|navigator|try|catch|_1|valueOf|ancestorOf|__prototyping|imports|_14|Hash|add|Math|switch|removeAt|sort|create|ignoreCase|object|source|partial|splice|_19|toUpperCase|unbind|type|AbstractView|DocumentEvent|StaticNodeList|createDelegate|Binding|getDefaultView|getNextElementSibling|nextSibling|ownerDocument|MSIE5|target|dispatchEvent|listener|fired|NodeSelector|parse|cache|escape|checked|sourceIndex|_39|getAttribute|x02|preceding|optimised|and|xpathParser|_41|cc_on|_jscript_version|createElement|_0|_2|_7|_12|__constructing|addName|Abstract|_13|merge|Collection|insertAt|default|reverse|replacement|number|parseInt|_18|toLowerCase|assertType|_20|_21|_22|DocumentSelector|ElementSelector|ViewCSS|HTMLDocument|bindings|attachEvent|continue|getPreviousElementSibling|isDocument|documentElement|initEvent|cancelable|returnValue|Events|src|KHTML|matchAll|matchSingle|b2_test|operators|enabled|first|root|_31|tags|rules|activeElement|version|alpha|jscript|gi|_4|_5|_6|_8|_9|_11|TypeError|every|Legacy|end|fetch|Duplicate|key|fetchAt|abs|Index|out|of|bounds|storeAt||Number|IGNORE|_17|index|combine|max|lastIndexOf|substring|Error|Invalid|assertArity|SyntaxError|_23|_24|_25|getNodeIndex|previousSibling|isEmpty|firstChild|parentWindow|bubbles|cancelBubble|preventDefault|on|event|createEventObject|load|script|__ready|readyState|complete|getComputedStyle|getElementsByClassName|matchesSelector|XPathResult|snapshotItem|setAttribute|_26|optimise|ESCAPE|x01|WHITESPACE|IMPLIED_SPACE|IMPLIED_ASTERISK|WILD_CARD|empty|_30|_32|_33|_34|e0|byId|register|b2_indexed|b2_index|b2_length|b2_adjacent|class|opera|types|identifiers|combinators||_40|selectNodes|compareDocumentPosition|href|specified|nodeValue|hasClass'.split('|'),0,{})); \ No newline at end of file +var base2={name:"base2",version:"1.0 (beta 2)",exports:"Base,Package,Abstract,Module,Enumerable,Map,Collection,RegGrp,"+"assert,assertArity,assertType,assignID,copy,detect,extend,"+"forEach,format,global,instanceOf,match,rescape,slice,trim,typeOf,"+"I,K,Undefined,Null,True,False,bind,delegate,flip,not,unbind",global:this,detect:new function(_){var global=_;var jscript=NaN/*@cc_on||@_jscript_version@*/;var java=_.java?true:false;if(_.navigator){var MSIE=/MSIE[\d.]+/g;var element=document.createElement("span");var userAgent=navigator.userAgent.replace(/([a-z])[\s\/](\d)/gi,"$1$2");if(!jscript)userAgent=userAgent.replace(MSIE,"");if(MSIE.test(userAgent))userAgent=userAgent.match(MSIE)[0]+" "+userAgent.replace(MSIE,"");userAgent=navigator.platform+" "+userAgent;java&=navigator.javaEnabled()}return function(a){var r=false;var b=a.charAt(0)=="!";if(b)a=a.slice(1);if(a.charAt(0)=="("){try{eval("r=!!"+a)}catch(e){}}else{r=new RegExp("("+a+")","i").test(userAgent)}return!!(b^r)}}(this)};new function(_){var _0="function base(o,a){return o.base.apply(o,a)};";eval(_0);var detect=base2.detect;var Undefined=K(),Null=K(null),True=K(true),False=K(false);var _1=/%([1-9])/g;var _2=/^\s\s*/;var _3=/\s\s*$/;var _4=/([\/()[\]{}|*+-.,^$?\\])/g;var _5=/eval/.test(detect)?/\bbase\s*\(/:/.*/;var _6=["constructor","toString","valueOf"];var _7=detect("(jscript)")?new RegExp("^"+rescape(isNaN).replace(/isNaN/,"\\w+")+"$"):{test:False};var _8=1;var _9=Array.prototype.slice;var slice=Array.slice||function(a){return _9.apply(a,_9.call(arguments,1))};_10();var _11=function(a,b){base2.__prototyping=this.prototype;var c=new this;extend(c,a);delete base2.__prototyping;var d=c.constructor;function e(){if(!base2.__prototyping){if(this.constructor==arguments.callee||this.__constructing){this.__constructing=true;d.apply(this,arguments);delete this.__constructing}else{return extend(arguments[0],c)}}return this};c.constructor=e;for(var i in Base)e[i]=this[i];e.ancestor=this;e.base=Undefined;e.init=Undefined;extend(e,b);e.prototype=c;e.init();return e};var Base=_11.call(Object,{constructor:function(){if(arguments.length>0){this.extend(arguments[0])}},base:function(){},extend:delegate(extend)},Base={ancestorOf:delegate(_12),extend:_11,forEach:delegate(_10),implement:function(a){if(typeof a=="function"){if(_12(Base,a)){a(this.prototype)}}else{extend(this.prototype,a)}return this}});var Package=Base.extend({constructor:function(d,e){this.extend(e);if(this.init)this.init();if(this.name!="base2"){if(!this.parent)this.parent=base2;this.parent.addName(this.name,this);this.namespace=format("var %1=%2;",this.name,String(this).slice(1,-1))}var f=/[^\s,]+/g;if(d){d.imports=Array2.reduce(this.imports.match(f),function(a,b){eval("var ns=base2."+b);assert(ns,format("Package not found: '%1'.",b),ReferenceError);return a+=ns.namespace},_0+base2.namespace+JavaScript.namespace);d.exports=Array2.reduce(this.exports.match(f),function(a,b){var c=this.name+"."+b;this.namespace+="var "+b+"="+c+";";return a+="if(!"+c+")"+c+"="+b+";"},"",this)}},exports:"",imports:"",name:"",namespace:"",parent:null,addName:function(a,b){if(!this[a]){this[a]=b;this.exports+=","+a;this.namespace+=format("var %1=%2.%1;",a,this.name)}},addPackage:function(a){this.addName(a,new Package(null,{name:a,parent:this}))},toString:function(){return format("[%1]",this.parent?String(this.parent).slice(1,-1)+"."+this.name:this.name)}});var Abstract=Base.extend({constructor:function(){throw new TypeError("Class cannot be instantiated.");}});var Module=Abstract.extend(null,{extend:function(a,b){var c=this.base();c.implement(this);c.implement(a);extend(c,b);c.init();return c},implement:function(d){var e=this;if(typeof d=="function"){if(!_12(d,e)){this.base(d)}if(_12(Module,d)){forEach(d,function(a,b){if(!e[b]){if(typeof a=="function"&&a.call&&d.prototype[b]){a=function(){return d[b].apply(d,arguments)}}e[b]=a}})}}else{extend(e,d);_10(Object,d,function(b,c){if(c.charAt(0)=="@"){if(detect(c.slice(1))){forEach(b,arguments.callee)}}else if(typeof b=="function"&&b.call){e.prototype[c]=function(){var a=_9.call(arguments);a.unshift(this);return e[c].apply(e,a)}}})}return e}});var Enumerable=Module.extend({every:function(c,d,e){var f=true;try{this.forEach(c,function(a,b){f=d.call(e,a,b,c);if(!f)throw StopIteration;})}catch(error){if(error!=StopIteration)throw error;}return!!f},filter:function(d,e,f){var i=0;return this.reduce(d,function(a,b,c){if(e.call(f,b,c,d)){a[i++]=b}return a},[])},invoke:function(b,c){var d=_9.call(arguments,2);return this.map(b,(typeof c=="function")?function(a){return(a==null)?undefined:c.apply(a,d)}:function(a){return(a==null)?undefined:a[c].apply(a,d)})},map:function(c,d,e){var f=[],i=0;this.forEach(c,function(a,b){f[i++]=d.call(e,a,b,c)});return f},pluck:function(b,c){return this.map(b,function(a){return(a==null)?undefined:a[c]})},reduce:function(c,d,e,f){var g=arguments.length>2;this.forEach(c,function(a,b){if(g){e=d.call(f,e,a,b,c)}else{e=a;g=true}});return e},some:function(a,b,c){return!this.every(a,not(b),c)}},{forEach:forEach});var _13="#";var Map=Base.extend({constructor:function(a){this.merge(a)},copy:delegate(copy),forEach:function(a,b){for(var c in this)if(c.charAt(0)==_13){a.call(b,this[c],c.slice(1),this)}},get:function(a){return this[_13+a]},getKeys:function(){return this.map(flip(I))},getValues:function(){return this.map(I)},has:function(a){/*@cc_on@*//*@if(@_14<5.5)return $Legacy.has(this,_13+a);@else@*/return _13+a in this;/*@end@*/},merge:function(b){var c=flip(this.put);forEach(arguments,function(a){forEach(a,c,this)},this);return this},remove:function(a){delete this[_13+a]},put:function(a,b){if(arguments.length==1)b=a;this[_13+a]=b},size:function(){var a=0;for(var b in this)if(b.charAt(0)==_13)a++;return a},union:function(a){return this.merge.apply(this.copy(),arguments)}});Map.implement(Enumerable);var _15="~";var Collection=Map.extend({constructor:function(a){this[_15]=new Array2;this.base(a)},add:function(a,b){assert(!this.has(a),"Duplicate key '"+a+"'.");this.put.apply(this,arguments)},copy:function(){var a=this.base();a[_15]=this[_15].copy();return a},forEach:function(a,b){var c=this[_15];var d=c.length;for(var i=0;i1900){Date.prototype.getYear=function(){return this.getFullYear()-1900};Date.prototype.setYear=function(a){return this.setFullYear(a+1900)}}Function.prototype.prototype={};if("".replace(/^/,K("$$"))=="$"){extend(String.prototype,"replace",function(a,b){if(typeof b=="function"){var c=b;b=function(){return String(c.apply(null,arguments)).split("$").join("$$")}}return this.base(a,b)})}var Array2=_23(Array,Array,"concat,join,pop,push,reverse,shift,slice,sort,splice,unshift",[Enumerable,{combine:function(d,e){if(!e)e=d;return this.reduce(d,function(a,b,c){a[b]=e[c];return a},{})},contains:function(a,b){return this.indexOf(a,b)!=-1},copy:function(a){var b=_9.call(a);if(!b.swap)this(b);return b},flatten:function(c){var d=0;return this.reduce(c,function(a,b){if(this.like(b)){this.reduce(b,arguments.callee,a,this)}else{a[d++]=b}return a},[],this)},forEach:_24,indexOf:function(a,b,c){var d=a.length;if(c==null){c=0}else if(c<0){c=Math.max(0,d+c)}for(var i=c;i=0;i--){if(a[i]===b)return i}return-1},map:function(c,d,e){var f=[];this.forEach(c,function(a,b){f[b]=d.call(e,a,b,c)});return f},remove:function(a,b){var c=this.indexOf(a,b);if(c!=-1)this.removeAt(a,c);return b},removeAt:function(a,b){return this.splice(a,b,1)},swap:function(a,b,c){if(b<0)b+=a.length;if(c<0)c+=a.length;var d=a[b];a[b]=a[c];a[c]=d;return a}}]);Array2.reduce=Enumerable.reduce;Array2.like=function(a){return!!(a&&typeof a=="object"&&typeof a.length=="number")};var _25=/^((-\d+|\d{4,})(-(\d{2})(-(\d{2}))?)?)?T((\d{2})(:(\d{2})(:(\d{2})(\.(\d{1,3})(\d)?\d*)?)?)?)?(([+-])(\d{2})(:(\d{2}))?|Z)?$/;var _26={FullYear:2,Month:4,Date:6,Hours:8,Minutes:10,Seconds:12,Milliseconds:14};var _27={Hectomicroseconds:15,UTC:16,Sign:17,Hours:18,Minutes:20};var _28=/(((00)?:0+)?:0+)?\.0+$/;var _29=/(T[0-9:.]+)$/;var Date2=_23(Date,function(a,b,c,h,m,s,d){switch(arguments.length){case 0:return new Date;case 1:return new Date(a);default:return new Date(a,b,arguments.length==2?1:c,h||0,m||0,s||0,d||0)}},"",[{toISOString:function(c){var d="####-##-##T##:##:##.###";for(var e in _26){d=d.replace(/#+/,function(a){var b=c["getUTC"+e]();if(e=="Month")b++;return("000"+b).slice(-a.length)})}return d.replace(_28,"").replace(_29,"$1Z")}}]);Date2.now=function(){return(new Date).valueOf()};Date2.parse=function(a,b){if(arguments.length>1){assertType(b,"number","defaultDate should be of type 'number'.")}var c=String(a).match(_25);if(c){if(c[_26.Month])c[_26.Month]--;if(c[_27.Hectomicroseconds]>=5)c[_26.Milliseconds]++;var d=new Date(b||0);var e=c[_27.UTC]||c[_27.Hours]?"UTC":"";for(var f in _26){var g=c[_26[f]];if(!g)continue;d["set"+e+f](g);if(d["get"+e+f]()!=c[_26[f]]){return NaN}}if(c[_27.Hours]){var h=Number(c[_27.Sign]+c[_27.Hours]);var i=Number(c[_27.Sign]+(c[_27.Minutes]||0));d.setUTCMinutes(d.getUTCMinutes()+(h*60)+i)}return d.valueOf()}else{return Date.parse(a)}};var String2=_23(String,function(a){return new String(arguments.length==0?"":a)},"charAt,charCodeAt,concat,indexOf,lastIndexOf,match,replace,search,slice,split,substr,substring,toLowerCase,toUpperCase",[{trim:trim}]);function _23(c,constructor,d,e){var f=Module.extend();forEach(d.match(/\w+/g),function(a){f[a]=unbind(c.prototype[a])});forEach(e,f.implement,f);var g=function(){return f(this.constructor==f?constructor.apply(null,arguments):arguments[0])};g.prototype=f.prototype;forEach(f,function(a,b){if(c[b]){f[b]=c[b];delete f.prototype[b]}g[b]=f[b]});g.ancestor=Object;delete g.extend;if(c!=Array)delete g.forEach;return g};function extend(a,b){if(a&&b){if(arguments.length>2){var c=b;b={};b[c]=arguments[2]}var d=(typeof b=="function"?Function:Object).prototype;var i=_6.length,c;if(base2.__prototyping){while(c=_6[--i]){var e=b[c];if(e!=d[c]){if(_5.test(e)){_22(a,c,e)}else{a[c]=e}}}}for(c in b){if(d[c]===undefined){var e=b[c];if(c.charAt(0)=="@"){if(detect(c.slice(1)))arguments.callee(a,e);continue}var f=a[c];if(f&&typeof e=="function"){if(e!=f&&(!f.method||!_12(e,f))){if(_5.test(e)){_22(a,c,e)}else{e.ancestor=f;a[c]=e}}}else{a[c]=e}}}}return a};function _12(a,b){while(b){if(!b.ancestor)return false;b=b.ancestor;if(b==a)return true}return false};function _22(c,d,e){var f=c[d];var g=base2.__prototyping;if(g&&f!=g[d])g=null;function h(){var a=this.base;this.base=g?g[d]:f;var b=e.apply(this,arguments);this.base=a;return b};h.ancestor=f;c[d]=h};if(typeof StopIteration=="undefined"){StopIteration=new Error("StopIteration")}function forEach(a,b,c,d){if(a==null)return;if(!d){if(typeof a=="function"&&a.call){d=Function}else if(typeof a.forEach=="function"&&a.forEach!=arguments.callee){a.forEach(b,c);return}else if(typeof a.length=="number"){_24(a,b,c);return}}_10(d||Object,a,b,c)};function _24(a,b,c){if(a==null)return;var d=a.length,i;if(typeof a=="string"){for(i=0;i1)?function(a,b,c,d){var e={};for(var f in b){if(!e[f]&&a.prototype[f]===undefined){e[f]=true;c.call(d,b[f],f,b)}}}:function(a,b,c,d){for(var e in b){if(a.prototype[e]===undefined){c.call(d,b[e],e,b)}}};_10(g,h,j,k)};function typeOf(a){var b=typeof a;switch(b){case"object":return a===null?"null":typeof a.call=="function"||_7.test(a)?"function":b;case"function":return typeof a.call=="function"?b:"object";default:return b}};function instanceOf(a,b){if(typeof b!="function"){throw new TypeError("Invalid 'instanceOf' operand.");}if(a==null)return false;/*@cc_on if(typeof a.constructor!="function"){return typeOf(a)==typeof b.prototype.valueOf()}@*//*@if(@_14<5.1)if($Legacy.instanceOf(a,b))return true;@else@*/if(a instanceof b)return true;/*@end@*/if(Base.ancestorOf==b.ancestorOf)return false;if(Base.ancestorOf==a.constructor.ancestorOf)return b==Object;switch(b){case Array:return!!(typeof a=="object"&&a.join&&a.splice);case Function:return typeOf(a)=="function";case RegExp:return typeof a.constructor.$1=="string";case Date:return!!a.getTimezoneOffset;case String:case Number:case Boolean:return typeof a==typeof b.prototype.valueOf();case Object:return true}return false};function assert(a,b,c){if(!a){throw new(c||Error)(b||"Assertion failed.");}};function assertArity(a,b,c){if(b==null)b=a.callee.length;if(a.lengthd){return 2}return 0}}});var _33=document.documentElement.sourceIndex?function(a){return a.sourceIndex}:function(a){var b=0;while(a){b=Traversal.getNodeIndex(a)+"."+b;a=a.parentNode}return b};var Document=Node.extend(null,{bind:function(b){extend(b,"createElement",function(a){return DOM.bind(this.base(a))});AbstractView.bind(b.defaultView);if(b!=window.document)new DOMContentLoadedEvent(b);return this.base(b)},"@!(document.defaultView)":{bind:function(a){a.defaultView=Traversal.getDefaultView(a);return this.base(a)}}});var _34=/^(href|src)$/;var _35={"class":"className","for":"htmlFor"};var Element=Node.extend({"@MSIE.+win":{getAttribute:function(a,b,c){if(a.className===undefined){return this.base(a,b)}var d=_36(a,b);if(d&&(d.specified||b=="value")){if(_34.test(b)){return this.base(a,b,2)}else if(b=="style"){return a.style.cssText}else{return d.nodeValue}}return null},setAttribute:function(a,b,c){if(a.className===undefined){this.base(a,b,c)}else if(b=="style"){a.style.cssText=c}else{c=String(c);var d=_36(a,b);if(d){d.nodeValue=c}else{this.base(a,_35[b]||b,c)}}}},"@!(element.hasAttribute)":{hasAttribute:function(a,b){return this.getAttribute(a,b)!=null}}});extend(Element.prototype,"cloneNode",function(a){var b=this.base(a||false);b.base2ID=undefined;return b});if(_30){var _37="colSpan,rowSpan,vAlign,dateTime,accessKey,tabIndex,encType,maxLength,readOnly,longDesc";extend(_35,Array2.combine(_37.toLowerCase().split(","),_37.split(",")));var _36=_31?function(a,b){return a.attributes[b]||a.attributes[_35[b.toLowerCase()]]}:function(a,b){return a.getAttributeNode(b)}}var TEXT=_30?"innerText":"textContent";var Traversal=Module.extend({getDefaultView:function(a){return this.getDocument(a).defaultView},getNextElementSibling:function(a){while(a&&(a=a.nextSibling)&&!this.isElement(a))continue;return a},getNodeIndex:function(a){var b=0;while(a&&(a=a.previousSibling))b++;return b},getOwnerDocument:function(a){return a.ownerDocument},getPreviousElementSibling:function(a){while(a&&(a=a.previousSibling)&&!this.isElement(a))continue;return a},getTextContent:function(a){return a[TEXT]},isEmpty:function(a){a=a.firstChild;while(a){if(a.nodeType==3||this.isElement(a))return false;a=a.nextSibling}return true},setTextContent:function(a,b){return a[TEXT]=b},"@MSIE":{getDefaultView:function(a){return(a.document||a).parentWindow},"@MSIE5":{getOwnerDocument:function(a){return a.ownerDocument||a.document}}}},{contains:function(a,b){while(b&&(b=b.parentNode)&&a!=b)continue;return!!b},getDocument:function(a){return this.isDocument(a)?a:this.getOwnerDocument(a)},isDocument:function(a){return!!(a&&a.documentElement)},isElement:function(a){return!!(a&&a.nodeType==1)},"@(element.contains)":{contains:function(a,b){return a!=b&&(this.isDocument(a)?a==this.getOwnerDocument(b):a.contains(b))}},"@MSIE5":{isElement:function(a){return!!(a&&a.nodeType==1&&a.nodeName!="!")}}});var AbstractView=Binding.extend();var Event=Binding.extend({"@!(document.createEvent)":{initEvent:function(a,b,c,d){a.type=b;a.bubbles=c;a.cancelable=d;a.timeStamp=new Date().valueOf()},"@MSIE":{initEvent:function(a,b,c,d){this.base(a,b,c,d);a.cancelBubble=!a.bubbles},preventDefault:function(a){if(a.cancelable!==false){a.returnValue=false}},stopPropagation:function(a){a.cancelBubble=true}}}},{"@!(document.createEvent)":{"@MSIE":{bind:function(a){if(!a.timeStamp){a.bubbles=!!_38[a.type];a.cancelable=!!_39[a.type];a.timeStamp=new Date().valueOf()}if(!a.target){a.target=a.srcElement}a.relatedTarget=a[(a.type=="mouseout"?"to":"from")+"Element"];return this.base(a)}}}});if(_30){var _38="abort,error,select,change,resize,scroll";var _39="click,mousedown,mouseup,mouseover,mousemove,mouseout,keydown,keyup,submit,reset";_38=Array2.combine((_38+","+_39).split(","));_39=Array2.combine(_39.split(","))}var EventTarget=Interface.extend({"@!(element.addEventListener)":{addEventListener:function(a,b,c,d){var e=assignID(a);var f=assignID(c);var g=_40[e];if(!g)g=_40[e]={};var h=g[b];var i=a["on"+b];if(!h){h=g[b]={};if(i)h[0]=i}h[f]=c;if(i!==undefined){a["on"+b]=_40._41}},dispatchEvent:function(a,b){return _41.call(a,b)},removeEventListener:function(a,b,c,d){var e=_40[a.base2ID];if(e&&e[b]){delete e[b][c.base2ID]}},"@(element.fireEvent)":{dispatchEvent:function(a,b){var c="on"+b.type;b.target=a;if(a[c]===undefined){return this.base(a,b)}else{return a.fireEvent(c,b)}}}}});var _40=new Base({_41:_41,"@MSIE":{_41:function(){var a=this;var b=(a.document||a).parentWindow;if(a.Infinity)a=b;return _41.call(a,b.event)}}});function _41(a){var b=true;var c=_40[this.base2ID];if(c){Event.bind(a);var d=c[a.type];for(var i in d){var listener=d[i];if(listener.handleEvent){var result=listener.handleEvent(a)}else{result=listener.call(this,a)}if(result===false||a.returnValue===false)b=false}}return b};var DocumentEvent=Interface.extend({"@!(document.createEvent)":{createEvent:function(a,b){return Event.bind({})},"@(document.createEventObject)":{createEvent:function(a,b){return Event.bind(a.createEventObject())}}},"@(document.createEvent)":{"@!(document.createEvent('Events'))":{createEvent:function(a,b){return this.base(a,b=="Events"?"UIEvents":b)}}}});var DOMContentLoadedEvent=Base.extend({constructor:function(b){var c=false;this.fire=function(){if(!c){c=true;setTimeout(function(){var a=DocumentEvent.createEvent(b,"Events");Event.initEvent(a,"DOMContentLoaded",false,false);EventTarget.dispatchEvent(b,a)},1)}};EventTarget.addEventListener(b,"DOMContentLoaded",function(){c=true},false);this.listen(b)},listen:function(a){EventTarget.addEventListener(Traversal.getDefaultView(a),"load",this.fire,false)},"@MSIE.+win":{listen:function(a){if(a.readyState!="complete"){var b=this;a.write(" + + + + + + +

    Start data:

    +
    
    +    

    Result:

    +
    
    +  
    +
    
    Added: kukit/kukit.js/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/dommer/run_tests.html
    ==============================================================================
    --- (empty file)
    +++ kukit/kukit.js/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/dommer/run_tests.html	Tue Apr 15 11:35:22 2008
    @@ -0,0 +1,53 @@
    +
    +
    +
    +Unit tests for Dommer
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    
    Added: kukit/kukit.js/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/dommer/test_dommer.js
    ==============================================================================
    --- (empty file)
    +++ kukit/kukit.js/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/dommer/test_dommer.js	Tue Apr 15 11:35:22 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/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/dommer/version.txt
    ==============================================================================
    --- (empty file)
    +++ kukit/kukit.js/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/dommer/version.txt	Tue Apr 15 11:35:22 2008
    @@ -0,0 +1 @@
    +0.4
    
    Added: kukit/kukit.js/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/jsbase/LICENSE.txt
    ==============================================================================
    --- (empty file)
    +++ kukit/kukit.js/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/jsbase/LICENSE.txt	Tue Apr 15 11:35:22 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/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/jsbase/README.txt
    ==============================================================================
    --- (empty file)
    +++ kukit/kukit.js/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/jsbase/README.txt	Tue Apr 15 11:35:22 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/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/jsbase/__init__.py
    ==============================================================================
    
    Added: kukit/kukit.js/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/jsbase/array.js
    ==============================================================================
    --- (empty file)
    +++ kukit/kukit.js/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/jsbase/array.js	Tue Apr 15 11:35:22 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/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/jsbase/conftest.py
    ==============================================================================
    --- (empty file)
    +++ kukit/kukit.js/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/jsbase/conftest.py	Tue Apr 15 11:35:22 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/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/jsbase/exception.js
    ==============================================================================
    --- (empty file)
    +++ kukit/kukit.js/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/jsbase/exception.js	Tue Apr 15 11:35:22 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/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/jsbase/function.js
    ==============================================================================
    --- (empty file)
    +++ kukit/kukit.js/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/jsbase/function.js	Tue Apr 15 11:35:22 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/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/jsbase/misclib.js
    ==============================================================================
    --- (empty file)
    +++ kukit/kukit.js/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/jsbase/misclib.js	Tue Apr 15 11:35:22 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/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/jsbase/number.js
    ==============================================================================
    --- (empty file)
    +++ kukit/kukit.js/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/jsbase/number.js	Tue Apr 15 11:35:22 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/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/jsbase/server.js
    ==============================================================================
    --- (empty file)
    +++ kukit/kukit.js/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/jsbase/server.js	Tue Apr 15 11:35:22 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/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/jsbase/string.js
    ==============================================================================
    --- (empty file)
    +++ kukit/kukit.js/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/jsbase/string.js	Tue Apr 15 11:35:22 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/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/jsbase/test_array.js
    ==============================================================================
    --- (empty file)
    +++ kukit/kukit.js/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/jsbase/test_array.js	Tue Apr 15 11:35:22 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/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/jsbase/test_misclib.js
    ==============================================================================
    --- (empty file)
    +++ kukit/kukit.js/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/jsbase/test_misclib.js	Tue Apr 15 11:35:22 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/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/jsbase/test_number.js
    ==============================================================================
    --- (empty file)
    +++ kukit/kukit.js/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/jsbase/test_number.js	Tue Apr 15 11:35:22 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/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/jsbase/test_string.js
    ==============================================================================
    --- (empty file)
    +++ kukit/kukit.js/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/jsbase/test_string.js	Tue Apr 15 11:35:22 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/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/jsbase/testing.js
    ==============================================================================
    --- (empty file)
    +++ kukit/kukit.js/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/jsbase/testing.js	Tue Apr 15 11:35:22 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/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/jsbase/testing/findtests.js
    ==============================================================================
    --- (empty file)
    +++ kukit/kukit.js/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/jsbase/testing/findtests.js	Tue Apr 15 11:35:22 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/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/jsbase/testing/testbase.js
    ==============================================================================
    --- (empty file)
    +++ kukit/kukit.js/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/jsbase/testing/testbase.js	Tue Apr 15 11:35:22 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/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/jsbase/version.txt
    ==============================================================================
    --- (empty file)
    +++ kukit/kukit.js/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/jsbase/version.txt	Tue Apr 15 11:35:22 2008
    @@ -0,0 +1 @@
    +0.1
    
    Added: kukit/kukit.js/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/minisax.js/LICENSE.txt
    ==============================================================================
    --- (empty file)
    +++ kukit/kukit.js/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/minisax.js/LICENSE.txt	Tue Apr 15 11:35:22 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/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/minisax.js/conftest.py
    ==============================================================================
    --- (empty file)
    +++ kukit/kukit.js/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/minisax.js/conftest.py	Tue Apr 15 11:35:22 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/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/minisax.js/example.html
    ==============================================================================
    --- (empty file)
    +++ kukit/kukit.js/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/minisax.js/example.html	Tue Apr 15 11:35:22 2008
    @@ -0,0 +1,69 @@
    +
    +
    +  
    +    MiniSAX test
    +    
    +    
    +    
    +    
    +  
    +  
    +    

    Start data:

    +
    
    +    

    Result:

    +
    
    +  
    +
    
    Added: kukit/kukit.js/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/minisax.js/helpers.js
    ==============================================================================
    --- (empty file)
    +++ kukit/kukit.js/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/minisax.js/helpers.js	Tue Apr 15 11:35:22 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/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/minisax.js/minisax.js
    ==============================================================================
    --- (empty file)
    +++ kukit/kukit.js/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/minisax.js/minisax.js	Tue Apr 15 11:35:22 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/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/minisax.js/test_minisax.js
    ==============================================================================
    --- (empty file)
    +++ kukit/kukit.js/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/minisax.js/test_minisax.js	Tue Apr 15 11:35:22 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/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/minisax.js/testhandler.js
    ==============================================================================
    --- (empty file)
    +++ kukit/kukit.js/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/minisax.js/testhandler.js	Tue Apr 15 11:35:22 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/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/minisax.js/version.txt
    ==============================================================================
    --- (empty file)
    +++ kukit/kukit.js/branch/ree-service-layer-and-refactoring/3rd_party/johnnydebris.net/minisax.js/version.txt	Tue Apr 15 11:35:22 2008
    @@ -0,0 +1 @@
    +0.3
    
    Modified: kukit/kukit.js/branch/ree-service-layer-and-refactoring/doc/HISTORY.txt
    ==============================================================================
    --- kukit/kukit.js/branch/ree-service-layer-and-refactoring/doc/HISTORY.txt	(original)
    +++ kukit/kukit.js/branch/ree-service-layer-and-refactoring/doc/HISTORY.txt	Tue Apr 15 11:35:22 2008
    @@ -2,8 +2,8 @@
     
         (name of developer listed in brackets)
         
    -kukit.js - 1.4dev Unreleased
    -
    +kukit.js - 1.5dev Unreleased
    +    
         - ...
     
         - Add a general registry for interfaces.
    @@ -43,6 +43,47 @@
           two places and considered as two broken selectors.
           [ree]
     
    +
    +    - 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.
    +      [ree]
    +
    +    - disabled input values should not be submitted with the form
    +      [gotcha]
    +
    +    - Updated base2-dom-fp.js with newest version.
    +      This fixes breakage on FireFox 3.
    +      [ree]
    +
    +kukit.js - 1.4dev Unreleased
    +
    +    - 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]
    +
    +    - Implement multiproperties in
    +      action-client and action-server
    +      [ree]
    +
    +    - add url() and alias() providers
    +      [ree]
    +
    +    - 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.
    +      
         - Fix multiple selection form fields
           marshalling on Safari 
           (fixes #22 in kssproject)
    
    Added: kukit/kukit.js/branch/ree-service-layer-and-refactoring/doc/draganddrop.kss.txt
    ==============================================================================
    --- (empty file)
    +++ kukit/kukit.js/branch/ree-service-layer-and-refactoring/doc/draganddrop.kss.txt	Tue Apr 15 11:35:22 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;
    +}
    
    Modified: kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/actionreg.js
    ==============================================================================
    --- kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/actionreg.js	(original)
    +++ kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/actionreg.js	Tue Apr 15 11:35:22 2008
    @@ -22,25 +22,26 @@
     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() {
     };
     
    -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);
    -;;;}
    -    var actions = kukit.interfaces.global.schema.actions;
    +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);
    +;;; }
    +    var actions = kukit.pluginregistry.schema.actions;
         actions.getAttribute(name).register({actionFunc: func});
     };
     
    -ActionRegistry.prototype.get = function(name) {
    -    var reg = kukit.interfaces.global.actions[name];
    +this.get = function(name) {
    +    var reg = kukit.pluginregistry.actions[name];
         if (! reg || ! reg.actionFunc) {
             // not found
     ;;;     kukit.E = 'Error : undefined client action [' + name + '].';
    @@ -48,17 +49,21 @@
             }
         return reg.actionFunc;
     };
    +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/branch/ree-service-layer-and-refactoring/kukit/commandprocessor.js
    ==============================================================================
    --- kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/commandprocessor.js	(original)
    +++ kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/commandprocessor.js	Tue Apr 15 11:35:22 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 = "";
    @@ -74,7 +74,7 @@
                     throw new Error('Bad payload, expected param (IE)');
                 }
             }        
    -        data = childNode.getAttribute('name');
    +        var data = childNode.getAttribute('name');
             if (data != null) { 
                 // Decide if we have a string or a dom parameter
                 var childCount = childNode.childNodes.length;
    @@ -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/branch/ree-service-layer-and-refactoring/kukit/commandreg.js
    ==============================================================================
    --- kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/commandreg.js	(original)
    +++ kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/commandreg.js	Tue Apr 15 11:35:22 2008
    @@ -27,25 +27,13 @@
     *  class _CommandRegistry
     */
     var _CommandRegistry = function () {
    +
    +this.initialize = function() {
     };
     
    -/* 
    -* 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) {
    -    var actions = kukit.interfaces.global.schema.actions;
    +    var actions = kukit.pluginregistry.schema.actions;
         //
         // register a given action as a command, using the given vactor
         var attrib = actions.getAttribute(srcname);
    @@ -70,15 +58,16 @@
             this._register(srcname, commandClass, attrib);
         }
     
    +
     };
     
    -_CommandRegistry.prototype.register = function(name, commandClass) {
    -    var actions = kukit.interfaces.global.schema.actions;
    +this.register = function(name, commandClass) {
    +    var actions = kukit.pluginregistry.schema.actions;
         var attrib = actions.getAttribute(name);
         this._register(name, commandClass, attrib);
     };
     
    -_CommandRegistry.prototype._register = function(name, commandClass, descriptor) {
    +this._register = function(name, commandClass, descriptor) {
         if (! descriptor.config) {
     ;;;     kukit.E = 'undefined client action [' + name + '] in CommandRegistry.register.';
             throw Error(kukit.E);
    @@ -91,17 +80,32 @@
         descriptor.config.commandClass = commandClass;
     };
     
    -_CommandRegistry.prototype.get = function(name) {
    -    var action = kukit.interfaces.global.actions[name];
    +this.get = function(name) {
    +    var action = kukit.pluginregistry.actions[name];
         var klass = action.commandClass;
         if (! klass) {
    -;;;    // not found
     ;;;     kukit.E = 'undefined command [' + name + ']';
             throw Error(kukit.E);
         }
         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();
     
     
    @@ -139,16 +143,21 @@
     };
     
     var _executeCommandOnSelector = function(oper) {
    -    var info = kukit.interfaces.global.selectors[this.selectorType];
    +    // if the selector type is null or undefined or '',
    +    // we use the default type.
    +    var selectorType = this.selectorType || 
    +                       kukit.selectorTypesGlobalRegistry.defaultSelectorType;
    +    var info = kukit.pluginregistry.valueproviders[selectorType];
         // Check if the selector name really exists.
    -    if (! info || ! info.selectorFunc) {
    -;;;     kukit.E = 'Undefined selector [';
    -;;;     kukit.E += this.methodName + '].';
    +    if (! info || ! info.returnType == 'selection' || ! info.selectorFunc) {
    +;;;     kukit.E = 'Undefined selector type [' + selectorType + '], ';
    +;;;     kukit.E = 'it exists as provider but it does not return a selection.';
             throw kukit.err.pluginRegistryError(null, kukit.E);
         }
    -    // When applying the selection, the original event target will be used
    +    // When evaluating the provider, the original event target will be used
         // as a starting point for the selection.
         var nodes = info.selectorFunc(this.selector, oper.orignode, {});
    +    //
     ;;;var printType;
     ;;;if (this.selectorType) {
     ;;;    printType = this.selectorType;
    @@ -170,22 +179,20 @@
     };
     
     cr.makeSelectorCommand = function(executeOnSingleNode) {
    -    var commandClass = function() {};
    -    commandClass.prototype = {
    -        execute: _executeCommand,
    -        executeOnScope: _executeCommandOnSelector,
    -        executeOnSingleNode: executeOnSingleNode
    -    };
    +    var commandClass = function() {
    +        this.execute = _executeCommand;
    +        this.executeOnScope = _executeCommandOnSelector;
    +        this.executeOnSingleNode = executeOnSingleNode;
    +        };
         return commandClass;
     };
     
     cr.makeGlobalCommand = function(executeOnce) {
    -    var commandClass = function() {};
    -    commandClass.prototype = {
    -        execute: _executeCommand,
    -        executeOnScope: executeOnce,
    -        executeOnSingleNode: executeOnce
    -    };
    +    var commandClass = function() {
    +        this.execute = _executeCommand;
    +        this.executeOnScope = executeOnce;
    +        this.executeOnSingleNode = executeOnce;
    +        };
         return commandClass;
     };
     
    
    Modified: kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/dom.js
    ==============================================================================
    --- kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/dom.js	(original)
    +++ kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/dom.js	Tue Apr 15 11:35:22 2008
    @@ -77,7 +77,7 @@
     ;;;    kukit.E = 'Selection error in kukit.dom.cssQuery';
             throw new Error(kukit.E);
         }
    -    return kukit.interfaces.global.core.cssQuery(selector, inNodes);
    +    return kukit.service.core.cssQuery(selector, inNodes);
     };
     
     /*
    @@ -198,27 +198,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 1) {
    +;;;     kukit.E = 'In [_EventRegistry.register], [namespace] cannot have';
    +;;;     kukit.E += 'dashes.';
    +        throw new Error(kukit.E);
    +    }
    +    return namespace + '-' + eventName;
    +};
     
     };
     
    @@ -96,26 +112,77 @@
     
     /* 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
     *
     */
    +/*
    + * XXX Late binder is not needed any more:
    + * the same need is better fulfilled by bind iterators.
    + * By commenting it out I want to demonstrate that it's not
    + * used anyway
    +
    +
    +var _LateBinder = function() {
     
    -/* Provide callins on the state instance that execute a given
    +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);
    +};
    +
    +End commenting LateBinder */
    +
    +/*
    +*
    +* 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
    @@ -125,7 +192,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:
     *
    @@ -144,7 +211,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:
     *
    @@ -162,7 +229,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:
     *
    @@ -181,8 +248,9 @@
     * 
     */
     
    -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)
         //
    @@ -230,12 +298,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.
    @@ -260,19 +334,18 @@
             } else {
                 newOper.defaultParameters = {};
             }
    -        this._EventBinder_triggerEvent(name, newOper);
    +        this.triggerEvent(name, newOper);
             executed += 1;
         }
     ;;; kukit.logDebug('Event [' + name + '] executed on ' + executed + ' nodes.');
     };
     
    -/*
    -*
    -* class _LateBinder
    -*
    -* postpone binding of actions until called first time
    -*
    -*/
    +this.__continueEvent_allNodes__ = function(name, defaultParameters) {
    +;;; var msg = 'Deprecated [__continueEvent_allNodes__],';
    +;;; msg += 'use [continueEventAllNodes] instead !';
    +;;; kukit.logWarning(msg);
    +    this.continueEventAllNodes(name, defaultParameters);
    +};
     
     /*
      * XXX Late binder is not needed any more:
    @@ -280,51 +353,25 @@
      * By commenting it out I want to demonstrate that it's not
      * used anyway
     
    -var _EventBinder_makeFuncToBind = function(name, node) {
    +
    +this.makeFuncToBind = function(name, node) {
        var executor = new er._LateBinder(this, name, node);
        return function() {
            executor.executeActions();
        };
     };
     
    -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.
    @@ -346,9 +393,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(name, oper, methodName) {
    +this.callMethod = function(name, oper, methodName) {
         // hidden method for calling just a method and checking that is exists.
         // (called from oper)
         var method = this[methodName];
    @@ -362,31 +416,43 @@
         method.call(this, name, oper);
     };
     
    +};
    +
     var _eventClassCounter = 0;
     
    -this.decorateEventBinderClass = function(cls) {
    +this.decorateEventBinderClass = 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);
    +    }
         // 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 (cls.__decorated_for_kss__) {
    +    if (klass.__decorated_for_kss__) {
             return;
         }
    -    var p = cls.prototype;
    -    // Put inherited methods on it
    -    p.__continueEvent__ = _EventBinder__continueEvent__;
    -    p.__continueEvent_allNodes__ =
    -        _EventBinder__continueEvent_allNodes__;
    -    p._EventBinder_triggerEvent = _EventBinder_triggerEvent;
    -    p._EventBinder_callMethod = _EventBinder_callMethod;
    -//    p.__makeFuncToBind__ = _EventBinder_makeFuncToBind; // only used by LateBinder atm
    -    // Generate a unique class name
    -    p.__className__ = '' + _eventClassCounter;
    -    _eventClassCounter ++;
    +    // 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;
         // mark decorated. We store the class there
         // so we can decide if this class has been
         // decorated or not.
    -    cls.__decorated_for_kss__ = true;
    +    klass.__decorated_for_kss__ = true;
     };
     
     /* Event instance registry 
    @@ -396,8 +462,9 @@
     *  used in run-time to keep track of the event instances
     *
     */
    +er.BinderInfoRegistry = function() {
     
    -er.BinderInfoRegistry = function () {
    +this.initialize = function() {
         this.info = {};
     };
     
    @@ -406,7 +473,7 @@
      * The binder info is returned, it contains binding information
      * and a reference link to the actual binder instance.
      */
    -er.BinderInfoRegistry.prototype.getOrCreateBinderInfo =
    +this.getOrCreateBinderInfo =
         function (kssSelector, node) {
         // We use the key as the selector's merge id.
         var key = kssSelector.getBindKey(node);
    @@ -433,9 +500,8 @@
         return binderInfo;
     };
     
    -
     /*
    -er.BinderInfoRegistry.prototype.getBinderInfoById = function (id) {
    +this.getBinderInfoById = function (id) {
         // Get an event.
         var binderInfo = this.info[id];
         if (typeof(binderInfo) == 'undefined') {
    @@ -448,7 +514,7 @@
     
     /* Not used from kukit actually */
     /*
    -er.BinderInfoRegistry.prototype.getSingletonBinderInfoByName =
    +this.getSingletonBinderInfoByName =
         function (namespace, name) {
         //Get className
         if (namespace) {
    @@ -467,7 +533,7 @@
     };
     */
     
    -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) {
    @@ -477,7 +543,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) {
    @@ -486,6 +552,8 @@
             binderInfo.processBindingEvents();
         }
     };
    +this.initialize.apply(this, arguments);
    +};
     
     /*
     * class _BinderInfo
    @@ -494,24 +562,57 @@
     * 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.getBinder = function () {
    +        return this.binder;
    +    };
    +
    +    this.startBindingPhase = function () {
    +        // The binding phase starts and it has the information for
    +        // the currently on-bound events.
    +        this.binding = new _OperRegistry();
    +    };
    +
    +    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.)
    +        //
    +        // first see if it can go to already bound ones
    +        this.bound.checkOperBindable(oper);
    +        // then register it properly to the binding events
    +        this.binding.bindOper(oper);
    +    };
    +
    +    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);
    +        // Now we to add these to the new ones.
    +        this.binding.propagateTo(this.bound);
    +        // Delete them from the registry, to protect against accidents.
    +        this.binding = null;
    +    };
    +
         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.)
    @@ -522,7 +623,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);
    @@ -531,25 +632,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 (iteration, 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) {
    @@ -559,7 +809,7 @@
         }
     };
     
    -_OperRegistry.prototype.checkOperBindable =
    +this.checkOperBindable =
         function (oper, name, nodeHash) {
         // Check if the binding with this oper could be done.
         // Throw exception otherwise.
    @@ -586,7 +836,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);
    @@ -601,9 +851,9 @@
         rulesPerNode[name] = oper;
     };
     
    -_OperRegistry.prototype.processBindingEvents = 
    +this.processBindingEvents = 
         function (binder) {
    -    var interfaces = kukit.interfaces.global;
    +    var interfaces = kukit.pluginregistry;
         // Let's see all our events in a cycle.
         processed = {};
         // We iterate through the event names in this binder instance only.
    @@ -619,7 +869,7 @@
             }
             // One iteration consists of more events. Process all these.
             // (One of these is eventName itself, but we need not care.)
    -        var iteration = interfaces.binditerations[eventName];
    +        var iteration = interfaces.bindsequences[eventName];
             // Let's exit if this element does not exist
             // (the interface registry finalizes invalid methods to undefined)
             if (! iteration) {
    @@ -640,7 +890,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.
    @@ -657,7 +907,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 = [];
    @@ -672,161 +922,19 @@
         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 = 
    -    function (iteration, binder, p1, p2, p3, p4, p5) {
    +this.callBindMethod = 
    +    function (iteration, binder, p1, p2, p3, p4, p5, p6) {
         // get the method itself
         var method = binder[iteration.bindMethodName];
         // Protect the binding for better logging
     ;;; try {
    -        method.call(binder, p1, p2, p3, p4, p5);
    +        method.call(binder, p1, p2, p3, p4, p5, p6);
     ;;; } catch(e) {
     ;;;     kukit.E = kukit.err.eventBindError(e, iteration.eventNames);
     ;;;     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 (iteration, binder) {
    -    for (var i=0; i-: 
         // evt---: 
     ;;; if (splitkey.length < 3) {
    @@ -193,12 +244,22 @@
             eventKey = splitkey[3];
             eventFullName = eventNamespace + '-' + eventName;
         }
    -;;; if (value.isMethod != false) {
    +    // preprocess values
    +    var allowedReturnTypes;
    +;;; allowedReturnTypes = {string: true};
    +;;; kukit.E = 'event parameter [' + key + ']';
    +    // global registry is used
    +    var registry = kukit.pluginregistry;
    +    var valuesByReturnType = kukit.va.createAndCheckRuleValues(values, 
    +            allowedReturnTypes, registry, false, kukit.E, this);
    +    var value = valuesByReturnType.string;
    +;;; // Check if it is static
    +;;; if (! value.check_remarks.isStatic) {
     ;;;     kukit.E = 'Wrong value for key [' + key + '] : ';
     ;;;     kukit.E += 'value providers are not ';
     ;;;     kukit.E += 'allowed as value for ';
     ;;;     kukit.E += 'evt-[-]- keys.';
    -;;;     this.emitError(kukit.E);
    +;;;     throw kukit.err.kssValueCheckError(null, kukit.E);
     ;;; }
         var eventParameters = this.eventFullNames[eventFullName];
         if (typeof(eventParameters) == 'undefined') {
    @@ -206,9 +267,9 @@
             eventParameters = this.eventFullNames[eventFullName];
         }
         eventParameters[eventKey] = value.txt;
    -}
    +};
     
    -kukit.kssp.Block.prototype.addActionDeclaration = function(key, splitkey, value) {
    +this.addActionDeclaration = function(key, splitkey, values) {
         // action-server: 
         // action-client: 
         // action-client: -
    @@ -219,12 +280,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 +288,32 @@
     ;;;     kukit.E += '"server" or "client" or "cancel".'; 
     ;;;     this.emitError(kukit.E);
     ;;;     }    
    +    // preprocess values
    +    var allowedReturnTypes;
    +;;; if (actionType == 'S') {
    +;;;     // action-server
    +;;;     allowedReturnTypes = {string: true, formquery: true, url: true};
    +;;; } else if (actionType == 'C') {
    +;;;     // action-client
    +;;;     allowedReturnTypes = {string: true, selection: true, alias: true};
    +;;; } else {
    +;;;     // action-cancel
    +;;;     allowedReturnTypes = {string: true};
    +;;; }
    +;;; kukit.E = 'action definition [' + key + ']';
    +    // check the rule values
    +    // global registry is used
    +    var registry = kukit.pluginregistry;
    +    var valuesByReturnType = kukit.va.createAndCheckRuleValues(values,
    +            allowedReturnTypes, registry, false, kukit.E, this);
    +    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) {
    @@ -240,20 +321,38 @@
     ;;;     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) {
    -        action.setType(actionType);
    -    } else {
    +    var action = this.actions.getOrCreateAction(value.txt, valuesByReturnType);
    +    if (actionType == 'X' &&  action.type == null) {
    +        // action-cancel, and the action existed already in the same block:
    +        // we delete it straight ahead
             this.actions.deleteAction(value.txt);
    +    } else {
    +        // any other qualifier then delete,
    +        // or action-cancel but there has been no action defined yet in the block:
    +        // set the action type.
    +        // (Remark: in case of action-cancel we set action's type to X, and
    +        // the cancellation will possibly happen later, during the merging.)
    +        action.setType(actionType);
         }
    -}
    +};
     
    -kukit.kssp.Block.prototype.addActionError = function(action, key, value) {
    +this.addActionError = function(action, key, values) {
         // -error: 
         // default-error: 
    -;;; if (value.isMethod == true) {
    +    //
    +    // This can only accept string. 
    +    var allowedReturnTypes;
    +;;; allowedReturnTypes = {string: true};
    +;;; kukit.E = 'Wrong value in action error parameter [' + key + ']';
    +    // global registry is used
    +    var registry = kukit.pluginregistry;
    +    var valuesByReturnType = kukit.va.createAndCheckRuleValues(values, 
    +            allowedReturnTypes, registry, false, kukit.E, this);
    +    var value = valuesByReturnType.string;
    +;;; // It cannot be a provider, it must be a real string.
    +;;; if (! value.check_remarks.isStatic) {
     ;;;     kukit.E = 'Wrong value for key [' + key + '] : ';
     ;;;     kukit.E += 'value providers are not ';
     ;;;     kukit.E += 'allowed for -error keys.';
    @@ -261,17 +360,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) {
    -    var interfaceForAction = {
    -        '': kukit.interfaces.global.valueproviders,
    -        'kssSelector': kukit.interfaces.global.selectors,
    -        'kssSubmitForm': kukit.interfaces.global.formproviders
    -    };
    +};
     
    +this.addActionParameter = function(action, key, values) {
         // -: 
         // default-: 
         // 
    @@ -282,27 +375,59 @@
         // This will also set the value providers on the value
         // (from check).
         //
    -    // Figure out which registry to use.
    -    var iface = interfaceForAction[key];
    -    if (typeof(iface) == 'undefined') {
    -        // for all other actions:
    -        // use default value providers
    -        iface = interfaceForAction[''];
    +    // global registry is used
    +    var registry = kukit.pluginregistry;
    +    var value;
    +    var allowedReturnTypes;
    +    var noStringRequired = false;
    +    if (key.substr(0, 3) == 'kss') {
    +;;;     // Action parameter types can have only one value
    +;;;     // ie we don't want form('ccc') and 'ccc' as string, as well
    +;;;     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);
    +;;;     }
    +;;;     // kss special parameter need various return types checking.
    +;;;     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 kssUrl string or url expected
    +;;;         allowedReturnTypes = {string: true, url: true};
    +;;;     }
    +;;;     kukit.E = 'kss action parameter [' + key + ']';
    +        // Call checking the values in both production and development mode.
    +        // 4th parameter (noStringRequired) is set to true, as
    +        // we do _not_ require the existence of a string type.
    +        // We ignore return value since there is one value anyway.
    +        kukit.va.createAndCheckRuleValues(values, allowedReturnTypes, 
    +                registry, true, kukit.E, this);
    +        // Always use the first (and only) value
    +        // This can be a string or what else is required by the 
    +        // special rule, and it will be evaluated later.
    +        value = values[0];
    +    } else {
    +        // Normal (not kssXxxx) parameters: can have a string only
    +;;;     allowedReturnTypes = {string: true};
    +;;;     kukit.E = 'action parameter [' + key + ']';
    +        // Call checking the values in both production and development mode.
    +        var valuesByReturnType = kukit.va.createAndCheckRuleValues(values, 
    +                allowedReturnTypes, registry, false, kukit.E, this);
    +        // The string value is used (there is no more value allowed)
    +        value = valuesByReturnType.string;
         }
    -    //
    -;;; try {
    -        // Check also sets the value provider on the value.
    -        value.check(iface);
    -;;; } catch(e) {
    -;;;     kukit.E = 'Error in value provider for parameter [' + key + '].';
    -;;;     this.emitWrappedError(e, 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.
    -    // the keys look like this:
    +this.addDeclaration = function(key, values) {
    +    // values contains a list of arguments (KssTextValue or KssMethodValue)
    +    //
    +    // the key looks like this:
         //
         // evt--: 
         // evt---: 
    @@ -330,11 +455,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 {
             // -: 
             // --: 
    @@ -357,129 +484,198 @@
                 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);
             }
         }
     };
     
    +};
    +kssp.Block = kukit.tk.mkParser('block', {
    +    ";": _mkReturnToken(kssp.semicolon),
    +    ":": function() {
    +             return [new kssp.colon(this.cursor), 
    +                 new kssp.MultiPropValue(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() {
    +    // 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);
    +;;; // Set value to null. PropValue will give the value "null",
    +;;; // in case there are no tokens at all in the PropValue.
    +;;; // (This may happen, if there are no arguments)
    +;;; this.value = null;
    +    // 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.va.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  .
    +    // Now we found the token that must be   .
         tokenIndex -= 2;
         if (tokenIndex < 0
              || (this.result[tokenIndex+2].symbol !=
    -                kukit.kssp.EventValue.prototype.symbol)
    +                kssp.EventValue.prototype.symbol)
              || (this.result[tokenIndex+1].symbol != 
    -                kukit.kssp.colon.prototype.symbol)
    +                kssp.colon.prototype.symbol)
              || (this.result[tokenIndex].symbol !=
                     kukit.tk.Fraction.prototype.symbol)) {
     ;;;     kukit.E = 'Wrong event selector : missing event qualifier ';
    @@ -771,13 +1021,7 @@
     ;;;     kukit.E += ' space before the colon.';
             this.emitError(kukit.E);
         }
    -    if ((! pseudotoken.value.isMethod && ! pseudotoken.value.txt) ||
    -            (pseudotoken.value.isMethod && ! pseudotoken.value.methodName)) {
    -;;;     kukit.E = 'Wrong event selector :';
    -;;;     kukit.E += ' event name must exist.';
    -        this.emitError(kukit.E);
    -    }
    -    css = this.cursor.text.substring(this.startpos, commatoken.startpos);
    +    var css = this.cursor.text.substring(this.startpos, commatoken.startpos);
         // Decide if we have an event or a method selector.
         // We have a method selector if a single word "document" or "behaviour".
         var singleword = css.replace(/[\r\n\t ]/g, ' ');
    @@ -789,38 +1033,46 @@
             // just store the single word, in case of event selectors
             css = singleword;
         }
    -    // XXX The interfaces for the selector can be taken from a given interface
    -    // registry. We use kukit.interfaces now which will make it operate on
    -    // the global registry. (This value is also passed to the KssSelector
    -    // upon its creation.)
    -    var interfaces = kukit.interfaces.global; 
    +    // global registry is used
    +    var registry = kukit.pluginregistry; 
         // create the selector.
         var id = null;
         var ppid = null;
         // Process the pseudotoken
         // it is like: click(1) or sdnd-drag(kssAttr(poolid))
         var eventName;
    -    if (pseudotoken.value.isMethod) {
    +    var isMethod = pseudotoken.value.isMethod;
    +    if ((! isMethod && ! pseudotoken.value.txt) ||
    +            (isMethod && ! pseudotoken.value.methodName)) {
    +;;;     kukit.E = 'Wrong event selector :';
    +;;;     kukit.E += ' event name must exist.';
    +        this.emitError(kukit.E);
    +    }
    +    if (isMethod) {
    +        // We have no () part at the end of the method.
             eventName = pseudotoken.value.methodName;
             var args = pseudotoken.value.args;
    -        // We do not need to check that argss has exactly one element,
    -        // since this is already assured by the parser syntax.
    -        var arg = args[0];
    -;;;     // We annotate the error, to give parsing information to it.
    -;;;     try {
    -            // Check it in every case.
    -            // always check as value provider
    -            arg.check(interfaces.valueproviders);
    -;;;     } catch(e) {
    -;;;             kukit.E = 'Error in value provider for event binder id.';
    -;;;             this.emitWrappedError(e, kukit.E);
    -;;;     }
    -        if (arg.isMethod) {
    +        // There is only one arg
    +        // but we don't need to check it, because
    +        // the syntax assures that
    +        var value = args[0];
    +        // Checking the value
    +        // this is needed for later evaluation.
    +        var allowedReturnTypes;
    +;;;     allowedReturnTypes = {string: true};
    +;;;     kukit.E = 'in value provider for event binder id.';
    +        kukit.va.createAndCheckRuleValue(value, allowedReturnTypes,
    +                registry, kukit.E, this);
    +        // The following separation gives us possibility to optimize.
    +        // If we have a static string, we know its value already in parsing time.
    +        // Therefore we handle it differently (in id vs. ppid, which will
    +        // only be known after all rules will have been merged).
    +        if (! value.check_remarks.isStatic) {
                 // store it as ppid
    -            ppid = arg;
    +            ppid = value;
             } else {
                 // just an id. Express in txt.
    -            id = arg.txt;
    +            id = value.txt;
             }
         } else {
             eventName = pseudotoken.value.txt;
    @@ -844,9 +1096,9 @@
         // Protect the error for better logging
     ;;; try {
             this.kssSelector = new kukit.rd.KssSelector(isEvent, css, eventName,
    -                id, ppid, interfaces);
    +                id, ppid, registry);
     ;;; } catch(e) {
    -;;;     if (e.name == 'KssSelectorError' || e.name == 'PluginRegistryError') {
    +;;;     if (e.name == 'KssSelectorError' || e.name == 'PluginRegistryError' || e.name == 'KssValueCheckError') {
     ;;;         // Log the message
     ;;;         // This will add line and column information to these errors.
     ;;;         kukit.E = 'Error during parsing KSS';
    @@ -859,18 +1111,32 @@
         this.result = [];
     };
     
    +};
    +kssp.KssSelector = kukit.tk.mkParser('kssselector', {
    +    ":": function() {
    +             return [new kssp.colon(this.cursor),
    +                     new kssp.EventValue(this.cursor)]
    +             },
    +    "{": _emitAndReturn,
    +    "\/\*": _returnComment
    +    },
    +    _KssSelector 
    +    );
    +
     /*
     * class KssRuleProcessor
     *
     * Rule processor that interfaces with kukit core
     */
    -kukit.kssp.KssRuleProcessor = function(href) {
    +kssp.KssRuleProcessor = function(href) {
    +
    +this.initialize = function() {
         this.href = href;
         this.loaded = false;
         this.rules = [];
     };
    -
    -kukit.kssp.KssRuleProcessor.prototype.load = function() {
    +    
    +this.load = function() {
           // Opera does not support getDomDocument.load, so we use XMLHttpRequest
           var domDoc = new XMLHttpRequest();
           domDoc.open("GET", this.href, false);
    @@ -879,11 +1145,11 @@
           this.loaded = true;
     };
     
    -kukit.kssp.KssRuleProcessor.prototype.parse = function() {
    +this.parse = function() {
     ;;; try {
             //Build a parser and parse the text into it
             var cursor = new kukit.tk.Cursor(this.txt);
    -        var parser = new kukit.kssp.Document(cursor, null, true);
    +        var parser = new kssp.Document(cursor, null, true);
             // Store event rules in the common list
             for (var i=0; i 0) {
    -        for (var i=0; i 0 && base.substring(baselen - 1) == '/') {
    -            base = base.substring(0, baselen - 1);
    -        }
    -    }
    +    base = kukit.ut.calculateBase(document, window.location.href);
         return base;
     };
     
    -ku.Engine.prototype.getRuleSheetLinks = function() {
    +this.getRuleSheetLinks = function() {
         var nodes = document.getElementsByTagName("link");
         var results = [];
         for (var i=0; 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(oper) {
    +this.__bind__node = function(oper) {
     ;;; if (oper.node == null) {
     ;;;     throw new Error('Native event [' + oper.getEventName() + '] must be bound to a node.');
     ;;; }
         this.__bind__(oper);
     };
     
    -kukit.pl.NativeEventBinder.prototype.__bind__nodeorwindow = 
    -    function(oper) {
    +this.__bind__nodeorwindow = function(oper) {
         if (oper.node == null) {
             oper.node = window;
         }
         this.__bind__(oper);
     };
     
    -kukit.pl.NativeEventBinder.prototype.__bind__window =
    -    function(oper) {
    +this.__bind__window = function(oper) {
     ;;; if (oper.node != null) {
     ;;;     throw new Error('Native event [' + oper.getEventName() + '] must not be bound to a node.');
     ;;; }
    @@ -163,16 +180,14 @@
         this.__bind__(oper);
     };
     
    -kukit.pl.NativeEventBinder.prototype.__bind__nodeordocument = 
    -    function(oper) {
    +this.__bind__nodeordocument = function(oper) {
         if (oper.node == null) {
             oper.node = document;
         }
         this.__bind__(oper);
     };
     
    -kukit.pl.NativeEventBinder.prototype.__bind__ = 
    -    function(oper, name) {
    +this.__bind__ = function(oper, name) {
     ;;; oper.componentName = 'native event binding';
         oper.evaluateParameters([], 
             {'preventdefault': '', 'allowbubbling': '', 'preventbubbling': ''});
    @@ -195,23 +210,10 @@
         }
         // we give the name parameter to the registration, so we
         // really bind to the event name we want.
    -    kukit.pl.registerBrowserEvent(oper, null, name);
    -    //
    -    // 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)
    -    //
    -    if (oper.parms.preventdefault && kukit.HAVE_SAFARI 
    -            && (oper.parms.allowbubbling || name == 'click'
    -            && oper.node.tagName.toLowerCase() == 'a')) {
    -        oper.node.onclick = function cancelClickSafari() {
    -            return false;
    -        };
    -    }
    +    pl.registerBrowserEvent(oper, null, name);
     };
     
    -kukit.pl.NativeEventBinder.prototype.__bind_key__ =
    +this.__bind_key__ =
         function(oper) {
     ;;; oper.componentName = 'native key event binding';
         oper.evaluateParameters([],
    @@ -282,58 +284,16 @@
                 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.registerForAllEvents(null, 'blur', kukit.pl.NativeEventBinder,
    -    '__bind__nodeorwindow', null, 'Each');
    -kukit.eventsGlobalRegistry.registerForAllEvents(null, 'focus', kukit.pl.NativeEventBinder,
    -    '__bind__nodeorwindow', null, 'Each');
    -kukit.eventsGlobalRegistry.registerForAllEvents(null, 'resize', kukit.pl.NativeEventBinder,
    -    '__bind__nodeorwindow', null, 'Each');
    -kukit.eventsGlobalRegistry.registerForAllEvents(null, 'click', kukit.pl.NativeEventBinder,
    -    '__bind__nodeordocument', null, 'Each');
    -kukit.eventsGlobalRegistry.registerForAllEvents(null, 'dblclick',
    -    kukit.pl.NativeEventBinder, '__bind__node', null, 'Each');
    -kukit.eventsGlobalRegistry.registerForAllEvents(null, 'mousedown',
    -    kukit.pl.NativeEventBinder, '__bind__nodeordocument', null, 'Each');
    -kukit.eventsGlobalRegistry.registerForAllEvents(null, 'mouseup',
    -    kukit.pl.NativeEventBinder, '__bind__nodeordocument', null, 'Each');
    -kukit.eventsGlobalRegistry.registerForAllEvents(null, 'mousemove',
    -    kukit.pl.NativeEventBinder, '__bind__nodeordocument', null, 'Each');
    -kukit.eventsGlobalRegistry.registerForAllEvents(null, 'mouseover',
    -    kukit.pl.NativeEventBinder, '__bind__node', null, 'Each');
    -kukit.eventsGlobalRegistry.registerForAllEvents(null, 'mouseout',
    -    kukit.pl.NativeEventBinder, '__bind__node', null, 'Each');
    -kukit.eventsGlobalRegistry.registerForAllEvents(null, 'change',
    -    kukit.pl.NativeEventBinder, '__bind__node', null, 'Each');
    -kukit.eventsGlobalRegistry.registerForAllEvents(null, 'reset',
    -    kukit.pl.NativeEventBinder, '__bind__node', null, 'Each');
    -kukit.eventsGlobalRegistry.registerForAllEvents(null, 'select',
    -    kukit.pl.NativeEventBinder, '__bind__node', null, 'Each');
    -kukit.eventsGlobalRegistry.registerForAllEvents(null, 'submit',
    -    kukit.pl.NativeEventBinder, '__bind__node', null, 'Each');
    -kukit.eventsGlobalRegistry.registerForAllEvents(null, 'keydown',
    -    kukit.pl.NativeEventBinder, '__bind_key__', null, 'Each');
    -kukit.eventsGlobalRegistry.registerForAllEvents(null, 'keypress',
    -    kukit.pl.NativeEventBinder, '__bind_key__', null, 'Each');
    -kukit.eventsGlobalRegistry.registerForAllEvents(null, 'keyup',
    -    kukit.pl.NativeEventBinder, '__bind_key__', null, 'Each');
    -//kukit.eventsGlobalRegistry.registerForAllEvents(null, 'unload',
    -//    kukit.pl.NativeEventBinder, '__bind__window', null, 'Each');
     
     /* XXX Example for using the interfaces registry
      *
      * The markup selects the part that should be parsed by the server.
      * Some info, that contains class names, should be outside this.
    - * (binditerations falls into this category, it is only needed
    + * (bindsequences falls into this category, it is only needed
      * on the client.)
      */
     
    @@ -349,12 +309,12 @@
         ['events', 'keydown', {
             defaultActionMethodName: null}],
     // END KSS REGISTRY
    -    ['binditerations', '', {
    +    ['bindsequences', '', {
             eventNames: ['click', 'dblclick'],
             iterName: 'Each',
             binderClass: kukit.pl.NativeEventBinder,
             bindMethodName:  '__bind_node'}],
    -    ['binditerations', '', {
    +    ['bindsequences', '', {
             eventNames: ['keyup', 'keydown'],
             iterName: 'Each',
             binderClass: kukit.pl.NativeEventBinder,
    @@ -373,12 +333,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');
    @@ -413,17 +374,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;
    @@ -470,7 +429,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,
    @@ -583,11 +542,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
    @@ -595,17 +550,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');
    @@ -618,8 +574,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;
    @@ -629,17 +584,74 @@
         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();
    +    var func = this.func_to_bind;
    +    func();
     };
    +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.registerForAllEvents(null, 'blur', kukit.pl.NativeEventBinder,
    +    '__bind__nodeorwindow', null, 'Each');
    +kukit.eventsGlobalRegistry.registerForAllEvents(null, 'focus', kukit.pl.NativeEventBinder,
    +    '__bind__nodeorwindow', null, 'Each');
    +kukit.eventsGlobalRegistry.registerForAllEvents(null, 'resize', kukit.pl.NativeEventBinder,
    +    '__bind__nodeorwindow', null, 'Each');
    +kukit.eventsGlobalRegistry.registerForAllEvents(null, 'click', kukit.pl.NativeEventBinder,
    +    '__bind__nodeordocument', null, 'Each');
    +kukit.eventsGlobalRegistry.registerForAllEvents(null, 'dblclick',
    +    kukit.pl.NativeEventBinder, '__bind__node', null, 'Each');
    +kukit.eventsGlobalRegistry.registerForAllEvents(null, 'mousedown',
    +    kukit.pl.NativeEventBinder, '__bind__nodeordocument', null, 'Each');
    +kukit.eventsGlobalRegistry.registerForAllEvents(null, 'mouseup',
    +    kukit.pl.NativeEventBinder, '__bind__nodeordocument', null, 'Each');
    +kukit.eventsGlobalRegistry.registerForAllEvents(null, 'mousemove',
    +    kukit.pl.NativeEventBinder, '__bind__nodeordocument', null, 'Each');
    +kukit.eventsGlobalRegistry.registerForAllEvents(null, 'mouseover',
    +    kukit.pl.NativeEventBinder, '__bind__node', null, 'Each');
    +kukit.eventsGlobalRegistry.registerForAllEvents(null, 'mouseout',
    +    kukit.pl.NativeEventBinder, '__bind__node', null, 'Each');
    +kukit.eventsGlobalRegistry.registerForAllEvents(null, 'change',
    +    kukit.pl.NativeEventBinder, '__bind__node', null, 'Each');
    +kukit.eventsGlobalRegistry.registerForAllEvents(null, 'reset',
    +    kukit.pl.NativeEventBinder, '__bind__node', null, 'Each');
    +kukit.eventsGlobalRegistry.registerForAllEvents(null, 'select',
    +    kukit.pl.NativeEventBinder, '__bind__node', null, 'Each');
    +kukit.eventsGlobalRegistry.registerForAllEvents(null, 'submit',
    +    kukit.pl.NativeEventBinder, '__bind__node', null, 'Each');
    +kukit.eventsGlobalRegistry.registerForAllEvents(null, 'keydown',
    +    kukit.pl.NativeEventBinder, '__bind_key__', null, 'Each');
    +kukit.eventsGlobalRegistry.registerForAllEvents(null, 'keypress',
    +    kukit.pl.NativeEventBinder, '__bind_key__', null, 'Each');
    +kukit.eventsGlobalRegistry.registerForAllEvents(null, 'keyup',
    +    kukit.pl.NativeEventBinder, '__bind_key__', null, 'Each');
    +//kukit.eventsGlobalRegistry.registerForAllEvents(null, 'unload',
    +//    kukit.pl.NativeEventBinder, '__bind__window', null, 'Each');
    +
    +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
    @@ -1121,7 +1133,7 @@
             old = oper.parms.className;
             has_old = true;
     ;;; var msg = 'Deprecated the [className] parameter in ' + oper.componentName;
    -;;; msg += ', use [value] instead !';
    +;;; msg += ', use [name] instead !';
     ;;; kukit.logWarning(msg); 
         }
         if (typeof(oper.parms.name) != 'undefined') {
    
    Modified: kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/providerreg.js
    ==============================================================================
    --- kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/providerreg.js	(original)
    +++ kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/providerreg.js	Tue Apr 15 11:35:22 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
    @@ -17,31 +17,42 @@
     * 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 (name) {
    -    this.name = name
    +this.initialize = function(name) {
    +    this.name = name;
     };
     
    -kukit.pr.ValueProviderRegistry.prototype.register = function(name, func) {
    +this.register = function(name, func, returnType) {
         if (typeof(func) == 'undefined') {
     ;;;     kukit.E = 'func argument is mandatory when registering a parameter'
     ;;;     kukit.E += ' provider [ValueProviderRegistry.register].';
             throw new Error(kukit.E);
         }
    +    if (typeof(returnType) == 'undefined') {
    +        // Default return type is string
    +        returnType = 'string';
    +    }
         // Always use the global interfaces to get the descriptor.
    -    var iface = kukit.interfaces.global.schema[this.name]; 
    -    iface.getAttribute(name).register({providerClass: func});
    +    var iface = kukit.pluginregistry.schema[this.name]; 
    +    iface.getAttribute(name).register({providerClass: func,
    +                                       returnType: returnType});
    +};
    +this.initialize.apply(this, arguments);
     };
     
    -kukit.pprovidersGlobalRegistry = new kukit.pr.ValueProviderRegistry('valueproviders');
    +}();                              /// MODULE END
     
    +kukit.corevalueproviders = new function() {   /// MODULE START
     /*
     * Register the core parameter providers
     *
    @@ -63,233 +74,309 @@
     * the string itself. This is by default defined as the identity function, but
     * can be overwritten to do something with the string value. The usage is that
     * this provider expects a single parameter, the string.
    +*
    +* XXX We want to register these classes from tests, so please keep all of them
    +* public in the closure.
    +*
     */
     
    -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
    +*/
    +
    +cvp = this;
    +
    +cvp.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
    +*/
    +cvp.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
    +*/
    +cvp.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);
     
    +};
     
    -/* 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 CurrentFormVarFromKssAttrPP
    +*/
    +cvp.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';
    +        recurseParents = kukit.ut.evalBool(args[1], kukit.E);
    +    }
    +    var formvarname = kukit.dom.getRecursiveAttribute(node, argname,
    +        recurseParents, kukit.dom.getKssAttribute);
    +    return kukit.fo.getFormVar(new kukit.fo.CurrentFormLocator(node),
    +        formvarname);
    +};
    +
    +};
    +
    +
    +/*
    +*  class NodeAttrPP
    +*/
    +cvp.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);
    +;;; }
    +};
    +
    +this.eval = function(args, node) {
    +    var argname = args[0];
    +;;; if (argname.toLowerCase() == 'style') {
    +;;;     throw new Error('nodeAttr method does not accept [style] as attrname.');
    +;;; }
    +;;; if (argname.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.';
    +        recurseParents = kukit.ut.evalBool(recurseParents, kukit.E);
         }
    +    return kukit.dom.getRecursiveAttribute(node, argname, recurseParents,
    +        kukit.dom.getAttribute);
     };
    -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 KssAttrPP
    +*/
    +cvp.KssAttrPP = function() {
    +
    +this.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]).';
    +;;;     throw new Error(kukit.E);
    +;;; }
    +};
    +
    +this.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);
    +;;; }
    +};
    +
    +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.';
    +        recurseParents = kukit.ut.evalBool(recurseParents, kukit.E);
         }
    +    return kukit.dom.getRecursiveAttribute(node, argname, recurseParents,
    +        kukit.dom.getKssAttribute);
     };
    -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);
    -;;;     }
    -    },
    -    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);
    -        }
    -        if (args[0].toLowerCase() == 'style') {
    -;;;         kukit.E = 'nodeAttr method does not accept [style] as attrname.';
    -            throw new Error(kukit.E);
    -        }
    -        if (args[0].match(/[ ]/)) {
    -;;;         throw new Error('attrname parameter in nodeAttr method cannot contain space.');
    -            throw new Error(kukit.E);
    -        }
    -        return kukit.dom.getRecursiveAttribute(node, argname, recurseParents,
    -            kukit.dom.getAttribute);
    +};
    +
    +/*
    +*  class NodeContentPP
    +*/
    +cvp.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);
     };
    -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);
    -;;;     }
    -    },
    -    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);
    -        }
    -        if (args[0].match(/[ -]/)) {
    -;;;         kukit.E = 'attrname parameter in kssAttr method cannot contain';
    -;;;         kukit.E += ' dashes or spaces.';
    -            throw new Error(kukit.E);
    -        }
    -        return kukit.dom.getRecursiveAttribute(node, argname, recurseParents,
    -            kukit.dom.getKssAttribute);
    +};
    +
    +/*
    +*  class StateVarPP
    +*/
    +cvp.StateVarPP = function() {
    +
    +this.check = function(args) {
    +;;; if (args.length != 1) {
    +;;;     throw new Error('stateVar method needs 1 argument [varname].');
    +;;; }
    +};
    +
    +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('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 PassPP
    +*/
    +cvp.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('nodeContent', kukit.pr.NodeContentPP);
     
    -kukit.pr.StateVarPP = function() {};
    -kukit.pr.StateVarPP.prototype = {
    -    check: function(args) {
    +};
    +
    +
    +/* The url() provider just passes the parameter, 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.
    + */
    +cvp.UrlPP = function() {
    +    this.check = function(args) {
     ;;;     if (args.length != 1) {
    -;;;         throw new Error('stateVar method needs 1 argument [varname].');
    +;;;         throw new Error('url() needs 1 argument.');
     ;;;     }
    -    },
    -    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);
    +cvp.UrlPP.prototype = new cvp.IdentityPP();
    +
     
    -kukit.pr.PassPP = function() {};
    -kukit.pr.PassPP.prototype = {
    -    check: function(args) {
    +/* The alias() provider just passes the parameter, and is used to have
    + * a different return type. It can be used in the line of action-client.
    + */
    +cvp.AliasPP = function() {
    +    this.check = function(args) {
     ;;;     if (args.length != 1) {
    -;;;         throw new Error('pass method needs 1 argument [attrname].');
    +;;;         throw new Error('alias() needs 1 argument.');
     ;;;     }
    -    },
    -    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;
    -    }
    +;;;     if (! args[0].check_remarks.isStatic) {
    +;;;         kukit.E = 'Value providers are not ';
    +;;;         kukit.E += 'allowed as argument for ';
    +;;;         kukit.E += 'alias(), [' + args[0].methodName + '] found.';
    +;;;         throw new Error(kukit.E);
    +;;;     }
    +    };
     };
    -kukit.pprovidersGlobalRegistry.register('pass', kukit.pr.PassPP);
    +cvp.AliasPP.prototype = new cvp.IdentityPP();
    +
    +
    +kukit.pprovidersGlobalRegistry = new kukit.pr.ValueProviderRegistry('valueproviders');
    +
    +kukit.pprovidersGlobalRegistry.register('', cvp.IdentityPP);
    +kukit.pprovidersGlobalRegistry.register('currentFormVar',
    +    cvp.CurrentFormVarPP);
    +kukit.pprovidersGlobalRegistry.register('currentFormVarFromKssAttr',
    +    cvp.CurrentFormVarFromKssAttrPP);
    +kukit.pprovidersGlobalRegistry.register('formVar', cvp.FormVarPP);
    +kukit.pprovidersGlobalRegistry.register('kssAttr', cvp.KssAttrPP);
    +kukit.pprovidersGlobalRegistry.register('stateVar', cvp.StateVarPP);
    +kukit.pprovidersGlobalRegistry.register('pass', cvp.PassPP);
    +kukit.pprovidersGlobalRegistry.register('nodeContent', cvp.NodeContentPP);
    +kukit.pprovidersGlobalRegistry.register('nodeAttr', cvp.NodeAttrPP);
    +// returnType = 'url'
    +kukit.pprovidersGlobalRegistry.register('url', cvp.UrlPP, 'url');
    +// returnType = 'alias'
    +kukit.pprovidersGlobalRegistry.register('alias', cvp.AliasPP, 'alias');
    +
    +}();                              /// MODULE END
     
    
    Modified: kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/requestmanager.js
    ==============================================================================
    --- kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/requestmanager.js	(original)
    +++ kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/requestmanager.js	Tue Apr 15 11:35:22 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 (name, maxNr, 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;
         }
    @@ -163,9 +189,12 @@
             nameString = '[' + name + '] ';
             }
         this.nameString = nameString;
    -    if (typeof(maxNr) != 'undefined' && maxNr != null) {
    -        this.maxNr = maxNr;
    +    // max request number
    +    if (typeof(maxNr) == 'undefined' || maxNr == null) {
    +        // Default is 4
    +        maxNr = 4;
         }
    +    this.maxNr = maxNr;
         // sets the timeout scheduler
         var checkTimeout = function() {
            self.checkTimeout();
    @@ -176,27 +205,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 +233,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 +253,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 +271,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 +288,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 +297,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 +324,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 +337,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 +346,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 +364,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 +379,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/branch/ree-service-layer-and-refactoring/kukit/resourcedata.js
    ==============================================================================
    --- kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/resourcedata.js	(original)
    +++ kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/resourcedata.js	Tue Apr 15 11:35:22 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,7 +19,9 @@
     
     /* Supplemental data that the parser builds up */
     
    -kukit.rd = {};
    +kukit.rd = new function() {   /// MODULE START
    +
    +var rd = this;
     
     /*
      * Function constructMergeId
    @@ -28,14 +30,16 @@
      * and the bind key. The bind key can have any characters since
      * it contains the id.
      */
    -kukit.rd.constructMergeId = function(name, bindKey) {
    +rd.constructMergeId = function(name, bindKey) {
         return name + '@' + bindKey;
     };
     
     /*
     *  class KssSelector
     */
    -kukit.rd.KssSelector = function(isEvent, css, name, id, ppid, interfaces) {
    +rd.KssSelector = function() {
    +
    +this.initialize = function(isEvent, css, name, id, ppid, registry) {
         this.isEventSelector = isEvent;
         this.isMethodSelector = ! isEvent;
     // XXX GC row and column are wrong...
    @@ -69,23 +73,20 @@
         this.bindKey = null;
         this.bindIteration = null;
         // 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.
         //
         // Perform checking based on the registry
    -    this.checkRegistry(interfaces);
    +    this.checkRegistry(registry);
     };
     
    -kukit.rd.KssSelector.prototype.checkRegistry = function(interfaces) {
    +this.checkRegistry = function(registry) {
         // Sets up id and class on the selector, based on registration info
         // This will throw errors if the event is not in the registry.
         //
         // It will also bind the selector to operate on this registry
         // ie. lookups are used from there.
         //
    -    // Store theinterfaces.
    -    this.interfaces = interfaces;
    +    // Store the valid registry we use
    +    this.registry = registry;
         // We prepare the id a bit. If there is no ppid specified,
         // we can already produce the mergeId here.
         // This is called from init.
    @@ -101,7 +102,7 @@
             // id should be merged on the same node.
             // Statically setting it here means we never have to look
             // at it depending on nodes.
    -        // This step will access the interfaces already
    +        // This step will access the registry already
             // by calling getBindIteration.
             this.bindKey = this.getBindKey();
             this.mergeId = this.getMergeId();
    @@ -117,17 +118,17 @@
         // Now we check the plugin part of the registry: this may not be
         // necessary but this way we reject an event which has the binder
         // set up, but has no actual event information.
    -    var events = this.interfaces.events[this.name];
    +    var events = registry.events[this.name];
         if (typeof(events) == 'undefined') {
     ;;;     kukit.E = 'Error : undefined event [' + this.name + '].';
             throw kukit.err.pluginRegistryError(null, kukit.E);
         } 
     };
     
    -kukit.rd.KssSelector.prototype.prepareId = function() {
    +this.prepareId = function() {
     };
     
    -kukit.rd.KssSelector.prototype.getId = function(node) {
    +this.getId = function(node) {
         // Gives the id depending on a node.
          if (this.ppid == null) {
             // Statically set.
    @@ -147,13 +148,13 @@
         }
     };
     
    -kukit.rd.KssSelector.prototype.getBindIteration = function() {
    +this.getBindIteration = function() {
         // Returns the bind iteration set up for this kss selector. This
         // depends on the event name only, but it needs access to the
         // registry, so we cache this result.
         if (! this.bindIteration) {
             // Look up the binder class from the registry.
    -        this.bindIteration = this.interfaces.binditerations[this.name];
    +        this.bindIteration = this.registry.bindsequences[this.name];
             if (typeof(this.bindIteration) == 'undefined') {
     ;;;         kukit.E = 'undefined or unbindable event (no iteration found) [' + this.name + '].';
                 throw kukit.err.pluginRegistryError(null, kukit.E);
    @@ -162,7 +163,7 @@
         return this.bindIteration;
     };
     
    -kukit.rd.KssSelector.prototype.getMergeId = function(node) {
    +this.getMergeId = function(node) {
         // Gives the merge id depending on a node.
         // This id will identify what other rules this rule can merge
         // with, if they match on the same node. Only rules with the same
    @@ -178,7 +179,7 @@
         }
     };
     
    -kukit.rd.KssSelector.prototype.getBindKey = function(node) {
    +this.getBindKey = function(node) {
         // Gives the bind key depending on a node.
         // This key identifies the binder instance on which
         // selector will operate. Therefore it consists of the
    @@ -200,99 +201,18 @@
             return className + '@' + id;
         }
     };
    -
    -
    -
    -/*
    -* Kss parameter values. There are two kinds: text and method.
    -*
    -* They are evaluated in two phases: check is invoked at parsing,
    -* allowing the early detection of errors. Evaluate is called
    -* when the action is to be called. This allows a kss method
    -* to add any parameter to the action.
    -*/
    -
    -/*
    -*  class KssTextValue
    -*/
    -kukit.rd.KssTextValue = function(txt) {
    -    // A text parameter in the format 
    -    //      key: value;
    -    this.txt = txt;
    +this.initialize.apply(this, arguments);
     };
     
    -kukit.rd.KssTextValue.prototype.isMethod = false;
     
    -kukit.rd.KssTextValue.prototype.check = function(iface) {
    -    // use the IdentityPP provider.
    -    this.pprovider = new (iface['']).providerClass();
    -};
    -
    -kukit.rd.KssTextValue.prototype.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);
    -};
    -
    -/*
    -*  class KssMethodValue
    -*/
    -kukit.rd.KssMethodValue = 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(iface) {
    -    // Check syntax
    -    var f = iface[this.methodName];
    -    // Check if the method name really existed.
    -    if (! f || ! f.providerClass) {
    -;;;     kukit.E = 'Undefined value provider [';
    -;;;     kukit.E += this.methodName + '].';
    -        throw kukit.err.pluginRegistryError(null, kukit.E);
    -    }
    -    // Create the provider checker and evaluator object
    -    this.pprovider = new f.providerClass();
    -    // Check the providers, this will give errors
    -    // in case something is wrong with the parameters.
    -    // Checking is also needed in production mode.
    -    // XXX We use global interfaces
    -    var interfaces = kukit.interfaces.global;
    -    var valueproviders = interfaces.valueproviders;
    -    for(i=0; i < this.args.length; i++){
    -        // With the recursion we always use the
    -        // value provider registry from the same interfaces
    -        this.args[i].check(valueproviders);
    -    }
    -;;; // Checking of the value provider itself (nr of args)
    -;;; this.pprovider.check(this.args);
    -};
    -
    -kukit.rd.KssMethodValue.prototype.evaluate =
    -    function(node, defaultParameters) {
    -    // First recursively evaluate all arguments
    -    var newArgs = [];
    -    for(var i=0; i < this.args.length; i++){
    -        var arg = this.args[i];
    -        newArgs.push(arg.evaluate(node, defaultParameters));
    -    }
    -    // return the value
    -    return this.pprovider.eval(newArgs, node, defaultParameters);
    -};
    -
    -
    -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
    @@ -300,9 +220,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;
    @@ -318,7 +238,7 @@
         }
     };
     
    -kukit.rd.EventRule.prototype.getIndex = function() {
    +this.getIndex = function() {
         if (this.mergedIndex) {
             return this.mergedIndex;
         } else {
    @@ -326,7 +246,7 @@
         }
     };
     
    -kukit.rd.EventRule.prototype.mergeForSelectedNodes = 
    +this.mergeForSelectedNodes = 
         function(ruletable, phase, inNodes) {
     
         // Select all nodes within the inNodes for phase==2.
    @@ -370,7 +290,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();
    @@ -385,7 +305,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;
    @@ -396,19 +316,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);
    @@ -416,7 +335,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');
     ;;; }
    @@ -444,7 +363,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
    @@ -463,29 +382,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, [';
    @@ -506,7 +430,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!
    @@ -528,17 +452,40 @@
         }
     };
     
    -kukit.rd.ActionSet.prototype.getOrCreateAction = function(name) {
    +this.getOrCreateAction = function(name, valuesByReturnType) {
    +    // kss parameters will ve set from valuesByReturnType 
    +    //
    +    // In case we alias, use the alias for name, this will become
    +    // the action name used for execution. The alias name will
    +    // be used as name, and serve for decide merging.
    +    var nameOverride;
    +    if (valuesByReturnType.alias) {
    +        nameOverride = name;
    +        // This is always a string, no provider allowed.
    +        name = valuesByReturnType.alias.args[0].txt;
    +    }
    +    // Check if we have this action already
         var action = this.content[name];
         if (typeof(action) == 'undefined') {
    -        action = new kukit.rd.Action();
    -        action.setName(name);
    +        action = new _Action();
    +        action.setName(name, nameOverride);
             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;
     };
     
    -kukit.rd.ActionSet.prototype.getActionOrNull = function(name) {
    +this.getActionOrNull = function(name) {
         var action = this.content[name];
         if (typeof(action) == 'undefined') {
             action = null;
    @@ -546,7 +493,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.');
    @@ -555,33 +502,77 @@
     
     };
     
    -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;
    +    this.nameOverride = null;
     };
     
    -kukit.rd.Action.prototype.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?)';
    -;;;     throw kukit.err.ruleMergeError(msg);
    +this.getExecutingName = function getExecutingName() {
    +    // Returns action name that is to be used for execution.
    +    // In case nameOverride is empty, name is used both as merging
    +    // key, and for selecting the action at execution.
    +    // In case nameOverride is specified, name is still used for
    +    // merging, but nameOverride is used when we need to
    +    // execute the action.
    +    // This is used for  action-client: nameOverride alias(name).
    +    return this.nameOverride || this.name;
    +};
    +
    +this.setName = function(name, nameOverride) {
    +    if (typeof(nameOverride) == 'undefined' || name == nameOverride) {
    +        // use null for no-value.
    +        //
    +        // Also: If we alias to the same name as the action name,
    +        // simply ignore aliasing and just handle the real action.
    +        nameOverride = null;
    +    }
    +;;; // We check that the name did not change.
    +;;; if (this.name != null) {
    +;;;     if (this.name != name) {
    +;;;         kukit.E = 'Error overriding action name [' + this.name;
    +;;;         kukit.E += '] to [' + name + '] (Unmatching action names or aliases at merge?)';
    +;;;         throw kukit.err.ruleMergeError(kukit.E);
    +;;;     }
    +;;;     // nameOverride can only be specified when name is also specified.
    +;;;     // We also check that the override cannot change, ie. it is not
    +;;;     // possible to use the same alias for different actions.
    +;;;     // However we allow this.nameOverride to have a value and nameOverride
    +;;;     // to be null.
    +;;;     if (nameOverride != null && this.nameOverride != nameOverride) {
    +;;;         kukit.E = 'Error overriding action name for alias [' + this.name;
    +;;;         kukit.E += '] from [' + this.nameOverride;
    +;;;         kukit.E += '] to [' + nameOverride + '] ';
    +;;;         kukit.E += '(Different actions aliased by the same alias?)';
    +;;;         throw kukit.err.ruleMergeError(kukit.E);
    +;;;     }
     ;;; }
    +    // Store the values.
         this.name = name;
    +    // nameOverride is only overwritten if value exists.
    +    if (nameOverride != null) {
    +        this.nameOverride = nameOverride;
    +    }
    +    // Handle default action.
         if (name == 'default') {
     ;;;     if (this.type != null && this.type != 'D') {
     ;;;         var msg = 'Error setting action to default on action [' + this.name;
    @@ -592,7 +583,7 @@
         }
     };
     
    -kukit.rd.Action.prototype.setType = function(type) {
    +this.setType = function(type) {
         // Allowed types:
         //
         // S = server
    @@ -621,7 +612,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.';
    @@ -630,10 +621,11 @@
         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);
    +        // We also use nameOverride from the other.
    +        this.setName(other.name, other.nameOverride);
         }
         if (other.type != null) { 
             this.setType(other.type);
    @@ -647,7 +639,18 @@
         }
     };
     
    -kukit.rd.Action.prototype.makeActionOper = function(oper) {
    +// 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")
    +//
    +var _defaultStringHandling = {
    +    'kssSelector': 'css',
    +    'kssSubmitForm': 'form'
    +};
    +
    +this.makeActionOper = function(oper) {
         // Fill the completed action parms, based on the node
         // The kssXxx parms, reserved for the action, are 
         // handled as appropriate.
    @@ -658,16 +661,32 @@
         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 = _defaultStringHandling[key];
    +        if (providerName && typeof(value) == 'string') {
    +            // Use the value provider. This means the string is
    +            // a shortcut and this provider is applied.
    +            // global registry is used
    +            var registry = kukit.pluginregistry;
    +            var valueproviders = registry.valueproviders;
    +            var provider = new valueproviders[providerName].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({
    @@ -678,7 +697,7 @@
         return anOper;
     };
     
    -kukit.rd.Action.prototype.execute = function(oper) {
    +this.execute = function(oper) {
         oper = this.makeActionOper(oper);
         switch (this.type) {
             case 'D': {
    @@ -692,7 +711,9 @@
             } break;
             case 'C': {
                 // Client action.
    -            oper.executeClientAction(this.name);
    +            // Need to execute the real name,
    +            // since aliasing is possible here.
    +            oper.executeClientAction(this.getExecutingName());
             } break;
             case 'E': {
                 // Error action (= client action)
    @@ -700,31 +721,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();
    @@ -734,7 +759,7 @@
         }
     };
     
    -kukit.rd.LoadActions.prototype.executeAll = function() {
    +this.executeAll = function() {
         var i = 0;
         while(true) {
             var success = this.execute();
    @@ -745,7 +770,8 @@
         }
         return i;
     };
    -
    +this.initialize.apply(this, arguments);
    +};
     
     /*
     *  class RuleTable
    @@ -770,14 +796,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': {}};
    @@ -788,7 +816,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) {
    @@ -811,9 +839,12 @@
         }
     };
     
    -kukit.rd.uid = 0;
    +this.initialize.apply(this, arguments);
    +};
    +
    +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
    @@ -824,9 +855,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;
     };
    @@ -839,13 +870,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];
    @@ -858,7 +891,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, 
    @@ -880,7 +913,7 @@
         return mergedRule;
     };
     
    -kukit.rd.MethodTable.prototype.bindall = function() {
    +this.bindall = function() {
         // bind document events
         var documentRules = this.content['document'];
         var counter = 0;
    @@ -891,3 +924,8 @@
         }
     ;;; kukit.logDebug(counter + ' rules bound to document.');
     };
    +
    +this.initialize.apply(this, arguments);
    +};
    +
    +}();                              /// MODULE END
    
    Modified: kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/selectorreg.js
    ==============================================================================
    --- kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/selectorreg.js	(original)
    +++ kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/selectorreg.js	Tue Apr 15 11:35:22 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
    @@ -17,61 +17,80 @@
     * 02111-1307, USA.
     */
     
    -kukit.sr = {};
    +kukit.sr = new function() {   /// MODULE START
    +
    +var sr = this;
    +
    +// Registry of the pprovider functions for selecting
    +
    +// XXX XXX XXX TODO factor this with selector reg
    +sr.pproviderSelRegistry = new kukit.pr.ValueProviderRegistry('selectorproviders'); 
    +
    +/*
    +* class _AnyPP
    +*
    +* This will provide an arbitrary selector, and is designed to
    +* be used with the makeAnyPP factory function.
    +*
    +*/
    +var _AnyPP = function(selectorFunc) {
     
    -// this will provide an arbitrary selector, and is designed to
    -// be used with the makeAnyPP factory function.
    -kukit.sr.AnyPP = function(selectorFunc) {
         this.selectorFunc = selectorFunc;    
    +
    +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) {
    +    // 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 this.selectorFunc(args[0], node, defaultParameters, node);
     };
     
    -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) {
    -        // 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 this.selectorFunc(args[0], node, defaultParameters, node);
    -    }
     };
     
    -kukit.sr.makeAnySelectorProvider = function(selectorFunc) {
    +sr.makeAnySelectorProvider = function(selectorFunc) {
          var providerClass = function() {};
    -     providerClass.prototype = new kukit.sr.AnyPP(selectorFunc);
    +     providerClass.prototype = new _AnyPP(selectorFunc);
          return providerClass;
     };
     
    -// 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;
     };
    -var iface = kukit.interfaces.global.schema.selectors;
    +
    +};
    +
    +var iface = kukit.pluginregistry.schema.valueproviders;
     iface.getAttribute('passnode').register({
    -        providerClass: kukit.sr.PassnodePP});
    +        providerClass: sr.PassnodePP,
    +        returnType: 'selection'});
     // the item now will contain providerClass only,
     // as passnode is only allowed from the kss file, not as a command selector.
     
    -
     /* 
     * class SelectorTypeRegistry 
     *
    @@ -82,10 +101,12 @@
     *  kukit.selectorTypesGlobalRegistry.register(name, func);
     *
     */
    -kukit.sr.SelectorTypeRegistry = function () {
    +var _SelectorTypeRegistry = function () {
    +
    +this.initialize = function() {
     };
     
    -kukit.sr.SelectorTypeRegistry.prototype.register = function(name, selectorFunc) {
    +this.register = function(name, selectorFunc) {
     ;;; // Check func parameter: diagnostics only, as this will cause
     ;;; // an error later anyway.
     ;;; if (typeof(selectorFunc) == 'undefined') {
    @@ -93,23 +114,29 @@
     ;;;     throw new Error(kukit.E);
     ;;; }
         // Also register the selector param provider
    -    var iface = kukit.interfaces.global.schema.selectors;
    -    var providerClass = kukit.sr.makeAnySelectorProvider(selectorFunc);
    +    var iface = kukit.pluginregistry.schema.valueproviders;
    +    var providerClass = sr.makeAnySelectorProvider(selectorFunc);
         iface.getAttribute(name).register({
             providerClass: providerClass,
    -        selectorFunc: selectorFunc});
    +        selectorFunc: selectorFunc,
    +        returnType: 'selection'});
         // the item now will contain providerClass and selectorFunc as well
     };
     
    -kukit.sr.SelectorTypeRegistry.prototype.get = function(name) {
    -    var info = kukit.interfaces.global.selectors[name];
    -;;; if (! info || ! info.selectorFunc) {
    +this.get = function(name) {
    +    var info = kukit.pluginregistry.valueproviders[name];
    +;;; if (! info || ! info.returnType == 'selection' || ! info.selectorFunc) {
     ;;;    throw new Error('Unknown selector type "' + name + '"');
     ;;; }
         return info.selectorFunc;
     };
    +this.initialize.apply(this, arguments);
    +};
    +
    +_SelectorTypeRegistry.prototype.defaultSelectorType = 'css';
     
    -kukit.selectorTypesGlobalRegistry = new kukit.sr.SelectorTypeRegistry();
    +
    +kukit.selectorTypesGlobalRegistry = new _SelectorTypeRegistry();
     
     kukit.selectorTypesGlobalRegistry.register('htmlid', function(expr, node) {
         var nodes = [];
    @@ -126,17 +153,6 @@
         return nodes;
     });
     
    -// Since css is the default selector, copy the provider class
    -// to the identity function. That is, if the selector is 
    -// not css() htmlid() etc. but a string, 
    -// we use the default selector, css.
    -//
    -//var iface = kukit.interfaces.global.schema.selectors;
    -var css_config = iface.getAttribute('css').config
    -iface.getAttribute('').register(css_config);
    -
    -// the item now will contain providerClass and selectorFunc: both are needed. 
    -
     kukit.selectorTypesGlobalRegistry.register('samenode', function(expr, node) {
         nodes = [node];
         return nodes;
    @@ -167,3 +183,7 @@
         }
         return results;
     });
    +
    +
    +}();                              /// MODULE END
    +
    
    Modified: kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/serveraction.js
    ==============================================================================
    --- kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/serveraction.js	(original)
    +++ kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/serveraction.js	Tue Apr 15 11:35:22 2008
    @@ -17,19 +17,53 @@
     * 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.calculateAbsoluteURL = function(url) {
    +        // Append slash to the end of the url, this helps with certain
    +        // webframeworks like Django
    +        if (!url.match(RegExp('\/$'))) {
    +            url += '/';
    +        }
    +
    +        //
    +        // If the url is an absolute path, it is used
    +        //
    +        // If the url is not an absolute path, it is put at the end of the context
    +        // url.
    +        //
    +        // example: url='@theview/getName',
    +        //          context='http://your.site.com/portal/folder/object'
    +        //
    +        //     result='http://your.site.com/portal/folder/object/@@theview/getName'
    +        //
    +        if (url.match(RegExp('/^https?:\/\//')) || url.match(RegExp('^\/'))) {
    +            return url;
    +        } 
    +
    +        var result = kukit.engine.baseUrl;
    +        if (!result.match(RegExp('\/$'))) {
    +            result += '/';
    +        }
    +
    +        return result + url;
    +    };
         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
         //
    @@ -44,13 +78,13 @@
         if (url.match(RegExp('/^https?:\/\//'))) {
             return url;
         } else {
    -        var result = kukit.engine.baseUrl + '/' + url;
    +        var result = kukit.engine.baseUrl + url;
             return result;
         }
     };
     
     // 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 +99,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 +134,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) {
    @@ -130,10 +164,10 @@
                     }
                 }
             }
    -    }
    +    };
     };
     
    -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 = [];
    @@ -160,9 +194,86 @@
                 }
                 commandstags = kukit.dom.getNsTags(dom, 'commands');
                 if (commandstags.length != 1) {
    -                // no good
    +                // no good, maybe better luck with it as html payload
                     dom = null;
                 }
    +        }
    +        // Check for html too, this enables setting the kss error command on the 
    +        // error response.
    +        if (dom == null) {
    +            // Read the header and load it as xml, if defined.
    +            var payload = domDoc.getResponseHeader('X-KSSCOMMANDS');
    +            if (payload) {
    +                try {
    +                    dom = (new DOMParser()).parseFromString(payload, "text/xml");
    +                } catch(e) {
    +;;;                 kukit.E = 'Error parsing X-KSSCOMMANDS header.';
    +                    throw kukit.err.responseParsingError(kukit.E);
    +                }
    +                commandstags = kukit.dom.getNsTags(dom, 'commands');
    +                if (commandstags.length != 1) {
    +                    // no good
    +                    dom = null;
    +                }
    +            } else {
    +                // Ok. we have not found it either in the headers.
    +                // Check if there was a parsing error in the xml, 
    +                // and log it as reported from the dom
    +                // Opera <= 8.5 does not have the parseError attribute,
    +                // so check for it first
    +;;;             dom = domDoc.responseXML;
    +;;;             kukit.E = 'Unknown server error (invalid KSS response, no error';
    +;;;             kukit.E += ' info received)';
    +;;;             if (dom && dom.parseError && (dom.parseError != 0)) {
    +;;;                 kukit.E += ' : ' + Sarissa.getParseErrorText(dom);
    +;;;                 }
    +                throw kukit.err.responseParsingError(kukit.E);
    +            }
    +        }
    +        if (dom == null) {
    +            // this should not happen
    +;;;         kukit.E = 'Neither xml nor html payload.';
    +            throw kukit.err.responseParsingError(msg);
    +        }
    +        // find the commands (atm we don't limit ourselves inside the commandstag)
    +        var commands = kukit.dom.getNsTags(dom, 'command');
    +        // Warning, if there is a valid response containing 0 commands.
    +        if (commands.length == 0) {
    +;;;         kukit.log('No commands in kukit response');
    +            return;
    +        }
    +        // 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();
    +    };
    +
    +    this.processError = function(errorcommand) {
    +        var error_action = null;
    +        if (this.oper.eventRule) {
    +            var error_action = this.oper.eventRule.actions.getErrorActionFor(
    +                this.oper.action);
    +            }
    +;;;     var reason = '';
    +;;;     if (typeof(errorcommand) == 'string') {
    +;;;         // not a command, just a string
    +;;;         reason = ', client_reason="' + errorcommand + '" ';
    +;;;     } else if (typeof(errorcommand) != 'undefined') {
    +;;;         // a real error command, sent by the server
    +;;;         // as kukit payload.
    +;;;         // this way the server sends whatever message he wants as a parameter
    +;;;         // to the error command.
    +;;;         reason = ', server_reason="' + errorcommand.parms.message + '" ';
    +;;;     }
    +        if (error_action) {
    +;;;         kukit.E = 'Request failed at url ' + this.oper.queueItem.url;
    +;;;         kukit.E += ', rid=' + this.oper.queueItem.rid + reason;
    +;;;         kukit.E += ', will be handled by action "' + error_action.name + '"';
    +;;;         kukit.logWarning(kukit.E);
    +            // Individual error handler was defined. Execute it!
    +            error_action.execute(this.oper);
             } else {
                 // Ok. we have not found it either in the headers.
                 // Check if there was a parsing error in the xml, 
    @@ -193,10 +304,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 +348,7 @@
             // TODO figure out something?
         }
     };
    +this.initialize.apply(this, arguments);
    +};
     
    +}();                              /// MODULE END
    
    Modified: kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/service.js
    ==============================================================================
    --- kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/service.js	(original)
    +++ kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/service.js	Tue Apr 15 11:35:22 2008
    @@ -2,14 +2,15 @@
     
     new function() {  // BEGIN CLOSURE service
     
    -var core = kukit.interfaces.global.schema.core;
    +var core = kukit.service.schema.core;
    +
     
     // Requirements towards core services. It contains
     // kukit's preferences to choose between sources
     // that implement a given functionality.
     
     core.getAttribute('cssQuery').require({
    -    preferredSources: ['base2', 'cssQuery'],
    +    preferredSources: ['base2', 'base2-legacy', 'cssQuery'],
         // a parameter checker common for each implementation
         checker: function(selector, inNodes) {
             // to eliminate possible errors
    @@ -44,6 +45,33 @@
             };
         }});
     
    +var _convertNodesToArray = function _convertNodesToArray(nodes) {
    +    var results = [];
    +    for(var i = 0; i < nodes.length; i++) {
    +        results.push(nodes.item(i));
    +    }
    +    return results;
    +};
    +
    +core.getAttribute('cssQuery').provide({
    +    sourceName: 'base2-legacy', 
    +    sourceVersion: '<<20020070816', 
    +    getter: function() {
    +        // Detect if base2 is present
    +        //
    +        if ((typeof(base2) == 'undefined') ||
    +            typeof(base2.DOM.Document.querySelectorAll) != 'undefined') {
    +            return;
    +        }
    +        // return the method plug
    +        return function(selector, inNodes) {
    +            // global scope, always.
    +            // This is very bad. However the binding makes sure that
    +            // nodes once bound will never be bound again
    +            var results = base2.DOM.Document.matchAll(document, selector);
    +            return _convertNodesToArray(results);
    +        };
    +    }});
     
     core.getAttribute('cssQuery').provide({
         sourceName: 'base2', 
    @@ -51,7 +79,8 @@
         getter: function() {
             // Detect if base2 is present
             //
    -        if (typeof(base2) == 'undefined') {
    +        if ((typeof(base2) == 'undefined') ||
    +            typeof(base2.DOM.Document.querySelectorAll) == 'undefined') {
                 return;
             }
             // return the method plug
    @@ -59,12 +88,8 @@
                 // global scope, always.
                 // This is very bad. However the binding makes sure that
                 // nodes once bound will never be bound again
    -            var results = base2.DOM.Document.matchAll(document, selector);
    -            var nodes = [];
    -            for(var i = 0; i < results.length; i++) {
    -                nodes.push(results.item(i));
    -            }
    -            return nodes;
    +            var results = base2.DOM.Document.querySelectorAll(document, selector);
    +            return _convertNodesToArray(results);
             };
         }});
     
    
    Modified: kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/tokenizer.js
    ==============================================================================
    --- kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/tokenizer.js	(original)
    +++ kukit/kukit.js/branch/ree-service-layer-and-refactoring/kukit/tokenizer.js	Tue Apr 15 11:35:22 2008
    @@ -19,53 +19,61 @@
     
     /* 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.
     ;;; this.emitWrappedError(null, msg);
         throw new Error(kukit.E);
     };
     
    -;;; kukit.tk._TokenBase.prototype.emitWrappedError = function(e, msg) {
    +;;; this.emitWrappedError = function(e, 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, 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;
    +// Provide an empty initialize. This allows
    +// that the tokens will inherit it and are
    +// not forced to implement it themselves.
    +this.initialize = function() {
    +};
     
    -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;
    @@ -75,31 +83,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,92 @@
     
     /* 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);
    +};
    +
    +ut.calculateBase = function(documentInstance, pageLocation) {
    +    var base = '';
    +    // fetch base from specific link in case of ill situations
    +    // like default pages in Plone 
    +    var nodes = documentInstance.getElementsByTagName("link");
    +    if (nodes.length > 0) {
    +        for (var i=0; i 
             
    +        
    +        
    +
    +        
    +
    +        
    +
    +        
    +
             
     
             
             
    +