diff -r 000000000000 -r b97547f5f1fa web/data/cubicweb.python.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/data/cubicweb.python.js Wed Nov 05 15:52:50 2008 +0100 @@ -0,0 +1,398 @@ +/* + * 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()) { + return true; + } + return false; +} + +Date.prototype.add = function(days) { + var res = new Date() + res.setTime(this.getTime() + (days * ONE_DAY)) + return res +} + +Date.prototype.sub = function(days) { + return this.add(-days); +} + +Date.prototype.iadd = function(days) { + // in-place add + this.setTime(this.getTime() + (days * ONE_DAY)) + // avoid strange rounding problems !! + this.setHours(12); +} + +Date.prototype.isub = function(days) { + // in-place sub + this.setTime(this.getTime() - (days * ONE_DAY)) +} + +/* + * returns the first day of the next month + */ +Date.prototype.nextMonth = function() { + if (this.getMonth() == 11) { + var d =new Date(this.getFullYear()+1, 0, 1); + return d; + } else { + var d2 = new Date(this.getFullYear(), this.getMonth()+1, 1); + return d2; + } +} + +/* + * returns the day of week, 0 being monday, 6 being sunday + */ +Date.prototype.getRealDay = function() { + // getDay() returns 0 for Sunday ==> 6 for Saturday + return (this.getDay()+6) % 7; +} + + +var _DATE_FORMAT_REGXES = { + 'Y': new RegExp('^-?[0-9]+'), + 'd': new RegExp('^[0-9]{1,2}'), + 'm': new RegExp('^[0-9]{1,2}'), + 'H': new RegExp('^[0-9]{1,2}'), + 'M': new RegExp('^[0-9]{1,2}') +} + +/* + * _parseData does the actual parsing job needed by `strptime` + */ +function _parseDate(datestring, format) { + var skip0 = new RegExp('^0*[0-9]+'); + var parsed = {}; + for (var i1=0,i2=0;i1 12) { + return null; + } + // !!! month indexes start at 0 in javascript !!! + date.setMonth(parsed.m - 1); + } + if (parsed.d) { + if (parsed.m < 1 || parsed.m > 31) { + return null; + } + date.setDate(parsed.d) + } + if (parsed.H) { + if (parsed.H < 0 || parsed.H > 23) { + return null; + } + date.setHours(parsed.H) + } + if (parsed.M) { + if (parsed.M < 0 || parsed.M > 59) { + return null; + } + date.setMinutes(parsed.M) + } + return date; +} + +// ========== END OF DATE EXTENSIONS ========== /// + + + +// ========== ARRAY EXTENSIONS ========== /// +Array.prototype.contains = function(element) { + return findValue(this, element) != -1; +} + +// ========== END OF ARRAY EXTENSIONS ========== /// + + + +// ========== STRING EXTENSIONS ========== // + +/* python-like startsWith method for js strings + * >>> + */ +String.prototype.startsWith = function(prefix) { + return this.indexOf(prefix) == 0; +} + +/* python-like endsWith method for js strings */ +String.prototype.endsWith = function(suffix) { + var startPos = this.length - suffix.length; + if (startPos < 0) { return false; } + return this.lastIndexOf(suffix, startPos) == startPos; +} + +/* python-like strip method for js strings */ +String.prototype.strip = function() { + return this.replace(/^\s*(.*?)\s*$/, "$1"); +}; + +/* py-equiv: string in list */ +String.prototype.in_ = function(values) { + return findValue(values, this) != -1; +} + +/* py-equiv: str.join(list) */ +String.prototype.join = function(args) { + return args.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] + */ +function list(iterable) { + iterator = iter(iterable); + var result = []; + while (true) { + /* iterates until StopIteration occurs */ + try { + result.push(iterator.next()); + } catch (exc) { + if (exc != StopIteration) { throw exc; } + return result; + } + } +} + +/* py-equiv: getattr(obj, attrname, default=None) */ +function getattr(obj, attrname, defaultValue) { + // when not passed, defaultValue === undefined + return obj[attrname] || defaultValue; +} + +/* py-equiv: operator.attrgetter */ +function attrgetter(attrname) { + return function(obj) { return getattr(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'] + */ +function sliceList(lst, start, stop, step) { + var start = start || 0; + var stop = stop || lst.length; + var step = step || 1; + if (stop < 0) { + stop = max(lst.length+stop, 0); + } + if (start < 0) { + start = min(lst.length+start, lst.length); + } + var result = []; + for (var i=start; i < stop; i+=step) { + result.push(lst[i]); + } + return result; +} + +/* returns a partial func that calls a mehod on its argument + * py-equiv: return lambda obj: getattr(obj, methname)(*args) + */ +function methodcaller(methname) { + var args = sliceList(arguments, 1); + return function(obj) { + return obj[methname].apply(obj, args); + }; +} + +/* use MochiKit's listMin / listMax */ +function min() { return listMin(arguments); } +function max() { return listMax(arguments); } + +// tricky multiple assign +// function assign(lst, varnames) { +// var length = min(lst.length, varnames.length); +// for(var i=0; i>> d = dict(["x", "y", "z"], [0, 1, 2]) + * >>> d['y'] + * 1 + * >>> d.y + * 1 + */ +function dict(keys, values) { + if (keys.length != values.length) { + throw "got different number of keys and values !"; + } + var newobj = {}; + for(var i=0; i methods are _STATICALLY_ attached when the class it created + * -> multiple inheritance was never tested, which means it doesn't work ;-) + */ +function defclass(name, bases, classdict) { + var baseclasses = bases || []; + + // this is the static inheritance approach (<=> differs from python) + var basemeths = {}; + var reverseLookup = []; + for(var i=baseclasses.length-1; i >= 0; i--) { + reverseLookup.push(baseclasses[i]); + } + reverseLookup.push({'__dict__' : classdict}); + + for(var i=0; i < reverseLookup.length; i++) { + var cls = reverseLookup[i]; + for (prop in cls.__dict__) { + // XXX hack to avoid __init__, __bases__... + if ( !_isAttrSkipped(prop) ) { + basemeths[prop] = cls.__dict__[prop]; + } + } + } + var userctor = basemeths['__init__']; + constructor = makeConstructor(userctor); + + // python-like interface + constructor.__name__ = name; + constructor.__bases__ = baseclasses; + constructor.__dict__ = {}; + constructor.prototype.__class__ = constructor; + // make bound / unbound methods + for (methname in basemeths) { + attachMethodToClass(constructor, methname, basemeths[methname]); + } + + return constructor; +} + +// Not really python-like +CubicWeb = {}; +// XXX backward compatibility +Erudi = CubicWeb; +CubicWeb.loaded = []; +CubicWeb.require = function(module) { + if (!CubicWeb.loaded.contains(module)) { + // a CubicWeb.load_javascript(module) function would require a dependency on ajax.js + log(module, ' is required but not loaded'); + } +}; + +CubicWeb.provide = function(module) { + if (!CubicWeb.loaded.contains(module)) { + CubicWeb.loaded.push(module); + } +}; + +CubicWeb.provide('python.js');