| Index: pkg/polymer/lib/elements/polymer-collapse/polymer-collapse.html
|
| diff --git a/pkg/polymer/lib/elements/polymer-collapse/polymer-collapse.html b/pkg/polymer/lib/elements/polymer-collapse/polymer-collapse.html
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..171d17ad8617fbcbd9f412338f862c0bd9dcc3df
|
| --- /dev/null
|
| +++ b/pkg/polymer/lib/elements/polymer-collapse/polymer-collapse.html
|
| @@ -0,0 +1,240 @@
|
| +<!--
|
| +Copyright 2013 The Polymer Authors. All rights reserved.
|
| +Use of this source code is governed by a BSD-style
|
| +license that can be found in the LICENSE file.
|
| +-->
|
| +<!--
|
| +/**
|
| + * @module Polymer Elements
|
| + */
|
| +/**
|
| + * polymer-collapse is used to add collapsible behavior to the
|
| + * target element. It adjusts the height or width of the target element
|
| + * to make the element collapse and expand.
|
| + *
|
| + * Example:
|
| + *
|
| + * <button on-click="{{toggle}}">toggle collapse</button>
|
| + * <div id="demo">
|
| + * ...
|
| + * </div>
|
| + * <polymer-collapse id="collapse" targetId="demo"></polymer-collapse>
|
| + *
|
| + * ...
|
| + *
|
| + * toggle: function() {
|
| + * this.$.collapse.toggle();
|
| + * }
|
| + *
|
| + * @class polymer-collapse
|
| + */
|
| +-->
|
| +<link rel="import" href="../polymer/polymer.html">
|
| +
|
| +<polymer-element name="polymer-collapse" attributes="targetId target horizontal closed duration fixedSize size">
|
| + <template>
|
| + <link rel="stylesheet" polymer-scope="controller" href="polymer-collapse.css">
|
| + <link rel="stylesheet" href="polymer-collapse.css">
|
| + <style>
|
| + :host {
|
| + display: none;
|
| + }
|
| + </style>
|
| + </template>
|
| + <script>
|
| + Polymer('polymer-collapse', {
|
| + /**
|
| + * The id of the target element.
|
| + *
|
| + * @attribute targetId
|
| + * @type string
|
| + * @default ''
|
| + */
|
| + targetId: '',
|
| + /**
|
| + * The target element.
|
| + *
|
| + * @attribute target
|
| + * @type object
|
| + * @default null
|
| + */
|
| + target: null,
|
| + /**
|
| + * If true, the orientation is horizontal; otherwise is vertical.
|
| + *
|
| + * @attribute horizontal
|
| + * @type boolean
|
| + * @default false
|
| + */
|
| + horizontal: false,
|
| + /**
|
| + * If true, the target element is hidden/collapsed.
|
| + *
|
| + * @attribute closed
|
| + * @type boolean
|
| + * @default false
|
| + */
|
| + closed: false,
|
| + /**
|
| + * Collapsing/expanding animation duration in second.
|
| + *
|
| + * @attribute duration
|
| + * @type number
|
| + * @default 0.33
|
| + */
|
| + duration: 0.33,
|
| + /**
|
| + * If true, the size of the target element is fixed and is set
|
| + * on the element. Otherwise it will try to
|
| + * use auto to determine the natural size to use
|
| + * for collapsing/expanding.
|
| + *
|
| + * @attribute fixedSize
|
| + * @type boolean
|
| + * @default false
|
| + */
|
| + fixedSize: false,
|
| + size: null,
|
| + attached: function() {
|
| + this.installControllerStyles();
|
| + this.inDocument = true;
|
| + this.async(function() {
|
| + this.afterInitialUpdate = true;
|
| + });
|
| + },
|
| + detached: function() {
|
| + if (this.target) {
|
| + this.removeListeners(this.target);
|
| + }
|
| + },
|
| + targetIdChanged: function() {
|
| + var p = this.parentNode;
|
| + while (p.parentNode) {
|
| + p = p.parentNode;
|
| + }
|
| + this.target = p.querySelector('#' + this.targetId);
|
| + },
|
| + targetChanged: function(old) {
|
| + if (old) {
|
| + this.removeListeners(old);
|
| + }
|
| + this.horizontalChanged();
|
| + this.isTargetReady = !!this.target;
|
| + if (this.target) {
|
| + this.target.style.overflow = 'hidden';
|
| + this.addListeners(this.target);
|
| + // set polymer-collapse-closed class initially to hide the target
|
| + this.toggleClosedClass(true);
|
| + }
|
| + // don't need to update if the size is already set and it's opened
|
| + if (!this.fixedSize || !this.closed) {
|
| + this.update();
|
| + }
|
| + },
|
| + addListeners: function(node) {
|
| + this.transitionEndListener = this.transitionEndListener ||
|
| + this.transitionEnd.bind(this);
|
| + node.addEventListener('webkitTransitionEnd', this.transitionEndListener);
|
| + node.addEventListener('transitionend', this.transitionEndListener);
|
| + },
|
| + removeListeners: function(node) {
|
| + node.removeEventListener('webkitTransitionEnd', this.transitionEndListener);
|
| + node.removeEventListener('transitionend', this.transitionEndListener);
|
| + },
|
| + horizontalChanged: function() {
|
| + this.dimension = this.horizontal ? 'width' : 'height';
|
| + },
|
| + closedChanged: function() {
|
| + this.update();
|
| + },
|
| + /**
|
| + * Toggle the closed state of the collapsible.
|
| + *
|
| + * @method toggle
|
| + */
|
| + toggle: function() {
|
| + this.closed = !this.closed;
|
| + },
|
| + setTransitionDuration: function(duration) {
|
| + var s = this.target.style;
|
| + s.webkitTransition = s.transition = duration ?
|
| + (this.dimension + ' ' + duration + 's') : null;
|
| + if (duration === 0) {
|
| + this.async('transitionEnd');
|
| + }
|
| + },
|
| + transitionEnd: function() {
|
| + if (!this.closed && !this.fixedSize) {
|
| + this.updateSize('auto', null);
|
| + }
|
| + this.setTransitionDuration(null);
|
| + this.toggleClosedClass(this.closed);
|
| + },
|
| + toggleClosedClass: function(add) {
|
| + this.hasClosedClass = add;
|
| + this.target.classList.toggle('polymer-collapse-closed', add);
|
| + },
|
| + updateSize: function(size, duration, forceEnd) {
|
| + if (duration) {
|
| + this.calcSize();
|
| + }
|
| + this.setTransitionDuration(duration);
|
| + var s = this.target.style;
|
| + var nochange = s[this.dimension] === size;
|
| + s[this.dimension] = size;
|
| + // transitonEnd will not be called if the size has not changed
|
| + if (forceEnd && nochange) {
|
| + this.transitionEnd();
|
| + }
|
| + },
|
| + update: function() {
|
| + if (!this.target || !this.inDocument) {
|
| + return;
|
| + }
|
| + if (!this.isTargetReady) {
|
| + this.targetChanged();
|
| + }
|
| + this.horizontalChanged();
|
| + this[this.closed ? 'hide' : 'show']();
|
| + },
|
| + calcSize: function() {
|
| + return this.target.getBoundingClientRect()[this.dimension] + 'px';
|
| + },
|
| + getComputedSize: function() {
|
| + return getComputedStyle(this.target)[this.dimension];
|
| + },
|
| + show: function() {
|
| + this.toggleClosedClass(false);
|
| + // for initial update, skip the expanding animation to optimize
|
| + // performance e.g. skip calcSize
|
| + if (!this.afterInitialUpdate) {
|
| + this.transitionEnd();
|
| + return;
|
| + }
|
| + if (!this.fixedSize) {
|
| + this.updateSize('auto', null);
|
| + var s = this.calcSize();
|
| + this.updateSize(0, null);
|
| + }
|
| + this.async(function() {
|
| + this.updateSize(this.size || s, this.duration, true);
|
| + });
|
| + },
|
| + hide: function() {
|
| + // don't need to do anything if it's already hidden
|
| + if (this.hasClosedClass && !this.fixedSize) {
|
| + return;
|
| + }
|
| + if (this.fixedSize) {
|
| + // save the size before hiding it
|
| + this.size = this.getComputedSize();
|
| + } else {
|
| + this.updateSize(this.calcSize(), null);
|
| + }
|
| + this.async(function() {
|
| + this.updateSize(0, this.duration);
|
| + });
|
| + }
|
| + });
|
| + </script>
|
| +</polymer-element>
|
|
|