element-table.html 5.81 KB
<link rel="import" href="../../bower_components/paper-styles/paper-styles.html">

<link rel="import" href="../element-action-menu/element-action-menu.html">
<link rel="import" href="../tag-link/tag-link.html">

<dom-module id="element-table">
  <template>
    <style>
      :host {
        display: block;
        position: relative;
        background: white;
        border: 1px solid #d0d0d0;
        border-radius: 3px;
        opacity: 1;
        transition: opacity 0.4s;
      }

      :host(.hidden) {
        transition: none;
        opacity: 0;
      }

      .header {
        padding: 0 24px;
        line-height: 56px;
        font-size: 12px;
        font-weight: 500;
        border-bottom: 1px solid #e5e5e5;
      }

      :host([narrow-viewport]) .header .description {
        display: none;
      }

      :host(:not([narrow-viewport])) .header,
      :host(:not([narrow-viewport])) .row,
      :host(:not([narrow-viewport])) .row a {
        @apply(--layout-horizontal);
      }

      :host([narrow-viewport]) .header,
      :host([narrow-viewport]) .row,
      :host([narrow-viewport]) .row a {
        @apply(--layout-vertical);
      }

      .row {
        border-bottom: 1px solid #e5e5e5;
      }

      .row a {
        box-sizing: border-box;
        cursor: pointer;
        overflow: hidden;
        width: 100%;
        padding: 15px 24px;
        font-weight: 400;
        font-size: 13px;
      }

      .row.hover {
        background: #fafafa;
      }

      :host(:not([narrow-viewport])) .row.hover .description {
        padding-right: 120px;
      }

      .name {
        min-width: 250px;
        font-weight: 500;
      }

      .name .narrow {
        display: none;
      }

      :host([narrow-viewport])  .name .narrow {
        display: inline;
      }

      .row .description {
        color: #757575;
      }

      :host(:not([narrow-viewport])) .row .description {
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
      }

      #actions element-action-menu {
        right: 0;
      }

    </style>
    <iron-media-query query="(max-width: 640px)" query-matches="{{narrowViewport}}"></iron-media-query>

    <div class="header" style$="[[_getHeaderStyle(color)]]">
      <div class="name">Name <span class="narrow">/ Description</span></div>
      <div class="description">Description</div>
    </div>
    <template is="dom-repeat" items="[[elements]]">
      <div class="row" data-index$="[[index]]">
        <a href$="[[_elementLink(item.name)]]">
          <div class="name">[[item.name]]</div>
          <div class="description">[[item.description]]</div>
        </a>
      </div>
    </template>
    <div id="actions"></div>
  </template>
</dom-module>
<script>
  Polymer({
    is: 'element-table',

    properties: {
      elements: {
        type: Array,
        observer: '_elementsChanged'
      },
      color: {
        type: String
      },
      narrowViewport: {
        type: Boolean,
        reflectToAttribute: true
      }
    },

    listeners: {
      'tap': '_tap',
      'mouseover': '_mouseOver',
      'mouseleave': '_mouseLeave'
    },

    _currentRowIndex: -1,

    _sharedActionMenu: null,

    _findAncestor: function(node, fn) {
      while (node && fn.call(this, node)) {
        node = node.parentNode;
      }
      return node;
    },

    _tap: function(e) {
      var sourceEvent = e.detail.sourceEvent;
      var A = this._findAncestor(e.target, function(node) {
        return node != this && node.tagName !== 'A';
      });

      if (A && A.tagName === 'A' && A.href.indexOf(location.host) > 0) {
        if (sourceEvent.ctrlKey || sourceEvent.metaKey) {
          window.open(A.href);
        } else {
          this.fire('nav', {url: A.href});
        }
        e.preventDefault();
      }
    },

    _mouseOver: function(e) {
      var row = this._findAncestor(e.target, function(node) {
        return node != this && !node.classList.contains('row') && node.id !== 'actions';
      });
      if (row && row.classList.contains('row')) {
        if (this._currentRowIndex != row.dataset.index) {
          this._hideActions();
          this._showActions(row, row.dataset.index);
        }
      } else if (row.id !== 'actions') {
        this._hideActions();
      }
    },

    _mouseLeave: function() {
      this._hideActions();
    },

    _showActions: function(row, index) {
      var sharedActionMenu = this._sharedActionMenu;
      var rowOffsetTop = row.offsetTop;

      if (!sharedActionMenu) {
        this._sharedActionMenu = document.createElement('element-action-menu');
        this._sharedActionMenu.classList.add('hidden');
        Polymer.dom(this.$.actions).appendChild(this._sharedActionMenu);
        sharedActionMenu = this._sharedActionMenu;
      }

      sharedActionMenu.iconsOnly = true;
      sharedActionMenu.element = this.elements[index].name;
      sharedActionMenu.style.top = rowOffsetTop + 'px';

      this._layoutIfNeeded(sharedActionMenu);
      sharedActionMenu.classList.remove('hidden');
      row.classList.add('hover');

      this._currentRowIndex = index;
      this._currentRow = row;
    },

    _hideActions: function() {
      var row = this._currentRow;
      var sharedActionMenu = this._sharedActionMenu;

      if (row) {
        if (sharedActionMenu) {
          sharedActionMenu.classList.add('hidden');
        }
        row.classList.remove('hover');
        this._currentRowIndex = -1;
        this._currentRow = null;
      }
    },

    _elementLink: function(name) {
      return "/elements/" + name;
    },

    _getHeaderStyle: function(color) {
      return 'background-color: '+ color+';';
    },

    _elementsChanged: function() {
      this.classList.add('hidden');
      this.async(function() {
        this.classList.remove('hidden');
      }, 1);
    },

     _layoutIfNeeded: function(el) {
      return el.offsetTop;
    }
  });
</script>