Skip to content

Commit

Permalink
Removes bindValue, bindChecked. Makes initial render of selects work
Browse files Browse the repository at this point in the history
  • Loading branch information
stephband committed Aug 15, 2024
1 parent 4b7ce1c commit a7b2e97
Show file tree
Hide file tree
Showing 7 changed files with 98 additions and 114 deletions.
47 changes: 45 additions & 2 deletions literal-html/test.html
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,50 @@ <h3>#template-7</h3>
<body>
<h1>Tests</h1>

<article class="test">















<template is="literal-html" data-quantity="1">
<label class="select-button button pink-bg size-35 font-11 @s-x2 @s-y1 y-end">
<select name="quantity" value="${ console.log('Q', data.quantity), data.quantity === 1 ? '25' : data.quantity }">
<option value="25">Up to 25 employees</option>
<option value="100">Up to 100 employees</option>
<option value="250">Up to 250 employees</option>
<option value="1000">Up to 1000 employees</option>
</select>
</label>
</template>


















<!--article class="test">
<template is="literal-html">
<h2>is="literal-html"</h2>
<p>Test attribute renderers.</p>
Expand Down Expand Up @@ -430,5 +473,5 @@ <h2>location</h2>
<pre>(${ this.renderCount }) location.identifier = ${ location.pathname }</pre>
${ location.pathname ? include('#template-' + /\w+$/.exec(location.pathname)[0], data) : '' }
</template>
</article>
</article-->
</body>
4 changes: 2 additions & 2 deletions modules/renderer/renderer-boolean.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@ attribute.
function setBooleanProperty(node, name, value) {
if (node[name] === !!value) return;
node[name] = !!value;
if (window.DEUBG) ++stats.property;
if (window.DEBUG) ++stats.property;
}

function setBooleanAttribute(node, name, value) {
// If attribute is already set...
if ((node.getAttribute(name) !== null)) {
if (value) return;
node.removeAttribute(name);
if (window.DEUBG) ++stats.attribute;
if (window.DEBUG) ++stats.attribute;
return;
}

Expand Down
1 change: 0 additions & 1 deletion modules/renderer/renderer-checked.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import isDefined from 'fn/is-defined.js';
import Signal from 'fn/signal.js';
import trigger from 'dom/trigger.js';
import config from '../config.js';
import bindChecked from '../../scope/bind-checked.js';
import AttributeRenderer from './renderer-attribute.js';
import { toAttributeBoolean } from './renderer-boolean.js';
import { getValue } from './renderer-value.js';
Expand Down
63 changes: 20 additions & 43 deletions modules/renderer/renderer-value.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,13 @@ import overload from 'fn/overload.js';
import Signal from 'fn/signal.js';
import trigger from 'dom/trigger.js';
import config from '../config.js';
import bindValue from '../../scope/bind-value.js';
import { stash } from '../stash.js';
import AttributeRenderer, { toAttributeString } from './renderer-attribute.js';
import { stats } from './renderer.js';
import toText from './to-text.js';


const A = Array.prototype;
const $value = Symbol('value');
const A = Array.prototype;

const enhancedTypes = {
'select-one': true,
Expand All @@ -28,7 +27,7 @@ const enhancedTypes = {
Literal provides a mechanism for setting and getting values of any type on
select, checkbox and radio inputs. Where `input.value` always returns a string
(on uncustomised DOM elements, at least), getValue(element) returns the value
(on uncustomised DOM elements, at least), `stash(element)` returns the value
set by a Literal template *before* it was coerced to a string. If no such value
exists it falls back to returning the string.
Expand All @@ -40,9 +39,9 @@ events('input', document.body)
**/

function getElementValue(element) {
return $value in element ? element[$value] :
return stash.has(element) ? stash.get(element) :
'value' in element ? element.value :
element.getAttribute('value') || undefined ;
element.getAttribute('value') ;
}

export const getValue = overload(get('type'), {
Expand Down Expand Up @@ -84,23 +83,19 @@ const types = {
function setElementValue(element, value) {
// Don't render into focused nodes, it makes the cursor jump to the
// end of the field, and we should cede control to the user
if (document.activeElement === element) {
return 0;
}
if (document.activeElement === element) return;

const isEnhanced = enhancedTypes[element.type];

// If value is already set on $value expando do nothing
if (isEnhanced && $value in element && element[$value] === value) return;
// If value is already stashed do nothing
if (isEnhanced && stash.has(element) && stash.get(element) === value) return;

// Refuse to set value that does not conform to input type
const expectedType = types[element.type];
if (expectedType && typeof value !== expectedType) return;

// Where input is an enhanced type set object value as a $value expando
if (isEnhanced) {
element[$value] = value;
}
// Where input is an enhanced type stash object
if (isEnhanced) stash.set(element, value);

// Convert to string with Literal's text rendering rules
const string = toText(value);
Expand Down Expand Up @@ -153,30 +148,19 @@ export const setValue = overload(get('type'), {
});


/**
removeValue(element)
Deletes value expando on element.
**/

export function removeValue(element) {
delete element[$value];
}


/**
ValueRenderer(fn, element, unused, consts)
Constructs an object responsible for rendering from a value attribute to a
value property. Parameter `name` is redundant, but here for symmetry with other
renderers.
**/

const toValue = overload(get('type'), {
const coercer = {
//'date': composeDate,
//'select-multiple': composeArray,
'number': Number,
'range': Number,
'default': id
});
'number': Number,
'range': Number
};

export default class ValueRenderer extends AttributeRenderer {
static consts = ['DATA', 'data', 'element', 'shadow', 'host', 'id'];
Expand All @@ -190,20 +174,13 @@ export default class ValueRenderer extends AttributeRenderer {
Signal.evaluate(this, this.evaluate);
}

render(strings) {
// If arguments contains a single expression use its value
const value = toValue(this.element.type, this.singleExpression ?
arguments[1] :
render(strings, value) {
return setValue(this.element,
this.singleExpression ?
coercer[this.element.type] ?
coercer[this.element.type](value) :
value :
toAttributeString(arguments)
);

return setValue(this.element, value);
}

stop() {
// Guard against memory leaks by cleaning up $value expando when
// the renderer is done.
removeValue(this.element);
return super.stop();
}
}
31 changes: 31 additions & 0 deletions modules/stash.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@

/**
stash(element)
stash(element, data)
Quick-and-dirty get or set a value on an element using a WeakMap. Useful for
stashing data for event delegation. Note that the `value` attribute renderer
uses `stash()` internally to store values on elements, which is useful when
you want an `<input>` to have a non-string value. Where an `'input'` or
`'change'` event is delegated these values can be retrieved inside the handler
by getting `stash(input)`.
**/

import overload from 'fn/overload.js';

export const stash = new WeakMap();

export default overload(function() { return arguments.length; }, {
1: (object) => {
return stash.get(object);
},

2: (object, value) => {
stash.set(object, value);
return value;
},

default: window.DEBUG ?
() => { throw new Error('Literal: stash(element) to get stashed value, stash(element, value) to set stashed value'); } :
undefined
});
33 changes: 0 additions & 33 deletions scope/bind-checked.js

This file was deleted.

33 changes: 0 additions & 33 deletions scope/bind-value.js

This file was deleted.

0 comments on commit a7b2e97

Please sign in to comment.