<link rel="import" href="../polymer/polymer.html"> <link rel="import" href="../iron-media-query/iron-media-query.html"> <link rel="import" href="../neon-animation/neon-animated-pages.html"> <link rel="import" href="../neon-animation/neon-animatable.html"> <link rel="import" href="../neon-animation/animations/fade-in-animation.html"> <link rel="import" href="../neon-animation/animations/fade-out-animation.html"> <link rel="import" href="../iron-resizable-behavior/iron-resizable-behavior.html"> <link rel="import" href="../iron-selector/iron-selector.html"> <link rel="import" href="../iron-flex-layout/iron-flex-layout.html"> <link rel="import" href="../paper-styles/paper-styles.html"> <link rel="import" href="../moment-element/moment-with-locales-import.html"> <link rel="import" href="paper-calendar.html"> <link rel="import" href="paper-date-picker-dialog-style.html"> <link rel="import" href="paper-year-list.html"> <!-- Material Design [Pickers](http://www.google.com/design/spec/components/pickers.html) Provides a responsive date picker based on the material design spec. ## Examples: Default picker: <paper-date-picker></paper-date-picker> Setting the initial date to April 20, 2015: <paper-date-picker date="April 20, 2015"></paper-date-picker> You may also specify a minimum and/or maximum date allowed in this picker using the same date notation: <paper-date-picker min-date="April 1, 2015" max-date="June 30, 2015"></paper-date-picker> If you include this element as part of `paper-dialog`, use the class `"paper-date-picker-dialog"` on the dialog element in order to give it proper styling: <paper-dialog id="dialog" class="paper-date-picker-dialog" modal on-iron-overlay-closed="dismissDialog"> <paper-date-picker id="picker" date="[[date]]"></paper-date-picker> <div class="buttons"> <paper-button dialog-dismiss>Cancel</paper-button> <paper-button dialog-confirm>OK</paper-button> </div> </paper-dialog> @element paper-date-picker @blurb Provides a responsive date picker based on the material design spec. @homepage http://bendavis78.github.io/paper-date-picker/ @demo demo/index.html --> <style is="custom-style" include="paper-date-picker-dialog-style"> /* includes dialog style at document-level for backward compatibility */ </style> <dom-module id="paper-date-picker"> <template> <style> :host { -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; display: inline-block; color: var(--primary-text-color); @apply(--paper-font-body1); @apply(--paper-date-picker); } /** Landscape ******************/ #datePicker { width: 512px; height: 248px; @apply(--layout-horizontal); } #heading { width: 168px; @apply(--paper-date-picker-heading); } /** Narrow *********************/ :host([narrow]) #datePicker { width: 328px; height: 428px; @apply(--layout-vertical); } :host([narrow]) #heading { width: auto; height: 96px; padding: 16px 24px; } /** Heading ********************/ #heading { padding: 16px; box-sizing: border-box; color: var(--text-primary-color); background: var(--default-primary-color); @apply(--layout-vertical); @apply(--layout-around-justfied); } #heading .date, #heading .year { cursor: pointer; } #heading .date { @apply(--paper-font-display1); font-weight: bold; margin-top: 2px; @apply(--paper-date-picker-heading-date); } #heading div.date { letter-spacing: 0.025em; } #heading .date span { white-space: nowrap; } #heading .year { @apply(--paper-font-body2); font-size: 16px; @apply(--paper-date-picker-heading-date); } #heading:not(.pg-chooseYear) .year, #heading.pg-chooseYear .date { color: var(--light-primary-color); } /** Calendar/Year picker ********/ :host([isTouch]) paper-year-list::-webkit-scrollbar { width: 0 !important; } #pages { flex: 1; width: auto; background: var(--default-background-color); } #calendar { --paper-calendar: { @apply(--paper-date-picker-calendar); } } </style> <iron-media-query query="{{_getMediaQuery(forceNarrow, responsiveWidth)}}" query-matches="{{_queryMatches}}"></iron-media-query> <div id="datePicker"> <div id="heading" class$="{{_getHeadingClass('heading-content', _selectedPage)}}"> <div class="year" on-tap="_tapHeadingYear">{{dateFormat(date, 'YYYY', locale)}}</div> <div class="date" on-tap="_tapHeadingDate"> <template is="dom-repeat" items="{{_splitHeadingDate(date, headingFormat, locale)}}"> <span>{{item}}</span> </template> </div> </div> <neon-animated-pages id="pages" selected="{{_selectedPage}}" attr-for-selected="id" entry-animation="fade-in-animation" exit-animation="fade-out-animation"> <neon-animatable id="chooseDate"> <paper-calendar id="calendar" locale="{{locale}}" date="{{date}}" min-date="{{minDate}}" max-date="{{maxDate}}"> </paper-calendar> </neon-animatable> <neon-animatable id="chooseYear"> <paper-year-list id="yearList" date="{{date}}" on-tap="_tapHeadingDate" min="[[_minYear]]" max="[[_maxYear]]"></paper-year-list> </neon-animatable> </neon-animated-pages> </div> </template> <script> Polymer({ is: 'paper-date-picker', properties: { /** * The selected date (YYYY-MM-DD) */ date: { type: Date, notify: true }, /** * Maximum screen width at which the picker uses a vertical layout */ responsiveWidth: { type: String, value: '560px' }, /** * The current locale */ locale: { type: String, value: 'en' }, /** * The format of the date displayed in the heading. * See docuemntation for Moment.js for more info. */ headingFormat: { type: String, value: 'ddd, MMM D' }, /** * The minimum allowed date */ minDate: { type: Date, value: null }, /** * The maximum allowed date */ maxDate: { type: Date, value: null }, /** * Force narrow layout */ forceNarrow: { type: Boolean, value: false }, narrow: { type: Boolean, reflectToAttribute: true, notify: true, computed: '_computeNarrow(forceNarrow, _queryMatches)' }, isTouch: { type: Boolean, value: false, readOnly: true, reflectToAttribute: true }, _queryMatches: { type: Boolean, value: false }, headingBreak: { type: String, value: '[,]' }, _selectedPage: String, _maxYear: { type: Number, computed: '_getFullYear(maxDate)' }, _minYear: { type: Number, computed: '_getFullYear(minDate)' } }, behaviors: [ Polymer.IronResizableBehavior ], listeners: { 'iron-resize': '_resizeHandler' }, ready: function() { this.today = this.$.calendar.today; this.isTouch = 'ontouchstart' in window; this._selectPage('chooseDate'); }, dateFormat: function() { return this.$.calendar.dateFormat.apply(this.$.calendar, arguments); }, _tapHeadingDate: function() { if (this.$.pages.selected !== 'chooseDate') { this._selectPage('chooseDate'); } }, _tapHeadingYear: function() { if (this.$.pages.selected !== 'chooseYear') { this._selectPage('chooseYear'); this.$.yearList.centerSelected(); } }, _selectPage: function(page) { this.$.pages.selected = page; }, _getMediaQuery: function(forceNarrow, responsiveWidth) { return '(max-width: ' + (forceNarrow ? '' : responsiveWidth) + ')'; }, _getHeadingClass: function(pfx, selectedPage) { return pfx + ' pg-' + selectedPage; }, _getFullYear: function(date) { return date ? date.getFullYear() : null; }, _splitHeadingDate: function(date, format, locale) { var re = new RegExp(this.headingBreak, 'g'); var text = this.dateFormat(date, format, locale); var seps = text.match(re); var value; if (!seps) { value = [text]; } else { value = text.split(re).map(function(s, i) { return s + (seps[i] || ''); }); } return value; }, _computeNarrow: function(queryMatches, forceNarrow) { return queryMatches || forceNarrow; }, _resizeHandler: function() { if (this._resizing) { return; } this._resizing = true; this.$.calendar.notifyResize(); this._resizing = false; this.updateStyles(); } }); </script> </dom-module>