[Checkins] SVN: z3c.ajax/ initial ajax package import

Oliver Petznick oliver at mopa.at
Thu Nov 2 06:09:29 EST 2006


Log message for revision 71026:
  initial ajax package import

Changed:
  A   z3c.ajax/
  A   z3c.ajax/branches/
  A   z3c.ajax/tags/
  A   z3c.ajax/trunk/
  A   z3c.ajax/trunk/src/
  A   z3c.ajax/trunk/src/z3c/
  A   z3c.ajax/trunk/src/z3c/__init__.py
  A   z3c.ajax/trunk/src/z3c/ajax/
  A   z3c.ajax/trunk/src/z3c/ajax/README.txt
  A   z3c.ajax/trunk/src/z3c/ajax/TODO.txt
  A   z3c.ajax/trunk/src/z3c/ajax/__init__.py
  A   z3c.ajax/trunk/src/z3c/ajax/configure.zcml
  A   z3c.ajax/trunk/src/z3c/ajax/form.py
  A   z3c.ajax/trunk/src/z3c/ajax/interfaces.py
  A   z3c.ajax/trunk/src/z3c/ajax/namespace.py
  A   z3c.ajax/trunk/src/z3c/ajax/resources/
  A   z3c.ajax/trunk/src/z3c/ajax/resources/test.html
  A   z3c.ajax/trunk/src/z3c/ajax/resources/z3c_ajax.js
  A   z3c.ajax/trunk/src/z3c/ajax/tests.py
  A   z3c.ajax/trunk/src/z3c/ajax/widget.py

-=-
Added: z3c.ajax/trunk/src/z3c/__init__.py
===================================================================


Property changes on: z3c.ajax/trunk/src/z3c/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: z3c.ajax/trunk/src/z3c/ajax/README.txt
===================================================================
--- z3c.ajax/trunk/src/z3c/ajax/README.txt	2006-11-02 08:29:23 UTC (rev 71025)
+++ z3c.ajax/trunk/src/z3c/ajax/README.txt	2006-11-02 11:09:26 UTC (rev 71026)
@@ -0,0 +1,5 @@
+======
+ ajax
+======
+
+  >>> from z3c.ajax.namespace import AjaxHandler


Property changes on: z3c.ajax/trunk/src/z3c/ajax/README.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: z3c.ajax/trunk/src/z3c/ajax/TODO.txt
===================================================================
--- z3c.ajax/trunk/src/z3c/ajax/TODO.txt	2006-11-02 08:29:23 UTC (rev 71025)
+++ z3c.ajax/trunk/src/z3c/ajax/TODO.txt	2006-11-02 11:09:26 UTC (rev 71026)
@@ -0,0 +1,10 @@
+
+remove obsolete stuff from @@ajax implementations
+
+up-to-date? make subform of listwidget a factory attribute, so we do not need a
+registered form for the subobjects
+
+when TextWidget is empty one can't click it
+
+
+


Property changes on: z3c.ajax/trunk/src/z3c/ajax/TODO.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: z3c.ajax/trunk/src/z3c/ajax/__init__.py
===================================================================
--- z3c.ajax/trunk/src/z3c/ajax/__init__.py	2006-11-02 08:29:23 UTC (rev 71025)
+++ z3c.ajax/trunk/src/z3c/ajax/__init__.py	2006-11-02 11:09:26 UTC (rev 71026)
@@ -0,0 +1 @@
+#


