[uilib] new js_dumps function allowing usage of bare js string (wrapped into JSString)
authorSylvain Thénault <sylvain.thenault@logilab.fr>
Wed, 29 Jun 2011 16:13:09 +0200
changeset 7575 335f14e8e5a7
parent 7574 34154f48d255
child 7577 9892937d9041
[uilib] new js_dumps function allowing usage of bare js string (wrapped into JSString) modify magic 'js' object to consider them as well
uilib.py
utils.py
--- 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`"""