Commits

Ralph Bean committed 558318f Merge

Merge branch 'release/0.0.3'

Comments (0)

Files changed (6)

 Links
 -----
 
-You can `get the source from github <http://github.com/ralphbean/tw2.d3>`_,
+You can `get the source from github <http://github.com/toscawidgets/tw2.d3>`_,
 check out `the PyPI page <http://pypi.python.org/pypi/tw2.d3>`_, and
-report or look into `bugs <http://github.com/ralphbean/tw2.d3/issues/>`_.
+report or look into `bugs <http://github.com/toscawidgets/tw2.d3/issues/>`_.
 
 Description
 -----------
 
 This module, tw2.d3, provides `toscawidgets2 (tw2)`_ widgets that render `d3`_ data visualizations.
 
-
 Sampling tw2.d3 in the WidgetBrowser
 ------------------------------------
 
 ``tw2.devtools`` WidgetBrowser.  To see the source code that configures them,
 check out ``tw2.d3/tw2/d3/samples.py``
 
-To give it a try you'll need git, mercurial, python, and virtualenv.  Run::
+To give it a try you'll need git, python, and `virtualenvwrapper
+<http://pypi.python.org/pypi/virtualenvwrapper>`_.  Run::
 
-    $ git clone git://github.com/ralphbean/tw2.d3.git
+    $ git clone git://github.com/toscawidgets/tw2.d3.git
     $ cd tw2.d3
     $ mkvirtualenv tw2.d3
     (tw2.d3) $ pip install tw2.devtools
     (tw2.d3) $ paster tw2.browser
 
 ...and browse to http://localhost:8000/ to check it out.