Property changes on: z3c.ajax/trunk/src/z3c/ajax/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: z3c.ajax/trunk/src/z3c/ajax/configure.zcml
===================================================================
--- z3c.ajax/trunk/src/z3c/ajax/configure.zcml	2006-11-02 08:29:23 UTC (rev 71025)
+++ z3c.ajax/trunk/src/z3c/ajax/configure.zcml	2006-11-02 11:09:26 UTC (rev 71026)
@@ -0,0 +1,108 @@
+<configure xmlns="http://namespaces.zope.org/zope"
+           xmlns:browser="http://namespaces.zope.org/browser">
+
+
+ <class class=".namespace.AjaxFormTraverser">
+  <allow interface="zope.publisher.interfaces.browser.IBrowserPage"/>
+ </class>
+ <class class=".namespace.AjaxWidgetTraverser">
+  <allow interface="zope.publisher.interfaces.browser.IBrowserPage"/>
+ </class>
+
+ <adapter
+  name="ajax"
+  provides="zope.traversing.interfaces.ITraversable" for="*"
+  factory=".namespace.AjaxHandler"
+  />
+ 
+ <view
+  name="ajax"
+  type="zope.interface.Interface"
+  provides="zope.traversing.interfaces.ITraversable" for="*"
+  factory=".namespace.AjaxHandler"
+  /> 
+
+ <adapter
+  provides="zope.traversing.interfaces.ITraversable"
+  for=".interfaces.IAjaxFormTraverser"
+  factory=".namespace.AjaxFormTraversable"/>
+ 
+ <adapter
+  provides="zope.traversing.interfaces.ITraversable"
+  for=".interfaces.IAjaxWidgetTraverser"
+  factory=".namespace.AjaxWidgetTraversable"/>
+
+ 
+ 
+ <!--
+ <adapter
+  name="input"
+  provides=".interfaces.IAjaxForm"
+  factory=".form.ajaxInputForm"
+  for="zope.formlib.interfaces.IForm"
+  trusted="true"/>
+ -->
+ 
+
+ <!--
+ <browser:page
+  for="zope.formlib.interfaces.IForm"
+  name="ajax"
+  class=".namespace.Ajax"
+  permission="zope.Public"
+  />
+ -->
+
+ <view
+  type="zope.publisher.interfaces.browser.IBrowserRequest"
+  for="zope.schema.interfaces.ITextLine"
+  provides=".interfaces.IAjaxWidget"
+  factory=".widget.TextWidget"
+  permission="zope.Public"
+  />
+
+ <view
+  type="zope.publisher.interfaces.browser.IBrowserRequest"
+  for="zope.schema.interfaces.IList"
+  provides=".interfaces.IAjaxWidget"
+  factory=".widget.ListWidget"
+  permission="zope.Public"
+  />
+
+<!--
+ <browser:pages
+  for=".interfaces.IAjaxWidget"
+  class=".widget.Page"
+  permission="zope.Public"
+  >
+
+  <browser:page name="index.html"
+                attribute="__call__"/>
+  <browser:page name="display"
+                attribute="display"/>
+  <browser:page name="input"
+                attribute="input"/>
+ </browser:pages>
+ -->
+ <!--
+ <browser:pages
+  for=".interfaces.IAjaxForm"
+  class=".form.Page"
+  permission="zope.Public"
+  >
+  <browser:page name="index.html"
+                attribute="__call__"/>
+  <browser:page name="display"
+                attribute="display"/>
+  <browser:page name="input"
+                attribute="input"/>
+ </browser:pages>
+ -->
+ 
+
+ <resourceLibrary name="z3c_ajax" require="z3c.javascript.scriptaculous">
+  <directory source="resources" include="z3c_ajax.js"/>
+ </resourceLibrary>
+
+ 
+</configure>
\ No newline at end of file


Property changes on: z3c.ajax/trunk/src/z3c/ajax/configure.zcml
___________________________________________________________________
Name: svn:eol-style
   + native

Added: z3c.ajax/trunk/src/z3c/ajax/form.py
===================================================================
--- z3c.ajax/trunk/src/z3c/ajax/form.py	2006-11-02 08:29:23 UTC (rev 71025)
+++ z3c.ajax/trunk/src/z3c/ajax/form.py	2006-11-02 11:09:26 UTC (rev 71026)
@@ -0,0 +1,31 @@
+from zope.formlib import form
+from interfaces import IAjaxForm
+from zope import interface
+
+class AjaxForm(form.FormBase):
+
+    """base ajax form class which makes its widgets locatable"""
+
+    interface.implements(IAjaxForm)
+    actions = form.Actions()
+    
+    def setUpWidgets(self,*args,**kw):
+        super(AjaxForm,self).setUpWidgets(*args,**kw)
+        for widget in self.widgets:
+            widget.__form__ = self
+            
+    def renderDisplay(self):
+
+        return "display"
+
+    def renderInput(self):
+
+        return "input"
+
+    def publishTraverse(self, request, name):
+        raise NotFound(self, name, request)
+
+
+
+    
+    


