update _render_attribute / _render_relation prototype to gain more control on label through uicfg (for attributes and relations). Keep bw compat for crm/iliane
/* * This file contains extensions for standard javascript types * */ONE_DAY=86400000;// (in milliseconds)// ========== DATE EXTENSIONS ========== ///Date.prototype.equals=function(other){/* compare with other date ignoring time differences */if(this.getYear()==other.getYear()&&this.getMonth()==other.getMonth()&&this.getDate()==other.getDate()){returntrue;}returnfalse;};Date.prototype.add=function(days){varres=newDate();res.setTime(this.getTime()+(days*ONE_DAY));returnres;};Date.prototype.sub=function(days){returnthis.add(-days);};Date.prototype.iadd=function(days){// in-place addthis.setTime(this.getTime()+(days*ONE_DAY));// avoid strange rounding problems !!this.setHours(12);};Date.prototype.isub=function(days){// in-place subthis.setTime(this.getTime()-(days*ONE_DAY));};/* * returns the first day of the next month */Date.prototype.nextMonth=function(){if(this.getMonth()==11){vard=newDate(this.getFullYear()+1,0,1);returnd;}else{vard2=newDate(this.getFullYear(),this.getMonth()+1,1);returnd2;}};/* * returns the day of week, 0 being monday, 6 being sunday */Date.prototype.getRealDay=function(){// getDay() returns 0 for Sunday ==> 6 for Saturdayreturn(this.getDay()+6)%7;};Date.prototype.strftime=function(fmt){if(this.toLocaleFormat!==undefined){// browser dependentreturnthis.toLocaleFormat(fmt);}// XXX implement at least a decent fallback implementationreturnthis.getFullYear()+'/'+(this.getMonth()+1)+'/'+this.getDate();};var_DATE_FORMAT_REGXES={'Y':newRegExp('^-?[0-9]+'),'d':newRegExp('^[0-9]{1,2}'),'m':newRegExp('^[0-9]{1,2}'),'H':newRegExp('^[0-9]{1,2}'),'M':newRegExp('^[0-9]{1,2}')}/* * _parseData does the actual parsing job needed by `strptime` */function_parseDate(datestring,format){varskip0=newRegExp('^0*[0-9]+');varparsed={};for(vari1=0,i2=0;i1<format.length;i1++,i2++){varc1=format.charAt(i1);varc2=datestring.charAt(i2);if(c1=='%'){c1=format.charAt(++i1);vardata=_DATE_FORMAT_REGXES[c1].exec(datestring.substring(i2));if(!data.length){returnnull;}data=data[0];i2+=data.length-1;varvalue=parseInt(data,10);if(isNaN(value)){returnnull;}parsed[c1]=value;continue;}if(c1!=c2){returnnull;}}returnparsed;}/* * basic implementation of strptime. The only recognized formats * defined in _DATE_FORMAT_REGEXES (i.e. %Y, %d, %m, %H, %M) */functionstrptime(datestring,format){varparsed=_parseDate(datestring,format);if(!parsed){returnnull;}// create initial date (!!! year=0 means 1900 !!!)vardate=newDate(0,0,1,0,0);date.setFullYear(0);// reset to year 0if(parsed.Y){date.setFullYear(parsed.Y);}if(parsed.m){if(parsed.m<1||parsed.m>12){returnnull;}// !!! month indexes start at 0 in javascript !!!date.setMonth(parsed.m-1);}if(parsed.d){if(parsed.m<1||parsed.m>31){returnnull;}date.setDate(parsed.d);}if(parsed.H){if(parsed.H<0||parsed.H>23){returnnull;}date.setHours(parsed.H);}if(parsed.M){if(parsed.M<0||parsed.M>59){returnnull;}date.setMinutes(parsed.M);}returndate;}// ========== END OF DATE EXTENSIONS ========== ///// ========== ARRAY EXTENSIONS ========== ///Array.prototype.contains=function(element){returnfindValue(this,element)!=-1;};// ========== END OF ARRAY EXTENSIONS ========== ///// ========== STRING EXTENSIONS ========== ///* python-like startsWith method for js strings * >>> */String.prototype.startsWith=function(prefix){returnthis.indexOf(prefix)==0;};/* python-like endsWith method for js strings */String.prototype.endsWith=function(suffix){varstartPos=this.length-suffix.length;if(startPos<0){returnfalse;}returnthis.lastIndexOf(suffix,startPos)==startPos;};/* python-like strip method for js strings */String.prototype.strip=function(){returnthis.replace(/^\s*(.*?)\s*$/,"$1");};/* py-equiv: string in list */String.prototype.in_=function(values){returnfindValue(values,this)!=-1;};/* py-equiv: str.join(list) */String.prototype.join=function(args){returnargs.join(this);};/* python-like list builtin * transforms an iterable in a js sequence * >>> gen = ifilter(function(x) {return x%2==0}, range(10)) * >>> s = list(gen) * [0,2,4,6,8] */functionlist(iterable){variterator=iter(iterable);varresult=[];while(true){/* iterates until StopIteration occurs */try{result.push(iterator.next());}catch(exc){if(exc!=StopIteration){throwexc;}returnresult;}}}/* py-equiv: getattr(obj, attrname, default=None) */functiongetattr(obj,attrname,defaultValue){// when not passed, defaultValue === undefinedreturnobj[attrname]||defaultValue;}/* py-equiv: operator.attrgetter */functionattrgetter(attrname){returnfunction(obj){returngetattr(obj,attrname);};}/* returns a subslice of `lst` using `start`/`stop`/`step` * start, stop might be negative * * >>> sliceList(['a', 'b', 'c', 'd', 'e', 'f'], 2) * ['c', 'd', 'e', 'f'] * >>> sliceList(['a', 'b', 'c', 'd', 'e', 'f'], 2, -2) * ['c', 'd'] * >>> sliceList(['a', 'b', 'c', 'd', 'e', 'f'], -3) * ['d', 'e', 'f'] */functionsliceList(lst,start,stop,step){varstart=start||0;varstop=stop||lst.length;varstep=step||1;if(stop<0){stop=max(lst.length+stop,0);}if(start<0){start=min(lst.length+start,lst.length);}varresult=[];for(vari=start;i<stop;i+=step){result.push(lst[i]);}returnresult;}/* returns a partial func that calls a mehod on its argument * py-equiv: return lambda obj: getattr(obj, methname)(*args) */functionmethodcaller(methname){varargs=sliceList(arguments,1);returnfunction(obj){returnobj[methname].apply(obj,args);};}/* use MochiKit's listMin / listMax */functionmin(){returnlistMin(arguments);}functionmax(){returnlistMax(arguments);}/* * >>> d = dict(["x", "y", "z"], [0, 1, 2]) * >>> d['y'] * 1 * >>> d.y * 1 */functiondict(keys,values){if(keys.length!=values.length){throw"got different number of keys and values !";}varnewobj={};for(vari=0;i<keys.length;i++){newobj[keys[i]]=values[i];}returnnewobj;}functionconcat(){return''.join(list(arguments));}/**** class factories ****/// transforms a function into an unbound methodfunctionmakeUnboundMethod(meth){functionunboundMeth(self){varnewargs=sliceList(arguments,1);returnmeth.apply(self,newargs);}unboundMeth.__name__=meth.__name__;returnunboundMeth;}functionattachMethodToClass(cls,methname,meth){meth.__name__=methname;// XXX : this is probably bad for memory usagecls.__dict__[methname]=meth;cls[methname]=makeUnboundMethod(meth);// for the class itselfcls.prototype[methname]=meth;// for the instance}// simple internal function that tells if the attribute should// be copied from baseclasses or notfunction_isAttrSkipped(attrname){varskipped=['__class__','__dict__','__bases__','prototype'];for(vari=0;i<skipped.length;i++){if(skipped[i]==attrname){returntrue;}}returnfalse;}// internal function used to build the class constructorfunctionmakeConstructor(userctor){returnfunction(){// this is a proxy to user's __init__if(userctor){userctor.apply(this,arguments);}};}/* this is a js class factory. objects returned by this function behave * more or less like a python class. The `class` function prototype is * inspired by the python `type` builtin * Important notes : * -> methods are _STATICALLY_ attached when the class it created * -> multiple inheritance was never tested, which means it doesn't work ;-) */functiondefclass(name,bases,classdict){varbaseclasses=bases||[];// this is the static inheritance approach (<=> differs from python)varbasemeths={};varreverseLookup=[];for(vari=baseclasses.length-1;i>=0;i--){reverseLookup.push(baseclasses[i]);}reverseLookup.push({'__dict__':classdict});for(vari=0;i<reverseLookup.length;i++){varcls=reverseLookup[i];for(propincls.__dict__){// XXX hack to avoid __init__, __bases__...if(!_isAttrSkipped(prop)){basemeths[prop]=cls.__dict__[prop];}}}varuserctor=basemeths['__init__'];varconstructor=makeConstructor(userctor);// python-like interfaceconstructor.__name__=name;constructor.__bases__=baseclasses;constructor.__dict__={};constructor.prototype.__class__=constructor;// make bound / unbound methodsfor(methnameinbasemeths){attachMethodToClass(constructor,methname,basemeths[methname]);}returnconstructor;}// Not really python-likeCubicWeb={};// XXX backward compatibilityErudi=CubicWeb;CubicWeb.loaded=[];CubicWeb.require=function(module){if(!CubicWeb.loaded.contains(module)){// a CubicWeb.load_javascript(module) function would require a dependency on ajax.jslog(module,' is required but not loaded');}};CubicWeb.provide=function(module){if(!CubicWeb.loaded.contains(module)){CubicWeb.loaded.push(module);}};CubicWeb.provide('python.js');