Yurik has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/214311

Change subject: Bumped Vega, added d3.layout.cloud lib
......................................................................

Bumped Vega, added d3.layout.cloud lib

* Minor cleanups in vega lib - either node-related or syntax
* Added wordcloud lib
* Version bump of topojson lib

Bug: T100006
Change-Id: I0a1fc5420f365613cd8223205dc6ad7b90cecd10
---
M extension.json
A lib/d3.layout.cloud.js
M lib/topojson.js
M lib/vega.js
4 files changed, 465 insertions(+), 54 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/Graph 
refs/changes/11/214311/1

diff --git a/extension.json b/extension.json
index c372611..d49b42a 100644
--- a/extension.json
+++ b/extension.json
@@ -21,6 +21,7 @@
                "ext.graph": {
                        "scripts": [
                                "lib/d3.js",
+                               "lib/d3.layout.cloud.js",
                                "lib/topojson.js",
                                "lib/vega.js",
                                "js/graph.js"
diff --git a/lib/d3.layout.cloud.js b/lib/d3.layout.cloud.js
new file mode 100644
index 0000000..f035837
--- /dev/null
+++ b/lib/d3.layout.cloud.js
@@ -0,0 +1,401 @@
+// Word cloud layout by Jason Davies, http://www.jasondavies.com/word-cloud/
+// Algorithm due to Jonathan Feinberg, http://static.mrfeinberg.com/bv_ch03.pdf
+(function() {
+  function cloud() {
+    var size = [256, 256],
+        text = cloudText,
+        font = cloudFont,
+        fontSize = cloudFontSize,
+        fontStyle = cloudFontNormal,
+        fontWeight = cloudFontNormal,
+        rotate = cloudRotate,
+        padding = cloudPadding,
+        spiral = archimedeanSpiral,
+        words = [],
+        timeInterval = Infinity,
+        event = d3.dispatch("word", "end"),
+        timer = null,
+        cloud = {};
+
+    cloud.start = function() {
+      var board = zeroArray((size[0] >> 5) * size[1]),
+          bounds = null,
+          n = words.length,
+          i = -1,
+          tags = [],
+          data = words.map(function(d, i) {
+            d.text = text.call(this, d, i);
+            d.font = font.call(this, d, i);
+            d.style = fontStyle.call(this, d, i);
+            d.weight = fontWeight.call(this, d, i);
+            d.rotate = rotate.call(this, d, i);
+            d.size = ~~fontSize.call(this, d, i);
+            d.padding = padding.call(this, d, i);
+            return d;
+          }).sort(function(a, b) { return b.size - a.size; });
+
+      if (timer) clearInterval(timer);
+      timer = setInterval(step, 0);
+      step();
+
+      return cloud;
+
+      function step() {
+        var start = +new Date,
+            d;
+        while (+new Date - start < timeInterval && ++i < n && timer) {
+          d = data[i];
+          d.x = (size[0] * (Math.random() + .5)) >> 1;
+          d.y = (size[1] * (Math.random() + .5)) >> 1;
+          cloudSprite(d, data, i);
+          if (d.hasText && place(board, d, bounds)) {
+            tags.push(d);
+            event.word(d);
+            if (bounds) cloudBounds(bounds, d);
+            else bounds = [{x: d.x + d.x0, y: d.y + d.y0}, {x: d.x + d.x1, y: 
d.y + d.y1}];
+            // Temporary hack
+            d.x -= size[0] >> 1;
+            d.y -= size[1] >> 1;
+          }
+        }
+        if (i >= n) {
+          cloud.stop();
+          event.end(tags, bounds);
+        }
+      }
+    }
+
+    cloud.stop = function() {
+      if (timer) {
+        clearInterval(timer);
+        timer = null;
+      }
+      return cloud;
+    };
+
+    cloud.timeInterval = function(x) {
+      if (!arguments.length) return timeInterval;
+      timeInterval = x == null ? Infinity : x;
+      return cloud;
+    };
+
+    function place(board, tag, bounds) {
+      var perimeter = [{x: 0, y: 0}, {x: size[0], y: size[1]}],
+          startX = tag.x,
+          startY = tag.y,
+          maxDelta = Math.sqrt(size[0] * size[0] + size[1] * size[1]),
+          s = spiral(size),
+          dt = Math.random() < .5 ? 1 : -1,
+          t = -dt,
+          dxdy,
+          dx,
+          dy;
+
+      while (dxdy = s(t += dt)) {
+        dx = ~~dxdy[0];
+        dy = ~~dxdy[1];
+
+        if (Math.min(dx, dy) > maxDelta) break;
+
+        tag.x = startX + dx;
+        tag.y = startY + dy;
+
+        if (tag.x + tag.x0 < 0 || tag.y + tag.y0 < 0 ||
+            tag.x + tag.x1 > size[0] || tag.y + tag.y1 > size[1]) continue;
+        // TODO only check for collisions within current bounds.
+        if (!bounds || !cloudCollide(tag, board, size[0])) {
+          if (!bounds || collideRects(tag, bounds)) {
+            var sprite = tag.sprite,
+                w = tag.width >> 5,
+                sw = size[0] >> 5,
+                lx = tag.x - (w << 4),
+                sx = lx & 0x7f,
+                msx = 32 - sx,
+                h = tag.y1 - tag.y0,
+                x = (tag.y + tag.y0) * sw + (lx >> 5),
+                last;
+            for (var j = 0; j < h; j++) {
+              last = 0;
+              for (var i = 0; i <= w; i++) {
+                board[x + i] |= (last << msx) | (i < w ? (last = sprite[j * w 
+ i]) >>> sx : 0);
+              }
+              x += sw;
+            }
+            delete tag.sprite;
+            return true;
+          }
+        }
+      }
+      return false;
+    }
+
+    cloud.words = function(x) {
+      if (!arguments.length) return words;
+      words = x;
+      return cloud;
+    };
+
+    cloud.size = function(x) {
+      if (!arguments.length) return size;
+      size = [+x[0], +x[1]];
+      return cloud;
+    };
+
+    cloud.font = function(x) {
+      if (!arguments.length) return font;
+      font = d3.functor(x);
+      return cloud;
+    };
+
+    cloud.fontStyle = function(x) {
+      if (!arguments.length) return fontStyle;
+      fontStyle = d3.functor(x);
+      return cloud;
+    };
+
+    cloud.fontWeight = function(x) {
+      if (!arguments.length) return fontWeight;
+      fontWeight = d3.functor(x);
+      return cloud;
+    };
+
+    cloud.rotate = function(x) {
+      if (!arguments.length) return rotate;
+      rotate = d3.functor(x);
+      return cloud;
+    };
+
+    cloud.text = function(x) {
+      if (!arguments.length) return text;
+      text = d3.functor(x);
+      return cloud;
+    };
+
+    cloud.spiral = function(x) {
+      if (!arguments.length) return spiral;
+      spiral = spirals[x + ""] || x;
+      return cloud;
+    };
+
+    cloud.fontSize = function(x) {
+      if (!arguments.length) return fontSize;
+      fontSize = d3.functor(x);
+      return cloud;
+    };
+
+    cloud.padding = function(x) {
+      if (!arguments.length) return padding;
+      padding = d3.functor(x);
+      return cloud;
+    };
+
+    return d3.rebind(cloud, event, "on");
+  }
+
+  function cloudText(d) {
+    return d.text;
+  }
+
+  function cloudFont() {
+    return "serif";
+  }
+
+  function cloudFontNormal() {
+    return "normal";
+  }
+
+  function cloudFontSize(d) {
+    return Math.sqrt(d.value);
+  }
+
+  function cloudRotate() {
+    return (~~(Math.random() * 6) - 3) * 30;
+  }
+
+  function cloudPadding() {
+    return 1;
+  }
+
+  // Fetches a monochrome sprite bitmap for the specified text.
+  // Load in batches for speed.
+  function cloudSprite(d, data, di) {
+    if (d.sprite) return;
+    c.clearRect(0, 0, (cw << 5) / ratio, ch / ratio);
+    var x = 0,
+        y = 0,
+        maxh = 0,
+        n = data.length;
+    --di;
+    while (++di < n) {
+      d = data[di];
+      c.save();
+      c.font = d.style + " " + d.weight + " " + ~~((d.size + 1) / ratio) + "px 
" + d.font;
+      var w = c.measureText(d.text + "m").width * ratio,
+          h = d.size << 1;
+      if (d.rotate) {
+        var sr = Math.sin(d.rotate * cloudRadians),
+            cr = Math.cos(d.rotate * cloudRadians),
+            wcr = w * cr,
+            wsr = w * sr,
+            hcr = h * cr,
+            hsr = h * sr;
+        w = (Math.max(Math.abs(wcr + hsr), Math.abs(wcr - hsr)) + 0x1f) >> 5 
<< 5;
+        h = ~~Math.max(Math.abs(wsr + hcr), Math.abs(wsr - hcr));
+      } else {
+        w = (w + 0x1f) >> 5 << 5;
+      }
+      if (h > maxh) maxh = h;
+      if (x + w >= (cw << 5)) {
+        x = 0;
+        y += maxh;
+        maxh = 0;
+      }
+      if (y + h >= ch) break;
+      c.translate((x + (w >> 1)) / ratio, (y + (h >> 1)) / ratio);
+      if (d.rotate) c.rotate(d.rotate * cloudRadians);
+      c.fillText(d.text, 0, 0);
+      if (d.padding) c.lineWidth = 2 * d.padding, c.strokeText(d.text, 0, 0);
+      c.restore();
+      d.width = w;
+      d.height = h;
+      d.xoff = x;
+      d.yoff = y;
+      d.x1 = w >> 1;
+      d.y1 = h >> 1;
+      d.x0 = -d.x1;
+      d.y0 = -d.y1;
+      d.hasText = true;
+      x += w;
+    }
+    var pixels = c.getImageData(0, 0, (cw << 5) / ratio, ch / ratio).data,
+        sprite = [];
+    while (--di >= 0) {
+      d = data[di];
+      if (!d.hasText) continue;
+      var w = d.width,
+          w32 = w >> 5,
+          h = d.y1 - d.y0;
+      // Zero the buffer
+      for (var i = 0; i < h * w32; i++) sprite[i] = 0;
+      x = d.xoff;
+      if (x == null) return;
+      y = d.yoff;
+      var seen = 0,
+          seenRow = -1;
+      for (var j = 0; j < h; j++) {
+        for (var i = 0; i < w; i++) {
+          var k = w32 * j + (i >> 5),
+              m = pixels[((y + j) * (cw << 5) + (x + i)) << 2] ? 1 << (31 - (i 
% 32)) : 0;
+          sprite[k] |= m;
+          seen |= m;
+        }
+        if (seen) seenRow = j;
+        else {
+          d.y0++;
+          h--;
+          j--;
+          y++;
+        }
+      }
+      d.y1 = d.y0 + seenRow;
+      d.sprite = sprite.slice(0, (d.y1 - d.y0) * w32);
+    }
+  }
+
+  // Use mask-based collision detection.
+  function cloudCollide(tag, board, sw) {
+    sw >>= 5;
+    var sprite = tag.sprite,
+        w = tag.width >> 5,
+        lx = tag.x - (w << 4),
+        sx = lx & 0x7f,
+        msx = 32 - sx,
+        h = tag.y1 - tag.y0,
+        x = (tag.y + tag.y0) * sw + (lx >> 5),
+        last;
+    for (var j = 0; j < h; j++) {
+      last = 0;
+      for (var i = 0; i <= w; i++) {
+        if (((last << msx) | (i < w ? (last = sprite[j * w + i]) >>> sx : 0))
+            & board[x + i]) return true;
+      }
+      x += sw;
+    }
+    return false;
+  }
+
+  function cloudBounds(bounds, d) {
+    var b0 = bounds[0],
+        b1 = bounds[1];
+    if (d.x + d.x0 < b0.x) b0.x = d.x + d.x0;
+    if (d.y + d.y0 < b0.y) b0.y = d.y + d.y0;
+    if (d.x + d.x1 > b1.x) b1.x = d.x + d.x1;
+    if (d.y + d.y1 > b1.y) b1.y = d.y + d.y1;
+  }
+
+  function collideRects(a, b) {
+    return a.x + a.x1 > b[0].x && a.x + a.x0 < b[1].x && a.y + a.y1 > b[0].y 
&& a.y + a.y0 < b[1].y;
+  }
+
+  function archimedeanSpiral(size) {
+    var e = size[0] / size[1];
+    return function(t) {
+      return [e * (t *= .1) * Math.cos(t), t * Math.sin(t)];
+    };
+  }
+
+  function rectangularSpiral(size) {
+    var dy = 4,
+        dx = dy * size[0] / size[1],
+        x = 0,
+        y = 0;
+    return function(t) {
+      var sign = t < 0 ? -1 : 1;
+      // See triangular numbers: T_n = n * (n + 1) / 2.
+      switch ((Math.sqrt(1 + 4 * sign * t) - sign) & 3) {
+        case 0:  x += dx; break;
+        case 1:  y += dy; break;
+        case 2:  x -= dx; break;
+        default: y -= dy; break;
+      }
+      return [x, y];
+    };
+  }
+
+  // TODO reuse arrays?
+  function zeroArray(n) {
+    var a = [],
+        i = -1;
+    while (++i < n) a[i] = 0;
+    return a;
+  }
+
+  var cloudRadians = Math.PI / 180,
+      cw = 1 << 11 >> 5,
+      ch = 1 << 11,
+      canvas,
+      ratio = 1;
+
+  if (typeof document !== "undefined") {
+    canvas = document.createElement("canvas");
+    canvas.width = 1;
+    canvas.height = 1;
+    ratio = Math.sqrt(canvas.getContext("2d").getImageData(0, 0, 1, 
1).data.length >> 2);
+    canvas.width = (cw << 5) / ratio;
+    canvas.height = ch / ratio;
+  } else {
+    // Attempt to use node-canvas.
+    canvas = new Canvas(cw << 5, ch);
+  }
+
+  var c = canvas.getContext("2d"),
+      spirals = {
+        archimedean: archimedeanSpiral,
+        rectangular: rectangularSpiral
+      };
+  c.fillStyle = c.strokeStyle = "red";
+  c.textAlign = "center";
+
+  if (typeof module === "object" && module.exports) module.exports = cloud;
+  else (d3.layout || (d3.layout = {})).cloud = cloud;
+})();
diff --git a/lib/topojson.js b/lib/topojson.js
index 52afa2a..43b43f5 100644
--- a/lib/topojson.js
+++ b/lib/topojson.js
@@ -1,6 +1,6 @@
 !function() {
   var topojson = {
-    version: "1.6.18",
+    version: "1.6.19",
     mesh: function(topology) { return object(topology, meshArcs.apply(this, 
arguments)); },
     meshArcs: meshArcs,
     merge: function(topology) { return object(topology, mergeArcs.apply(this, 
arguments)); },
diff --git a/lib/vega.js b/lib/vega.js
index 583ff71..456a0da 100644
--- a/lib/vega.js
+++ b/lib/vega.js
@@ -21,7 +21,7 @@
 //---------------------------------------------------
 
   var vg = {
-    version:  "1.5.2", // semantic versioning
+    version:  "1.5.3", // semantic versioning
     d3:       d3,      // stash d3 for use in property functions
     topojson: topojson // stash topojson similarly
   };
@@ -67,7 +67,7 @@
 
 vg.boolean = function(s) { return s === null ? null :  !!s; };
 
-vg.date = function(s) {return s === null ? null : Date.parse(s); }
+vg.date = function(s) {return s === null ? null : Date.parse(s); };
 
 // ES6 compatibility per 
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/startsWith#Polyfill
 // We could have used the polyfill code, but lets wait until ES6 becomes a 
standard first
@@ -163,7 +163,7 @@
     return 1;
   }
   return NaN;
-}
+};
 
 vg.numcmp = function(a, b) { return a - b; };
 
@@ -581,7 +581,7 @@
       .add(cos*x1 - sin*y2 + cx,  sin*x1 + cos*y2 + cy)
       .add(cos*x2 - sin*y1 + cx,  sin*x2 + cos*y1 + cy)
       .add(cos*x2 - sin*y2 + cx,  sin*x2 + cos*y2 + cy);
-  }
+  };
 
   prototype.union = function(b) {
     if (b.x1 < this.x1) this.x1 = b.x1;
@@ -637,7 +637,7 @@
     this.x2 = 1;
     this.y1 = 0;
     this.y2 = 0;
-  };
+  }
 
   var prototype = gradient.prototype;
 