-
-
-
 
 setup(
     name='tw2.d3',
-    version='0.0.2a1',
+    version='0.0.3',
     description='toscawidgets2 wrapper for d3 (data-driven documents)',
     long_description=long_description,
     author='Ralph Bean',
     author_email='rbean@redhat.com',
-    url='http://github.com/ralphbean/tw2.d3',
+    url='http://github.com/toscawidgets/tw2.d3',
     install_requires=[
         "tw2.core",
         "tw2.jquery",
         'toscawidgets.widgets',
     ],
     classifiers = [
-        'Development Status :: 3 - Alpha',
+        'Development Status :: 3 - Beta',
         'Environment :: Web Environment',
         'Environment :: Web Environment :: ToscaWidgets',
         'Topic :: Software Development :: Libraries :: Python Modules',

tw2/d3/__init__.py

 """
 A bunch of cool widgets built on d3
 
-Get this source from http://github.com/ralphbean/tw2.d3
+Get this source from http://github.com/toscawidgets/tw2.d3
 
 d3 itself can be found here:  http://mbostock.github.com/d3/
 """

tw2/d3/samples.py

 WidgetBrowser.
 """
 
+import tw2.core as twc
+
 from widgets import (
     BarChart,
 )
     width = 450
     height = 120
 
+    # Top, Right, Bottom, Left
     padding = [30, 10, 10, 90]
 
+    # The redraw interval (in milliseconds).
+    interval = 1000
+
     data = collections.OrderedDict(
         oranges=42,
         kiwis=102,
         apples=21,
         bananas=63,
     )
+
+    # This only gets called just before the widget is displayed
+    def prepare(self):
+        super(DemoBarChart, self).prepare()
+        # Register a javascript call to a utility function that tw2.d3 provides.
+        # This one indicates that every element in the data should decay by a
+        # certain halflife (2000ms), that function should be run every 1000ms,
+        # and elements should just be removed if their value goes below a
+        # certain epsilon (0.001)
+        self.add_call(twc.js_function('tw2.d3.bar.schedule_halflife')(
+            self.attrs['id'],
+            2000,
+            1000,
+            0.001,
+        ))
+        # This registers another javascript callback that is just nice for
+        # testing.  It schedules a callback that runs every 100 milliseconds
+        # which adds random noise to the data elements.
+        self.add_call(twc.js_function('tw2.d3.util.schedule_bump_random')(
+            self.attrs['id'],
+            100
+        ))

tw2/d3/static/ext/bar.js

         filter: function(data) {
             // Generic utility.  Remove elements with 0 value from the list.
             // Equivalent to the following python:
-            //     >>> data = [d for d in data if d.value > 0]
+            //     >>> data = [d for d in data if d.value > epsilon]
+            if (typeof epsilon === 'undefined') { epsilon = 0.001; }
             for (var i = 0; i < data.length; i++) {
-                if (data[i].value <= 0) {
+                if (data[i].value <= epsilon) {
                     data.splice(i, 1);
                 }
             }
             return data;
         },
+        schedule_bump_random: function(selector, interval) {
+            // Schedule randomly bump data points for `selector`
+            setInterval(function() {
+                for (var i = 0; i < tw2.store[selector].data.length; i++) {
+                    tw2.store[selector].data[i].value += Math.random() * 3;
+                }
+            }, interval);
+        }
     },
+
     bar: {
-        init: function (selector, data, width, height, padding) {
+        init: function (selector, data, width, height, padding, interval) {
             $(document).ready(function() {
-                tw2.d3.bar._init(selector, data, width, height, padding);
+                tw2.d3.bar._init(selector, data, width, height, padding, interval);
             });
         },
-        _init: function (selector, data, width, height, padding) {
+        _init: function (selector, data, width, height, padding, interval) {
             var w = width - padding[1] - padding[3];
             var h = height - padding[0] - padding[2];
 
                 width: width,
                 height: height,
                 padding: padding,
+                interval: interval,
             };
 
             svg.append("g").attr("class", "x axis")
             svg.append("g").attr("class", "y axis")
 
-            tw2.d3.bar.redraw(selector)
-            setInterval(function() { tw2.d3.bar.redraw(selector)}, 1000);
+            tw2.d3.bar.redraw(selector, 'cubic-in-out')
+            if (interval > 0) {
+                setInterval(function() {tw2.d3.bar.redraw(selector)}, interval);
+            }
         },
-        redraw: function(selector) {
-            tw2.store[selector].data[0].value -= 15;
-            tw2.store[selector].data = tw2.d3.util.filter(
-                tw2.store[selector].data
-            );
+        redraw: function(selector, easing) {
+            if (typeof easing === 'undefined') { easing = 'linear'; }
+
             var data = tw2.store[selector].data;
+            var interval = tw2.store[selector].interval;
 
             var w =
             tw2.store[selector].width - 
 
             bar.exit().remove();
 
-            bar.transition().duration(750).attr("transform", function(d) {
+            bar.transition().duration(interval).attr("transform", function(d) {
                 return "translate(0," + y(d.key) + ")";
             });
 
             bar.selectAll("rect")
             .data(data, function(d) { return d.key })
             .attr("height", y.rangeBand())
-            .transition()
+            .transition().ease(easing).duration(interval)
             .attr("width", function(d) { return x(d.value); });
 
             tw2.store[selector].svg.selectAll("g.x")
-            .transition().duration(750).call(xAxis);
+            .transition().ease(easing).duration(interval).call(xAxis);
             tw2.store[selector].svg.selectAll("g.y")
-            .transition().duration(750).call(yAxis);
+            .transition().ease(easing).duration(interval).call(yAxis);
+        },
+        decay_amount: function(selector, amount, epsilon) {
+            for (var i = 0; i < tw2.store[selector].data.length; i++) {
+                tw2.store[selector].data[i].value -= amount;
+            }
+            tw2.store[selector].data = tw2.d3.util.filter(
+                tw2.store[selector].data,
+                epsilon
+            );
+        },
+        schedule_halflife: function(selector, halflife, interval, epsilon) {
+            setInterval(function() {
+                // halflife means 'In this many milliseconds, the value should
+                // be half of what it was.'
+                var factor = 2 * halflife / interval;
+                var amount;
+                for (var i = 0; i < tw2.store[selector].data.length; i++) {
+                    amount = tw2.store[selector].data[i].value / factor;
+                    tw2.store[selector].data[i].value -= amount;
+                }
+                tw2.store[selector].data = tw2.d3.util.filter(
+                    tw2.store[selector].data,
+                    epsilon
+                );
+            }, interval);
         },
     },
 });

tw2/d3/widgets.py

     padding = twc.Param("A list of ints [top, right, bottom, left]",
                         default=[30, 10, 10, 30])
 
+    interval = twc.Param("Redraw-interval in milliseconds.", default=0)
+
     def prepare(self):
 
         # Check the types of everything
         int(self.width)
         int(self.height)
+        int(self.interval)
         self.padding = [int(ele) for ele in self.padding]
 
         if self.data == None:
             self.width,
             self.height,
             self.padding,
+            self.interval,
         ))