Due to the touchend listener being overwritten for every touchstart, two
touchstart events would result in d3_event_dragSuppress being called
twice, with only a single drag restore, meaning that a document's
user-select style could be lost.
This restructuring means that the first touchstart creates the closures
for subsequent touchstart, touchmove and touchend events. A nice
side-benefit is that fewer closures are created for multitouch.
For a two-finger pinch, if two touchstart events fire, this results in
two touchmove and touchend listeners. The first will have a single
location in the locations variable, but its touchmove listener will
fire with two touches, causing it to fail due to not finding the
location of the second touch.
If the first listener fires before the second, this exception breaks
touch zooming (as no further listeners will be called), but the order is
undefined so may be browser/device dependent (for reproducing the bug).
Since zooming only ever involves a single gesture at a time, it makes
more sense to only have one listener of each type at a time, unlike
dragging, which involves multiple drag gestures at once.
Rather than duck-checking for a forEach method, limit the use of forEach to
d3_Map instances. In ECMAScript 6, the map.forEach method passes the callback
(value, key) rather than (key, value); likewise, array.forEach does the same.
This partially reverts ce6526cfe3. Although this
lacks the occasional convenience of a color instance, it has several advantages:
strings are immutable, so there is no concern of modifying the return value
(#1030); performance is improved; sometimes (e.g., Canvas, IE9 #1371) automatic
string coercion of values is unavailable, so strings are more convenient.
Previously we were trying to be clever and reuse the translate0 state while
touching; it’s simpler to just use a separate variable. Also, this commit now
restores the mousedown listener on touchend, just in case the device happens to
support both mouse and touch.
Rather than registering new timers, reassign the transition’s timer callback in-
place such that the order of callbacks for transitions is always prioritized
based on when the transition was created.
Since Math.log is a monotonic function for positive values, we can safely remove
the Math.log from both sides of the comparison. The reason Math.log was used
previously is that this is an estimate of error (the log difference between the
desired number of ticks and the actual number of ticks).