@@ -652,7 +652,8 @@
   return gradient;
 })();
 
-var vg_gradient_id = 0;vg.canvas = {};vg.canvas.path = (function() {
+var vg_gradient_id = 0;
+vg.canvas = {};vg.canvas.path = (function() {
 
   // Path parsing and rendering code taken from fabric.js -- Thanks!
   var cmdLength = { m:2, l:2, h:1, v:1, c:6, s:4, q:4, t:2, a:7 },
@@ -1736,7 +1737,7 @@
   function drawAll(pathFunc) {
     return function(g, scene, bounds) {
       drawPathAll(pathFunc, g, scene, bounds);
-    }
+    };
   }
 
   function drawOne(pathFunc) {
@@ -1745,7 +1746,7 @@
       if (bounds && !bounds.intersects(scene.items[0].bounds))
         return; // bounds check
       drawPathOne(pathFunc, g, scene.items[0], scene.items);
-    }
+    };
   }
 
   function drawGroup(g, scene, bounds) {
@@ -2805,7 +2806,7 @@
       marks.update[type].call(node, item);
       marks.style.call(node, item);
     }
-  }
+  };
   
   prototype.draw = function(ctx, scene, index) {
     var marktype = scene.marktype,
@@ -2963,7 +2964,7 @@
   return function(data) {
     data.forEach(func);
     return data;
-  }
+  };
 };
 
 vg.data.size = function(size, group) {
@@ -3076,11 +3077,11 @@
 
   function http(url, callback) {
     vg.log('LOAD HTTP: ' + url);
-    var options = {url: url};
+    var options = {url: url, encoding: null, gzip: true};
     if (vg.config.dataHeaders) {
       options.headers = vg.config.dataHeaders;
     }
-    var req = require('request')(options, function(error, response, body) {
+    require('request').get(options, function(error, response, body) {
       if (!error && response.statusCode === 200) {
         callback(null, body);
       } else {
@@ -3257,7 +3258,7 @@
     var ops = this.ops;
     for (var i=0; i<ops.length; ++i) {
       if (ops[i] === 'count') {
-        o["count"] = this.count;
+        o.count = this.count;
       } else {
         o[ops[i] + "_" + this.field] = this.value(ops[i]);
       }
@@ -3364,9 +3365,9 @@
   var field,
       accessor,
       setter,
-      min = undefined,
-      max = undefined,
-      step = undefined,
+      min,
+      max,
+      step,
       maxbins = 20,
       output = "bin";
 
@@ -3711,7 +3712,7 @@
     force[name] = function(x) {
       layout[name](x);
       return force;
-    }
+    };
   });
 
   return force;
@@ -3792,7 +3793,7 @@
         opt[name] = x;
         func[name](x);
         return map;
-      }
+      };
     });
     
     map.lon = function(field) {
@@ -3816,11 +3817,12 @@
     
     
     return map;
-  };
+  }
   
   geo.params = params;
   return geo;
