make inline relation forms individually renderable
/* MochiKit -> jQuery compatibility module */functionforEach(array,func){for(vari=0,length=array.length;i<length;i++){func(array[i]);}}functiongetElementsByTagAndClassName(tag,klass,root){root=root||document;// FIXME root is not used in this compat implementationreturnjQuery(tag+'.'+klass);}functionmap(func,array){// XXX jQUery tends to simplify lists with only one element :// >>> y = ['a:b:c']// >>> jQuery.map(y, function(y) { return y.split(':');})// ["a", "b", "c"]// where I would expect :// [ ["a", "b", "c"] ]// return jQuery.map(array, func);varresult=[];for(vari=0,length=array.length;i<length;i++){result.push(func(array[i]));}returnresult;}functionfindValue(array,element){returnjQuery.inArray(element,array);}functionfilter(func,array){returnjQuery.grep(array,func);}functionnoop(){}functionaddElementClass(node,klass){jQuery(node).addClass(klass);}functiontoggleElementClass(node,klass){jQuery(node).toggleClass(klass);}functionremoveElementClass(node,klass){jQuery(node).removeClass(klass);}hasElementClass=jQuery.className.has;functionpartial(func){varargs=sliceList(arguments,1);returnfunction(){returnfunc.apply(null,merge(args,arguments));};}functionlog(){// XXX dummy implementation// console.log.apply(arguments); ???varargs=[];for(vari=0;i<arguments.length;i++){args.push(arguments[i]);}if(typeof(window)!="undefined"&&window.console&&window.console.log){window.console.log(args.join(' '));}}functiongetNodeAttribute(node,attribute){returnjQuery(node).attr(attribute);}functionisArray(it){// taken from dojoreturnit&&(itinstanceofArray||typeofit=="array");}functionisString(it){// taken from dojoreturn!!arguments.length&&it!=null&&(typeofit=="string"||itinstanceofString);}functionisArrayLike(it){// taken from dojoreturn(it&&it!==undefined&&// keep out built-in constructors (Number, String, ...) which have length// properties!isString(it)&&!jQuery.isFunction(it)&&!(it.tagName&&it.tagName.toLowerCase()=='form')&&(isArray(it)||isFinite(it.length)));}functiongetNode(node){if(typeof(node)=='string'){returndocument.getElementById(node);}returnnode;}/* safe version of jQuery('#nodeid') because we use ':' in nodeids * which messes with jQuery selection mechanism */functionjqNode(node){node=getNode(node);if(node){returnjQuery(node);}returnnull;}functionevalJSON(json){// trust sourcereturneval("("+json+")");}functionurlEncode(str){if(typeof(encodeURIComponent)!="undefined"){returnencodeURIComponent(str).replace(/\'/g,'%27');}else{returnescape(str).replace(/\+/g,'%2B').replace(/\"/g,'%22').rval.replace(/\'/g,'%27');}}functionswapDOM(dest,src){dest=getNode(dest);varparent=dest.parentNode;if(src){src=getNode(src);parent.replaceChild(src,dest);}else{parent.removeChild(dest);}returnsrc;}functionreplaceChildNodes(node/*, nodes...*/){varelem=getNode(node);arguments[0]=elem;varchild;while((child=elem.firstChild)){elem.removeChild(child);}if(arguments.length<2){returnelem;}else{for(vari=1;i<arguments.length;i++){elem.appendChild(arguments[i]);}returnelem;}}update=jQuery.extend;functioncreateDomFunction(tag){functionbuilddom(params,children){varnode=document.createElement(tag);for(keyinparams){varvalue=params[key];if(key.substring(0,2)=='on'){// this is an event handler definitionif(typeofvalue=='string'){// litteral definitionvalue=newFunction(value);}node[key]=value;}else{// normal node attributenode.setAttribute(key,params[key]);}}if(children){if(!isArrayLike(children)){children=[children];for(vari=2;i<arguments.length;i++){vararg=arguments[i];if(isArray(arg)){children=merge(children,arg);}else{children.push(arg);}}}for(vari=0;i<children.length;i++){varchild=children[i];if(typeofchild=="string"||typeofchild=="number"){child=document.createTextNode(child);}node.appendChild(child);}}returnnode;}returnbuilddom;}A=createDomFunction('a');BUTTON=createDomFunction('button');BR=createDomFunction('br');CANVAS=createDomFunction('canvas');DD=createDomFunction('dd');DIV=createDomFunction('div');DL=createDomFunction('dl');DT=createDomFunction('dt');FIELDSET=createDomFunction('fieldset');FORM=createDomFunction('form');H1=createDomFunction('H1');H2=createDomFunction('H2');H3=createDomFunction('H3');H4=createDomFunction('H4');H5=createDomFunction('H5');H6=createDomFunction('H6');HR=createDomFunction('hr');IMG=createDomFunction('img');INPUT=createDomFunction('input');LABEL=createDomFunction('label');LEGEND=createDomFunction('legend');LI=createDomFunction('li');OL=createDomFunction('ol');OPTGROUP=createDomFunction('optgroup');OPTION=createDomFunction('option');P=createDomFunction('p');PRE=createDomFunction('pre');SELECT=createDomFunction('select');SPAN=createDomFunction('span');STRONG=createDomFunction('strong');TABLE=createDomFunction('table');TBODY=createDomFunction('tbody');TD=createDomFunction('td');TEXTAREA=createDomFunction('textarea');TFOOT=createDomFunction('tfoot');TH=createDomFunction('th');THEAD=createDomFunction('thead');TR=createDomFunction('tr');TT=createDomFunction('tt');UL=createDomFunction('ul');// cubicweb specific//IFRAME = createDomFunction('iframe');functionIFRAME(params){if('name'inparams){try{varnode=document.createElement('<iframe name="'+params['name']+'">');}catch(ex){varnode=document.createElement('iframe');}}else{varnode=document.createElement('iframe');}for(keyinparams){if(key!='name'){varvalue=params[key];if(key.substring(0,2)=='on'){// this is an event handler definitionif(typeofvalue=='string'){// litteral definitionvalue=newFunction(value);}node[key]=value;}else{// normal node attributenode.setAttribute(key,params[key]);}}}returnnode;}// dummy ultra minimalist implementation on deferred for jQueryfunctionDeferred(){this.__init__(this);}jQuery.extend(Deferred.prototype,{__init__:function(){this.onSuccess=[];this.onFailure=[];this.req=null;},addCallback:function(callback){this.onSuccess.push([callback,sliceList(arguments,1)]);returnthis;},addErrback:function(callback){this.onFailure.push([callback,sliceList(arguments,1)]);returnthis;},success:function(result){try{for(vari=0;i<this.onSuccess.length;i++){varcallback=this.onSuccess[i][0];varargs=merge([result,this.req],this.onSuccess[i][1]);callback.apply(null,args);}}catch(error){this.error(this.xhr,null,error);}},error:function(xhr,status,error){for(vari=0;i<this.onFailure.length;i++){varcallback=this.onFailure[i][0];varargs=merge([error,this.req],this.onFailure[i][1]);callback.apply(null,args);}}});/** @id MochiKit.DateTime.toISOTime */toISOTime=function(date,realISO/* = false */){if(typeof(date)=="undefined"||date===null){returnnull;}varhh=date.getHours();varmm=date.getMinutes();varss=date.getSeconds();varlst=[((realISO&&(hh<10))?"0"+hh:hh),((mm<10)?"0"+mm:mm),((ss<10)?"0"+ss:ss)];returnlst.join(":");};_padTwo=function(n){return(n>9)?n:"0"+n;};/** @id MochiKit.DateTime.toISODate */toISODate=function(date){if(typeof(date)=="undefined"||date===null){returnnull;}return[date.getFullYear(),_padTwo(date.getMonth()+1),_padTwo(date.getDate())].join("-");};/** @id MochiKit.DateTime.toISOTimeStamp */toISOTimestamp=function(date,realISO/* = false*/){if(typeof(date)=="undefined"||date===null){returnnull;}varsep=realISO?"T":" ";varfoot=realISO?"Z":"";if(realISO){date=newDate(date.getTime()+(date.getTimezoneOffset()*60000));}returntoISODate(date)+sep+toISOTime(date,realISO)+foot;};/* * Asynchronously load an url and return a deferred * whose callbacks args are decoded according to * the Content-Type response header */functionloadRemote(url,data,reqtype){vard=newDeferred();jQuery.ajax({url:url,type:reqtype,data:data,beforeSend:function(xhr){d.req=xhr;},success:function(data,status){if(d.req.getResponseHeader("content-type")=='application/json'){data=evalJSON(data);}d.success(data);},error:function(xhr,status,error){error=evalJSON(xhr.responseText);d.error(xhr,status,error['reason']);}});returnd;}/* depth-first implementation of the nodeWalk function found * in MochiKit.Base * cf. http://mochikit.com/doc/html/MochiKit/Base.html#fn-nodewalk */functionnodeWalkDepthFirst(node,visitor){varchildren=visitor(node);if(children){for(vari=0;i<children.length;i++){nodeWalkDepthFirst(children[i],visitor);}}}/* Returns true if all the given Array-like or string arguments are not empty (obj.length > 0) */functionisNotEmpty(obj){for(vari=0;i<arguments.length;i++){varo=arguments[i];if(!(o&&o.length)){returnfalse;}}returntrue;}/** this implementation comes from MochiKit */functionformContents(elem/* = document.body */){varnames=[];varvalues=[];if(typeof(elem)=="undefined"||elem===null){elem=document.body;}else{elem=getNode(elem);}nodeWalkDepthFirst(elem,function(elem){varname=elem.name;if(isNotEmpty(name)){vartagName=elem.tagName.toUpperCase();if(tagName==="INPUT"&&(elem.type=="radio"||elem.type=="checkbox")&&!elem.checked){returnnull;}if(tagName==="SELECT"){if(elem.type=="select-one"){if(elem.selectedIndex>=0){varopt=elem.options[elem.selectedIndex];varv=opt.value;if(!v){varh=opt.outerHTML;// internet explorer sure does suck.if(h&&!h.match(/^[^>]+\svalue\s*=/i)){v=opt.text;}}names.push(name);values.push(v);returnnull;}// no form elements?names.push(name);values.push("");returnnull;}else{varopts=elem.options;if(!opts.length){names.push(name);values.push("");returnnull;}for(vari=0;i<opts.length;i++){varopt=opts[i];if(!opt.selected){continue;}varv=opt.value;if(!v){varh=opt.outerHTML;// internet explorer sure does suck.if(h&&!h.match(/^[^>]+\svalue\s*=/i)){v=opt.text;}}names.push(name);values.push(v);}returnnull;}}if(tagName==="FORM"||tagName==="P"||tagName==="SPAN"||tagName==="DIV"){returnelem.childNodes;}names.push(name);values.push(elem.value||'');returnnull;}returnelem.childNodes;});return[names,values];}functionmerge(array1,array2){varresult=[];for(vari=0,length=arguments.length;i<length;i++){vararray=arguments[i];for(varj=0,alength=array.length;j<alength;j++){result.push(array[j]);}}returnresult;}varKEYS={KEY_ESC:27,KEY_ENTER:13};