Permalink
Browse files

Merge branch 'release'

  • Loading branch information...
2 parents 3c8fabb + c1d7fbc commit 1885dd55c8156607b0f56c5aea1b2ad929035b50 @mbostock mbostock committed Jul 10, 2011
View
@@ -38,6 +38,7 @@ d3.core.js: \
src/core/min.js \
src/core/max.js \
src/core/sum.js \
+ src/core/quantile.js \
src/core/zip.js \
src/core/bisect.js \
src/core/first.js \
View
@@ -2,111 +2,158 @@
// TODO unbind zoom behavior?
// TODO unbind listener?
d3.behavior.zoom = function() {
-
var x = 0,
y = 0,
z = 0,
- listeners = [],
- pan,
- zooming;
+ panning,
+ zooming,
+ locations = {}, // identifier -> location
+ last = 0,
+ target,
+ targuments,
+ event = d3.dispatch("zoom");
+
+ // mousewheel events are totally broken!
+ // https://bugs.webkit.org/show_bug.cgi?id=40441
+ // not only that, but Chrome and Safari differ in re. to acceleration!
+ var div = d3.select("body").append("div")
+ .style("visibility", "hidden")
+ .style("top", 0)
+ .style("height", 0)
+ .style("width", 0)
+ .style("overflow-y", "scroll")
+ .append("div")
+ .style("height", "2000px")
+ .node().parentNode;
function zoom() {
- var container = this
- .on("mousedown", mousedown)
- .on("mousewheel", mousewheel)
- .on("DOMMouseScroll", mousewheel)
- .on("dblclick", mousewheel);
+ this
+ .on("mousedown.zoom", mousedown)
+ .on("mousewheel.zoom", mousewheel)
+ .on("DOMMouseScroll.zoom", dblclick)
+ .on("dblclick.zoom", dblclick)
+ .on("touchstart.zoom", touchstart);
d3.select(window)
- .on("mousemove", mousemove)
- .on("mouseup", mouseup);
+ .on("mousemove.zoom", mousemove)
+ .on("mouseup.zoom", mouseup)
+ .on("touchmove.zoom", touchmove)
+ .on("touchend.zoom", touchup);
}
- function mousedown(d, i) {
- pan = {
- x0: x - d3.event.clientX,
- y0: y - d3.event.clientY,
- target: this,
- data: d,
- index: i
- };
+ function location(point) {
+ return [point[0] - x, point[1] - y, z];
+ }
+
+ // snapshot the target, data and index for subsequent dispatch
+ function start() {
+ target = this;
+ targuments = arguments;
+ }
+
+ // Note: Since we don't rotate, it's possible for the touches to become
+ // slightly detached from their original positions. Thus, we recompute the
+ // touch points on touchend as well as touchstart!
+ function touchup() {
+ var touches = d3.svg.touches(target),
+ i = -1,
+ n = touches.length,
+ touch;
+ while (++i < n) locations[(touch = touches[i]).identifier] = location(touch);
+ return touches;
+ }
+
+ function touchstart() {
+ start.apply(this, arguments);
+ var touches = touchup(),
+ touch,
+ now = Date.now();
+
+ // doubletap detection
+ if ((touches.length === 1) && (now - last < 300)) {
+ var touch = touches[0];
+ zoomto(1 + Math.floor(z), touch, locations[touch.identifier]);
+ }
+ last = now;
+ }
+
+ function touchmove() {
+ var touches = d3.svg.touches(target);
+ switch (touches.length) {
+
+ // single-touch pan
+ case 1: {
+ var touch = touches[0];
+ zoomto(z, touch, locations[touch.identifier]);
+ break;
+ }
+
+ // double-touch pan + zoom
+ case 2: {
+ var p0 = touches[0],
+ p1 = touches[1],
+ p2 = [(p0[0] + p1[0]) / 2, (p0[1] + p1[1]) / 2],
+ l0 = locations[p0.identifier],
+ l1 = locations[p1.identifier],
+ l2 = [(l0[0] + l1[0]) / 2, (l0[1] + l1[1]) / 2, l0[2]];
+ zoomto(Math.log(d3.event.scale) / Math.LN2 + l0[2], p2, l2);
+ break;
+ }
+ }
+ }
+
+ function mousedown() {
+ start.apply(this, arguments);
+ panning = location(d3.svg.mouse(target));
d3.event.preventDefault();
- window.focus(); // TODO focusableParent
+ window.focus();
}
function mousemove() {
zooming = null;
- if (pan) {
- x = d3.event.clientX + pan.x0;
- y = d3.event.clientY + pan.y0;
- dispatch.call(pan.target, pan.data, pan.index);
- }
+ if (panning) zoomto(z, d3.svg.mouse(target), panning);
}
function mouseup() {
- if (pan) {
+ if (panning) {
mousemove();
- pan = null;
+ panning = null;
}
}
- // mousewheel events are totally broken!
- // https://bugs.webkit.org/show_bug.cgi?id=40441
- // not only that, but Chrome and Safari differ in re. to acceleration!
+ function mousewheel() {
+ start.apply(this, arguments);
- var outer = d3.select("body").append("div")
- .style("visibility", "hidden")
- .style("position", "absolute")
- .style("top", "-3000px")
- .style("height", 0)
- .style("overflow-y", "scroll")
- .append("div")
- .style("height", "2000px")
- .node().parentNode;
+ // store starting mouse location
+ if (!zooming) zooming = location(d3.svg.mouse(target));
- function mousewheel(d, i) {
- var e = d3.event;
-
- // initialize the mouse location for zooming (to avoid drift)
- if (!zooming) {
- var p = d3.svg.mouse(this.nearestViewportElement || this);
- zooming = {
- x0: x,
- y0: y,
- z0: z,
- x1: x - p[0],
- y1: y - p[1]
- };
+ // detect the pixels that would be scrolled by this wheel event
+ var e = d3.event, delta;
+ try {
+ div.scrollTop = 1000;
+ div.dispatchEvent(e);
+ delta = 1000 - div.scrollTop;
+ } catch (error) {
+ delta = e.wheelDelta || -e.detail;
}
- // adjust zoom level
- if (e.type === "dblclick") {
- z = e.shiftKey ? Math.ceil(z - 1) : Math.floor(z + 1);
- } else {
- var delta = e.wheelDelta || -e.detail;
- if (delta) {
- try {
- outer.scrollTop = 1000;
- outer.dispatchEvent(e);
- delta = 1000 - outer.scrollTop;
- } catch (error) {
- // Derp! Hope for the best?
- }
- delta *= .005;
- }
- z += delta;
- }
+ zoomto(delta * .005 + z, d3.svg.mouse(target), zooming);
+ }
- // adjust x and y to center around mouse location
- var k = Math.pow(2, z - zooming.z0) - 1;
- x = zooming.x0 + zooming.x1 * k;
- y = zooming.y0 + zooming.y1 * k;
+ function dblclick() {
+ start.apply(this, arguments);
+ var mouse = d3.svg.mouse(target);
+ zoomto(d3.event.shiftKey ? Math.ceil(z - 1) : Math.floor(z + 1), mouse, location(mouse));
+ }
- // dispatch redraw
- dispatch.call(this, d, i);
+ function zoomto(z1, x0, x1) {
+ var k = Math.pow(2, (z = z1) - x1[2]);
+ x = x0[0] - k * x1[0];
+ y = x0[1] - k * x1[1];
+ dispatch();
}
- function dispatch(d, i) {
+ function dispatch() {
var o = d3.event, // Events can be reentrant (e.g., focus).
k = Math.pow(2, z);
@@ -126,16 +173,16 @@ d3.behavior.zoom = function() {
}
try {
- for (var j = 0, m = listeners.length; j < m; j++) {
- listeners[j].call(this, d, i);
- }
+ event.zoom.dispatch.apply(target, targuments);
} finally {
d3.event = o;
}
+
+ o.preventDefault();
}
zoom.on = function(type, listener) {
- if (type == "zoom") listeners.push(listener);
+ event[type].add(listener);
return zoom;
};
View
@@ -1 +1 @@
-(function(){d3.behavior={},d3.behavior.zoom=function(){function m(e,f){function i(a,b){var c=a.__domain||(a.__domain=a.domain()),d=a.range().map(function(a){return(a-b)/h});a.domain(c).domain(d.map(a.invert))}var g=d3.event,h=Math.pow(2,c);d3.event={scale:h,translate:[a,b],transform:function(c,d){c&&i(c,a),d&&i(d,b)}};try{for(var j=0,k=d.length;j<k;j++)d[j].call(this,e,f)}finally{d3.event=g}}function l(d,e){var g=d3.event;if(!f){var h=d3.svg.mouse(this.nearestViewportElement||this);f={x0:a,y0:b,z0:c,x1:a-h[0],y1:b-h[1]}}if(g.type==="dblclick")c=g.shiftKey?Math.ceil(c-1):Math.floor(c+1);else{var i=g.wheelDelta||-g.detail;if(i){try{k.scrollTop=1e3,k.dispatchEvent(g),i=1e3-k.scrollTop}catch(j){}i*=.005}c+=i}var l=Math.pow(2,c-f.z0)-1;a=f.x0+f.x1*l,b=f.y0+f.y1*l,m.call(this,d,e)}function j(){e&&(i(),e=null)}function i(){f=null,e&&(a=d3.event.clientX+e.x0,b=d3.event.clientY+e.y0,m.call(e.target,e.data,e.index))}function h(c,d){e={x0:a-d3.event.clientX,y0:b-d3.event.clientY,target:this,data:c,index:d},d3.event.preventDefault(),window.focus()}function g(){var a=this.on("mousedown",h).on("mousewheel",l).on("DOMMouseScroll",l).on("dblclick",l);d3.select(window).on("mousemove",i).on("mouseup",j)}var a=0,b=0,c=0,d=[],e,f,k=d3.select("body").append("div").style("visibility","hidden").style("position","absolute").style("top","-3000px").style("height",0).style("overflow-y","scroll").append("div").style("height","2000px").node().parentNode;g.on=function(a,b){a=="zoom"&&d.push(b);return g};return g}})()
+(function(){d3.behavior={},d3.behavior.zoom=function(){function x(){function f(a,b){var c=a.__domain||(a.__domain=a.domain()),d=a.range().map(function(a){return(a-b)/e});a.domain(c).domain(d.map(a.invert))}var d=d3.event,e=Math.pow(2,c);d3.event={scale:e,translate:[a,b],transform:function(c,d){c&&f(c,a),d&&f(d,b)}};try{j.zoom.dispatch.apply(h,i)}finally{d3.event=d}d.preventDefault()}function w(d,e,f){var g=Math.pow(2,(c=d)-f[2]);a=e[0]-g*f[0],b=e[1]-g*f[1],x()}function v(){n.apply(this,arguments);var a=d3.svg.mouse(h);w(d3.event.shiftKey?Math.ceil(c-1):Math.floor(c+1),a,m(a))}function u(){n.apply(this,arguments),e||(e=m(d3.svg.mouse(h)));var a=d3.event,b;try{k.scrollTop=1e3,k.dispatchEvent(a),b=1e3-k.scrollTop}catch(d){b=a.wheelDelta||-a.detail}w(b*.005+c,d3.svg.mouse(h),e)}function t(){d&&(s(),d=null)}function s(){e=null,d&&w(c,d3.svg.mouse(h),d)}function r(){n.apply(this,arguments),d=m(d3.svg.mouse(h)),d3.event.preventDefault(),window.focus()}function q(){var a=d3.svg.touches(h);switch(a.length){case 1:var b=a[0];w(c,b,f[b.identifier]);break;case 2:var d=a[0],e=a[1],g=[(d[0]+e[0])/2,(d[1]+e[1])/2],i=f[d.identifier],j=f[e.identifier],k=[(i[0]+j[0])/2,(i[1]+j[1])/2,i[2]];w(Math.log(d3.event.scale)/Math.LN2+i[2],g,k)}}function p(){n.apply(this,arguments);var a=o(),b,d=Date.now();if(a.length===1&&d-g<300){var b=a[0];w(1+Math.floor(c),b,f[b.identifier])}g=d}function o(){var a=d3.svg.touches(h),b=-1,c=a.length,d;while(++b<c)f[(d=a[b]).identifier]=m(d);return a}function n(){h=this,i=arguments}function m(d){return[d[0]-a,d[1]-b,c]}function l(){this.on("mousedown.zoom",r).on("mousewheel.zoom",u).on("DOMMouseScroll.zoom",v).on("dblclick.zoom",v).on("touchstart.zoom",p),d3.select(window).on("mousemove.zoom",s).on("mouseup.zoom",t).on("touchmove.zoom",q).on("touchend.zoom",o)}var a=0,b=0,c=0,d,e,f={},g=0,h,i,j=d3.dispatch("zoom"),k=d3.select("body").append("div").style("visibility","hidden").style("top",0).style("height",0).style("width",0).style("overflow-y","scroll").append("div").style("height","2000px").node().parentNode;l.on=function(a,b){j[a].add(b);return l};return l}})()
View
@@ -290,11 +290,11 @@ function d3_chart_boxWhiskers(d) {
}
function d3_chart_boxQuartiles(d) {
- var n = d.length;
- return [.25, .5, .75].map(function(q) {
- q *= n;
- return ~~q === q ? (d[q] + d[q + 1]) / 2 : d[Math.round(q)];
- });
+ return [
+ d3.quantile(d, .25),
+ d3.quantile(d, .5),
+ d3.quantile(d, .75)
+ ];
}
// Chart design based on the recommendations of Stephen Few. Implementation
// based on the work of Clint Ivy, Jamie Love, and Jason Davies.
Oops, something went wrong.

0 comments on commit 1885dd5

Please sign in to comment.