-})();vg.data.geopath = function() {
+})();
+vg.data.geopath = function() {
   var geopath = d3.geo.path().projection(d3.geo.mercator()),
       projection = "mercator",
       geojson = vg.identity,
@@ -3849,7 +3851,7 @@
       opt[name] = x;
       (geopath.projection())[name](x);
       return map;
-    }
+    };
   });
    
   map.value = function(field) {
@@ -4090,9 +4092,9 @@
       };
 
   function stack(data) {
-    var out_y0 = output["y0"],
-        out_y1 = output["y1"],
-        out_cy = output["cy"];
+    var out_y0 = output.y0,
+        out_y1 = output.y1,
+        out_cy = output.cy;
     
     var series = stacks(data);
     if (series.length === 0) return data;
@@ -4158,7 +4160,7 @@
     stack[name] = function(x) {
       layout[name](x);
       return stack;
-    }
+    };
   });
 
   stack.output = function(map) {
@@ -4327,7 +4329,7 @@
     treemap[name] = function(x) {
       layout[name](x);
       return treemap;
-    }
+    };
   });
 
   treemap.output = function(map) {
@@ -4528,7 +4530,7 @@
     cloud[name] = function(x) {
       layout[name](x);
       return cloud;
-    }
+    };
   });
 
   cloud.output = function(map) {
@@ -4545,7 +4547,7 @@
   var z = null,
       as = "zip",
       key = vg.accessor("data"),
-      defaultValue = undefined,
+      defaultValue,
       withKey = null;
 
   function zip(data, db) {
@@ -7237,7 +7239,7 @@
       axes[index] = axes[index] || vg.scene.axis();
       axis(def, index, axes[index], scales);
     });
