# HG changeset patch # User Adrien Di Mascio # Date 1276069372 -7200 # Node ID ba23470501446ad1f09547319988d79144484ee5 # Parent 18d4e78b9369f5a136b993335c254d35c7d3399e# Parent 6de8437b06bd0ade0281f6604f55bd9b715a6cf7 backport stable branch diff -r 6de8437b06bd -r ba2347050144 __pkginfo__.py --- a/__pkginfo__.py Wed Jun 09 09:41:36 2010 +0200 +++ b/__pkginfo__.py Wed Jun 09 09:42:52 2010 +0200 @@ -43,7 +43,7 @@ 'logilab-common': '>= 0.50.2', 'logilab-mtconverter': '>= 0.6.0', 'rql': '>= 0.26.0', - 'yams': '>= 0.28.1', + 'yams': '>= 0.30.0', 'docutils': '>= 0.6', #gettext # for xgettext, msgcat, etc... # web dependancies diff -r 6de8437b06bd -r ba2347050144 appobject.py --- a/appobject.py Wed Jun 09 09:41:36 2010 +0200 +++ b/appobject.py Wed Jun 09 09:42:52 2010 +0200 @@ -39,6 +39,92 @@ from logilab.common.decorators import classproperty from logilab.common.logging_ext import set_log_methods +from cubicweb.cwconfig import CubicWebConfiguration + +def class_regid(cls): + """returns a unique identifier for an appobject class""" + if 'id' in cls.__dict__: + warn('[3.6] %s.%s: id is deprecated, use __regid__' + % (cls.__module__, cls.__name__), DeprecationWarning) + cls.__regid__ = cls.id + if hasattr(cls, 'id') and not isinstance(cls.id, property): + return cls.id + return cls.__regid__ + +# helpers for debugging selectors +TRACED_OIDS = None + +def _trace_selector(cls, selector, args, ret): + # /!\ lltrace decorates pure function or __call__ method, this + # means argument order may be different + if isinstance(cls, Selector): + selname = str(cls) + vobj = args[0] + else: + selname = selector.__name__ + vobj = cls + if TRACED_OIDS == 'all' or class_regid(vobj) in TRACED_OIDS: + #SELECTOR_LOGGER.warning('selector %s returned %s for %s', selname, ret, cls) + print '%s -> %s for %s(%s)' % (selname, ret, vobj, vobj.__regid__) + +def lltrace(selector): + """use this decorator on your selectors so the becomes traceable with + :class:`traced_selection` + """ + # don't wrap selectors if not in development mode + if CubicWebConfiguration.mode == 'system': # XXX config.debug + return selector + def traced(cls, *args, **kwargs): + ret = selector(cls, *args, **kwargs) + if TRACED_OIDS is not None: + _trace_selector(cls, selector, args, ret) + return ret + traced.__name__ = selector.__name__ + traced.__doc__ = selector.__doc__ + return traced + +class traced_selection(object): + """ + Typical usage is : + + .. sourcecode:: python + + >>> from cubicweb.selectors import traced_selection + >>> with traced_selection(): + ... # some code in which you want to debug selectors + ... # for all objects + + Don't forget the 'from __future__ import with_statement' at the module top-level + if you're using python prior to 2.6. + + This will yield lines like this in the logs:: + + selector one_line_rset returned 0 for + + You can also give to :class:`traced_selection` the identifiers of objects on + which you want to debug selection ('oid1' and 'oid2' in the example above). + + .. sourcecode:: python + + >>> with traced_selection( ('regid1', 'regid2') ): + ... # some code in which you want to debug selectors + ... # for objects with __regid__ 'regid1' and 'regid2' + + A potentially usefull point to set up such a tracing function is + the `cubicweb.vregistry.Registry.select` method body. + """ + + def __init__(self, traced='all'): + self.traced = traced + + def __enter__(self): + global TRACED_OIDS + TRACED_OIDS = self.traced + + def __exit__(self, exctype, exc, traceback): + global TRACED_OIDS + TRACED_OIDS = None + return traceback is None # selector base classes and operations ######################################## @@ -175,6 +261,7 @@ class AndSelector(MultiSelector): """and-chained selectors (formerly known as chainall)""" + @lltrace def __call__(self, cls, *args, **kwargs): score = 0 for selector in self.selectors: @@ -187,6 +274,7 @@ class OrSelector(MultiSelector): """or-chained selectors (formerly known as chainfirst)""" + @lltrace def __call__(self, cls, *args, **kwargs): for selector in self.selectors: partscore = selector(cls, *args, **kwargs) @@ -199,6 +287,7 @@ def __init__(self, selector): self.selector = selector + @lltrace def __call__(self, cls, *args, **kwargs): score = self.selector(cls, *args, **kwargs) return int(not score) diff -r 6de8437b06bd -r ba2347050144 cwconfig.py --- a/cwconfig.py Wed Jun 09 09:41:36 2010 +0200 +++ b/cwconfig.py Wed Jun 09 09:42:52 2010 +0200 @@ -295,8 +295,6 @@ # log_format = '%(asctime)s - [%(threadName)s] (%(name)s) %(levelname)s: %(message)s' # nor remove appobjects based on unused interface [???] cleanup_interface_sobjects = True - # debug mode - debugmode = False if (CWDEV and _forced_mode != 'system'): @@ -662,12 +660,14 @@ vregpath.append(path + '.py') return vregpath - def __init__(self): + def __init__(self, debugmode=False): register_stored_procedures() ConfigurationMixIn.__init__(self) + self.debugmode = debugmode self.adjust_sys_path() self.load_defaults() - self.translations = {} + # will be properly initialized later by _gettext_init + self.translations = {'en': (unicode, lambda ctx, msgid: unicode(msgid) )} # don't register ReStructured Text directives by simple import, avoid pb # with eg sphinx. # XXX should be done properly with a function from cw.uicfg @@ -682,26 +682,23 @@ # overriden in CubicWebConfiguration self.cls_adjust_sys_path() - def init_log(self, logthreshold=None, debug=False, - logfile=None, syslog=False): + def init_log(self, logthreshold=None, logfile=None, syslog=False): """init the log service""" if logthreshold is None: - if debug: + if self.debugmode: logthreshold = 'DEBUG' else: logthreshold = self['log-threshold'] - self.debugmode = debug if sys.platform == 'win32': # no logrotate on win32, so use logging rotation facilities # for now, hard code weekly rotation every sunday, and 52 weeks kept # idea: make this configurable? - init_log(debug, syslog, logthreshold, logfile, self.log_format, + init_log(self.debugmode, syslog, logthreshold, logfile, self.log_format, rotation_parameters={'when': 'W6', # every sunday 'interval': 1, - 'backupCount': 52, - }) + 'backupCount': 52,}) else: - init_log(debug, syslog, logthreshold, logfile, self.log_format) + init_log(self.debugmode, syslog, logthreshold, logfile, self.log_format) # configure simpleTal logger logging.getLogger('simpleTAL').setLevel(logging.ERROR) @@ -815,12 +812,12 @@ return mdir @classmethod - def config_for(cls, appid, config=None): + def config_for(cls, appid, config=None, debugmode=False): """return a configuration instance for the given instance identifier """ config = config or guess_configuration(cls.instance_home(appid)) configcls = configuration_cls(config) - return configcls(appid) + return configcls(appid, debugmode) @classmethod def possible_configurations(cls, appid): @@ -888,9 +885,9 @@ # instance methods used to get instance specific resources ############# - def __init__(self, appid): + def __init__(self, appid, debugmode=False): self.appid = appid - CubicWebNoAppConfiguration.__init__(self) + CubicWebNoAppConfiguration.__init__(self, debugmode) self._cubes = None self._site_loaded = set() self.load_file_configuration(self.main_config_file()) @@ -1003,14 +1000,14 @@ super(CubicWebConfiguration, self).load_configuration() if self.apphome and self.set_language: # init gettext - self._set_language() + self._gettext_init() - def init_log(self, logthreshold=None, debug=False, force=False): + def init_log(self, logthreshold=None, force=False): """init the log service""" if not force and hasattr(self, '_logging_initialized'): return self._logging_initialized = True - CubicWebNoAppConfiguration.init_log(self, logthreshold, debug, + CubicWebNoAppConfiguration.init_log(self, logthreshold, logfile=self.get('log-file')) # read a config file if it exists logconfig = join(self.apphome, 'logging.conf') @@ -1031,7 +1028,7 @@ if lang != 'en': yield lang - def _set_language(self): + def _gettext_init(self): """set language for gettext""" from gettext import translation path = join(self.apphome, 'i18n') diff -r 6de8437b06bd -r ba2347050144 cwctl.py --- a/cwctl.py Wed Jun 09 09:41:36 2010 +0200 +++ b/cwctl.py Wed Jun 09 09:42:52 2010 +0200 @@ -477,14 +477,13 @@ def start_instance(self, appid): """start the instance's server""" - debug = self['debug'] force = self['force'] loglevel = self['loglevel'] - config = cwcfg.config_for(appid) + config = cwcfg.config_for(appid, debugmode=self['debug']) if loglevel is not None: loglevel = 'LOG_%s' % loglevel.upper() config.global_set_option('log-threshold', loglevel) - config.init_log(loglevel, debug=debug, force=True) + config.init_log(loglevel, force=True) if self['profile']: config.global_set_option('profile', self.config.profile) helper = self.config_helper(config, cmdname='start') @@ -493,7 +492,7 @@ msg = "%s seems to be running. Remove %s by hand if necessary or use \ the --force option." raise ExecutionError(msg % (appid, pidf)) - helper.start_server(config, debug) + helper.start_server(config) class StopInstanceCommand(InstanceCommand): @@ -781,11 +780,15 @@ repository internals (session, etc...) so most migration commands won't be available. + Arguments after bare "--" string will not be processed by the shell command + You can use it to pass extra arguments to your script and expect for + them in '__args__' afterwards. + the identifier of the instance to connect. """ name = 'shell' - arguments = ' [batch command file]' + arguments = ' [batch command file(s)] [-- * - *================================================== + * */ if (typeof SimileAjax == "undefined") { @@ -213,9 +213,9 @@ SimileAjax.loaded = true; })(); } -/*================================================== +/* * Platform Utility Functions and Constants - *================================================== + * */ /* This must be called after our jQuery has been loaded @@ -319,9 +319,10 @@ SimileAjax.Platform.getDefaultLocale = function() { return SimileAjax.Platform.clientLocale; -};/*================================================== +}; +/* * Debug Utility Functions - *================================================== + * */ SimileAjax.Debug = { @@ -678,9 +679,9 @@ } }; })(); -/*================================================== +/* * DOM Utility Functions - *================================================== + * */ SimileAjax.DOM = new Object(); @@ -1040,9 +1041,9 @@ SimileAjax.includeCssFile(document, SimileAjax.urlPrefix + "styles/graphics-ie6.css"); } -/*================================================== +/* * Opacity, translucency - *================================================== + * */ SimileAjax.Graphics._createTranslucentImage1 = function(url, verticalAlign) { var elmt = document.createElement("img"); @@ -1119,9 +1120,9 @@ } }; -/*================================================== +/* * Bubble - *================================================== + * */ SimileAjax.Graphics.bubbleConfig = { @@ -1479,9 +1480,9 @@ }; }; -/*================================================== +/* * Animation - *================================================== + * */ /** @@ -1549,11 +1550,11 @@ } }; -/*================================================== +/* * CopyPasteButton * * Adapted from http://spaces.live.com/editorial/rayozzie/demo/liveclip/liveclipsample/techPreview.html. - *================================================== + * */ /** @@ -1606,9 +1607,9 @@ return div; }; -/*================================================== +/* * getWidthHeight - *================================================== + * */ SimileAjax.Graphics.getWidthHeight = function(el) { // RETURNS hash {width: w, height: h} in pixels @@ -1633,9 +1634,9 @@ }; -/*================================================== +/* * FontRenderingContext - *================================================== + * */ SimileAjax.Graphics.getFontRenderingContext = function(elmt, width) { return new SimileAjax.Graphics._FontRenderingContext(elmt, width); @@ -2127,9 +2128,9 @@ var d = new Date().getTimezoneOffset(); return d / -60; }; -/*================================================== +/* * String Utility Functions and Constants - *================================================== + * */ String.prototype.trim = function() { @@ -2170,9 +2171,9 @@ } return result; }; -/*================================================== +/* * HTML Utility Functions - *================================================== + * */ SimileAjax.HTML = new Object(); @@ -2655,9 +2656,9 @@ return (this._a.length > 0) ? this._a[this._a.length - 1] : null; }; -/*================================================== +/* * Event Index - *================================================== + * */ SimileAjax.EventIndex = function(unit) { @@ -2889,9 +2890,9 @@ return this._index < this._events.length() ? this._events.elementAt(this._index++) : null; } -};/*================================================== +};/* * Default Unit - *================================================== + * */ SimileAjax.NativeDateUnit = new Object(); @@ -2953,9 +2954,9 @@ return new Date(v.getTime() + n); }; -/*================================================== +/* * General, miscellaneous SimileAjax stuff - *================================================== + * */ SimileAjax.ListenerQueue = function(wildcardHandlerName) { @@ -2998,7 +2999,7 @@ } }; -/*====================================================================== +/* * History * * This is a singleton that keeps track of undoable user actions and @@ -3020,7 +3021,7 @@ * * An iframe is inserted into the document's body element to track * onload events. - *====================================================================== + * */ SimileAjax.History = { @@ -3632,7 +3633,7 @@ } return elmt; }; -/*================================================== +/* * Timeline API * * This file will load all the Javascript files @@ -3696,7 +3697,7 @@ * Note that the Ajax version is usually NOT the same as the Timeline version. * See variable simile_ajax_ver below for the current version * - *================================================== + * */ (function() { @@ -3928,7 +3929,7 @@ loadMe(); } })(); -/*================================================= +/* * * Coding standards: * @@ -3950,14 +3951,14 @@ * We also want to use jslint: http://www.jslint.com/ * * - *================================================== + * */ -/*================================================== +/* * Timeline VERSION - *================================================== + * */ // Note: version is also stored in the build.xml file Timeline.version = 'pre 2.4.0'; // use format 'pre 1.2.3' for trunk versions @@ -3965,9 +3966,9 @@ Timeline.display_version = Timeline.version + ' (with Ajax lib ' + Timeline.ajax_lib_version + ')'; // cf method Timeline.writeVersion -/*================================================== +/* * Timeline - *================================================== + * */ Timeline.strings = {}; // localization string tables Timeline.HORIZONTAL = 0; @@ -4183,9 +4184,9 @@ -/*================================================== +/* * Timeline Implementation object - *================================================== + * */ Timeline._Impl = function(elmt, bandInfos, orientation, unit, timelineID) { SimileAjax.WindowManager.initialize(); @@ -4585,7 +4586,7 @@ this.paint(); }; -/*================================================= +/* * * Coding standards: * @@ -4607,14 +4608,14 @@ * We also want to use jslint: http://www.jslint.com/ * * - *================================================== + * */ -/*================================================== +/* * Band - *================================================== + * */ Timeline._Band = function(timeline, bandInfo, index) { // hack for easier subclassing @@ -5344,9 +5345,9 @@ Timeline._Band.prototype.closeBubble = function() { SimileAjax.WindowManager.cancelPopups(); }; -/*================================================== +/* * Classic Theme - *================================================== + * */ @@ -5523,14 +5524,14 @@ }; this.mouseWheel = 'scroll'; // 'default', 'zoom', 'scroll' -};/*================================================== +};/* * An "ether" is a object that maps date/time to pixel coordinates. - *================================================== + * */ -/*================================================== +/* * Linear Ether - *================================================== + * */ Timeline.LinearEther = function(params) { @@ -5601,9 +5602,9 @@ }; -/*================================================== +/* * Hot Zone Ether - *================================================== + * */ Timeline.HotZoneEther = function(params) { @@ -5828,9 +5829,9 @@ Timeline.HotZoneEther.prototype._getScale = function() { return this._interval / this._pixelsPerInterval; }; -/*================================================== +/* * Gregorian Ether Painter - *================================================== + * */ Timeline.GregorianEtherPainter = function(params) { @@ -5919,9 +5920,9 @@ }; -/*================================================== +/* * Hot Zone Gregorian Ether Painter - *================================================== + * */ Timeline.HotZoneGregorianEtherPainter = function(params) { @@ -6080,9 +6081,9 @@ } }; -/*================================================== +/* * Year Count Ether Painter - *================================================== + * */ Timeline.YearCountEtherPainter = function(params) { @@ -6169,9 +6170,9 @@ Timeline.YearCountEtherPainter.prototype.softPaint = function() { }; -/*================================================== +/* * Quarterly Ether Painter - *================================================== + * */ Timeline.QuarterlyEtherPainter = function(params) { @@ -6257,9 +6258,9 @@ Timeline.QuarterlyEtherPainter.prototype.softPaint = function() { }; -/*================================================== +/* * Ether Interval Marker Layout - *================================================== + * */ Timeline.EtherIntervalMarkerLayout = function(timeline, band, theme, align, showLine) { @@ -6363,9 +6364,9 @@ }; }; -/*================================================== +/* * Ether Highlight Layout - *================================================== + * */ Timeline.EtherHighlight = function(timeline, band, theme, backgroundLayer) { @@ -6404,9 +6405,9 @@ } } }; -/*================================================== +/* * Event Utils - *================================================== + * */ Timeline.EventUtils = {}; @@ -6421,7 +6422,7 @@ }; Timeline.EventUtils.decodeEventElID = function(elementID) { - /*================================================== + /* * * Use this function to decode an event element's id on a band (label div, * tape div or icon img). @@ -6447,7 +6448,7 @@ * by using Timeline.getTimeline, Timeline.getBand, or * Timeline.getEvent and passing in the element's id * - *================================================== + * */ var parts = elementID.split('-'); @@ -6467,9 +6468,9 @@ // elType should be one of {label | icon | tapeN | highlightN} return elType + "-tl-" + timeline.timelineID + "-" + band.getIndex() + "-" + evt.getID(); -};/*================================================== +};/* * Gregorian Date Labeller - *================================================== + * */ Timeline.GregorianDateLabeller = function(locale, timeZone) { @@ -6558,9 +6559,9 @@ return { text: text, emphasized: emphasized }; } -/*================================================== +/* * Default Event Source - *================================================== + * */ @@ -7125,12 +7126,12 @@ }; -/*================================================== +/* * Original Event Painter - *================================================== + * */ -/*================================================== +/* * * To enable a single event listener to monitor everything * on a Timeline, we need a way to map from an event's icon, @@ -7152,7 +7153,7 @@ * You can then retrieve the band/timeline objects and event object * by using Timeline.EventUtils.decodeEventElID * - *================================================== + * */ /* @@ -7818,9 +7819,9 @@ this._eventPaintListeners[i](this._band, op, evt, els); } }; -/*================================================== +/* * Detailed Event Painter - *================================================== + * */ // Note: a number of features from original-painter @@ -8509,9 +8510,9 @@ this._onSelectListeners[i](eventID); } }; -/*================================================== +/* * Overview Event Painter - *================================================== + * */ Timeline.OverviewEventPainter = function(params) { @@ -8767,9 +8768,9 @@ Timeline.OverviewEventPainter.prototype.showBubble = function(evt) { // not implemented }; -/*================================================== +/* * Compact Event Painter - *================================================== + * */ Timeline.CompactEventPainter = function(params) { @@ -9831,9 +9832,9 @@ this._onSelectListeners[i](eventIDs); } }; -/*================================================== +/* * Span Highlight Decorator - *================================================== + * */ Timeline.SpanHighlightDecorator = function(params) { @@ -9948,9 +9949,9 @@ Timeline.SpanHighlightDecorator.prototype.softPaint = function() { }; -/*================================================== +/* * Point Highlight Decorator - *================================================== + * */ Timeline.PointHighlightDecorator = function(params) { @@ -10015,9 +10016,9 @@ Timeline.PointHighlightDecorator.prototype.softPaint = function() { }; -/*================================================== +/* * Default Unit - *================================================== + * */ Timeline.NativeDateUnit = new Object(); @@ -10083,35 +10084,35 @@ return new Date(v.getTime() + n); }; -/*================================================== +/* * Common localization strings - *================================================== + * */ Timeline.strings["fr"] = { wikiLinkLabel: "Discute" }; -/*================================================== +/* * Localization of labellers.js - *================================================== + * */ Timeline.GregorianDateLabeller.monthNames["fr"] = [ "jan", "fev", "mar", "avr", "mai", "jui", "jui", "aou", "sep", "oct", "nov", "dec" ]; -/*================================================== +/* * Common localization strings - *================================================== + * */ Timeline.strings["en"] = { wikiLinkLabel: "Discuss" }; -/*================================================== +/* * Localization of labellers.js - *================================================== + * */ Timeline.GregorianDateLabeller.monthNames["en"] = [ diff -r 6de8437b06bd -r ba2347050144 web/data/cubicweb.timeline-ext.js --- a/web/data/cubicweb.timeline-ext.js Wed Jun 09 09:41:36 2010 +0200 +++ b/web/data/cubicweb.timeline-ext.js Wed Jun 09 09:42:52 2010 +0200 @@ -1,49 +1,49 @@ -/* +/** * :organization: Logilab - * :copyright: 2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved. + * :copyright: 2008-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved. * :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr * */ - -/* provide our own custom date parser since the default +/** + * provide our own custom date parser since the default * one only understands iso8601 and gregorian dates */ SimileAjax.NativeDateUnit.getParser = Timeline.NativeDateUnit.getParser = function(format) { if (typeof format == "string") { - if (format.indexOf('%') != -1) { - return function(datestring) { - if (datestring) { - return strptime(datestring, format); - } - return null; - }; - } + if (format.indexOf('%') != - 1) { + return function(datestring) { + if (datestring) { + return strptime(datestring, format); + } + return null; + }; + } format = format.toLowerCase(); } if (format == "iso8601" || format == "iso 8601") { - return Timeline.DateTime.parseIso8601DateTime; + return Timeline.DateTime.parseIso8601DateTime; } return Timeline.DateTime.parseGregorianDateTime; }; /*** CUBICWEB EVENT PAINTER *****************************************************/ Timeline.CubicWebEventPainter = function(params) { -// Timeline.OriginalEventPainter.apply(this, arguments); - this._params = params; - this._onSelectListeners = []; + // Timeline.OriginalEventPainter.apply(this, arguments); + this._params = params; + this._onSelectListeners = []; - this._filterMatcher = null; - this._highlightMatcher = null; - this._frc = null; + this._filterMatcher = null; + this._highlightMatcher = null; + this._frc = null; - this._eventIdToElmt = {}; + this._eventIdToElmt = {}; }; Timeline.CubicWebEventPainter.prototype = new Timeline.OriginalEventPainter(); Timeline.CubicWebEventPainter.prototype._paintEventLabel = function( - evt, text, left, top, width, height, theme) { +evt, text, left, top, width, height, theme) { var doc = this._timeline.getDocument(); var labelDiv = doc.createElement("div"); @@ -54,15 +54,21 @@ labelDiv.style.top = top + "px"; if (evt._obj.onclick) { - labelDiv.appendChild(A({'href': evt._obj.onclick}, text)); + labelDiv.appendChild(A({ + 'href': evt._obj.onclick + }, + text)); } else if (evt._obj.image) { - labelDiv.appendChild(IMG({src: evt._obj.image, width: '30px', height: '30px'})); + labelDiv.appendChild(IMG({ + src: evt._obj.image, + width: '30px', + height: '30px' + })); } else { - labelDiv.innerHTML = text; + labelDiv.innerHTML = text; } - if(evt._title != null) - labelDiv.title = evt._title; + if (evt._title != null) labelDiv.title = evt._title; var color = evt.getTextColor(); if (color == null) { @@ -72,29 +78,31 @@ labelDiv.style.color = color; } var classname = evt.getClassName(); - if(classname) labelDiv.className +=' ' + classname; + if (classname) labelDiv.className += ' ' + classname; this._eventLayer.appendChild(labelDiv); return { - left: left, - top: top, - width: width, + left: left, + top: top, + width: width, height: height, - elmt: labelDiv + elmt: labelDiv }; }; +Timeline.CubicWebEventPainter.prototype._showBubble = function(x, y, evt) { + var div = DIV({ + id: 'xxx' + }); + var width = this._params.theme.event.bubble.width; + if (!evt._obj.bubbleUrl) { + evt.fillInfoBubble(div, this._params.theme, this._band.getLabeller()); + } + SimileAjax.WindowManager.cancelPopups(); + SimileAjax.Graphics.createBubbleForContentAndPoint(div, x, y, width); + if (evt._obj.bubbleUrl) { + jQuery('#xxx').loadxhtml(evt._obj.bubbleUrl, null, 'post', 'replace'); + } +}; -Timeline.CubicWebEventPainter.prototype._showBubble = function(x, y, evt) { - var div = DIV({id: 'xxx'}); - var width = this._params.theme.event.bubble.width; - if (!evt._obj.bubbleUrl) { - evt.fillInfoBubble(div, this._params.theme, this._band.getLabeller()); - } - SimileAjax.WindowManager.cancelPopups(); - SimileAjax.Graphics.createBubbleForContentAndPoint(div, x, y, width); - if (evt._obj.bubbleUrl) { - jQuery('#xxx').loadxhtml(evt._obj.bubbleUrl, null, 'post', 'replace'); - } -}; diff -r 6de8437b06bd -r ba2347050144 web/data/cubicweb.widgets.js --- a/web/data/cubicweb.widgets.js Wed Jun 09 09:41:36 2010 +0200 +++ b/web/data/cubicweb.widgets.js Wed Jun 09 09:42:52 2010 +0200 @@ -1,6 +1,8 @@ -/* +/** + * Functions dedicated to widgets. + * * :organization: Logilab - * :copyright: 2003-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved. + * :copyright: 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved. * :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr * * @@ -9,144 +11,175 @@ // widget namespace Widgets = {}; - -/* this function takes a DOM node defining a widget and +/** + * .. function:: buildWidget(wdgnode) + * + * this function takes a DOM node defining a widget and * instantiates / builds the appropriate widget class */ function buildWidget(wdgnode) { var wdgclass = Widgets[wdgnode.getAttribute('cubicweb:wdgtype')]; if (wdgclass) { - var wdg = new wdgclass(wdgnode); + var wdg = new wdgclass(wdgnode); } } -/* This function is called on load and is in charge to build +/** + * .. function:: buildWidgets(root) + * + * This function is called on load and is in charge to build * JS widgets according to DOM nodes found in the page */ function buildWidgets(root) { root = root || document; jQuery(root).find('.widget').each(function() { - if (this.getAttribute('cubicweb:loadtype') == 'auto') { - buildWidget(this); - } + if (this.getAttribute('cubicweb:loadtype') == 'auto') { + buildWidget(this); + } }); } - // we need to differenciate cases where initFacetBoxEvents is called // with one argument or without any argument. If we use `initFacetBoxEvents` // as the direct callback on the jQuery.ready event, jQuery will pass some argument // of his, so we use this small anonymous function instead. -jQuery(document).ready(function() {buildWidgets();}); +jQuery(document).ready(function() { + buildWidgets(); +}); +function postJSON(url, data, callback) { + return jQuery.post(url, data, callback, 'json'); +} + +function getJSON(url, data, callback) { + return jQuery.get(url, data, callback, 'json'); +} Widgets.SuggestField = defclass('SuggestField', null, { __init__: function(node, options) { - var multi = node.getAttribute('cubicweb:multi') || "no"; - options = options || {}; - options.multiple = (multi == "yes") ? true : false; - var dataurl = node.getAttribute('cubicweb:dataurl'); + var multi = node.getAttribute('cubicweb:multi') || "no"; + options = options || {}; + options.multiple = (multi == "yes") ? true: false; + var dataurl = node.getAttribute('cubicweb:dataurl'); var method = postJSON; - if (options.method == 'get'){ - method = function(url, data, callback) { - // We can't rely on jQuery.getJSON because the server - // might set the Content-Type's response header to 'text/plain' - jQuery.get(url, data, function(response) { - callback(evalJSON(response)); - }); - }; - } - var self = this; // closure - method(dataurl, null, function(data) { - // in case we received a list of couple, we assume that the first - // element is the real value to be sent, and the second one is the - // value to be displayed - if (data.length && data[0].length == 2) { - options.formatItem = function(row) { return row[1]; }; - self.hideRealValue(node); - self.setCurrentValue(node, data); - } - jQuery(node).autocomplete(data, options); - }); + if (options.method == 'get') { + method = function(url, data, callback) { + // We can't rely on jQuery.getJSON because the server + // might set the Content-Type's response header to 'text/plain' + jQuery.get(url, data, function(response) { + callback(cw.evalJSON(response)); + }); + }; + } + var self = this; // closure + method(dataurl, null, function(data) { + // in case we received a list of couple, we assume that the first + // element is the real value to be sent, and the second one is the + // value to be displayed + if (data.length && data[0].length == 2) { + options.formatItem = function(row) { + return row[1]; + }; + self.hideRealValue(node); + self.setCurrentValue(node, data); + } + jQuery(node).autocomplete(data, options); + }); }, hideRealValue: function(node) { - var hidden = INPUT({'type': "hidden", 'name': node.name, 'value': node.value}); - node.parentNode.appendChild(hidden); - // remove 'name' attribute from visible input so that it is not submitted - // and set correct value in the corresponding hidden field - jQuery(node).removeAttr('name').bind('result', function(_, row, _) { - hidden.value = row[0]; - }); + var hidden = INPUT({ + 'type': "hidden", + 'name': node.name, + 'value': node.value + }); + node.parentNode.appendChild(hidden); + // remove 'name' attribute from visible input so that it is not submitted + // and set correct value in the corresponding hidden field + jQuery(node).removeAttr('name').bind('result', function(_, row, _) { + hidden.value = row[0]; + }); }, setCurrentValue: function(node, data) { - // called when the data is loaded to reset the correct displayed - // value in the visible input field (typically replacing an eid - // by a displayable value) - var curvalue = node.value; - if (!node.value) { - return; - } - for (var i=0,length=data.length; i