Merge pull request #314 from caridy/caridy/boolean-attributes

fixes issue #306 and others: boolean attributes alignment with HTML
pull/318/head
Simon Friis Vindum 8 years ago committed by GitHub
commit ecd2b1a38d

@ -3,22 +3,10 @@ import {Module} from './module';
export type Attrs = Record<string, string | number | boolean>
const booleanAttrs = ["allowfullscreen", "async", "autofocus", "autoplay", "checked", "compact", "controls", "declare",
"default", "defaultchecked", "defaultmuted", "defaultselected", "defer", "disabled",
"enabled", "formnovalidate", "hidden", "indeterminate", "inert", "ismap", "itemscope", "loop", "multiple",
"muted", "nohref", "noresize", "noshade", "novalidate", "nowrap", "open", "pauseonexit", "readonly",
"required", "reversed", "scoped", "seamless", "selected", "sortable", "spellcheck", "translate",
"truespeed", "typemustmatch", "visible"];
const xlinkNS = 'http://www.w3.org/1999/xlink';
const xmlNS = 'http://www.w3.org/XML/1998/namespace';
const colonChar = 58;
const xChar = 120;
const booleanAttrsDict: {[attribute: string]: boolean} = Object.create(null);
for (let i = 0, len = booleanAttrs.length; i < len; i++) {
booleanAttrsDict[booleanAttrs[i]] = true;
}
function updateAttrs(oldVnode: VNode, vnode: VNode): void {
var key: string, elm: Element = vnode.elm as Element,
@ -35,12 +23,10 @@ function updateAttrs(oldVnode: VNode, vnode: VNode): void {
const cur = attrs[key];
const old = oldAttrs[key];
if (old !== cur) {
if (booleanAttrsDict[key]) {
if (cur) {
elm.setAttribute(key, "");
} else {
elm.removeAttribute(key);
}
if (cur === true) {
elm.setAttribute(key, "");
} else if (cur === false) {
elm.removeAttribute(key);
} else {
// because those in TypeScript are too restrictive: https://github.com/Microsoft/TSJS-lib-generator/pull/237
type SetAttribute = (name: string, value: string | number | boolean) => void;

@ -13,31 +13,34 @@ describe('attributes', function() {
vnode0 = elm;
});
it('have their provided values', function() {
var vnode1 = h('div', {attrs: {href: '/foo', minlength: 1, value: true}});
var vnode1 = h('div', {attrs: {href: '/foo', minlength: 1, selected: true, disabled: false}});
elm = patch(vnode0, vnode1).elm;
assert.strictEqual(elm.getAttribute('href'), '/foo');
assert.strictEqual(elm.getAttribute('minlength'), '1');
assert.strictEqual(elm.getAttribute('value'), 'true');
assert.strictEqual(elm.hasAttribute('selected'), true);
assert.strictEqual(elm.getAttribute('selected'), '');
assert.strictEqual(elm.hasAttribute('disabled'), false);
});
it('can be memoized', function() {
var cachedAttrs = {href: '/foo', minlength: 1, value: true};
var cachedAttrs = {href: '/foo', minlength: 1, selected: true};
var vnode1 = h('div', {attrs: cachedAttrs});
var vnode2 = h('div', {attrs: cachedAttrs});
elm = patch(vnode0, vnode1).elm;
assert.strictEqual(elm.getAttribute('href'), '/foo');
assert.strictEqual(elm.getAttribute('minlength'), '1');
assert.strictEqual(elm.getAttribute('value'), 'true');
assert.strictEqual(elm.getAttribute('selected'), '');
elm = patch(vnode1, vnode2).elm;
assert.strictEqual(elm.getAttribute('href'), '/foo');
assert.strictEqual(elm.getAttribute('minlength'), '1');
assert.strictEqual(elm.getAttribute('value'), 'true');
assert.strictEqual(elm.getAttribute('selected'), '');
});
it('are not omitted when falsy values are provided', function() {
var vnode1 = h('div', {attrs: {href: null, minlength: 0, value: false}});
var vnode1 = h('div', {attrs: {href: null, minlength: 0, value: '', title:'undefined'}});
elm = patch(vnode0, vnode1).elm;
assert.strictEqual(elm.getAttribute('href'), 'null');
assert.strictEqual(elm.getAttribute('minlength'), '0');
assert.strictEqual(elm.getAttribute('value'), 'false');
assert.strictEqual(elm.getAttribute('value'), '');
assert.strictEqual(elm.getAttribute('title'), 'undefined');
});
it('are set correctly when namespaced', function() {
var vnode1 = h('div', {attrs: {'xlink:href': '#foo'}});
@ -63,26 +66,32 @@ describe('attributes', function() {
assert.strictEqual(elm.hasAttribute('required'), true);
assert.strictEqual(elm.getAttribute('required'), '');
assert.strictEqual(elm.hasAttribute('readonly'), true);
assert.strictEqual(elm.getAttribute('readonly'), '');
assert.strictEqual(elm.getAttribute('readonly'), '1');
assert.strictEqual(elm.hasAttribute('noresize'), true);
assert.strictEqual(elm.getAttribute('noresize'), '');
assert.strictEqual(elm.getAttribute('noresize'), 'truthy');
});
it('is omitted if the value is falsy', function() {
var vnode1 = h('div', {attrs: {required: false, readonly: 0, noresize: null}});
it('is omitted if the value is false', function() {
var vnode1 = h('div', {attrs: {required: false}});
elm = patch(vnode0, vnode1).elm;
assert.strictEqual(elm.hasAttribute('required'), false);
assert.strictEqual(elm.getAttribute('required'), null);
assert.strictEqual(elm.getAttribute('readonly'), null);
assert.strictEqual(elm.getAttribute('noresize'), null);
});
it('is not omitted if the value is falsy but casted to string', function() {
var vnode1 = h('div', {attrs: {readonly: 0, noresize: null}});
elm = patch(vnode0, vnode1).elm;
assert.strictEqual(elm.getAttribute('readonly'), '0');
assert.strictEqual(elm.getAttribute('noresize'), 'null');
});
});
describe('Object.prototype property', function() {
it('is not considered as a boolean attribute and shouldn\'t be omitted', function() {
var vnode1 = h('div', {attrs: {constructor: true}});
elm = patch(vnode0, vnode1).elm;
assert.strictEqual(elm.getAttribute('constructor'), 'true');
assert.strictEqual(elm.hasAttribute('constructor'), true);
assert.strictEqual(elm.getAttribute('constructor'), '');
var vnode2 = h('div', {attrs: {constructor: false}});
elm = patch(vnode0, vnode2).elm;
assert.strictEqual(elm.getAttribute('constructor'), 'false');
assert.strictEqual(elm.hasAttribute('constructor'), false);
});
});
});

Loading…
Cancel
Save