480 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			HTML
		
	
	
	
			
		
		
	
	
			480 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			HTML
		
	
	
	
<!--
 | 
						|
@license
 | 
						|
Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
 | 
						|
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
 | 
						|
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
 | 
						|
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
 | 
						|
Code distributed by Google as part of the polymer project is also
 | 
						|
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
 | 
						|
-->
 | 
						|
 | 
						|
<link rel="import" href="../polymer/polymer.html">
 | 
						|
<link rel="import" href="../iron-a11y-keys-behavior/iron-a11y-keys-behavior.html">
 | 
						|
<link rel="import" href="../iron-behaviors/iron-control-state.html">
 | 
						|
<link rel="import" href="../iron-dropdown/iron-dropdown.html">
 | 
						|
<link rel="import" href="../neon-animation/animations/fade-in-animation.html">
 | 
						|
<link rel="import" href="../neon-animation/animations/fade-out-animation.html">
 | 
						|
<link rel="import" href="../paper-styles/default-theme.html">
 | 
						|
<link rel="import" href="../paper-styles/shadow.html">
 | 
						|
<link rel="import" href="paper-menu-button-animations.html">
 | 
						|
 | 
						|
<!--
 | 
						|
Material design: [Dropdown buttons](https://www.google.com/design/spec/components/buttons.html#buttons-dropdown-buttons)
 | 
						|
 | 
						|
`paper-menu-button` allows one to compose a designated "trigger" element with
 | 
						|
another element that represents "content", to create a dropdown menu that
 | 
						|
displays the "content" when the "trigger" is clicked.
 | 
						|
 | 
						|
The child element with the class `dropdown-trigger` will be used as the
 | 
						|
"trigger" element. The child element with the class `dropdown-content` will be
 | 
						|
used as the "content" element.
 | 
						|
 | 
						|
The `paper-menu-button` is sensitive to its content's `iron-select` events. If
 | 
						|
the "content" element triggers an `iron-select` event, the `paper-menu-button`
 | 
						|
will close automatically.
 | 
						|
 | 
						|
Example:
 | 
						|
 | 
						|
    <paper-menu-button>
 | 
						|
      <paper-icon-button icon="menu" class="dropdown-trigger"></paper-icon-button>
 | 
						|
      <paper-menu class="dropdown-content">
 | 
						|
        <paper-item>Share</paper-item>
 | 
						|
        <paper-item>Settings</paper-item>
 | 
						|
        <paper-item>Help</paper-item>
 | 
						|
      </paper-menu>
 | 
						|
    </paper-menu-button>
 | 
						|
 | 
						|
### Styling
 | 
						|
 | 
						|
The following custom properties and mixins are also available for styling:
 | 
						|
 | 
						|
Custom property | Description | Default
 | 
						|
----------------|-------------|----------
 | 
						|
`--paper-menu-button-dropdown-background` | Background color of the paper-menu-button dropdown | `--primary-background-color`
 | 
						|
`--paper-menu-button` | Mixin applied to the paper-menu-button | `{}`
 | 
						|
`--paper-menu-button-disabled` | Mixin applied to the paper-menu-button when disabled | `{}`
 | 
						|
`--paper-menu-button-dropdown` | Mixin applied to the paper-menu-button dropdown | `{}`
 | 
						|
`--paper-menu-button-content` | Mixin applied to the paper-menu-button content | `{}`
 | 
						|
 | 
						|
@hero hero.svg
 | 
						|
@demo demo/index.html
 | 
						|
-->
 | 
						|
 | 
						|
<dom-module id="paper-menu-button">
 | 
						|
  <template>
 | 
						|
    <style>
 | 
						|
      :host {
 | 
						|
        display: inline-block;
 | 
						|
        position: relative;
 | 
						|
        padding: 8px;
 | 
						|
        outline: none;
 | 
						|
 | 
						|
        @apply(--paper-menu-button);
 | 
						|
      }
 | 
						|
 | 
						|
      :host([disabled]) {
 | 
						|
        cursor: auto;
 | 
						|
        color: var(--disabled-text-color);
 | 
						|
 | 
						|
        @apply(--paper-menu-button-disabled);
 | 
						|
      }
 | 
						|
 | 
						|
      iron-dropdown {
 | 
						|
        @apply(--paper-menu-button-dropdown);
 | 
						|
      }
 | 
						|
 | 
						|
      .dropdown-content {
 | 
						|
        @apply(--shadow-elevation-2dp);
 | 
						|
 | 
						|
        position: relative;
 | 
						|
        border-radius: 2px;
 | 
						|
        background-color: var(--paper-menu-button-dropdown-background, --primary-background-color);
 | 
						|
 | 
						|
        @apply(--paper-menu-button-content);
 | 
						|
      }
 | 
						|
 | 
						|
      :host([vertical-align="top"]) .dropdown-content {
 | 
						|
        margin-bottom: 20px;
 | 
						|
        margin-top: -10px;
 | 
						|
        top: 10px;
 | 
						|
      }
 | 
						|
 | 
						|
      :host([vertical-align="bottom"]) .dropdown-content {
 | 
						|
        bottom: 10px;
 | 
						|
        margin-bottom: -10px;
 | 
						|
        margin-top: 20px;
 | 
						|
      }
 | 
						|
      
 | 
						|
      #trigger {
 | 
						|
        cursor: pointer;
 | 
						|
      }
 | 
						|
    </style>
 | 
						|
 | 
						|
    <div id="trigger" on-tap="toggle">
 | 
						|
      <content select=".dropdown-trigger"></content>
 | 
						|
    </div>
 | 
						|
 | 
						|
    <iron-dropdown
 | 
						|
      id="dropdown"
 | 
						|
      opened="{{opened}}"
 | 
						|
      horizontal-align="[[horizontalAlign]]"
 | 
						|
      vertical-align="[[verticalAlign]]"
 | 
						|
      dynamic-align="[[dynamicAlign]]"
 | 
						|
      horizontal-offset="[[horizontalOffset]]"
 | 
						|
      vertical-offset="[[verticalOffset]]"
 | 
						|
      no-overlap="[[noOverlap]]"
 | 
						|
      open-animation-config="[[openAnimationConfig]]"
 | 
						|
      close-animation-config="[[closeAnimationConfig]]"
 | 
						|
      no-animations="[[noAnimations]]"
 | 
						|
      focus-target="[[_dropdownContent]]"
 | 
						|
      allow-outside-scroll="[[allowOutsideScroll]]"
 | 
						|
      restore-focus-on-close="[[restoreFocusOnClose]]"
 | 
						|
      on-iron-overlay-canceled="__onIronOverlayCanceled">
 | 
						|
      <div class="dropdown-content">
 | 
						|
        <content id="content" select=".dropdown-content"></content>
 | 
						|
      </div>
 | 
						|
    </iron-dropdown>
 | 
						|
  </template>
 | 
						|
 | 
						|
  <script>
 | 
						|
    (function() {
 | 
						|
      'use strict';
 | 
						|
 | 
						|
      var config = {
 | 
						|
        ANIMATION_CUBIC_BEZIER: 'cubic-bezier(.3,.95,.5,1)',
 | 
						|
        MAX_ANIMATION_TIME_MS: 400
 | 
						|
      };
 | 
						|
 | 
						|
      var PaperMenuButton = Polymer({
 | 
						|
        is: 'paper-menu-button',
 | 
						|
 | 
						|
        /**
 | 
						|
         * Fired when the dropdown opens.
 | 
						|
         *
 | 
						|
         * @event paper-dropdown-open
 | 
						|
         */
 | 
						|
 | 
						|
        /**
 | 
						|
         * Fired when the dropdown closes.
 | 
						|
         *
 | 
						|
         * @event paper-dropdown-close
 | 
						|
         */
 | 
						|
 | 
						|
        behaviors: [
 | 
						|
          Polymer.IronA11yKeysBehavior,
 | 
						|
          Polymer.IronControlState
 | 
						|
        ],
 | 
						|
 | 
						|
        properties: {
 | 
						|
          /**
 | 
						|
           * True if the content is currently displayed.
 | 
						|
           */
 | 
						|
          opened: {
 | 
						|
            type: Boolean,
 | 
						|
            value: false,
 | 
						|
            notify: true,
 | 
						|
            observer: '_openedChanged'
 | 
						|
          },
 | 
						|
 | 
						|
          /**
 | 
						|
           * The orientation against which to align the menu dropdown
 | 
						|
           * horizontally relative to the dropdown trigger.
 | 
						|
           */
 | 
						|
          horizontalAlign: {
 | 
						|
            type: String,
 | 
						|
            value: 'left',
 | 
						|
            reflectToAttribute: true
 | 
						|
          },
 | 
						|
 | 
						|
          /**
 | 
						|
           * The orientation against which to align the menu dropdown
 | 
						|
           * vertically relative to the dropdown trigger.
 | 
						|
           */
 | 
						|
          verticalAlign: {
 | 
						|
            type: String,
 | 
						|
            value: 'top',
 | 
						|
            reflectToAttribute: true
 | 
						|
          },
 | 
						|
 | 
						|
          /**
 | 
						|
           * If true, the `horizontalAlign` and `verticalAlign` properties will
 | 
						|
           * be considered preferences instead of strict requirements when
 | 
						|
           * positioning the dropdown and may be changed if doing so reduces
 | 
						|
           * the area of the dropdown falling outside of `fitInto`.
 | 
						|
           */
 | 
						|
          dynamicAlign: {
 | 
						|
            type: Boolean
 | 
						|
          },
 | 
						|
 | 
						|
          /**
 | 
						|
           * A pixel value that will be added to the position calculated for the
 | 
						|
           * given `horizontalAlign`. Use a negative value to offset to the
 | 
						|
           * left, or a positive value to offset to the right.
 | 
						|
           */
 | 
						|
          horizontalOffset: {
 | 
						|
            type: Number,
 | 
						|
            value: 0,
 | 
						|
            notify: true
 | 
						|
          },
 | 
						|
 | 
						|
          /**
 | 
						|
           * A pixel value that will be added to the position calculated for the
 | 
						|
           * given `verticalAlign`. Use a negative value to offset towards the
 | 
						|
           * top, or a positive value to offset towards the bottom.
 | 
						|
           */
 | 
						|
          verticalOffset: {
 | 
						|
            type: Number,
 | 
						|
            value: 0,
 | 
						|
            notify: true
 | 
						|
          },
 | 
						|
 | 
						|
          /**
 | 
						|
           * If true, the dropdown will be positioned so that it doesn't overlap
 | 
						|
           * the button.
 | 
						|
           */
 | 
						|
          noOverlap: {
 | 
						|
            type: Boolean
 | 
						|
          },
 | 
						|
 | 
						|
          /**
 | 
						|
           * Set to true to disable animations when opening and closing the
 | 
						|
           * dropdown.
 | 
						|
           */
 | 
						|
          noAnimations: {
 | 
						|
            type: Boolean,
 | 
						|
            value: false
 | 
						|
          },
 | 
						|
 | 
						|
          /**
 | 
						|
           * Set to true to disable automatically closing the dropdown after
 | 
						|
           * a selection has been made.
 | 
						|
           */
 | 
						|
          ignoreSelect: {
 | 
						|
            type: Boolean,
 | 
						|
            value: false
 | 
						|
          },
 | 
						|
 | 
						|
          /**
 | 
						|
           * Set to true to enable automatically closing the dropdown after an
 | 
						|
           * item has been activated, even if the selection did not change.
 | 
						|
           */
 | 
						|
          closeOnActivate: {
 | 
						|
            type: Boolean,
 | 
						|
            value: false
 | 
						|
          },
 | 
						|
 | 
						|
          /**
 | 
						|
           * An animation config. If provided, this will be used to animate the
 | 
						|
           * opening of the dropdown.
 | 
						|
           */
 | 
						|
          openAnimationConfig: {
 | 
						|
            type: Object,
 | 
						|
            value: function() {
 | 
						|
              return [{
 | 
						|
                name: 'fade-in-animation',
 | 
						|
                timing: {
 | 
						|
                  delay: 100,
 | 
						|
                  duration: 200
 | 
						|
                }
 | 
						|
              }, {
 | 
						|
                name: 'paper-menu-grow-width-animation',
 | 
						|
                timing: {
 | 
						|
                  delay: 100,
 | 
						|
                  duration: 150,
 | 
						|
                  easing: config.ANIMATION_CUBIC_BEZIER
 | 
						|
                }
 | 
						|
              }, {
 | 
						|
                name: 'paper-menu-grow-height-animation',
 | 
						|
                timing: {
 | 
						|
                  delay: 100,
 | 
						|
                  duration: 275,
 | 
						|
                  easing: config.ANIMATION_CUBIC_BEZIER
 | 
						|
                }
 | 
						|
              }];
 | 
						|
            }
 | 
						|
          },
 | 
						|
 | 
						|
          /**
 | 
						|
           * An animation config. If provided, this will be used to animate the
 | 
						|
           * closing of the dropdown.
 | 
						|
           */
 | 
						|
          closeAnimationConfig: {
 | 
						|
            type: Object,
 | 
						|
            value: function() {
 | 
						|
              return [{
 | 
						|
                name: 'fade-out-animation',
 | 
						|
                timing: {
 | 
						|
                  duration: 150
 | 
						|
                }
 | 
						|
              }, {
 | 
						|
                name: 'paper-menu-shrink-width-animation',
 | 
						|
                timing: {
 | 
						|
                  delay: 100,
 | 
						|
                  duration: 50,
 | 
						|
                  easing: config.ANIMATION_CUBIC_BEZIER
 | 
						|
                }
 | 
						|
              }, {
 | 
						|
                name: 'paper-menu-shrink-height-animation',
 | 
						|
                timing: {
 | 
						|
                  duration: 200,
 | 
						|
                  easing: 'ease-in'
 | 
						|
                }
 | 
						|
              }];
 | 
						|
            }
 | 
						|
          },
 | 
						|
 | 
						|
          /**
 | 
						|
           * By default, the dropdown will constrain scrolling on the page
 | 
						|
           * to itself when opened.
 | 
						|
           * Set to true in order to prevent scroll from being constrained
 | 
						|
           * to the dropdown when it opens.
 | 
						|
           */
 | 
						|
          allowOutsideScroll: {
 | 
						|
            type: Boolean,
 | 
						|
            value: false
 | 
						|
          },
 | 
						|
 | 
						|
          /**
 | 
						|
           * Whether focus should be restored to the button when the menu closes.
 | 
						|
           */
 | 
						|
          restoreFocusOnClose: {
 | 
						|
            type: Boolean,
 | 
						|
            value: true
 | 
						|
          },
 | 
						|
 | 
						|
          /**
 | 
						|
           * This is the element intended to be bound as the focus target
 | 
						|
           * for the `iron-dropdown` contained by `paper-menu-button`.
 | 
						|
           */
 | 
						|
          _dropdownContent: {
 | 
						|
            type: Object
 | 
						|
          }
 | 
						|
        },
 | 
						|
 | 
						|
        hostAttributes: {
 | 
						|
          role: 'group',
 | 
						|
          'aria-haspopup': 'true'
 | 
						|
        },
 | 
						|
 | 
						|
        listeners: {
 | 
						|
          'iron-activate': '_onIronActivate',
 | 
						|
          'iron-select': '_onIronSelect'
 | 
						|
        },
 | 
						|
 | 
						|
        /**
 | 
						|
         * The content element that is contained by the menu button, if any.
 | 
						|
         */
 | 
						|
        get contentElement() {
 | 
						|
          return Polymer.dom(this.$.content).getDistributedNodes()[0];
 | 
						|
        },
 | 
						|
 | 
						|
        /**
 | 
						|
         * Toggles the drowpdown content between opened and closed.
 | 
						|
         */
 | 
						|
        toggle: function() {
 | 
						|
          if (this.opened) {
 | 
						|
            this.close();
 | 
						|
          } else {
 | 
						|
            this.open();
 | 
						|
          }
 | 
						|
        },
 | 
						|
 | 
						|
        /**
 | 
						|
         * Make the dropdown content appear as an overlay positioned relative
 | 
						|
         * to the dropdown trigger.
 | 
						|
         */
 | 
						|
        open: function() {
 | 
						|
          if (this.disabled) {
 | 
						|
            return;
 | 
						|
          }
 | 
						|
 | 
						|
          this.$.dropdown.open();
 | 
						|
        },
 | 
						|
 | 
						|
        /**
 | 
						|
         * Hide the dropdown content.
 | 
						|
         */
 | 
						|
        close: function() {
 | 
						|
          this.$.dropdown.close();
 | 
						|
        },
 | 
						|
 | 
						|
        /**
 | 
						|
         * When an `iron-select` event is received, the dropdown should
 | 
						|
         * automatically close on the assumption that a value has been chosen.
 | 
						|
         *
 | 
						|
         * @param {CustomEvent} event A CustomEvent instance with type
 | 
						|
         * set to `"iron-select"`.
 | 
						|
         */
 | 
						|
        _onIronSelect: function(event) {
 | 
						|
          if (!this.ignoreSelect) {
 | 
						|
            this.close();
 | 
						|
          }
 | 
						|
        },
 | 
						|
 | 
						|
        /**
 | 
						|
         * Closes the dropdown when an `iron-activate` event is received if
 | 
						|
         * `closeOnActivate` is true.
 | 
						|
         *
 | 
						|
         * @param {CustomEvent} event A CustomEvent of type 'iron-activate'.
 | 
						|
         */
 | 
						|
        _onIronActivate: function(event) {
 | 
						|
          if (this.closeOnActivate) {
 | 
						|
            this.close();
 | 
						|
          }
 | 
						|
        },
 | 
						|
 | 
						|
        /**
 | 
						|
         * When the dropdown opens, the `paper-menu-button` fires `paper-open`.
 | 
						|
         * When the dropdown closes, the `paper-menu-button` fires `paper-close`.
 | 
						|
         *
 | 
						|
         * @param {boolean} opened True if the dropdown is opened, otherwise false.
 | 
						|
         * @param {boolean} oldOpened The previous value of `opened`.
 | 
						|
         */
 | 
						|
        _openedChanged: function(opened, oldOpened) {
 | 
						|
          if (opened) {
 | 
						|
            // TODO(cdata): Update this when we can measure changes in distributed
 | 
						|
            // children in an idiomatic way.
 | 
						|
            // We poke this property in case the element has changed. This will
 | 
						|
            // cause the focus target for the `iron-dropdown` to be updated as
 | 
						|
            // necessary:
 | 
						|
            this._dropdownContent = this.contentElement;
 | 
						|
            this.fire('paper-dropdown-open');
 | 
						|
          } else if (oldOpened != null) {
 | 
						|
            this.fire('paper-dropdown-close');
 | 
						|
          }
 | 
						|
        },
 | 
						|
 | 
						|
        /**
 | 
						|
         * If the dropdown is open when disabled becomes true, close the
 | 
						|
         * dropdown.
 | 
						|
         *
 | 
						|
         * @param {boolean} disabled True if disabled, otherwise false.
 | 
						|
         */
 | 
						|
        _disabledChanged: function(disabled) {
 | 
						|
          Polymer.IronControlState._disabledChanged.apply(this, arguments);
 | 
						|
          if (disabled && this.opened) {
 | 
						|
            this.close();
 | 
						|
          }
 | 
						|
        },
 | 
						|
 | 
						|
        __onIronOverlayCanceled: function(event) {
 | 
						|
          var uiEvent = event.detail;
 | 
						|
          var target = Polymer.dom(uiEvent).rootTarget;
 | 
						|
          var trigger = this.$.trigger;
 | 
						|
          var path = Polymer.dom(uiEvent).path;
 | 
						|
 | 
						|
          if (path.indexOf(trigger) > -1) {
 | 
						|
            event.preventDefault();
 | 
						|
          }
 | 
						|
        }
 | 
						|
      });
 | 
						|
 | 
						|
      Object.keys(config).forEach(function (key) {
 | 
						|
        PaperMenuButton[key] = config[key];
 | 
						|
      });
 | 
						|
 | 
						|
      Polymer.PaperMenuButton = PaperMenuButton;
 | 
						|
    })();
 | 
						|
  </script>
 | 
						|
</dom-module>
 |