[js utils] backport some generic code from comments cube stable
authorSylvain Thénault <sylvain.thenault@logilab.fr>
Mon, 31 Jan 2011 17:28:51 +0100
branchstable
changeset 6924 b88221afe491
parent 6923 327443ec7120
child 6925 352db17719d2
[js utils] backport some generic code from comments cube to handle inline ajax form as you get to add comment to entities. Following stuff has been generalized and backported to ease such things: * lazy_view_holder() method on EntityCtxComponent class, to build place holder where the form will be inserted * ajax_composite_form() function in cw.web.views.ajaxedit, to build the form itself * reload() and reloadCtxComponentsSection() javascript function in cubicweb.ajax.js for the javascript processing side
web/component.py
web/data/cubicweb.ajax.js
web/views/ajaxedit.py
--- a/web/component.py	Mon Jan 31 17:24:05 2011 +0100
+++ b/web/component.py	Mon Jan 31 17:28:51 2011 +0100
@@ -399,6 +399,28 @@
     def domid(self):
         return domid(self.__regid__) + unicode(self.entity.eid)
 
+    def lazy_view_holder(self, w, entity, oid, registry='views'):
+        """add a holder and return an url that may be used to replace this
+        holder by the html generate by the view specified by registry and
+        identifier. Registry defaults to 'views'.
+        """
+        holderid = '%sHolder' % self.domid
+        w(u'<div id="%s"></div>' % holderid)
+        params = self.cw_extra_kwargs.copy()
+        params.pop('view', None)
+        params.pop('entity', None)
+        form = params.pop('formparams', {})
+        form['pageid'] = self._cw.pageid
+        if entity.has_eid():
+            eid = entity.eid
+        else:
+            eid = None
+            form['etype'] = entity.__regid__
+            form['tempEid'] = entity.eid
+        args = [json_dumps(x) for x in (registry, oid, eid, params)]
+        return self._cw.ajax_replace_url(
+            holderid, fname='render', arg=args, **form)
+
 
 # high level abstract classes ##################################################
 
--- a/web/data/cubicweb.ajax.js	Mon Jan 31 17:24:05 2011 +0100
+++ b/web/data/cubicweb.ajax.js	Mon Jan 31 17:28:51 2011 +0100
@@ -563,6 +563,51 @@
                );
 }
 
+/* High-level functions *******************************************************/
+
+/**
+ * .. function:: reloadCtxComponentsSection(context, actualEid, creationEid=None)
+ *
+ * reload all components in the section for a given `context`.
+ *
+ * This is necessary for cases where the parent entity (on which the section
+ * apply) has been created during post, hence the section has to be reloaded to
+ * consider its new eid, hence the two additional arguments `actualEid` and
+ * `creationEid`: `actualEid` is the eid of newly created top level entity and
+ * `creationEid` the fake eid that was given as form creation marker (e.g. A).
+ *
+ * You can still call this function with only the actual eid if you're not in
+ * such creation case.
+ */
+function reloadCtxComponentsSection(context, actualEid, creationEid) {
+    // in this case, actualEid is the eid of newly created top level entity and
+    // creationEid the fake eid given as form creation marker (e.g. A)
+    if (!creationEid) { creationEid = actualEid ; }
+    var $compsholder = $('#' + context + creationEid);
+    // reload the whole components section
+    $compsholder.children().each(function (index) {
+	// XXX this.id[:-len(eid)]
+	var compid = this.id.replace("_", ".").rstrip(creationEid);
+	var params = ajaxFuncArgs('render', null, 'ctxcomponents',
+				  compid, actualEid);
+	$(this).loadxhtml('json', params, null, 'swap', true);
+    });
+    $compsholder.attr('id', context + actualEid);
+}
+
+
+/**
+ * .. function:: reload(domid, registry, formparams, *render_args)
+ *
+ * `js_render` based reloading of views and components.
+ */
+function reload(domid, compid, registry, formparams  /* ... */) {
+    var ajaxArgs = ['render', formparams, registry, compid];
+    ajaxArgs = ajaxArgs.concat(cw.utils.sliceList(arguments, 4));
+    var params = ajaxFuncArgs.apply(null, ajaxArgs);
+    $('#'+domid).loadxhtml('json', params, null, 'swap');
+}
+
 /* DEPRECATED *****************************************************************/
 
 preprocessAjaxLoad = cw.utils.deprecatedFunction(
--- a/web/views/ajaxedit.py	Mon Jan 31 17:24:05 2011 +0100
+++ b/web/views/ajaxedit.py	Mon Jan 31 17:28:51 2011 +0100
@@ -22,9 +22,9 @@
 from cubicweb import role
 from cubicweb.view import View
 from cubicweb.selectors import match_form_params, match_kwargs
-from cubicweb.web.component import EditRelationMixIn
+from cubicweb.web import component, stdmsgs, formwidgets as fw
 
-class AddRelationView(EditRelationMixIn, View):
+class AddRelationView(component.EditRelationMixIn, View):
     """base class for view which let add entities linked by a given relation
 
     subclasses should define at least id, rtype and target class attributes.
@@ -36,7 +36,7 @@
     cw_property_defs = {} # don't want to inherit this from Box
     expected_kwargs = form_params = ('rtype', 'target')
 
-    build_js = EditRelationMixIn.build_reload_js_call
+    build_js = component.EditRelationMixIn.build_reload_js_call
 
     def cell_call(self, row, col, rtype=None, target=None, etype=None):
         self.rtype = rtype or self._cw.form['rtype']
@@ -73,3 +73,41 @@
             self.pagination(self._cw, rset, w=self.w)
             return rset.entities()
         super(AddRelationView, self).unrelated_entities(self)
+
+
+def ajaxCompositeForm(container, entity, rtype, okjs, canceljs,
+                      entityfkwargs=None):
+    """
+    * if entity is None, edit container (assert container.has_eid())
+    * if entity has not eid, will be created
+    * if container has not eid, will be created (see vcreview InsertionPoint)
+    """
+    req = container._cw
+    parentexists = entity is None or container.has_eid()
+    buttons = [fw.Button(onclick=okjs),
+               fw.Button(stdmsgs.BUTTON_CANCEL, onclick=canceljs)]
+    freg = req.vreg['forms']
+    # main form kwargs
+    mkwargs = dict(action='#', domid='%sForm%s' % (rtype, container.eid),
+                   form_buttons=buttons,
+                   onsubmit='javascript: %s; return false' % okjs)
+    # entity form kwargs
+    # use formtype=inlined to skip the generic relations edition section
+    fkwargs = dict(entity=entity or container, formtype='inlined')
+    if entityfkwargs is not None:
+        fkwargs.update(entityfkwargs)
+    # form values
+    formvalues = {}
+    if entity is not None: # creation
+        formvalues[rtype] = container.eid
+    if parentexists: # creation / edition
+        mkwargs.update(fkwargs)
+        # use formtype=inlined to avoid viewing the relation edition section
+        form = freg.select('edition', req, **mkwargs)
+    else: # creation of both container and comment entities
+        form = freg.select('composite', req, form_renderer_id='default',
+                            **mkwargs)
+        form.add_subform(freg.select('edition', req, entity=container,
+                                      mainform=False, mainentity=True))
+        form.add_subform(freg.select('edition', req, mainform=False, **fkwargs))
+    return form, formvalues