Skip to content

Commit c6fbcb8

Browse files
committed
Added direct attributes access via . notation
As this feature has been proven to be worth it in various occasions with _lighterhtml_, and since it's super trivial to implement, I've decided to offer the same feature in hyperHTML.
1 parent 0a11145 commit c6fbcb8

File tree

7 files changed

+130
-85
lines changed

7 files changed

+130
-85
lines changed

cjs/objects/Updates.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,19 @@ const asNode = (item, i) => {
4949
// returns true if domdiff can handle the value
5050
const canDiff = value => 'ELEMENT_NODE' in value;
5151

52+
const hyperSetter = (node, name, svg) => svg ?
53+
value => {
54+
try {
55+
node[name] = value;
56+
}
57+
catch (nope) {
58+
node.setAttribute(name, value);
59+
}
60+
} :
61+
value => {
62+
node[name] = value;
63+
};
64+
5265
// when a Promise is used as interpolation value
5366
// its result must be parsed once resolved.
5467
// This callback is in charge of understanding what to do
@@ -99,6 +112,9 @@ Tagger.prototype = {
99112
// handle it differently from others
100113
if (name === 'style')
101114
return hyperStyle(node, original, isSVG);
115+
// direct accessors for <input .value=${...}> and friends
116+
else if (name.slice(0, 1) === '.')
117+
return hyperSetter(node, name.slice(1), isSVG);
102118
// the name is an event one,
103119
// add/remove event listeners accordingly
104120
else if (/^on/.test(name)) {

esm.js

Lines changed: 8 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

esm/objects/Updates.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,19 @@ const asNode = (item, i) => {
4949
// returns true if domdiff can handle the value
5050
const canDiff = value => 'ELEMENT_NODE' in value;
5151

52+
const hyperSetter = (node, name, svg) => svg ?
53+
value => {
54+
try {
55+
node[name] = value;
56+
}
57+
catch (nope) {
58+
node.setAttribute(name, value);
59+
}
60+
} :
61+
value => {
62+
node[name] = value;
63+
};
64+
5265
// when a Promise is used as interpolation value
5366
// its result must be parsed once resolved.
5467
// This callback is in charge of understanding what to do
@@ -99,6 +112,9 @@ Tagger.prototype = {
99112
// handle it differently from others
100113
if (name === 'style')
101114
return hyperStyle(node, original, isSVG);
115+
// direct accessors for <input .value=${...}> and friends
116+
else if (name.slice(0, 1) === '.')
117+
return hyperSetter(node, name.slice(1), isSVG);
102118
// the name is an event one,
103119
// add/remove event listeners accordingly
104120
else if (/^on/.test(name)) {

index.js

Lines changed: 69 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1470,6 +1470,18 @@ var hyperHTML = (function (document) {
14701470

14711471
var canDiff = function canDiff(value) {
14721472
return 'ELEMENT_NODE' in value;
1473+
};
1474+
1475+
var hyperSetter = function hyperSetter(node, name, svg) {
1476+
return svg ? function (value) {
1477+
try {
1478+
node[name] = value;
1479+
} catch (nope) {
1480+
node.setAttribute(name, value);
1481+
}
1482+
} : function (value) {
1483+
node[name] = value;
1484+
};
14731485
}; // when a Promise is used as interpolation value
14741486
// its result must be parsed once resolved.
14751487
// This callback is in charge of understanding what to do
@@ -1522,77 +1534,78 @@ var hyperHTML = (function (document) {
15221534
var oldValue; // if the attribute is the style one
15231535
// handle it differently from others
15241536

1525-
if (name === 'style') return hyperStyle(node, original, isSVG); // the name is an event one,
1526-
// add/remove event listeners accordingly
1527-
else if (/^on/.test(name)) {
1528-
var type = name.slice(2);
1529-
1530-
if (type === CONNECTED || type === DISCONNECTED) {
1531-
observe(node);
1532-
} else if (name.toLowerCase() in node) {
1533-
type = type.toLowerCase();
1534-
}
1537+
if (name === 'style') return hyperStyle(node, original, isSVG); // direct accessors for <input .value=${...}> and friends
1538+
else if (name.slice(0, 1) === '.') return hyperSetter(node, name.slice(1), isSVG); // the name is an event one,
1539+
// add/remove event listeners accordingly
1540+
else if (/^on/.test(name)) {
1541+
var type = name.slice(2);
15351542

1536-
return function (newValue) {
1537-
if (oldValue !== newValue) {
1538-
if (oldValue) node.removeEventListener(type, oldValue, false);
1539-
oldValue = newValue;
1540-
if (newValue) node.addEventListener(type, newValue, false);
1543+
if (type === CONNECTED || type === DISCONNECTED) {
1544+
observe(node);
1545+
} else if (name.toLowerCase() in node) {
1546+
type = type.toLowerCase();
15411547
}
1542-
};
1543-
} // the attribute is special ('value' in input)
1544-
// and it's not SVG *or* the name is exactly data,
1545-
// in this case assign the value directly
1546-
else if (name === 'data' || !isSVG && name in node && !readOnly.test(name)) {
1547-
return function (newValue) {
1548-
if (oldValue !== newValue) {
1549-
oldValue = newValue;
1550-
1551-
if (node[name] !== newValue && newValue == null) {
1552-
// cleanup on null to avoid silly IE/Edge bug
1553-
node[name] = '';
1554-
node.removeAttribute(name);
1555-
} else node[name] = newValue;
1556-
}
1557-
};
1558-
} else if (name in Intent.attributes) {
1559-
return function (any) {
1560-
var newValue = Intent.attributes[name](node, any);
15611548

1549+
return function (newValue) {
15621550
if (oldValue !== newValue) {
1551+
if (oldValue) node.removeEventListener(type, oldValue, false);
15631552
oldValue = newValue;
1564-
if (newValue == null) node.removeAttribute(name);else node.setAttribute(name, newValue);
1553+
if (newValue) node.addEventListener(type, newValue, false);
15651554
}
15661555
};
1567-
} // in every other case, use the attribute node as it is
1568-
// update only the value, set it as node only when/if needed
1569-
else {
1570-
var owner = false;
1571-
var attribute = original.cloneNode(true);
1556+
} // the attribute is special ('value' in input)
1557+
// and it's not SVG *or* the name is exactly data,
1558+
// in this case assign the value directly
1559+
else if (name === 'data' || !isSVG && name in node && !readOnly.test(name)) {
15721560
return function (newValue) {
15731561
if (oldValue !== newValue) {
15741562
oldValue = newValue;
15751563

1576-
if (attribute.value !== newValue) {
1577-
if (newValue == null) {
1578-
if (owner) {
1579-
owner = false;
1580-
node.removeAttributeNode(attribute);
1581-
}
1582-
1583-
attribute.value = newValue;
1584-
} else {
1585-
attribute.value = newValue;
1564+
if (node[name] !== newValue && newValue == null) {
1565+
// cleanup on null to avoid silly IE/Edge bug
1566+
node[name] = '';
1567+
node.removeAttribute(name);
1568+
} else node[name] = newValue;
1569+
}
1570+
};
1571+
} else if (name in Intent.attributes) {
1572+
return function (any) {
1573+
var newValue = Intent.attributes[name](node, any);
15861574

1587-
if (!owner) {
1588-
owner = true;
1589-
node.setAttributeNode(attribute);
1575+
if (oldValue !== newValue) {
1576+
oldValue = newValue;
1577+
if (newValue == null) node.removeAttribute(name);else node.setAttribute(name, newValue);
1578+
}
1579+
};
1580+
} // in every other case, use the attribute node as it is
1581+
// update only the value, set it as node only when/if needed
1582+
else {
1583+
var owner = false;
1584+
var attribute = original.cloneNode(true);
1585+
return function (newValue) {
1586+
if (oldValue !== newValue) {
1587+
oldValue = newValue;
1588+
1589+
if (attribute.value !== newValue) {
1590+
if (newValue == null) {
1591+
if (owner) {
1592+
owner = false;
1593+
node.removeAttributeNode(attribute);
1594+
}
1595+
1596+
attribute.value = newValue;
1597+
} else {
1598+
attribute.value = newValue;
1599+
1600+
if (!owner) {
1601+
owner = true;
1602+
node.setAttributeNode(attribute);
1603+
}
15901604
}
15911605
}
15921606
}
1593-
}
1594-
};
1595-
}
1607+
};
1608+
}
15961609
},
15971610
// in a hyper(node)`<div>${content}</div>` case
15981611
// everything could happen:

0 commit comments

Comments
 (0)