Property changes on: z3c.ajax/trunk/src/z3c/ajax/form.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: z3c.ajax/trunk/src/z3c/ajax/interfaces.py
===================================================================
--- z3c.ajax/trunk/src/z3c/ajax/interfaces.py	2006-11-02 08:29:23 UTC (rev 71025)
+++ z3c.ajax/trunk/src/z3c/ajax/interfaces.py	2006-11-02 11:09:26 UTC (rev 71026)
@@ -0,0 +1,36 @@
+from zope import interface
+from zope.app.form.interfaces import IInputWidget, IDisplayWidget
+
+
+class IAjaxTraverser(interface.Interface):
+
+    """an ajax traverser"""
+
+class IAjaxWidget(interface.Interface):
+
+    """an ajax widget, which is actualy a browser page"""
+
+class IAjaxFormTraverser(interface.Interface):
+
+    """a traverser that traverses to widgets of a form"""
+
+class IAjaxWidgetTraverser(interface.Interface):
+
+    """a traverser that traverses to displays of a widget"""
+
+class IAjaxForm(IInputWidget):
+
+    def __call__(self):
+        """default view"""
+
+    def renderDisplay():
+
+        """render display view"""
+
+    def renderInput():
+
+        """render input view"""
+
+    def browserDefault():
+
+        """ """


Property changes on: z3c.ajax/trunk/src/z3c/ajax/interfaces.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: z3c.ajax/trunk/src/z3c/ajax/namespace.py
===================================================================
--- z3c.ajax/trunk/src/z3c/ajax/namespace.py	2006-11-02 08:29:23 UTC (rev 71025)
+++ z3c.ajax/trunk/src/z3c/ajax/namespace.py	2006-11-02 11:09:26 UTC (rev 71026)
@@ -0,0 +1,158 @@
+from zope.traversing.namespace import SimpleHandler
+from zope import component,interface
+from zope.publisher.browser import BrowserPage,BrowserView
+from zope.app.form.interfaces import IInputWidget, IDisplayWidget
+from interfaces import IAjaxWidget
+from zope.traversing.browser.absoluteurl import absoluteURL
+from zc import resourcelibrary
+from zope.app.form.browser.textwidgets import renderElement
+from zope.security.proxy import removeSecurityProxy
+from interfaces import IAjaxFormTraverser,IAjaxWidgetTraverser
+
+class Ajax(BrowserPage):
+    #implements(IAbsoluteURL)
+
+    def __call__(self):
+        return u"no call"
+
+    def publishTraverse(self, request, name):
+
+        name = name.split('.')[-1]
+        fields = removeSecurityProxy(self.context.form_fields) 
+        form_field = fields[name]
+        field = form_field.field
+        interface = field.interface
+        adapter = interface(removeSecurityProxy(self.context).context)
+        field = field.bind(adapter)
+        if form_field.custom_widget is not None:
+            widget = form_field.custom_widget(field, request)
+        else:
+            widget = component.getMultiAdapter((field, request),
+                                               IAjaxWidget)
+        prefix = removeSecurityProxy(self.context).prefix
+        if form_field.prefix:
+            prefix += '.' + form_field.prefix
+        widget.setPrefix(prefix)
+        widget.__form__=self.context
+        return widget
+
+
+class AjaxWidgetTraverser(BrowserPage):
+
+    interface.implements(IAjaxWidgetTraverser)
+
+    def __call__(self):
+        # renders a widget loader
+        #form = component.getMultiAdapter((self.context, self.request),
+        #                                 name=self.__parent__.__name__)
+        url = absoluteURL(self.context,self.request)
+        url = '%s/++ajax++%s/%s' % (url,self.__parent__.__name__,
+                                    self.__name__)
+        # we switch to display as standard mode
+        html =  renderElement('span',
+                              cssClass='ajax:container',
+                              extra='ajax:src="%s/display"' % url,
+                              contents='Loading ...')
+        return html
+
+    def publishTraverse(self, request, name):
+
+        if name=='input':
+            forInput = True
+        elif name=='display':
+            forInput = False
+        else:
+            return super(AjaxWidgetTraverser,self).publishTraverse(
+                request,name)
+        form = component.getMultiAdapter((self.context, self.request),
+                                         name=self.__parent__.__name__)
+
+        # hm, how can we prevent this line?
+        fieldName = self.__name__.split('.')[-1]
+        fields = form.form_fields
+        #import pdb;pdb.set_trace()
+        form_field = fields[fieldName]
+        field = form_field.field
+        interface = field.interface
+        adapter = interface(form.context)
+        field = field.bind(adapter)
+        if form_field.custom_widget is not None:
+            widget = form_field.custom_widget(field, request)
+        else:
+            widget = component.getMultiAdapter((field, request),
+                                               IAjaxWidget)
+        prefix = form.prefix
+        if form_field.prefix:
+            prefix += '.' + form_field.prefix
+        widget.setPrefix(prefix)
+        widget.__form__=form
+        widget.__parent__=self
+        if forInput:
+            return widget.renderInput
+        else:
+            return widget.renderDisplay
+
+
+from zope.traversing.adapters import DefaultTraversable
+class AjaxWidgetTraversable(DefaultTraversable):
+
+    def traverse(self, name, furtherPath):
+        if not name in ('input','display'):
+            return super(AjaxWidgetTraversable,self).traverse(
+                name,furtherPath)
+        
+        return self._subject.publishTraverse(self._subject.request,
+                                             name)
+        
+
+class AjaxFormTraversable(DefaultTraversable):
+
+    def traverse(self, name, furtherPath):
+        wt = AjaxWidgetTraverser(self._subject.context,
+                                 self._subject.request)
+        wt.__parent__=self._subject
+        wt.__name__=name
+        return wt
+    
+
+class AjaxFormTraverser(BrowserPage):
+
+    interface.implements(IAjaxFormTraverser)
+
+    def __init__(self,context,request,name):
+        super(AjaxFormTraverser,self).__init__(context,request)
+        self.__name__=name
+
+    def __call__(self):
+        # renders a form loader
+        view = component.getMultiAdapter((self.context, self.request),
+                                         name=self.__name__)
+        url = absoluteURL(view,self.request)
+        resourcelibrary.need('z3c_ajax')
+        # remember: forms only have one display mode, so we load them
+        # from their location
+        html =  renderElement('div',
+                              cssClass='ajax:container',
+                              extra='ajax:src="%s"' % url,
+                              contents='Loading ...')
+        return html
+
+    def publishTraverse(self, request, name):
+
+        wt = AjaxWidgetTraverser(self.context,request)
+        wt.__parent__=self
+        wt.__name__=name
+        return wt
+
+class AjaxHandler(SimpleHandler):
+
+    """returns the ajax view widget for a given field in a view"""
+
+    def __init__(self,context,request=None):
+        super(AjaxHandler,self).__init__(context,request)
+        self.request=request
+
+    def traverse(self,name,ignored):
+        # context is a content object
+        return AjaxFormTraverser(self.context,self.request,name)
+


