Skip to content

Instantly share code, notes, and snippets.

@mattduffield
Forked from fkleuver/app.html
Last active April 25, 2019 17:59
Show Gist options
  • Save mattduffield/c73ff2af4b01feabe7090ab0478269e0 to your computer and use it in GitHub Desktop.
Save mattduffield/c73ff2af4b01feabe7090ab0478269e0 to your computer and use it in GitHub Desktop.
Date Binding Behavior
<template>
<!--<require from="./card-number-format-value-converter"></require>-->
<!--<require from="./currency-binding-behavior"></require>-->
<require from="./date-binding-behavior"></require>
<!--<require from="./date-picker"></require>-->
<!--<input type="text" id="cardNumber" placeholder="1234 5678 9123 4567" -->
<!--value.bind="cardNumber & cardNumberFormat">-->
<!--<br>-->
<!--<input type="text" id="currencyNumber" placeholder="$0.00" -->
<!--value.bind="currencyNumber & currency">-->
<!--<br>-->
<input type="date" id="dateValue" value.two-way="dateValue & date">
<br>
<button click.delegate="log($event)">Log</button>
<br>
<!--<date-picker value.bind="dateValue"></date-picker>-->
</template>
export class App {
cardNumber;
currencyNumber = 0.00;
dateValue = new Date().toISOString();
log(e) {
e.preventDefault();
e.stopPropagation();
console.log('dateValue', this.dateValue);
}
}
export class CardNumberFormatBindingBehavior {
bind(binding, source, lookupFunctions) {
binding.originalUpdateSource = binding.updateSource;
binding.updateSource = value => {
const cleanValue = value.replace(/[^\d]/g, '');
binding.updateTarget(cleanValue);
console.log(`updateSource, cleanValue=${cleanValue}, value=${value}`);
binding.originalUpdateSource(cleanValue);
}
binding.originalUpdateTarget = binding.updateTarget;
binding.updateTarget = value => {
let cardNumberBlocks = this.createCardNumberBlocks(value);
if (cardNumberBlocks) {
console.log("Returning " + cardNumberBlocks.join(" "))
binding.originalUpdateTarget(cardNumberBlocks.join(" "));
} else {
console.log("Returning nothing.")
binding.originalUpdateTarget("");
}
}
}
unbind(binding, source) {
binding.updateSource = binding.originalUpdateSource;
delete binding.originalUpdateSource;
binding.updateTarget = binding.originalUpdateTarget;
delete binding.originalUpdateTarget;
}
createCardNumberBlocks(value) {
if (!value) return "";
return value.match(/\d{1,4}/g);
}
}
export class CurrencyBindingBehavior {
caretPos;
bind(binding, source, lookupFunctions) {
const target = binding.target;
binding.originalUpdateSource = binding.updateSource;
binding.updateSource = value => {
this.caretPos = this.getCaretPosition(target);
console.log(` updateSource, caretPos=${this.caretPos}, value=${value}`);
const cleanValue = value.replace(/[^\d\.]/g, '');
binding.updateTarget(cleanValue);
console.log(`updateSource, cleanValue=${cleanValue}, value=${value}`);
binding.originalUpdateSource(cleanValue);
}
binding.originalUpdateTarget = binding.updateTarget;
binding.updateTarget = value => {
let currencyBlock = this.createCurrencyBlock(value);
if (currencyBlock) {
console.log("Returning " + currencyBlock)
binding.originalUpdateTarget(currencyBlock);
} else {
console.log("Returning nothing.")
binding.originalUpdateTarget("");
}
// Set caret position
target.selectionStart = this.caretPos;
}
}
unbind(binding, source) {
binding.updateSource = binding.originalUpdateSource;
delete binding.originalUpdateSource;
binding.updateTarget = binding.originalUpdateTarget;
delete binding.originalUpdateTarget;
}
getCaretPosition(target) {
return target.selectionStart;
}
createCurrencyBlock(value) {
let formatter = new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD',
minimumFractionDigits: 2,
});
if (!value) return "";
return formatter.format(value.toString().replace('$', ''));
}
}
export class DateBindingBehavior {
bind(binding, source, lookupFunctions) {
const target = binding.target;
// binding.originalUpdateSource = binding.updateSource;
// binding.updateSource = value => {
// console.log(`updateSource, value=${value}`);
// let valueString = '';
// if (value) {
// const date = Date.parse(value);
// if (date !== NaN) {
// valueString = new Date(date).toISOString();
// }
// }
// if (valueString) {
// console.log("updateSource Returning " + valueString)
// // binding.updateTarget(valueString);
// binding.originalUpdateSource(valueString);
// } else {
// console.log("updateSource Returning nothing.")
// binding.updateTarget("");
// }
// }
binding.originalUpdateTarget = binding.updateTarget;
binding.updateTarget = value => {
console.log(`updateTarget, value=${value}`);
let valueString = '';
const date = Date.parse(value);
if (value && date !== NaN) {
const dt = new Date(date);
const y = dt.getFullYear();
const m = dt.getMonth() + 1;
const d = dt.getDate();
valueString = `${y}-${m.toString().padStart(2, '0')}-${d.toString().padStart(2, '0')}`;
}
if (valueString) {
console.log("updateTarget Returning " + valueString)
binding.originalUpdateTarget(valueString);
} else {
console.log("updateTarget Returning nothing.")
binding.originalUpdateTarget("");
}
}
}
unbind(binding, source) {
binding.updateSource = binding.originalUpdateSource;
delete binding.originalUpdateSource;
binding.updateTarget = binding.originalUpdateTarget;
delete binding.originalUpdateTarget;
}
}
<template>
<input type="tel" value.bind="monthPart" minlength="0" maxlength="2" pattern="[0-9]{2}"> <input type="tel" value.bind="dayPart"> <input type="tel" value.bind="yearPart">
</template>
import {bindable} from 'aurelia-framework';
export class DatePickerCustomElement {
@bindable value;
@bindable monthPart;
@bindable dayPart;
@bindable yearPart;
bind(ctx) {
let valueString = '';
const date = Date.parse(this.value);
if (this.value && date !== NaN) {
const dt = new Date(date);
this.yearPart = dt.getFullYear();
this.monthPart = dt.getMonth() + 1;
this.dayPart = dt.getDate();
}
}
unbind() {
}
monthPartChanged(newValue, oldValue) {
console.log('monthPart', newValue);
}
dayPartChanged(newValue, oldValue) {
console.log('dayPart', newValue);
}
yearPartChanged(newValue, oldValue) {
console.log('yearPart', newValue);
}
}
<!doctype html>
<html>
<head>
<title>Aurelia</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body aurelia-app>
<h1>Loading...</h1>
<script src="https://cdn.rawgit.com/jdanyow/aurelia-bundle/v1.0.3/jspm_packages/system.js"></script>
<script src="https://cdn.rawgit.com/jdanyow/aurelia-bundle/v1.0.3/config.js"></script>
<script>
System.import('aurelia-bootstrapper');
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment