<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.js"></script>
<script>var $j = jQuery.noConflict();</script>
<script src="https://polygit.org/components/webcomponentsjs/webcomponents-lite.js"></script>
<link rel="import" href="frevvo-date-time.html">
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.19.1/moment.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/flatpickr/dist/flatpickr.min.css">
<script src="https://cdn.jsdelivr.net/npm/flatpickr"></script>
<link rel="stylesheet" type="text/css" href="http://www.w3schools.com/lib/w3.css" />
</head>
<body>
<div class="w3-container w3-padding w3-border-top">
Testing of flatpickr wrapped in custom element:
<div>
<frevvo-date-time date="true" required="true"
placeholder="Enter a date value">
</frevvo-date-time>
</div>
<div>
<frevvo-date-time time="true" required="true"
placeholder="Enter a time value">
</frevvo-date-time>
</div>
<div>
<frevvo-date-time date-time="true" required="true"
placeholder="Enter a date/time value">
</frevvo-date-time>
</div>
</div>
<div class="w3-container w3-padding w3-border-top">
Raw Testing of flatpickr:
<div>
<label for="myDatePicker">Pick a date</label>
<input id="myDatePicker" placeholder="Pick a date">
</div>
<div>
<label for="myDateTimePicker">Pick a date/time</label>
<input id="myDateTimePicker" placeholder="Pick a date and time">
</div>
<div>
<label for="myTimePicker">Pick a time</label>
<input id="myTimePicker" placeholder="Pick a time">
</div>
<script>
$j(document).ready(function() {
flatpickr("#myDatePicker", {
"dateFormat":"n/j/Y",
"allowInput":true,
"onOpen": function(selectedDates, dateStr, instance) {
instance.setDate(instance.input.value, false);
}
});
flatpickr("#myDateTimePicker", {
"dateFormat":"n/j/Y H:i",
"enableTime":true,
"allowInput":true
});
flatpickr("#myTimePicker", {
"dateFormat":"H:i",
"enableTime":true,
"allowInput":true,
"noCalendar": true
});
});
</script>
<script>
// test moment
if (moment("12-02-1995", "MM-DD-YYYY", true).isValid())
console.log('moment date parse is ok');
else
console.log('moment date parse is invalid');
if (moment("1995-12-30T13:59:59+04:00", "YYYY-MM-DDTHH:mm:ssZ", true).isValid())
console.log('moment dateTime parse is ok');
else
console.log('moment dateTime parse is invalid');
</script>
</div>
</body>
</html>
<link rel="import" href="https://polygit.org/components/polymer/polymer-element.html">
<dom-module id="picture-frame">
<template>
<!-- scoped CSS for this element -->
<style>
div {
display: inline-block;
background-color: #ccc;
border-radius: 8px;
padding: 4px;
}
</style>
<!--
TODO: Try adding other HTML elements to the DOM template to see how they are positioned relative to the distributed child nodes.
-->
<div>
<!-- any children are rendered here -->
<slot></slot>
</div>
</template>
<script>
class PictureFrame extends Polymer.Element {
static get is() { return "picture-frame"; }
}
customElements.define(PictureFrame.is, PictureFrame);
</script>
</dom-module>
<link rel="import" href="https://polygit.org/components/polymer/polymer-element.html">
<dom-module id="frevvo-control-styles">
<template>
<style>
button, input, select, textarea {
font: inherit;
}
.fc-container{padding:0.01em 16px}
.fc-round-small{border-radius:2px}.fc-round,.fc-round-medium{border-radius:4px}
.fc-round-large{border-radius:8px}.fc-round-xlarge{border-radius:16px}
.fc-round-xxlarge{border-radius:32px}.fc-round-jumbo{border-radius:64px}
.fc-border-0{border:0}
.fc-border{border:1px solid #ccc!important}
.fc-border-top{border-top:1px solid #ccc}.fc-border-bottom{border-bottom:1px solid #ccc}
.fc-border-left{border-left:1px solid #ccc}.fc-border-right{border-right:1px solid #ccc}
.fc-margin{margin:16px}.fc-margin-0{margin:0}
.fc-margin-top{margin-top:16px}.fc-margin-bottom{margin-bottom:16px}
.fc-margin-left{margin-left:16px}.fc-margin-right{margin-right:16px}
.fc-section{margin-top:16px;margin-bottom:16px}
.fc-padding-tiny{padding:2px 4px}.fc-padding-small{padding:4px 8px}
.fc-padding-medium,.fc-padding,.fc-form{padding:8px 16px}
.fc-padding-large{padding:12px 24px}.fc-padding-xlarge{padding:16px 32px}
.fc-padding-xxlarge{padding:24px 48px}.fc-padding-jumbo{padding:32px 64px}
.fc-padding-4,.fc-padding-hor-4{padding-top:4px;padding-bottom:4px}
.fc-padding-8,.fc-padding-hor-8{padding-top:8px;padding-bottom:8px}
.fc-padding-12,.fc-padding-hor-12{padding-top:12px;padding-bottom:12px}
.fc-padding-16,.fc-padding-hor-16{padding-top:16px;padding-bottom:16px}
.fc-padding-24,.fc-padding-hor-24{padding-top:24px;padding-bottom:24px}
.fc-padding-32,.fc-padding-hor-32{padding-top:32px;padding-bottom:32px}
.fc-padding-48,.fc-padding-hor-48{padding-top:48px;padding-bottom:48px}
.fc-padding-64,.fc-padding-hor-64{padding-top:64px;padding-bottom:64px}
.fc-padding-128,.fc-padding-hor-128{padding-top:128px;padding-bottom:128px}
.fc-padding-0{padding:0}
.fc-padding-top{padding-top:8px}.fc-padding-bottom{padding-bottom:8px}
.fc-padding-left{padding-left:16px}.fc-padding-right{padding-right:16px}
.fc-tag{background-color:#000;color:#fff;display:inline-block;padding-left:8px;padding-right:8px;text-align:center}
.fc-amber,.fc-hover-amber:hover{color:#000!important;background-color:#ffc107!important}
.fc-aqua,.fc-hover-aqua:hover{color:#000!important;background-color:#00ffff!important}
.fc-blue,.fc-hover-blue:hover{color:#fff!important;background-color:#2196F3!important}
.fc-light-blue,.fc-hover-light-blue:hover{color:#000!important;background-color:#87CEEB!important}
.fc-brown,.fc-hover-brown:hover{color:#fff!important;background-color:#795548!important}
.fc-cyan,.fc-hover-cyan:hover{color:#000!important;background-color:#00bcd4!important}
.fc-blue-grey,.fc-hover-blue-grey:hover{color:#fff!important;background-color:#607d8b!important}
.fc-green,.fc-hover-green:hover{color:#fff!important;background-color:#4CAF50!important}
.fc-light-green,.fc-hover-light-green:hover{color:#000!important;background-color:#8bc34a!important}
.fc-indigo,.fc-hover-indigo:hover{color:#fff!important;background-color:#3f51b5!important}
.fc-khaki,.fc-hover-khaki:hover{color:#000!important;background-color:#f0e68c!important}
.fc-lime,.fc-hover-lime:hover{color:#000!important;background-color:#cddc39!important}
.fc-orange,.fc-hover-orange:hover{color:#000!important;background-color:#ff9800!important}
.fc-deep-orange,.fc-hover-deep-orange:hover{color:#fff!important;background-color:#ff5722!important}
.fc-pink,.fc-hover-pink:hover{color:#fff!important;background-color:#e91e63!important}
.fc-purple,.fc-hover-purple:hover{color:#fff!important;background-color:#9c27b0!important}
.fc-deep-purple,.fc-hover-deep-purple:hover{color:#fff!important;background-color:#673ab7!important}
.fc-red,.fc-hover-red:hover{color:#fff!important;background-color:#f44336!important}
.fc-sand,.fc-hover-sand:hover{color:#000!important;background-color:#fdf5e6!important}
.fc-teal,.fc-hover-teal:hover{color:#fff!important;background-color:#009688!important}
.fc-yellow,.fc-hover-yellow:hover{color:#000!important;background-color:#ffeb3b!important}
.fc-white,.fc-hover-white:hover{color:#000!important;background-color:#fff!important}
.fc-black,.fc-hover-black:hover{color:#fff!important;background-color:#000!important}
.fc-grey,.fc-hover-grey:hover{color:#000!important;background-color:#9e9e9e!important}
.fc-light-grey,.fc-hover-light-grey:hover{color:#000!important;background-color:#f1f1f1!important}
.fc-medium-grey,.fc-hover-medium-grey:hover{color:#fff!important;background-color:#777777!important}
.fc-dark-grey,.fc-hover-dark-grey:hover{color:#fff!important;background-color:#616161!important}
.fc-pale-red,.fc-hover-pale-red:hover{color:#000!important;background-color:#ffdddd!important}
.fc-pale-green,.fc-hover-pale-green:hover{color:#000!important;background-color:#ddffdd!important}
.fc-pale-yellow,.fc-hover-pale-yellow:hover{color:#000!important;background-color:#ffffcc!important}
.fc-pale-blue,.fc-hover-pale-blue:hover{color:#000!important;background-color:#ddffff!important}
.fc-text-amber,.fc-hover-text-amber:hover{color:#ffc107!important}
.fc-text-aqua,.fc-hover-text-aqua:hover{color:#00ffff!important}
.fc-text-blue,.fc-hover-text-blue:hover{color:#2196F3!important}
.fc-text-light-blue,.fc-hover-text-light-blue:hover{color:#87CEEB!important}
.fc-text-brown,.fc-hover-text-brown:hover{color:#795548!important}
.fc-text-cyan,.fc-hover-text-cyan:hover{color:#00bcd4!important}
.fc-text-blue-grey,.fc-hover-text-blue-grey:hover{color:#607d8b!important}
.fc-text-green,.fc-hover-text-green:hover{color:#4CAF50!important}
.fc-text-light-green,.fc-hover-text-light-green:hover{color:#8bc34a!important}
.fc-text-indigo,.fc-hover-text-indigo:hover{color:#3f51b5!important}
.fc-text-khaki,.fc-hover-text-khaki:hover{color:#b4aa50!important}
.fc-text-lime,.fc-hover-text-lime:hover{color:#cddc39!important}
.fc-text-orange,.fc-hover-text-orange:hover{color:#ff9800!important}
.fc-text-deep-orange,.fc-hover-text-deep-orange:hover{color:#ff5722!important}
.fc-text-pink,.fc-hover-text-pink:hover{color:#e91e63!important}
.fc-text-purple,.fc-hover-text-purple:hover{color:#9c27b0!important}
.fc-text-deep-purple,.fc-hover-text-deep-purple:hover{color:#673ab7!important}
.fc-text-red,.fc-hover-text-red:hover{color:#f44336!important}
.fc-text-sand,.fc-hover-text-sand:hover{color:#fdf5e6!important}
.fc-text-teal,.fc-hover-text-teal:hover{color:#009688!important}
.fc-text-yellow,.fc-hover-text-yellow:hover{color:#d2be0e!important}
.fc-text-white,.fc-hover-text-white:hover{color:#fff!important}
.fc-text-black,.fc-hover-text-black:hover{color:#000!important}
.fc-text-grey,.fc-hover-text-grey:hover{color:#757575!important}
.fc-text-medium-grey,.fc-hover-text-medium-grey:hover{color:#777777!important}
.fc-text-light-grey,.fc-hover-text-light-grey:hover{color:#f1f1f1!important}
.fc-text-dark-grey,.fc-hover-text-dark-grey:hover{color:#3a3a3a!important}
.fc-border-amber,.fc-hover-border-amber:hover{border-color:#ffc107!important}
.fc-border-aqua,.fc-hover-border-aqua:hover{border-color:#00ffff!important}
.fc-border-blue,.fc-hover-border-blue:hover{border-color:#2196F3!important}
.fc-border-light-blue,.fc-hover-border-light-blue:hover{border-color:#87CEEB!important}
.fc-border-brown,.fc-hover-border-brown:hover{border-color:#795548!important}
.fc-border-cyan,.fc-hover-border-cyan:hover{border-color:#00bcd4!important}
.fc-border-blue-grey,.fc-hover-blue-grey:hover{border-color:#607d8b!important}
.fc-border-green,.fc-hover-border-green:hover{border-color:#4CAF50!important}
.fc-border-light-green,.fc-hover-border-light-green:hover{border-color:#8bc34a!important}
.fc-border-indigo,.fc-hover-border-indigo:hover{border-color:#3f51b5!important}
.fc-border-khaki,.fc-hover-border-khaki:hover{border-color:#f0e68c!important}
.fc-border-lime,.fc-hover-border-lime:hover{border-color:#cddc39!important}
.fc-border-orange,.fc-hover-border-orange:hover{border-color:#ff9800!important}
.fc-border-deep-orange,.fc-hover-border-deep-orange:hover{border-color:#ff5722!important}
.fc-border-pink,.fc-hover-border-pink:hover{border-color:#e91e63!important}
.fc-border-purple,.fc-hover-border-purple:hover{border-color:#9c27b0!important}
.fc-border-deep-purple,.fc-hover-border-deep-purple:hover{border-color:#673ab7!important}
.fc-border-red,.fc-hover-border-red:hover{border-color:#f44336!important}
.fc-border-sand,.fc-hover-border-sand:hover{border-color:#fdf5e6!important}
.fc-border-teal,.fc-hover-border-teal:hover{border-color:#009688!important}
.fc-border-yellow,.fc-hover-border-yellow:hover{border-color:#ffeb3b!important}
.fc-border-white,.fc-hover-border-white:hover{border-color:#fff!important}
.fc-border-black,.fc-hover-border-black:hover{border-color:#000!important}
.fc-border-grey,.fc-hover-border-grey:hover{border-color:#9e9e9e!important}
.fc-border-light-grey,.fc-hover-border-light-grey:hover{border-color:#f1f1f1!important}
.fc-border-medium-grey,.fc-hover-border-medium-grey:hover{border-color:#777777!important}
.fc-border-dark-grey,.fc-hover-border-dark-grey:hover{border-color:#616161!important}
.fc-border-pale-red,.fc-hover-border-pale-red:hover{border-color:#ffe7e7!important}.fc-border-pale-green,.fc-hover-border-pale-green:hover{border-color:#e7ffe7!important}
.fc-border-pale-yellow,.fc-hover-border-pale-yellow:hover{border-color:#ffffd7!important}.fc-border-pale-blue,.fc-hover-border-pale-blue:hover{border-color:#e7ffff!important}
.fc-left{float:left}
.fc-right{float:right}
.fc-hide{display:none!important}
.fc-show-block,.fc-show{display:block!important}
.fc-show-inline-block{display:inline-block!important}
.fc-btn,.fc-btn-block{border:none;display:inline-block;outline:0;padding:6px 16px;vertical-align:middle;overflow:hidden;text-decoration:none!important;color:#fff;background-color:#000;text-align:center;cursor:pointer;white-space:nowrap}
.fc-disabled,.fc-btn:disabled,.fc-btn-floating:disabled,.fc-btn-floating-large:disabled{cursor:not-allowed;opacity:0.3}
.fc-btn.fc-disabled *,.fc-btn-block.fc-disabled,.fc-btn-floating.fc-disabled *,.fc-btn:disabled *,.fc-btn-floating:disabled *{pointer-events:none}
.fc-btn.fc-disabled:hover,.fc-btn-block.fc-disabled:hover,.fc-btn:disabled:hover,.fc-btn-floating.fc-disabled:hover,.fc-btn-floating:disabled:hover,
.fc-btn-floating-large.fc-disabled:hover,.fc-btn-floating-large:disabled:hover{box-shadow:none}
.fc-btn:hover,.fc-btn-block:hover,.fc-btn-floating:hover,.fc-btn-floating-large:hover{box-shadow:0 8px 16px 0 rgba(0,0,0,0.2),0 6px 20px 0 rgba(0,0,0,0.19)}
.fc-btn-block{width:100%}
.fc-btn,.fc-btn-floating,.fc-btn-floating-large{-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}
.fc-btn-floating,.fc-btn-floating-large{display:inline-block;text-align:center;color:#fff;background-color:#000;position:relative;overflow:hidden;z-index:1;padding:0;border-radius:50%;cursor:pointer;font-size:24px}
.fc-btn-floating{width:40px;height:40px;line-height:40px}
.fc-btn-floating-large{width:56px;height:56px;line-height:56px}
.fc-btn,.fc-btn-floating,.fc-btn-floating-large,.fc-btn-block{-webkit-transition:background-color .3s,color .15s,box-shadow .3s,opacity 0.3s;transition:background-color .3s,color .15s,box-shadow .3s,opacity 0.3s}
.clearfix {
/*overflow: auto;*/
}
.clearfix:after {
content: ".";
/* the period is placed on the page as the last thing before the div closes */
display: block;
/* inline elements don't respond to the clear property */
height: 0; /* ensure the period is not visible */
clear: both; /* make the container clear the period */
visibility: hidden; /* further ensures the period is not visible */
}
/* the following select cause error in FF and its absence does not seems to cause
any side effect */
.clearfix {
display: inline-block;
}
.clearfix {
display: block;
}
/* With Polymer 2, needed to do this??? */
[hidden] {
display: none!important;
}
</style>
</template>
</dom-module>
<link rel="import" href="https://polygit.org/components/polymer/polymer.html">
<link rel="import" href="https://polygit.org/components/iron-input/iron-input.html">
<link rel="import" href="https://polygit.org/components/iron-icons/iron-icons.html">
<link rel="import" href="frevvo-control-styles.html">
<link rel="import" href="frevvo-validatable-behavior.html">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.js"></script>
<script> var jq = jQuery.noConflict();</script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/flatpickr/dist/flatpickr.min.css">
<script src="https://cdn.jsdelivr.net/npm/flatpickr"></script>
<link rel="import" href="frevvo-date-behavior.html">
<link rel="import" href="frevvo-time-behavior.html">
<link rel="import" href="frevvo-date-time-behavior.html">
<!--
'<frevvo-date-time>' is the input element to use for date, date-time and time input fields. It has three behaviors:
date, date-time and time that add the appropriate input masking, picker and validation for each type. '<frevvo-date-time>' must
be set with appropriate boolean attribute (date, date-time and time) in order to enable the appropriate behavior.
-->
<dom-module id="frevvo-date-time">
<template>
<style include="frevvo-control-styles"></style>
<style>
:host {
display: inline-block;
}
:host[invalid] {
color:#000!important;
background-color:#ffffcc!important;
}
/* Multiple selectors here to get it working right on IE */
#frevvoInputWrapper:not([data-valid]), .frevvoInput:not([data-valid]) {
color:#000!important;
background-color:#ffffcc!important;
}
#frevvoInputWrapper {
padding-left: 1px;
padding-right: 1px;
position: relative;
}
.frevvoInput, #frevvoIronInput {
border: none;
width: 100%;
-webkit-box-sizing: border-box; /* Safari/Chrome, other WebKit */
-moz-box-sizing: border-box; /* Firefox, other Gecko */
box-sizing: border-box;
background-color: inherit;
}
#frevvoInputWrapper ::slotted(input) {
visibility: hidden;
position: absolute;
top:0;
left: 0;
width: 100%;
height: 100%;
border: none;
padding: 0;
}
#frevvo-picker {
cursor: pointer;
position: absolute;
right: 1px;
top: 4px;
}
#frevvo-validation-error {
position: absolute;
right: 24px;
top: 4px;
}
/* With shadow DOM, hidden does not seem to work in local dom?? */
.frevvoIcon[hidden] {
display: none;
}
</style>
<frevvo-date-validator date-format="[[dateFormat]]"></frevvo-date-validator>
<frevvo-date-time-validator date-time-format="[[dateTimeFormat]]"></frevvo-date-time-validator>
<frevvo-time-validator time-format="[[timeFormat]]"></frevvo-time-validator>
<div id="frevvoInputWrapper" class="fc-border fc-round clearfix" data-valid$="[[valid]]">
<iron-input id="frevvoIronInput" bind-value="{{displayValue}}">
<input value="{{displayValue::input}}"
class="frevvoInput fc-padding-small"
on-change="_onChange" data-valid$="[[valid]]"
allowed-pattern="[[pattern]]" prevent-invalid-input="[[preventInvalidInput]]"
placeholder$="[[placeholder]]"/>
</iron-input>
<slot id="inputSlot"></slot>
<iron-icon id="frevvo-picker" on-tap="_onPickerActivate"
class="fc-text-grey" icon="[[pickerIcon]]"></iron-icon>
<iron-icon id="frevvo-validation-error" hidden$="[[!error]]"
class="frevvoIcon fc-text-red" icon="icons:warning"></iron-icon>
</div>
</template>
<script>
Polymer({
is: "frevvo-date-time",
properties: {
/**
* The value of the control.
*/
value: {
type: String,
value: '',
notify: true,
observer: '_onValueChanged'
},
/**
* The displayed value of the control (user input).
*/
displayValue: {
type: String,
value: '',
notify: true,
observer: '_onDisplayValueChanged'
},
/**
* Placeholer text displayed until a selection is made.
*/
placeholder: String,
},
behaviors: [_frevvo.behaviors.FrevvoValidatableBehavior,
_frevvo.behaviors.FrevvoDateBehavior,
_frevvo.behaviors.FrevvoDateTimeBehavior,
_frevvo.behaviors.FrevvoTimeBehavior],
_onChange: function() {
if (!this.validate(this.displayValue))
this.value = '';
this.dispatchEvent(new CustomEvent('frevvo-input-change', { bubbles: true, composed: true, "detail":{"value": this.value} }));
},
_onValueChanged: function(newValue, oldValue) {
// input behavior should override
//console.log('frevvo-date-time _onValueChanged - Should NOT see this.');
},
_onDisplayValueChanged: function(newDisplayValue, oldDisplayValue) {
// input behavior should override
//console.log('frevvo-date-time _onDisplayValueChanged - Should NOT see this.');
},
_onPickerActivate: function(e) {
// input behavior should override
},
attached: function() {
this.isAttached = true;
},
detached: function() {
}
});
</script>
</dom-module>
<link rel="import" href="https://polygit.org/components/polymer/polymer.html">
<link rel="import" href="https://polygit.org/components/iron-validatable-behavior/iron-validatable-behavior.html">
<script>
/**
* `Use _frevvo.behaviors.FrevvoValidatableBehavior` to implement an element that validates user input and supports the required property.
* Use the related `Polymer.IronValidatorBehavior` to add custom validation logic to an element.
*
* NOTE: The main purpose of this extension of Polymer.IronValidatableBehavior is to add a valid property for backwards compatibility
* with the standard frevvo control design and also support for a required property.
* Polymer.IronValidatableBehavior itself adds the invalid property support.
*
*/
window._frevvo = window._frevvo || {};
window._frevvo.behaviors = window._frevvo.behaviors || {};
_frevvo.behaviors.FrevvoValidatableBehaviorImpl = {
properties: {
/**
* True if the last call to `validate` is valid.
*/
valid: {
notify: true,
reflectToAttribute: true,
type: Boolean,
value: true
},
/**
* Is the value in error (did not parse)
*/
error: {
readOnly: true,
reflectToAttribute: true,
type: Boolean,
value: false
},
/**
* Makes the control required, i.e. must have a value.
*/
required: {
notify: true,
reflectToAttribute: true,
type: Boolean,
value: false
}
},
observers: [
'_validChanged(valid)'
],
_invalidChanged: function() {
if (!this.internalChange) {
this.internalChange = true;
try { this.valid = !this.invalid;}
finally {this.internalChange = false;}
if (this.invalid) {
this.setAttribute('aria-invalid', 'true');
} else {
this.removeAttribute('aria-invalid');
}
}
},
_validChanged: function() {
if (!this.internalChange) {
this.internalChange = true;
try { this.invalid = !this.valid;}
finally {this.internalChange = false;}
if (!this.valid) {
this.setAttribute('aria-invalid', 'true');
} else {
this.removeAttribute('aria-invalid');
}
}
},
/**
* Returns true if `value` is valid. By default, it is passed
* to the validator's `validate()` function, if a validator is set. You
* should override this method if you want to implement custom validity
* logic for your element. Also supports the required property if set, so if
* empty and required then the element is invalid.
*
* @param {Object} value The value to be validated.
* @return {boolean} True if `value` is valid.
*/
_getValidity: function(value) {
if (this.required) {
if (!value && value !== 0) { // what about booleans here?
this.invalid = true;
this._setError(false);
return !this.invalid;
}
}
if (this.hasValidator()) {
var isValid = this._validator.validate(value);
this._setError(!isValid);
return isValid;
}
this._setError(false);
return true;
},
attached: function() {
this._getValidity(this.displayValue);
}
};
// Define the behavior
_frevvo.behaviors.FrevvoValidatableBehavior = [ Polymer.IronValidatableBehavior, _frevvo.behaviors.FrevvoValidatableBehaviorImpl ]
</script>
<link rel="import" href="https://polygit.org/components/iron-validatable-behavior/iron-validatable-behavior.html">
<link rel="import" href="https://polygit.org/components/iron-validator-behavior/iron-validator-behavior.html">
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.19.1/moment.js"></script>
<!--
'_frevvo.behaviors.FrevvoDateBehavior' adds date input masking, a date picker and date input validation for the
'<frevvo-date-time>' custom element. This behavior should only be used in conjunction with '<frevvo-date-time>'.
-->
<script>
window._frevvo = window._frevvo || {};
window._frevvo.behaviors = window._frevvo.behaviors || {};
_frevvo.behaviors.FrevvoDateBehavior = {
properties: {
/**
* Set true to force date type input amd validation behavior.
*/
date: {
type: Boolean,
value: false
},
/**
* The format to use for date formatting and validation.
* See: [moment.js formatting options.](https://momentjs.com/docs/#/parsing/string-format/)
*/
dateFormat: {
type: String,
value: 'M/D/YYYY'
},
/**
* The format to use for picker display.
* See: [flatpickr formatting options.](https://chmln.github.io/flatpickr/formatting/#date-formatting-tokens)
*/
pickerFormat: {
type: String
}
},
_ISOFormat: 'YYYY-MM-DD', // 4-digit year (moment.js)
ready: function() {
if (this.date) {
this.pickerFormat = 'n/j/Y';
this._picker = function() {
return jq(Polymer.FlattenedNodesObserver.getFlattenedNodes(this.shadowRoot)).find('.frevvoInput')[0]._flatpickr;
};
this._fixPickerMonthDate = function(instance) {
// HACK HACk HACK
// There is css shim bug on firefox and edge that messes up flatpickr's month and year. Force a fix. UGLY!
//instance.currentYearElement.nextElementSibling.value = instance.currentYear
jq(instance.currentYearElement.parentElement).find('.cur-year').val(instance.currentYear);
jq(instance.currentMonthElement.parentElement).contents().filter(function(){return this.nodeType == 3;}).remove(); // remove extra text
};
var input = jq(Polymer.FlattenedNodesObserver.getFlattenedNodes(this.shadowRoot)).find('.frevvoInput')[0];
flatpickr(input, {
"dateFormat":this.pickerFormat,
"allowInput":true,
"onOpen": function(selectedDates, dateStr, instance) {
instance.setDate(this.displayValue, false);
this._fixPickerMonthDate(instance);
}.bind(this),
onChange: function(selectedDates, dateStr, instance) {
this.displayValue = dateStr;
this._onChange && this._onChange();
}.bind(this),
onMonthChange: function(selectedDates, dateStr, instance) {
this._fixPickerMonthDate(instance);
}.bind(this),
onYearChange: function(selectedDates, dateStr, instance) {
this._fixPickerMonthDate(instance);
}.bind(this)
});
this._onDisplayValueChanged = function(newDisplayValue, oldDisplayValue) {
//console.log('_onDateDisplayValueChanged called')
// parse it and set value
// parse it with the format and if that fails, try the ISO format
if (!this.internalChange) {
var date;
try {
date = moment(Array.isArray(newDisplayValue) ? newDisplayValue.join('') : newDisplayValue, this.dateFormat, true);
if (date.isValid()) {
this.__setValue(date);
return;
}
}
catch (e) {}
try {
date = moment(Array.isArray(newDisplayValue) ? newDisplayValue.join('') : newDisplayValue, this._ISOFormat, true);
if (date.isValid())
this.__setValue(date);
}
catch (e) {}
}
};
this.__setValue = function(date) {
this.internalChange = true;
try { this.value = moment(date).format(this._ISOFormat); }
finally { this.internalChange = false; }
};
this._onValueChanged = function(newValue, oldValue) {
//console.log('_onDateValueChanged called')
if (!this.internalChange) {
// parse it and set display value
// value is always in 'yyyy-mm-dd' ISO format
try {
var date = null;
if (newValue)
date = moment(Array.isArray(newValue) ? newValue.join('') : newValue, this._ISOFormat, true);
this.internalChange = true;
try {
if (date != null && date.isValid())
this.displayValue = moment(date).format(this.dateFormat);
else
this.displayValue = "";
// unfortunately will be parsing yet again on the validate but need to do it to get ui state correct
this.validate(this.displayValue);
}
finally { this.internalChange = false; }
}
catch (e) {}
}
};
this.validator = "frevvo-date-validator";
this.pickerIcon = "icons:date-range";
this._onPickerActivate = function(e) {
this._picker().open();
};
if (this.value) {
// need to force an initial set because the property could have been set before the listener was in place
this._onValueChanged(this.value);
}
}
}
}
/**
* 'frevvo-date-validator' is the date validator to be used in conjunction with the '<frevvo-date-time>' custom element.
*/
Polymer({
is: "frevvo-date-validator",
properties: {
dateFormat: {
type: String,
value: 'M/D/YYYY'
}
},
behaviors: [
Polymer.IronValidatorBehavior
],
_ISODateFormat: 'YYYY-M-D', // 4-digit year
validate: function(values) {
//console.log('validator called')
// parse it with the format and if that fails, try the ISO format
try {
if (moment(Array.isArray(values) ? values.join('') : values, this.dateFormat, true).isValid())
return true;
}
catch (e) {
}
try {
return moment(Array.isArray(values) ? values.join('') : values, this._ISODateFormat, true).isValid();
}
catch (e) {
return false;
}
}
});
</script>
<link rel="import" href="https://polygit.org/components/iron-validatable-behavior/iron-validatable-behavior.html">
<link rel="import" href="https://polygit.org/components/iron-validator-behavior/iron-validator-behavior.html">
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.19.1/moment.js"></script>
<!--
'_frevvo.behaviors.FrevvoTimeBehavior' adds time input masking, a time picker and time input validation for the
'<frevvo-date-time>' custom element. This behavior should only be used in conjunction with '<frevvo-date-time>'.
-->
<script>
window._frevvo = window._frevvo || {};
window._frevvo.behaviors = window._frevvo.behaviors || {};
_frevvo.behaviors.FrevvoTimeBehavior = {
properties: {
/**
* Set true to force time type input amd validation behavior.
*/
time: {
type: Boolean,
value: false
},
/**
* The format to use for validation.
* See: [moment.js formatting options.](https://momentjs.com/docs/#/parsing/string-format/)
*
*/
timeFormat: {
type: String,
value: 'H:m'
},
/**
* The format to use for picker display.
* See: [flatpickr formatting options.](https://chmln.github.io/flatpickr/formatting/#date-formatting-tokens)
*/
pickerFormat: {
type: String
}
},
_ISOTimeFormat: 'HH:mm:ss', // 24-hour
ready: function() {
if (this.time) {
this.pickerFormat = 'H:i';
this._fixPicker = function(instance) {
// HACK HACk HACK
// There is css shim bug on firefox and edge that messes up flatpickr's month and year and hour/minute. Force a fix. UGLY!
var hr = 12, min = 0;
if (this.value) {
var timeObj = moment(this.value, this._ISOTimeFormat);
if (timeObj.isValid()) {
if (instance.config.time_24hr)
hr = moment(timeObj).format("H");
else
hr = moment(timeObj).format("h");
min = moment(timeObj).format("m");
}
}
var hrEl = jq(instance.calendarContainer).find('.flatpickr-hour');
if (hrEl.val().length == 0 || hrEl.val() != hr)
hrEl.val(hr);
var minEl = jq(instance.calendarContainer).find('.flatpickr-minute');
if (minEl.val().length == 0 || minEl.val() != min)
minEl.val(min);
};
var input = jq(Polymer.FlattenedNodesObserver.getFlattenedNodes(this.shadowRoot)).find('.frevvoInput')[0];
flatpickr(input, {
"dateFormat":this.pickerFormat,
"enableTime":true,
"time_24hr": true,
"noCalendar": true,
"allowInput":true,
"onOpen": function(selectedDates, dateStr, instance) {
instance.setDate(this.displayValue, false);
this._fixPicker(instance);
}.bind(this),
onChange: function(selectedDates, dateStr, instance) {
//console.log("onChange " + dateStr);
this.displayValue = dateStr;
this._onChange && this._onChange();
this._fixPicker(instance);
}.bind(this)
});
this._onDisplayValueChanged = function(newDisplayValue, oldDisplayValue) {
// parse it and set value
// parse it with the format and if that fails, try the ISO format
if (!this.internalChange) {
var timeObj;
try {
timeObj = moment(Array.isArray(newDisplayValue) ? newDisplayValue.join('') : newDisplayValue, this.timeFormat, true);
if (timeObj.isValid()) {
this.__setValue(timeObj);
}
else {
timeObj = moment(Array.isArray(newDisplayValue) ? newDisplayValue.join('') : newDisplayValue, this._ISOTimeFormat, true);
if (timeObj.isValid())
this.__setValue(timeObj);
}
}
catch (e) {}
}
};
this.__setValue = function(timeObj) {
this.internalChange = true;
try {
this.value = moment(timeObj).format(this._ISOTimeFormat);
}
finally { this.internalChange = false; }
};
this._onValueChanged = function(newValue, oldValue) {
// time
if (!this.internalChange) {
// parse it and set display value
// value is always in ISO format
try {
var timeObj = null;
if (newValue)
timeObj = moment(Array.isArray(newValue) ? newValue.join('') : newValue, this._ISOTimeFormat, true);
this.internalChange = true;
try {
if (timeObj)
this.displayValue = moment(timeObj).format(this.timeFormat);
else
this.displayValue = '';
// unfortunately will be parsing yet again on the validate but need to do it to get ui state correct
this.validate(this.displayValue);
}
finally { this.internalChange = false; }
}
catch (e) {}
}
};
this.validator = "frevvo-time-validator";
this.pickerIcon = "icons:watch-later";
this._onPickerActivate = function(e) {
jq(Polymer.FlattenedNodesObserver.getFlattenedNodes(this.shadowRoot)).find('.frevvoInput')[0]._flatpickr.open();
};
if (this.value) {
// need to force an initial set because the property could have been set before the listener was in place
this._onValueChanged(this.value);
}
}
}
}
/**
* 'frevvo-time-validator' is the time validator to be used in conjunction with the '<frevvo-date-time>' custom element.
*/
Polymer({
is: "frevvo-time-validator",
properties: {
timeFormat: {
type: String,
value: 'H:m'
}
},
behaviors: [
Polymer.IronValidatorBehavior
],
_ISOTimeFormat: 'H:m:s', // 24-hour
validate: function(values) {
//console.log('validator called')
// parse it with the format and if that fails, try the ISO format
try {
// Returns a time object if successful, false otherwise
if (moment(Array.isArray(values) ? values.join('') : values, this.timeFormat, true).isValid())
return true;
}
catch (e) {}
try {
return moment(Array.isArray(values) ? values.join('') : values, this._ISOTimeFormat, true).isValid();
}
catch (e) {}
return false;
}
});
</script>
<link rel="import" href="https://polygit.org/components/iron-validatable-behavior/iron-validatable-behavior.html">
<link rel="import" href="https://polygit.org/components/iron-validator-behavior/iron-validator-behavior.html">
<!--
'_frevvo.behaviors.FrevvoDateTimeBehavior' adds dateTime input masking, a date&time picker and dateTime input validation for the
'<frevvo-date-time>' custom element. This behavior should only be used in conjunction with '<frevvo-date-time>'.
-->
<script>
window._frevvo = window._frevvo || {};
window._frevvo.behaviors = window._frevvo.behaviors || {};
_frevvo.behaviors.FrevvoDateTimeBehavior = {
properties: {
/**
* Set true to force date/time type input amd validation behavior.
*/
dateTime: {
type: Boolean,
value: false
},
/**
* The format to use for user date & time entry and validation.
* See: [moment.js formatting options.](https://momentjs.com/docs/#/parsing/string-format/)
*/
dateTimeFormat: {
type: String,
value: 'M/D/YYYY H:m'
},
/**
* The format to use for picker display.
* See: [flatpickr formatting options.](https://chmln.github.io/flatpickr/formatting/#date-formatting-tokens)
*/
pickerFormat: {
type: String
}
},
_getTimeObj: function(date) {
var offset = date.getTimezoneOffset();
var offsetHr = offset/60;
var offsetMin = offset/60;
var offsetStr = offset>=0?'+':'-';
offsetStr += (offsetHr<10?'0':'') + offsetHr + (offsetMin<10?'0':'') + offsetMin;
return {
hour: date.getHours(),
minute: date.getMinutes(),
second: date.getSeconds(),
timezone: offsetStr
};
},
ready: function() {
if (this.dateTime) {
this._ISODateTimeFormat = 'YYYY-MM-DDTHH:mm:ssZ'; // 4-digit year
this.pickerFormat = 'n/j/Y H:i';
this._fixPicker = function(instance) {
// HACK HACk HACK
// There is css shim bug on firefox and edge that messes up flatpickr's month and year and hour/minute. Force a fix. UGLY!
var hr = 12, min = 0;
if (this.value) {
var timeObj = moment(this.value, this._ISODateTimeFormat);
if (timeObj.isValid()) {
if (instance.config.time_24hr)
hr = moment(timeObj).format("H");
else
hr = moment(timeObj).format("h");
min = moment(timeObj).format("m");
}
}
var hrEl = jq(instance.calendarContainer).find('.flatpickr-hour');
if (hrEl.val().length == 0 || hrEl.val() != hr)
hrEl.val(hr);
var minEl = jq(instance.calendarContainer).find('.flatpickr-minute');
if (minEl.val().length == 0 || minEl.val() != min)
minEl.val(min);
jq(instance.currentYearElement.parentElement).find('.cur-year').val(instance.currentYear);
jq(instance.currentMonthElement.parentElement).contents().filter(function(){return this.nodeType == 3;}).remove(); // remove extra text
};
var input = jq(Polymer.FlattenedNodesObserver.getFlattenedNodes(this.shadowRoot)).find('.frevvoInput')[0];
flatpickr(input, {
"dateFormat":this.pickerFormat,
"enableTime":true,
"time_24hr": true,
"allowInput":true,
"onOpen": function(selectedDates, dateStr, instance) {
instance.setDate(this.displayValue, false);
this._fixPicker(instance);
}.bind(this),
onChange: function(selectedDates, dateStr, instance) {
this.displayValue = dateStr;
this._onChange && this._onChange();
this._fixPicker(instance);
}.bind(this),
onMonthChange: function(selectedDates, dateStr, instance) {
this._fixPicker(instance);
}.bind(this),
onYearChange: function(selectedDates, dateStr, instance) {
this._fixPicker(instance);
}.bind(this)
});
this._onDisplayValueChanged = function(newDisplayValue, oldDisplayValue) {
//console.log('_onDateDisplayValueChanged called')
// parse it and set value
// parse it with the format and if that fails, try the ISO format
if (!this.internalChange) {
var dateTimeObj;
try {
dateTimeObj = moment(Array.isArray(newDisplayValue) ? newDisplayValue.join('') : newDisplayValue, this.dateTimeFormat, true);
if (dateTimeObj.isValid()) {
this.__setValue(dateTimeObj);
return;
}
}
catch (e) {}
try {
dateTimeObj = moment(Array.isArray(newDisplayValue) ? newDisplayValue.join('') : newDisplayValue, this._ISODateTimeFormat, true);
if (dateTimeObj.isValid())
this.__setValue(dateTimeObj);
}
catch (e) {}
}
};
this.__setValue = function(date) {
this.internalChange = true;
try { this.value = moment(date).format(this._ISODateTimeFormat); }
finally { this.internalChange = false; }
};
this._onValueChanged = function(newValue, oldValue) {
//console.log('_onDateValueChanged called')
if (!this.internalChange) {
// value is always in 'yyyy-mm-ddTHH:mm:ssZ' ISO format
try {
var date = null;
if (newValue)
date = moment(Array.isArray(newValue) ? newValue.join('') : newValue, this._ISODateTimeFormat, true);
this.internalChange = true;
try {
if (date != null && date.isValid())
this.displayValue = moment(date).format(this.dateFormat);
else
this.displayValue = "";
// unfortunately will be parsing yet again on the validate but need to do it to get ui state correct
this.validate(this.displayValue);
}
finally { this.internalChange = false; }
}
catch (e) {}
}
};
this.validator = "frevvo-date-time-validator";
this.pickerIcon = "icons:today";
this._onPickerActivate = function(e) {
jq(Polymer.FlattenedNodesObserver.getFlattenedNodes(this.shadowRoot)).find('.frevvoInput')[0]._flatpickr.open();
};
if (this.value) {
// need to force an initial set because the property could have been set before the listener was in place
this._onValueChanged(this.value);
}
}
}
}
/**
* 'frevvo-date-time-validator' is the date & time validator to be used in conjunction with the '<frevvo-date-time>' custom element.
*/
Polymer({
is: "frevvo-date-time-validator",
properties: {
dateTimeFormat: {
type: String,
value: 'M/D/YYYY H:m'
}
},
behaviors: [
Polymer.IronValidatorBehavior
],
_ISODateTimeFormat: 'YYYY-MM-DDTHH:mm:ssZ', // 4-digit year
validate: function(values) {
//console.log('validator called')
// parse it with the format and if that fails, try the ISO format
try {
if (moment(Array.isArray(values) ? values.join('') : values, this.dateTimeFormat, true).isValid())
return true;
}
catch (e) {
}
try {
return moment(Array.isArray(values) ? values.join('') : values, this._ISODateTimeFormat, true).isValid();
}
catch (e) {
return false;
}
}
});
</script>