text: /*!
   * AngularJS Material Design
   * https://github.com/angular/material
   * @license MIT
   * v1.1.21
   */
  (function( window, angular, undefined ){
  "use strict";
  
  /**
   * @ngdoc module
   * @name material.components.icon
   * @description
   * Icon
   */
  angular.module('material.components.icon', ['material.core']);
  
  angular
    .module('material.components.icon')
    .directive('mdIcon', ['$mdIcon', '$mdTheming', '$mdAria', '$sce', mdIconDirective]);
  
  /**
   * @ngdoc directive
   * @name mdIcon
   * @module material.components.icon
   *
   * @restrict E
   *
   * @description
   * The `md-icon` directive makes it easier to use vector-based icons in your app (as opposed to
   * raster-based icons types like PNG). The directive supports both icon fonts and SVG icons.
   *
   * Icons should be considered view-only elements that should not be used directly as buttons; instead nest a `<md-icon>`
   * inside a `md-button` to add hover and click features.
   *
   * ### Icon fonts
   * Icon fonts are a technique in which you use a font where the glyphs in the font are
   * your icons instead of text. Benefits include a straightforward way to bundle everything into a
   * single HTTP request, simple scaling, easy color changing, and more.
   *
   * `md-icon` lets you consume an icon font by letting you reference specific icons in that font
   * by name rather than character code.
   *
   * When using font-icons, developers must follow three (3) simple steps:
   *
   * <ol>
   * <li>Load the font library. e.g.<br/>
   *    `<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">`
   * </li>
   * <li>
   *   Use either (a) font-icon class names or (b) a fontset and a font ligature to render the font glyph by
   *   using its textual name _or_ numerical character reference. Note that `material-icons` is the default fontset when
   *   none is specified.
   * </li>
   * <li> Use any of the following templates: <br/>
   *   <ul>
   *     <li>`<md-icon md-font-icon="classname"></md-icon>`</li>
   *     <li>`<md-icon md-font-set="font library classname or alias">textual_name</md-icon>`</li>
   *     <li>`<md-icon> numerical_character_reference </md-icon>`</li>
   *     <li>`<md-icon ng_bind="'textual_name'"></md-icon>`</li>
   *     <li>`<md-icon ng-bind="scopeVariable"></md-icon>`</li>
   *   </ul>
   * </li>
   * </ol>
   *
   * Full details for these steps can be found in the
   * <a href="http://google.github.io/material-design-icons/#icon-font-for-the-web" target="_blank">
   * Material Design Icon font for the web docs</a>.
   *
   * You can browse and search the Material Design icon style <code>.material-icons</code>
   * in the <a href="https://material.io/tools/icons/" target="_blank">Material Design Icons tool</a>.
   *
   * ### SVG
   * For SVGs, the problem with using `<img>` or a CSS `background-image` is that you can't take
   * advantage of some SVG features, such as styling specific parts of the icon with CSS or SVG
   * animation.
   *
   * `md-icon` makes it easier to use SVG icons by *inlining* the SVG into an `<svg>` element in the
   * document. The most straightforward way of referencing an SVG icon is via URL, just like a
   * traditional `<img>`. `$mdIconProvider`, as a convenience, lets you _name_ an icon so you can
   * reference it by name instead of URL throughout your templates.
   *
   * Additionally, you may not want to make separate HTTP requests for every icon, so you can bundle
   * your SVG icons together and pre-load them with `$mdIconProvider` as an icon set. An icon set can
   * also be given a name, which acts as a namespace for individual icons, so you can reference them
   * like `"social:cake"`.
   *
   * When using SVGs, both external SVGs (via URLs) or sets of SVGs (from icon sets) can be
   * easily loaded and used.
   *
   * ### Localization
   *
   * Because an `md-icon` element's text content is not intended to be translated, it is recommended
   * to declare the text content for an `md-icon` element in its start tag. Instead of using the HTML
   * text content, consider using `ng-bind` with a scope variable or literal string.
   *
   * Examples:
   *
   * <ul>
   *   <li>`<md-icon ng-bind="myIconVariable"></md-icon>`</li>
   *   <li>`<md-icon ng-bind="'menu'"></md-icon>`
   * </ul>
   *
   * <h2 id="material_design_icons">Material Design Icons tool</h2>
   * Using the Material Design Icons tool, developers can easily and quickly search for a specific
   * open source Material Design icon. The search is in the top left. Below search, you can select
   * from the new icon themes or filter by icon category.
   *
   * <a href="https://material.io/tools/icons/" target="_blank" style="border-bottom:none;">
   * <img src="https://user-images.githubusercontent.com/3506071/41942584-ef0695d0-796d-11e8-9436-44f25023a111.png"
   *      aria-label="Material Design Icons tool" style="max-width:95%">
   * </a>
   *
   * <div class="md-caption" style="text-align: center; margin-bottom: 24px">
   *  Click on the image above to open the
   *  <a href="https://material.io/tools/icons/" target="_blank">Material Design Icons tool</a>.
   * </div>
   *
   * Click on any icon, then click on the "Selected Icon" chevron to see the slide-up
   * information panel with details regarding a SVG download and information on the font-icon's
   * textual name. This panel also allows you to select a black on transparent or white on transparent
   * icon and to change the icon size. These settings only affect the downloaded icons.
   *
   * @param {string} md-font-icon String name of CSS icon associated with the font-face will be used
   * to render the icon. Requires the fonts and the named CSS styles to be preloaded.
   * @param {string} md-font-set CSS style name associated with the font library; which will be assigned as
   * the class for the font-icon ligature. This value may also be an alias that is used to lookup the classname;
   * internally use `$mdIconProvider.fontSet(<alias>)` to determine the style name.
   * @param {string} md-svg-src String URL (or expression) used to load, cache, and display an
   *     external SVG.
   * @param {string} md-svg-icon md-svg-icon String name used for lookup of the icon from the internal cache;
   *     interpolated strings or expressions may also be used. Specific set names can be used with
   *     the syntax `<set name>:<icon name>`.<br/><br/>
   * To use icon sets, developers are required to pre-register the sets using the `$mdIconProvider` service.
   * @param {string=} aria-label Labels icon for accessibility. If an empty string is provided, icon
   * will be hidden from accessibility layer with `aria-hidden="true"`. If there's no aria-label on the icon
   * nor a label on the parent element, a warning will be logged to the console.
   * @param {string=} alt Labels icon for accessibility. If an empty string is provided, icon
   * will be hidden from accessibility layer with `aria-hidden="true"`. If there's no alt on the icon
   * nor a label on the parent element, a warning will be logged to the console.
   *
   * @usage
   * When using SVGs:
   * <hljs lang="html">
   *
   *<!-- Icon ID; may contain optional icon set prefix.
   *     Icons must be registered using $mdIconProvider. -->
   *<md-icon md-svg-icon="social:android"    aria-label="android " ></md-icon>
   *
   *<!-- Icon urls; may be preloaded in templateCache -->
   *<md-icon md-svg-src="/android.svg"       aria-label="android " ></md-icon>
   *<md-icon md-svg-src="{{ getAndroid() }}" aria-label="android " ></md-icon>
   *
   * </hljs>
   *
   * Use the <code>$mdIconProvider</code> to configure your application with
   * SVG icon sets.
   *
   * <hljs lang="js">
   * angular.module('appSvgIconSets', ['ngMaterial'])
   *   .controller('DemoCtrl', function($scope) {})
   *   .config(function($mdIconProvider) {
   *     $mdIconProvider
   *       .iconSet('social', 'img/icons/sets/social-icons.svg', 24)
   *       .defaultIconSet('img/icons/sets/core-icons.svg', 24);
   *    });
   * </hljs>
   *
   *
   * When using Font Icons with classnames:
   * <hljs lang="html">
   *
   * <md-icon md-font-icon="android" aria-label="android" ></md-icon>
   * <md-icon class="icon_home" aria-label="Home"></md-icon>
   *
   * </hljs>
   *
   * When using Material Font Icons with ligatures:
   * <hljs lang="html">
   *  <!--
   *  For Material Design Icons
   *  The class '.material-icons' is auto-added if a style has NOT been specified
   *  since `material-icons` is the default fontset. So your markup:
   *  -->
   *  <md-icon> face </md-icon>
   *  <!-- becomes this at runtime: -->
   *  <md-icon md-font-set="material-icons"> face </md-icon>
   *  <!-- If the fontset does not support ligature names, then we need to use the ligature unicode.-->
   *  <md-icon> &#xE87C; </md-icon>
   *  <!-- The class '.material-icons' must be manually added if other styles are also specified-->
   *  <md-icon class="material-icons md-light md-48"> face </md-icon>
   * </hljs>
   *
   * When using other Font-Icon libraries:
   *
   * <hljs lang="js">
   *  // Specify a font-icon style alias
   *  angular.config(function($mdIconProvider) {
   *    $mdIconProvider.fontSet('md', 'material-icons');
   *  });
   * </hljs>
   *
   * <hljs lang="html">
   *  <md-icon md-font-set="md">favorite</md-icon>
   * </hljs>
   *
   */
  function mdIconDirective($mdIcon, $mdTheming, $mdAria, $sce) {
  
    return {
      restrict: 'E',
      link : postLink
    };
  
  
    /**
     * Directive postLink
     * Supports embedded SVGs, font-icons, & external SVGs
     */
    function postLink(scope, element, attr) {
      $mdTheming(element);
      var lastFontIcon = attr.mdFontIcon;
      var lastFontSet = $mdIcon.fontSet(attr.mdFontSet);
  
      prepareForFontIcon();
  
      attr.$observe('mdFontIcon', fontIconChanged);
      attr.$observe('mdFontSet', fontIconChanged);
  
      // Keep track of the content of the svg src so we can compare against it later to see if the
      // attribute is static (and thus safe).
      var originalSvgSrc = element[0].getAttribute(attr.$attr.mdSvgSrc);
  
      // If using a font-icon, then the textual name of the icon itself
      // provides the aria-label.
  
      var attrName = attr.$normalize(attr.$attr.mdSvgIcon || attr.$attr.mdSvgSrc || '');
  
      /* Provide a default accessibility role of img */
      if (!attr.role) {
        $mdAria.expect(element, 'role', 'img');
        /* manually update attr variable */
        attr.role = 'img';
      }
  
      /* Don't process ARIA if already valid */
      if (attr.role === "img" && !attr.ariaHidden && !$mdAria.hasAriaLabel(element)) {
        var iconName;
        if (attr.alt) {
          /* Use alt text by default if available */
          $mdAria.expect(element, 'aria-label', attr.alt);
        } else if ($mdAria.parentHasAriaLabel(element, 2)) {
          /* Parent has ARIA so we will assume it will describe the image */
          $mdAria.expect(element, 'aria-hidden', 'true');
        } else if (iconName = (attr.mdFontIcon || attr.mdSvgIcon || element.text())) {
          /* Use icon name as aria-label */
          $mdAria.expect(element, 'aria-label', iconName);
        } else {
          /* No label found */
          $mdAria.expect(element, 'aria-hidden', 'true');
        }
      }
  
      if (attrName) {
        // Use either pre-configured SVG or URL source, respectively.
        attr.$observe(attrName, function(attrVal) {
          element.empty();
          if (attrVal) {
            $mdIcon(attrVal)
              .then(function(svg) {
              element.empty();
              element.append(svg);
            });
          }
        });
      }
  
      function prepareForFontIcon() {
        if (!attr.mdSvgIcon && !attr.mdSvgSrc) {
          if (attr.mdFontIcon) {
            element.addClass('md-font ' + attr.mdFontIcon);
          }
  
          element.addClass(lastFontSet);
        }
      }
  
      function fontIconChanged() {
        if (!attr.mdSvgIcon && !attr.mdSvgSrc) {
          if (attr.mdFontIcon) {
            element.removeClass(lastFontIcon);
            element.addClass(attr.mdFontIcon);
  
            lastFontIcon = attr.mdFontIcon;
          }
  
          var fontSet = $mdIcon.fontSet(attr.mdFontSet);
  
          if (lastFontSet !== fontSet) {
            element.removeClass(lastFontSet);
            element.addClass(fontSet);
  
            lastFontSet = fontSet;
          }
        }
      }
    }
  }
  
    
  MdIconService['$inject'] = ["config", "$templateRequest", "$q", "$log", "$mdUtil", "$sce"];angular
      .module('material.components.icon')
      .constant('$$mdSvgRegistry', {
          'mdTabsArrow':   'data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIHg9IjBweCIgeT0iMHB4IiB2aWV3Qm94PSIwIDAgMjQgMjQiPjxnPjxwb2x5Z29uIHBvaW50cz0iMTUuNCw3LjQgMTQsNiA4LDEyIDE0LDE4IDE1LjQsMTYuNiAxMC44LDEyICIvPjwvZz48L3N2Zz4=',
          'mdClose':       'data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIHg9IjBweCIgeT0iMHB4IiB2aWV3Qm94PSIwIDAgMjQgMjQiPjxnPjxwYXRoIGQ9Ik0xOSA2LjQxbC0xLjQxLTEuNDEtNS41OSA1LjU5LTUuNTktNS41OS0xLjQxIDEuNDEgNS41OSA1LjU5LTUuNTkgNS41OSAxLjQxIDEuNDEgNS41OS01LjU5IDUuNTkgNS41OSAxLjQxLTEuNDEtNS41OS01LjU5eiIvPjwvZz48L3N2Zz4=',
          'mdCancel':      'data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIHg9IjBweCIgeT0iMHB4IiB2aWV3Qm94PSIwIDAgMjQgMjQiPjxnPjxwYXRoIGQ9Ik0xMiAyYy01LjUzIDAtMTAgNC40Ny0xMCAxMHM0LjQ3IDEwIDEwIDEwIDEwLTQuNDcgMTAtMTAtNC40Ny0xMC0xMC0xMHptNSAxMy41OWwtMS40MSAxLjQxLTMuNTktMy41OS0zLjU5IDMuNTktMS40MS0xLjQxIDMuNTktMy41OS0zLjU5LTMuNTkgMS40MS0xLjQxIDMuNTkgMy41OSAzLjU5LTMuNTkgMS40MSAxLjQxLTMuNTkgMy41OSAzLjU5IDMuNTl6Ii8+PC9nPjwvc3ZnPg==',
          'mdMenu':        'data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIHg9IjBweCIgeT0iMHB4IiB2aWV3Qm94PSIwIDAgMjQgMjQiPjxwYXRoIGQ9Ik0zLDZIMjFWOEgzVjZNMywxMUgyMVYxM0gzVjExTTMsMTZIMjFWMThIM1YxNloiIC8+PC9zdmc+',
          'mdToggleArrow': 'data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIHg9IjBweCIgeT0iMHB4IiB2aWV3Qm94PSIwIDAgNDggNDgiPjxwYXRoIGQ9Ik0yNCAxNmwtMTIgMTIgMi44MyAyLjgzIDkuMTctOS4xNyA5LjE3IDkuMTcgMi44My0yLjgzeiIvPjxwYXRoIGQ9Ik0wIDBoNDh2NDhoLTQ4eiIgZmlsbD0ibm9uZSIvPjwvc3ZnPg==',
          'mdCalendar':    'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij48cGF0aCBkPSJNMTkgM2gtMVYxaC0ydjJIOFYxSDZ2Mkg1Yy0xLjExIDAtMS45OS45LTEuOTkgMkwzIDE5YzAgMS4xLjg5IDIgMiAyaDE0YzEuMSAwIDItLjkgMi0yVjVjMC0xLjEtLjktMi0yLTJ6bTAgMTZINVY4aDE0djExek03IDEwaDV2NUg3eiIvPjwvc3ZnPg==',
          'mdChecked':     'data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIHg9IjBweCIgeT0iMHB4IiB2aWV3Qm94PSIwIDAgMjQgMjQiPjxnPjxwYXRoIGQ9Ik05IDE2LjE3TDQuODMgMTJsLTEuNDIgMS40MUw5IDE5IDIxIDdsLTEuNDEtMS40MXoiLz48L2c+PC9zdmc+'
      })
      .provider('$mdIcon', MdIconProvider);
  
  /**
   * @ngdoc service
   * @name $mdIconProvider
   * @module material.components.icon
   *
   * @description
   * `$mdIconProvider` is used only to register icon IDs with URLs. These configuration features allow
   * icons and icon sets to be pre-registered and associated with source URLs **before** the `<md-icon />`
   * directives are compiled.
   *
   * If using font-icons, the developer is responsible for loading the fonts.
   *
   * If using SVGs, loading of the actual svg files are deferred to on-demand requests and are loaded
   * internally by the `$mdIcon` service using the `$templateRequest` service. When an SVG is
   * requested by name/ID, the `$mdIcon` service searches its registry for the associated source URL;
   * that URL is used to on-demand load and parse the SVG dynamically.
   *
   * The `$templateRequest` service expects the icons source to be loaded over trusted URLs.<br/>
   * This means, when loading icons from an external URL, you have to trust the URL in the `$sceDelegateProvider`.
   *
   * <hljs lang="js">
   *   app.config(function($sceDelegateProvider) {
   *     $sceDelegateProvider.resourceUrlWhitelist([
   *       // Adding 'self' to the whitelist, will allow requests from the current origin.
   *       'self',
   *       // Using double asterisks here, will allow all URLs to load.
   *       // We recommend to only specify the given domain you want to allow.
   *       '**'
   *     ]);
   *   });
   * </hljs>
   *
   * Read more about the [$sceDelegateProvider](https://docs.angularjs.org/api/ng/provider/$sceDelegateProvider).
   *
   * **Notice:** Most font-icons libraries do not support ligatures (for example `fontawesome`).<br/>
   *  In such cases you are not able to use the icon's ligature name - Like so:
   *
   *  <hljs lang="html">
   *    <md-icon md-font-set="fa">fa-bell</md-icon>
   *  </hljs>
   *
   * You should instead use the given unicode, instead of the ligature name.
   *
   * <p ng-hide="true"> ##// Notice we can't use a hljs element here, because the characters will be escaped.</p>
   *  ```html
   *    <md-icon md-font-set="fa">&#xf0f3</md-icon>
   *  ```
   *
   * All unicode ligatures are prefixed with the `&#x` string.
   *
   * @usage
   * <hljs lang="js">
   *   app.config(function($mdIconProvider) {
      *
      *     // Configure URLs for icons specified by [set:]id.
      *
      *     $mdIconProvider
      *          .defaultFontSet( 'fa' )                   // This sets our default fontset className.
      *          .defaultIconSet('my/app/icons.svg')       // Register a default set of SVG icons
      *          .iconSet('social', 'my/app/social.svg')   // Register a named icon set of SVGs
      *          .icon('android', 'my/app/android.svg')    // Register a specific icon (by name)
      *          .icon('work:chair', 'my/app/chair.svg');  // Register icon in a specific set
      *   });
   * </hljs>
   *
   * SVG icons and icon sets can be easily pre-loaded and cached using either (a) a build process or (b) a runtime
   * **startup** process (shown below):
   *
   * <hljs lang="js">
   *   app.config(function($mdIconProvider) {
      *
      *     // Register a default set of SVG icon definitions
      *     $mdIconProvider.defaultIconSet('my/app/icons.svg')
      *
      *   })
   *   .run(function($templateRequest){
      *
      *     // Pre-fetch icons sources by URL and cache in the $templateCache...
      *     // subsequent $templateRequest calls will look there first.
      *
      *     var urls = [ 'imy/app/icons.svg', 'img/icons/android.svg'];
      *
      *     angular.forEach(urls, function(url) {
      *       $templateRequest(url);
      *     });
      *
      *   });
   *
   * </hljs>
   *
   * > <b>Note:</b> The loaded SVG data is subsequently cached internally for future requests.
   *
   */
  
  /**
   * @ngdoc method
   * @name $mdIconProvider#icon
   *
   * @description
   * Register a source URL for a specific icon name; the name may include optional 'icon set' name prefix.
   * These icons  will later be retrieved from the cache using `$mdIcon( <icon name> )`
   *
   * @param {string} id Icon name/id used to register the icon
   * @param {string} url specifies the external location for the data file. Used internally by
   * `$templateRequest` to load the data or as part of the lookup in `$templateCache` if pre-loading
   * was configured.
   * @param {number=} viewBoxSize Sets the width and height the icon's viewBox.
   * It is ignored for icons with an existing viewBox. Default size is 24.
   *
   * @returns {obj} an `$mdIconProvider` reference; used to support method call chains for the API
   *
   * @usage
   * <hljs lang="js">
   *   app.config(function($mdIconProvider) {
      *
      *     // Configure URLs for icons specified by [set:]id.
      *
      *     $mdIconProvider
      *          .icon('android', 'my/app/android.svg')    // Register a specific icon (by name)
      *          .icon('work:chair', 'my/app/chair.svg');  // Register icon in a specific set
      *   });
   * </hljs>
   *
   */
  /**
   * @ngdoc method
   * @name $mdIconProvider#iconSet
   *
   * @description
   * Register a source URL for a 'named' set of icons; group of SVG definitions where each definition
   * has an icon id. Individual icons can be subsequently retrieved from this cached set using
   * `$mdIcon(<icon set name>:<icon name>)`
   *
   * @param {string} id Icon name/id used to register the iconset
   * @param {string} url specifies the external location for the data file. Used internally by
   * `$templateRequest` to load the data or as part of the lookup in `$templateCache` if pre-loading
   * was configured.
   * @param {number=} viewBoxSize Sets the width and height of the viewBox of all icons in the set.
   * It is ignored for icons with an existing viewBox. All icons in the icon set should be the same size.
   * Default value is 24.
   *
   * @returns {obj} an `$mdIconProvider` reference; used to support method call chains for the API
   *
   *
   * @usage
   * <hljs lang="js">
   *   app.config(function($mdIconProvider) {
      *
      *     // Configure URLs for icons specified by [set:]id.
      *
      *     $mdIconProvider
      *          .iconSet('social', 'my/app/social.svg')   // Register a named icon set
      *   });
   * </hljs>
   *
   */
  /**
   * @ngdoc method
   * @name $mdIconProvider#defaultIconSet
   *
   * @description
   * Register a source URL for the default 'named' set of icons. Unless explicitly registered,
   * subsequent lookups of icons will failover to search this 'default' icon set.
   * Icon can be retrieved from this cached, default set using `$mdIcon(<name>)`
   *
   * @param {string} url specifies the external location for the data file. Used internally by
   * `$templateRequest` to load the data or as part of the lookup in `$templateCache` if pre-loading
   * was configured.
   * @param {number=} viewBoxSize Sets the width and height of the viewBox of all icons in the set.
   * It is ignored for icons with an existing viewBox. All icons in the icon set should be the same size.
   * Default value is 24.
   *
   * @returns {obj} an `$mdIconProvider` reference; used to support method call chains for the API
   *
   * @usage
   * <hljs lang="js">
   *   app.config(function($mdIconProvider) {
      *
      *     // Configure URLs for icons specified by [set:]id.
      *
      *     $mdIconProvider
      *          .defaultIconSet( 'my/app/social.svg' )   // Register a default icon set
      *   });
   * </hljs>
   *
   */
  /**
   * @ngdoc method
   * @name $mdIconProvider#defaultFontSet
   *
   * @description
   * When using Font-Icons, AngularJS Material assumes the the Material Design icons will be used and automatically
   * configures the default font-set == 'material-icons'. Note that the font-set references the font-icon library
   * class style that should be applied to the `<md-icon>`.
   *
   * Configuring the default means that the attributes
   * `md-font-set="material-icons"` or `class="material-icons"` do not need to be explicitly declared on the
   * `<md-icon>` markup. For example:
   *
   *  `<md-icon> face </md-icon>`
   *  will render as
   *  `<span class="material-icons"> face </span>`, and
   *
   *  `<md-icon md-font-set="fa"> face </md-icon>`
   *  will render as
   *  `<span class="fa"> face </span>`
   *
   * @param {string} name of the font-library style that should be applied to the md-icon DOM element
   *
   * @usage
   * <hljs lang="js">
   *   app.config(function($mdIconProvider) {
     *     $mdIconProvider.defaultFontSet( 'fa' );
     *   });
   * </hljs>
   *
   */
  
  /**
   * @ngdoc method
   * @name $mdIconProvider#fontSet
   *
   * @description
   * When using a font set for `<md-icon>` you must specify the correct font classname in the `md-font-set`
   * attribute. If the fonset className is really long, your markup may become cluttered... an easy
   * solution is to define an `alias` for your fontset:
   *
   * @param {string} alias of the specified fontset.
   * @param {string} className of the fontset.
   *
   * @usage
   * <hljs lang="js">
   *   app.config(function($mdIconProvider) {
     *     // In this case, we set an alias for the `material-icons` fontset.
     *     $mdIconProvider.fontSet('md', 'material-icons');
     *   });
   * </hljs>
   *
   */
  
  /**
   * @ngdoc method
   * @name $mdIconProvider#defaultViewBoxSize
   *
   * @description
   * While `<md-icon />` markup can also be style with sizing CSS, this method configures
   * the default width **and** height used for all icons; unless overridden by specific CSS.
   * The default sizing is (24px, 24px).
   * @param {number=} viewBoxSize Sets the width and height of the viewBox for an icon or an icon set.
   * All icons in a set should be the same size. The default value is 24.
   *
   * @returns {obj} an `$mdIconProvider` reference; used to support method call chains for the API
   *
   * @usage
   * <hljs lang="js">
   *   app.config(function($mdIconProvider) {
      *
      *     // Configure URLs for icons specified by [set:]id.
      *
      *     $mdIconProvider
      *          .defaultViewBoxSize(36)   // Register a default icon size (width == height)
      *   });
   * </hljs>
   *
   */
  
  var config = {
    defaultViewBoxSize: 24,
    defaultFontSet: 'material-icons',
    fontSets: []
  };
  
  function MdIconProvider() {
  }
  
  MdIconProvider.prototype = {
    icon: function(id, url, viewBoxSize) {
      if (id.indexOf(':') == -1) id = '$default:' + id;
  
      config[id] = new ConfigurationItem(url, viewBoxSize);
      return this;
    },
  
    iconSet: function(id, url, viewBoxSize) {
      config[id] = new ConfigurationItem(url, viewBoxSize);
      return this;
    },
  
    defaultIconSet: function(url, viewBoxSize) {
      var setName = '$default';
  
      if (!config[setName]) {
        config[setName] = new ConfigurationItem(url, viewBoxSize);
      }
  
      config[setName].viewBoxSize = viewBoxSize || config.defaultViewBoxSize;
  
      return this;
    },
  
    defaultViewBoxSize: function(viewBoxSize) {
      config.defaultViewBoxSize = viewBoxSize;
      return this;
    },
  
    /**
     * Register an alias name associated with a font-icon library style ;
     */
    fontSet: function fontSet(alias, className) {
      config.fontSets.push({
        alias: alias,
        fontSet: className || alias
      });
      return this;
    },
  
    /**
     * Specify a default style name associated with a font-icon library
     * fallback to Material Icons.
     *
     */
    defaultFontSet: function defaultFontSet(className) {
      config.defaultFontSet = !className ? '' : className;
      return this;
    },
  
    defaultIconSize: function defaultIconSize(iconSize) {
      config.defaultIconSize = iconSize;
      return this;
    },
  
    $get: ['$templateRequest', '$q', '$log', '$mdUtil', '$sce', function($templateRequest, $q, $log, $mdUtil, $sce) {
      return MdIconService(config, $templateRequest, $q, $log, $mdUtil, $sce);
    }]
  };
  
    /**
     * Configuration item stored in the Icon registry; used for lookups
     * to load if not already cached in the `loaded` cache
     * @param {string} url
     * @param {=number} viewBoxSize
     * @constructor
     */
    function ConfigurationItem(url, viewBoxSize) {
      this.url = url;
      this.viewBoxSize = viewBoxSize || config.defaultViewBoxSize;
    }
  
  /**
   * @ngdoc service
   * @name $mdIcon
   * @module material.components.icon
   *
   * @description
   * The `$mdIcon` service is a function used to lookup SVG icons.
   *
   * @param {string} id Query value for a unique Id or URL. If the argument is a URL, then the service will retrieve the icon element
   * from its internal cache or load the icon and cache it first. If the value is not a URL-type string, then an ID lookup is
   * performed. The Id may be a unique icon ID or may include an iconSet ID prefix.
   *
   * For the **id** query to work properly, this means that all id-to-URL mappings must have been previously configured
   * using the `$mdIconProvider`.
   *
   * @returns {angular.$q.Promise} A promise that gets resolved to a clone of the initial SVG DOM element; which was
   * created from the SVG markup in the SVG data file. If an error occurs (e.g. the icon cannot be found) the promise
   * will get rejected.
   *
   * @usage
   * <hljs lang="js">
   * function SomeDirective($mdIcon) {
    *
    *   // See if the icon has already been loaded, if not
    *   // then lookup the icon from the registry cache, load and cache
    *   // it for future requests.
    *   // NOTE: ID queries require configuration with $mdIconProvider
    *
    *   $mdIcon('android').then(function(iconEl)    { element.append(iconEl); });
    *   $mdIcon('work:chair').then(function(iconEl) { element.append(iconEl); });
    *
    *   // Load and cache the external SVG using a URL
    *
    *   $mdIcon('img/icons/android.svg').then(function(iconEl) {
    *     element.append(iconEl);
    *   });
    * };
   * </hljs>
   *
   * > <b>Note:</b> The `<md-icon>` directive internally uses the `$mdIcon` service to query, load,
   *   and instantiate SVG DOM elements.
   */
  
  /* ngInject */
  function MdIconService(config, $templateRequest, $q, $log, $mdUtil, $sce) {
    var iconCache = {};
    var svgCache = {};
    var urlRegex = /[-\w@:%+.~#?&//=]{2,}\.[a-z]{2,4}\b(\/[-\w@:%+.~#?&//=]*)?/i;
    var dataUrlRegex = /^data:image\/svg\+xml[\s*;\w\-=]*?(base64)?,(.*)$/i;
  
    Icon.prototype = {clone: cloneSVG, prepare: prepareAndStyle};
    getIcon.fontSet = findRegisteredFontSet;
  
    // Publish service...
    return getIcon;
  
    /**
     * Actual $mdIcon service is essentially a lookup function
     * @param {*} id $sce trust wrapper over a URL string, URL, icon registry id, or icon set id
     * @returns {angular.$q.Promise}
     */
    function getIcon(id) {
      id = id || '';
  
      // If the "id" provided is not a string, the only other valid value is a $sce trust wrapper
      // over a URL string. If the value is not trusted, this will intentionally throw an error
      // because the user is attempted to use an unsafe URL, potentially opening themselves up
      // to an XSS attack.
      if (!angular.isString(id)) {
        id = $sce.getTrustedUrl(id);
      }
  
      // If already loaded and cached, use a clone of the cached icon.
      // Otherwise either load by URL, or lookup in the registry and then load by URL, and cache.
  
      if (iconCache[id]) {
        return $q.when(transformClone(iconCache[id]));
      }
  
      if (urlRegex.test(id) || dataUrlRegex.test(id)) {
        return loadByURL(id).then(cacheIcon(id));
      }
  
      if (id.indexOf(':') === -1) {
        id = '$default:' + id;
      }
  
      var load = config[id] ? loadByID : loadFromIconSet;
      return load(id)
        .then(cacheIcon(id));
    }
  
    /**
     * Lookup a registered fontSet style using its alias.
     * @param {string} alias used to lookup the alias in the array of fontSets
     * @returns {*} matching fontSet or the defaultFontSet if that alias does not match
     */
    function findRegisteredFontSet(alias) {
      var useDefault = angular.isUndefined(alias) || !(alias && alias.length);
      if (useDefault) {
        return config.defaultFontSet;
      }
  
      var result = alias;
      angular.forEach(config.fontSets, function(fontSet) {
        if (fontSet.alias === alias) {
          result = fontSet.fontSet || result;
        }
      });
  
      return result;
    }
  
    /**
     * @param {!Icon} cacheElement cached icon from the iconCache
     * @returns {Icon} cloned Icon element with unique ids
     */
    function transformClone(cacheElement) {
      var clone = cacheElement.clone();
      var newUid = $mdUtil.nextUid();
      var cacheSuffix, svgUrlQuerySelector, i, xlinkHrefValue;
      // These are SVG attributes that can reference element ids.
      var svgUrlAttributes = [
        'clip-path', 'color-profile', 'cursor', 'fill', 'filter', 'href', 'marker-start',
        'marker-mid', 'marker-end', 'mask', 'stroke', 'style', 'vector-effect'
      ];
      var isIeSvg = clone.innerHTML === undefined;
  
      // Verify that the newUid only contains a number and not some XSS content.
      if (!isFinite(Number(newUid))) {
        throw new Error('Unsafe and unexpected non-number result from $mdUtil.nextUid().');
      }
      cacheSuffix = '_cache' + newUid;
  
      // For each cached icon, we need to modify the id attributes and references.
      // This is needed because SVG ids are treated as normal DOM ids and should not be duplicated on
      // the page.
      if (clone.id) {
        clone.id += cacheSuffix;
      }
  
      // Do as much as possible with querySelectorAll as it provides much greater performance
      // than RegEx against serialized DOM.
      angular.forEach(clone.querySelectorAll('[id]'), function(descendantElem) {
        svgUrlQuerySelector = '';
        for (i = 0; i < svgUrlAttributes.length; i++) {
          svgUrlQuerySelector += '[' + svgUrlAttributes[i] + '="url(#' + descendantElem.id + ')"]';
          if (i + 1 < svgUrlAttributes.length) {
            svgUrlQuerySelector += ', ';
          }
        }
        // Append the cacheSuffix to references of the element's id within url(#id) calls.
        angular.forEach(clone.querySelectorAll(svgUrlQuerySelector), function(refItem) {
          updateSvgIdReferences(descendantElem, refItem, isIeSvg, newUid);
        });
        // Handle usages of url(#id) in the SVG's stylesheets
        angular.forEach(clone.querySelectorAll('style'), function(refItem) {
          updateSvgIdReferences(descendantElem, refItem, isIeSvg, newUid);
        });
  
        // Update ids referenced by the deprecated (in SVG v2) xlink:href XML attribute. The now
        // preferred href attribute is handled above. However, this non-standard XML namespaced
        // attribute cannot be handled in the same way. Explanation of this query selector here:
        // https://stackoverflow.com/q/23034283/633107.
        angular.forEach(clone.querySelectorAll('[*|href]:not([href])'), function(refItem) {
          xlinkHrefValue = refItem.getAttribute('xlink:href');
          if (xlinkHrefValue) {
            xlinkHrefValue = xlinkHrefValue.replace("#" + descendantElem.id, "#" + descendantElem.id + cacheSuffix);
            refItem.setAttribute('xlink:href', xlinkHrefValue);
          }
        });
  
        descendantElem.id += cacheSuffix;
      });
  
      return clone;
    }
  
    /**
     * @param {Element} referencedElement element w/ id that needs to be updated
     * @param {Element} referencingElement element that references the original id
     * @param {boolean} isIeSvg true if we're dealing with an SVG in IE11, false otherwise
     * @param {string} newUid the cache id to add as part of the cache suffix
     */
    function updateSvgIdReferences(referencedElement, referencingElement, isIeSvg, newUid) {
      var svgElement, cacheSuffix;
  
      // Verify that the newUid only contains a number and not some XSS content.
      if (!isFinite(Number(newUid))) {
        throw new Error('Unsafe and unexpected non-number result for newUid.');
      }
      cacheSuffix = '_cache' + newUid;
  
      // outerHTML of SVG elements is not supported by IE11
      if (isIeSvg) {
        svgElement = $mdUtil.getOuterHTML(referencingElement);
        svgElement = svgElement.replace("url(#" + referencedElement.id + ")",
          "url(#" + referencedElement.id + cacheSuffix + ")");
        referencingElement.textContent = angular.element(svgElement)[0].innerHTML;
      } else {
        // This use of outerHTML should be safe from XSS attack since we are only injecting the
        // cacheSuffix with content from $mdUtil.nextUid which we verify is a finite number above.
        referencingElement.outerHTML = referencingElement.outerHTML.replace(
          "url(#" + referencedElement.id + ")",
          "url(#" + referencedElement.id + cacheSuffix + ")");
      }
    }
  
    /**
     * Prepare and cache the loaded icon for the specified `id`.
     * @param {string} id icon cache id
     * @returns {function(*=): *}
     */
    function cacheIcon(id) {
  
      return function updateCache(icon) {
        iconCache[id] = isIcon(icon) ? icon : new Icon(icon, config[id]);
  
        return transformClone(iconCache[id]);
      };
    }
  
    /**
     * Lookup the configuration in the registry, if !registered throw an error
     * otherwise load the icon [on-demand] using the registered URL.
     * @param {string} id icon registry id
     * @returns {angular.$q.Promise}
     */
    function loadByID(id) {
      var iconConfig = config[id];
      return loadByURL(iconConfig.url).then(function(icon) {
        return new Icon(icon, iconConfig);
      });
    }
  
    /**
     * Loads the file as XML and uses querySelector( <id> ) to find the desired node...
     * @param {string} id icon id in icon set
     * @returns {angular.$q.Promise}
     */
    function loadFromIconSet(id) {
      var setName = id.substring(0, id.lastIndexOf(':')) || '$default';
      var iconSetConfig = config[setName];
  
      return !iconSetConfig ? announceIdNotFound(id) : loadByURL(iconSetConfig.url).then(extractFromSet);
  
      function extractFromSet(set) {
        var iconName = id.slice(id.lastIndexOf(':') + 1);
        var icon = set.querySelector('#' + iconName);
        return icon ? new Icon(icon, iconSetConfig) : announceIdNotFound(id);
      }
  
      function announceIdNotFound(id) {
        var msg = 'icon ' + id + ' not found';
        $log.warn(msg);
  
        return $q.reject(msg || id);
      }
    }
  
    /**
     * Load the icon by URL (may use the $templateCache).
     * Extract the data for later conversion to Icon
     * @param {string} url icon URL
     * @returns {angular.$q.Promise}
     */
    function loadByURL(url) {
      /* Load the icon from embedded data URL. */
      function loadByDataUrl(url) {
        var results = dataUrlRegex.exec(url);
        var isBase64 = /base64/i.test(url);
        var data = isBase64 ? window.atob(results[2]) : results[2];
  
        return $q.when(angular.element(data)[0]);
      }
  
      /* Load the icon by URL using HTTP. */
      function loadByHttpUrl(url) {
        return $q(function(resolve, reject) {
          // Catch HTTP or generic errors not related to incorrect icon IDs.
          var announceAndReject = function(err) {
              var msg = angular.isString(err) ? err : (err.message || err.data || err.statusText);
              $log.warn(msg);
              reject(err);
            },
            extractSvg = function(response) {
              if (!svgCache[url]) {
                svgCache[url] = angular.element('<div>').append(response)[0].querySelector('svg');
              }
              resolve(svgCache[url]);
            };
  
          $templateRequest(url, true).then(extractSvg, announceAndReject);
        });
      }
  
      return dataUrlRegex.test(url)
        ? loadByDataUrl(url)
        : loadByHttpUrl(url);
    }
  
    /**
     * Check target signature to see if it is an Icon instance.
     * @param {Icon|Element} target
     * @returns {boolean} true if the specified target is an Icon object, false otherwise.
     */
    function isIcon(target) {
      return angular.isDefined(target.element) && angular.isDefined(target.config);
    }
  
    /**
     * Define the Icon class
     * @param {Element} el
     * @param {=ConfigurationItem} config
     * @constructor
     */
    function Icon(el, config) {
      // If the node is a <symbol>, it won't be rendered so we have to convert it into <svg>.
      if (el && el.tagName.toLowerCase() === 'symbol') {
        var viewbox = el.getAttribute('viewBox');
        // // Check if innerHTML is supported as IE11 does not support innerHTML on SVG elements.
        if (el.innerHTML) {
          el = angular.element('<svg xmlns="http://www.w3.org/2000/svg">')
            .html(el.innerHTML)[0];
        } else {
          el = angular.element('<svg xmlns="http://www.w3.org/2000/svg">')
            .append($mdUtil.getInnerHTML(el))[0];
        }
        if (viewbox) el.setAttribute('viewBox', viewbox);
      }
  
      if (el && el.tagName.toLowerCase() !== 'svg') {
        el = angular.element(
          '<svg xmlns="http://www.w3.org/2000/svg">').append(el.cloneNode(true))[0];
      }
  
      // Inject the namespace if not available...
      if (!el.getAttribute('xmlns')) {
        el.setAttribute('xmlns', "http://www.w3.org/2000/svg");
      }
  
      this.element = el;
      this.config = config;
      this.prepare();
    }
  
    /**
     *  Prepare the DOM element that will be cached in the
     *  loaded iconCache store.
     */
    function prepareAndStyle() {
      var viewBoxSize = this.config ? this.config.viewBoxSize : config.defaultViewBoxSize;
      angular.forEach({
        'fit': '',
        'height': '100%',
        'width': '100%',
        'preserveAspectRatio': 'xMidYMid meet',
        'viewBox': this.element.getAttribute('viewBox') || ('0 0 ' + viewBoxSize + ' ' + viewBoxSize),
        'focusable': false // Disable IE11s default behavior to make SVGs focusable
      }, function(val, attr) {
        this.element.setAttribute(attr, val);
      }, this);
    }
  
    /**
     * Clone the Icon DOM element.
     */
    function cloneSVG() {
      // If the element or any of its children have a style attribute, then a CSP policy without
      // 'unsafe-inline' in the style-src directive, will result in a violation.
      return this.element.cloneNode(true);
    }
  
  }
  
  })(window, window.angular);