-  };
+  }
 
   function axis(def, index, axis, scales) {
     // axis scale
@@ -7327,10 +7329,14 @@
       if (error) {
         vg.error("LOADING FAILED: " + d.url);
       } else {
-        model.load[d.name] = vg.data.read(data.toString(), d.format);
+        try {
+          model.load[d.name] = vg.data.read(data.toString(), d.format);
+        } catch (err) {
+          vg.error("UNABLE TO PARSE: " + d.url + ' ' + err.toString());
+        }
       }
       if (--count === 0) callback();
-    }
+    };
   }
   
   // process each data set definition
@@ -7409,7 +7415,7 @@
       legends[index] = legends[index] || vg.scene.legend();
       legend(def, index, legends[index], scales);
     });
-  };
+  }
 
   function legend(def, index, legend, scales) {
     // legend scales
@@ -7443,7 +7449,8 @@
   }
   
   return legends;
-})();vg.parse.mark = function(mark) {
+})();
+vg.parse.mark = function(mark) {
   var props = mark.properties,
       group = mark.marks;
 
@@ -7496,7 +7503,7 @@
         names = vg.keys(spec),
         i, len, name, ref, vars = {};
         
-    code += "var o = trans ? {} : item;\n"
+    code += "var o = trans ? {} : item;\n";
     
     for (i=0, len=names.length; i<len; ++i) {
       ref = spec[name = names[i]];
@@ -7513,14 +7520,14 @@
       } else if (vars.width) {
         code += "\n  o.x = (o.x2 - o.width);";
       } else {
-        code += "\n  o.x = o.x2;"
+        code += "\n  o.x = o.x2;";
       }
     }
     if (vars.xc) {
       if (vars.width) {
         code += "\n  o.x = (o.xc - o.width/2);";
       } else {
-        code += "\n  o.x = o.xc;"
+        code += "\n  o.x = o.xc;";
       }
     }
 
