// Copyright 2015 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. (function() { /** * Size of additional padding in the inner scrollable section of the dropdown. */ var DROPDOWN_INNER_PADDING = 12; /** Size of vertical padding on the outer #dropdown element. */ var DROPDOWN_OUTER_PADDING = 2; /** Minimum height of toolbar dropdowns (px). */ var MIN_DROPDOWN_HEIGHT = 200; Polymer({ is: 'viewer-toolbar-dropdown', properties: { /** String to be displayed at the top of the dropdown. */ header: String, /** Icon to display when the dropdown is closed. */ closedIcon: String, /** Icon to display when the dropdown is open. */ openIcon: String, /** True if the dropdown is currently open. */ dropdownOpen: { type: Boolean, reflectToAttribute: true, value: false }, /** Toolbar icon currently being displayed. */ dropdownIcon: { type: String, computed: 'computeIcon_(dropdownOpen, closedIcon, openIcon)' }, /** Lowest vertical point that the dropdown should occupy (px). */ lowerBound: { type: Number, observer: 'lowerBoundChanged_' }, /** * True if the max-height CSS property for the dropdown scroll container * is valid. If false, the height will be updated the next time the * dropdown is visible. */ maxHeightValid_: false, /** Current animation being played, or null if there is none. */ animation_: Object }, computeIcon_: function(dropdownOpen, closedIcon, openIcon) { return dropdownOpen ? openIcon : closedIcon; }, lowerBoundChanged_: function() { this.maxHeightValid_ = false; if (this.dropdownOpen) this.updateMaxHeight(); }, toggleDropdown: function() { this.dropdownOpen = !this.dropdownOpen; if (this.dropdownOpen) { this.$.dropdown.style.display = 'block'; if (!this.maxHeightValid_) this.updateMaxHeight(); } this.cancelAnimation_(); this.playAnimation_(this.dropdownOpen); }, updateMaxHeight: function() { var scrollContainer = this.$['scroll-container']; var height = this.lowerBound - scrollContainer.getBoundingClientRect().top - DROPDOWN_INNER_PADDING; height = Math.max(height, MIN_DROPDOWN_HEIGHT); scrollContainer.style.maxHeight = height + 'px'; this.maxHeightValid_ = true; }, cancelAnimation_: function() { if (this._animation) this._animation.cancel(); }, /** * Start an animation on the dropdown. * @param {boolean} isEntry True to play entry animation, false to play * exit. * @private */ playAnimation_: function(isEntry) { this.animation_ = isEntry ? this.animateEntry_() : this.animateExit_(); this.animation_.onfinish = function() { this.animation_ = null; if (!this.dropdownOpen) this.$.dropdown.style.display = 'none'; }.bind(this); }, animateEntry_: function() { var maxHeight = this.$.dropdown.getBoundingClientRect().height - DROPDOWN_OUTER_PADDING; if (maxHeight < 0) maxHeight = 0; var fade = new KeyframeEffect(this.$.dropdown, [ {opacity: 0}, {opacity: 1} ], {duration: 150, easing: 'cubic-bezier(0, 0, 0.2, 1)'}); var slide = new KeyframeEffect(this.$.dropdown, [ {height: '20px', transform: 'translateY(-10px)'}, {height: maxHeight + 'px', transform: 'translateY(0)'} ], {duration: 250, easing: 'cubic-bezier(0, 0, 0.2, 1)'}); return document.timeline.play(new GroupEffect([fade, slide])); }, animateExit_: function() { return this.$.dropdown.animate([ {transform: 'translateY(0)', opacity: 1}, {transform: 'translateY(-5px)', opacity: 0} ], {duration: 100, easing: 'cubic-bezier(0.4, 0, 1, 1)'}); } }); })();