Invoke event listener with several arguments in array #13

pull/18/head
paldepind 10 years ago
parent f839ac08bb
commit d0a2f5176e

@ -1,11 +1,14 @@
var is = require('../is'); var is = require('../is');
function arrInvoker(arr) { function arrInvoker(arr) {
return function() { arr[0](arr[1]); }; return function() {
// Special case when length is two, for performance
arr.length === 2 ? arr[0](arr[1]) : arr[0].apply(undefined, arr.splice(1));
};
} }
function fnInvoker(arr) { function fnInvoker(o) {
return function(ev) { arr[0](ev); }; return function(ev) { o.fn(ev); };
} }
function updateEventListeners(oldVnode, vnode) { function updateEventListeners(oldVnode, vnode) {
@ -19,16 +22,17 @@ function updateEventListeners(oldVnode, vnode) {
if (is.array(cur)) { if (is.array(cur)) {
elm.addEventListener(name, arrInvoker(cur)); elm.addEventListener(name, arrInvoker(cur));
} else { } else {
cur = [cur]; cur = {fn: cur};
on[name] = cur; on[name] = cur;
elm.addEventListener(name, fnInvoker(cur)); elm.addEventListener(name, fnInvoker(cur));
} }
} else if (old.length === 2) { } else if (is.array(old)) {
old[0] = cur[0]; // Deliberately modify old array since it's // Deliberately modify old array since it's captured in closure created with `arrInvoker`
old[1] = cur[1]; // captured in closure created with `arrInvoker` old.length = cur.length;
for (var i = 0; i < old.length; ++i) old[i] = cur[i];
on[name] = old; on[name] = old;
} else { } else {
old[0] = cur; old.fn = cur;
on[name] = old; on[name] = old;
} }
} }

