diff options
Diffstat (limited to 'alpinejs/packages/alpinejs/src/directives/x-model.js')
-rw-r--r-- | alpinejs/packages/alpinejs/src/directives/x-model.js | 107 |
1 files changed, 0 insertions, 107 deletions
diff --git a/alpinejs/packages/alpinejs/src/directives/x-model.js b/alpinejs/packages/alpinejs/src/directives/x-model.js deleted file mode 100644 index 12ee3d8..0000000 --- a/alpinejs/packages/alpinejs/src/directives/x-model.js +++ /dev/null @@ -1,107 +0,0 @@ -import { evaluateLater } from '../evaluator' -import { directive } from '../directives' -import { mutateDom } from '../mutation' -import bind from '../utils/bind' -import on from '../utils/on' - -directive('model', (el, { modifiers, expression }, { effect, cleanup }) => { - let evaluate = evaluateLater(el, expression) - let assignmentExpression = `${expression} = rightSideOfExpression($event, ${expression})` - let evaluateAssignment = evaluateLater(el, assignmentExpression) - - // If the element we are binding to is a select, a radio, or checkbox - // we'll listen for the change event instead of the "input" event. - var event = (el.tagName.toLowerCase() === 'select') - || ['checkbox', 'radio'].includes(el.type) - || modifiers.includes('lazy') - ? 'change' : 'input' - - let assigmentFunction = generateAssignmentFunction(el, modifiers, expression) - - let removeListener = on(el, event, modifiers, (e) => { - evaluateAssignment(() => {}, { scope: { - '$event': e, - rightSideOfExpression: assigmentFunction - }}) - }) - - cleanup(() => removeListener()) - - el._x_forceModelUpdate = () => { - evaluate(value => { - // If nested model key is undefined, set the default value to empty string. - if (value === undefined && expression.match(/\./)) value = '' - - // @todo: This is nasty - window.fromModel = true - mutateDom(() => bind(el, 'value', value)) - delete window.fromModel - }) - } - - effect(() => { - // Don't modify the value of the input if it's focused. - if (modifiers.includes('unintrusive') && document.activeElement.isSameNode(el)) return - - el._x_forceModelUpdate() - }) -}) - -function generateAssignmentFunction(el, modifiers, expression) { - if (el.type === 'radio') { - // Radio buttons only work properly when they share a name attribute. - // People might assume we take care of that for them, because - // they already set a shared "x-model" attribute. - mutateDom(() => { - if (! el.hasAttribute('name')) el.setAttribute('name', expression) - }) - } - - return (event, currentValue) => { - return mutateDom(() => { - // Check for event.detail due to an issue where IE11 handles other events as a CustomEvent. - // Safari autofill triggers event as CustomEvent and assigns value to target - // so we return event.target.value instead of event.detail - if (event instanceof CustomEvent && event.detail !== undefined) { - return event.detail || event.target.value - } else if (el.type === 'checkbox') { - // If the data we are binding to is an array, toggle its value inside the array. - if (Array.isArray(currentValue)) { - let newValue = modifiers.includes('number') ? safeParseNumber(event.target.value) : event.target.value - - return event.target.checked ? currentValue.concat([newValue]) : currentValue.filter(el => ! checkedAttrLooseCompare(el, newValue)) - } else { - return event.target.checked - } - } else if (el.tagName.toLowerCase() === 'select' && el.multiple) { - return modifiers.includes('number') - ? Array.from(event.target.selectedOptions).map(option => { - let rawValue = option.value || option.text - return safeParseNumber(rawValue) - }) - : Array.from(event.target.selectedOptions).map(option => { - return option.value || option.text - }) - } else { - let rawValue = event.target.value - return modifiers.includes('number') - ? safeParseNumber(rawValue) - : (modifiers.includes('trim') ? rawValue.trim() : rawValue) - } - }) - } -} - -function safeParseNumber(rawValue) { - let number = rawValue ? parseFloat(rawValue) : null - - return isNumeric(number) ? number : rawValue -} - -function checkedAttrLooseCompare(valueA, valueB) { - return valueA == valueB -} - -function isNumeric(subject){ - return ! Array.isArray(subject) && ! isNaN(subject) -} |