<link rel="import" href="../iron-flex-layout/iron-flex-layout.html"> <link rel="import" href="../iron-list/iron-list.html"> <link rel="import" href="../iron-resizable-behavior/iron-resizable-behavior.html"> <link rel="import" href="../paper-ripple/paper-ripple.html"> <link rel="import" href="../paper-styles/default-theme.html"> <link rel="import" href="../polymer/polymer.html"> <dom-module id="paper-year-list"> <template> <style> :host { display: block; box-sizing: border-box; height: 100%; @apply(--paper-font-common-base); /* for iron-list to fit */ position: relative; } .year { cursor: pointer; height: var(--paper-year-list-item-height, 44px); line-height: var(--paper-year-list-item-height, 44px); text-align: center; vertical-align: middle; } .selected { color: var(--default-primary-color); font-size: 24px; } iron-list { @apply(--layout-fit); } </style> <iron-list id="yearList" items="[[_years]]"> <template> <div class$="year{{_addSelectedClass(selected)}}" on-tap="_tappedYearHandler"> [[item.year]] </div> </template> </iron-list> </template> <script> Polymer({ is: 'paper-year-list', properties: { date: { type: Date, notify: true, observer: '_dateChange' }, /** * Maximum allowed year. */ max: { type: Number, value: 2100, observer: '_maxChange' }, /** * Minimum allowed year. */ min: { type: Number, value: 1900, observer: '_minChange' }, /** * The selected year, sync with the year of the given date * or null if year isn't within range. */ selected: { type: Number, notify: true, observer: '_selectedChange' }, /** * The allowed years array. */ _years: { type: Array, computed: '_computeYears(min, max)', readOnly: true, value: function() { return Date.now().getFullYear; } } }, ready: function() { // hack for iron-list not to scroll to the first visible index on resize this.$.yearList._resizeHandler = function() { this.debounce('resize', function() { this._render(); if (this._itemsRendered && this._physicalItems && this._isVisible) { this._resetAverage(); this.updateViewportBoundaries(); } }); }.bind(this.$.yearList); }, /** * Scroll in the years list to center the selected year. */ centerSelected: function() { if (this.selected != null) { var selectedYearIdx = this.selected - this.min; this.$.yearList.scrollToIndex(selectedYearIdx); // see https://github.com/PolymerElements/iron-list/issues/140 this.$.yearList._render(); this.async(function() { var selectedPos = selectedYearIdx * this._physicalAverage + 1; if (selectedPos != this.scrollTop) { this._update(); this.scrollTop = selectedPos; this._refresh(); } if (this.scrollHeight - this.offsetHeight != this.scrollTop) { this.scrollTop += (this._physicalAverage - this.offsetHeight) / 2; this._refresh(); } }.bind(this.$.yearList)); } }, /** * Return the selected class if needed. */ _addSelectedClass(selected) { if (selected) { return ' selected'; } }, /** * Compute the years array passed to the iron-list. */ _computeYears: function(min, max) { if (!(typeof min == 'number') || !(typeof max == 'number')) { return; } var years = []; for (;min <= max; min++) { years.push({year: min}); } return years; }, /** * Set 'selected' attribute to the new date's year if it is within range, else set it to null. */ _dateChange: function(date) { var newYear = date.getFullYear(); this.selected = this._withinRange(newYear) ? newYear : null; }, _maxChange: function(max) { if (!(typeof max == 'number')) { this.max = 2100; } }, _minChange: function(min) { if (!(typeof min == 'number')) { this.min = 1900; } }, /** * If selected is null, clear iron-list selection, * else select it in iron-list and synchronize 'date' attribute. */ _selectedChange: function(selected) { if (selected == null) { this.$.yearList.clearSelection(); return; } if (selected != this.date.getFullYear()) { // set the year using a new Date instance for notifying to work this.date = new Date(this.date.setFullYear(selected)); } this._selectYearInList(selected); }, /** * Select the given year in the years list. */ _selectYearInList: function(year) { var yearIdx = year - this.min; this.$.yearList.selectItem(yearIdx); }, /** * Update 'selected' attribute and select in iron-list * from a tapped item's event in the years list. */ _tappedYearHandler: function(e) { var yearItem = e.model.__data__.item; var year = yearItem.year; if (this.selected != year) { this.$.yearList.selectItem(yearItem); this.selected = year; } }, /** * Return true if year is between min and max. */ _withinRange: function(year) { return !(this.min && year < this.min || this.max && year > this.max ); }, behaviors: [ Polymer.IronResizableBehavior ] }); </script> </dom-module>