@ngdoc directive
@name mdGridTile
@module material.components.gridList
@restrict E
@description
Tiles contain the content of an `md-grid-list`. They span one or more grid
cells vertically or horizontally, and use `md-grid-tile-{footer,header}` to
display secondary content.

### Responsive Attributes

The `md-grid-tile` directive supports "responsive" attributes, which allow
different `md-rowspan` and `md-colspan` values depending on the currently
matching media query.

In order to set a responsive attribute, first define the fallback value with
the standard attribute name, then add additional attributes with the
following convention: `{base-attribute-name}-{media-query-name}="{value}"`
(ie. `md-colspan-sm="4"`)

@param {number=} md-colspan The number of columns to span (default 1). Cannot
exceed the number of columns in the grid. Supports interpolation.
@param {number=} md-rowspan The number of rows to span (default 1). Supports
interpolation.

@usage
With header:
<hljs lang="html">
<md-grid-tile>
<md-grid-tile-header>
<h3>This is a header</h3>
</md-grid-tile-header>
</md-grid-tile>
</hljs>

With footer:
<hljs lang="html">
<md-grid-tile>
<md-grid-tile-footer>
<h3>This is a footer</h3>
</md-grid-tile-footer>
</md-grid-tile>
</hljs>

Spanning multiple rows/columns:
<hljs lang="html">
<md-grid-tile md-colspan="2" md-rowspan="3">
</md-grid-tile>
</hljs>

Responsive attributes:
<hljs lang="html">
<md-grid-tile md-colspan="1" md-colspan-sm="3" md-colspan-md="5">
</md-grid-tile>
</hljs>
function GridTileDirective($mdMedia) {
  return {
    restrict: 'E',
    require: '^mdGridList',
    template: '<figure ng-transclude></figure>',
    transclude: true,
    scope: {},
    // Simple controller that exposes attributes to the grid directive
    controller: ["$attrs", function($attrs) {
      this.$attrs = $attrs;
    }],
    link: postLink
  };

  function postLink(scope, element, attrs, gridCtrl) {
    // Apply semantics
    element.attr('role', 'listitem');

    // If our colspan or rowspan changes, trigger a layout
    var unwatchAttrs = $mdMedia.watchResponsiveAttributes(['md-colspan', 'md-rowspan'],
        attrs, angular.bind(gridCtrl, gridCtrl.invalidateLayout));

    // Tile registration/deregistration
    gridCtrl.invalidateTiles();
    scope.$on('$destroy', function() {
      // Mark the tile as destroyed so it is no longer considered in layout,
      // even if the DOM element sticks around (like during a leave animation)
      element[0].$$mdDestroyed = true;
      unwatchAttrs();
      gridCtrl.invalidateLayout();
    });

    if (angular.isDefined(scope.$parent.$index)) {
      scope.$watch(function() { return scope.$parent.$index; },
        function indexChanged(newIdx, oldIdx) {
          if (newIdx === oldIdx) {
            return;
          }
          gridCtrl.invalidateTiles();
        });
    }
  }
}