Ñò ʹJc@sÜdZddkZddkZddklZddkZddkZdddgZei e ƒZ dei i fd„ƒYZdefd „ƒYZdefd „ƒYZdefd „ƒYZd efd „ƒYZdS(s³ Python-JS interface to dynamically create JS function calls from your widgets. This module 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. iÿÿÿÿN(timapt js_callbackt js_functiont js_symbolt TWEncodercBs;eZdZd„Zd„Zd„Zd„Zd„ZRS(sŽ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 tw.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)}}} Technical note: simplejson does not support arbitrary js injection, which is needed in this module. We work around this by inserting distinct tokens into the JSON encoding stream that can later be replaced with the objects' js representations. cOstt|ƒi||ŽdS(N(tsuperRt__init__(tselftargstkw((s./usr/lib/python2.6/site-packages/tw/core/js.pyR-scCsRt|dƒo|i|ƒSt|dƒot|iƒStt|ƒi|ƒS(Nt get_js_reprt_id(thasattrtmark_for_escapetstrtidRRtdefault(Rtobj((s./usr/lib/python2.6/site-packages/tw/core/js.pyR0s cCs=h|_tt|ƒi|ƒ}|i|ƒ}h|_|S(N(tunescape_symbolsRRtencodetunescape_marked(RRtencodedt unescaped((s./usr/lib/python2.6/site-packages/tw/core/js.pyR7s   cCs'||it|ƒscs.tidƒ}‡fd†}|i||ƒS(Ns"TWEncoder_unescape_([0-9]*)"csHy0t|idƒƒ}ˆi|}|iƒSWn|idƒSXdS(Nii(tinttgroupRR (tmatchtobj_idR(R(s./usr/lib/python2.6/site-packages/tw/core/js.pytunescapeDs  (tretcompiletsub(RRtunescape_patternR((Rs./usr/lib/python2.6/site-packages/tw/core/js.pyRBs(t__name__t __module__t__doc__RRRR R(((s./usr/lib/python2.6/site-packages/tw/core/js.pyRs     cBs#eZd„Zd„Zd„ZRS(cCs ||_dS(N(t_name(Rtname((s./usr/lib/python2.6/site-packages/tw/core/js.pyROscCs t|iƒS(N(RR$(R((s./usr/lib/python2.6/site-packages/tw/core/js.pyR QscCs |iƒS(N(R (R((s./usr/lib/python2.6/site-packages/tw/core/js.pyt__str__Ss(R!R"RR R&(((s./usr/lib/python2.6/site-packages/tw/core/js.pyRNs  cBs2eZdZd„Zd„Zd„Zd„ZRS(s²A js function that can be passed as a callback to be called by another JS function Examples: .. sourcecode:: python >>> 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)})}) cGsrt|tƒo ||_nRt|tƒod||Œ|_n+t|tƒod||_n d|_dS(Nsfunction(){%s}t(t isinstancet basestringtcbRt_js_call(RR*R((s./usr/lib/python2.6/site-packages/tw/core/js.pyRxs cGstdƒ‚dS(Ns*A js_callback cannot be called from Python(t TypeError(RR((s./usr/lib/python2.6/site-packages/tw/core/js.pyt__call__‚scCs|iS(N(R*(R((s./usr/lib/python2.6/site-packages/tw/core/js.pyR …scCs |iƒS(N(R (R((s./usr/lib/python2.6/site-packages/tw/core/js.pyR&ˆs(R!R"R#RR-R R&(((s./usr/lib/python2.6/site-packages/tw/core/js.pyRVs !  cBs2eZdZd„Zd„Zd„Zd„ZRS(s A JS function that can be "called" from python and 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:: .. sourcecode:: python >>> 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. .. sourcecode:: python >>> from tw.api import Widget >>> class SomeWidget(Widget): ... params = ["pickerOptions"] ... pickerOptions = {} ... def __init__(self, *args, **kw): ... super(SomeWidget, self).__init__(*args, **kw) ... self.add_call( ... jQuery('#%s' % self.id).datePicker(self.pickerOptions) ... ) If we want to dynamically make calls on every request, we ca also add_calls inside the ``update_params`` method. .. sourcecode:: python >>> class SomeWidget(Widget): ... params = ["pickerOptions"] ... pickerOptions = {} ... def update_params(self, d): ... super(SomeWidget, self).update_params(d) ... 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: .. sourcecode:: python >>> 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()' cCs ||_dS(N(t_js_function__name(RR%((s./usr/lib/python2.6/site-packages/tw/core/js.pyRÑscGst|ig|dtƒS(Ntcalled(R+R.tTrue(RR((s./usr/lib/python2.6/site-packages/tw/core/js.pyR-ÔscCs t|iƒS(N(RR.(R((s./usr/lib/python2.6/site-packages/tw/core/js.pyR ×scCs |iƒS(N(R (R((s./usr/lib/python2.6/site-packages/tw/core/js.pyR&Ús(R!R"R#RR-R R&(((s./usr/lib/python2.6/site-packages/tw/core/js.pyR‹s E   R+cBsSeZd Zd ed„Zd„Zd„Zd„Zd„Z d „Z d „Z RS( t__namet __call_listt__argst__calledcCs9||_||_||_|ii|ƒ||_dS(N(t_js_call__namet_js_call__argst_js_call__call_listtappendt_js_call__called(RR%t call_listRR/((s./usr/lib/python2.6/site-packages/tw/core/js.pyRás    cCs|i||iƒS(N(t __class__R7(RR%((s./usr/lib/python2.6/site-packages/tw/core/js.pyt __getattr__èscGs||_t|_|S(N(R6R0R9(RR((s./usr/lib/python2.6/site-packages/tw/core/js.pyR-ës  cs)tƒ‰di‡fd†|iDƒƒS(Nt.c3s"x|]}|iˆƒVqWdS(N(t_js_call__get_js_repr_fragment(t.0tc(tencoder(s./usr/lib/python2.6/site-packages/tw/core/js.pys òs (RtjoinR7(R((RAs./usr/lib/python2.6/site-packages/tw/core/js.pyR ðs cCsE|io0|i}d|idit|i|ƒƒfS|iSdS(Ns%s(%s)s, (R9R6R5RBRR(RRAR((s./usr/lib/python2.6/site-packages/tw/core/js.pyt__get_js_repr_fragmentôs  'cCs$|iptdƒ‚n|iƒS(Ns*Last element in the chain has to be called(R9R,R (R((s./usr/lib/python2.6/site-packages/tw/core/js.pyR&ûs cCst|ƒitiƒƒS(N(Rtdecodetsystgetdefaultencoding(R((s./usr/lib/python2.6/site-packages/tw/core/js.pyt __unicode__s(s__names __call_lists__argss__calledN( R!R"t __slots__tNonetFalseRR<R-R R>R&RG(((s./usr/lib/python2.6/site-packages/tw/core/js.pyR+Þs     (R#REtloggingt itertoolsRRtsimplejson.encodert simplejsont__all__t getLoggerR!tlogRAt JSONEncoderRtobjectRRRR+(((s./usr/lib/python2.6/site-packages/tw/core/js.pyt s    95S