@@ -7532,14 +7539,14 @@
       } else if (vars.height) {
         code += "\n  o.y = (o.y2 - o.height);";
       } else {
-        code += "\n  o.y = o.y2;"
+        code += "\n  o.y = o.y2;";
       }
     }
     if (vars.yc) {
       if (vars.height) {
         code += "\n  o.y = (o.yc - o.height/2);";
       } else {
-        code += "\n  o.y = o.yc;"
+        code += "\n  o.y = o.yc;";
       }
     }
     
@@ -8025,7 +8032,7 @@
   }
 
   return source;
-}
+};
 
 var vg_template_re = /\{\{(.+?)\}\}|$/g;
 
@@ -8081,7 +8088,7 @@
 vg.scene.UPDATE = 1,
 vg.scene.EXIT   = 2;
 
-vg.scene.DEFAULT_DATA = {"sentinel":1}
+vg.scene.DEFAULT_DATA = {"sentinel":1};
 
 vg.scene.data = function(data, parentData) {
   var DEFAULT = vg.scene.DEFAULT_DATA;
@@ -8184,13 +8191,13 @@
     }
     
     return node;
-  };
+  }
   
   function buildNode(def, node) {
     node = node || {};
     node.def = def;
     node.marktype = def.type;
-    node.interactive = !(def.interactive === false);
+    node.interactive = (def.interactive !== false);
     return node;
   }
   
