ampersand-dom-bindings
Advanced tools
Comparing version 3.3.3 to 3.4.0
@@ -45,2 +45,14 @@ /*$AMPERSAND_VERSION*/ | ||
function setAttributes(el, attrs) { | ||
for (var name in attrs) { | ||
dom.setAttribute(el, name, attrs[name]); | ||
} | ||
} | ||
function removeAttributes(el, attrs) { | ||
for (var name in attrs) { | ||
dom.removeAttribute(el, name); | ||
} | ||
} | ||
function makeArray(val) { | ||
@@ -137,10 +149,32 @@ return Array.isArray(val) ? val : [val]; | ||
} else if (type === 'booleanAttribute') { | ||
return function (el, value, keyName) { | ||
var name = makeArray(binding.name || keyName); | ||
getMatches(el, selector).forEach(function (match) { | ||
name.forEach(function (attr) { | ||
dom[value ? 'addAttribute' : 'removeAttribute'](match, attr); | ||
// if there are `yes` and `no` selectors, this swaps between them | ||
if (hasYesNo) { | ||
yes = makeArray(yes || ''); | ||
no = makeArray(no || ''); | ||
return function (el, value) { | ||
var prevAttribute = value ? no : yes; | ||
var newAttribute = value ? yes : no; | ||
getMatches(el, selector).forEach(function (match) { | ||
prevAttribute.forEach(function (pa) { | ||
if (pa) { | ||
dom.removeAttribute(match, pa); | ||
} | ||
}); | ||
newAttribute.forEach(function (na) { | ||
if (na) { | ||
dom.addAttribute(match, na); | ||
} | ||
}); | ||
}); | ||
}); | ||
}; | ||
}; | ||
} else { | ||
return function (el, value, keyName) { | ||
var name = makeArray(binding.name || keyName); | ||
getMatches(el, selector).forEach(function (match) { | ||
name.forEach(function (attr) { | ||
dom[value ? 'addAttribute' : 'removeAttribute'](match, attr); | ||
}); | ||
}); | ||
}; | ||
} | ||
} else if (type === 'toggle') { | ||
@@ -191,2 +225,22 @@ // this doesn't require a selector since we can pass yes/no selectors | ||
}; | ||
} else if (type === 'switchAttribute') { | ||
if (!binding.cases) throw Error('switchAttribute bindings must have "cases"'); | ||
return function (el, value, keyName) { | ||
getMatches(el, selector).forEach(function (match) { | ||
if (previousValue) { | ||
removeAttributes(match, previousValue); | ||
} | ||
if (value in binding.cases) { | ||
var attrs = binding.cases[value]; | ||
if (typeof attrs === 'string') { | ||
attrs = {}; | ||
attrs[binding.name || keyName] = binding.cases[value]; | ||
} | ||
setAttributes(match, attrs); | ||
previousValue = attrs; | ||
} | ||
}); | ||
}; | ||
} else { | ||
@@ -193,0 +247,0 @@ throw new Error('no such binding type: ' + type); |
{ | ||
"name": "ampersand-dom-bindings", | ||
"description": "Takes binding declarations and returns key-tree-store of functions that can be used to apply those bindings.", | ||
"version": "3.3.3", | ||
"version": "3.4.0", | ||
"author": "'Henrik Joreteg' <henrik@andyet.net>", | ||
@@ -6,0 +6,0 @@ "browserify": { |
@@ -94,3 +94,8 @@ # ampersand-dom-bindings | ||
selector: '#something', // or hook | ||
// to specify name of attribute to toggle (if different than key name) | ||
// you could either specify a name | ||
name: 'checked' | ||
// or a yes/no case | ||
yes: 'data-is-awesome', | ||
no: 'data-is-not-awesome' | ||
} | ||
@@ -149,2 +154,31 @@ ``` | ||
### switchAttribute | ||
Sets attribute(s) on matching elements based on the value of a property matching the case. | ||
```js | ||
'model.key': { | ||
type: 'switchAttribute', | ||
selector: 'a', // or hook | ||
name: 'href', // name defaults to the property name (e.g. 'key' from 'model.key' in this example) | ||
cases: { | ||
value1: '/foo', | ||
value2: '/bar' | ||
} | ||
} | ||
``` | ||
You can also specify multiple attributes by using an object as the case value. The object keys are used instead of the `name` option. | ||
```js | ||
'model.key': { | ||
type: 'switchAttribute', | ||
selector: 'a', // or hook | ||
cases: { | ||
value1: { href: '/foo', name: 'foo' }, | ||
value2: { href: '/bar', name: 'bar' } | ||
} | ||
} | ||
``` | ||
### innerHTML | ||
@@ -151,0 +185,0 @@ |
@@ -330,2 +330,61 @@ var test = require('tape'); | ||
test('booleanAttribute yes/no bindings', function (t) { | ||
var el = getEl('<input type="checkbox" class="thing" data-hook="some-hook">'); | ||
var bindings = domBindings({ | ||
'model': { | ||
type: 'booleanAttribute', | ||
selector: '.thing', | ||
yes: 'awesome', | ||
no: 'not-awesome' | ||
} | ||
}); | ||
t.notOk(el.firstChild.hasAttribute('awesome'), 'should not start with yes attribute'); | ||
t.notOk(el.firstChild.hasAttribute('not-awesome'), 'should not start with no attribute'); | ||
bindings.run('', null, el, true); | ||
t.ok(el.firstChild.hasAttribute('awesome'), 'should have yes attribute'); | ||
t.notOk(el.firstChild.hasAttribute('not-awesome'), 'should not have no attribute'); | ||
bindings.run('', null, el, false); | ||
t.notOk(el.firstChild.hasAttribute('awesome'), 'should not have yes attribute'); | ||
t.ok(el.firstChild.hasAttribute('not-awesome'), 'should have no attribute'); | ||
t.end(); | ||
}); | ||
test('booleanAttribute yes/no array bindings', function (t) { | ||
var el = getEl('<input type="checkbox" class="thing" data-hook="some-hook">'); | ||
var bindings = domBindings({ | ||
'model': { | ||
type: 'booleanAttribute', | ||
selector: '.thing', | ||
yes: ['awesome', 'very-awesome', 'super-awesome'], | ||
no: ['not-awesome', 'very-not-awesome'] | ||
} | ||
}); | ||
t.notOk(el.firstChild.hasAttribute('awesome'), 'should not start with yes attribute'); | ||
t.notOk(el.firstChild.hasAttribute('very-awesome'), 'should not start with no attribute'); | ||
t.notOk(el.firstChild.hasAttribute('super-awesome'), 'should not start with no attribute'); | ||
t.notOk(el.firstChild.hasAttribute('not-awesome'), 'should not start with yes attribute'); | ||
t.notOk(el.firstChild.hasAttribute('very-not-awesome'), 'should not start with no attribute'); | ||
bindings.run('', null, el, true); | ||
t.ok(el.firstChild.hasAttribute('awesome'), 'should have yes attribute'); | ||
t.ok(el.firstChild.hasAttribute('very-awesome'), 'should have yes attribute'); | ||
t.ok(el.firstChild.hasAttribute('super-awesome'), 'should have yes attribute'); | ||
t.notOk(el.firstChild.hasAttribute('not-awesome'), 'should not have no attribute'); | ||
t.notOk(el.firstChild.hasAttribute('very-not-awesome'), 'should not have no attribute'); | ||
bindings.run('', null, el, false); | ||
t.notOk(el.firstChild.hasAttribute('awesome'), 'should not have yes attribute'); | ||
t.notOk(el.firstChild.hasAttribute('very-awesome'), 'should not have yes attribute'); | ||
t.notOk(el.firstChild.hasAttribute('super-awesome'), 'should not have yes attribute'); | ||
t.ok(el.firstChild.hasAttribute('not-awesome'), 'should have no attribute'); | ||
t.ok(el.firstChild.hasAttribute('very-not-awesome'), 'should have no attribute'); | ||
t.end(); | ||
}); | ||
test('innerHTML bindings', function (t) { | ||
@@ -378,2 +437,121 @@ var el = getEl(); | ||
test('switchAttribute bindings using name option', function(t) { | ||
var el = getEl('<div></div>'); | ||
var bindings = domBindings({ | ||
'model': { | ||
type: 'switchAttribute', | ||
selector: 'div', | ||
name: 'type', | ||
cases: { | ||
foo: 'text', | ||
bar: 'password', | ||
} | ||
} | ||
}); | ||
t.strictEqual(dom.getAttribute(el, 'type'), null, 'el should not have the attribute "type"'); | ||
bindings.run('', null, el, 'foo'); | ||
t.equal(dom.getAttribute(el, 'type'), 'text'); | ||
bindings.run('', null, el, 'bar'); | ||
t.equal(dom.getAttribute(el, 'type'), 'password'); | ||
bindings.run('', null, el, 'abcdefg'); | ||
t.equal(dom.getAttribute(el, 'type'), null); | ||
t.end(); | ||
}); | ||
test('switchAttribute bindings without name option', function(t) { | ||
var el = getEl('<div></div>'); | ||
var bindings = domBindings({ | ||
'model.href': { | ||
type: 'switchAttribute', | ||
selector: 'div', | ||
cases: { | ||
foo: '/foo', | ||
bar: '/bar', | ||
} | ||
} | ||
}); | ||
t.strictEqual(dom.getAttribute(el, 'href'), null, 'el should not have the attribute "href"'); | ||
bindings.run('', null, el, 'foo', 'href'); | ||
t.equal(dom.getAttribute(el, 'href'), '/foo'); | ||
bindings.run('', null, el, 'bar', 'href'); | ||
t.equal(dom.getAttribute(el, 'href'), '/bar'); | ||
bindings.run('', null, el, 'abcdefg', 'href'); | ||
t.equal(dom.getAttribute(el, 'href'), null); | ||
t.end(); | ||
}); | ||
test('switchAttribute bindings with multiple attributes', function(t) { | ||
var el = getEl('<div></div>'); | ||
var bindings = domBindings({ | ||
'model': { | ||
type: 'switchAttribute', | ||
selector: 'div', | ||
cases: { | ||
foo: { href: '/one', name: 'one' }, | ||
bar: { href: '/two', name: 'two' }, | ||
} | ||
} | ||
}); | ||
t.strictEqual(dom.getAttribute(el, 'href'), null, 'el should not have the attribute "href"'); | ||
t.strictEqual(dom.getAttribute(el, 'name'), null, 'el should not have the attribute "name"'); | ||
bindings.run('', null, el, 'foo'); | ||
t.equal(dom.getAttribute(el, 'href'), '/one'); | ||
t.equal(dom.getAttribute(el, 'name'), 'one'); | ||
bindings.run('', null, el, 'bar'); | ||
t.equal(dom.getAttribute(el, 'href'), '/two'); | ||
t.equal(dom.getAttribute(el, 'name'), 'two'); | ||
bindings.run('', null, el, 'abcdefg'); | ||
t.equal(dom.getAttribute(el, 'href'), null); | ||
t.equal(dom.getAttribute(el, 'name'), null); | ||
t.end(); | ||
}); | ||
test('switchAttribute with boolean/undefined properties', function(t) { | ||
var el = getEl(); | ||
var bindings = domBindings({ | ||
'model': { | ||
type: 'switchAttribute', | ||
selector: 'div', | ||
name: 'style', | ||
cases: { | ||
true: 'display: block', | ||
false: 'display: none', | ||
undefined: 'color: gray', | ||
} | ||
} | ||
}); | ||
t.strictEqual(dom.getAttribute(el, 'style'), null, 'el should not have the attribute "style"'); | ||
bindings.run('', null, el, true); | ||
t.equal(dom.getAttribute(el, 'style'), 'display: block'); | ||
bindings.run('', null, el, false); | ||
t.equal(dom.getAttribute(el, 'style'), 'display: none'); | ||
bindings.run('', null, el, undefined); | ||
t.equal(dom.getAttribute(el, 'style'), 'color: gray'); | ||
t.end(); | ||
}); | ||
test('ensure selector matches root element', function (t) { | ||
@@ -717,2 +895,38 @@ var el = getEl(); | ||
test('handle yes/no cases for `booleanAttribute` when missing `yes` or `no`', function (t) { | ||
var el = getEl('<span></span>'); | ||
var bindings = domBindings({ | ||
'model1': { | ||
type: 'booleanAttribute', | ||
no: 'no', | ||
selector: 'span' | ||
} | ||
}); | ||
t.notOk(el.firstChild.hasAttribute('no')); | ||
bindings.run('model1', null, el, false); | ||
t.ok(el.firstChild.hasAttribute('no')); | ||
bindings.run('model1', null, el, true); | ||
t.notOk(el.firstChild.hasAttribute('no')); | ||
el = getEl('<span></span>'); | ||
bindings = domBindings({ | ||
'model1': { | ||
type: 'booleanAttribute', | ||
yes: 'yes', | ||
selector: 'span' | ||
} | ||
}); | ||
t.notOk(el.firstChild.hasAttribute('yes')); | ||
bindings.run('model1', null, el, true); | ||
t.ok(el.firstChild.hasAttribute('yes')); | ||
bindings.run('model1', null, el, false); | ||
t.notOk(el.firstChild.hasAttribute('yes')); | ||
t.end(); | ||
}); | ||
test('handle yes/no cases for `toggle` when missing `yes` or `no`', function (t) { | ||
@@ -719,0 +933,0 @@ var el = getEl('<span></span>'); |
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
50751
9
988
331
0