Property changes on: z3c.ajax/trunk/src/z3c/ajax/namespace.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: z3c.ajax/trunk/src/z3c/ajax/resources/test.html
===================================================================
--- z3c.ajax/trunk/src/z3c/ajax/resources/test.html	2006-11-02 08:29:23 UTC (rev 71025)
+++ z3c.ajax/trunk/src/z3c/ajax/resources/test.html	2006-11-02 11:09:26 UTC (rev 71026)
@@ -0,0 +1,14 @@
+<html xmlns:ajax="ajax" xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+  <tal:block replace="resource_library:z3c_ajax"/>
+
+ </head>
+ <body>
+  
+  <div class="ajax:container"
+       ajax:src="http://localhost:8080/++skin++Debug/book/++attribute++groups/0/@@edit.html/@@ajax/title">
+   Loading ...
+  </div>
+ </body>
+ 
+</html>
\ No newline at end of file


Property changes on: z3c.ajax/trunk/src/z3c/ajax/resources/test.html
___________________________________________________________________
Name: svn:eol-style
   + native

Added: z3c.ajax/trunk/src/z3c/ajax/resources/z3c_ajax.js
===================================================================
--- z3c.ajax/trunk/src/z3c/ajax/resources/z3c_ajax.js	2006-11-02 08:29:23 UTC (rev 71025)
+++ z3c.ajax/trunk/src/z3c/ajax/resources/z3c_ajax.js	2006-11-02 11:09:26 UTC (rev 71026)
@@ -0,0 +1,222 @@
+Array.prototype.indexOf = function(v) {
+    for(var i = 0; i < this.length; i++) if(this[i] == v) return i; return -1;
+}
+
+Array.prototype.remove = function(v) {
+    for(var i = 0; i < this.length; i++) if(this[i] == v) { this.splice(i, 1); return; }
+}
+
+// Adds event to window.onload without overwriting currently 
+// assigned onload functions.
+function addLoadEvent(func)
+{
+    var oldonload = window.onload;
+    if (typeof window.onload != 'function')
+    {
+        window.onload = func;
+    } 
+    else 
+    {
+        window.onload = function()
+        {
+            oldonload();
+            func();
+        }
+    }
+}
+
+var z3cContainerOnLoadListeners = Array();
+function z3cContainerLoaded(container){
+    //alert(z3cContainerOnLoadListeners.length);
+    z3cContainerOnLoadListeners.each(function(f){
+            f(container);
+        });
+}
+
+
+function z3cAddContainerLoadListener(func){
+    z3cContainerOnLoadListeners.push(func);
+}
+
+function z3cRemoveContainerLoadListener(func){
+    z3cContainerOnLoadListeners.remove(func);
+}
+
+function fnSuccess(t){
+    //alert(t.responseText);
+}
+
+function fnFailure(resp){
+    alert('failure: ' + t.responseText);
+}
+
+var z3cAjaxContainerCount=0;
+
+// returns the next parent of obj which has the given class
+function z3cNextParentByClass(obj,klass){
+    obj = $(obj);
+    
+    while(!Element.hasClassName(obj,klass)){
+        if (obj.parentNode==document){
+            return null;
+        }
+        obj=obj.parentNode;
+    }
+    if (obj){
+        return obj;
+    }
+    return null;
+}
+
+function z3cIsContainer(obj){
+    obj = $(obj);
+    return (obj.getAttribute('class')=='ajax:container');
+}
+
+function z3cNextContainer(obj){
+
+    obj = $(obj);
+    while(obj && (!z3cIsContainer(obj))){
+        obj=obj.parentNode;
+
+    }
+    if (z3cIsContainer(obj)){
+        return obj;
+    }
+    return null;
+}
+
+function z3cContainerURL(obj,view){
+    var container = z3cNextContainer(obj);
+    var current = container.getAttribute('ajax:src');
+    return current.substr(0,current.lastIndexOf('/')+1) + view;
+}
+
+// calls an url on the container
+function z3cCallContainer(obj,view,callback){
+    var container = z3cNextContainer(obj);
+    var url = z3cContainerURL(obj,view);
+    new Ajax.Request(url,
+                     {asynchronous:true,
+                             method: 'get',
+                             onSuccess: fnSuccess,
+                             onFailure: fnFailure,
+                             onComplete: callback,
+                             evalScripts:true}
+                     );
+    //alert('loaded');
+}
+
+
+function z3cChangeView(obj,view,condition){
+    if ((condition != null)&&(!condition)){
+        return;
+    }
+    var container = z3cNextContainer(obj);
+    var url = z3cContainerURL(container,view);
+    z3cLoadContainer(container,url);
+}
+
+function z3cLoadContainer(container,url,paras){
+    // XXX: this should be a class because of the onComplete func
+    var container=$(container);
+
+    if (!url){
+        url = container.getAttribute('ajax:src');
+    }
+    new Ajax.Updater(container.id,
+                     url,
+                     {asynchronous:true,
+                             method: 'get',
+                             onSuccess: fnSuccess,
+                             onFailure: fnFailure,
+                             parameters: paras,
+                             onComplete: function (t){
+                             return z3cContainerLoaded(container);
+                         },
+                             evalScripts:true}
+                     );
+}
+
+// recursive load containers
+z3cAddContainerLoadListener(z3cLoadContainers);
+
+function z3cLoadContent(event){
+    z3cLoadContainers(document.body);
+}
+
+function z3cSaveForm(f){
+    var f = $(f);
+    var container = z3cNextContainer(f);
+    var paras = (Form.serialize(f));
+    z3cLoadContainer(container,null,paras);
+    return;
+    new Ajax.Request(f.action,
+                     {asynchronous:false,
+                             method: 'get',
+                             onSuccess: fnSuccess,
+                             onFailure: fnFailure,
+                             parameters: paras,
+                             evalScripts:true}
+                     );
+}
+
+function z3cLoadContainers(obj){
+    // loads containers in obj
+    var obj = $(obj);
+    var containers = document.getElementsByClassName('ajax:container',obj);
+    for (i=0;i<containers.length;i++) {
+        var container = containers[i];
+        // make sure we have an id
+        if (!container.id){
+            z3cAjaxContainerCount++;
+            var id='ajax:container:' +z3cAjaxContainerCount;
+            container.id=id;
+        }
+        z3cLoadContainer(container);
+    }
+}
+
+addLoadEvent(z3cLoadContent);
+
+
+
+
+function makeEdit(id){
+    
+    var containerId = id + ".container";
+    var name = $(containerId).getAttribute('name');
+    //var url = document.location + '/@@ajax/' + id;
+    var url=$(containerId).getAttribute('url');
+    //alert(url);
+    var paras = '__input__=1';
+    new Ajax.Updater(containerId,
+                     url,
+                     {asynchronous:true,
+                             method: 'get',
+                             onSuccess: fnSuccess,
+                             onFailure: fnFailure,
+                             parameters: paras,
+                             evalScripts:true}
+                     );
+}
+
+function z3cApplyChanges(obj){
+    var value = $F(obj);
+    z3cChangeView(obj,'display?apply=1&' + obj.name +'='+$F(obj));
+}
+
+
+function applyAndDisplay(id){
+    var containerId = id + ".container";
+    var url = document.location + '/@@ajax/' + id;
+    paras = id +'='+ $F(id) + '&' + id +'.apply=1';
+    new Ajax.Updater(containerId,
+                     url,
+                     {asynchronous:true,
+                             method: 'get',
+                             parameters: paras,
+                             }
+                     );
+
+}
\ No newline at end of file

