[uilib] new js_dumps function allowing usage of bare js string (wrapped into JSString)
modify magic 'js' object to consider them as well
--- a/uilib.py Wed Jun 29 16:04:01 2011 +0200
+++ b/uilib.py Wed Jun 29 16:13:09 2011 +0200
@@ -31,7 +31,7 @@
from logilab.mtconverter import xml_escape, html_unescape
from logilab.common.date import ustrftime
-from cubicweb.utils import json_dumps
+from cubicweb.utils import JSString, json_dumps
def rql_for_eid(eid):
@@ -281,16 +281,23 @@
self.args = args
self.parent = parent
def __unicode__(self):
- args = u','.join(json_dumps(arg) for arg in self.args)
+ args = []
+ for arg in self.args:
+ if isinstance(arg, JSString):
+ args.append(arg)
+ else:
+ args.append(json_dumps(arg))
if self.parent:
- return u'%s(%s)' % (self.parent, args)
- return args
+ return u'%s(%s)' % (self.parent, ','.join(args))
+ return ','.join(args)
class _JS(object):
def __getattr__(self, attr):
return _JSId(attr)
-"""magic object to return strings suitable to call some javascript function with
+js = _JS()
+js.__doc__ = """\
+magic object to return strings suitable to call some javascript function with
the given arguments (which should be correctly typed).
>>> str(js.pouet(1, "2"))
@@ -298,9 +305,10 @@
>>> str(js.cw.pouet(1, "2"))
'cw.pouet(1,"2")'
>>> str(js.cw.pouet(1, "2").pouet(None))
-'cw.pouet(1,"2").pouet(null)')
+'cw.pouet(1,"2").pouet(null)'
+>>> str(js.cw.pouet(1, JSString("$")).pouet(None))
+'cw.pouet(1,$).pouet(null)'
"""
-js = _JS()
def domid(string):
"""return a valid DOM id from a string (should also be usable in jQuery
--- a/utils.py Wed Jun 29 16:04:01 2011 +0200
+++ b/utils.py Wed Jun 29 16:13:09 2011 +0200
@@ -444,7 +444,7 @@
else:
import json
except ImportError:
- json_dumps = None
+ json_dumps = JSString = None
else:
from logilab.common.date import ustrftime
@@ -478,6 +478,40 @@
return json.dumps(value, cls=CubicWebJsonEncoder)
+ class JSString(str):
+ """use this string sub class in values given to :func:`js_dumps` to
+ insert raw javascript chain in some JSON string
+ """
+
+ def _dict2js(d, predictable=False):
+ res = [key + ': ' + js_dumps(val, predictable)
+ for key, val in d.iteritems()]
+ return '{%s}' % ', '.join(res)
+
+ def _list2js(l, predictable=False):
+ return '[%s]' % ', '.join([js_dumps(val, predictable) for val in l])
+
+ def js_dumps(something, predictable=False):
+ """similar as :func:`json_dumps`, except values which are instances of
+ :class:`JSString` are expected to be valid javascript and will be output
+ as is
+
+ >>> js_dumps({'hop': JSString('$.hop'), 'bar': None}, predictable=True)
+ '{bar: null, hop: $.hop}'
+ >>> js_dumps({'hop': '$.hop'})
+ '{hop: "$.hop"}'
+ >>> js_dumps({'hip': {'hop': JSString('momo')}})
+ '{hip: {hop: momo}}'
+ """
+ if isinstance(something, dict):
+ return _dict2js(something, predictable)
+ if isinstance(something, list):
+ return _list2js(something, predictable)
+ if isinstance(something, JSString):
+ return something
+ return json_dumps(something)
+
+
@deprecated('[3.7] merge_dicts is deprecated')
def merge_dicts(dict1, dict2):
"""update a copy of `dict1` with `dict2`"""