@ -1,6 +1,6 @@
{ {
"name": "snabbdom", "name": "snabbdom",
"version": "0.2.3", "version": "0.2.4",
"description": "A virtual DOM library with focus on simplicity, modularity, powerful features and performance.", "description": "A virtual DOM library with focus on simplicity, modularity, powerful features and performance.",
"main": "snabbdom.js", "main": "snabbdom.js",
"directories": { "directories": {

@ -29,7 +29,7 @@ function createKeyToOldIdx(children, beginIdx, endIdx) {
return map; return map;
} }
function createRmCb(parentElm, childElm, listeners) { function createRmCb(childElm, listeners) {
return function() { return function() {
if (--listeners === 0) childElm.parentElement.removeChild(childElm); if (--listeners === 0) childElm.parentElement.removeChild(childElm);
}; };
@ -109,7 +109,7 @@ function init(modules) {
if (isDef(ch.sel)) { if (isDef(ch.sel)) {
invokeDestroyHook(ch); invokeDestroyHook(ch);
listeners = cbs.remove.length + 1; listeners = cbs.remove.length + 1;
rm = createRmCb(parentElm, ch.elm, listeners); rm = createRmCb(ch.elm, listeners);
for (i = 0; i < cbs.remove.length; ++i) cbs.remove[i](ch, rm); for (i = 0; i < cbs.remove.length; ++i) cbs.remove[i](ch, rm);
if (isDef(i = ch.data) && isDef(i = i.hook) && isDef(i = i.remove)) { if (isDef(i = ch.data) && isDef(i = i.hook) && isDef(i = i.remove)) {
i(ch, rm); i(ch, rm);

@ -416,63 +416,6 @@ describe('snabbdom', function() {
}); });
}); });
}); });
describe('event handling', function() {
it('attaches click event handler to element', function() {
var result = [];
function clicked(ev) { result.push(ev); }
var vnode = h('div', {on: {click: clicked}}, [
h('a', 'Click my parent'),
]);
patch(vnode0, vnode);
elm.click();
assert.equal(1, result.length);
});
it('does not attach new listener', function() {
var result = [];
//function clicked(ev) { result.push(ev); }
var vnode1 = h('div', {on: {click: function(ev) { result.push(1); }}}, [
h('a', 'Click my parent'),
]);
var vnode2 = h('div', {on: {click: function(ev) { result.push(2); }}}, [
h('a', 'Click my parent'),
]);
patch(vnode0, vnode1);
elm.click();
patch(vnode1, vnode2);
elm.click();
assert.deepEqual(result, [1, 2]);
});
it('does calls handler for function in array', function() {
var result = [];
function clicked(ev) { result.push(ev); }
var vnode = h('div', {on: {click: [clicked, 1]}}, [
h('a', 'Click my parent'),
]);
patch(vnode0, vnode);
elm.click();
assert.deepEqual(result, [1]);
});
it('handles changed value in array', function() {
var result = [];
function clicked(ev) { result.push(ev); }
var vnode1 = h('div', {on: {click: [clicked, 1]}}, [
h('a', 'Click my parent'),
]);
var vnode2 = h('div', {on: {click: [clicked, 2]}}, [
h('a', 'Click my parent'),
]);
var vnode3 = h('div', {on: {click: [clicked, 3]}}, [
h('a', 'Click my parent'),
]);
patch(vnode0, vnode1);
elm.click();
patch(vnode1, vnode2);
elm.click();
patch(vnode2, vnode3);
elm.click();
assert.deepEqual(result, [1, 2, 3]);
});
});
describe('hooks', function() { describe('hooks', function() {
describe('element hooks', function() { describe('element hooks', function() {
it('calls `create` listener before inserted into parent but after children', function() { it('calls `create` listener before inserted into parent but after children', function() {

@ -0,0 +1,90 @@
var assert = require('assert');
var snabbdom = require('../snabbdom');
var patch = snabbdom.init([
require('../modules/eventlisteners.js'),
]);
var h = require('../h');
describe('event listeners', function() {
var elm, vnode0;
beforeEach(function() {
elm = document.createElement('div');
vnode0 = elm;
});
it('attaches click event handler to element', function() {
var result = [];
function clicked(ev) { result.push(ev); }
var vnode = h('div', {on: {click: clicked}}, [
h('a', 'Click my parent'),
]);
patch(vnode0, vnode);
elm.click();
assert.equal(1, result.length);
});
it('does not attach new listener', function() {
var result = [];
//function clicked(ev) { result.push(ev); }
var vnode1 = h('div', {on: {click: function(ev) { result.push(1); }}}, [
h('a', 'Click my parent'),
]);
var vnode2 = h('div', {on: {click: function(ev) { result.push(2); }}}, [
h('a', 'Click my parent'),
]);
patch(vnode0, vnode1);
elm.click();
patch(vnode1, vnode2);
elm.click();
assert.deepEqual(result, [1, 2]);
});
it('does calls handler for function in array', function() {
var result = [];
function clicked(ev) { result.push(ev); }
var vnode = h('div', {on: {click: [clicked, 1]}}, [
h('a', 'Click my parent'),
]);
patch(vnode0, vnode);
elm.click();
assert.deepEqual(result, [1]);
});
it('handles changed value in array', function() {
var result = [];
function clicked(ev) { result.push(ev); }
var vnode1 = h('div', {on: {click: [clicked, 1]}}, [
h('a', 'Click my parent'),
]);
var vnode2 = h('div', {on: {click: [clicked, 2]}}, [
h('a', 'Click my parent'),
]);
var vnode3 = h('div', {on: {click: [clicked, 3]}}, [
h('a', 'Click my parent'),
]);
patch(vnode0, vnode1);
elm.click();
patch(vnode1, vnode2);
elm.click();
patch(vnode2, vnode3);
elm.click();
assert.deepEqual(result, [1, 2, 3]);
});
it('handles changed several values in array', function() {
var result = [];
function clicked() { result.push([].slice.call(arguments)); }
var vnode1 = h('div', {on: {click: [clicked, 1, 2, 3]}}, [
h('a', 'Click my parent'),
]);
var vnode2 = h('div', {on: {click: [clicked, 1, 2]}}, [
h('a', 'Click my parent'),
]);
var vnode3 = h('div', {on: {click: [clicked, 2, 3]}}, [
h('a', 'Click my parent'),
]);
patch(vnode0, vnode1);
elm.click();
patch(vnode1, vnode2);
elm.click();
patch(vnode2, vnode3);
elm.click();
assert.deepEqual(result, [[1, 2, 3], [1, 2], [2, 3]]);
});
});

@ -1,4 +1,5 @@
require('./core'); require('./core');
require('./style'); require('./style');
require('./eventlisteners');
require('./attachto'); require('./attachto');
require('./thunk'); require('./thunk');

Loading…
Cancel
Save