web/data/cubicweb.edition.js
changeset 1808 aa09e20dd8c0
parent 1798 cc86fe8efaaa
child 1864 4ceaf8f2709b
equal deleted inserted replaced
1693:49075f57cf2c 1808:aa09e20dd8c0
     1 /*
     1 /*
     2  *  :organization: Logilab
     2  *  :organization: Logilab
     3  *  :copyright: 2003-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
     3  *  :copyright: 2003-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
     4  *  :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
     4  *  :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
     5  */
     5  */
     6 
     6 
     7 CubicWeb.require('python.js');
     7 CubicWeb.require('python.js');
     8 CubicWeb.require('htmlhelpers.js');
     8 CubicWeb.require('htmlhelpers.js');
    18  *
    18  *
    19  * @param varname the name of the variable as used in the original creation form
    19  * @param varname the name of the variable as used in the original creation form
    20  * @param tabindex the tabindex that should be set on the widget
    20  * @param tabindex the tabindex that should be set on the widget
    21  */
    21  */
    22 function setPropValueWidget(varname, tabindex) {
    22 function setPropValueWidget(varname, tabindex) {
    23     var key = firstSelected(jQuery('#pkey:'+varname));
    23     var key = firstSelected(document.getElementById('pkey:'+varname));
    24     if (key) {
    24     if (key) {
    25 	var args = _buildRemoteArgs('prop_widget', key, varname, tabindex);
    25 	var args = {fname: 'prop_widget', pageid: pageid,
    26 	jQuery('#div:value:'+varname).loadxhtml(JSON_BASE_URL, args, 'post');
    26      		    arg: map(jQuery.toJSON, [key, varname, tabindex])};
       
    27 	jqNode('div:value:'+varname).loadxhtml(JSON_BASE_URL, args, 'post');
    27     }
    28     }
    28 }
    29 }
    29 
    30 
    30 
    31 
    31 // *** EDITION FUNCTIONS ****************************************** //
    32 // *** EDITION FUNCTIONS ****************************************** //
    49 	}
    50 	}
    50 	return filter(isElementNode, elem.childNodes);
    51 	return filter(isElementNode, elem.childNodes);
    51     });
    52     });
    52 }
    53 }
    53 
    54 
       
    55 
    54 function showMatchingSelect(selectedValue, eid) {
    56 function showMatchingSelect(selectedValue, eid) {
    55     if (selectedValue) {
    57     if (selectedValue) {
    56 	divId = 'div' + selectedValue + '_' + eid;
    58 	divId = 'div' + selectedValue + '_' + eid;
    57 	var divNode = jQuery('#' + divId);
    59 	var divNode = jQuery('#' + divId);
    58 	if (!divNode.length) {
    60 	if (!divNode.length) {
    59 	    var args = {vid: 'unrelateddivs', relation: selectedValue,
    61 	    var args = {vid: 'unrelateddivs', relation: selectedValue,
    60 			rql: rql_for_eid(eid), pageid: pageid,
    62 			rql: rql_for_eid(eid), '__notemplate': 1,
    61 			'__notemplate': 1};
    63 			callback: function() {_showMatchingSelect(eid, jQuery('#' + divId))}};
    62 	    jQuery.get(JSON_BASE_URL, args, function(response) {
    64 	    jQuery('#unrelatedDivs_' + eid).loadxhtml(baseuri() + 'view', args, 'post', 'append');
    63 		// append generated HTML to the cell
       
    64 		jQuery('#unrelatedDivs_' + eid).append(getDomFromResponse(response));
       
    65 		_showMatchingSelect(eid, jQuery('#' + divId));
       
    66 	    });
       
    67 	    // deferred = doXHR(JSON_BASE_URL + queryString(args));
       
    68 	    // deferred.addCallback(_buildAndShowMatchingSelect, eid, divId);
       
    69 	} else {
    65 	} else {
    70 	    _showMatchingSelect(eid, divNode);
    66 	    _showMatchingSelect(eid, divNode);
    71 	}
    67 	}
    72     }
    68     } else {
    73     else {
       
    74 	_showMatchingSelect(eid, null);
    69 	_showMatchingSelect(eid, null);
    75     }
    70     }
    76 }
    71 }
    77 
    72 
    78 
       
    79 
       
    80 // @param divStr a HTML string returned by the server
       
    81 // function _buildAndShowMatchingSelect(eid, divId, req) {
       
    82 //     var tdNode = jQuery('#unrelatedDivs_' + eid);
       
    83 //     // append generated HTML to the cell
       
    84 //     tdNode.appendChild(getDomFromRequest(req));
       
    85 //     _showMatchingSelect(eid, jQuery('#' + divId));
       
    86 // }
       
    87 
    73 
    88 // @param divNode is a jQuery selection
    74 // @param divNode is a jQuery selection
    89 function _showMatchingSelect(eid, divNode) {
    75 function _showMatchingSelect(eid, divNode) {
    90     // hide all divs, and then show the matching one
    76     // hide all divs, and then show the matching one
    91     // (would actually be better to directly hide the displayed one)
    77     // (would actually be better to directly hide the displayed one)
   152 	return;
   138 	return;
   153     }
   139     }
   154     // add hidden parameter
   140     // add hidden parameter
   155     var entityForm = jQuery('#entityForm');
   141     var entityForm = jQuery('#entityForm');
   156     var oid = optionNode.id.substring(2); // option id is prefixed by "id"
   142     var oid = optionNode.id.substring(2); // option id is prefixed by "id"
   157     remote_exec('add_pending_insert', oid.split(':'));
   143     remoteExec('add_pending_inserts', [oid.split(':')]);
   158     var selectNode = optionNode.parentNode;
   144     var selectNode = optionNode.parentNode;
   159     // remove option node
   145     // remove option node
   160     selectNode.removeChild(optionNode);
   146     selectNode.removeChild(optionNode);
   161     // add line in table
   147     // add line in table
   162     if (cell) {
   148     if (cell) {
   178     var entityView = jqNode('a' + elementId).text();
   164     var entityView = jqNode('a' + elementId).text();
   179     jqNode(element_name + elementId).remove();
   165     jqNode(element_name + elementId).remove();
   180     if (comboId) {
   166     if (comboId) {
   181 	// re-insert option in combobox if it was taken from there
   167 	// re-insert option in combobox if it was taken from there
   182 	var selectNode = getNode(comboId);
   168 	var selectNode = getNode(comboId);
       
   169         // XXX what on object relation
   183 	if (selectNode){
   170 	if (selectNode){
   184 	   var options = selectNode.options;
   171 	   var options = selectNode.options;
   185 	   var node_id = elementId.substring(0, elementId.indexOf(':'));
   172 	   var node_id = elementId.substring(0, elementId.indexOf(':'));
   186 	   options[options.length] = OPTION({'id' : elementId, 'value' : node_id}, entityView);
   173 	   options[options.length] = OPTION({'id' : elementId, 'value' : node_id}, entityView);
   187 	}
   174 	}
   188     }
   175     }
   189     remote_exec('remove_pending_insert', elementId.split(':'));
   176     elementId = elementId.substring(2, elementId.length);
       
   177     remoteExec('remove_pending_insert', elementId.split(':'));
   190 }
   178 }
   191 
   179 
   192 // this function builds a Handle to cancel pending insertion
   180 // this function builds a Handle to cancel pending insertion
   193 function buildPendingDeleteHandle(elementId, eid) {
   181 function buildPendingDeleteHandle(elementId, eid) {
   194   var jscall = "javascript: addPendingDelete('" + elementId + ', ' + eid + "');";
   182   var jscall = "javascript: addPendingDelete('" + elementId + ', ' + eid + "');";
   196     'title' : _("delete this relation")}, '[x]');
   184     'title' : _("delete this relation")}, '[x]');
   197 }
   185 }
   198 
   186 
   199 // @param nodeId eid_from:r_type:eid_to
   187 // @param nodeId eid_from:r_type:eid_to
   200 function addPendingDelete(nodeId, eid) {
   188 function addPendingDelete(nodeId, eid) {
   201     var d = async_remote_exec('add_pending_delete', nodeId.split(':'));
   189     var d = asyncRemoteExec('add_pending_delete', nodeId.split(':'));
   202     d.addCallback(function () {
   190     d.addCallback(function () {
   203 	// and strike entity view
   191 	// and strike entity view
   204 	jqNode('span' + nodeId).addClass('pendingDelete');
   192 	jqNode('span' + nodeId).addClass('pendingDelete');
   205 	// replace handle text
   193 	// replace handle text
   206 	jqNode('handle' + nodeId).text('+');
   194 	jqNode('handle' + nodeId).text('+');
   207     });
   195     });
   208 }
   196 }
   209 
   197 
   210 // @param nodeId eid_from:r_type:eid_to
   198 // @param nodeId eid_from:r_type:eid_to
   211 function cancelPendingDelete(nodeId, eid) {
   199 function cancelPendingDelete(nodeId, eid) {
   212     var d = async_remote_exec('remove_pending_delete', nodeId.split(':'));
   200     var d = asyncRemoteExec('remove_pending_delete', nodeId.split(':'));
   213     d.addCallback(function () {
   201     d.addCallback(function () {
   214 	// reset link's CSS class
   202 	// reset link's CSS class
   215 	jqNode('span' + nodeId).removeClass('pendingDelete');
   203 	jqNode('span' + nodeId).removeClass('pendingDelete');
   216 	// replace handle text
   204 	// replace handle text
   217 	jqNode('handle' + nodeId).text('x');
   205 	jqNode('handle' + nodeId).text('x');
   230 
   218 
   231 
   219 
   232 function selectForAssociation(tripletIdsString, originalEid) {
   220 function selectForAssociation(tripletIdsString, originalEid) {
   233     var tripletlist = map(function (x) { return x.split(':'); },
   221     var tripletlist = map(function (x) { return x.split(':'); },
   234 			  tripletIdsString.split('-'));
   222 			  tripletIdsString.split('-'));
   235     var d = async_remote_exec('add_pending_inserts', tripletlist);
   223     var d = asyncRemoteExec('add_pending_inserts', tripletlist);
   236     d.addCallback(function () {
   224     d.addCallback(function () {
   237 	var args = {vid: 'edition', __mode: 'normal',
   225 	var args = {vid: 'edition', __mode: 'normal',
   238 		    rql: rql_for_eid(originalEid)};
   226 		    rql: rql_for_eid(originalEid)};
   239 	document.location = 'view?' + as_url(args);
   227 	document.location = 'view?' + asURL(args);
   240     });
   228     });
   241 
   229 
   242 }
   230 }
   243 
   231 
   244 
   232 
   245 function updateInlinedEntitiesCounters(rtype) {
   233 function updateInlinedEntitiesCounters(rtype) {
   246     jQuery('#inline' + rtype + 'slot span.icounter').each(function (i) {
   234     jQuery('#inline' + rtype + 'slot span.icounter').each(function (i) {
   247 	this.innerHTML = i+1;
   235 	this.innerHTML = i+1;
   248     });
   236     });
   249     // var divnode = jQuery('#inline' + rtype + 'slot');
   237 }
   250     // var iforms = getElementsByTagAndClassName('span', 'icounter', divnode);
   238 
   251     // for (var i=0; i<iforms.length; i++) {
       
   252     //   iforms[i].innerHTML = i+1;
       
   253     // }
       
   254 }
       
   255 
   239 
   256 /*
   240 /*
   257  * makes an AJAX request to get an inline-creation view's content
   241  * makes an AJAX request to get an inline-creation view's content
   258  * @param peid : the parent entity eid
   242  * @param peid : the parent entity eid
   259  * @param ptype : the parent entity type
       
   260  * @param ttype : the target (inlined) entity type
   243  * @param ttype : the target (inlined) entity type
   261  * @param rtype : the relation type between both entities
   244  * @param rtype : the relation type between both entities
   262  */
   245  */
   263 function addInlineCreationForm(peid, ptype, ttype, rtype, role) {
   246 function addInlineCreationForm(peid, ttype, rtype, role) {
   264     var d = async_rawremote_exec('inline_creation_form', peid, ptype, ttype, rtype, role);
   247     var d = asyncRemoteExec('inline_creation_form', peid, ttype, rtype, role);
   265     d.addCallback(function (response) {
   248     d.addCallback(function (response) {
   266 	var linknode = getNode('add' + rtype + ':' + peid + 'link');
   249 	var linknode = getNode('add' + rtype + ':' + peid + 'link');
   267         var dom = getDomFromResponse(response);
   250         var dom = getDomFromResponse(response);
   268 	var form = jQuery(dom);
   251 	var form = jQuery(dom);
   269 	form.css('display', 'none');
   252 	form.css('display', 'none');
   270 	form.insertBefore(linknode.parentNode).slideDown('fast');
   253 	form.insertBefore(linknode.parentNode).slideDown('fast');
   271 	// setStyle(form, {display: 'none'});
       
   272 	// insertSiblingNodesBefore(linknode.parentNode, form);
       
   273 	updateInlinedEntitiesCounters(rtype);
   254 	updateInlinedEntitiesCounters(rtype);
   274 	// slideDown(form, {'duration':0.6});
       
   275 	reorderTabindex();
   255 	reorderTabindex();
   276 	form.trigger('inlinedform-added');
   256 	form.trigger('inlinedform-added');
   277         postAjaxLoad(dom);
   257         postAjaxLoad(dom);
   278 	// MochiKit.Signal.signal(CubicWeb, 'inlinedform-added', form);
       
   279     });
   258     });
   280     d.addErrback(function (xxx) {
   259     d.addErrback(function (xxx) {
   281 	log('xxx =', xxx);
   260 	log('xxx =', xxx);
   282     });
   261     });
   283 }
   262 }
   299  * @param rtype : the relation type between both entities
   278  * @param rtype : the relation type between both entities
   300  * @param eid : the inlined entity eid
   279  * @param eid : the inlined entity eid
   301  */
   280  */
   302 function removeInlinedEntity(peid, rtype, eid) {
   281 function removeInlinedEntity(peid, rtype, eid) {
   303     var nodeid = ['rel', peid, rtype, eid].join('-');
   282     var nodeid = ['rel', peid, rtype, eid].join('-');
   304     var divid = ['div', peid, rtype, eid].join('-');
       
   305     var noticeid = ['notice', peid, rtype, eid].join('-');
       
   306     var node = jqNode(nodeid);
   283     var node = jqNode(nodeid);
   307     if (node && node.length) {
   284     if (node && node.length) {
   308 	node.remove();
   285 	node.remove();
       
   286 	var divid = ['div', peid, rtype, eid].join('-');
   309 	jqNode(divid).fadeTo('fast', 0.5);
   287 	jqNode(divid).fadeTo('fast', 0.5);
   310 	// setOpacity(divid, 0.4);
   288 	var noticeid = ['notice', peid, rtype, eid].join('-');
   311 	jqNode(noticeid).fadeIn('fast');
   289 	jqNode(noticeid).fadeIn('fast');
   312 	// appear(jQuery('#' + noticeid), {'duration': 0.5});
       
   313     }
   290     }
   314 }
   291 }
   315 
   292 
   316 function restoreInlinedEntity(peid, rtype, eid) {
   293 function restoreInlinedEntity(peid, rtype, eid) {
   317     var nodeid = ['rel', peid, rtype, eid].join('-');
   294     var nodeid = ['rel', peid, rtype, eid].join('-');
   320     var node = jqNode(nodeid);
   297     var node = jqNode(nodeid);
   321     if (!(node && node.length)) {
   298     if (!(node && node.length)) {
   322 	node = INPUT({type: 'hidden', id: nodeid,
   299 	node = INPUT({type: 'hidden', id: nodeid,
   323 		      name: rtype+':'+peid, value: eid});
   300 		      name: rtype+':'+peid, value: eid});
   324 	jqNode(['fs', peid, rtype, eid].join('-')).append(node);
   301 	jqNode(['fs', peid, rtype, eid].join('-')).append(node);
   325 	// appendChildNodes(fs, node);
       
   326 	jqNode(divid).fadeTo('fast', 1);
   302 	jqNode(divid).fadeTo('fast', 1);
   327 	// setOpacity(divid, 1);
       
   328 	jqNode(noticeid).hide();
   303 	jqNode(noticeid).hide();
   329 	// jQuery('#' + noticeid).hide();
       
   330     }
   304     }
   331 }
   305 }
   332 
   306 
   333 function _clearPreviousErrors(formid) {
   307 function _clearPreviousErrors(formid) {
   334     jQuery('#' + formid + ' span.error').remove();
   308     jQuery('#' + formid + ' span.error').remove();
   432     jQuery('form.entityForm').each(function () {
   406     jQuery('form.entityForm').each(function () {
   433 	var form = jQuery(this);
   407 	var form = jQuery(this);
   434 	var target = form.attr('cubicweb:target');
   408 	var target = form.attr('cubicweb:target');
   435 	if (target) {
   409 	if (target) {
   436 	    form.attr('target', target);
   410 	    form.attr('target', target);
   437 	    /* do not use display: none because some browser ignore iframe
   411 	    /* do not use display: none because some browsers ignore iframe
   438              *     with no display */
   412              * with no display */
   439 	    form.append(IFRAME({name: target, id: target,
   413 	    form.append(IFRAME({name: target, id: target,
   440 				src: 'javascript: void(0)',
   414 				src: 'javascript: void(0)',
   441 				width: '0px', height: '0px'}));
   415 				width: '0px', height: '0px'}));
   442 	}
   416 	}
   443     });
   417     });
   444 }
   418 }
   445 
   419 
   446 $(document).ready(setFormsTarget);
   420 $(document).ready(setFormsTarget);
   447 
   421 
   448 function _sendForm(formid, action) {
       
   449     var zipped = formContents(formid);
       
   450     return async_remote_exec('validate_form', action, zipped[0], zipped[1]);
       
   451 }
       
   452 
   422 
   453 /*
   423 /*
   454  * called on traditionnal form submission : the idea is to try
   424  * called on traditionnal form submission : the idea is to try
   455  * to post the form. If the post is successful, `validateForm` redirects
   425  * to post the form. If the post is successful, `validateForm` redirects
   456  * to the appropriate URL. Otherwise, the validation errors are displayed
   426  * to the appropriate URL. Otherwise, the validation errors are displayed
   457  * around the corresponding input fields.
   427  * around the corresponding input fields.
   458  */
   428  */
   459 function validateForm(formid, action, onsuccess) {
   429 function validateForm(formid, action, onsuccess) {
   460     try {
   430     try {
   461 	var d = _sendForm(formid, action);
   431 	var zipped = formContents(formid);
       
   432 	var d = asyncRemoteExec('validate_form', action, zipped[0], zipped[1]);
   462     } catch (ex) {
   433     } catch (ex) {
   463 	log('got exception', ex);
   434 	log('got exception', ex);
   464 	return false;
   435 	return false;
   465     }
   436     }
   466     function _callback(result, req) {
   437     function _callback(result, req) {
   467 	handleFormValidationResponse(formid, onsuccess, result);
   438 	handleFormValidationResponse(formid, onsuccess, result);
   468     }
   439     }
   469     // d.addCallback(handleFormValidationResponse, formid, onsuccess);
       
   470     d.addCallback(_callback);
   440     d.addCallback(_callback);
   471     return false;
   441     return false;
   472 }
   442 }
   473 
   443 
   474 /*
   444 
   475  * called by live-edit forms to submit changes
   445 /*
       
   446  * called by reledit forms to submit changes
   476  * @param formid : the dom id of the form used
   447  * @param formid : the dom id of the form used
   477  * @param rtype : the attribute being edited
   448  * @param rtype : the attribute being edited
   478  * @param eid : the eid of the entity being edited
   449  * @param eid : the eid of the entity being edited
   479  * @param reload: boolean to reload page if true (when changing URL dependant data)
   450  * @param reload: boolean to reload page if true (when changing URL dependant data)
   480  */
   451  */
   481 function inlineValidateForm(formid, rtype, eid, divid, reload) {
   452 function inlineValidateAttributeForm(formid, rtype, eid, divid, reload, default_value) {
   482     try {
   453     try {
   483 	var form = getNode(formid);
   454 	var form = getNode(formid);
   484 	if (typeof FCKeditorAPI != "undefined") {
   455 	if (typeof FCKeditorAPI != "undefined") {
   485 	    for ( var name in FCKeditorAPI.__Instances ) {
   456 	    for ( var name in FCKeditorAPI.__Instances ) {
   486 		var oEditor = FCKeditorAPI.__Instances[name] ;
   457 		var oEditor = FCKeditorAPI.__Instances[name] ;
   488 		    oEditor.UpdateLinkedField();
   459 		    oEditor.UpdateLinkedField();
   489 		}
   460 		}
   490 	    }
   461 	    }
   491 	}
   462 	}
   492 	var zipped = formContents(form);
   463 	var zipped = formContents(form);
   493 	var d = async_remote_exec('edit_field', 'apply', zipped[0], zipped[1], rtype, eid);
   464 	var d = asyncRemoteExec('edit_field', 'apply', zipped[0], zipped[1],
       
   465                                 rtype, eid, default_value);
   494     } catch (ex) {
   466     } catch (ex) {
   495 	log('got exception', ex);
   467 	log('got exception', ex);
   496 	return false;
   468 	return false;
   497     }
   469     }
   498     d.addCallback(function (result, req) {
   470     d.addCallback(function (result, req) {
   515 	return false;
   487 	return false;
   516     });
   488     });
   517     return false;
   489     return false;
   518 }
   490 }
   519 
   491 
       
   492 function inlineValidateRelationForm(formid, rtype, role, eid, divid, vid, default_value) {
       
   493     try {
       
   494 	var form = getNode(formid);
       
   495         var relname = rtype + ':' + eid;
       
   496         var newtarget = jQuery('[name=' + relname + ']').val();
       
   497 	var zipped = formContents(form);
       
   498 	var d = asyncRemoteExec('edit_relation', 'apply', zipped[0], zipped[1], rtype, role,
       
   499                                 eid, vid, default_value);
       
   500     } catch (ex) {
       
   501 	log('got exception', ex);
       
   502 	return false;
       
   503     }
       
   504     d.addCallback(function (result, req) {
       
   505         handleFormValidationResponse(formid, noop, result);
       
   506 	var fieldview = getNode(divid);
       
   507         fieldview.innerHTML = result[2];
       
   508 	// switch inline form off only if no error
       
   509 	if (result[0]) {
       
   510           // hide global error messages
       
   511 	  jQuery('div.errorMessage').remove();
       
   512 	  jQuery('#appMsg').hide();
       
   513           var inputname = 'edit' + role[0] + '-' + relname;
       
   514           jQuery('input[name=' + inputname + ']').val(newtarget);
       
   515 	  cancelInlineEdit(eid, rtype, divid);
       
   516 	}
       
   517         return false;
       
   518     });
       
   519   return false;
       
   520 }
       
   521 
       
   522 
   520 /**** inline edition ****/
   523 /**** inline edition ****/
   521 function showInlineEditionForm(eid, rtype, divid) {
   524 function showInlineEditionForm(eid, rtype, divid) {
   522     jQuery('#' + divid).hide();
   525     jQuery('#' + divid).hide();
   523     jQuery('#' + divid + '-form').show();
   526     jQuery('#' + divid + '-form').show();
   524 }
   527 }