@@ -8255,7 +8262,7 @@
 
   function buildTrans(def, node) {
     if (def.duration) node.duration = def.duration;
-    if (def.ease) node.ease = d3.ease(def.ease)
+    if (def.ease) node.ease = d3.ease(def.ease);
     if (def.delay) {
       var items = node.items, group = node.group, n = items.length, i;
       for (i=0; i<n; ++i) def.delay.call(this, items[i], group);
@@ -8271,11 +8278,12 @@
         s += String(f[i](d));
       }
       return s;
-    }
+    };
   }
   
   return build;
-})();vg.scene.bounds = (function() {
+})();
+vg.scene.bounds = (function() {
 
   var parse = vg.canvas.path.parse,
       boundPath = vg.canvas.path.bounds,
@@ -8800,7 +8808,7 @@
 
     this.callback();
     return stop;
-  };
+  }
   
   return trans;
   
@@ -8808,7 +8816,8 @@
 
 vg.scene.transition = function(dur, ease) {
   return new vg.scene.Transition(dur, ease);
-};vg.scene.axis = function() {
+};
+vg.scene.axis = function() {
   var scale,
       orient = vg.config.axis.orient,
       offset = 0,
@@ -9348,7 +9357,7 @@
       values = null,
       format = null,
       formatString = null,
-      title = undefined,
+      title,
       orient = "right",
       offset = vg.config.legend.offset,
       padding = vg.config.legend.padding,
@@ -9697,7 +9706,7 @@
       gx = group.bounds ? group.bounds.x1 : 0;
       o.x += gx - offset - lw;
       break;
-    };
+    }
     case "right": {
       gx = group.width;
       if (group.bounds) gx = trans
@@ -9705,7 +9714,7 @@
         : group.bounds.x2;
       o.x += gx + offset;
       break;
-    };
+    }
   }
   
   if (trans) trans.interpolate(item, o);
@@ -10353,7 +10362,7 @@
       height: h
     };
     if (bgcolor != null) {
-      headAttr.style = 'background-color:' + bgcolor + ';'
+      headAttr.style = 'background-color:' + bgcolor + ';';
     }
 
     t.head = open('svg', headAttr, vg.config.svgNamespace);
@@ -10701,7 +10710,7 @@
           defs.gradient[value.id] = value;
           value = "url(" + window.location.href + "#" + value.id + ")";
         }
-        s += name + ':' + value + ';'
+        s += name + ':' + value + ';';
       }
     }
     
@@ -10925,7 +10934,7 @@
 
     // configure renderer
     this._renderer.initialize(this._el, tw, th, pad, bg);
-  }
+  };
   
   prototype.render = function(items) {
     this._renderer.render(this._model.scene(), items);

-- 
To view, visit https://gerrit.wikimedia.org/r/214311
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I0a1fc5420f365613cd8223205dc6ad7b90cecd10
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/Graph
Gerrit-Branch: master
Gerrit-Owner: Yurik <[email protected]>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to