Added tag cubicweb-debian-version-3.9.6-1 for changeset 7d2cab567735
/** * Functions dedicated to edition. * * :organization: Logilab * :copyright: 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved. * :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr * *///============= Eproperty form functions =====================================///** * .. function:: setPropValueWidget(varname, tabindex) * * called on Eproperty key selection: * - get the selected value * - get a widget according to the key by a sync query to the server * - fill associated div with the returned html * * * `varname`, the name of the variable as used in the original creation form * * `tabindex`, the tabindex that should be set on the widget */functionsetPropValueWidget(varname,tabindex){varkey=firstSelected(document.getElementById('pkey:'+varname));if(key){varargs={fname:'prop_widget',pageid:pageid,arg:$.map([key,varname,tabindex],jQuery.toJSON)};cw.jqNode('div:value:'+varname).loadxhtml(JSON_BASE_URL,args,'post');}}// *** EDITION FUNCTIONS ****************************************** ///** * .. function:: reorderTabindex(start, formid) * * this function is called when an AJAX form was generated to * make sure tabindex remains consistent */functionreorderTabindex(start,formid){varform=cw.getNode(formid||'entityForm');varinputTypes=['INPUT','SELECT','TEXTAREA'];vartabindex=(start==null)?15:start;cw.utils.nodeWalkDepthFirst(form,function(elem){vartagName=elem.tagName.toUpperCase();if($.inArray(tagName,inputTypes)){if(jQuery(elem).attr('tabindex')!=null){tabindex+=1;jQuery(elem).attr('tabindex',tabindex);}returnnull;}returnjQuery.grep(elem.childNodes,isElementNode);});}functionshowMatchingSelect(selectedValue,eid){if(selectedValue){divId='div'+selectedValue+'_'+eid;vardivNode=jQuery('#'+divId);if(!divNode.length){varargs={vid:'unrelateddivs',relation:selectedValue,rql:rql_for_eid(eid),'__notemplate':1,callback:function(){_showMatchingSelect(eid,jQuery('#'+divId));}};jQuery('#unrelatedDivs_'+eid).loadxhtml(baseuri()+'view',args,'post','append');}else{_showMatchingSelect(eid,divNode);}}else{_showMatchingSelect(eid,null);}}/** * .. function:: _showMatchingSelect(eid, divNode) * * * `divNode`, a jQuery selection */function_showMatchingSelect(eid,divNode){// hide all divs, and then show the matching one// (would actually be better to directly hide the displayed one)jQuery('#unrelatedDivs_'+eid).children().hide();// divNode not found means 'no relation selected' (i.e. first blank item)if(divNode&&divNode.length){divNode.show();}}/** * .. function:: buildPendingInsertHandle(elementId, element_name, selectNodeId, eid) * * this function builds a Handle to cancel pending insertion */functionbuildPendingInsertHandle(elementId,element_name,selectNodeId,eid){jscall="javascript: cancelPendingInsert('"+[elementId,element_name,selectNodeId,eid].join("', '")+"')";returnA({'class':'handle','href':jscall,'title':_("cancel this insert")},'[x]');}functionbuildEntityLine(relationName,selectedOptionNode,comboId,eid){// textContent doesn't seem to work on selectedOptionNodevarcontent=selectedOptionNode.firstChild.nodeValue;varhandle=buildPendingInsertHandle(selectedOptionNode.id,'tr',comboId,eid);varlink=A({'href':'view?rql='+selectedOptionNode.value,'class':'editionPending','id':'a'+selectedOptionNode.id},content);vartr=TR({'id':'tr'+selectedOptionNode.id},[TH(null,relationName),TD(null,[handle,link])]);try{varseparator=cw.getNode('relationSelectorRow_'+eid);//dump('relationSelectorRow_' + eid) XXX warn dump is not implemented in konqueror (at least)// XXX Warning: separator.parentNode is not (always ?) the// table itself, but an intermediate node (TableSectionElement)vartableBody=separator.parentNode;tableBody.insertBefore(tr,separator);}catch(ex){log("got exception(2)!"+ex);}}functionbuildEntityCell(relationName,selectedOptionNode,comboId,eid){varhandle=buildPendingInsertHandle(selectedOptionNode.id,'div_insert_',comboId,eid);varlink=A({'href':'view?rql='+selectedOptionNode.value,'class':'editionPending','id':'a'+selectedOptionNode.id},content);vardiv=DIV({'id':'div_insert_'+selectedOptionNode.id},[handle,link]);try{vartd=jQuery('#cell'+relationName+'_'+eid);td.appendChild(div);}catch(ex){alert("got exception(3)!"+ex);}}functionaddPendingInsert(optionNode,eid,cell,relname){varvalue=jQuery(optionNode).attr('value');if(!value){// occurs when the first element in the box is selected (which is not// an entity but the combobox title)return;}// 2nd special caseif(value.indexOf('http')==0){document.location=value;return;}// add hidden parametervarentityForm=jQuery('#entityForm');varoid=optionNode.id.substring(2);// option id is prefixed by "id"loadRemote('json',ajaxFuncArgs('add_pending_inserts',null,[oid.split(':')]),'GET',true);varselectNode=optionNode.parentNode;// remove option nodeselectNode.removeChild(optionNode);// add line in tableif(cell){// new relation as a cell in multiple edit// var relation_name = relationSelected.getAttribute('value');// relation_name = relation_name.slice(0, relation_name.lastIndexOf('_'));buildEntityCell(relname,optionNode,selectNode.id,eid);}else{varrelationSelector=cw.getNode('relationSelector_'+eid);varrelationSelected=relationSelector.options[relationSelector.selectedIndex];// new relation as a line in simple editbuildEntityLine(relationSelected.text,optionNode,selectNode.id,eid);}}functioncancelPendingInsert(elementId,element_name,comboId,eid){// remove matching insert elementvarentityView=cw.jqNode('a'+elementId).text();cw.jqNode(element_name+elementId).remove();if(comboId){// re-insert option in combobox if it was taken from therevarselectNode=cw.getNode(comboId);// XXX what on object relationif(selectNode){varoptions=selectNode.options;varnode_id=elementId.substring(0,elementId.indexOf(':'));options[options.length]=OPTION({'id':elementId,'value':node_id},entityView);}}elementId=elementId.substring(2,elementId.length);loadRemote('json',ajaxFuncArgs('remove_pending_inserts',null,elementId.split(':')),'GET',true);}/** * .. function:: buildPendingDeleteHandle(elementId, eid) * * this function builds a Handle to cancel pending insertion */functionbuildPendingDeleteHandle(elementId,eid){varjscall="javascript: addPendingDelete('"+elementId+', '+eid+"');";returnA({'href':jscall,'class':'pendingDeleteHandle','title':_("delete this relation")},'[x]');}/** * .. function:: addPendingDelete(nodeId, eid) * * * `nodeId`, eid_from:r_type:eid_to */functionaddPendingDelete(nodeId,eid){vard=loadRemote('json',ajaxFuncArgs('add_pending_delete',null,nodeId.split(':')));d.addCallback(function(){// and strike entity viewcw.jqNode('span'+nodeId).addClass('pendingDelete');// replace handle textcw.jqNode('handle'+nodeId).text('+');});}/** * .. function:: cancelPendingDelete(nodeId, eid) * * * `nodeId`, eid_from:r_type:eid_to */functioncancelPendingDelete(nodeId,eid){vard=loadRemote('json',ajaxFuncArgs('remove_pending_delete',null,nodeId.split(':')));d.addCallback(function(){// reset link's CSS classcw.jqNode('span'+nodeId).removeClass('pendingDelete');// replace handle textcw.jqNode('handle'+nodeId).text('x');});}/** * .. function:: togglePendingDelete(nodeId, eid) * * * `nodeId`, eid_from:r_type:eid_to */functiontogglePendingDelete(nodeId,eid){// node found means we should cancel deletionif(jQuery.className.has(cw.getNode('span'+nodeId),'pendingDelete')){cancelPendingDelete(nodeId,eid);}else{addPendingDelete(nodeId,eid);}}functionselectForAssociation(tripletIdsString,originalEid){vartripletlist=$.map(tripletIdsString.split('-'),function(x){return[x.split(':')];});vard=loadRemote('json',ajaxFuncArgs('add_pending_inserts',null,tripletlist));d.addCallback(function(){varargs={vid:'edition',__mode:'normal',rql:rql_for_eid(originalEid)};document.location='view?'+asURL(args);});}functionupdateInlinedEntitiesCounters(rtype,role){jQuery('div.inline-'+rtype+'-'+role+'-slot span.icounter').each(function(i){this.innerHTML=i+1;});}/** * .. function:: addInlineCreationForm(peid, petype, ttype, rtype, role, i18nctx, insertBefore) * * makes an AJAX request to get an inline-creation view's content * * `peid`, the parent entity eid * * * `petype`, the parent entity type * * * `ttype`, the target (inlined) entity type * * * `rtype`, the relation type between both entities */functionaddInlineCreationForm(peid,petype,ttype,rtype,role,i18nctx,insertBefore){insertBefore=insertBefore||cw.getNode('add'+rtype+':'+peid+'link').parentNode;varargs=ajaxFuncArgs('inline_creation_form',null,peid,petype,ttype,rtype,role,i18nctx);vard=loadRemote('json',args);d.addCallback(function(response){vardom=getDomFromResponse(response);loadAjaxHtmlHead(dom);varform=jQuery(dom);form.css('display','none');form.insertBefore(insertBefore).slideDown('fast');updateInlinedEntitiesCounters(rtype,role);reorderTabindex(null,$(insertBefore).closest('form')[0]);jQuery(CubicWeb).trigger('inlinedform-added',form);// if the inlined form contains a file input, we must force// the form enctype to multipart/form-dataif(form.find('input:file').length){// NOTE: IE doesn't support dynamic enctype modification, we have// to set encoding too.form.closest('form').attr('enctype','multipart/form-data').attr('encoding','multipart/form-data');}_postAjaxLoad(dom);});d.addErrback(function(xxx){log('xxx =',xxx);});}/** * .. function:: removeInlineForm(peid, rtype, role, eid, showaddnewlink) * * removes the part of the form used to edit an inlined entity */functionremoveInlineForm(peid,rtype,role,eid,showaddnewlink){cw.jqNode(['div',peid,rtype,eid].join('-')).slideUp('fast',function(){$(this).remove();updateInlinedEntitiesCounters(rtype,role);});if(showaddnewlink){toggleVisibility(showaddnewlink);}}/** * .. function:: removeInlinedEntity(peid, rtype, eid) * * alternatively adds or removes the hidden input that make the * edition of the relation `rtype` possible between `peid` and `eid` * * `peid`, the parent entity eid * * * `rtype`, the relation type between both entities * * * `eid`, the inlined entity eid */functionremoveInlinedEntity(peid,rtype,eid){// XXX work around the eid_param thing (eid + ':' + eid) for #471746varnodeid=['rel',peid,rtype,eid+':'+eid].join('-');varnode=cw.jqNode(nodeid);if(!node.attr('cubicweb:type')){node.attr('cubicweb:type',node.val());node.val('');vardivid=['div',peid,rtype,eid].join('-');cw.jqNode(divid).fadeTo('fast',0.5);varnoticeid=['notice',peid,rtype,eid].join('-');cw.jqNode(noticeid).fadeIn('fast');}}functionrestoreInlinedEntity(peid,rtype,eid){// XXX work around the eid_param thing (eid + ':' + eid) for #471746varnodeid=['rel',peid,rtype,eid+':'+eid].join('-');varnode=cw.jqNode(nodeid);if(node.attr('cubicweb:type')){node.val(node.attr('cubicweb:type'));node.attr('cubicweb:type','');cw.jqNode(['fs',peid,rtype,eid].join('-')).append(node);vardivid=['div',peid,rtype,eid].join('-');cw.jqNode(divid).fadeTo('fast',1);varnoticeid=['notice',peid,rtype,eid].join('-');cw.jqNode(noticeid).hide();}}function_clearPreviousErrors(formid){// on some case (eg max request size exceeded, we don't know the formidif(formid){jQuery('#'+formid+'ErrorMessage').remove();jQuery('#'+formid+' span.errorMsg').remove();jQuery('#'+formid+' .error').removeClass('error');}else{jQuery('span.errorMsg').remove();jQuery('.error').removeClass('error');}}function_displayValidationerrors(formid,eid,errors){varglobalerrors=[];varfirsterrfield=null;for(fieldnameinerrors){varerrmsg=errors[fieldname];if(!fieldname){globalerrors.push(errmsg);}else{varfieldid=fieldname+':'+eid;varsuffixes=['','-subject','-object'];varfound=false;// XXX remove suffixes at some pointfor(vari=0,length=suffixes.length;i<length;i++){varfield=cw.jqNode(fieldname+suffixes[i]+':'+eid);if(field&&jQuery(field).attr('type')!='hidden'){if(!firsterrfield){firsterrfield='err-'+fieldid;}jQuery(field).addClass('error');varspan=SPAN({'id':'err-'+fieldid,'class':"errorMsg"},errmsg);field.before(span);found=true;break;}}if(!found){firsterrfield=formid;globalerrors.push(_(fieldname)+' : '+errmsg);}}}if(globalerrors.length){if(globalerrors.length==1){varinnernode=SPAN(null,globalerrors[0]);}else{varinnernode=UL(null,$.map(globalerrors,partial(LI,null)));}// insert DIV and innernode before the formvardiv=DIV({'class':"errorMessage",'id':formid+'ErrorMessage'});div.appendChild(innernode);jQuery('#'+formid).before(div);}returnfirsterrfield||formid;}functionhandleFormValidationResponse(formid,onsuccess,onfailure,result,cbargs){// Successif(result[0]){if(onsuccess){onsuccess(result,formid,cbargs);}else{document.location.href=result[1];}returntrue;}if(onfailure&&!onfailure(result,formid,cbargs)){returnfalse;}unfreezeFormButtons(formid);// Failures_clearPreviousErrors(formid);vardescr=result[1];varerrmsg;// Unknown structureif(!cw.utils.isArrayLike(descr)||descr.length!=2){errmsg=descr;}else{_displayValidationerrors(formid,descr[0],descr[1]);errmsg=_('please correct errors below');}updateMessage(errmsg);// ensure the browser does not scroll downdocument.location.hash='#header';returnfalse;}/** * .. function:: unfreezeFormButtons(formid) * * unfreeze form buttons when the validation process is over */functionunfreezeFormButtons(formid){jQuery('#progress').hide();// on some case (eg max request size exceeded, we don't know the formidif(formid){jQuery('#'+formid+' .validateButton').removeAttr('disabled');}else{jQuery('.validateButton').removeAttr('disabled');}returntrue;}/** * .. function:: freezeFormButtons(formid) * * disable form buttons while the validation is being done */functionfreezeFormButtons(formid){jQuery('#progress').show();jQuery('#'+formid+' .validateButton').attr('disabled','disabled');returntrue;}/** * .. function:: postForm(bname, bvalue, formid) * * used by additional submit buttons to remember which button was clicked */functionpostForm(bname,bvalue,formid){varform=cw.getNode(formid);if(bname){varchild=form.appendChild(INPUT({type:'hidden',name:bname,value:bvalue}));}varonsubmit=form.onsubmit;if(!onsubmit||(onsubmit&&onsubmit())){form.submit();}if(bname){jQuery(child).remove();}}/** * .. function:: setFormsTarget(node) * * called on load to set target and iframeso object. * * .. note:: * * this is a hack to make the XHTML compliant. * * .. note:: * * `object` nodes might be a potential replacement for iframes * * .. note:: * * there is a XHTML module allowing iframe elements but there * is still the problem of the form's `target` attribute */functionsetFormsTarget(node){var$node=jQuery(node||document.body);$node.find('form').each(function(){varform=jQuery(this);vartarget=form.attr('cubicweb:target');if(target){form.attr('target',target);/* do not use display: none because some browsers ignore iframe * with no display */form.append(IFRAME({name:target,id:target,src:'javascript: void(0)',width:'0px',height:'0px'}));}});}jQuery(document).ready(function(){setFormsTarget();});/** * .. function:: validateForm(formid, action, onsuccess, onfailure) * * called on traditionnal form submission : the idea is to try * to post the form. If the post is successful, `validateForm` redirects * to the appropriate URL. Otherwise, the validation errors are displayed * around the corresponding input fields. */functionvalidateForm(formid,action,onsuccess,onfailure){try{varzipped=cw.utils.formContents(formid);varargs=ajaxFuncArgs('validate_form',null,action,zipped[0],zipped[1]);vard=loadRemote('json',args,'POST');}catch(ex){log('got exception',ex);returnfalse;}function_callback(result,req){handleFormValidationResponse(formid,onsuccess,onfailure,result);}d.addCallback(_callback);returnfalse;}// ======================= DEPRECATED FUNCTIONS ========================= //// (mostly reledit related)/** * .. function:: inlineValidateRelationFormOptions(rtype, eid, divid, options) * * called by reledit forms to submit changes * * `rtype`, the attribute being edited * * * `eid`, the eid of the entity being edited * * * `options`, a dictionnary of options used by the form validation handler such * as ``role``, ``onsuccess``, ``onfailure``, ``reload``, ``vid``, ``lzone`` * and ``default_value``: * * * `onsucess`, javascript function to execute on success, default is noop * * * `onfailure`, javascript function to execute on failure, default is noop * * * `default_value`, value if the field is empty * * * `lzone`, html fragment (string) for a clic-zone triggering actual edition */showInlineEditionForm=cw.utils.deprecatedFunction('[3.9] this is now unused by reledit (see cw.reledit.js)',functionshowInlineEditionForm(eid,rtype,divid){jQuery('#'+divid).hide();jQuery('#'+divid+'-value').hide();jQuery('#'+divid+'-form').show();});hideInlineEdit=cw.utils.deprecatedFunction('[3.9] this is now unused by reledit (see cw.reledit.js)',functionhideInlineEdit(eid,rtype,divid){jQuery('#appMsg').hide();jQuery('div.errorMessage').remove();jQuery('#'+divid).show();jQuery('#'+divid+'-value').show();jQuery('#'+divid+'-form').hide();});inlineValidateRelationFormOptions=cw.utils.deprecatedFunction('[3.9] this is now unused by reledit (see cw.reledit.js)',functioninlineValidateRelationFormOptions(rtype,eid,divid,options){try{varform=cw.getNode(divid+'-form');varrelname=rtype+':'+eid;varnewtarget=jQuery('[name='+relname+']').val();varzipped=cw.utils.formContents(form);varargs=ajaxFuncArgs('validate_form',null,'apply',zipped[0],zipped[1]);vard=loadRemote(JSON_BASE_URL,args,'POST');}catch(ex){returnfalse;}d.addCallback(function(result,req){execFormValidationResponse(rtype,eid,divid,options,result);});returnfalse;});execFormValidationResponse=cw.utils.deprecatedFunction('[3.9] this is now unused by reledit (see cw.reledit.js)',functionexecFormValidationResponse(rtype,eid,divid,options,result){options=$.extend({onsuccess:noop,onfailure:noop},options);if(handleFormValidationResponse(divid+'-form',options.onsucess,options.onfailure,result)){if(options.reload){document.location.reload();}else{varargs={fname:'reledit_form',rtype:rtype,role:options.role,eid:eid,divid:divid,reload:options.reload,vid:options.vid,default_value:options.default_value,landing_zone:options.lzone};jQuery('#'+divid+'-reledit').parent().loadxhtml(JSON_BASE_URL,args,'post');}}});/** * .. function:: loadInlineEditionFormOptions(eid, rtype, divid, options) * * inline edition */loadInlineEditionFormOptions=cw.utils.deprecatedFunction('[3.9] this is now unused by reledit (see cw.reledit.js) ',functionloadInlineEditionFormOptions(eid,rtype,divid,options){varargs={fname:'reledit_form',rtype:rtype,role:options.role,eid:eid,divid:divid,reload:options.reload,vid:options.vid,default_value:options.default_value,landing_zone:options.lzone,callback:function(){showInlineEditionForm(eid,rtype,divid);}};jQuery('#'+divid+'-reledit').parent().loadxhtml(JSON_BASE_URL,args,'post');});inlineValidateRelationForm=cw.utils.deprecatedFunction('[3.9] inlineValidateRelationForm() function is deprecated, use inlineValidateRelationFormOptions instead',function(rtype,role,eid,divid,reload,vid,default_value,lzone,onsucess,onfailure){try{varform=cw.getNode(divid+'-form');varrelname=rtype+':'+eid;varnewtarget=jQuery('[name='+relname+']').val();varzipped=cw.utils.formContents(form);vard=asyncRemoteExec('validate_form','apply',zipped[0],zipped[1]);}catch(ex){returnfalse;}d.addCallback(function(result,req){varoptions={role:role,reload:reload,vid:vid,default_value:default_value,lzone:lzone,onsucess:onsucess||$.noop,onfailure:onfailure||$.noop};execFormValidationResponse(rtype,eid,divid,options);});returnfalse;});loadInlineEditionForm=cw.utils.deprecatedFunction('[3.9] loadInlineEditionForm() function is deprecated, use loadInlineEditionFormOptions instead',function(eid,rtype,role,divid,reload,vid,default_value,lzone){varargs={fname:'reledit_form',rtype:rtype,role:role,eid:eid,divid:divid,reload:reload,vid:vid,default_value:default_value,landing_zone:lzone,callback:function(){showInlineEditionForm(eid,rtype,divid);}};jQuery('#'+divid+'-reledit').parent().loadxhtml(JSON_BASE_URL,args,'post');});