merge stable
authorSylvain Thénault <sylvain.thenault@logilab.fr>
Tue, 19 May 2009 13:21:29 +0200
branchstable
changeset 1867 b2fe73a55899
parent 1862 94dc8ccd320b (current diff)
parent 1866 118c7528d08f (diff)
child 1868 af1ae863606d
merge
--- a/web/data/cubicweb.edition.js	Tue May 19 13:08:51 2009 +0200
+++ b/web/data/cubicweb.edition.js	Tue May 19 13:21:29 2009 +0200
@@ -342,11 +342,11 @@
 }
 
 
-function handleFormValidationResponse(formid, onsuccess, result) {
+function handleFormValidationResponse(formid, onsuccess, onfailure, result) {
     // Success
     if (result[0]) {
 	if (onsuccess) {
-	    return onsuccess(result[1]);
+	    return onsuccess(result[1], formid);
 	} else {
 	    document.location.href = result[1];
 	    return ;
@@ -365,6 +365,9 @@
     _displayValidationerrors(formid, descr[0], descr[1]);
     updateMessage(_("please correct errors below"));
     document.location.hash = '#header';
+    if (onfailure){
+	onfailure(formid);
+    }
     return false;
 }
 
@@ -426,7 +429,7 @@
  * to the appropriate URL. Otherwise, the validation errors are displayed
  * around the corresponding input fields.
  */
-function validateForm(formid, action, onsuccess) {
+function validateForm(formid, action, onsuccess, onfailure) {
     try {
 	var zipped = formContents(formid);
 	var d = asyncRemoteExec('validate_form', action, zipped[0], zipped[1]);
@@ -435,7 +438,7 @@
 	return false;
     }
     function _callback(result, req) {
-	handleFormValidationResponse(formid, onsuccess, result);
+	handleFormValidationResponse(formid, onsuccess, onfailure, result);
     }
     d.addCallback(_callback);
     return false;
--- a/web/data/cubicweb.preferences.css	Tue May 19 13:08:51 2009 +0200
+++ b/web/data/cubicweb.preferences.css	Tue May 19 13:21:29 2009 +0200
@@ -6,28 +6,14 @@
  */
 
 
-table.preferences td{ 
- padding: 0 0.5em 1em;
+.preferences .validateButton{ 
+ margin-top:0px;
  }
 
 fieldset.preferences{  
  border : 1px solid #CFCEB7;
- margin:1em 0;
- padding:0 1em 1em;
-}
-
-div.preffield {
- margin-bottom: 0.8em ;
-}
-
-/*
-div.preffield label{ 
- font-size:110%
- }
-*/
-
-div.prefinput{ 
- margin:.3em 0;
+ margin:7px 1em 0;
+ padding:2px 6px 6px;
 }
 
 div.componentLink{ 
@@ -36,35 +22,49 @@
 
 a.componentTitle{
  font-weight:bold;
- color: #000;
+ color: #000/*#0083AB;*/
  }
 
 a.componentTitle:visited{
  color: #000;
 }
 
-
-
 h2.propertiesform a{
  display:block;
  margin: 10px 0px 6px 0px;
  font-weight: bold;
- color: #222211;
+ color: #000;
  padding: 0.2em 0.2em 0.2em 16px;
  background:#eeedd9 url("puce_down.png") 3px center no-repeat;
- font-size:76%;
+ font-size:89%;
+}
+
+h2.propertiesform a:hover{ 
+ background-color:#cfceb7;
 }
 
-h2.propertiesform a:hover{
- color:#000;
- background-color:#cfceb7;
+h2.propertiesform a:hover,
+h2.propertiesform a:visited{
  text-decoration:none;
+ color: #000;
 }
 
+div.preffield {
+ margin-bottom: 5px; 
+ padding:2px 5px;
+ background:#eeedd9;
+}
+
+div.prefinput{ 
+ margin:.3em;  
+}
+
+
 div.prefinput select.changed,
 div.prefinput input.changed{ 
- background:#eeedd9;
- border: 1px solid #eeedd9;
+ border: 1px solid #000;
+ font-weight:bold;
+
 }
 
 div.prefinput select,
@@ -74,23 +74,26 @@
 }
 
 .prefinput input.error {
- background:transparent url(error.png) no-repeat scroll 100% 50% !important;
+ /* background:#fff url(error.png) no-repeat scroll 100% 50% !important; */
+ border:1px solid red !important; 
+ color:red;
+ padding-right:1em;
 }
 
 
 div.formsg{ 
  font-weight:bold;
  margin:0.5em 0px;
- }
+}
 
 
-div.formsg .critical{ 
+div.critical{ 
  color:red;
  padding-left:20px;
  background:#fff url(critical.png) no-repeat;
  }
 
-div.formsg .message{ 
+div.formsg .msg{ 
  color : green;
 }
 
@@ -105,11 +108,6 @@
   cursor: default;
 }
 
-.error{ 
- color:red;
- padding-right:1em;
- }
-
 div.openlink{ 
  display:inline;
- }
\ No newline at end of file
+ }
--- a/web/data/cubicweb.preferences.js	Tue May 19 13:08:51 2009 +0200
+++ b/web/data/cubicweb.preferences.js	Tue May 19 13:21:29 2009 +0200
@@ -4,11 +4,9 @@
  *     move me in a more appropriate place
  */
 
-function toggleVisibility(elemId, cookiename) {
-    _clearPreviousMessages();
-    jqNode(elemId).toggleClass('hidden');
-    asyncRemoteExec('set_cookie', cookiename,
-                      jQuery('#' + elemId).attr('class'));
+function togglePrefVisibility(elemId) {
+    clearPreviousMessages();
+    jQuery('#' + elemId).toggleClass('hidden');
 }
 
 function closeFieldset(fieldsetid){
@@ -43,44 +41,25 @@
 }
 
 function validatePrefsForm(formid){
-    var form = getNode(formid);
     freezeFormButtons(formid);
-    try {
-	var d = _sendForm(formid, null);
-    } catch (ex) {
-	log('got exception', ex);
-	return false;
-    }
-    function _callback(result, req) {
-	_clearPreviousMessages();
-	_clearPreviousErrors(formid);
-	// success
-	if(result[0]){
-	    return submitSucces(formid)
-	}
- 	// Failures
-	unfreezeFormButtons(formid);
-	var descr = result[1];
-        if (!isArrayLike(descr) || descr.length != 2) {
-	   log('got strange error :', descr);
-	   updateMessage(descr);
-	   return ;
-	}
-        _displayValidationerrors(formid, descr[0], descr[1]);
-	var dom = DIV({'class':'critical'},
-		      _("please correct errors below"));
-	jQuery(form).find('div.formsg').empty().append(dom);
-	updateMessage(_(""));
-	return false;
-    }
-    d.addCallback(_callback);
-    return false;
+    clearPreviousMessages();
+    clearPreviousErrors(formid);
+    return validateForm(formid, null,  submitSucces, submitFailure);
 }
 
-function submitSucces(formid){
+function submitFailure(formid){
+    var form = jQuery('#'+formid);
+    var dom = DIV({'class':'critical'},
+		  _("please correct errors below"));
+    jQuery(form).find('div.formsg').empty().append(dom);
+    // clearPreviousMessages()
+    jQuery(form).find('span.error').next().focus();
+}
+
+function submitSucces(url, formid){
     var form = jQuery('#'+formid);
     setCurrentValues(form);
-    var dom = DIV({'class':'message'},
+    var dom = DIV({'class':'msg'},
 		  _("changes applied"));
     jQuery(form).find('div.formsg').empty().append(dom);
     jQuery(form).find('input').removeClass('changed');
@@ -88,13 +67,13 @@
     return;
 }
 
-function _clearPreviousMessages() {
+function clearPreviousMessages() {
     jQuery('div#appMsg').addClass('hidden');
     jQuery('div.formsg').empty();
 }
 
-function _clearPreviousErrors(formid) {
-    jQuery('#' + formid + ' span.error').remove();
+function clearPreviousErrors(formid) {
+    jQuery('#err-value:' + formid).remove();
 }
 
 
@@ -111,20 +90,20 @@
 		unfreezeButtons = _checkValue(jQuery(this), unfreezeButtons);
 	    }
      }); 
-   
+    
     if (unfreezeButtons){
 	unfreezeFormButtons(form.attr('id'));
     }else{
 	if (!success){
-	    _clearPreviousMessages();
+	    clearPreviousMessages();
 	}
-	_clearPreviousErrors(form.attr('id'));
+	clearPreviousErrors(form.attr('id'));
 	freezeFormButtons(form.attr('id'));
     }
 }
 
 function _checkValue(input, unfreezeButtons){
-     var currentValueInput = jQuery("input[id=current-" + input.attr('name') + "]");
+     var currentValueInput = jQuery("input[name=current-" + input.attr('name') + "]");
      if (currentValueInput.attr('value') != input.attr('value')){
 	 input.addClass('changed');
 	 unfreezeButtons = true;
@@ -138,14 +117,13 @@
 
 
 function setCurrentValues(form){
-    jQuery(form).find('input[id^=current-value]').each(function () { 
+    jQuery(form).find('input[name^=current-value]').each(function () { 
 	    var currentValueInput = jQuery(this);
-	    var name = currentValueInput.attr('id').split('-')[1];
+	    var name = currentValueInput.attr('name').split('-')[1];
 	    jQuery(form).find("[name=" + name + "]").each(function (){
 		    var input = jQuery(this);
 		    if(input.attr('type')=='radio'){
 			if(input.attr('checked')){
-			    log(input.attr('value'));
 			    currentValueInput.attr('value', input.attr('value'));
 			}
 		    }else{
@@ -155,7 +133,6 @@
     });
 }
 
-
 function initEvents(){
   jQuery('form').each(function() { 
 	  var form = jQuery(this);
@@ -169,6 +146,7 @@
 	  form.find('select').change(function(){  
 		  checkValues(form);	 
           });
+	  setCurrentValues(form);
     });
 }
 
--- a/web/formrenderers.py	Tue May 19 13:08:51 2009 +0200
+++ b/web/formrenderers.py	Tue May 19 13:21:29 2009 +0200
@@ -83,13 +83,13 @@
         return tags.label(label, **attrs)
 
     def render_help(self, form, field):
-        help = [ u'<br/>' ]
+	help = []
         descr = field.help
         if descr:
-            help.append('<span class="helper">%s</span>' % form.req._(descr))
+            help.append('<div class="helper">%s</div>' % form.req._(descr))
         example = field.example_format(form.req)
         if example:
-            help.append('<span class="helper">(%s: %s)</span>'
+            help.append('<div class="helper">(%s: %s)</div>'
                         % (form.req._('sample format'), example))
         return u'&nbsp;'.join(help)
 
--- a/web/views/cwproperties.py	Tue May 19 13:08:51 2009 +0200
+++ b/web/views/cwproperties.py	Tue May 19 13:21:29 2009 +0200
@@ -17,6 +17,7 @@
 from cubicweb.view import StartupView
 from cubicweb.web import uicfg, stdmsgs
 from cubicweb.web.form import CompositeForm, EntityFieldsForm, FormViewMixIn
+from cubicweb.web.formrenderers import FormRenderer
 from cubicweb.web.formfields import FIELDS, StringField
 from cubicweb.web.formwidgets import Select, Button, SubmitButton
 from cubicweb.web.views import primary
@@ -48,10 +49,9 @@
 _('category')
 
 
-def make_togglable_link(nodeid, label, cookiename):
+def make_togglable_link(nodeid, label):
     """builds a HTML link that switches the visibility & remembers it"""
-    action = u"javascript: toggleVisibility('%s', '%s')" % \
-        (nodeid, cookiename)
+    action = u"javascript: togglePrefVisibility('%s')" % nodeid
     return u'<a href="%s">%s</a>' % (action, label)
 
 def css_class(someclass):
@@ -95,7 +95,7 @@
 
     def call(self, **kwargs):
         """The default view representing the application's index"""
-        self.req.add_js('cubicweb.preferences.js')
+        self.req.add_js(('cubicweb.edition.js', 'cubicweb.preferences.js', 'cubicweb.ajax.js'))
         self.req.add_css('cubicweb.preferences.css')
         vreg = self.vreg
         values = self.defined_keys
@@ -113,41 +113,51 @@
                 mainopts.setdefault(parts[0], []).append(key)
         # precompute form to consume error message
         for group, keys in mainopts.items():
-            mainopts[group] = self.form(keys, True)
+            mainopts[group] = self.form(group, keys, False)
+
         for group, objects in groupedopts.items():
             for oid, keys in objects.items():
-                groupedopts[group][oid] = self.form(keys, True)
+                groupedopts[group][oid] = self.form(group + '-' + oid, keys, True)
+
         w = self.w
         req = self.req
         _ = req._
         w(u'<h1>%s</h1>\n' % _(self.title))
-        # we don't want this in each sub-forms
+        # we don't want this in each sub-forms XXX
         w(u'<div id="progress">%s</div>' % self.req._('validating...'))
         for label, group, form in sorted((_(g), g, f)
                                          for g, f in mainopts.iteritems()):
             status = css_class(self._group_status(group))
             w(u'<h2 class="propertiesform">%s</h2>\n' %
-              (make_togglable_link('fieldset_' + group, label,
-                                   self._cookie_name(group))))
+            (make_togglable_link('fieldset_' + group, label.capitalize())))
             w(u'<div id="fieldset_%s" %s>' % (group, status))
+            w(u'<fieldset class="preferences">')
             w(form)
-            w(u'</div>')
+            w(u'</fieldset></div>')
+
         for label, group, objects in sorted((_(g), g, o)
                                             for g, o in groupedopts.iteritems()):
             status = css_class(self._group_status(group))
             w(u'<h2 class="propertiesform">%s</h2>\n' %
-              (make_togglable_link('fieldset_' + group, label,
-                                   self._cookie_name(group))))
+              (make_togglable_link('fieldset_' + group, label.capitalize())))
             w(u'<div id="fieldset_%s" %s>' % (group, status))
-            for label, oid, form in sorted((self.req.__('%s_%s' % (group, o)), o, f)
-                                           for o, f in objects.iteritems()):
-                w(u'<fieldset class="subentity">')
-                w(u'<legend class="componentTitle">%s</legend>\n' % label)
+	    
+	    # create selection
+	    sorted_objects =  sorted((self.req.__('%s_%s' % (group, o)), o, f)
+                                           for o, f in objects.iteritems())
+	    for label, oid, form in sorted_objects:
+                w(u'''<div class="componentLink"><a href="javascript:noop();" onclick="javascript:toggleVisibility('field_%(oid)s_%(group)s')" class="componentTitle">%(label)s</a>''' % {'label':label, 'oid':oid, 'group':group})
+                w(u''' (<div class="openlink"><a href="javascript:noop();" onclick="javascript:closeFieldset('fieldset_%(group)s')">%(label)s</a></div>)'''
+                  % {'label':_('close all'), 'group':group})
+                w(u'</div>')
                 docmsgid = '%s_%s_description' % (group, oid)
                 doc = _(docmsgid)
                 if doc != docmsgid:
-                    w(u'<p class="description">%s</p>' % html_escape(doc))
-                w(form)
+                    w(u'<div class="helper">%s</div>' % html_escape(doc).capitalize())
+		    
+		w(u'<fieldset id="field_%(oid)s_%(group)s" class="%(group)s preferences">'
+                  % {'oid':oid, 'group':group})
+		w(form)
                 w(u'</fieldset>')
             w(u'</div>')
 
@@ -175,20 +185,22 @@
             entity['value'] = self.vreg.property_value(key)
         return entity
 
-    def form(self, keys, splitlabel=False):
-        buttons = [SubmitButton(),
-                   Button(stdmsgs.BUTTON_CANCEL, cwaction='cancel')]
-        form = CompositeForm(self.req, domid=None, action=self.build_url(),
-                             form_buttons=buttons,
+    def form(self, formid, keys, splitlabel=False):
+        buttons = [SubmitButton()]
+        form = CompositeForm(self.req, domid=formid, action=self.build_url(),
+                             form_buttons=buttons, 
+			     onsubmit="return validatePrefsForm('%s')" % formid,
                              submitmsg=self.req._('changes applied'))
-        path = self.req.relative_path()
+	path = self.req.relative_path()
         if '?' in path:
             path, params = path.split('?', 1)
             form.form_add_hidden('__redirectparams', params)
         form.form_add_hidden('__redirectpath', path)
         for key in keys:
             self.form_row(form, key, splitlabel)
-        return form.form_render(display_progress_div=False)
+	renderer = EPropertiesFormRenderer()
+        return form.form_render(display_progress_div=False,
+				renderer=renderer)
 
     def form_row(self, form, key, splitlabel):
         entity = self.entity_for_key(key)
@@ -196,15 +208,16 @@
             label = key.split('.')[-1]
         else:
             label = key
-        subform = EntityFieldsForm(self.req, entity=entity, set_error_url=False)
+	subform = EntityFieldsForm(self.req, entity=entity, set_error_url=False)
+	
         subform.append_field(PropertyValueField(name='value', label=label,
                                                 eidparam=True))
         subform.vreg = self.vreg
         subform.form_add_hidden('pkey', key, eidparam=True)
+ 	subform.form_add_hidden("current-value:%s" % entity.eid,)
         form.form_add_subform(subform)
         return subform
-
-
+    
 def is_user_prefs(cls, req, rset, row=None, col=0, **kwargs):
     return req.user.eid == rset[row or 0][col]
 
@@ -326,7 +339,7 @@
         if vocab is not None:
             if callable(vocab):
                 # list() just in case its a generator function
-                self.choices = list(vocab(form.req))
+                self.choices = list(vocab(form.req)) 
             else:
                 self.choices = vocab
             wdg = Select()
@@ -338,6 +351,30 @@
                 wdg.attrs.setdefault('size', 3)
         self.widget = wdg
 
+class EPropertiesFormRenderer(FormRenderer):
+    """specific renderer for cwproperties"""
+
+    def open_form(self, form, values):
+	err = '<div class="formsg"></div>'
+	return super(EPropertiesFormRenderer, self).open_form(form, values) + err
+    
+    def _render_fields(self, fields, w, form):
+	for field in fields:
+	    w(u'<div class="preffield">\n')
+	    if self.display_label:
+		w(u'%s' % self.render_label(form, field))
+            error = form.form_field_error(field)
+	    w(u'%s' % self.render_help(form, field))
+	    w(u'<div class="prefinput">')
+      	    w(field.render(form, self))
+	    w(u'</div>')
+	    w(u'</div>')
+
+    def render_buttons(self, w, form):
+        w(u'<div>\n')
+        for button in form.form_buttons:
+            w(u'%s\n' % button.render(form))
+        w(u'</div>')
 
 uicfg.autoform_field.tag_attribute(('CWProperty', 'pkey'), PropertyKeyField)
 uicfg.autoform_field.tag_attribute(('CWProperty', 'value'), PropertyValueField)