# HG changeset patch # User Sylvain Thénault # Date 1273078519 -7200 # Node ID 5790462343cb57f1cfe6a1f20a9194a4e1dad194 # Parent 1a30c5a56256775e2c49e43bc4dec46ab85e00d4# Parent 4a033d7f1d93a097361a07e882a9139c44d00820 backport stable diff -r 1a30c5a56256 -r 5790462343cb doc/book/en/annexes/index.rst --- a/doc/book/en/annexes/index.rst Wed May 05 18:48:31 2010 +0200 +++ b/doc/book/en/annexes/index.rst Wed May 05 18:55:19 2010 +0200 @@ -19,11 +19,3 @@ depends javascript-api docstrings-conventions - -(X)HTML tricks to apply ------------------------ - -Some web browser (Firefox for example) are not happy with empty `
` -(by empty we mean that there is no content in the tag, but there -could be attributes), so we should always use `
` even if -it is empty and not use `
`. diff -r 1a30c5a56256 -r 5790462343cb doc/book/en/devweb/edition/dissection.rst --- a/doc/book/en/devweb/edition/dissection.rst Wed May 05 18:48:31 2010 +0200 +++ b/doc/book/en/devweb/edition/dissection.rst Wed May 05 18:55:19 2010 +0200 @@ -1,5 +1,7 @@ -Dissection of a Form +.. _form_dissection: + +Dissection of a form -------------------- This is done (again) with a vanilla instance of the `tracker`_ @@ -110,12 +112,17 @@ back correctly. The `freezeFormButtons(...)` javascript callback defined on the -``conlick`` event of the form element prevents accidental multiple +``onlick`` event of the form element prevents accidental multiple clicks in a row. -The ``action`` of the form is mapped to the `validateform` controller +The ``action`` of the form is mapped to the ``validateform`` controller (situated in :mod:`cubicweb.web.views.basecontrollers`). +A full explanation of the validation loop is given in +:ref:`validation_process`. + +.. _attributes_section: + The attributes section '''''''''''''''''''''' @@ -252,19 +259,22 @@ @@ -273,4 +283,87 @@ The most notable artifacts here are the ``postForm(...)`` calls defined on click events on these buttons. This function basically -submits the form. XXX validateform vs validateForm, ajax or not ? +submits the form. + +.. _validation_process: + +The form validation process +--------------------------- + +Preparation +~~~~~~~~~~~ + +After the (html) document is loaded, the ``setFormsTarget`` javascript +function dynamically transforms the DOM as follows. For all forms of +the DOM, it: + +* sets the ``target`` attribute where there is a ``cubicweb:target`` + attribute (with the same value) + +* appends an empty `IFRAME` element at the end + +Let us have a look again at the form element. We have omitted some +irrelevant attributes. + +.. sourcecode::html + +
+ ... +
+ +Validation loop +~~~~~~~~~~~~~~~ + +On form submission, the form.action is invoked. Basically, the +``validateform`` controller is called and its output lands in the +specified ``target``, the iframe that was previously prepared. + +Hence, the main page is not replaced, only the iframe contents. The +``validateform`` controller only outputs a tiny javascript fragment +which is then immediately executed. + +.. sourcecode:: html + + + +The ``window.parent`` part ensures the javascript function is called +on the right context (that is: the form element). We will describe its +parameters: + +* first comes the form id (`entityForm`) + +* then two optional callbacks for the success and failure case + +* an array containing: + + * a boolean which indicates status (success or failure), and then, on error: + + * an array structured as ``[eid, {'rtype-role': 'error msg'}, ...]`` + + * on success: + + * an url (string) representing the next thing to jump to + +Given the array structure described above, it is quite simple to +manipulate the DOM to show the errors at appropriate places. + +Explanation +~~~~~~~~~~~ + +This mecanism may seem a bit overcomplicated but we have to deal with +two realities: + +* in the (strict) XHTML world, there are no iframes (hence the dynamic + inclusion, tolerated by Firefox) + +* no (or not all) browser(s) support file input field handling through + ajax. diff -r 1a30c5a56256 -r 5790462343cb doc/book/en/devweb/edition/editcontroller.rst --- a/doc/book/en/devweb/edition/editcontroller.rst Wed May 05 18:48:31 2010 +0200 +++ b/doc/book/en/devweb/edition/editcontroller.rst Wed May 05 18:55:19 2010 +0200 @@ -1,72 +1,68 @@ .. _edit_controller: The `edit controller` -+++++++++++++++++++++ +--------------------- -It can be found in (:mod:`cubicweb.web.views.editcontroller`). +It can be found in (:mod:`cubicweb.web.views.editcontroller`). This +controller processes data received from an html form to create or +update entities. -Editing control +Edition handling ~~~~~~~~~~~~~~~~ -.. XXX this look obsolete +The parameters related to entities to edit are specified as follows +(first seen in :ref:`attributes_section`):: -The parameters related to entities to edit are specified as follows :: - - : + : where entity eid could be a letter in case of an entity to create. We name those parameters as *qualified*. -1. Retrieval of entities to edit by looking for the forms parameters - starting by `eid:` and also having a parameter `__type` associated - (also *qualified* by eid) +* Retrieval of entities to edit is done by using the forms parameters + `eid` and `__type` -2. For all the attributes and the relations of an entity to edit: +* For all the attributes and the relations of an entity to edit + (attributes and relations are handled a bit differently but these + details are not much relevant here) : + + * using the ``rtype``, ``role`` and ``__type`` information, fetch + an appropriate field instance - 1. search for a parameter `edits-` or `edito-` - qualified in the case of a relation where the entity is object - 2. if found, the value returned is considered as the initial value - for this relaiton and we then look for the new value(s) in the parameter - (qualified) - 3. if the value returned is different from the initial value, an database update - request is done + * check if the field has been modified (if not, proceed to the next + relation) + + * build an rql expression to update the entity -3. For each entity to edit: +At the end, all rql expressions are executed. - 1. if a qualified parameter `__linkto` is specified, its value has to be - a string (or a list of string) such as: :: +* For each entity to edit: + + * if a qualified parameter `__linkto` is specified, its value has + to be a string (or a list of strings) such as: :: :: - where is either `subject` or `object` and each eid could be - separated from the others by a `_`. Target specifies if the *edited entity* - is subject or object of the relation and each relation specified will - be inserted. + where is either `subject` or `object` and each eid could + be separated from the others by a `_`. Target specifies if the + *edited entity* is subject or object of the relation and each + relation specified will be inserted. - 2. if a qualified parameter `__clone_eid` is specified for an entity, the - relations of the specified entity passed as value of this parameter are - copied on the edited entity. - - 3. if a qualified parameter `__delete` is specified, its value must be - a string or a list of string such as follows: :: - - :: + * if a qualified parameter `__clone_eid` is specified for an entity, the + relations of the specified entity passed as value of this parameter are + copied on the edited entity. - where each eid subject or object can be seperated from the other - by `_`. Each relation specified will be deleted. + * if a qualified parameter `__delete` is specified, its value must be + a string or a list of string such as follows: :: - 4. if a qualified parameter `__insert` is specified, its value should - follow the same pattern as `__delete`, but each relation specified is - inserted. + :: -4. If the parameters `__insert` and/or `__delete` are found not qualified, - they are interpreted as explained above (independantly from the number - of entities edited). + where each eid subject or object can be seperated from the other + by `_`. Each specified relation will be deleted. + -5. If no entity is edited but the form contains the parameters `__linkto` - and `eid`, this one is interpreted by using the value specified for `eid` - to designate the entity on which to add the relations. - +* If no entity is edited but the form contains the parameters `__linkto` + and `eid`, this one is interpreted by using the value specified for `eid` + to designate the entity on which to add the relations. .. note:: diff -r 1a30c5a56256 -r 5790462343cb doc/book/en/devweb/edition/examples.rst --- a/doc/book/en/devweb/edition/examples.rst Wed May 05 18:48:31 2010 +0200 +++ b/doc/book/en/devweb/edition/examples.rst Wed May 05 18:55:19 2010 +0200 @@ -1,8 +1,50 @@ Examples -------- -Example of ad-hoc fields form -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +(Automatic) Entity form +~~~~~~~~~~~~~~~~~~~~~~~ + +Looking at some cubes available on the `cubicweb forge`_ we find some +with form manipulation. The following example comes from the the +`conference`_ cube. It extends the change state form for the case +where a ``Talk`` entity is getting into ``submitted`` state. The goal +is to select reviewers for the submitted talk. + +.. _`cubicweb forge`: http://www.cubicweb.org/view?rql=Any+P+ORDERBY+N+WHERE+P+name+LIKE+%22cubicweb-%25%22%2C+P+is+Project%2C+P+name+N +.. _`conference`: http://www.cubicweb.org/project/cubicweb-conference + +.. sourcecode:: python + + from cubicweb.web import formfields as ff, formwidgets as fwdgs + class SendToReviewerStatusChangeView(ChangeStateFormView): + __select__ = (ChangeStateFormView.__select__ & + implements('Talk') & + rql_condition('X in_state S, S name "submitted"')) + + def get_form(self, entity, transition, **kwargs): + form = super(SendToReviewerStatusChangeView, self).get_form(entity, transition, **kwargs) + relation = ff.RelationField(name='reviews', role='object', + eidparam=True, + label=_('select reviewers'), + widget=fwdgs.Select(multiple=True)) + form.append_field(relation) + return form + +Simple extension of a form can be done from within the `FormView` +wrapping the form. FormView instances have a handy ``get_form`` method +that returns the form to be rendered. Here we add a ``RelationField`` +to the base state change form. + +One notable point is the ``eidparam`` argument: it tells both the +field and the ``edit controller`` that the field is linked to a +specific entity. + +It is hence entirely possible to add ad-hoc fields that will be +processed by some specialized instance of the edit controller. + + +Ad-hoc fields form +~~~~~~~~~~~~~~~~~~ We want to define a form doing something else than editing an entity. The idea is to propose a form to send an email to entities in a resultset which implements diff -r 1a30c5a56256 -r 5790462343cb doc/book/en/devweb/js.rst --- a/doc/book/en/devweb/js.rst Wed May 05 18:48:31 2010 +0200 +++ b/doc/book/en/devweb/js.rst Wed May 05 18:55:19 2010 +0200 @@ -22,8 +22,8 @@ .. XXX external_resources variable (which needs love) -CubicWeb javascript API -~~~~~~~~~~~~~~~~~~~~~~~ +Server-side Javascript API +~~~~~~~~~~~~~~~~~~~~~~~~~~ Javascript resources are typically loaded on demand, from views. The request object (available as self._cw from most application objects, @@ -39,8 +39,8 @@ snippet inline in the html headers. This is quite useful for setting up early jQuery(document).ready(...) initialisations. -CubicWeb javascript events -~~~~~~~~~~~~~~~~~~~~~~~~~~ +Javascript events +~~~~~~~~~~~~~~~~~ * ``server-response``: this event is triggered on HTTP responses (both standard and ajax). The two following extra parameters are passed @@ -53,8 +53,8 @@ ajax request, otherwise the document itself for standard HTTP requests. -Important AJAX APIS -~~~~~~~~~~~~~~~~~~~ +Important javascript AJAX APIS +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * `asyncRemoteExec` and `remoteExec` are the base building blocks for doing arbitrary async (resp. sync) communications with the server @@ -72,10 +72,10 @@ A simple example with asyncRemoteExec ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -In the python side, we have to extend the BaseController class. The -@jsonize decorator ensures that the `return value` of the method is -encoded as JSON data. By construction, the JSonController inputs -everything in JSON format. +In the python side, we have to extend the ``BaseController`` +class. The ``@jsonize`` decorator ensures that the return value of the +method is encoded as JSON data. By construction, the JSonController +inputs everything in JSON format. .. sourcecode: python @@ -225,13 +225,13 @@ `http://myinstance/json?`). The actual JSonController method name is encoded in the `params` dictionary using the `fname` key. -A more real-life example from CubicWeb -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +A more real-life example +~~~~~~~~~~~~~~~~~~~~~~~~ -A frequent use case of Web 2 applications is the delayed (or -on-demand) loading of pieces of the DOM. This is typically achieved -using some preparation of the initial DOM nodes, jQuery event handling -and proper use of loadxhtml. +A frequent need of Web 2 applications is the delayed (or demand +driven) loading of pieces of the DOM. This is typically achieved using +some preparation of the initial DOM nodes, jQuery event handling and +proper use of loadxhtml. We present here a skeletal version of the mecanism used in CubicWeb and available in web/views/tabs.py, in the `LazyViewMixin` class. @@ -317,9 +317,6 @@ } - - -.. XXX reloadComponent .. XXX userCallback / user_callback Javascript library: overview diff -r 1a30c5a56256 -r 5790462343cb doc/book/en/devweb/rtags.rst --- a/doc/book/en/devweb/rtags.rst Wed May 05 18:48:31 2010 +0200 +++ b/doc/book/en/devweb/rtags.rst Wed May 05 18:55:19 2010 +0200 @@ -9,8 +9,8 @@ .. _uicfg: -The ``uicfg`` module -~~~~~~~~~~~~~~~~~~~~ +The uicfg module +~~~~~~~~~~~~~~~~ .. note:: diff -r 1a30c5a56256 -r 5790462343cb migration.py --- a/migration.py Wed May 05 18:48:31 2010 +0200 +++ b/migration.py Wed May 05 18:55:19 2010 +0200 @@ -391,7 +391,7 @@ if optdict.get('default') is REQUIRED: self.config.input_option(optdescr[1], optdict) self.config.generate_config(open(newconfig, 'w')) - show_diffs(configfile, newconfig) + show_diffs(configfile, newconfig, ask_confirm=self.confirm is not yes) os.close(fd) if exists(newconfig): os.unlink(newconfig) diff -r 1a30c5a56256 -r 5790462343cb web/data/cubicweb.edition.js --- a/web/data/cubicweb.edition.js Wed May 05 18:48:31 2010 +0200 +++ b/web/data/cubicweb.edition.js Wed May 05 18:55:19 2010 +0200 @@ -402,6 +402,7 @@ } _displayValidationerrors(formid, descr[0], descr[1]); updateMessage(_('please correct errors below')); + // ensure the browser does not scroll down document.location.hash = '#header'; return false; }