[Checkins] SVN: z3c.listjs/ Initial import.
Martijn Faassen
faassen at infrae.com
Tue Jan 6 15:36:22 EST 2009
Log message for revision 94552:
Initial import.
Changed:
A z3c.listjs/
A z3c.listjs/trunk/
A z3c.listjs/trunk/CHANGES.txt
A z3c.listjs/trunk/buildout.cfg
A z3c.listjs/trunk/setup.py
A z3c.listjs/trunk/src/
A z3c.listjs/trunk/src/z3c/
A z3c.listjs/trunk/src/z3c/__init__.py
A z3c.listjs/trunk/src/z3c/listjs/
A z3c.listjs/trunk/src/z3c/listjs/__init__.py
A z3c.listjs/trunk/src/z3c/listjs/configure.zcml
A z3c.listjs/trunk/src/z3c/listjs/ftesting.zcml
A z3c.listjs/trunk/src/z3c/listjs/ftests.py
A z3c.listjs/trunk/src/z3c/listjs/listjswidget.pt
A z3c.listjs/trunk/src/z3c/listjs/listjswidget_record.pt
A z3c.listjs/trunk/src/z3c/listjs/resources/
A z3c.listjs/trunk/src/z3c/listjs/resources/listjs.js
A z3c.listjs/trunk/src/z3c/listjs/testing.py
A z3c.listjs/trunk/src/z3c/listjs/widget.py
-=-
Added: z3c.listjs/trunk/CHANGES.txt
===================================================================
--- z3c.listjs/trunk/CHANGES.txt (rev 0)
+++ z3c.listjs/trunk/CHANGES.txt 2009-01-06 20:36:22 UTC (rev 94552)
@@ -0,0 +1,7 @@
+CHANGES
+*******
+
+0.1 (unreleased)
+================
+
+* Initial public release.
Added: z3c.listjs/trunk/buildout.cfg
===================================================================
--- z3c.listjs/trunk/buildout.cfg (rev 0)
+++ z3c.listjs/trunk/buildout.cfg 2009-01-06 20:36:22 UTC (rev 94552)
@@ -0,0 +1,12 @@
+[buildout]
+develop = .
+parts = test
+extends = http://grok.zope.org/releaseinfo/grok-0.14.cfg
+versions = versions
+
+[versions]
+
+[test]
+recipe = zc.recipe.testrunner
+eggs = z3c.listjs
+defaults = ['--tests-pattern', '^f?tests$', '-v']
Added: z3c.listjs/trunk/setup.py
===================================================================
--- z3c.listjs/trunk/setup.py (rev 0)
+++ z3c.listjs/trunk/setup.py 2009-01-06 20:36:22 UTC (rev 94552)
@@ -0,0 +1,30 @@
+from setuptools import setup, find_packages
+import sys, os
+
+def read(*rnames):
+ return open(os.path.join(os.path.dirname(__file__), *rnames)).read()
+
+setup(
+ name='z3c.listjs',
+ version='0.1dev',
+ description="A formlib list widget that uses Javascript",
+ classifiers=[],
+ keywords='',
+ author='Martijn Faassen',
+ author_email='faassen at startifact.com',
+ license='',
+ packages=find_packages('src'),
+ package_dir={'': 'src'},
+ namespace_packages=['z3c'],
+ include_package_data=True,
+ zip_safe=False,
+ install_requires=[
+ 'setuptools',
+ 'zope.schema',
+ 'zope.app.form',
+ 'grokcore.component',
+ 'hurry.resource',
+ 'hurry.zoperesource >= 0.3',
+ ],
+ entry_points={},
+ )
Added: z3c.listjs/trunk/src/z3c/__init__.py
===================================================================
--- z3c.listjs/trunk/src/z3c/__init__.py (rev 0)
+++ z3c.listjs/trunk/src/z3c/__init__.py 2009-01-06 20:36:22 UTC (rev 94552)
@@ -0,0 +1,7 @@
+# this is a namespace package
+try:
+ import pkg_resources
+ pkg_resources.declare_namespace(__name__)
+except ImportError:
+ import pkgutil
+ __path__ = pkgutil.extend_path(__path__, __name__)
Added: z3c.listjs/trunk/src/z3c/listjs/__init__.py
===================================================================
--- z3c.listjs/trunk/src/z3c/listjs/__init__.py (rev 0)
+++ z3c.listjs/trunk/src/z3c/listjs/__init__.py 2009-01-06 20:36:22 UTC (rev 94552)
@@ -0,0 +1 @@
+from z3c.listjs.widget import ListJsWidget
Added: z3c.listjs/trunk/src/z3c/listjs/configure.zcml
===================================================================
--- z3c.listjs/trunk/src/z3c/listjs/configure.zcml (rev 0)
+++ z3c.listjs/trunk/src/z3c/listjs/configure.zcml 2009-01-06 20:36:22 UTC (rev 94552)
@@ -0,0 +1,11 @@
+<configure
+ xmlns="http://namespaces.zope.org/zope"
+ xmlns:browser="http://namespaces.zope.org/browser">
+
+ <include package="hurry.zoperesource" />
+
+ <browser:resourceDirectory
+ name="z3c.listjs"
+ directory="resources" />
+
+</configure>
Added: z3c.listjs/trunk/src/z3c/listjs/ftesting.zcml
===================================================================
--- z3c.listjs/trunk/src/z3c/listjs/ftesting.zcml (rev 0)
+++ z3c.listjs/trunk/src/z3c/listjs/ftesting.zcml 2009-01-06 20:36:22 UTC (rev 94552)
@@ -0,0 +1,38 @@
+<configure
+ xmlns="http://namespaces.zope.org/zope"
+ i18n_domain="z3c.listjs"
+ package="z3c.listjs"
+ >
+
+ <include package="zope.app.zcmlfiles" file="meta.zcml" />
+ <include package="zope.securitypolicy" file="meta.zcml" />
+
+ <include package="zope.app.zcmlfiles" />
+ <include package="zope.app.authentication" />
+
+ <include package="z3c.listjs" />
+
+ <!-- Typical functional testing security setup -->
+ <securityPolicy
+ component="zope.securitypolicy.zopepolicy.ZopeSecurityPolicy"
+ />
+
+ <unauthenticatedPrincipal
+ id="zope.anybody"
+ title="Unauthenticated User"
+ />
+ <grant
+ permission="zope.View"
+ principal="zope.anybody"
+ />
+ <principal
+ id="zope.mgr"
+ title="Manager"
+ login="mgr"
+ password="mgrpw"
+ />
+
+ <role id="zope.Manager" title="Site Manager" />
+ <grantAll role="zope.Manager" />
+ <grant role="zope.Manager" principal="zope.mgr" />
+</configure>
Added: z3c.listjs/trunk/src/z3c/listjs/ftests.py
===================================================================
--- z3c.listjs/trunk/src/z3c/listjs/ftests.py (rev 0)
+++ z3c.listjs/trunk/src/z3c/listjs/ftests.py 2009-01-06 20:36:22 UTC (rev 94552)
@@ -0,0 +1,19 @@
+import unittest
+
+from zope.app.testing.setup import setUpTestAsModule, tearDownTestAsModule
+from zope.app.testing.functional import FunctionalDocFileSuite
+from z3c.listjs.testing import FunctionalLayer
+
+def setUp(test):
+ setUpTestAsModule(test, name='__builtin__')
+
+def test_suite():
+ globs = {}
+# readme = FunctionalDocFileSuite(
+# 'README.txt',
+# globs = globs,
+# setUp=setUp,
+# tearDown=tearDownTestAsModule,
+# )
+ readme.layer = FunctionalLayer
+ return unittest.TestSuite([readme])
Added: z3c.listjs/trunk/src/z3c/listjs/listjswidget.pt
===================================================================
--- z3c.listjs/trunk/src/z3c/listjs/listjswidget.pt (rev 0)
+++ z3c.listjs/trunk/src/z3c/listjs/listjswidget.pt 2009-01-06 20:36:22 UTC (rev 94552)
@@ -0,0 +1,35 @@
+<table border="0" class="sequencewidget"
+ tal:attributes="id string:${view/name}.table"
+ i18n:domain="zope">
+ <tr tal:repeat="widget view/widgets" class="list_item">
+ <td>
+ <input class="editcheck" type="checkbox"
+ tal:attributes="
+ name string:${view/name}.remove_${repeat/widget/index}"
+ tal:condition="view/need_delete" />
+ </td>
+ <td>
+ <span tal:define="error widget/error"
+ tal:replace="structure error" tal:condition="error" />
+ <input tal:replace="structure widget" />
+ </td>
+ </tr>
+ <tr tal:attributes="id string:${view/name}.buttons">
+ <td colspan="2">
+ <input type="button" value="Remove selected items"
+ tal:attributes="name string:${view/name}.remove;
+ onClick string:Z3C.listjs.remove('${view/name}')"
+ i18n:attributes="value remove-selected-items" />
+ <input type="button" value="Add foo"
+ tal:attributes="name string:${view/name}.add;
+ value view/addButtonLabel;
+ onClick string:Z3C.listjs.add('${view/name}')"
+ />
+ </td>
+ </tr>
+</table>
+<input type="hidden" tal:attributes="
+ name string:${view/name}.template;
+ id string:${view/name}.template;
+ value view/record_template" />
+<input tal:replace="structure view/marker" />
Added: z3c.listjs/trunk/src/z3c/listjs/listjswidget_record.pt
===================================================================
--- z3c.listjs/trunk/src/z3c/listjs/listjswidget_record.pt (rev 0)
+++ z3c.listjs/trunk/src/z3c/listjs/listjswidget_record.pt 2009-01-06 20:36:22 UTC (rev 94552)
@@ -0,0 +1,9 @@
+ <td>
+ <input class="editcheck" type="checkbox"
+ tal:attributes="
+ name string:${view/name}.remove_0" />
+ </td>
+ <td>
+ <input tal:replace="structure view/widgetTemplate" />
+ </td>
+
Added: z3c.listjs/trunk/src/z3c/listjs/resources/listjs.js
===================================================================
--- z3c.listjs/trunk/src/z3c/listjs/resources/listjs.js (rev 0)
+++ z3c.listjs/trunk/src/z3c/listjs/resources/listjs.js 2009-01-06 20:36:22 UTC (rev 94552)
@@ -0,0 +1,145 @@
+// create the top-level Z3C namespace if needed
+if (typeof Z3C == "undefined" || !Z3C) {
+ var Z3C = {};
+}
+
+// create a new namespace (under Z3C)
+Z3C.namespace = function(name) {
+ var ns = Z3C;
+ var parts = name.split(".");
+ if (parts[0] == "Z3C") {
+ parts = parts.slice(1);
+ }
+ for (var i = 0; i < parts.length; i++) {
+ var part = parts[i];
+ ns[part] = ns[part] || {};
+ ns = ns[part];
+ }
+ return ns;
+};
+
+(function() {
+ Z3C.namespace('listjs');
+
+ // return true if string starts with a prefix
+ var startswith = function(s, prefix) {
+ return (s.substring(0, prefix.length) == prefix);
+ };
+
+ // check whether a particular object is a number
+ var isNumber = function(o) {
+ return typeof o === 'number' && isFinite(o);
+ };
+
+ // change all numbers in a string with a dotted name to a new number
+ // also renumber remove_X
+ var renumber = function(s, nr) {
+ var i;
+ var fragment;
+ var fragments = s.split('.');
+ var result = [];
+ for (i = 0; i < fragments.length; i++ ) {
+ fragment = fragments[i];
+ if (isNumber(parseInt(fragment))) {
+ result[result.length] = nr.toString();
+ } else if (startswith(fragment, 'remove_')) {
+ result[result.length] = 'remove_' + nr.toString();
+ } else {
+ result[result.length] = fragment;
+ }
+ };
+ return result.join('.');
+ };
+
+
+ // simplistic implementation that doesn't understand
+ // multiple classes per element
+ var getElementsByClassName = function(class_name, root_el, tag) {
+ tag = tag || '*';
+
+ var result = [];
+ var elements = root_el.getElementsByTagName(tag);
+
+ for (var i = 0, len = elements.length; i < len; ++i) {
+ if (elements[i].className) {
+ result[result.length] = elements[i];
+ }
+ }
+ return result;
+ };
+
+ // number all relevant attributes under el with nr
+ var updateNumbers = function(el, nr, prefix) {
+ // optimization - skip non-element nodes (ELEMENT_NODE 1)
+ if (el.nodeType != 1) {
+ return;
+ }
+ var i;
+ var attributes = ['id', 'name', 'for'];
+ for (i = 0; i < attributes.length; i++) {
+ attr = el.getAttribute(attributes[i]);
+ if (attr && startswith(attr, prefix)) {
+ el.setAttribute(attributes[i], renumber(attr, nr));
+ }
+ }
+ // recursion
+ var node = el.firstChild;
+ while (node) {
+ updateNumbers(node, nr, prefix);
+ node = node.nextSibling;
+ }
+ };
+
+ // update all numbers in el root
+ var updateAllNumbers = function(prefix) {
+ var table_el = document.getElementById(prefix + '.table');
+ // update numbering in table
+ var els = getElementsByClassName('list_item', table_el, 'tr');
+ var i;
+ for (i = 0; i < els.length; i++) {
+ updateNumbers(els[i], i, 'form.');
+ }
+ // update count
+ var count_el = document.getElementById(prefix + '.count');
+ count_el.value = els.length;
+ }
+
+ // add a new repeating element to the list
+ Z3C.listjs.add = function(prefix) {
+ var table_el = document.getElementById(prefix + '.table');
+ var template_el = document.getElementById(prefix + '.template');
+ var template_text = template_el.value;
+ var buttons_el = document.getElementById(prefix + '.buttons');
+
+ var new_tr = document.createElement('tr');
+ new_tr.className = 'list_item';
+ buttons_el.parentNode.insertBefore(new_tr, buttons_el);
+ new_tr.innerHTML = template_text;
+
+ updateAllNumbers(prefix);
+ };
+
+ // remove all selected repeating elements from the list
+ Z3C.listjs.remove = function(prefix) {
+ var table_el = document.getElementById(prefix + '.table');
+
+ // find all elements that are checked
+ var els = getElementsByClassName('editcheck', table_el, 'input');
+ var i;
+ var to_remove = [];
+ for (i = 0; i < els.length; i++) {
+ if (els[i].checked) {
+ // remove the tr (two levels up from the input box)
+ to_remove[to_remove.length] = els[i].parentNode.parentNode;
+ }
+ }
+ // now actually remove them
+ for (i = 0; i < to_remove.length; i++) {
+ to_remove[i].parentNode.removeChild(to_remove[i]);
+ }
+
+ updateAllNumbers(prefix);
+ };
+
+
+})();
Added: z3c.listjs/trunk/src/z3c/listjs/testing.py
===================================================================
--- z3c.listjs/trunk/src/z3c/listjs/testing.py (rev 0)
+++ z3c.listjs/trunk/src/z3c/listjs/testing.py 2009-01-06 20:36:22 UTC (rev 94552)
@@ -0,0 +1,7 @@
+import os
+import z3c.listjs
+from zope.app.testing.functional import ZCMLLayer
+
+ftesting_zcml = os.path.join(
+ os.path.dirname(z3c.listjs.__file__), 'ftesting.zcml')
+FunctionalLayer = ZCMLLayer(ftesting_zcml, __name__, 'FunctionalLayer')
Added: z3c.listjs/trunk/src/z3c/listjs/widget.py
===================================================================
--- z3c.listjs/trunk/src/z3c/listjs/widget.py (rev 0)
+++ z3c.listjs/trunk/src/z3c/listjs/widget.py 2009-01-06 20:36:22 UTC (rev 94552)
@@ -0,0 +1,35 @@
+from zope.app.form.browser import ListSequenceWidget
+from zope.app.form.interfaces import IInputWidget
+from zope.app.form.browser.widget import renderElement
+from zope.app.pagetemplate.viewpagetemplatefile import ViewPageTemplateFile
+
+from zope import component
+
+from hurry.resource import Library, ResourceInclusion
+
+listjs_lib = Library('z3c.listjs')
+listjs_resource = ResourceInclusion(listjs_lib, 'listjs.js')
+
+class _ListJsWidget(ListSequenceWidget):
+
+ template = ViewPageTemplateFile('listjswidget.pt')
+ record_template = ViewPageTemplateFile('listjswidget_record.pt')
+
+ def widgetTemplate(self):
+ # XXX hack: always get a widget that isn't in the sequence
+ sequence = self._getRenderedValue()
+ return self._getWidget(len(sequence))()
+
+ def __call__(self):
+ result = ListSequenceWidget.__call__(self)
+ listjs_resource.need()
+ return result
+
+ def _getPresenceMarker(self, count=0):
+ return ('<input type="hidden" id="%s.count" name="%s.count" value="%d" />'
+ % (self.name, self.name, count))
+
+
+def ListJsWidget(field, request):
+ return _ListJsWidget(field, field, request)
+
More information about the Checkins
mailing list