Index: chrome/browser/resources/md_history/lazy_load.crisper.js |
diff --git a/chrome/browser/resources/md_history/lazy_load.crisper.js b/chrome/browser/resources/md_history/lazy_load.crisper.js |
new file mode 100644 |
index 0000000000000000000000000000000000000000..29502b017090db42b4004999cd9ec846036c4f53 |
--- /dev/null |
+++ b/chrome/browser/resources/md_history/lazy_load.crisper.js |
@@ -0,0 +1,3291 @@ |
+Polymer({ |
+ is: 'iron-collapse', |
+ behaviors: [ Polymer.IronResizableBehavior ], |
+ properties: { |
+ horizontal: { |
+ type: Boolean, |
+ value: false, |
+ observer: '_horizontalChanged' |
+ }, |
+ opened: { |
+ type: Boolean, |
+ value: false, |
+ notify: true, |
+ observer: '_openedChanged' |
+ }, |
+ noAnimation: { |
+ type: Boolean |
+ }, |
+ _desiredSize: { |
+ type: String, |
+ value: '' |
+ } |
+ }, |
+ get dimension() { |
+ return this.horizontal ? 'width' : 'height'; |
+ }, |
+ get _dimensionMax() { |
+ return this.horizontal ? 'maxWidth' : 'maxHeight'; |
+ }, |
+ get _dimensionMaxCss() { |
+ return this.horizontal ? 'max-width' : 'max-height'; |
+ }, |
+ hostAttributes: { |
+ role: 'group', |
+ 'aria-hidden': 'true', |
+ 'aria-expanded': 'false' |
+ }, |
+ listeners: { |
+ transitionend: '_transitionEnd' |
+ }, |
+ attached: function() { |
+ this._transitionEnd(); |
+ }, |
+ toggle: function() { |
+ this.opened = !this.opened; |
+ }, |
+ show: function() { |
+ this.opened = true; |
+ }, |
+ hide: function() { |
+ this.opened = false; |
+ }, |
+ updateSize: function(size, animated) { |
+ size = size === 'auto' ? '' : size; |
+ if (this._desiredSize === size) { |
+ return; |
+ } |
+ this._desiredSize = size; |
+ this._updateTransition(false); |
+ var willAnimate = animated && !this.noAnimation && this._isDisplayed; |
+ if (willAnimate) { |
+ var startSize = this._calcSize(); |
+ if (size === '') { |
+ this.style[this._dimensionMax] = ''; |
+ size = this._calcSize(); |
+ } |
+ this.style[this._dimensionMax] = startSize; |
+ this.scrollTop = this.scrollTop; |
+ this._updateTransition(true); |
+ willAnimate = size !== startSize; |
+ } |
+ this.style[this._dimensionMax] = size; |
+ if (!willAnimate) { |
+ this._transitionEnd(); |
+ } |
+ }, |
+ enableTransition: function(enabled) { |
+ Polymer.Base._warn('`enableTransition()` is deprecated, use `noAnimation` instead.'); |
+ this.noAnimation = !enabled; |
+ }, |
+ _updateTransition: function(enabled) { |
+ this.style.transitionDuration = enabled && !this.noAnimation ? '' : '0s'; |
+ }, |
+ _horizontalChanged: function() { |
+ this.style.transitionProperty = this._dimensionMaxCss; |
+ var otherDimension = this._dimensionMax === 'maxWidth' ? 'maxHeight' : 'maxWidth'; |
+ this.style[otherDimension] = ''; |
+ this.updateSize(this.opened ? 'auto' : '0px', false); |
+ }, |
+ _openedChanged: function() { |
+ this.setAttribute('aria-expanded', this.opened); |
+ this.setAttribute('aria-hidden', !this.opened); |
+ this.toggleClass('iron-collapse-closed', false); |
+ this.toggleClass('iron-collapse-opened', false); |
+ this.updateSize(this.opened ? 'auto' : '0px', true); |
+ if (this.opened) { |
+ this.focus(); |
+ } |
+ }, |
+ _transitionEnd: function() { |
+ this.style[this._dimensionMax] = this._desiredSize; |
+ this.toggleClass('iron-collapse-closed', !this.opened); |
+ this.toggleClass('iron-collapse-opened', this.opened); |
+ this._updateTransition(false); |
+ this.notifyResize(); |
+ }, |
+ get _isDisplayed() { |
+ var rect = this.getBoundingClientRect(); |
+ for (var prop in rect) { |
+ if (rect[prop] !== 0) return true; |
+ } |
+ return false; |
+ }, |
+ _calcSize: function() { |
+ return this.getBoundingClientRect()[this.dimension] + 'px'; |
+ } |
+}); |
+ |
+// Copyright 2016 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+var HistoryDomain; |
+ |
+var HistoryGroup; |
+ |
+Polymer({ |
+ is: 'history-grouped-list', |
+ behaviors: [ HistoryListBehavior ], |
+ properties: { |
+ historyData: { |
+ type: Array |
+ }, |
+ groupedHistoryData_: { |
+ type: Array |
+ }, |
+ searchedTerm: { |
+ type: String, |
+ value: '' |
+ }, |
+ range: { |
+ type: Number |
+ }, |
+ queryStartTime: String, |
+ queryEndTime: String |
+ }, |
+ observers: [ 'updateGroupedHistoryData_(range, historyData)' ], |
+ createHistoryDomains_: function(visits) { |
+ var domainIndexes = {}; |
+ var domains = []; |
+ for (var i = 0, visit; visit = visits[i]; i++) { |
+ var domain = visit.domain; |
+ if (domainIndexes[domain] == undefined) { |
+ domainIndexes[domain] = domains.length; |
+ domains.push({ |
+ domain: domain, |
+ visits: [], |
+ expanded: false, |
+ rendered: false |
+ }); |
+ } |
+ domains[domainIndexes[domain]].visits.push(visit); |
+ } |
+ var sortByVisits = function(a, b) { |
+ return b.visits.length - a.visits.length; |
+ }; |
+ domains.sort(sortByVisits); |
+ return domains; |
+ }, |
+ updateGroupedHistoryData_: function() { |
+ if (this.historyData.length == 0) { |
+ this.groupedHistoryData_ = []; |
+ return; |
+ } |
+ if (this.range == HistoryRange.WEEK) { |
+ var days = []; |
+ var currentDayVisits = [ this.historyData[0] ]; |
+ var pushCurrentDay = function() { |
+ days.push({ |
+ title: this.searchedTerm ? currentDayVisits[0].dateShort : currentDayVisits[0].dateRelativeDay, |
+ domains: this.createHistoryDomains_(currentDayVisits) |
+ }); |
+ }.bind(this); |
+ var visitsSameDay = function(a, b) { |
+ if (this.searchedTerm) return a.dateShort == b.dateShort; |
+ return a.dateRelativeDay == b.dateRelativeDay; |
+ }.bind(this); |
+ for (var i = 1; i < this.historyData.length; i++) { |
+ var visit = this.historyData[i]; |
+ if (!visitsSameDay(visit, currentDayVisits[0])) { |
+ pushCurrentDay(); |
+ currentDayVisits = []; |
+ } |
+ currentDayVisits.push(visit); |
+ } |
+ pushCurrentDay(); |
+ this.groupedHistoryData_ = days; |
+ } else if (this.range == HistoryRange.MONTH) { |
+ this.groupedHistoryData_ = [ { |
+ title: this.queryStartTime + ' – ' + this.queryEndTime, |
+ domains: this.createHistoryDomains_(this.historyData) |
+ } ]; |
+ } |
+ }, |
+ toggleDomainExpanded_: function(e) { |
+ var collapse = e.currentTarget.parentNode.querySelector('iron-collapse'); |
+ e.model.set('domain.rendered', true); |
+ setTimeout(function() { |
+ collapse.toggle(); |
+ }, 0); |
+ }, |
+ needsTimeGap_: function(groupIndex, domainIndex, itemIndex) { |
+ var visits = this.groupedHistoryData_[groupIndex].domains[domainIndex].visits; |
+ return md_history.HistoryItem.needsTimeGap(visits, itemIndex, this.searchedTerm); |
+ }, |
+ pathForItem_: function(groupIndex, domainIndex, itemIndex) { |
+ return [ 'groupedHistoryData_', groupIndex, 'domains', domainIndex, 'visits', itemIndex ].join('.'); |
+ }, |
+ getWebsiteIconStyle_: function(domain) { |
+ return 'background-image: ' + cr.icon.getFavicon(domain.visits[0].url); |
+ }, |
+ getDropdownIcon_: function(expanded) { |
+ return expanded ? 'cr:expand-less' : 'cr:expand-more'; |
+ } |
+}); |
+ |
+Polymer.PaperButtonBehaviorImpl = { |
+ properties: { |
+ elevation: { |
+ type: Number, |
+ reflectToAttribute: true, |
+ readOnly: true |
+ } |
+ }, |
+ observers: [ '_calculateElevation(focused, disabled, active, pressed, receivedFocusFromKeyboard)', '_computeKeyboardClass(receivedFocusFromKeyboard)' ], |
+ hostAttributes: { |
+ role: 'button', |
+ tabindex: '0', |
+ animated: true |
+ }, |
+ _calculateElevation: function() { |
+ var e = 1; |
+ if (this.disabled) { |
+ e = 0; |
+ } else if (this.active || this.pressed) { |
+ e = 4; |
+ } else if (this.receivedFocusFromKeyboard) { |
+ e = 3; |
+ } |
+ this._setElevation(e); |
+ }, |
+ _computeKeyboardClass: function(receivedFocusFromKeyboard) { |
+ this.toggleClass('keyboard-focus', receivedFocusFromKeyboard); |
+ }, |
+ _spaceKeyDownHandler: function(event) { |
+ Polymer.IronButtonStateImpl._spaceKeyDownHandler.call(this, event); |
+ if (this.hasRipple() && this.getRipple().ripples.length < 1) { |
+ this._ripple.uiDownAction(); |
+ } |
+ }, |
+ _spaceKeyUpHandler: function(event) { |
+ Polymer.IronButtonStateImpl._spaceKeyUpHandler.call(this, event); |
+ if (this.hasRipple()) { |
+ this._ripple.uiUpAction(); |
+ } |
+ } |
+}; |
+ |
+Polymer.PaperButtonBehavior = [ Polymer.IronButtonState, Polymer.IronControlState, Polymer.PaperRippleBehavior, Polymer.PaperButtonBehaviorImpl ]; |
+ |
+Polymer({ |
+ is: 'paper-button', |
+ behaviors: [ Polymer.PaperButtonBehavior ], |
+ properties: { |
+ raised: { |
+ type: Boolean, |
+ reflectToAttribute: true, |
+ value: false, |
+ observer: '_calculateElevation' |
+ } |
+ }, |
+ _calculateElevation: function() { |
+ if (!this.raised) { |
+ this._setElevation(0); |
+ } else { |
+ Polymer.PaperButtonBehaviorImpl._calculateElevation.apply(this); |
+ } |
+ } |
+}); |
+ |
+Polymer.PaperItemBehaviorImpl = { |
+ hostAttributes: { |
+ role: 'option', |
+ tabindex: '0' |
+ } |
+}; |
+ |
+Polymer.PaperItemBehavior = [ Polymer.IronButtonState, Polymer.IronControlState, Polymer.PaperItemBehaviorImpl ]; |
+ |
+Polymer({ |
+ is: 'paper-item', |
+ behaviors: [ Polymer.PaperItemBehavior ] |
+}); |
+ |
+Polymer.IronFitBehavior = { |
+ properties: { |
+ sizingTarget: { |
+ type: Object, |
+ value: function() { |
+ return this; |
+ } |
+ }, |
+ fitInto: { |
+ type: Object, |
+ value: window |
+ }, |
+ noOverlap: { |
+ type: Boolean |
+ }, |
+ positionTarget: { |
+ type: Element |
+ }, |
+ horizontalAlign: { |
+ type: String |
+ }, |
+ verticalAlign: { |
+ type: String |
+ }, |
+ dynamicAlign: { |
+ type: Boolean |
+ }, |
+ horizontalOffset: { |
+ type: Number, |
+ value: 0, |
+ notify: true |
+ }, |
+ verticalOffset: { |
+ type: Number, |
+ value: 0, |
+ notify: true |
+ }, |
+ autoFitOnAttach: { |
+ type: Boolean, |
+ value: false |
+ }, |
+ _fitInfo: { |
+ type: Object |
+ } |
+ }, |
+ get _fitWidth() { |
+ var fitWidth; |
+ if (this.fitInto === window) { |
+ fitWidth = this.fitInto.innerWidth; |
+ } else { |
+ fitWidth = this.fitInto.getBoundingClientRect().width; |
+ } |
+ return fitWidth; |
+ }, |
+ get _fitHeight() { |
+ var fitHeight; |
+ if (this.fitInto === window) { |
+ fitHeight = this.fitInto.innerHeight; |
+ } else { |
+ fitHeight = this.fitInto.getBoundingClientRect().height; |
+ } |
+ return fitHeight; |
+ }, |
+ get _fitLeft() { |
+ var fitLeft; |
+ if (this.fitInto === window) { |
+ fitLeft = 0; |
+ } else { |
+ fitLeft = this.fitInto.getBoundingClientRect().left; |
+ } |
+ return fitLeft; |
+ }, |
+ get _fitTop() { |
+ var fitTop; |
+ if (this.fitInto === window) { |
+ fitTop = 0; |
+ } else { |
+ fitTop = this.fitInto.getBoundingClientRect().top; |
+ } |
+ return fitTop; |
+ }, |
+ get _defaultPositionTarget() { |
+ var parent = Polymer.dom(this).parentNode; |
+ if (parent && parent.nodeType === Node.DOCUMENT_FRAGMENT_NODE) { |
+ parent = parent.host; |
+ } |
+ return parent; |
+ }, |
+ get _localeHorizontalAlign() { |
+ if (this._isRTL) { |
+ if (this.horizontalAlign === 'right') { |
+ return 'left'; |
+ } |
+ if (this.horizontalAlign === 'left') { |
+ return 'right'; |
+ } |
+ } |
+ return this.horizontalAlign; |
+ }, |
+ attached: function() { |
+ this._isRTL = window.getComputedStyle(this).direction == 'rtl'; |
+ this.positionTarget = this.positionTarget || this._defaultPositionTarget; |
+ if (this.autoFitOnAttach) { |
+ if (window.getComputedStyle(this).display === 'none') { |
+ setTimeout(function() { |
+ this.fit(); |
+ }.bind(this)); |
+ } else { |
+ this.fit(); |
+ } |
+ } |
+ }, |
+ fit: function() { |
+ this.position(); |
+ this.constrain(); |
+ this.center(); |
+ }, |
+ _discoverInfo: function() { |
+ if (this._fitInfo) { |
+ return; |
+ } |
+ var target = window.getComputedStyle(this); |
+ var sizer = window.getComputedStyle(this.sizingTarget); |
+ this._fitInfo = { |
+ inlineStyle: { |
+ top: this.style.top || '', |
+ left: this.style.left || '', |
+ position: this.style.position || '' |
+ }, |
+ sizerInlineStyle: { |
+ maxWidth: this.sizingTarget.style.maxWidth || '', |
+ maxHeight: this.sizingTarget.style.maxHeight || '', |
+ boxSizing: this.sizingTarget.style.boxSizing || '' |
+ }, |
+ positionedBy: { |
+ vertically: target.top !== 'auto' ? 'top' : target.bottom !== 'auto' ? 'bottom' : null, |
+ horizontally: target.left !== 'auto' ? 'left' : target.right !== 'auto' ? 'right' : null |
+ }, |
+ sizedBy: { |
+ height: sizer.maxHeight !== 'none', |
+ width: sizer.maxWidth !== 'none', |
+ minWidth: parseInt(sizer.minWidth, 10) || 0, |
+ minHeight: parseInt(sizer.minHeight, 10) || 0 |
+ }, |
+ margin: { |
+ top: parseInt(target.marginTop, 10) || 0, |
+ right: parseInt(target.marginRight, 10) || 0, |
+ bottom: parseInt(target.marginBottom, 10) || 0, |
+ left: parseInt(target.marginLeft, 10) || 0 |
+ } |
+ }; |
+ if (this.verticalOffset) { |
+ this._fitInfo.margin.top = this._fitInfo.margin.bottom = this.verticalOffset; |
+ this._fitInfo.inlineStyle.marginTop = this.style.marginTop || ''; |
+ this._fitInfo.inlineStyle.marginBottom = this.style.marginBottom || ''; |
+ this.style.marginTop = this.style.marginBottom = this.verticalOffset + 'px'; |
+ } |
+ if (this.horizontalOffset) { |
+ this._fitInfo.margin.left = this._fitInfo.margin.right = this.horizontalOffset; |
+ this._fitInfo.inlineStyle.marginLeft = this.style.marginLeft || ''; |
+ this._fitInfo.inlineStyle.marginRight = this.style.marginRight || ''; |
+ this.style.marginLeft = this.style.marginRight = this.horizontalOffset + 'px'; |
+ } |
+ }, |
+ resetFit: function() { |
+ var info = this._fitInfo || {}; |
+ for (var property in info.sizerInlineStyle) { |
+ this.sizingTarget.style[property] = info.sizerInlineStyle[property]; |
+ } |
+ for (var property in info.inlineStyle) { |
+ this.style[property] = info.inlineStyle[property]; |
+ } |
+ this._fitInfo = null; |
+ }, |
+ refit: function() { |
+ var scrollLeft = this.sizingTarget.scrollLeft; |
+ var scrollTop = this.sizingTarget.scrollTop; |
+ this.resetFit(); |
+ this.fit(); |
+ this.sizingTarget.scrollLeft = scrollLeft; |
+ this.sizingTarget.scrollTop = scrollTop; |
+ }, |
+ position: function() { |
+ if (!this.horizontalAlign && !this.verticalAlign) { |
+ return; |
+ } |
+ this._discoverInfo(); |
+ this.style.position = 'fixed'; |
+ this.sizingTarget.style.boxSizing = 'border-box'; |
+ this.style.left = '0px'; |
+ this.style.top = '0px'; |
+ var rect = this.getBoundingClientRect(); |
+ var positionRect = this.__getNormalizedRect(this.positionTarget); |
+ var fitRect = this.__getNormalizedRect(this.fitInto); |
+ var margin = this._fitInfo.margin; |
+ var size = { |
+ width: rect.width + margin.left + margin.right, |
+ height: rect.height + margin.top + margin.bottom |
+ }; |
+ var position = this.__getPosition(this._localeHorizontalAlign, this.verticalAlign, size, positionRect, fitRect); |
+ var left = position.left + margin.left; |
+ var top = position.top + margin.top; |
+ var right = Math.min(fitRect.right - margin.right, left + rect.width); |
+ var bottom = Math.min(fitRect.bottom - margin.bottom, top + rect.height); |
+ var minWidth = this._fitInfo.sizedBy.minWidth; |
+ var minHeight = this._fitInfo.sizedBy.minHeight; |
+ if (left < margin.left) { |
+ left = margin.left; |
+ if (right - left < minWidth) { |
+ left = right - minWidth; |
+ } |
+ } |
+ if (top < margin.top) { |
+ top = margin.top; |
+ if (bottom - top < minHeight) { |
+ top = bottom - minHeight; |
+ } |
+ } |
+ this.sizingTarget.style.maxWidth = right - left + 'px'; |
+ this.sizingTarget.style.maxHeight = bottom - top + 'px'; |
+ this.style.left = left - rect.left + 'px'; |
+ this.style.top = top - rect.top + 'px'; |
+ }, |
+ constrain: function() { |
+ if (this.horizontalAlign || this.verticalAlign) { |
+ return; |
+ } |
+ this._discoverInfo(); |
+ var info = this._fitInfo; |
+ if (!info.positionedBy.vertically) { |
+ this.style.position = 'fixed'; |
+ this.style.top = '0px'; |
+ } |
+ if (!info.positionedBy.horizontally) { |
+ this.style.position = 'fixed'; |
+ this.style.left = '0px'; |
+ } |
+ this.sizingTarget.style.boxSizing = 'border-box'; |
+ var rect = this.getBoundingClientRect(); |
+ if (!info.sizedBy.height) { |
+ this.__sizeDimension(rect, info.positionedBy.vertically, 'top', 'bottom', 'Height'); |
+ } |
+ if (!info.sizedBy.width) { |
+ this.__sizeDimension(rect, info.positionedBy.horizontally, 'left', 'right', 'Width'); |
+ } |
+ }, |
+ _sizeDimension: function(rect, positionedBy, start, end, extent) { |
+ this.__sizeDimension(rect, positionedBy, start, end, extent); |
+ }, |
+ __sizeDimension: function(rect, positionedBy, start, end, extent) { |
+ var info = this._fitInfo; |
+ var fitRect = this.__getNormalizedRect(this.fitInto); |
+ var max = extent === 'Width' ? fitRect.width : fitRect.height; |
+ var flip = positionedBy === end; |
+ var offset = flip ? max - rect[end] : rect[start]; |
+ var margin = info.margin[flip ? start : end]; |
+ var offsetExtent = 'offset' + extent; |
+ var sizingOffset = this[offsetExtent] - this.sizingTarget[offsetExtent]; |
+ this.sizingTarget.style['max' + extent] = max - margin - offset - sizingOffset + 'px'; |
+ }, |
+ center: function() { |
+ if (this.horizontalAlign || this.verticalAlign) { |
+ return; |
+ } |
+ this._discoverInfo(); |
+ var positionedBy = this._fitInfo.positionedBy; |
+ if (positionedBy.vertically && positionedBy.horizontally) { |
+ return; |
+ } |
+ this.style.position = 'fixed'; |
+ if (!positionedBy.vertically) { |
+ this.style.top = '0px'; |
+ } |
+ if (!positionedBy.horizontally) { |
+ this.style.left = '0px'; |
+ } |
+ var rect = this.getBoundingClientRect(); |
+ var fitRect = this.__getNormalizedRect(this.fitInto); |
+ if (!positionedBy.vertically) { |
+ var top = fitRect.top - rect.top + (fitRect.height - rect.height) / 2; |
+ this.style.top = top + 'px'; |
+ } |
+ if (!positionedBy.horizontally) { |
+ var left = fitRect.left - rect.left + (fitRect.width - rect.width) / 2; |
+ this.style.left = left + 'px'; |
+ } |
+ }, |
+ __getNormalizedRect: function(target) { |
+ if (target === document.documentElement || target === window) { |
+ return { |
+ top: 0, |
+ left: 0, |
+ width: window.innerWidth, |
+ height: window.innerHeight, |
+ right: window.innerWidth, |
+ bottom: window.innerHeight |
+ }; |
+ } |
+ return target.getBoundingClientRect(); |
+ }, |
+ __getCroppedArea: function(position, size, fitRect) { |
+ var verticalCrop = Math.min(0, position.top) + Math.min(0, fitRect.bottom - (position.top + size.height)); |
+ var horizontalCrop = Math.min(0, position.left) + Math.min(0, fitRect.right - (position.left + size.width)); |
+ return Math.abs(verticalCrop) * size.width + Math.abs(horizontalCrop) * size.height; |
+ }, |
+ __getPosition: function(hAlign, vAlign, size, positionRect, fitRect) { |
+ var positions = [ { |
+ verticalAlign: 'top', |
+ horizontalAlign: 'left', |
+ top: positionRect.top, |
+ left: positionRect.left |
+ }, { |
+ verticalAlign: 'top', |
+ horizontalAlign: 'right', |
+ top: positionRect.top, |
+ left: positionRect.right - size.width |
+ }, { |
+ verticalAlign: 'bottom', |
+ horizontalAlign: 'left', |
+ top: positionRect.bottom - size.height, |
+ left: positionRect.left |
+ }, { |
+ verticalAlign: 'bottom', |
+ horizontalAlign: 'right', |
+ top: positionRect.bottom - size.height, |
+ left: positionRect.right - size.width |
+ } ]; |
+ if (this.noOverlap) { |
+ for (var i = 0, l = positions.length; i < l; i++) { |
+ var copy = {}; |
+ for (var key in positions[i]) { |
+ copy[key] = positions[i][key]; |
+ } |
+ positions.push(copy); |
+ } |
+ positions[0].top = positions[1].top += positionRect.height; |
+ positions[2].top = positions[3].top -= positionRect.height; |
+ positions[4].left = positions[6].left += positionRect.width; |
+ positions[5].left = positions[7].left -= positionRect.width; |
+ } |
+ vAlign = vAlign === 'auto' ? null : vAlign; |
+ hAlign = hAlign === 'auto' ? null : hAlign; |
+ var position; |
+ for (var i = 0; i < positions.length; i++) { |
+ var pos = positions[i]; |
+ if (!this.dynamicAlign && !this.noOverlap && pos.verticalAlign === vAlign && pos.horizontalAlign === hAlign) { |
+ position = pos; |
+ break; |
+ } |
+ var alignOk = (!vAlign || pos.verticalAlign === vAlign) && (!hAlign || pos.horizontalAlign === hAlign); |
+ if (!this.dynamicAlign && !alignOk) { |
+ continue; |
+ } |
+ position = position || pos; |
+ pos.croppedArea = this.__getCroppedArea(pos, size, fitRect); |
+ var diff = pos.croppedArea - position.croppedArea; |
+ if (diff < 0 || diff === 0 && alignOk) { |
+ position = pos; |
+ } |
+ if (position.croppedArea === 0 && alignOk) { |
+ break; |
+ } |
+ } |
+ return position; |
+ } |
+}; |
+ |
+(function() { |
+ 'use strict'; |
+ Polymer({ |
+ is: 'iron-overlay-backdrop', |
+ properties: { |
+ opened: { |
+ reflectToAttribute: true, |
+ type: Boolean, |
+ value: false, |
+ observer: '_openedChanged' |
+ } |
+ }, |
+ listeners: { |
+ transitionend: '_onTransitionend' |
+ }, |
+ created: function() { |
+ this.__openedRaf = null; |
+ }, |
+ attached: function() { |
+ this.opened && this._openedChanged(this.opened); |
+ }, |
+ prepare: function() { |
+ if (this.opened && !this.parentNode) { |
+ Polymer.dom(document.body).appendChild(this); |
+ } |
+ }, |
+ open: function() { |
+ this.opened = true; |
+ }, |
+ close: function() { |
+ this.opened = false; |
+ }, |
+ complete: function() { |
+ if (!this.opened && this.parentNode === document.body) { |
+ Polymer.dom(this.parentNode).removeChild(this); |
+ } |
+ }, |
+ _onTransitionend: function(event) { |
+ if (event && event.target === this) { |
+ this.complete(); |
+ } |
+ }, |
+ _openedChanged: function(opened) { |
+ if (opened) { |
+ this.prepare(); |
+ } else { |
+ var cs = window.getComputedStyle(this); |
+ if (cs.transitionDuration === '0s' || cs.opacity == 0) { |
+ this.complete(); |
+ } |
+ } |
+ if (!this.isAttached) { |
+ return; |
+ } |
+ if (this.__openedRaf) { |
+ window.cancelAnimationFrame(this.__openedRaf); |
+ this.__openedRaf = null; |
+ } |
+ this.scrollTop = this.scrollTop; |
+ this.__openedRaf = window.requestAnimationFrame(function() { |
+ this.__openedRaf = null; |
+ this.toggleClass('opened', this.opened); |
+ }.bind(this)); |
+ } |
+ }); |
+})(); |
+ |
+Polymer.IronOverlayManagerClass = function() { |
+ this._overlays = []; |
+ this._minimumZ = 101; |
+ this._backdropElement = null; |
+ Polymer.Gestures.add(document, 'tap', this._onCaptureClick.bind(this)); |
+ document.addEventListener('focus', this._onCaptureFocus.bind(this), true); |
+ document.addEventListener('keydown', this._onCaptureKeyDown.bind(this), true); |
+}; |
+ |
+Polymer.IronOverlayManagerClass.prototype = { |
+ constructor: Polymer.IronOverlayManagerClass, |
+ get backdropElement() { |
+ if (!this._backdropElement) { |
+ this._backdropElement = document.createElement('iron-overlay-backdrop'); |
+ } |
+ return this._backdropElement; |
+ }, |
+ get deepActiveElement() { |
+ var active = document.activeElement || document.body; |
+ while (active.root && Polymer.dom(active.root).activeElement) { |
+ active = Polymer.dom(active.root).activeElement; |
+ } |
+ return active; |
+ }, |
+ _bringOverlayAtIndexToFront: function(i) { |
+ var overlay = this._overlays[i]; |
+ if (!overlay) { |
+ return; |
+ } |
+ var lastI = this._overlays.length - 1; |
+ var currentOverlay = this._overlays[lastI]; |
+ if (currentOverlay && this._shouldBeBehindOverlay(overlay, currentOverlay)) { |
+ lastI--; |
+ } |
+ if (i >= lastI) { |
+ return; |
+ } |
+ var minimumZ = Math.max(this.currentOverlayZ(), this._minimumZ); |
+ if (this._getZ(overlay) <= minimumZ) { |
+ this._applyOverlayZ(overlay, minimumZ); |
+ } |
+ while (i < lastI) { |
+ this._overlays[i] = this._overlays[i + 1]; |
+ i++; |
+ } |
+ this._overlays[lastI] = overlay; |
+ }, |
+ addOrRemoveOverlay: function(overlay) { |
+ if (overlay.opened) { |
+ this.addOverlay(overlay); |
+ } else { |
+ this.removeOverlay(overlay); |
+ } |
+ }, |
+ addOverlay: function(overlay) { |
+ var i = this._overlays.indexOf(overlay); |
+ if (i >= 0) { |
+ this._bringOverlayAtIndexToFront(i); |
+ this.trackBackdrop(); |
+ return; |
+ } |
+ var insertionIndex = this._overlays.length; |
+ var currentOverlay = this._overlays[insertionIndex - 1]; |
+ var minimumZ = Math.max(this._getZ(currentOverlay), this._minimumZ); |
+ var newZ = this._getZ(overlay); |
+ if (currentOverlay && this._shouldBeBehindOverlay(overlay, currentOverlay)) { |
+ this._applyOverlayZ(currentOverlay, minimumZ); |
+ insertionIndex--; |
+ var previousOverlay = this._overlays[insertionIndex - 1]; |
+ minimumZ = Math.max(this._getZ(previousOverlay), this._minimumZ); |
+ } |
+ if (newZ <= minimumZ) { |
+ this._applyOverlayZ(overlay, minimumZ); |
+ } |
+ this._overlays.splice(insertionIndex, 0, overlay); |
+ this.trackBackdrop(); |
+ }, |
+ removeOverlay: function(overlay) { |
+ var i = this._overlays.indexOf(overlay); |
+ if (i === -1) { |
+ return; |
+ } |
+ this._overlays.splice(i, 1); |
+ this.trackBackdrop(); |
+ }, |
+ currentOverlay: function() { |
+ var i = this._overlays.length - 1; |
+ return this._overlays[i]; |
+ }, |
+ currentOverlayZ: function() { |
+ return this._getZ(this.currentOverlay()); |
+ }, |
+ ensureMinimumZ: function(minimumZ) { |
+ this._minimumZ = Math.max(this._minimumZ, minimumZ); |
+ }, |
+ focusOverlay: function() { |
+ var current = this.currentOverlay(); |
+ if (current) { |
+ current._applyFocus(); |
+ } |
+ }, |
+ trackBackdrop: function() { |
+ var overlay = this._overlayWithBackdrop(); |
+ if (!overlay && !this._backdropElement) { |
+ return; |
+ } |
+ this.backdropElement.style.zIndex = this._getZ(overlay) - 1; |
+ this.backdropElement.opened = !!overlay; |
+ }, |
+ getBackdrops: function() { |
+ var backdrops = []; |
+ for (var i = 0; i < this._overlays.length; i++) { |
+ if (this._overlays[i].withBackdrop) { |
+ backdrops.push(this._overlays[i]); |
+ } |
+ } |
+ return backdrops; |
+ }, |
+ backdropZ: function() { |
+ return this._getZ(this._overlayWithBackdrop()) - 1; |
+ }, |
+ _overlayWithBackdrop: function() { |
+ for (var i = 0; i < this._overlays.length; i++) { |
+ if (this._overlays[i].withBackdrop) { |
+ return this._overlays[i]; |
+ } |
+ } |
+ }, |
+ _getZ: function(overlay) { |
+ var z = this._minimumZ; |
+ if (overlay) { |
+ var z1 = Number(overlay.style.zIndex || window.getComputedStyle(overlay).zIndex); |
+ if (z1 === z1) { |
+ z = z1; |
+ } |
+ } |
+ return z; |
+ }, |
+ _setZ: function(element, z) { |
+ element.style.zIndex = z; |
+ }, |
+ _applyOverlayZ: function(overlay, aboveZ) { |
+ this._setZ(overlay, aboveZ + 2); |
+ }, |
+ _overlayInPath: function(path) { |
+ path = path || []; |
+ for (var i = 0; i < path.length; i++) { |
+ if (path[i]._manager === this) { |
+ return path[i]; |
+ } |
+ } |
+ }, |
+ _onCaptureClick: function(event) { |
+ var overlay = this.currentOverlay(); |
+ if (overlay && this._overlayInPath(Polymer.dom(event).path) !== overlay) { |
+ overlay._onCaptureClick(event); |
+ } |
+ }, |
+ _onCaptureFocus: function(event) { |
+ var overlay = this.currentOverlay(); |
+ if (overlay) { |
+ overlay._onCaptureFocus(event); |
+ } |
+ }, |
+ _onCaptureKeyDown: function(event) { |
+ var overlay = this.currentOverlay(); |
+ if (overlay) { |
+ if (Polymer.IronA11yKeysBehavior.keyboardEventMatchesKeys(event, 'esc')) { |
+ overlay._onCaptureEsc(event); |
+ } else if (Polymer.IronA11yKeysBehavior.keyboardEventMatchesKeys(event, 'tab')) { |
+ overlay._onCaptureTab(event); |
+ } |
+ } |
+ }, |
+ _shouldBeBehindOverlay: function(overlay1, overlay2) { |
+ return !overlay1.alwaysOnTop && overlay2.alwaysOnTop; |
+ } |
+}; |
+ |
+Polymer.IronOverlayManager = new Polymer.IronOverlayManagerClass(); |
+ |
+(function() { |
+ 'use strict'; |
+ Polymer.IronOverlayBehaviorImpl = { |
+ properties: { |
+ opened: { |
+ observer: '_openedChanged', |
+ type: Boolean, |
+ value: false, |
+ notify: true |
+ }, |
+ canceled: { |
+ observer: '_canceledChanged', |
+ readOnly: true, |
+ type: Boolean, |
+ value: false |
+ }, |
+ withBackdrop: { |
+ observer: '_withBackdropChanged', |
+ type: Boolean |
+ }, |
+ noAutoFocus: { |
+ type: Boolean, |
+ value: false |
+ }, |
+ noCancelOnEscKey: { |
+ type: Boolean, |
+ value: false |
+ }, |
+ noCancelOnOutsideClick: { |
+ type: Boolean, |
+ value: false |
+ }, |
+ closingReason: { |
+ type: Object |
+ }, |
+ restoreFocusOnClose: { |
+ type: Boolean, |
+ value: false |
+ }, |
+ alwaysOnTop: { |
+ type: Boolean |
+ }, |
+ _manager: { |
+ type: Object, |
+ value: Polymer.IronOverlayManager |
+ }, |
+ _focusedChild: { |
+ type: Object |
+ } |
+ }, |
+ listeners: { |
+ 'iron-resize': '_onIronResize' |
+ }, |
+ get backdropElement() { |
+ return this._manager.backdropElement; |
+ }, |
+ get _focusNode() { |
+ return this._focusedChild || Polymer.dom(this).querySelector('[autofocus]') || this; |
+ }, |
+ get _focusableNodes() { |
+ var FOCUSABLE_WITH_DISABLED = [ 'a[href]', 'area[href]', 'iframe', '[tabindex]', '[contentEditable=true]' ]; |
+ var FOCUSABLE_WITHOUT_DISABLED = [ 'input', 'select', 'textarea', 'button' ]; |
+ var selector = FOCUSABLE_WITH_DISABLED.join(':not([tabindex="-1"]),') + ':not([tabindex="-1"]),' + FOCUSABLE_WITHOUT_DISABLED.join(':not([disabled]):not([tabindex="-1"]),') + ':not([disabled]):not([tabindex="-1"])'; |
+ var focusables = Polymer.dom(this).querySelectorAll(selector); |
+ if (this.tabIndex >= 0) { |
+ focusables.splice(0, 0, this); |
+ } |
+ return focusables.sort(function(a, b) { |
+ if (a.tabIndex === b.tabIndex) { |
+ return 0; |
+ } |
+ if (a.tabIndex === 0 || a.tabIndex > b.tabIndex) { |
+ return 1; |
+ } |
+ return -1; |
+ }); |
+ }, |
+ ready: function() { |
+ this.__isAnimating = false; |
+ this.__shouldRemoveTabIndex = false; |
+ this.__firstFocusableNode = this.__lastFocusableNode = null; |
+ this.__raf = null; |
+ this.__restoreFocusNode = null; |
+ this._ensureSetup(); |
+ }, |
+ attached: function() { |
+ if (this.opened) { |
+ this._openedChanged(this.opened); |
+ } |
+ this._observer = Polymer.dom(this).observeNodes(this._onNodesChange); |
+ }, |
+ detached: function() { |
+ Polymer.dom(this).unobserveNodes(this._observer); |
+ this._observer = null; |
+ if (this.__raf) { |
+ window.cancelAnimationFrame(this.__raf); |
+ this.__raf = null; |
+ } |
+ this._manager.removeOverlay(this); |
+ }, |
+ toggle: function() { |
+ this._setCanceled(false); |
+ this.opened = !this.opened; |
+ }, |
+ open: function() { |
+ this._setCanceled(false); |
+ this.opened = true; |
+ }, |
+ close: function() { |
+ this._setCanceled(false); |
+ this.opened = false; |
+ }, |
+ cancel: function(event) { |
+ var cancelEvent = this.fire('iron-overlay-canceled', event, { |
+ cancelable: true |
+ }); |
+ if (cancelEvent.defaultPrevented) { |
+ return; |
+ } |
+ this._setCanceled(true); |
+ this.opened = false; |
+ }, |
+ _ensureSetup: function() { |
+ if (this._overlaySetup) { |
+ return; |
+ } |
+ this._overlaySetup = true; |
+ this.style.outline = 'none'; |
+ this.style.display = 'none'; |
+ }, |
+ _openedChanged: function(opened) { |
+ if (opened) { |
+ this.removeAttribute('aria-hidden'); |
+ } else { |
+ this.setAttribute('aria-hidden', 'true'); |
+ } |
+ if (!this.isAttached) { |
+ return; |
+ } |
+ this.__isAnimating = true; |
+ this.__onNextAnimationFrame(this.__openedChanged); |
+ }, |
+ _canceledChanged: function() { |
+ this.closingReason = this.closingReason || {}; |
+ this.closingReason.canceled = this.canceled; |
+ }, |
+ _withBackdropChanged: function() { |
+ if (this.withBackdrop && !this.hasAttribute('tabindex')) { |
+ this.setAttribute('tabindex', '-1'); |
+ this.__shouldRemoveTabIndex = true; |
+ } else if (this.__shouldRemoveTabIndex) { |
+ this.removeAttribute('tabindex'); |
+ this.__shouldRemoveTabIndex = false; |
+ } |
+ if (this.opened && this.isAttached) { |
+ this._manager.trackBackdrop(); |
+ } |
+ }, |
+ _prepareRenderOpened: function() { |
+ this.__restoreFocusNode = this._manager.deepActiveElement; |
+ this._preparePositioning(); |
+ this.refit(); |
+ this._finishPositioning(); |
+ if (this.noAutoFocus && document.activeElement === this._focusNode) { |
+ this._focusNode.blur(); |
+ this.__restoreFocusNode.focus(); |
+ } |
+ }, |
+ _renderOpened: function() { |
+ this._finishRenderOpened(); |
+ }, |
+ _renderClosed: function() { |
+ this._finishRenderClosed(); |
+ }, |
+ _finishRenderOpened: function() { |
+ this.notifyResize(); |
+ this.__isAnimating = false; |
+ var focusableNodes = this._focusableNodes; |
+ this.__firstFocusableNode = focusableNodes[0]; |
+ this.__lastFocusableNode = focusableNodes[focusableNodes.length - 1]; |
+ this.fire('iron-overlay-opened'); |
+ }, |
+ _finishRenderClosed: function() { |
+ this.style.display = 'none'; |
+ this.style.zIndex = ''; |
+ this.notifyResize(); |
+ this.__isAnimating = false; |
+ this.fire('iron-overlay-closed', this.closingReason); |
+ }, |
+ _preparePositioning: function() { |
+ this.style.transition = this.style.webkitTransition = 'none'; |
+ this.style.transform = this.style.webkitTransform = 'none'; |
+ this.style.display = ''; |
+ }, |
+ _finishPositioning: function() { |
+ this.style.display = 'none'; |
+ this.scrollTop = this.scrollTop; |
+ this.style.transition = this.style.webkitTransition = ''; |
+ this.style.transform = this.style.webkitTransform = ''; |
+ this.style.display = ''; |
+ this.scrollTop = this.scrollTop; |
+ }, |
+ _applyFocus: function() { |
+ if (this.opened) { |
+ if (!this.noAutoFocus) { |
+ this._focusNode.focus(); |
+ } |
+ } else { |
+ this._focusNode.blur(); |
+ this._focusedChild = null; |
+ if (this.restoreFocusOnClose && this.__restoreFocusNode) { |
+ this.__restoreFocusNode.focus(); |
+ } |
+ this.__restoreFocusNode = null; |
+ var currentOverlay = this._manager.currentOverlay(); |
+ if (currentOverlay && this !== currentOverlay) { |
+ currentOverlay._applyFocus(); |
+ } |
+ } |
+ }, |
+ _onCaptureClick: function(event) { |
+ if (!this.noCancelOnOutsideClick) { |
+ this.cancel(event); |
+ } |
+ }, |
+ _onCaptureFocus: function(event) { |
+ if (!this.withBackdrop) { |
+ return; |
+ } |
+ var path = Polymer.dom(event).path; |
+ if (path.indexOf(this) === -1) { |
+ event.stopPropagation(); |
+ this._applyFocus(); |
+ } else { |
+ this._focusedChild = path[0]; |
+ } |
+ }, |
+ _onCaptureEsc: function(event) { |
+ if (!this.noCancelOnEscKey) { |
+ this.cancel(event); |
+ } |
+ }, |
+ _onCaptureTab: function(event) { |
+ if (!this.withBackdrop) { |
+ return; |
+ } |
+ var shift = event.shiftKey; |
+ var nodeToCheck = shift ? this.__firstFocusableNode : this.__lastFocusableNode; |
+ var nodeToSet = shift ? this.__lastFocusableNode : this.__firstFocusableNode; |
+ var shouldWrap = false; |
+ if (nodeToCheck === nodeToSet) { |
+ shouldWrap = true; |
+ } else { |
+ var focusedNode = this._manager.deepActiveElement; |
+ shouldWrap = focusedNode === nodeToCheck || focusedNode === this; |
+ } |
+ if (shouldWrap) { |
+ event.preventDefault(); |
+ this._focusedChild = nodeToSet; |
+ this._applyFocus(); |
+ } |
+ }, |
+ _onIronResize: function() { |
+ if (this.opened && !this.__isAnimating) { |
+ this.__onNextAnimationFrame(this.refit); |
+ } |
+ }, |
+ _onNodesChange: function() { |
+ if (this.opened && !this.__isAnimating) { |
+ this.notifyResize(); |
+ } |
+ }, |
+ __openedChanged: function() { |
+ if (this.opened) { |
+ this._prepareRenderOpened(); |
+ this._manager.addOverlay(this); |
+ this._applyFocus(); |
+ this._renderOpened(); |
+ } else { |
+ this._manager.removeOverlay(this); |
+ this._applyFocus(); |
+ this._renderClosed(); |
+ } |
+ }, |
+ __onNextAnimationFrame: function(callback) { |
+ if (this.__raf) { |
+ window.cancelAnimationFrame(this.__raf); |
+ } |
+ var self = this; |
+ this.__raf = window.requestAnimationFrame(function nextAnimationFrame() { |
+ self.__raf = null; |
+ callback.call(self); |
+ }); |
+ } |
+ }; |
+ Polymer.IronOverlayBehavior = [ Polymer.IronFitBehavior, Polymer.IronResizableBehavior, Polymer.IronOverlayBehaviorImpl ]; |
+})(); |
+ |
+Polymer.NeonAnimatableBehavior = { |
+ properties: { |
+ animationConfig: { |
+ type: Object |
+ }, |
+ entryAnimation: { |
+ observer: '_entryAnimationChanged', |
+ type: String |
+ }, |
+ exitAnimation: { |
+ observer: '_exitAnimationChanged', |
+ type: String |
+ } |
+ }, |
+ _entryAnimationChanged: function() { |
+ this.animationConfig = this.animationConfig || {}; |
+ this.animationConfig['entry'] = [ { |
+ name: this.entryAnimation, |
+ node: this |
+ } ]; |
+ }, |
+ _exitAnimationChanged: function() { |
+ this.animationConfig = this.animationConfig || {}; |
+ this.animationConfig['exit'] = [ { |
+ name: this.exitAnimation, |
+ node: this |
+ } ]; |
+ }, |
+ _copyProperties: function(config1, config2) { |
+ for (var property in config2) { |
+ config1[property] = config2[property]; |
+ } |
+ }, |
+ _cloneConfig: function(config) { |
+ var clone = { |
+ isClone: true |
+ }; |
+ this._copyProperties(clone, config); |
+ return clone; |
+ }, |
+ _getAnimationConfigRecursive: function(type, map, allConfigs) { |
+ if (!this.animationConfig) { |
+ return; |
+ } |
+ if (this.animationConfig.value && typeof this.animationConfig.value === 'function') { |
+ this._warn(this._logf('playAnimation', "Please put 'animationConfig' inside of your components 'properties' object instead of outside of it.")); |
+ return; |
+ } |
+ var thisConfig; |
+ if (type) { |
+ thisConfig = this.animationConfig[type]; |
+ } else { |
+ thisConfig = this.animationConfig; |
+ } |
+ if (!Array.isArray(thisConfig)) { |
+ thisConfig = [ thisConfig ]; |
+ } |
+ if (thisConfig) { |
+ for (var config, index = 0; config = thisConfig[index]; index++) { |
+ if (config.animatable) { |
+ config.animatable._getAnimationConfigRecursive(config.type || type, map, allConfigs); |
+ } else { |
+ if (config.id) { |
+ var cachedConfig = map[config.id]; |
+ if (cachedConfig) { |
+ if (!cachedConfig.isClone) { |
+ map[config.id] = this._cloneConfig(cachedConfig); |
+ cachedConfig = map[config.id]; |
+ } |
+ this._copyProperties(cachedConfig, config); |
+ } else { |
+ map[config.id] = config; |
+ } |
+ } else { |
+ allConfigs.push(config); |
+ } |
+ } |
+ } |
+ } |
+ }, |
+ getAnimationConfig: function(type) { |
+ var map = {}; |
+ var allConfigs = []; |
+ this._getAnimationConfigRecursive(type, map, allConfigs); |
+ for (var key in map) { |
+ allConfigs.push(map[key]); |
+ } |
+ return allConfigs; |
+ } |
+}; |
+ |
+Polymer.NeonAnimationRunnerBehaviorImpl = { |
+ _configureAnimations: function(configs) { |
+ var results = []; |
+ if (configs.length > 0) { |
+ for (var config, index = 0; config = configs[index]; index++) { |
+ var neonAnimation = document.createElement(config.name); |
+ if (neonAnimation.isNeonAnimation) { |
+ var result = null; |
+ try { |
+ result = neonAnimation.configure(config); |
+ if (typeof result.cancel != 'function') { |
+ result = document.timeline.play(result); |
+ } |
+ } catch (e) { |
+ result = null; |
+ console.warn('Couldnt play', '(', config.name, ').', e); |
+ } |
+ if (result) { |
+ results.push({ |
+ neonAnimation: neonAnimation, |
+ config: config, |
+ animation: result |
+ }); |
+ } |
+ } else { |
+ console.warn(this.is + ':', config.name, 'not found!'); |
+ } |
+ } |
+ } |
+ return results; |
+ }, |
+ _shouldComplete: function(activeEntries) { |
+ var finished = true; |
+ for (var i = 0; i < activeEntries.length; i++) { |
+ if (activeEntries[i].animation.playState != 'finished') { |
+ finished = false; |
+ break; |
+ } |
+ } |
+ return finished; |
+ }, |
+ _complete: function(activeEntries) { |
+ for (var i = 0; i < activeEntries.length; i++) { |
+ activeEntries[i].neonAnimation.complete(activeEntries[i].config); |
+ } |
+ for (var i = 0; i < activeEntries.length; i++) { |
+ activeEntries[i].animation.cancel(); |
+ } |
+ }, |
+ playAnimation: function(type, cookie) { |
+ var configs = this.getAnimationConfig(type); |
+ if (!configs) { |
+ return; |
+ } |
+ this._active = this._active || {}; |
+ if (this._active[type]) { |
+ this._complete(this._active[type]); |
+ delete this._active[type]; |
+ } |
+ var activeEntries = this._configureAnimations(configs); |
+ if (activeEntries.length == 0) { |
+ this.fire('neon-animation-finish', cookie, { |
+ bubbles: false |
+ }); |
+ return; |
+ } |
+ this._active[type] = activeEntries; |
+ for (var i = 0; i < activeEntries.length; i++) { |
+ activeEntries[i].animation.onfinish = function() { |
+ if (this._shouldComplete(activeEntries)) { |
+ this._complete(activeEntries); |
+ delete this._active[type]; |
+ this.fire('neon-animation-finish', cookie, { |
+ bubbles: false |
+ }); |
+ } |
+ }.bind(this); |
+ } |
+ }, |
+ cancelAnimation: function() { |
+ for (var k in this._animations) { |
+ this._animations[k].cancel(); |
+ } |
+ this._animations = {}; |
+ } |
+}; |
+ |
+Polymer.NeonAnimationRunnerBehavior = [ Polymer.NeonAnimatableBehavior, Polymer.NeonAnimationRunnerBehaviorImpl ]; |
+ |
+Polymer.NeonAnimationBehavior = { |
+ properties: { |
+ animationTiming: { |
+ type: Object, |
+ value: function() { |
+ return { |
+ duration: 500, |
+ easing: 'cubic-bezier(0.4, 0, 0.2, 1)', |
+ fill: 'both' |
+ }; |
+ } |
+ } |
+ }, |
+ isNeonAnimation: true, |
+ timingFromConfig: function(config) { |
+ if (config.timing) { |
+ for (var property in config.timing) { |
+ this.animationTiming[property] = config.timing[property]; |
+ } |
+ } |
+ return this.animationTiming; |
+ }, |
+ setPrefixedProperty: function(node, property, value) { |
+ var map = { |
+ transform: [ 'webkitTransform' ], |
+ transformOrigin: [ 'mozTransformOrigin', 'webkitTransformOrigin' ] |
+ }; |
+ var prefixes = map[property]; |
+ for (var prefix, index = 0; prefix = prefixes[index]; index++) { |
+ node.style[prefix] = value; |
+ } |
+ node.style[property] = value; |
+ }, |
+ complete: function() {} |
+}; |
+ |
+Polymer({ |
+ is: 'opaque-animation', |
+ behaviors: [ Polymer.NeonAnimationBehavior ], |
+ configure: function(config) { |
+ var node = config.node; |
+ this._effect = new KeyframeEffect(node, [ { |
+ opacity: '1' |
+ }, { |
+ opacity: '1' |
+ } ], this.timingFromConfig(config)); |
+ node.style.opacity = '0'; |
+ return this._effect; |
+ }, |
+ complete: function(config) { |
+ config.node.style.opacity = ''; |
+ } |
+}); |
+ |
+(function() { |
+ 'use strict'; |
+ var LAST_TOUCH_POSITION = { |
+ pageX: 0, |
+ pageY: 0 |
+ }; |
+ var ROOT_TARGET = null; |
+ var SCROLLABLE_NODES = []; |
+ Polymer.IronDropdownScrollManager = { |
+ get currentLockingElement() { |
+ return this._lockingElements[this._lockingElements.length - 1]; |
+ }, |
+ elementIsScrollLocked: function(element) { |
+ var currentLockingElement = this.currentLockingElement; |
+ if (currentLockingElement === undefined) return false; |
+ var scrollLocked; |
+ if (this._hasCachedLockedElement(element)) { |
+ return true; |
+ } |
+ if (this._hasCachedUnlockedElement(element)) { |
+ return false; |
+ } |
+ scrollLocked = !!currentLockingElement && currentLockingElement !== element && !this._composedTreeContains(currentLockingElement, element); |
+ if (scrollLocked) { |
+ this._lockedElementCache.push(element); |
+ } else { |
+ this._unlockedElementCache.push(element); |
+ } |
+ return scrollLocked; |
+ }, |
+ pushScrollLock: function(element) { |
+ if (this._lockingElements.indexOf(element) >= 0) { |
+ return; |
+ } |
+ if (this._lockingElements.length === 0) { |
+ this._lockScrollInteractions(); |
+ } |
+ this._lockingElements.push(element); |
+ this._lockedElementCache = []; |
+ this._unlockedElementCache = []; |
+ }, |
+ removeScrollLock: function(element) { |
+ var index = this._lockingElements.indexOf(element); |
+ if (index === -1) { |
+ return; |
+ } |
+ this._lockingElements.splice(index, 1); |
+ this._lockedElementCache = []; |
+ this._unlockedElementCache = []; |
+ if (this._lockingElements.length === 0) { |
+ this._unlockScrollInteractions(); |
+ } |
+ }, |
+ _lockingElements: [], |
+ _lockedElementCache: null, |
+ _unlockedElementCache: null, |
+ _hasCachedLockedElement: function(element) { |
+ return this._lockedElementCache.indexOf(element) > -1; |
+ }, |
+ _hasCachedUnlockedElement: function(element) { |
+ return this._unlockedElementCache.indexOf(element) > -1; |
+ }, |
+ _composedTreeContains: function(element, child) { |
+ var contentElements; |
+ var distributedNodes; |
+ var contentIndex; |
+ var nodeIndex; |
+ if (element.contains(child)) { |
+ return true; |
+ } |
+ contentElements = Polymer.dom(element).querySelectorAll('content'); |
+ for (contentIndex = 0; contentIndex < contentElements.length; ++contentIndex) { |
+ distributedNodes = Polymer.dom(contentElements[contentIndex]).getDistributedNodes(); |
+ for (nodeIndex = 0; nodeIndex < distributedNodes.length; ++nodeIndex) { |
+ if (this._composedTreeContains(distributedNodes[nodeIndex], child)) { |
+ return true; |
+ } |
+ } |
+ } |
+ return false; |
+ }, |
+ _scrollInteractionHandler: function(event) { |
+ if (event.cancelable && this._shouldPreventScrolling(event)) { |
+ event.preventDefault(); |
+ } |
+ if (event.targetTouches) { |
+ var touch = event.targetTouches[0]; |
+ LAST_TOUCH_POSITION.pageX = touch.pageX; |
+ LAST_TOUCH_POSITION.pageY = touch.pageY; |
+ } |
+ }, |
+ _lockScrollInteractions: function() { |
+ this._boundScrollHandler = this._boundScrollHandler || this._scrollInteractionHandler.bind(this); |
+ document.addEventListener('wheel', this._boundScrollHandler, true); |
+ document.addEventListener('mousewheel', this._boundScrollHandler, true); |
+ document.addEventListener('DOMMouseScroll', this._boundScrollHandler, true); |
+ document.addEventListener('touchstart', this._boundScrollHandler, true); |
+ document.addEventListener('touchmove', this._boundScrollHandler, true); |
+ }, |
+ _unlockScrollInteractions: function() { |
+ document.removeEventListener('wheel', this._boundScrollHandler, true); |
+ document.removeEventListener('mousewheel', this._boundScrollHandler, true); |
+ document.removeEventListener('DOMMouseScroll', this._boundScrollHandler, true); |
+ document.removeEventListener('touchstart', this._boundScrollHandler, true); |
+ document.removeEventListener('touchmove', this._boundScrollHandler, true); |
+ }, |
+ _shouldPreventScrolling: function(event) { |
+ var target = Polymer.dom(event).rootTarget; |
+ if (event.type !== 'touchmove' && ROOT_TARGET !== target) { |
+ ROOT_TARGET = target; |
+ SCROLLABLE_NODES = this._getScrollableNodes(Polymer.dom(event).path); |
+ } |
+ if (!SCROLLABLE_NODES.length) { |
+ return true; |
+ } |
+ if (event.type === 'touchstart') { |
+ return false; |
+ } |
+ var info = this._getScrollInfo(event); |
+ return !this._getScrollingNode(SCROLLABLE_NODES, info.deltaX, info.deltaY); |
+ }, |
+ _getScrollableNodes: function(nodes) { |
+ var scrollables = []; |
+ var lockingIndex = nodes.indexOf(this.currentLockingElement); |
+ for (var i = 0; i <= lockingIndex; i++) { |
+ var node = nodes[i]; |
+ if (node.nodeType === 11) { |
+ continue; |
+ } |
+ var style = node.style; |
+ if (style.overflow !== 'scroll' && style.overflow !== 'auto') { |
+ style = window.getComputedStyle(node); |
+ } |
+ if (style.overflow === 'scroll' || style.overflow === 'auto') { |
+ scrollables.push(node); |
+ } |
+ } |
+ return scrollables; |
+ }, |
+ _getScrollingNode: function(nodes, deltaX, deltaY) { |
+ if (!deltaX && !deltaY) { |
+ return; |
+ } |
+ var verticalScroll = Math.abs(deltaY) >= Math.abs(deltaX); |
+ for (var i = 0; i < nodes.length; i++) { |
+ var node = nodes[i]; |
+ var canScroll = false; |
+ if (verticalScroll) { |
+ canScroll = deltaY < 0 ? node.scrollTop > 0 : node.scrollTop < node.scrollHeight - node.clientHeight; |
+ } else { |
+ canScroll = deltaX < 0 ? node.scrollLeft > 0 : node.scrollLeft < node.scrollWidth - node.clientWidth; |
+ } |
+ if (canScroll) { |
+ return node; |
+ } |
+ } |
+ }, |
+ _getScrollInfo: function(event) { |
+ var info = { |
+ deltaX: event.deltaX, |
+ deltaY: event.deltaY |
+ }; |
+ if ('deltaX' in event) {} else if ('wheelDeltaX' in event) { |
+ info.deltaX = -event.wheelDeltaX; |
+ info.deltaY = -event.wheelDeltaY; |
+ } else if ('axis' in event) { |
+ info.deltaX = event.axis === 1 ? event.detail : 0; |
+ info.deltaY = event.axis === 2 ? event.detail : 0; |
+ } else if (event.targetTouches) { |
+ var touch = event.targetTouches[0]; |
+ info.deltaX = LAST_TOUCH_POSITION.pageX - touch.pageX; |
+ info.deltaY = LAST_TOUCH_POSITION.pageY - touch.pageY; |
+ } |
+ return info; |
+ } |
+ }; |
+})(); |
+ |
+(function() { |
+ 'use strict'; |
+ Polymer({ |
+ is: 'iron-dropdown', |
+ behaviors: [ Polymer.IronControlState, Polymer.IronA11yKeysBehavior, Polymer.IronOverlayBehavior, Polymer.NeonAnimationRunnerBehavior ], |
+ properties: { |
+ horizontalAlign: { |
+ type: String, |
+ value: 'left', |
+ reflectToAttribute: true |
+ }, |
+ verticalAlign: { |
+ type: String, |
+ value: 'top', |
+ reflectToAttribute: true |
+ }, |
+ openAnimationConfig: { |
+ type: Object |
+ }, |
+ closeAnimationConfig: { |
+ type: Object |
+ }, |
+ focusTarget: { |
+ type: Object |
+ }, |
+ noAnimations: { |
+ type: Boolean, |
+ value: false |
+ }, |
+ allowOutsideScroll: { |
+ type: Boolean, |
+ value: false |
+ }, |
+ _boundOnCaptureScroll: { |
+ type: Function, |
+ value: function() { |
+ return this._onCaptureScroll.bind(this); |
+ } |
+ } |
+ }, |
+ listeners: { |
+ 'neon-animation-finish': '_onNeonAnimationFinish' |
+ }, |
+ observers: [ '_updateOverlayPosition(positionTarget, verticalAlign, horizontalAlign, verticalOffset, horizontalOffset)' ], |
+ get containedElement() { |
+ return Polymer.dom(this.$.content).getDistributedNodes()[0]; |
+ }, |
+ get _focusTarget() { |
+ return this.focusTarget || this.containedElement; |
+ }, |
+ ready: function() { |
+ this._scrollTop = 0; |
+ this._scrollLeft = 0; |
+ this._refitOnScrollRAF = null; |
+ }, |
+ attached: function() { |
+ if (!this.sizingTarget || this.sizingTarget === this) { |
+ this.sizingTarget = this.containedElement; |
+ } |
+ }, |
+ detached: function() { |
+ this.cancelAnimation(); |
+ document.removeEventListener('scroll', this._boundOnCaptureScroll); |
+ Polymer.IronDropdownScrollManager.removeScrollLock(this); |
+ }, |
+ _openedChanged: function() { |
+ if (this.opened && this.disabled) { |
+ this.cancel(); |
+ } else { |
+ this.cancelAnimation(); |
+ this._updateAnimationConfig(); |
+ this._saveScrollPosition(); |
+ if (this.opened) { |
+ document.addEventListener('scroll', this._boundOnCaptureScroll); |
+ !this.allowOutsideScroll && Polymer.IronDropdownScrollManager.pushScrollLock(this); |
+ } else { |
+ document.removeEventListener('scroll', this._boundOnCaptureScroll); |
+ Polymer.IronDropdownScrollManager.removeScrollLock(this); |
+ } |
+ Polymer.IronOverlayBehaviorImpl._openedChanged.apply(this, arguments); |
+ } |
+ }, |
+ _renderOpened: function() { |
+ if (!this.noAnimations && this.animationConfig.open) { |
+ this.$.contentWrapper.classList.add('animating'); |
+ this.playAnimation('open'); |
+ } else { |
+ Polymer.IronOverlayBehaviorImpl._renderOpened.apply(this, arguments); |
+ } |
+ }, |
+ _renderClosed: function() { |
+ if (!this.noAnimations && this.animationConfig.close) { |
+ this.$.contentWrapper.classList.add('animating'); |
+ this.playAnimation('close'); |
+ } else { |
+ Polymer.IronOverlayBehaviorImpl._renderClosed.apply(this, arguments); |
+ } |
+ }, |
+ _onNeonAnimationFinish: function() { |
+ this.$.contentWrapper.classList.remove('animating'); |
+ if (this.opened) { |
+ this._finishRenderOpened(); |
+ } else { |
+ this._finishRenderClosed(); |
+ } |
+ }, |
+ _onCaptureScroll: function() { |
+ if (!this.allowOutsideScroll) { |
+ this._restoreScrollPosition(); |
+ } else { |
+ this._refitOnScrollRAF && window.cancelAnimationFrame(this._refitOnScrollRAF); |
+ this._refitOnScrollRAF = window.requestAnimationFrame(this.refit.bind(this)); |
+ } |
+ }, |
+ _saveScrollPosition: function() { |
+ if (document.scrollingElement) { |
+ this._scrollTop = document.scrollingElement.scrollTop; |
+ this._scrollLeft = document.scrollingElement.scrollLeft; |
+ } else { |
+ this._scrollTop = Math.max(document.documentElement.scrollTop, document.body.scrollTop); |
+ this._scrollLeft = Math.max(document.documentElement.scrollLeft, document.body.scrollLeft); |
+ } |
+ }, |
+ _restoreScrollPosition: function() { |
+ if (document.scrollingElement) { |
+ document.scrollingElement.scrollTop = this._scrollTop; |
+ document.scrollingElement.scrollLeft = this._scrollLeft; |
+ } else { |
+ document.documentElement.scrollTop = this._scrollTop; |
+ document.documentElement.scrollLeft = this._scrollLeft; |
+ document.body.scrollTop = this._scrollTop; |
+ document.body.scrollLeft = this._scrollLeft; |
+ } |
+ }, |
+ _updateAnimationConfig: function() { |
+ var animations = (this.openAnimationConfig || []).concat(this.closeAnimationConfig || []); |
+ for (var i = 0; i < animations.length; i++) { |
+ animations[i].node = this.containedElement; |
+ } |
+ this.animationConfig = { |
+ open: this.openAnimationConfig, |
+ close: this.closeAnimationConfig |
+ }; |
+ }, |
+ _updateOverlayPosition: function() { |
+ if (this.isAttached) { |
+ this.notifyResize(); |
+ } |
+ }, |
+ _applyFocus: function() { |
+ var focusTarget = this.focusTarget || this.containedElement; |
+ if (focusTarget && this.opened && !this.noAutoFocus) { |
+ focusTarget.focus(); |
+ } else { |
+ Polymer.IronOverlayBehaviorImpl._applyFocus.apply(this, arguments); |
+ } |
+ } |
+ }); |
+})(); |
+ |
+Polymer({ |
+ is: 'fade-in-animation', |
+ behaviors: [ Polymer.NeonAnimationBehavior ], |
+ configure: function(config) { |
+ var node = config.node; |
+ this._effect = new KeyframeEffect(node, [ { |
+ opacity: '0' |
+ }, { |
+ opacity: '1' |
+ } ], this.timingFromConfig(config)); |
+ return this._effect; |
+ } |
+}); |
+ |
+Polymer({ |
+ is: 'fade-out-animation', |
+ behaviors: [ Polymer.NeonAnimationBehavior ], |
+ configure: function(config) { |
+ var node = config.node; |
+ this._effect = new KeyframeEffect(node, [ { |
+ opacity: '1' |
+ }, { |
+ opacity: '0' |
+ } ], this.timingFromConfig(config)); |
+ return this._effect; |
+ } |
+}); |
+ |
+Polymer({ |
+ is: 'paper-menu-grow-height-animation', |
+ behaviors: [ Polymer.NeonAnimationBehavior ], |
+ configure: function(config) { |
+ var node = config.node; |
+ var rect = node.getBoundingClientRect(); |
+ var height = rect.height; |
+ this._effect = new KeyframeEffect(node, [ { |
+ height: height / 2 + 'px' |
+ }, { |
+ height: height + 'px' |
+ } ], this.timingFromConfig(config)); |
+ return this._effect; |
+ } |
+}); |
+ |
+Polymer({ |
+ is: 'paper-menu-grow-width-animation', |
+ behaviors: [ Polymer.NeonAnimationBehavior ], |
+ configure: function(config) { |
+ var node = config.node; |
+ var rect = node.getBoundingClientRect(); |
+ var width = rect.width; |
+ this._effect = new KeyframeEffect(node, [ { |
+ width: width / 2 + 'px' |
+ }, { |
+ width: width + 'px' |
+ } ], this.timingFromConfig(config)); |
+ return this._effect; |
+ } |
+}); |
+ |
+Polymer({ |
+ is: 'paper-menu-shrink-width-animation', |
+ behaviors: [ Polymer.NeonAnimationBehavior ], |
+ configure: function(config) { |
+ var node = config.node; |
+ var rect = node.getBoundingClientRect(); |
+ var width = rect.width; |
+ this._effect = new KeyframeEffect(node, [ { |
+ width: width + 'px' |
+ }, { |
+ width: width - width / 20 + 'px' |
+ } ], this.timingFromConfig(config)); |
+ return this._effect; |
+ } |
+}); |
+ |
+Polymer({ |
+ is: 'paper-menu-shrink-height-animation', |
+ behaviors: [ Polymer.NeonAnimationBehavior ], |
+ configure: function(config) { |
+ var node = config.node; |
+ var rect = node.getBoundingClientRect(); |
+ var height = rect.height; |
+ var top = rect.top; |
+ this.setPrefixedProperty(node, 'transformOrigin', '0 0'); |
+ this._effect = new KeyframeEffect(node, [ { |
+ height: height + 'px', |
+ transform: 'translateY(0)' |
+ }, { |
+ height: height / 2 + 'px', |
+ transform: 'translateY(-20px)' |
+ } ], this.timingFromConfig(config)); |
+ return this._effect; |
+ } |
+}); |
+ |
+// Copyright 2016 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+var SLIDE_CUBIC_BEZIER = 'cubic-bezier(0.3, 0.95, 0.5, 1)'; |
+ |
+Polymer({ |
+ is: 'cr-shared-menu', |
+ behaviors: [ Polymer.IronA11yKeysBehavior ], |
+ properties: { |
+ menuOpen: { |
+ type: Boolean, |
+ observer: 'menuOpenChanged_', |
+ value: false, |
+ notify: true |
+ }, |
+ itemData: { |
+ type: Object, |
+ value: null |
+ }, |
+ keyEventTarget: { |
+ type: Object, |
+ value: function() { |
+ return this.$.menu; |
+ } |
+ }, |
+ openAnimationConfig: { |
+ type: Object, |
+ value: function() { |
+ return [ { |
+ name: 'fade-in-animation', |
+ timing: { |
+ delay: 50, |
+ duration: 200 |
+ } |
+ }, { |
+ name: 'paper-menu-grow-width-animation', |
+ timing: { |
+ delay: 50, |
+ duration: 150, |
+ easing: SLIDE_CUBIC_BEZIER |
+ } |
+ }, { |
+ name: 'paper-menu-grow-height-animation', |
+ timing: { |
+ delay: 100, |
+ duration: 275, |
+ easing: SLIDE_CUBIC_BEZIER |
+ } |
+ } ]; |
+ } |
+ }, |
+ closeAnimationConfig: { |
+ type: Object, |
+ value: function() { |
+ return [ { |
+ name: 'fade-out-animation', |
+ timing: { |
+ duration: 150 |
+ } |
+ } ]; |
+ } |
+ } |
+ }, |
+ keyBindings: { |
+ tab: 'onTabPressed_' |
+ }, |
+ listeners: { |
+ 'dropdown.iron-overlay-canceled': 'onOverlayCanceled_' |
+ }, |
+ lastAnchor_: null, |
+ firstFocus_: null, |
+ lastFocus_: null, |
+ attached: function() { |
+ window.addEventListener('resize', this.closeMenu.bind(this)); |
+ }, |
+ closeMenu: function() { |
+ if (this.root.activeElement == null) { |
+ this.$.dropdown.restoreFocusOnClose = false; |
+ } |
+ this.menuOpen = false; |
+ }, |
+ openMenu: function(anchor, opt_itemData) { |
+ if (this.lastAnchor_ == anchor && this.menuOpen) return; |
+ if (this.menuOpen) this.closeMenu(); |
+ this.itemData = opt_itemData || null; |
+ this.lastAnchor_ = anchor; |
+ this.$.dropdown.restoreFocusOnClose = true; |
+ var focusableChildren = Polymer.dom(this).querySelectorAll('[tabindex]:not([disabled]):not([hidden]),' + 'button:not([disabled]):not([hidden])'); |
+ if (focusableChildren.length > 0) { |
+ this.$.dropdown.focusTarget = focusableChildren[0]; |
+ this.firstFocus_ = focusableChildren[0]; |
+ this.lastFocus_ = focusableChildren[focusableChildren.length - 1]; |
+ } |
+ this.$.dropdown.positionTarget = anchor; |
+ this.menuOpen = true; |
+ }, |
+ toggleMenu: function(anchor, opt_itemData) { |
+ if (anchor == this.lastAnchor_ && this.menuOpen) this.closeMenu(); else this.openMenu(anchor, opt_itemData); |
+ }, |
+ onTabPressed_: function(e) { |
+ if (!this.firstFocus_ || !this.lastFocus_) return; |
+ var toFocus; |
+ var keyEvent = e.detail.keyboardEvent; |
+ if (keyEvent.shiftKey && keyEvent.target == this.firstFocus_) toFocus = this.lastFocus_; else if (!keyEvent.shiftKey && keyEvent.target == this.lastFocus_) toFocus = this.firstFocus_; |
+ if (!toFocus) return; |
+ e.preventDefault(); |
+ toFocus.focus(); |
+ }, |
+ menuOpenChanged_: function() { |
+ if (!this.menuOpen) { |
+ this.itemData = null; |
+ this.lastAnchor_ = null; |
+ } |
+ }, |
+ onOverlayCanceled_: function(e) { |
+ if (e.detail.type == 'tap') this.$.dropdown.restoreFocusOnClose = false; |
+ } |
+}); |
+ |
+Polymer({ |
+ is: 'paper-icon-button-light', |
+ "extends": 'button', |
+ behaviors: [ Polymer.PaperRippleBehavior ], |
+ listeners: { |
+ down: '_rippleDown', |
+ up: '_rippleUp', |
+ focus: '_rippleDown', |
+ blur: '_rippleUp' |
+ }, |
+ _rippleDown: function() { |
+ this.getRipple().downAction(); |
+ }, |
+ _rippleUp: function() { |
+ this.getRipple().upAction(); |
+ }, |
+ ensureRipple: function(var_args) { |
+ var lastRipple = this._ripple; |
+ Polymer.PaperRippleBehavior.ensureRipple.apply(this, arguments); |
+ if (this._ripple && this._ripple !== lastRipple) { |
+ this._ripple.center = true; |
+ this._ripple.classList.add('circle'); |
+ } |
+ } |
+}); |
+ |
+// Copyright 2016 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+Polymer({ |
+ is: 'history-synced-device-card', |
+ properties: { |
+ device: String, |
+ lastUpdateTime: String, |
+ tabs: { |
+ type: Array, |
+ value: function() { |
+ return []; |
+ }, |
+ observer: 'updateIcons_' |
+ }, |
+ separatorIndexes: Array, |
+ opened: Boolean, |
+ searchTerm: String, |
+ sessionTag: String |
+ }, |
+ openTab_: function(e) { |
+ var tab = e.model.tab; |
+ var browserService = md_history.BrowserService.getInstance(); |
+ browserService.recordHistogram(SYNCED_TABS_HISTOGRAM_NAME, SyncedTabsHistogram.LINK_CLICKED, SyncedTabsHistogram.LIMIT); |
+ browserService.openForeignSessionTab(this.sessionTag, tab.windowId, tab.sessionId, e); |
+ e.preventDefault(); |
+ }, |
+ toggleTabCard: function() { |
+ var histogramValue = this.$.collapse.opened ? SyncedTabsHistogram.COLLAPSE_SESSION : SyncedTabsHistogram.EXPAND_SESSION; |
+ md_history.BrowserService.getInstance().recordHistogram(SYNCED_TABS_HISTOGRAM_NAME, histogramValue, SyncedTabsHistogram.LIMIT); |
+ this.$.collapse.toggle(); |
+ this.$['dropdown-indicator'].icon = this.$.collapse.opened ? 'cr:expand-less' : 'cr:expand-more'; |
+ }, |
+ updateIcons_: function() { |
+ this.async(function() { |
+ var icons = Polymer.dom(this.root).querySelectorAll('.website-icon'); |
+ for (var i = 0; i < this.tabs.length; i++) { |
+ icons[i].style.backgroundImage = cr.icon.getFavicon(this.tabs[i].url); |
+ } |
+ }); |
+ }, |
+ isWindowSeparatorIndex_: function(index, separatorIndexes) { |
+ return this.separatorIndexes.indexOf(index) != -1; |
+ }, |
+ getCollapseIcon_: function(opened) { |
+ return opened ? 'cr:expand-less' : 'cr:expand-more'; |
+ }, |
+ getCollapseTitle_: function(opened) { |
+ return opened ? loadTimeData.getString('collapseSessionButton') : loadTimeData.getString('expandSessionButton'); |
+ }, |
+ onMenuButtonTap_: function(e) { |
+ this.fire('toggle-menu', { |
+ target: Polymer.dom(e).localTarget, |
+ tag: this.sessionTag |
+ }); |
+ e.stopPropagation(); |
+ }, |
+ onLinkRightClick_: function() { |
+ md_history.BrowserService.getInstance().recordHistogram(SYNCED_TABS_HISTOGRAM_NAME, SyncedTabsHistogram.LINK_RIGHT_CLICKED, SyncedTabsHistogram.LIMIT); |
+ } |
+}); |
+ |
+// Copyright 2016 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+var ForeignDeviceInternal; |
+ |
+Polymer({ |
+ is: 'history-synced-device-manager', |
+ properties: { |
+ sessionList: { |
+ type: Array, |
+ observer: 'updateSyncedDevices' |
+ }, |
+ searchTerm: { |
+ type: String, |
+ observer: 'searchTermChanged' |
+ }, |
+ syncedDevices_: { |
+ type: Array, |
+ value: function() { |
+ return []; |
+ } |
+ }, |
+ signInState: { |
+ type: Boolean, |
+ observer: 'signInStateChanged_' |
+ }, |
+ guestSession_: { |
+ type: Boolean, |
+ value: loadTimeData.getBoolean('isGuestSession') |
+ }, |
+ fetchingSyncedTabs_: { |
+ type: Boolean, |
+ value: false |
+ }, |
+ hasSeenForeignData_: Boolean |
+ }, |
+ listeners: { |
+ 'toggle-menu': 'onToggleMenu_', |
+ scroll: 'onListScroll_' |
+ }, |
+ attached: function() { |
+ chrome.send('otherDevicesInitialized'); |
+ md_history.BrowserService.getInstance().recordHistogram(SYNCED_TABS_HISTOGRAM_NAME, SyncedTabsHistogram.INITIALIZED, SyncedTabsHistogram.LIMIT); |
+ }, |
+ getContentScrollTarget: function() { |
+ return this; |
+ }, |
+ createInternalDevice_: function(session) { |
+ var tabs = []; |
+ var separatorIndexes = []; |
+ for (var i = 0; i < session.windows.length; i++) { |
+ var windowId = session.windows[i].sessionId; |
+ var newTabs = session.windows[i].tabs; |
+ if (newTabs.length == 0) continue; |
+ newTabs.forEach(function(tab) { |
+ tab.windowId = windowId; |
+ }); |
+ var windowAdded = false; |
+ if (!this.searchTerm) { |
+ tabs = tabs.concat(newTabs); |
+ windowAdded = true; |
+ } else { |
+ var searchText = this.searchTerm.toLowerCase(); |
+ for (var j = 0; j < newTabs.length; j++) { |
+ var tab = newTabs[j]; |
+ if (tab.title.toLowerCase().indexOf(searchText) != -1) { |
+ tabs.push(tab); |
+ windowAdded = true; |
+ } |
+ } |
+ } |
+ if (windowAdded && i != session.windows.length - 1) separatorIndexes.push(tabs.length - 1); |
+ } |
+ return { |
+ device: session.name, |
+ lastUpdateTime: '– ' + session.modifiedTime, |
+ opened: true, |
+ separatorIndexes: separatorIndexes, |
+ timestamp: session.timestamp, |
+ tabs: tabs, |
+ tag: session.tag |
+ }; |
+ }, |
+ onSignInTap_: function() { |
+ chrome.send('startSignInFlow'); |
+ }, |
+ onListScroll_: function() { |
+ var menu = this.$.menu.getIfExists(); |
+ if (menu) menu.closeMenu(); |
+ }, |
+ onToggleMenu_: function(e) { |
+ var menu = this.$.menu.get(); |
+ menu.toggleMenu(e.detail.target, e.detail.tag); |
+ if (menu.menuOpen) { |
+ md_history.BrowserService.getInstance().recordHistogram(SYNCED_TABS_HISTOGRAM_NAME, SyncedTabsHistogram.SHOW_SESSION_MENU, SyncedTabsHistogram.LIMIT); |
+ } |
+ }, |
+ onOpenAllTap_: function() { |
+ var menu = assert(this.$.menu.getIfExists()); |
+ var browserService = md_history.BrowserService.getInstance(); |
+ browserService.recordHistogram(SYNCED_TABS_HISTOGRAM_NAME, SyncedTabsHistogram.OPEN_ALL, SyncedTabsHistogram.LIMIT); |
+ browserService.openForeignSessionAllTabs(menu.itemData); |
+ menu.closeMenu(); |
+ }, |
+ onDeleteSessionTap_: function() { |
+ var menu = assert(this.$.menu.getIfExists()); |
+ var browserService = md_history.BrowserService.getInstance(); |
+ browserService.recordHistogram(SYNCED_TABS_HISTOGRAM_NAME, SyncedTabsHistogram.HIDE_FOR_NOW, SyncedTabsHistogram.LIMIT); |
+ browserService.deleteForeignSession(menu.itemData); |
+ menu.closeMenu(); |
+ }, |
+ clearDisplayedSyncedDevices_: function() { |
+ this.syncedDevices_ = []; |
+ }, |
+ showNoSyncedMessage: function(signInState, syncedDevicesLength, guestSession) { |
+ if (guestSession) return true; |
+ return signInState && syncedDevicesLength == 0; |
+ }, |
+ showSignInGuide: function(signInState, guestSession) { |
+ var show = !signInState && !guestSession; |
+ if (show) { |
+ md_history.BrowserService.getInstance().recordAction('Signin_Impression_FromRecentTabs'); |
+ } |
+ return show; |
+ }, |
+ noSyncedTabsMessage: function(fetchingSyncedTabs) { |
+ return loadTimeData.getString(fetchingSyncedTabs ? 'loading' : 'noSyncedResults'); |
+ }, |
+ updateSyncedDevices: function(sessionList) { |
+ this.fetchingSyncedTabs_ = false; |
+ if (!sessionList) return; |
+ if (sessionList.length > 0 && !this.hasSeenForeignData_) { |
+ this.hasSeenForeignData_ = true; |
+ md_history.BrowserService.getInstance().recordHistogram(SYNCED_TABS_HISTOGRAM_NAME, SyncedTabsHistogram.HAS_FOREIGN_DATA, SyncedTabsHistogram.LIMIT); |
+ } |
+ var updateCount = Math.min(sessionList.length, this.syncedDevices_.length); |
+ for (var i = 0; i < updateCount; i++) { |
+ var oldDevice = this.syncedDevices_[i]; |
+ if (oldDevice.tag != sessionList[i].tag || oldDevice.timestamp != sessionList[i].timestamp) { |
+ this.splice('syncedDevices_', i, 1, this.createInternalDevice_(sessionList[i])); |
+ } |
+ } |
+ if (sessionList.length >= this.syncedDevices_.length) { |
+ for (var i = updateCount; i < sessionList.length; i++) { |
+ this.push('syncedDevices_', this.createInternalDevice_(sessionList[i])); |
+ } |
+ } else { |
+ this.splice('syncedDevices_', updateCount, this.syncedDevices_.length - updateCount); |
+ } |
+ }, |
+ tabSyncDisabled: function() { |
+ this.fetchingSyncedTabs_ = false; |
+ this.clearDisplayedSyncedDevices_(); |
+ }, |
+ signInStateChanged_: function() { |
+ this.fire('history-view-changed'); |
+ if (!this.signInState) { |
+ this.clearDisplayedSyncedDevices_(); |
+ return; |
+ } |
+ this.fetchingSyncedTabs_ = true; |
+ }, |
+ searchTermChanged: function(searchTerm) { |
+ this.clearDisplayedSyncedDevices_(); |
+ this.updateSyncedDevices(this.sessionList); |
+ } |
+}); |
+ |
+// Copyright 2016 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+Polymer({ |
+ is: 'cr-dialog', |
+ "extends": 'dialog', |
+ created: function() { |
+ window.addEventListener('popstate', function() { |
+ if (this.open) this.cancel(); |
+ }.bind(this)); |
+ }, |
+ cancel: function() { |
+ this.fire('cancel'); |
+ HTMLDialogElement.prototype.close.call(this, ''); |
+ }, |
+ close: function(opt_returnValue) { |
+ HTMLDialogElement.prototype.close.call(this, 'success'); |
+ }, |
+ getCloseButton: function() { |
+ return this.$.close; |
+ } |
+}); |
+ |
+Polymer({ |
+ is: 'app-drawer', |
+ properties: { |
+ opened: { |
+ type: Boolean, |
+ value: false, |
+ notify: true, |
+ reflectToAttribute: true |
+ }, |
+ persistent: { |
+ type: Boolean, |
+ value: false, |
+ reflectToAttribute: true |
+ }, |
+ align: { |
+ type: String, |
+ value: 'left' |
+ }, |
+ position: { |
+ type: String, |
+ readOnly: true, |
+ value: 'left', |
+ reflectToAttribute: true |
+ }, |
+ swipeOpen: { |
+ type: Boolean, |
+ value: false, |
+ reflectToAttribute: true |
+ }, |
+ noFocusTrap: { |
+ type: Boolean, |
+ value: false |
+ } |
+ }, |
+ observers: [ 'resetLayout(position)', '_resetPosition(align, isAttached)' ], |
+ _translateOffset: 0, |
+ _trackDetails: null, |
+ _drawerState: 0, |
+ _boundEscKeydownHandler: null, |
+ _firstTabStop: null, |
+ _lastTabStop: null, |
+ ready: function() { |
+ this.setScrollDirection('y'); |
+ this._setTransitionDuration('0s'); |
+ }, |
+ attached: function() { |
+ Polymer.RenderStatus.afterNextRender(this, function() { |
+ this._setTransitionDuration(''); |
+ this._boundEscKeydownHandler = this._escKeydownHandler.bind(this); |
+ this._resetDrawerState(); |
+ this.listen(this, 'track', '_track'); |
+ this.addEventListener('transitionend', this._transitionend.bind(this)); |
+ this.addEventListener('keydown', this._tabKeydownHandler.bind(this)); |
+ }); |
+ }, |
+ detached: function() { |
+ document.removeEventListener('keydown', this._boundEscKeydownHandler); |
+ }, |
+ open: function() { |
+ this.opened = true; |
+ }, |
+ close: function() { |
+ this.opened = false; |
+ }, |
+ toggle: function() { |
+ this.opened = !this.opened; |
+ }, |
+ getWidth: function() { |
+ return this.$.contentContainer.offsetWidth; |
+ }, |
+ resetLayout: function() { |
+ this.debounce('_resetLayout', function() { |
+ this.fire('app-drawer-reset-layout'); |
+ }, 1); |
+ }, |
+ _isRTL: function() { |
+ return window.getComputedStyle(this).direction === 'rtl'; |
+ }, |
+ _resetPosition: function() { |
+ switch (this.align) { |
+ case 'start': |
+ this._setPosition(this._isRTL() ? 'right' : 'left'); |
+ return; |
+ |
+ case 'end': |
+ this._setPosition(this._isRTL() ? 'left' : 'right'); |
+ return; |
+ } |
+ this._setPosition(this.align); |
+ }, |
+ _escKeydownHandler: function(event) { |
+ var ESC_KEYCODE = 27; |
+ if (event.keyCode === ESC_KEYCODE) { |
+ event.preventDefault(); |
+ this.close(); |
+ } |
+ }, |
+ _track: function(event) { |
+ if (this.persistent) { |
+ return; |
+ } |
+ event.preventDefault(); |
+ switch (event.detail.state) { |
+ case 'start': |
+ this._trackStart(event); |
+ break; |
+ |
+ case 'track': |
+ this._trackMove(event); |
+ break; |
+ |
+ case 'end': |
+ this._trackEnd(event); |
+ break; |
+ } |
+ }, |
+ _trackStart: function(event) { |
+ this._drawerState = this._DRAWER_STATE.TRACKING; |
+ this._setTransitionDuration('0s'); |
+ this.style.visibility = 'visible'; |
+ var rect = this.$.contentContainer.getBoundingClientRect(); |
+ if (this.position === 'left') { |
+ this._translateOffset = rect.left; |
+ } else { |
+ this._translateOffset = rect.right - window.innerWidth; |
+ } |
+ this._trackDetails = []; |
+ }, |
+ _trackMove: function(event) { |
+ this._translateDrawer(event.detail.dx + this._translateOffset); |
+ this._trackDetails.push({ |
+ dx: event.detail.dx, |
+ timeStamp: Date.now() |
+ }); |
+ }, |
+ _trackEnd: function(event) { |
+ var x = event.detail.dx + this._translateOffset; |
+ var drawerWidth = this.getWidth(); |
+ var isPositionLeft = this.position === 'left'; |
+ var isInEndState = isPositionLeft ? x >= 0 || x <= -drawerWidth : x <= 0 || x >= drawerWidth; |
+ if (!isInEndState) { |
+ var trackDetails = this._trackDetails; |
+ this._trackDetails = null; |
+ this._flingDrawer(event, trackDetails); |
+ if (this._drawerState === this._DRAWER_STATE.FLINGING) { |
+ return; |
+ } |
+ } |
+ var halfWidth = drawerWidth / 2; |
+ if (event.detail.dx < -halfWidth) { |
+ this.opened = this.position === 'right'; |
+ } else if (event.detail.dx > halfWidth) { |
+ this.opened = this.position === 'left'; |
+ } |
+ if (isInEndState) { |
+ this._resetDrawerState(); |
+ } |
+ this._setTransitionDuration(''); |
+ this._resetDrawerTranslate(); |
+ this.style.visibility = ''; |
+ }, |
+ _calculateVelocity: function(event, trackDetails) { |
+ var now = Date.now(); |
+ var timeLowerBound = now - 100; |
+ var trackDetail; |
+ var min = 0; |
+ var max = trackDetails.length - 1; |
+ while (min <= max) { |
+ var mid = min + max >> 1; |
+ var d = trackDetails[mid]; |
+ if (d.timeStamp >= timeLowerBound) { |
+ trackDetail = d; |
+ max = mid - 1; |
+ } else { |
+ min = mid + 1; |
+ } |
+ } |
+ if (trackDetail) { |
+ var dx = event.detail.dx - trackDetail.dx; |
+ var dt = now - trackDetail.timeStamp || 1; |
+ return dx / dt; |
+ } |
+ return 0; |
+ }, |
+ _flingDrawer: function(event, trackDetails) { |
+ var velocity = this._calculateVelocity(event, trackDetails); |
+ if (Math.abs(velocity) < this._MIN_FLING_THRESHOLD) { |
+ return; |
+ } |
+ this._drawerState = this._DRAWER_STATE.FLINGING; |
+ var x = event.detail.dx + this._translateOffset; |
+ var drawerWidth = this.getWidth(); |
+ var isPositionLeft = this.position === 'left'; |
+ var isVelocityPositive = velocity > 0; |
+ var isClosingLeft = !isVelocityPositive && isPositionLeft; |
+ var isClosingRight = isVelocityPositive && !isPositionLeft; |
+ var dx; |
+ if (isClosingLeft) { |
+ dx = -(x + drawerWidth); |
+ } else if (isClosingRight) { |
+ dx = drawerWidth - x; |
+ } else { |
+ dx = -x; |
+ } |
+ if (isVelocityPositive) { |
+ velocity = Math.max(velocity, this._MIN_TRANSITION_VELOCITY); |
+ this.opened = this.position === 'left'; |
+ } else { |
+ velocity = Math.min(velocity, -this._MIN_TRANSITION_VELOCITY); |
+ this.opened = this.position === 'right'; |
+ } |
+ this._setTransitionDuration(this._FLING_INITIAL_SLOPE * dx / velocity + 'ms'); |
+ this._setTransitionTimingFunction(this._FLING_TIMING_FUNCTION); |
+ this._resetDrawerTranslate(); |
+ }, |
+ _transitionend: function(event) { |
+ var target = Polymer.dom(event).rootTarget; |
+ if (target === this.$.contentContainer || target === this.$.scrim) { |
+ if (this._drawerState === this._DRAWER_STATE.FLINGING) { |
+ this._setTransitionDuration(''); |
+ this._setTransitionTimingFunction(''); |
+ this.style.visibility = ''; |
+ } |
+ this._resetDrawerState(); |
+ } |
+ }, |
+ _setTransitionDuration: function(duration) { |
+ this.$.contentContainer.style.transitionDuration = duration; |
+ this.$.scrim.style.transitionDuration = duration; |
+ }, |
+ _setTransitionTimingFunction: function(timingFunction) { |
+ this.$.contentContainer.style.transitionTimingFunction = timingFunction; |
+ this.$.scrim.style.transitionTimingFunction = timingFunction; |
+ }, |
+ _translateDrawer: function(x) { |
+ var drawerWidth = this.getWidth(); |
+ if (this.position === 'left') { |
+ x = Math.max(-drawerWidth, Math.min(x, 0)); |
+ this.$.scrim.style.opacity = 1 + x / drawerWidth; |
+ } else { |
+ x = Math.max(0, Math.min(x, drawerWidth)); |
+ this.$.scrim.style.opacity = 1 - x / drawerWidth; |
+ } |
+ this.translate3d(x + 'px', '0', '0', this.$.contentContainer); |
+ }, |
+ _resetDrawerTranslate: function() { |
+ this.$.scrim.style.opacity = ''; |
+ this.transform('', this.$.contentContainer); |
+ }, |
+ _resetDrawerState: function() { |
+ var oldState = this._drawerState; |
+ if (this.opened) { |
+ this._drawerState = this.persistent ? this._DRAWER_STATE.OPENED_PERSISTENT : this._DRAWER_STATE.OPENED; |
+ } else { |
+ this._drawerState = this._DRAWER_STATE.CLOSED; |
+ } |
+ if (oldState !== this._drawerState) { |
+ if (this._drawerState === this._DRAWER_STATE.OPENED) { |
+ this._setKeyboardFocusTrap(); |
+ document.addEventListener('keydown', this._boundEscKeydownHandler); |
+ document.body.style.overflow = 'hidden'; |
+ } else { |
+ document.removeEventListener('keydown', this._boundEscKeydownHandler); |
+ document.body.style.overflow = ''; |
+ } |
+ if (oldState !== this._DRAWER_STATE.INIT) { |
+ this.fire('app-drawer-transitioned'); |
+ } |
+ } |
+ }, |
+ _setKeyboardFocusTrap: function() { |
+ if (this.noFocusTrap) { |
+ return; |
+ } |
+ var focusableElementsSelector = [ 'a[href]:not([tabindex="-1"])', 'area[href]:not([tabindex="-1"])', 'input:not([disabled]):not([tabindex="-1"])', 'select:not([disabled]):not([tabindex="-1"])', 'textarea:not([disabled]):not([tabindex="-1"])', 'button:not([disabled]):not([tabindex="-1"])', 'iframe:not([tabindex="-1"])', '[tabindex]:not([tabindex="-1"])', '[contentEditable=true]:not([tabindex="-1"])' ].join(','); |
+ var focusableElements = Polymer.dom(this).querySelectorAll(focusableElementsSelector); |
+ if (focusableElements.length > 0) { |
+ this._firstTabStop = focusableElements[0]; |
+ this._lastTabStop = focusableElements[focusableElements.length - 1]; |
+ } else { |
+ this._firstTabStop = null; |
+ this._lastTabStop = null; |
+ } |
+ var tabindex = this.getAttribute('tabindex'); |
+ if (tabindex && parseInt(tabindex, 10) > -1) { |
+ this.focus(); |
+ } else if (this._firstTabStop) { |
+ this._firstTabStop.focus(); |
+ } |
+ }, |
+ _tabKeydownHandler: function(event) { |
+ if (this.noFocusTrap) { |
+ return; |
+ } |
+ var TAB_KEYCODE = 9; |
+ if (this._drawerState === this._DRAWER_STATE.OPENED && event.keyCode === TAB_KEYCODE) { |
+ if (event.shiftKey) { |
+ if (this._firstTabStop && Polymer.dom(event).localTarget === this._firstTabStop) { |
+ event.preventDefault(); |
+ this._lastTabStop.focus(); |
+ } |
+ } else { |
+ if (this._lastTabStop && Polymer.dom(event).localTarget === this._lastTabStop) { |
+ event.preventDefault(); |
+ this._firstTabStop.focus(); |
+ } |
+ } |
+ } |
+ }, |
+ _MIN_FLING_THRESHOLD: .2, |
+ _MIN_TRANSITION_VELOCITY: 1.2, |
+ _FLING_TIMING_FUNCTION: 'cubic-bezier(0.667, 1, 0.667, 1)', |
+ _FLING_INITIAL_SLOPE: 1.5, |
+ _DRAWER_STATE: { |
+ INIT: 0, |
+ OPENED: 1, |
+ OPENED_PERSISTENT: 2, |
+ CLOSED: 3, |
+ TRACKING: 4, |
+ FLINGING: 5 |
+ } |
+}); |
+ |
+Polymer.IronFormElementBehavior = { |
+ properties: { |
+ name: { |
+ type: String |
+ }, |
+ value: { |
+ notify: true, |
+ type: String |
+ }, |
+ required: { |
+ type: Boolean, |
+ value: false |
+ }, |
+ _parentForm: { |
+ type: Object |
+ } |
+ }, |
+ attached: function() { |
+ this.fire('iron-form-element-register'); |
+ }, |
+ detached: function() { |
+ if (this._parentForm) { |
+ this._parentForm.fire('iron-form-element-unregister', { |
+ target: this |
+ }); |
+ } |
+ } |
+}; |
+ |
+Polymer.IronCheckedElementBehaviorImpl = { |
+ properties: { |
+ checked: { |
+ type: Boolean, |
+ value: false, |
+ reflectToAttribute: true, |
+ notify: true, |
+ observer: '_checkedChanged' |
+ }, |
+ toggles: { |
+ type: Boolean, |
+ value: true, |
+ reflectToAttribute: true |
+ }, |
+ value: { |
+ type: String, |
+ value: 'on', |
+ observer: '_valueChanged' |
+ } |
+ }, |
+ observers: [ '_requiredChanged(required)' ], |
+ created: function() { |
+ this._hasIronCheckedElementBehavior = true; |
+ }, |
+ _getValidity: function(_value) { |
+ return this.disabled || !this.required || this.checked; |
+ }, |
+ _requiredChanged: function() { |
+ if (this.required) { |
+ this.setAttribute('aria-required', 'true'); |
+ } else { |
+ this.removeAttribute('aria-required'); |
+ } |
+ }, |
+ _checkedChanged: function() { |
+ this.active = this.checked; |
+ this.fire('iron-change'); |
+ }, |
+ _valueChanged: function() { |
+ if (this.value === undefined || this.value === null) { |
+ this.value = 'on'; |
+ } |
+ } |
+}; |
+ |
+Polymer.IronCheckedElementBehavior = [ Polymer.IronFormElementBehavior, Polymer.IronValidatableBehavior, Polymer.IronCheckedElementBehaviorImpl ]; |
+ |
+Polymer.PaperCheckedElementBehaviorImpl = { |
+ _checkedChanged: function() { |
+ Polymer.IronCheckedElementBehaviorImpl._checkedChanged.call(this); |
+ if (this.hasRipple()) { |
+ if (this.checked) { |
+ this._ripple.setAttribute('checked', ''); |
+ } else { |
+ this._ripple.removeAttribute('checked'); |
+ } |
+ } |
+ }, |
+ _buttonStateChanged: function() { |
+ Polymer.PaperRippleBehavior._buttonStateChanged.call(this); |
+ if (this.disabled) { |
+ return; |
+ } |
+ if (this.isAttached) { |
+ this.checked = this.active; |
+ } |
+ } |
+}; |
+ |
+Polymer.PaperCheckedElementBehavior = [ Polymer.PaperInkyFocusBehavior, Polymer.IronCheckedElementBehavior, Polymer.PaperCheckedElementBehaviorImpl ]; |
+ |
+Polymer({ |
+ is: 'paper-checkbox', |
+ behaviors: [ Polymer.PaperCheckedElementBehavior ], |
+ hostAttributes: { |
+ role: 'checkbox', |
+ 'aria-checked': false, |
+ tabindex: 0 |
+ }, |
+ properties: { |
+ ariaActiveAttribute: { |
+ type: String, |
+ value: 'aria-checked' |
+ } |
+ }, |
+ attached: function() { |
+ var inkSize = this.getComputedStyleValue('--calculated-paper-checkbox-ink-size'); |
+ if (inkSize === '-1px') { |
+ var checkboxSize = parseFloat(this.getComputedStyleValue('--calculated-paper-checkbox-size')); |
+ var defaultInkSize = Math.floor(8 / 3 * checkboxSize); |
+ if (defaultInkSize % 2 !== checkboxSize % 2) { |
+ defaultInkSize++; |
+ } |
+ this.customStyle['--paper-checkbox-ink-size'] = defaultInkSize + 'px'; |
+ this.updateStyles(); |
+ } |
+ }, |
+ _computeCheckboxClass: function(checked, invalid) { |
+ var className = ''; |
+ if (checked) { |
+ className += 'checked '; |
+ } |
+ if (invalid) { |
+ className += 'invalid'; |
+ } |
+ return className; |
+ }, |
+ _computeCheckmarkClass: function(checked) { |
+ return checked ? '' : 'hidden'; |
+ }, |
+ _createRipple: function() { |
+ this._rippleContainer = this.$.checkboxContainer; |
+ return Polymer.PaperInkyFocusBehaviorImpl._createRipple.call(this); |
+ } |
+}); |
+ |
+Polymer({ |
+ is: 'paper-tab', |
+ behaviors: [ Polymer.IronControlState, Polymer.IronButtonState, Polymer.PaperRippleBehavior ], |
+ properties: { |
+ link: { |
+ type: Boolean, |
+ value: false, |
+ reflectToAttribute: true |
+ } |
+ }, |
+ hostAttributes: { |
+ role: 'tab' |
+ }, |
+ listeners: { |
+ down: '_updateNoink', |
+ tap: '_onTap' |
+ }, |
+ attached: function() { |
+ this._updateNoink(); |
+ }, |
+ get _parentNoink() { |
+ var parent = Polymer.dom(this).parentNode; |
+ return !!parent && !!parent.noink; |
+ }, |
+ _updateNoink: function() { |
+ this.noink = !!this.noink || !!this._parentNoink; |
+ }, |
+ _onTap: function(event) { |
+ if (this.link) { |
+ var anchor = this.queryEffectiveChildren('a'); |
+ if (!anchor) { |
+ return; |
+ } |
+ if (event.target === anchor) { |
+ return; |
+ } |
+ anchor.click(); |
+ } |
+ } |
+}); |
+ |
+Polymer.IronMenuBehaviorImpl = { |
+ properties: { |
+ focusedItem: { |
+ observer: '_focusedItemChanged', |
+ readOnly: true, |
+ type: Object |
+ }, |
+ attrForItemTitle: { |
+ type: String |
+ } |
+ }, |
+ hostAttributes: { |
+ role: 'menu', |
+ tabindex: '0' |
+ }, |
+ observers: [ '_updateMultiselectable(multi)' ], |
+ listeners: { |
+ focus: '_onFocus', |
+ keydown: '_onKeydown', |
+ 'iron-items-changed': '_onIronItemsChanged' |
+ }, |
+ keyBindings: { |
+ up: '_onUpKey', |
+ down: '_onDownKey', |
+ esc: '_onEscKey', |
+ 'shift+tab:keydown': '_onShiftTabDown' |
+ }, |
+ attached: function() { |
+ this._resetTabindices(); |
+ }, |
+ select: function(value) { |
+ if (this._defaultFocusAsync) { |
+ this.cancelAsync(this._defaultFocusAsync); |
+ this._defaultFocusAsync = null; |
+ } |
+ var item = this._valueToItem(value); |
+ if (item && item.hasAttribute('disabled')) return; |
+ this._setFocusedItem(item); |
+ Polymer.IronMultiSelectableBehaviorImpl.select.apply(this, arguments); |
+ }, |
+ _resetTabindices: function() { |
+ var selectedItem = this.multi ? this.selectedItems && this.selectedItems[0] : this.selectedItem; |
+ this.items.forEach(function(item) { |
+ item.setAttribute('tabindex', item === selectedItem ? '0' : '-1'); |
+ }, this); |
+ }, |
+ _updateMultiselectable: function(multi) { |
+ if (multi) { |
+ this.setAttribute('aria-multiselectable', 'true'); |
+ } else { |
+ this.removeAttribute('aria-multiselectable'); |
+ } |
+ }, |
+ _focusWithKeyboardEvent: function(event) { |
+ for (var i = 0, item; item = this.items[i]; i++) { |
+ var attr = this.attrForItemTitle || 'textContent'; |
+ var title = item[attr] || item.getAttribute(attr); |
+ if (!item.hasAttribute('disabled') && title && title.trim().charAt(0).toLowerCase() === String.fromCharCode(event.keyCode).toLowerCase()) { |
+ this._setFocusedItem(item); |
+ break; |
+ } |
+ } |
+ }, |
+ _focusPrevious: function() { |
+ var length = this.items.length; |
+ var curFocusIndex = Number(this.indexOf(this.focusedItem)); |
+ for (var i = 1; i < length + 1; i++) { |
+ var item = this.items[(curFocusIndex - i + length) % length]; |
+ if (!item.hasAttribute('disabled')) { |
+ var owner = Polymer.dom(item).getOwnerRoot() || document; |
+ this._setFocusedItem(item); |
+ if (Polymer.dom(owner).activeElement == item) { |
+ return; |
+ } |
+ } |
+ } |
+ }, |
+ _focusNext: function() { |
+ var length = this.items.length; |
+ var curFocusIndex = Number(this.indexOf(this.focusedItem)); |
+ for (var i = 1; i < length + 1; i++) { |
+ var item = this.items[(curFocusIndex + i) % length]; |
+ if (!item.hasAttribute('disabled')) { |
+ var owner = Polymer.dom(item).getOwnerRoot() || document; |
+ this._setFocusedItem(item); |
+ if (Polymer.dom(owner).activeElement == item) { |
+ return; |
+ } |
+ } |
+ } |
+ }, |
+ _applySelection: function(item, isSelected) { |
+ if (isSelected) { |
+ item.setAttribute('aria-selected', 'true'); |
+ } else { |
+ item.removeAttribute('aria-selected'); |
+ } |
+ Polymer.IronSelectableBehavior._applySelection.apply(this, arguments); |
+ }, |
+ _focusedItemChanged: function(focusedItem, old) { |
+ old && old.setAttribute('tabindex', '-1'); |
+ if (focusedItem) { |
+ focusedItem.setAttribute('tabindex', '0'); |
+ focusedItem.focus(); |
+ } |
+ }, |
+ _onIronItemsChanged: function(event) { |
+ if (event.detail.addedNodes.length) { |
+ this._resetTabindices(); |
+ } |
+ }, |
+ _onShiftTabDown: function(event) { |
+ var oldTabIndex = this.getAttribute('tabindex'); |
+ Polymer.IronMenuBehaviorImpl._shiftTabPressed = true; |
+ this._setFocusedItem(null); |
+ this.setAttribute('tabindex', '-1'); |
+ this.async(function() { |
+ this.setAttribute('tabindex', oldTabIndex); |
+ Polymer.IronMenuBehaviorImpl._shiftTabPressed = false; |
+ }, 1); |
+ }, |
+ _onFocus: function(event) { |
+ if (Polymer.IronMenuBehaviorImpl._shiftTabPressed) { |
+ return; |
+ } |
+ var rootTarget = Polymer.dom(event).rootTarget; |
+ if (rootTarget !== this && typeof rootTarget.tabIndex !== "undefined" && !this.isLightDescendant(rootTarget)) { |
+ return; |
+ } |
+ this._defaultFocusAsync = this.async(function() { |
+ var selectedItem = this.multi ? this.selectedItems && this.selectedItems[0] : this.selectedItem; |
+ this._setFocusedItem(null); |
+ if (selectedItem) { |
+ this._setFocusedItem(selectedItem); |
+ } else if (this.items[0]) { |
+ this._focusNext(); |
+ } |
+ }); |
+ }, |
+ _onUpKey: function(event) { |
+ this._focusPrevious(); |
+ event.detail.keyboardEvent.preventDefault(); |
+ }, |
+ _onDownKey: function(event) { |
+ this._focusNext(); |
+ event.detail.keyboardEvent.preventDefault(); |
+ }, |
+ _onEscKey: function(event) { |
+ this.focusedItem.blur(); |
+ }, |
+ _onKeydown: function(event) { |
+ if (!this.keyboardEventMatchesKeys(event, 'up down esc')) { |
+ this._focusWithKeyboardEvent(event); |
+ } |
+ event.stopPropagation(); |
+ }, |
+ _activateHandler: function(event) { |
+ Polymer.IronSelectableBehavior._activateHandler.call(this, event); |
+ event.stopPropagation(); |
+ } |
+}; |
+ |
+Polymer.IronMenuBehaviorImpl._shiftTabPressed = false; |
+ |
+Polymer.IronMenuBehavior = [ Polymer.IronMultiSelectableBehavior, Polymer.IronA11yKeysBehavior, Polymer.IronMenuBehaviorImpl ]; |
+ |
+Polymer.IronMenubarBehaviorImpl = { |
+ hostAttributes: { |
+ role: 'menubar' |
+ }, |
+ keyBindings: { |
+ left: '_onLeftKey', |
+ right: '_onRightKey' |
+ }, |
+ _onUpKey: function(event) { |
+ this.focusedItem.click(); |
+ event.detail.keyboardEvent.preventDefault(); |
+ }, |
+ _onDownKey: function(event) { |
+ this.focusedItem.click(); |
+ event.detail.keyboardEvent.preventDefault(); |
+ }, |
+ get _isRTL() { |
+ return window.getComputedStyle(this)['direction'] === 'rtl'; |
+ }, |
+ _onLeftKey: function(event) { |
+ if (this._isRTL) { |
+ this._focusNext(); |
+ } else { |
+ this._focusPrevious(); |
+ } |
+ event.detail.keyboardEvent.preventDefault(); |
+ }, |
+ _onRightKey: function(event) { |
+ if (this._isRTL) { |
+ this._focusPrevious(); |
+ } else { |
+ this._focusNext(); |
+ } |
+ event.detail.keyboardEvent.preventDefault(); |
+ }, |
+ _onKeydown: function(event) { |
+ if (this.keyboardEventMatchesKeys(event, 'up down left right esc')) { |
+ return; |
+ } |
+ this._focusWithKeyboardEvent(event); |
+ } |
+}; |
+ |
+Polymer.IronMenubarBehavior = [ Polymer.IronMenuBehavior, Polymer.IronMenubarBehaviorImpl ]; |
+ |
+Polymer({ |
+ is: 'paper-tabs', |
+ behaviors: [ Polymer.IronResizableBehavior, Polymer.IronMenubarBehavior ], |
+ properties: { |
+ noink: { |
+ type: Boolean, |
+ value: false, |
+ observer: '_noinkChanged' |
+ }, |
+ noBar: { |
+ type: Boolean, |
+ value: false |
+ }, |
+ noSlide: { |
+ type: Boolean, |
+ value: false |
+ }, |
+ scrollable: { |
+ type: Boolean, |
+ value: false |
+ }, |
+ fitContainer: { |
+ type: Boolean, |
+ value: false |
+ }, |
+ disableDrag: { |
+ type: Boolean, |
+ value: false |
+ }, |
+ hideScrollButtons: { |
+ type: Boolean, |
+ value: false |
+ }, |
+ alignBottom: { |
+ type: Boolean, |
+ value: false |
+ }, |
+ selectable: { |
+ type: String, |
+ value: 'paper-tab' |
+ }, |
+ autoselect: { |
+ type: Boolean, |
+ value: false |
+ }, |
+ autoselectDelay: { |
+ type: Number, |
+ value: 0 |
+ }, |
+ _step: { |
+ type: Number, |
+ value: 10 |
+ }, |
+ _holdDelay: { |
+ type: Number, |
+ value: 1 |
+ }, |
+ _leftHidden: { |
+ type: Boolean, |
+ value: false |
+ }, |
+ _rightHidden: { |
+ type: Boolean, |
+ value: false |
+ }, |
+ _previousTab: { |
+ type: Object |
+ } |
+ }, |
+ hostAttributes: { |
+ role: 'tablist' |
+ }, |
+ listeners: { |
+ 'iron-resize': '_onTabSizingChanged', |
+ 'iron-items-changed': '_onTabSizingChanged', |
+ 'iron-select': '_onIronSelect', |
+ 'iron-deselect': '_onIronDeselect' |
+ }, |
+ keyBindings: { |
+ 'left:keyup right:keyup': '_onArrowKeyup' |
+ }, |
+ created: function() { |
+ this._holdJob = null; |
+ this._pendingActivationItem = undefined; |
+ this._pendingActivationTimeout = undefined; |
+ this._bindDelayedActivationHandler = this._delayedActivationHandler.bind(this); |
+ this.addEventListener('blur', this._onBlurCapture.bind(this), true); |
+ }, |
+ ready: function() { |
+ this.setScrollDirection('y', this.$.tabsContainer); |
+ }, |
+ detached: function() { |
+ this._cancelPendingActivation(); |
+ }, |
+ _noinkChanged: function(noink) { |
+ var childTabs = Polymer.dom(this).querySelectorAll('paper-tab'); |
+ childTabs.forEach(noink ? this._setNoinkAttribute : this._removeNoinkAttribute); |
+ }, |
+ _setNoinkAttribute: function(element) { |
+ element.setAttribute('noink', ''); |
+ }, |
+ _removeNoinkAttribute: function(element) { |
+ element.removeAttribute('noink'); |
+ }, |
+ _computeScrollButtonClass: function(hideThisButton, scrollable, hideScrollButtons) { |
+ if (!scrollable || hideScrollButtons) { |
+ return 'hidden'; |
+ } |
+ if (hideThisButton) { |
+ return 'not-visible'; |
+ } |
+ return ''; |
+ }, |
+ _computeTabsContentClass: function(scrollable, fitContainer) { |
+ return scrollable ? 'scrollable' + (fitContainer ? ' fit-container' : '') : ' fit-container'; |
+ }, |
+ _computeSelectionBarClass: function(noBar, alignBottom) { |
+ if (noBar) { |
+ return 'hidden'; |
+ } else if (alignBottom) { |
+ return 'align-bottom'; |
+ } |
+ return ''; |
+ }, |
+ _onTabSizingChanged: function() { |
+ this.debounce('_onTabSizingChanged', function() { |
+ this._scroll(); |
+ this._tabChanged(this.selectedItem); |
+ }, 10); |
+ }, |
+ _onIronSelect: function(event) { |
+ this._tabChanged(event.detail.item, this._previousTab); |
+ this._previousTab = event.detail.item; |
+ this.cancelDebouncer('tab-changed'); |
+ }, |
+ _onIronDeselect: function(event) { |
+ this.debounce('tab-changed', function() { |
+ this._tabChanged(null, this._previousTab); |
+ this._previousTab = null; |
+ }, 1); |
+ }, |
+ _activateHandler: function() { |
+ this._cancelPendingActivation(); |
+ Polymer.IronMenuBehaviorImpl._activateHandler.apply(this, arguments); |
+ }, |
+ _scheduleActivation: function(item, delay) { |
+ this._pendingActivationItem = item; |
+ this._pendingActivationTimeout = this.async(this._bindDelayedActivationHandler, delay); |
+ }, |
+ _delayedActivationHandler: function() { |
+ var item = this._pendingActivationItem; |
+ this._pendingActivationItem = undefined; |
+ this._pendingActivationTimeout = undefined; |
+ item.fire(this.activateEvent, null, { |
+ bubbles: true, |
+ cancelable: true |
+ }); |
+ }, |
+ _cancelPendingActivation: function() { |
+ if (this._pendingActivationTimeout !== undefined) { |
+ this.cancelAsync(this._pendingActivationTimeout); |
+ this._pendingActivationItem = undefined; |
+ this._pendingActivationTimeout = undefined; |
+ } |
+ }, |
+ _onArrowKeyup: function(event) { |
+ if (this.autoselect) { |
+ this._scheduleActivation(this.focusedItem, this.autoselectDelay); |
+ } |
+ }, |
+ _onBlurCapture: function(event) { |
+ if (event.target === this._pendingActivationItem) { |
+ this._cancelPendingActivation(); |
+ } |
+ }, |
+ get _tabContainerScrollSize() { |
+ return Math.max(0, this.$.tabsContainer.scrollWidth - this.$.tabsContainer.offsetWidth); |
+ }, |
+ _scroll: function(e, detail) { |
+ if (!this.scrollable) { |
+ return; |
+ } |
+ var ddx = detail && -detail.ddx || 0; |
+ this._affectScroll(ddx); |
+ }, |
+ _down: function(e) { |
+ this.async(function() { |
+ if (this._defaultFocusAsync) { |
+ this.cancelAsync(this._defaultFocusAsync); |
+ this._defaultFocusAsync = null; |
+ } |
+ }, 1); |
+ }, |
+ _affectScroll: function(dx) { |
+ this.$.tabsContainer.scrollLeft += dx; |
+ var scrollLeft = this.$.tabsContainer.scrollLeft; |
+ this._leftHidden = scrollLeft === 0; |
+ this._rightHidden = scrollLeft === this._tabContainerScrollSize; |
+ }, |
+ _onLeftScrollButtonDown: function() { |
+ this._scrollToLeft(); |
+ this._holdJob = setInterval(this._scrollToLeft.bind(this), this._holdDelay); |
+ }, |
+ _onRightScrollButtonDown: function() { |
+ this._scrollToRight(); |
+ this._holdJob = setInterval(this._scrollToRight.bind(this), this._holdDelay); |
+ }, |
+ _onScrollButtonUp: function() { |
+ clearInterval(this._holdJob); |
+ this._holdJob = null; |
+ }, |
+ _scrollToLeft: function() { |
+ this._affectScroll(-this._step); |
+ }, |
+ _scrollToRight: function() { |
+ this._affectScroll(this._step); |
+ }, |
+ _tabChanged: function(tab, old) { |
+ if (!tab) { |
+ this.$.selectionBar.classList.remove('expand'); |
+ this.$.selectionBar.classList.remove('contract'); |
+ this._positionBar(0, 0); |
+ return; |
+ } |
+ var r = this.$.tabsContent.getBoundingClientRect(); |
+ var w = r.width; |
+ var tabRect = tab.getBoundingClientRect(); |
+ var tabOffsetLeft = tabRect.left - r.left; |
+ this._pos = { |
+ width: this._calcPercent(tabRect.width, w), |
+ left: this._calcPercent(tabOffsetLeft, w) |
+ }; |
+ if (this.noSlide || old == null) { |
+ this.$.selectionBar.classList.remove('expand'); |
+ this.$.selectionBar.classList.remove('contract'); |
+ this._positionBar(this._pos.width, this._pos.left); |
+ return; |
+ } |
+ var oldRect = old.getBoundingClientRect(); |
+ var oldIndex = this.items.indexOf(old); |
+ var index = this.items.indexOf(tab); |
+ var m = 5; |
+ this.$.selectionBar.classList.add('expand'); |
+ var moveRight = oldIndex < index; |
+ var isRTL = this._isRTL; |
+ if (isRTL) { |
+ moveRight = !moveRight; |
+ } |
+ if (moveRight) { |
+ this._positionBar(this._calcPercent(tabRect.left + tabRect.width - oldRect.left, w) - m, this._left); |
+ } else { |
+ this._positionBar(this._calcPercent(oldRect.left + oldRect.width - tabRect.left, w) - m, this._calcPercent(tabOffsetLeft, w) + m); |
+ } |
+ if (this.scrollable) { |
+ this._scrollToSelectedIfNeeded(tabRect.width, tabOffsetLeft); |
+ } |
+ }, |
+ _scrollToSelectedIfNeeded: function(tabWidth, tabOffsetLeft) { |
+ var l = tabOffsetLeft - this.$.tabsContainer.scrollLeft; |
+ if (l < 0) { |
+ this.$.tabsContainer.scrollLeft += l; |
+ } else { |
+ l += tabWidth - this.$.tabsContainer.offsetWidth; |
+ if (l > 0) { |
+ this.$.tabsContainer.scrollLeft += l; |
+ } |
+ } |
+ }, |
+ _calcPercent: function(w, w0) { |
+ return 100 * w / w0; |
+ }, |
+ _positionBar: function(width, left) { |
+ width = width || 0; |
+ left = left || 0; |
+ this._width = width; |
+ this._left = left; |
+ this.transform('translateX(' + left + '%) scaleX(' + width / 100 + ')', this.$.selectionBar); |
+ }, |
+ _onBarTransitionEnd: function(e) { |
+ var cl = this.$.selectionBar.classList; |
+ if (cl.contains('expand')) { |
+ cl.remove('expand'); |
+ cl.add('contract'); |
+ this._positionBar(this._pos.width, this._pos.left); |
+ } else if (cl.contains('contract')) { |
+ cl.remove('contract'); |
+ } |
+ } |
+}); |