<!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>