OLD | NEW |
1 'use strict'; | 1 'use strict'; |
2 | 2 |
3 /** | 3 /** |
4 * Provides a declarative structure around interactive D3 | 4 * Provides a declarative structure around interactive D3 |
5 * applications. | 5 * applications. |
6 * | 6 * |
7 * @module d3-components | 7 * @module d3-components |
8 **/ | 8 **/ |
9 | 9 |
10 YUI.add('d3-components', function(Y) { | 10 YUI.add('d3-components', function(Y) { |
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
187 modEvents = this.events[modName], | 187 modEvents = this.events[modName], |
188 module = this.modules[modName], | 188 module = this.modules[modName], |
189 owns = Y.Object.owns, | 189 owns = Y.Object.owns, |
190 container = this.get('container'), | 190 container = this.get('container'), |
191 subscriptions = [], | 191 subscriptions = [], |
192 handlers, | 192 handlers, |
193 handler; | 193 handler; |
194 | 194 |
195 function _bindEvent(name, handler, container, selector, context) { | 195 function _bindEvent(name, handler, container, selector, context) { |
196 // Adapt between d3 events and YUI delegates. | 196 // Adapt between d3 events and YUI delegates. |
197 var d3Adaptor = function(evt) { | 197 var d3Adapter = function(evt) { |
198 var selection = d3.select(evt.currentTarget.getDOMNode()), | 198 var selection = d3.select(evt.currentTarget.getDOMNode()), |
199 d = selection.data()[0]; | 199 d = selection.data()[0]; |
200 // This is a minor violation (extension) | 200 // This is a minor violation (extension) |
201 // of the interface, but suits us well. | 201 // of the interface, but suits us well. |
202 d3.event = evt; | 202 d3.event = evt; |
| 203 //console.debug('Handler for', name, selector, d3.event); |
203 return handler.call( | 204 return handler.call( |
204 evt.currentTarget.getDOMNode(), d, context); | 205 evt.currentTarget.getDOMNode(), d, context); |
205 }; | 206 }; |
206 | 207 |
207 subscriptions.push( | 208 subscriptions.push( |
208 Y.delegate(name, d3Adaptor, container, selector, context)); | 209 Y.delegate(name, d3Adapter, container, selector, context)); |
209 } | 210 } |
210 | 211 |
211 this.unbind(modName); | 212 this.unbind(modName); |
212 | 213 |
213 // Bind 'scene' events | 214 // Bind 'scene' events |
214 Y.each(modEvents.scene, function(handlers, selector, sceneEvents) { | 215 Y.each(modEvents.scene, function(handlers, selector, sceneEvents) { |
215 Y.each(handlers, function(handler, trigger) { | 216 Y.each(handlers, function(handler, trigger) { |
216 handler = self._normalizeHandler(handler, module, selector); | 217 handler = self._normalizeHandler(handler, module, selector); |
217 if (L.isValue(handler)) { | 218 if (L.isValue(handler)) { |
218 _bindEvent(trigger, handler.callback, | 219 _bindEvent(trigger, handler.callback, |
(...skipping 26 matching lines...) Expand all Loading... |
245 // context as third argument. | 246 // context as third argument. |
246 var target = self, | 247 var target = self, |
247 callback = Y.bind(handler.callback, handler.context); | 248 callback = Y.bind(handler.callback, handler.context); |
248 if (Y.Array.indexOf(['windowresize'], name) !== -1) { | 249 if (Y.Array.indexOf(['windowresize'], name) !== -1) { |
249 target = Y; | 250 target = Y; |
250 handler.context = null; | 251 handler.context = null; |
251 } else { | 252 } else { |
252 // (re)Register the event to bubble. | 253 // (re)Register the event to bubble. |
253 self.publish(name, {emitFacade: true}); | 254 self.publish(name, {emitFacade: true}); |
254 } | 255 } |
255 console.debug('d3 component yui event binding', target.toString(), | 256 console.debug('yui event binding', module.name, eventPhase, name); |
256 eventPhase, name); | |
257 subscriptions.push( | 257 subscriptions.push( |
258 target[eventPhase]( | 258 target[eventPhase]( |
259 name, callback, handler.context)); | 259 name, callback, handler.context)); |
260 }); | 260 }); |
261 } | 261 } |
262 }); | 262 }); |
263 } | 263 } |
264 return subscriptions; | 264 return subscriptions; |
265 }, | 265 }, |
266 | 266 |
(...skipping 14 matching lines...) Expand all Loading... |
281 Y.each(Y.Object.keys(eventSet), function(name) { | 281 Y.each(Y.Object.keys(eventSet), function(name) { |
282 this.events[name].subscriptions = this._bindEvents(name); | 282 this.events[name].subscriptions = this._bindEvents(name); |
283 }, this); | 283 }, this); |
284 return this; | 284 return this; |
285 }, | 285 }, |
286 | 286 |
287 /** | 287 /** |
288 * Specialized handling of events only found in d3. | 288 * Specialized handling of events only found in d3. |
289 * This is again an internal implementation detail. | 289 * This is again an internal implementation detail. |
290 * | 290 * |
291 * Its worth noting that d3 events don't use a delegate pattern | 291 * It is worth noting that d3 events don't use a delegate pattern |
292 * and thus must be bound to nodes present in a selection. | 292 * and thus must be bound to nodes present in a selection. |
293 * For this reason binding d3 events happens after render cycles. | 293 * For this reason binding d3 events happens after render cycles. |
294 * | 294 * |
295 * @method _bindD3Events | 295 * @method _bindD3Events |
296 * @param {String} modName Module name. | 296 * @param {String} modName Module name. |
297 **/ | 297 **/ |
298 _bindD3Events: function(modName) { | 298 _bindD3Events: function(modName) { |
299 // Walk each selector for a given module 'name', doing a | 299 // Walk each selector for a given module 'name', doing a |
300 // d3 selection and an 'on' binding. | 300 // d3 selection and an 'on' binding. |
301 var self = this, | 301 var self = this, |
302 modEvents = this.events[modName], | 302 modEvents = this.events[modName], |
303 owns = Y.Object.owns, | 303 owns = Y.Object.owns, |
304 module; | 304 module; |
305 | 305 |
306 if (!modEvents || !modEvents.d3) { | 306 if (!modEvents || !modEvents.d3) { |
307 return; | 307 return; |
308 } | 308 } |
309 modEvents = modEvents.d3; | 309 modEvents = modEvents.d3; |
310 module = this.modules[modName]; | 310 module = this.modules[modName]; |
311 | 311 |
312 Y.each(modEvents, function(handlers, selector) { | 312 Y.each(modEvents, function(handlers, selector) { |
313 Y.each(handlers, function(handler, trigger) { | 313 Y.each(handlers, function(handler, trigger) { |
314 var adapter; | 314 var adapter; |
315 handler = self._normalizeHandler(handler, module); | 315 handler = self._normalizeHandler(handler, module); |
316 // Create an adaptor | 316 // Create an adapter |
317 adapter = function() { | 317 adapter = function() { |
318 var selection = d3.select(this), | 318 var selection = d3.select(this), |
319 d = selection.data()[0]; | 319 d = selection.data()[0]; |
| 320 console.debug('D3 Handler for', selector, trigger); |
320 return handler.callback.call(this, d, handler.context); | 321 return handler.callback.call(this, d, handler.context); |
321 }; | 322 }; |
322 d3.selectAll(selector).on(trigger, adapter); | 323 d3.selectAll(selector).on(trigger, adapter); |
323 }); | 324 }); |
324 }); | 325 }); |
325 }, | 326 }, |
326 | 327 |
327 /** | 328 /** |
328 * Allow d3 event rebinding after rendering. | 329 * Allow d3 event rebinding after rendering. The component |
| 330 * can trigger this after it is sure relevant elements |
| 331 * are in the bound DOM. |
329 * | 332 * |
330 **/ | 333 **/ |
331 bindAllD3Events: function() { | 334 bindAllD3Events: function() { |
332 var self = this; | 335 var self = this; |
333 Y.each(this.modules, function(mod, name) { | 336 Y.each(this.modules, function(mod, name) { |
334 self._bindD3Events(name); | 337 self._bindD3Events(name); |
335 }); | 338 }); |
336 }, | 339 }, |
337 | 340 |
338 /** | 341 /** |
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
503 } | 506 } |
504 | 507 |
505 }); | 508 }); |
506 ns.Component = Component; | 509 ns.Component = Component; |
507 }, '0.1', { | 510 }, '0.1', { |
508 'requires': ['d3', | 511 'requires': ['d3', |
509 'base', | 512 'base', |
510 'array-extras', | 513 'array-extras', |
511 'event', | 514 'event', |
512 'event-resize']}); | 515 'event-resize']}); |
OLD | NEW |