Coverage for tw2.core.js : 89%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
""" Python-JS interface to dynamically create JS function calls from your widgets.
This moudle doesn't aim to serve as a Python-JS "translator". You should code your client-side code in JavaScript and make it available in static files which you include as JSLinks or inline using JSSources. This module is only intended as a "bridge" or interface between Python and JavaScript so JS function **calls** can be generated programatically. """
"""A JSON encoder that can encode Widgets, js_calls, js_symbols and js_callbacks.
Example::
>>> encode = TWEncoder().encode >>> print encode({ ... 'onLoad': js_function("do_something")(js_symbol("this")) ... }) {"onLoad": do_something(this)}
>>> from tw2.core.api import Widget >>> w = Widget("foo") >>> args = { ... 'onLoad': js_callback( ... js_function('jQuery')(w).click(js_symbol('onClick')) ... ) ... } >>> print encode(args) {"onLoad": function(){jQuery(\\"foo\\").click(onClick)}} >>> print encode({'args':args}) {"args": {"onLoad": function(){jQuery(\\"foo\\").click(onClick)}}} """
# This makes encoded objects be prettily formatted. It is very nice # for debugging and should be made configurable at some point. # TODO -- make json encoding pretty-printing configurable #kw['indent'] = ' '
# This is required to get encoding of _js_call to work
return obj.__json__()
encoded = super(TWEncoder, self).encode(obj) return self.unescape_marked(encoded)
""" An unquoted js symbol like ``document`` or ``window`` """
raise ValueError("js_symbol must be given name or src") raise ValueError("js_symbol must not be given name and src") else:
"""A js function that can be passed as a callback to be called by another JS function
Examples:
>>> str(js_callback("update_div")) 'update_div'
>>> str(js_callback("function (event) { .... }")) 'function (event) { .... }'
Can also create callbacks for deferred js calls
>>> str(js_callback(js_function('foo')(1,2,3))) 'function(){foo(1, 2, 3)}'
Or equivalently
>>> str(js_callback(js_function('foo'), 1,2,3)) 'function(){foo(1, 2, 3)}'
A more realistic example
>>> jQuery = js_function('jQuery') >>> my_cb = js_callback('function() { alert(this.text)}') >>> on_doc_load = jQuery('#foo').bind('click', my_cb) >>> call = jQuery(js_callback(on_doc_load)) >>> print call jQuery(function(){jQuery(\\"#foo\\").bind( \\"click\\", function() { alert(this.text)})})
""" self.cb = "function(){%s}" % cb(*args) else: self.cb = ''
raise TypeError("A js_callback cannot be called from Python")
"""A JS function that can be "called" from python and added to a widget by widget.add_call() so it get's called every time the widget is rendered.
Used to create a callable object that can be called from your widgets to trigger actions in the browser. It's used primarily to initialize JS code programatically. Calls can be chained and parameters are automatically json-encoded into something JavaScript undersrtands. Example::
>>> jQuery = js_function('jQuery') >>> call = jQuery('#foo').datePicker({'option1': 'value1'}) >>> str(call) 'jQuery("#foo").datePicker({"option1": "value1"})'
Calls are added to the widget call stack with the ``add_call`` method.
If made at Widget initialization those calls will be placed in the template for every request that renders the widget.
>>> import tw2.core as twc >>> class SomeWidget(twc.Widget): ... pickerOptions = twc.Param(default={}) >>> SomeWidget.add_call( ... jQuery('#%s' % SomeWidget.id).datePicker(SomeWidget.pickerOptions) ... )
More likely, we will want to dynamically make calls on every request. Here we will call add_calls inside the ``prepare`` method.
>>> class SomeWidget(Widget): ... pickerOptions = twc.Param(default={}) ... def prepare(self): ... super(SomeWidget, self).prepare() ... self.add_call( ... jQuery('#%s' % d.id).datePicker(d.pickerOptions) ... )
This would allow to pass different options to the datePicker on every display.
JS calls are rendered by the same mechanisms that render required css and js for a widget and places those calls at bodybottom so DOM elements which we might target are available.
Examples:
>>> call = js_function('jQuery')("a .async") >>> str(call) 'jQuery("a .async")'
js_function calls can be chained:
>>> call = js_function('jQuery')("a .async").foo().bar() >>> str(call) 'jQuery("a .async").foo().bar()'
"""
self.__name, ', '.join(map(encoder.encode, args)) ) .replace('\\"', '"')\ .replace("\\'", "'")\ .replace('\\n', '\n') else: return self.__name
raise TypeError('Last element in the chain has to be called')
return str(self).decode(sys.getdefaultencoding())
|