Search code examples
polymerweb-componentshadow-dom

Polymer: Animating iron-selector with neon-animation


To illustrate the problem I'm experiencing, I put together a little accordion-menu element based on version 1.0.7 of Polymer's <seed-element> boilerplate. To create your own copy of this element, follow these six steps:

  1. Download the <seed-element> boilerplate linked to above

  2. Open bower.json, replace all instances of "seed-element" with "accordion-menu", and replace the dependencies with this:

    "neon-animation": "PolymerElements/neon-animation#1.2.3",
    "polymer": "Polymer/polymer#1.4.0"
    
  3. Rename "seed-element.html" to "accordion-menu.html" and replace its contents with this:

    <!--
    @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-selector/iron-selector.html">
    <link rel="import" href="../neon-animation/animations/slide-down-animation.html">
    <link rel="import" href="../neon-animation/animations/slide-up-animation.html">
    <link rel="import" href="../neon-animation/neon-animation-runner-behavior.html">
    
    <!--
    @demo demo/index.html
    -->
    
    <dom-module id="accordion-menu">
      <template>
        <style>
          :host {
            display: block;
            box-sizing: border-box;
          }
    
          /deep/ .accordion-title {
            display: block;
            padding: 8px;
            color: #fff;
          }
    
          /deep/ .accordion-title:before {
            margin-right: 5px;
          }
    
          /deep/ div:not(.iron-selected) .accordion-title {
            background-color: #444;
            cursor: pointer;
          }
    
          /deep/ div:not(.iron-selected) .accordion-title:hover {
            background-color: #777;
          }
    
          /deep/ div:not(.iron-selected) .accordion-title:before {
            content: "\25BA";
          }
    
          /deep/ .iron-selected .accordion-title {
            background-color: #070;
          }
    
          /deep/ .iron-selected .accordion-title:before {
            content: "\25BC";
          }
    
          /deep/ .accordion-content {
            display: none;
          }
    
          /deep/ .iron-selected .accordion-content {
            display: block;
          }
        </style>
    
        <iron-selector selected="0"><content></content></iron-selector>
      </template>
    
      <script>
        Polymer({
          is: 'accordion-menu',
    
          properties: {
            animationConfig: {
              value: function() {
                return {
                  'entry': {
                    name: 'slide-down-animation',
                    node: this.root.querySelector('iron-selector').root.querySelector('.iron-selected'),
                  },
                }
              }
            },
          },
    
          'listeners': {
            'iron-deselect': 'onDeselect',
            'iron-select': 'onSelect',
          },
    
          'behaviors': [
            Polymer.NeonAnimationRunnerBehavior,
          ],
    
          onDeselect: function(e) {
            var deselectedItem = e.detail.item;
            // this.playAnimation('exit');
          },
    
          onSelect: function(e) {
            var selectedItem = e.detail.item;
            this.playAnimation('entry');
          }
        });
      </script>
    </dom-module>
    
  4. Replace the contents of "demo/index.html" with this:

    <!doctype 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
    -->
    <html>
      <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
        <title>accordion-menu Demo</title>
        <script src="../../webcomponentsjs/webcomponents-lite.min.js"></script>
        <link rel="import" href="../../paper-styles/demo-pages.html">
        <link rel="import" href="../accordion-menu.html">
      </head>
      <body unresolved>
    
        <p>An example of <code>&lt;accordion-menu&gt;</code>:</p>
    
        <accordion-menu>
          <div>
            <span class="accordion-title">Section 1</span>
            <div class="accordion-content">
              <p>Section 1's content</p>
            </div>
          </div>
    
          <div>
            <span class="accordion-title">Section 2</span>
            <div class="accordion-content">
              <p>Section 2's content</p>
            </div>
          </div>
    
          <div>
            <span class="accordion-title">Section 3</span>
            <div class="accordion-content">
              <p>Section 3's content</p>
            </div>
          </div>
    
          <div>
            <span class="accordion-title">Section 4</span>
            <div class="accordion-content">
              <p>Section 4's content</p>
            </div>
          </div>
        </accordion-menu>
    
      </body>
    </html>
    
  5. Run bower install

  6. Use polyserve to see the demo

When you click on any of the section titles, the section shows like it should, but it does not animate. The console has this error message:

Couldnt play ( entry [Object] ). TypeError: Cannot read property 'style' of null

I know the problem is what I have at line 82 of "accordion-menu.html":

node: this.root.querySelector('iron-selector').root.querySelector('.iron-selected'),

What should I put instead of what I have above?


Solution

  • Since the node changes depending on the selected item, I would do the following.

    Remove the

    node: this.root.querySelector('iron-selector').root.querySelector('.iron-selected')
    

    from

               return {
                  'entry': {
                    name: 'slide-down-animation',
                    node: this.root.querySelector('iron-selector').root.querySelector('.iron-selected'),
                  },
                }
    

    and change the

    onSelect: function(e) {
            var selectedItem = e.detail.item;
            this.playAnimation('entry');
          }
    

    to

     onSelect: function(e) {
            var selectedItem = e.detail.item;
            this.animationConfig.entry.node = selectedItem.querySelector(".accordion-content");
            this.playAnimation('entry');
          }