Added: z3c.ajax/trunk/src/z3c/ajax/tests.py
===================================================================
--- z3c.ajax/trunk/src/z3c/ajax/tests.py	2006-11-02 08:29:23 UTC (rev 71025)
+++ z3c.ajax/trunk/src/z3c/ajax/tests.py	2006-11-02 11:09:26 UTC (rev 71026)
@@ -0,0 +1,27 @@
+import doctest
+import unittest
+from zope.testing.doctestunit import DocFileSuite, DocTestSuite
+from zope.app.testing import setup
+from zope import component
+
+def setUp(test):
+    setup.placefulSetUp()
+
+
+def tearDown(test):
+    setup.placefulTearDown()
+
+
+def test_suite():
+    
+    return unittest.TestSuite(
+        (
+        DocFileSuite('README.txt',
+                     setUp=setUp,tearDown=tearDown,
+                     optionflags=doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS,
+                     ),
+        ))
+
+if __name__ == '__main__':
+    unittest.main(defaultTest='test_suite')
+


Property changes on: z3c.ajax/trunk/src/z3c/ajax/tests.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: z3c.ajax/trunk/src/z3c/ajax/widget.py
===================================================================
--- z3c.ajax/trunk/src/z3c/ajax/widget.py	2006-11-02 08:29:23 UTC (rev 71025)
+++ z3c.ajax/trunk/src/z3c/ajax/widget.py	2006-11-02 11:09:26 UTC (rev 71026)
@@ -0,0 +1,182 @@
+from zope.app.form.browser.textwidgets import TextWidget as BaseTextWidget
+from interfaces import IAjaxWidget
+from zope import interface, component
+from zope.publisher.browser import BrowserPage
+from xml.sax.saxutils import quoteattr, escape
+from zope.app.form.browser.textwidgets import renderElement
+from zc import resourcelibrary
+from zope.traversing.browser.absoluteurl import absoluteURL
+from zope.app.form.interfaces import WidgetInputError
+
+class BaseAjaxWidget(BaseTextWidget):
+    interface.implements(IAjaxWidget)
+    containerTag='span'
+
+    def __init__(self,*args,**kw):
+        resourcelibrary.need('z3c_ajax')
+        super(BaseTextWidget,self).__init__(*args,**kw)
+        if self.request:
+            self.request.response.setHeader('Content-Type','text/html')
+
+    def getValue(self):
+        return self.context.get(self.context.context)
+
+    def getURL(self):
+
+        """returns the name of the form"""
+        #TODO make an absolute_url view for this
+        #import pdb;pdb.set_trace()
+        
+        url =absoluteURL(self.__form__,self.request)
+        
+        formName = url.split('/')[-1]
+        contextURL = absoluteURL(self.__form__.context,self.request)
+        return '%s/++ajax++%s/%s' % (contextURL,self.__form__.__name__,
+                                     self.name)
+
+    def __call__(self):
+        resourcelibrary.need('z3c_ajax')
+        html =  renderElement(self.containerTag,
+                              cssClass='ajax:container',
+                              extra='ajax:src="%s/display"' % self.getURL(),
+                              contents='Loading ...')
+        return html
+
+    def renderInput(self):
+        self.applyMethods()
+
+    def renderDisplay(self):
+        self.applyMethods()
+        
+    def applyMethods(self):
+        pass
+        
+
+class TextWidget(BaseAjaxWidget):
+
+    inputOnBlur = "z3cChangeView(this,'display?apply=1&' + this.name +'='+$F(this))"
+    displayOnClick = "z3cChangeView(this,'input')"
+    
+    def applyMethods(self):
+        if 'apply' in self.request.form:
+            try:
+                self.applyChanges(self.context.context)
+            except WidgetInputError,e:
+                # XXX to some valueable default here
+                pass
+
+
+    def renderInput(self):
+        self.applyMethods()
+        resourcelibrary.need('z3c_ajax')
+        value = self.getValue()
+        self.setRenderedValue(value)
+        value = self._getFormValue()
+        if value is None or value == self.context.missing_value:
+            value = ''
+
+        kwargs = {'type': self.type,
+                  'name': self.name,
+                  'id': self.name,
+                  'value': value,
+                  'cssClass': self.cssClass,
+                  'style': self.style,
+                  'onblur':self.inputOnBlur,
+                  'size': self.displayWidth,
+                  'extra': self.extra}
+        if self.displayMaxWidth:
+            kwargs['maxlength'] = self.displayMaxWidth
+
+        contents = renderElement(self.tag, **kwargs)
+        return contents
+
+    def renderDisplay(self):
+        self.applyMethods()
+        resourcelibrary.need('z3c_ajax')
+        value = self.getValue()
+        contents = renderElement(self.containerTag,
+                                 name=self.name,
+                                 id=self.name,
+                                 contents=value,
+                                 onclick=self.displayOnClick)
+        return contents
+
+
+from zope.formlib import form
+
+from zope.app.container.contained import ContainedProxy
+from zope.security.proxy import removeSecurityProxy
+
+class ListWidget(BaseAjaxWidget):
+
+    # factory has to take a unicode as constructor
+    contentFactory = None
+    subFormName = u'edit.html'
+    containerTag='div'
+    added = None
+    deleted = None
+    
+    def items(self):
+
+        """returns (idx,value) of original value in order to keep the
+        appopriate indexes intact"""
+        
+        value = self.getValue()
+        return zip(range(len(value)),value)
+
+
+    def applyMethods(self):
+        if not hasattr(self,'value'):
+            raise RuntimeError,u"self.value is not set"
+        if 'add' in self.request.form and self.added is None:
+            self.createAndAdd(self.request.form.get('add'))
+        if 'delete' in self.request.form and self.deleted is None:
+            value = self.getValue()
+            idx = int(self.request.form.get('delete'))
+            del value[idx]
+            self.deleted = idx
+
+
+    def renderDisplay(self):
+        self.applyMethods()
+        resourcelibrary.need('z3c_ajax')
+        value = self.getValue()
+        html = u''
+        index=0
+        #import pdb;pdb.set_trace()
+        for item in value:
+            item = ContainedProxy(removeSecurityProxy(item))
+            item.__parent__=value
+            item.__name__=unicode(index)
+            sf =component.getMultiAdapter((item, self.request),
+                                          name=self.subFormName)
+            #sf = self._subForm(item,self.request)
+            sf.setPrefix('%s.%s' % (self.name,index))
+            sf.update()
+            for widget in sf.widgets:
+                widget.__form__=sf
+            print "url------",
+            html += u'<div>%s</div>' % sf.widgets['title']()
+            index+=1
+        onClick = """z3cChangeView(this,'display?add=1')"""
+        html += '<div onclick="%s">+</div>' % onClick
+        return html
+
+    def createAndAdd(self,*args):
+        value = self.getValue()
+        o = self.contentFactory(*args)
+        self.added=o
+        value.append(o)
+
+
+from zope.security.proxy import removeSecurityProxy
+class Page(object):
+
+    def __call__(self):
+        return removeSecurityProxy(self.context)()
+
+    def display(self):
+        return removeSecurityProxy(self.context).renderDisplay()
+
+    def input(self):
+        return removeSecurityProxy(self.context).renderInput()


Property changes on: z3c.ajax/trunk/src/z3c/ajax/widget.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native



More information about the Checkins mailing list