element-card.html 6.88 KB
<link rel="import" href="../../bower_components/iron-icons/maps-icons.html">
<link rel="import" href="../../bower_components/paper-material/paper-material.html">

<link rel="import" href="../catalog-element/catalog-element.html">
<link rel="import" href="../catalog-package/catalog-package.html">
<link rel="import" href="../hero-image/hero-image.html">
<link rel="import" href="../package-symbol/package-symbol.html">
<link rel="import" href="../element-action-menu/element-action-menu.html">

<dom-module id="element-card">
  <template>
    <style>
      :host {
        display: block;
        margin: 10px 10px 10px 0;
        cursor: pointer;
        border-radius: 4px;
        border: 1px solid #d0d0d0;
        background: white;
        flex: 1 250px;
        max-width: calc(33% - 10px);
        transition-properties: opacity, box-shadow;
        transition-duration: 0.4s;

        -webkit-transition-properties: opacity, box-shadow;
        -webkit-transition-duration: 0.4s;
      }

      @media (max-width: 1070px) {
        :host {
          max-width: calc(50% - 10px);
        }
      }

      @media (max-width: 530px) {
        :host {
          max-width: calc(100% - 10px);
        }
      }

      :host(:hover),
      :host(.hover) {
        @apply(--shadow-elevation-2dp);
      }

      h3 {
        font-size: 16px;
        font-weight: 500;
        margin: 0;
        padding: 10px 16px 0;
      }

      p {
        margin: 0;
      }

      #el {
        cursor: pointer;
      }

      #hero {
        width: 100%;
        height: 120px;
        background: #ccc;
        border-radius: 3px 3px 0 0;
        overflow: hidden;
        border-bottom: 1px solid #e5e5e5;
      }

      #hero > img {
        width: 100%;
        height: 100%;
      }

      .meta {
        border-top: 1px solid;
        border-bottom: 1px solid;
        border-color: var(--divider-color);
        padding: 10px 16px;
      }

      .meta + .meta {
        border-top: 0;
      }

      .meta:last-child {
        border-bottom: 0;
      }

      #el-desc {
        @apply(--paper-font-body1);
        color: var(--secondary-text-color);
        margin: 0;
        padding: 10px 16px;
        height: 75px;
      }

      .package {
        font-size: 12px;
        font-weight: 500;
      }

      .package package-symbol {
        margin: 0 15px 0 0;
      }

      .package > a:hover {
        text-decoration: underline;
      }

      .tags iron-icon {
        margin: 0 15px 0 0;
        padding: 5px;
        color: var(--secondary-text-color);
        --iron-icon-size: 18px;
      }

      .tag {
        margin-right: 4px;
        font-size: 12px;
      }

      .tag:hover {
        text-decoration: underline;
      }

      .tag:after {
        margin-left: -3px;
        content: " ,";
      }

      .tag:last-of-type:after {
        content: "";
      }
    </style>
    <a href="[[_getElementLink(item.name)]]">
      <div id="content" class="vertical layout">
        <div id="el" view="docs">
          <div id="hero" on-mouseenter="_mouseEnter" on-mouseleave="_mouseLeave" style$="[[_computeStyle(color)]]">
            <img src="[[_getImageSrc(item.hero)]]">
          </div>
          <h3>[[item.name]]</h3>
        </div>
        <p id="el-desc">[[item.description]]</p>
        <div class="horizontal layout center meta package">
          <package-symbol symbol="[[packageSymbol]]" color="[[color]]"></package-symbol>
          <a href="[[_getPackageLink(item.package)]]">[[item.package]]</a>
        </div>
        <div class="meta tags">
          <iron-icon icon="maps:local-offer" class="flex-none"></iron-icon>
            <template is="dom-repeat" items="[[item.tags]]" as="tag">
              <a href="[[_getTagLink(item.package, tag)]]" class="tag">[[tag]]</a>
            </template>
        </div>
      </div>
    </a>
  </template>
</dom-module>

<script>
(function() {
  var sharedActionMenu = null;
  var activeCard = null;

  function mouseEnter() {
    if (activeCard) {
      activeCard.showActions();
    }
  }

  function mouseLeave() {
    if (activeCard) {
      activeCard.hideActions();
    }
  }

  Polymer({
    is: 'element-card',
    enableCustomStyleProperties: true,
    properties: {
      item: Object,
      color: String,
      packageSymbol: String
    },

    observers: [
      '_updatePackage(_element)'
    ],

    attached: function() {
      this.style.opacity = 0;

      this.async(function() {
        this.style.opacity = 1;
      }, 1);
    },

    detached: function() {
      if (activeCard === this) {
        activeCard = null;
        if (sharedActionMenu) {
          Polymer.dom(this.parentNode).removeChild(sharedActionMenu);
          sharedActionMenu = null;
        }
      }
    },

    _tagClicked: function(e) {
      e.stopPropagation();
      this.fire('update-params', {tag: e.currentTarget.name});
    },
    _computeStyle: function(color) {
      return 'background-color:' + color;
    },
    _getElementLink: function(elementName) {
      return '/elements/' + elementName;
    },
    _getImageSrc: function(src) {
      return src && src.length ? src : '/images/hero/random-' + Math.ceil(Math.random() * 4) + '.svg';
    },

    _getPackageLink: function(packageName) {
      return '/browse?package=' + packageName + '&view=cards';
    },

    _getTagLink: function(packageName, tag) {
      return '/browse?tag=' + tag + '&view=cards';
    },

    showActions: function() {
      var top = this.$.hero.offsetTop;
      var left = this.$.hero.offsetLeft;
      var width = this.$.hero.offsetWidth;

      if (!sharedActionMenu) {
        sharedActionMenu = document.createElement('element-action-menu');
        sharedActionMenu.classList.add('cards');
        sharedActionMenu.classList.add('hidden');
        sharedActionMenu.addEventListener('mouseenter', mouseEnter);
        sharedActionMenu.addEventListener('mouseleave', mouseLeave);
      }
      if (!sharedActionMenu.parentNode) {
        Polymer.dom(this.parentNode).appendChild(sharedActionMenu);
      }

      top += this.$.hero.offsetHeight - sharedActionMenu.offsetHeight;

      sharedActionMenu.element = this.item.name;
      sharedActionMenu.style.top = top + 'px';
      sharedActionMenu.style.left = left + 'px';
      sharedActionMenu.style.width = width + 'px';

      this._layoutIfNeeded(sharedActionMenu);
      sharedActionMenu.classList.remove('hidden');
      this.classList.add('hover');
      sharedActionMenu.cancelDebouncer('hide');
    },

    hideActions: function() {
      if (sharedActionMenu && sharedActionMenu.element == this.item.name) {
        sharedActionMenu.debounce('hide', function() {
          sharedActionMenu.classList.add('hidden');
        }, 10);
        this.classList.remove('hover');
      }
    },

    _mouseEnter: function() {
      activeCard = this;
      mouseEnter();
    },

    _mouseLeave: function(e) {
      mouseLeave();
    },

    _layoutIfNeeded: function(el) {
      return el.offsetTop;
    }
  });

})();
</script>