| 1 | function contextListener(listener) {
|
|---|
| 2 | return function(event) {
|
|---|
| 3 | listener.call(this, event, this.__data__);
|
|---|
| 4 | };
|
|---|
| 5 | }
|
|---|
| 6 |
|
|---|
| 7 | function parseTypenames(typenames) {
|
|---|
| 8 | return typenames.trim().split(/^|\s+/).map(function(t) {
|
|---|
| 9 | var name = "", i = t.indexOf(".");
|
|---|
| 10 | if (i >= 0) name = t.slice(i + 1), t = t.slice(0, i);
|
|---|
| 11 | return {type: t, name: name};
|
|---|
| 12 | });
|
|---|
| 13 | }
|
|---|
| 14 |
|
|---|
| 15 | function onRemove(typename) {
|
|---|
| 16 | return function() {
|
|---|
| 17 | var on = this.__on;
|
|---|
| 18 | if (!on) return;
|
|---|
| 19 | for (var j = 0, i = -1, m = on.length, o; j < m; ++j) {
|
|---|
| 20 | if (o = on[j], (!typename.type || o.type === typename.type) && o.name === typename.name) {
|
|---|
| 21 | this.removeEventListener(o.type, o.listener, o.options);
|
|---|
| 22 | } else {
|
|---|
| 23 | on[++i] = o;
|
|---|
| 24 | }
|
|---|
| 25 | }
|
|---|
| 26 | if (++i) on.length = i;
|
|---|
| 27 | else delete this.__on;
|
|---|
| 28 | };
|
|---|
| 29 | }
|
|---|
| 30 |
|
|---|
| 31 | function onAdd(typename, value, options) {
|
|---|
| 32 | return function() {
|
|---|
| 33 | var on = this.__on, o, listener = contextListener(value);
|
|---|
| 34 | if (on) for (var j = 0, m = on.length; j < m; ++j) {
|
|---|
| 35 | if ((o = on[j]).type === typename.type && o.name === typename.name) {
|
|---|
| 36 | this.removeEventListener(o.type, o.listener, o.options);
|
|---|
| 37 | this.addEventListener(o.type, o.listener = listener, o.options = options);
|
|---|
| 38 | o.value = value;
|
|---|
| 39 | return;
|
|---|
| 40 | }
|
|---|
| 41 | }
|
|---|
| 42 | this.addEventListener(typename.type, listener, options);
|
|---|
| 43 | o = {type: typename.type, name: typename.name, value: value, listener: listener, options: options};
|
|---|
| 44 | if (!on) this.__on = [o];
|
|---|
| 45 | else on.push(o);
|
|---|
| 46 | };
|
|---|
| 47 | }
|
|---|
| 48 |
|
|---|
| 49 | export default function(typename, value, options) {
|
|---|
| 50 | var typenames = parseTypenames(typename + ""), i, n = typenames.length, t;
|
|---|
| 51 |
|
|---|
| 52 | if (arguments.length < 2) {
|
|---|
| 53 | var on = this.node().__on;
|
|---|
| 54 | if (on) for (var j = 0, m = on.length, o; j < m; ++j) {
|
|---|
| 55 | for (i = 0, o = on[j]; i < n; ++i) {
|
|---|
| 56 | if ((t = typenames[i]).type === o.type && t.name === o.name) {
|
|---|
| 57 | return o.value;
|
|---|
| 58 | }
|
|---|
| 59 | }
|
|---|
| 60 | }
|
|---|
| 61 | return;
|
|---|
| 62 | }
|
|---|
| 63 |
|
|---|
| 64 | on = value ? onAdd : onRemove;
|
|---|
| 65 | for (i = 0; i < n; ++i) this.each(on(typenames[i], value, options));
|
|---|
| 66 | return this;
|
|---|
| 67 | }
|
|---|