arnaucube
arnaucube/socketioMEANseedPublic Self-hosted repository
socketioMEANseed/www/bower_components/angular-material/modules/closure/icon/icon.js
www/bower_components/angular-material/modules/closure/icon/icon.jsRaw
  1/*!
  2 * Angular Material Design
  3 * https://github.com/angular/material
  4 * @license MIT
  5 * v1.1.3
  6 */
  7goog.provide('ngmaterial.components.icon');
  8goog.require('ngmaterial.core');
  9/**
 10 * @ngdoc module
 11 * @name material.components.icon
 12 * @description
 13 * Icon
 14 */
 15angular.module('material.components.icon', ['material.core']);
 16
 17angular
 18  .module('material.components.icon')
 19  .directive('mdIcon', ['$mdIcon', '$mdTheming', '$mdAria', '$sce', mdIconDirective]);
 20
 21/**
 22 * @ngdoc directive
 23 * @name mdIcon
 24 * @module material.components.icon
 25 *
 26 * @restrict E
 27 *
 28 * @description
 29 * The `md-icon` directive makes it easier to use vector-based icons in your app (as opposed to
 30 * raster-based icons types like PNG). The directive supports both icon fonts and SVG icons.
 31 *
 32 * Icons should be considered view-only elements that should not be used directly as buttons; instead nest a `<md-icon>`
 33 * inside a `md-button` to add hover and click features.
 34 *
 35 * ### Icon fonts
 36 * Icon fonts are a technique in which you use a font where the glyphs in the font are
 37 * your icons instead of text. Benefits include a straightforward way to bundle everything into a
 38 * single HTTP request, simple scaling, easy color changing, and more.
 39 *
 40 * `md-icon` lets you consume an icon font by letting you reference specific icons in that font
 41 * by name rather than character code.
 42 *
 43 * ### SVG
 44 * For SVGs, the problem with using `<img>` or a CSS `background-image` is that you can't take
 45 * advantage of some SVG features, such as styling specific parts of the icon with CSS or SVG
 46 * animation.
 47 *
 48 * `md-icon` makes it easier to use SVG icons by *inlining* the SVG into an `<svg>` element in the
 49 * document. The most straightforward way of referencing an SVG icon is via URL, just like a
 50 * traditional `<img>`. `$mdIconProvider`, as a convenience, lets you _name_ an icon so you can
 51 * reference it by name instead of URL throughout your templates.
 52 *
 53 * Additionally, you may not want to make separate HTTP requests for every icon, so you can bundle
 54 * your SVG icons together and pre-load them with $mdIconProvider as an icon set. An icon set can
 55 * also be given a name, which acts as a namespace for individual icons, so you can reference them
 56 * like `"social:cake"`.
 57 *
 58 * When using SVGs, both external SVGs (via URLs) or sets of SVGs [from icon sets] can be
 59 * easily loaded and used. When using font-icons, developers must follow three (3) simple steps:
 60 *
 61 * <ol>
 62 * <li>Load the font library. e.g.<br/>
 63 *    `<link href="https://fonts.googleapis.com/icon?family=Material+Icons"
 64 *    rel="stylesheet">`
 65 * </li>
 66 * <li>
 67 *   Use either (a) font-icon class names or (b) a fontset and a font ligature to render the font glyph by
 68 *   using its textual name _or_ numerical character reference. Note that `material-icons` is the default fontset when
 69 *   none is specified.
 70 * </li>
 71 * <li> Use any of the following templates: <br/>
 72 *   <ul>
 73 *     <li>`<md-icon md-font-icon="classname"></md-icon>`</li>
 74 *     <li>`<md-icon md-font-set="font library classname or alias">textual_name</md-icon>`</li>
 75 *     <li>`<md-icon> numerical_character_reference </md-icon>`</li>
 76 *     <li>`<md-icon ng_bind="'textual_name'"></md-icon>`</li>
 77 *     <li>`<md-icon ng-bind="scopeVariable"></md-icon>`</li>
 78 *   </ul>
 79 * </li>
 80 * </ol>
 81 *
 82 * Full details for these steps can be found:
 83 *
 84 * <ul>
 85 * <li>http://google.github.io/material-design-icons/</li>
 86 * <li>http://google.github.io/material-design-icons/#icon-font-for-the-web</li>
 87 * </ul>
 88 *
 89 * The Material Design icon style <code>.material-icons</code> and the icon font references are published in
 90 * Material Design Icons:
 91 *
 92 * <ul>
 93 * <li>https://design.google.com/icons/</li>
 94 * <li>https://design.google.com/icons/#ic_accessibility</li>
 95 * </ul>
 96 *
 97 * ### Localization
 98 *
 99 * Because an `md-icon` element's text content is not intended to translated, it is recommended to declare the text
100 * content for an `md-icon` element in its start tag. Instead of using the HTML text content, consider using `ng-bind`
101 * with a scope variable or literal string.
102 *
103 * Examples:
104 *
105 * <ul>
106 *   <li>`<md-icon ng-bind="myIconVariable"></md-icon>`</li>
107 *   <li>`<md-icon ng-bind="'menu'"></md-icon>`
108 * </ul>
109 *
110 * <h2 id="material_design_icons">Material Design Icons</h2>
111 * Using the Material Design Icon-Selector, developers can easily and quickly search for a Material Design font-icon and
112 * determine its textual name and character reference code. Click on any icon to see the slide-up information
113 * panel with details regarding a SVG download or information on the font-icon usage.
114 *
115 * <a href="https://www.google.com/design/icons/#ic_accessibility" target="_blank" style="border-bottom:none;">
116 * <img src="https://cloud.githubusercontent.com/assets/210413/7902490/fe8dd14c-0780-11e5-98fb-c821cc6475e6.png"
117 *      aria-label="Material Design Icon-Selector" style="max-width:75%;padding-left:10%">
118 * </a>
119 *
120 * <span class="image_caption">
121 *  Click on the image above to link to the
122 *  <a href="https://design.google.com/icons/#ic_accessibility" target="_blank">Material Design Icon-Selector</a>.
123 * </span>
124 *
125 * @param {string} md-font-icon String name of CSS icon associated with the font-face will be used
126 * to render the icon. Requires the fonts and the named CSS styles to be preloaded.
127 * @param {string} md-font-set CSS style name associated with the font library; which will be assigned as
128 * the class for the font-icon ligature. This value may also be an alias that is used to lookup the classname;
129 * internally use `$mdIconProvider.fontSet(<alias>)` to determine the style name.
130 * @param {string} md-svg-src String URL (or expression) used to load, cache, and display an
131 *     external SVG.
132 * @param {string} md-svg-icon md-svg-icon String name used for lookup of the icon from the internal cache;
133 *     interpolated strings or expressions may also be used. Specific set names can be used with
134 *     the syntax `<set name>:<icon name>`.<br/><br/>
135 * To use icon sets, developers are required to pre-register the sets using the `$mdIconProvider` service.
136 * @param {string=} aria-label Labels icon for accessibility. If an empty string is provided, icon
137 * will be hidden from accessibility layer with `aria-hidden="true"`. If there's no aria-label on the icon
138 * nor a label on the parent element, a warning will be logged to the console.
139 * @param {string=} alt Labels icon for accessibility. If an empty string is provided, icon
140 * will be hidden from accessibility layer with `aria-hidden="true"`. If there's no alt on the icon
141 * nor a label on the parent element, a warning will be logged to the console.
142 *
143 * @usage
144 * When using SVGs:
145 * <hljs lang="html">
146 *
147 *  <!-- Icon ID; may contain optional icon set prefix; icons must registered using $mdIconProvider -->
148 *  <md-icon md-svg-icon="social:android"    aria-label="android " ></md-icon>
149 *
150 *  <!-- Icon urls; may be preloaded in templateCache -->
151 *  <md-icon md-svg-src="/android.svg"       aria-label="android " ></md-icon>
152 *  <md-icon md-svg-src="{{ getAndroid() }}" aria-label="android " ></md-icon>
153 *
154 * </hljs>
155 *
156 * Use the <code>$mdIconProvider</code> to configure your application with
157 * svg iconsets.
158 *
159 * <hljs lang="js">
160 *  angular.module('appSvgIconSets', ['ngMaterial'])
161 *    .controller('DemoCtrl', function($scope) {})
162 *    .config(function($mdIconProvider) {
163 *      $mdIconProvider
164 *         .iconSet('social', 'img/icons/sets/social-icons.svg', 24)
165 *         .defaultIconSet('img/icons/sets/core-icons.svg', 24);
166 *     });
167 * </hljs>
168 *
169 *
170 * When using Font Icons with classnames:
171 * <hljs lang="html">
172 *
173 *  <md-icon md-font-icon="android" aria-label="android" ></md-icon>
174 *  <md-icon class="icon_home"      aria-label="Home"    ></md-icon>
175 *
176 * </hljs>
177 *
178 * When using Material Font Icons with ligatures:
179 * <hljs lang="html">
180 *  <!--
181 *  For Material Design Icons
182 *  The class '.material-icons' is auto-added if a style has NOT been specified
183 *  since `material-icons` is the default fontset. So your markup:
184 *  -->
185 *  <md-icon> face </md-icon>
186 *  <!-- becomes this at runtime: -->
187 *  <md-icon md-font-set="material-icons"> face </md-icon>
188 *  <!-- If the fontset does not support ligature names, then we need to use the ligature unicode.-->
189 *  <md-icon> &#xE87C; </md-icon>
190 *  <!-- The class '.material-icons' must be manually added if other styles are also specified-->
191 *  <md-icon class="material-icons md-light md-48"> face </md-icon>
192 * </hljs>
193 *
194 * When using other Font-Icon libraries:
195 *
196 * <hljs lang="js">
197 *  // Specify a font-icon style alias
198 *  angular.config(function($mdIconProvider) {
199 *    $mdIconProvider.fontSet('md', 'material-icons');
200 *  });
201 * </hljs>
202 *
203 * <hljs lang="html">
204 *  <md-icon md-font-set="md">favorite</md-icon>
205 * </hljs>
206 *
207 */
208function mdIconDirective($mdIcon, $mdTheming, $mdAria, $sce) {
209
210  return {
211    restrict: 'E',
212    link : postLink
213  };
214
215
216  /**
217   * Directive postLink
218   * Supports embedded SVGs, font-icons, & external SVGs
219   */
220  function postLink(scope, element, attr) {
221    $mdTheming(element);
222    var lastFontIcon = attr.mdFontIcon;
223    var lastFontSet = $mdIcon.fontSet(attr.mdFontSet);
224
225    prepareForFontIcon();
226
227    attr.$observe('mdFontIcon', fontIconChanged);
228    attr.$observe('mdFontSet', fontIconChanged);
229
230    // Keep track of the content of the svg src so we can compare against it later to see if the
231    // attribute is static (and thus safe).
232    var originalSvgSrc = element[0].getAttribute(attr.$attr.mdSvgSrc);
233
234    // If using a font-icon, then the textual name of the icon itself
235    // provides the aria-label.
236
237    var label = attr.alt || attr.mdFontIcon || attr.mdSvgIcon || element.text();
238    var attrName = attr.$normalize(attr.$attr.mdSvgIcon || attr.$attr.mdSvgSrc || '');
239
240    if ( !attr['aria-label'] ) {
241
242      if (label !== '' && !parentsHaveText() ) {
243
244        $mdAria.expect(element, 'aria-label', label);
245        $mdAria.expect(element, 'role', 'img');
246
247      } else if ( !element.text() ) {
248        // If not a font-icon with ligature, then
249        // hide from the accessibility layer.
250
251        $mdAria.expect(element, 'aria-hidden', 'true');
252      }
253    }
254
255    if (attrName) {
256      // Use either pre-configured SVG or URL source, respectively.
257      attr.$observe(attrName, function(attrVal) {
258        element.empty();
259        if (attrVal) {
260          $mdIcon(attrVal)
261            .then(function(svg) {
262            element.empty();
263            element.append(svg);
264          });
265        }
266
267      });
268    }
269
270    function parentsHaveText() {
271      var parent = element.parent();
272      if (parent.attr('aria-label') || parent.text()) {
273        return true;
274      }
275      else if(parent.parent().attr('aria-label') || parent.parent().text()) {
276        return true;
277      }
278      return false;
279    }
280
281    function prepareForFontIcon() {
282      if (!attr.mdSvgIcon && !attr.mdSvgSrc) {
283        if (attr.mdFontIcon) {
284          element.addClass('md-font ' + attr.mdFontIcon);
285        }
286
287        element.addClass(lastFontSet);
288      }
289    }
290
291    function fontIconChanged() {
292      if (!attr.mdSvgIcon && !attr.mdSvgSrc) {
293        if (attr.mdFontIcon) {
294          element.removeClass(lastFontIcon);
295          element.addClass(attr.mdFontIcon);
296
297          lastFontIcon = attr.mdFontIcon;
298        }
299
300        var fontSet = $mdIcon.fontSet(attr.mdFontSet);
301
302        if (lastFontSet !== fontSet) {
303          element.removeClass(lastFontSet);
304          element.addClass(fontSet);
305
306          lastFontSet = fontSet;
307        }
308      }
309    }
310  }
311}
312
313  
314MdIconService['$inject'] = ["config", "$templateRequest", "$q", "$log", "$mdUtil", "$sce"];angular
315    .module('material.components.icon')
316    .constant('$$mdSvgRegistry', {
317        'mdTabsArrow':   'data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIHg9IjBweCIgeT0iMHB4IiB2aWV3Qm94PSIwIDAgMjQgMjQiPjxnPjxwb2x5Z29uIHBvaW50cz0iMTUuNCw3LjQgMTQsNiA4LDEyIDE0LDE4IDE1LjQsMTYuNiAxMC44LDEyICIvPjwvZz48L3N2Zz4=',
318        'mdClose':       'data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIHg9IjBweCIgeT0iMHB4IiB2aWV3Qm94PSIwIDAgMjQgMjQiPjxnPjxwYXRoIGQ9Ik0xOSA2LjQxbC0xLjQxLTEuNDEtNS41OSA1LjU5LTUuNTktNS41OS0xLjQxIDEuNDEgNS41OSA1LjU5LTUuNTkgNS41OSAxLjQxIDEuNDEgNS41OS01LjU5IDUuNTkgNS41OSAxLjQxLTEuNDEtNS41OS01LjU5eiIvPjwvZz48L3N2Zz4=',
319        'mdCancel':      'data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIHg9IjBweCIgeT0iMHB4IiB2aWV3Qm94PSIwIDAgMjQgMjQiPjxnPjxwYXRoIGQ9Ik0xMiAyYy01LjUzIDAtMTAgNC40Ny0xMCAxMHM0LjQ3IDEwIDEwIDEwIDEwLTQuNDcgMTAtMTAtNC40Ny0xMC0xMC0xMHptNSAxMy41OWwtMS40MSAxLjQxLTMuNTktMy41OS0zLjU5IDMuNTktMS40MS0xLjQxIDMuNTktMy41OS0zLjU5LTMuNTkgMS40MS0xLjQxIDMuNTkgMy41OSAzLjU5LTMuNTkgMS40MSAxLjQxLTMuNTkgMy41OSAzLjU5IDMuNTl6Ii8+PC9nPjwvc3ZnPg==',
320        'mdMenu':        'data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIHg9IjBweCIgeT0iMHB4IiB2aWV3Qm94PSIwIDAgMjQgMjQiPjxwYXRoIGQ9Ik0zLDZIMjFWOEgzVjZNMywxMUgyMVYxM0gzVjExTTMsMTZIMjFWMThIM1YxNloiIC8+PC9zdmc+',
321        'mdToggleArrow': 'data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIHg9IjBweCIgeT0iMHB4IiB2aWV3Qm94PSIwIDAgNDggNDgiPjxwYXRoIGQ9Ik0yNCAxNmwtMTIgMTIgMi44MyAyLjgzIDkuMTctOS4xNyA5LjE3IDkuMTcgMi44My0yLjgzeiIvPjxwYXRoIGQ9Ik0wIDBoNDh2NDhoLTQ4eiIgZmlsbD0ibm9uZSIvPjwvc3ZnPg==',
322        'mdCalendar':    'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij48cGF0aCBkPSJNMTkgM2gtMVYxaC0ydjJIOFYxSDZ2Mkg1Yy0xLjExIDAtMS45OS45LTEuOTkgMkwzIDE5YzAgMS4xLjg5IDIgMiAyaDE0YzEuMSAwIDItLjkgMi0yVjVjMC0xLjEtLjktMi0yLTJ6bTAgMTZINVY4aDE0djExek03IDEwaDV2NUg3eiIvPjwvc3ZnPg==',
323        'mdChecked':     'data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIHg9IjBweCIgeT0iMHB4IiB2aWV3Qm94PSIwIDAgMjQgMjQiPjxnPjxwYXRoIGQ9Ik05IDE2LjE3TDQuODMgMTJsLTEuNDIgMS40MUw5IDE5IDIxIDdsLTEuNDEtMS40MXoiLz48L2c+PC9zdmc+'
324    })
325    .provider('$mdIcon', MdIconProvider);
326
327/**
328 * @ngdoc service
329 * @name $mdIconProvider
330 * @module material.components.icon
331 *
332 * @description
333 * `$mdIconProvider` is used only to register icon IDs with URLs. These configuration features allow
334 * icons and icon sets to be pre-registered and associated with source URLs **before** the `<md-icon />`
335 * directives are compiled.
336 *
337 * If using font-icons, the developer is responsible for loading the fonts.
338 *
339 * If using SVGs, loading of the actual svg files are deferred to on-demand requests and are loaded
340 * internally by the `$mdIcon` service using the `$templateRequest` service. When an SVG is
341 * requested by name/ID, the `$mdIcon` service searches its registry for the associated source URL;
342 * that URL is used to on-demand load and parse the SVG dynamically.
343 *
344 * The `$templateRequest` service expects the icons source to be loaded over trusted URLs.<br/>
345 * This means, when loading icons from an external URL, you have to trust the URL in the `$sceDelegateProvider`.
346 *
347 * <hljs lang="js">
348 *   app.config(function($sceDelegateProvider) {
349 *     $sceDelegateProvider.resourceUrlWhitelist([
350 *       // Adding 'self' to the whitelist, will allow requests from the current origin.
351 *       'self',
352 *       // Using double asterisks here, will allow all URLs to load.
353 *       // We recommend to only specify the given domain you want to allow.
354 *       '**'
355 *     ]);
356 *   });
357 * </hljs>
358 *
359 * Read more about the [$sceDelegateProvider](https://docs.angularjs.org/api/ng/provider/$sceDelegateProvider).
360 *
361 * **Notice:** Most font-icons libraries do not support ligatures (for example `fontawesome`).<br/>
362 *  In such cases you are not able to use the icon's ligature name - Like so:
363 *
364 *  <hljs lang="html">
365 *    <md-icon md-font-set="fa">fa-bell</md-icon>
366 *  </hljs>
367 *
368 * You should instead use the given unicode, instead of the ligature name.
369 *
370 * <p ng-hide="true"> ##// Notice we can't use a hljs element here, because the characters will be escaped.</p>
371 *  ```html
372 *    <md-icon md-font-set="fa">&#xf0f3</md-icon>
373 *  ```
374 *
375 * All unicode ligatures are prefixed with the `&#x` string.
376 *
377 * @usage
378 * <hljs lang="js">
379 *   app.config(function($mdIconProvider) {
380    *
381    *     // Configure URLs for icons specified by [set:]id.
382    *
383    *     $mdIconProvider
384    *          .defaultFontSet( 'fa' )                   // This sets our default fontset className.
385    *          .defaultIconSet('my/app/icons.svg')       // Register a default set of SVG icons
386    *          .iconSet('social', 'my/app/social.svg')   // Register a named icon set of SVGs
387    *          .icon('android', 'my/app/android.svg')    // Register a specific icon (by name)
388    *          .icon('work:chair', 'my/app/chair.svg');  // Register icon in a specific set
389    *   });
390 * </hljs>
391 *
392 * SVG icons and icon sets can be easily pre-loaded and cached using either (a) a build process or (b) a runtime
393 * **startup** process (shown below):
394 *
395 * <hljs lang="js">
396 *   app.config(function($mdIconProvider) {
397    *
398    *     // Register a default set of SVG icon definitions
399    *     $mdIconProvider.defaultIconSet('my/app/icons.svg')
400    *
401    *   })
402 *   .run(function($templateRequest){
403    *
404    *     // Pre-fetch icons sources by URL and cache in the $templateCache...
405    *     // subsequent $templateRequest calls will look there first.
406    *
407    *     var urls = [ 'imy/app/icons.svg', 'img/icons/android.svg'];
408    *
409    *     angular.forEach(urls, function(url) {
410    *       $templateRequest(url);
411    *     });
412    *
413    *   });
414 *
415 * </hljs>
416 *
417 * > <b>Note:</b> The loaded SVG data is subsequently cached internally for future requests.
418 *
419 */
420
421/**
422 * @ngdoc method
423 * @name $mdIconProvider#icon
424 *
425 * @description
426 * Register a source URL for a specific icon name; the name may include optional 'icon set' name prefix.
427 * These icons  will later be retrieved from the cache using `$mdIcon( <icon name> )`
428 *
429 * @param {string} id Icon name/id used to register the icon
430 * @param {string} url specifies the external location for the data file. Used internally by
431 * `$templateRequest` to load the data or as part of the lookup in `$templateCache` if pre-loading
432 * was configured.
433 * @param {number=} viewBoxSize Sets the width and height the icon's viewBox.
434 * It is ignored for icons with an existing viewBox. Default size is 24.
435 *
436 * @returns {obj} an `$mdIconProvider` reference; used to support method call chains for the API
437 *
438 * @usage
439 * <hljs lang="js">
440 *   app.config(function($mdIconProvider) {
441    *
442    *     // Configure URLs for icons specified by [set:]id.
443    *
444    *     $mdIconProvider
445    *          .icon('android', 'my/app/android.svg')    // Register a specific icon (by name)
446    *          .icon('work:chair', 'my/app/chair.svg');  // Register icon in a specific set
447    *   });
448 * </hljs>
449 *
450 */
451/**
452 * @ngdoc method
453 * @name $mdIconProvider#iconSet
454 *
455 * @description
456 * Register a source URL for a 'named' set of icons; group of SVG definitions where each definition
457 * has an icon id. Individual icons can be subsequently retrieved from this cached set using
458 * `$mdIcon(<icon set name>:<icon name>)`
459 *
460 * @param {string} id Icon name/id used to register the iconset
461 * @param {string} url specifies the external location for the data file. Used internally by
462 * `$templateRequest` to load the data or as part of the lookup in `$templateCache` if pre-loading
463 * was configured.
464 * @param {number=} viewBoxSize Sets the width and height of the viewBox of all icons in the set.
465 * It is ignored for icons with an existing viewBox. All icons in the icon set should be the same size.
466 * Default value is 24.
467 *
468 * @returns {obj} an `$mdIconProvider` reference; used to support method call chains for the API
469 *
470 *
471 * @usage
472 * <hljs lang="js">
473 *   app.config(function($mdIconProvider) {
474    *
475    *     // Configure URLs for icons specified by [set:]id.
476    *
477    *     $mdIconProvider
478    *          .iconSet('social', 'my/app/social.svg')   // Register a named icon set
479    *   });
480 * </hljs>
481 *
482 */
483/**
484 * @ngdoc method
485 * @name $mdIconProvider#defaultIconSet
486 *
487 * @description
488 * Register a source URL for the default 'named' set of icons. Unless explicitly registered,
489 * subsequent lookups of icons will failover to search this 'default' icon set.
490 * Icon can be retrieved from this cached, default set using `$mdIcon(<name>)`
491 *
492 * @param {string} url specifies the external location for the data file. Used internally by
493 * `$templateRequest` to load the data or as part of the lookup in `$templateCache` if pre-loading
494 * was configured.
495 * @param {number=} viewBoxSize Sets the width and height of the viewBox of all icons in the set.
496 * It is ignored for icons with an existing viewBox. All icons in the icon set should be the same size.
497 * Default value is 24.
498 *
499 * @returns {obj} an `$mdIconProvider` reference; used to support method call chains for the API
500 *
501 * @usage
502 * <hljs lang="js">
503 *   app.config(function($mdIconProvider) {
504    *
505    *     // Configure URLs for icons specified by [set:]id.
506    *
507    *     $mdIconProvider
508    *          .defaultIconSet( 'my/app/social.svg' )   // Register a default icon set
509    *   });
510 * </hljs>
511 *
512 */
513/**
514 * @ngdoc method
515 * @name $mdIconProvider#defaultFontSet
516 *
517 * @description
518 * When using Font-Icons, Angular Material assumes the the Material Design icons will be used and automatically
519 * configures the default font-set == 'material-icons'. Note that the font-set references the font-icon library
520 * class style that should be applied to the `<md-icon>`.
521 *
522 * Configuring the default means that the attributes
523 * `md-font-set="material-icons"` or `class="material-icons"` do not need to be explicitly declared on the
524 * `<md-icon>` markup. For example:
525 *
526 *  `<md-icon> face </md-icon>`
527 *  will render as
528 *  `<span class="material-icons"> face </span>`, and
529 *
530 *  `<md-icon md-font-set="fa"> face </md-icon>`
531 *  will render as
532 *  `<span class="fa"> face </span>`
533 *
534 * @param {string} name of the font-library style that should be applied to the md-icon DOM element
535 *
536 * @usage
537 * <hljs lang="js">
538 *   app.config(function($mdIconProvider) {
539   *     $mdIconProvider.defaultFontSet( 'fa' );
540   *   });
541 * </hljs>
542 *
543 */
544
545/**
546 * @ngdoc method
547 * @name $mdIconProvider#fontSet
548 *
549 * @description
550 * When using a font set for `<md-icon>` you must specify the correct font classname in the `md-font-set`
551 * attribute. If the fonset className is really long, your markup may become cluttered... an easy
552 * solution is to define an `alias` for your fontset:
553 *
554 * @param {string} alias of the specified fontset.
555 * @param {string} className of the fontset.
556 *
557 * @usage
558 * <hljs lang="js">
559 *   app.config(function($mdIconProvider) {
560   *     // In this case, we set an alias for the `material-icons` fontset.
561   *     $mdIconProvider.fontSet('md', 'material-icons');
562   *   });
563 * </hljs>
564 *
565 */
566
567/**
568 * @ngdoc method
569 * @name $mdIconProvider#defaultViewBoxSize
570 *
571 * @description
572 * While `<md-icon />` markup can also be style with sizing CSS, this method configures
573 * the default width **and** height used for all icons; unless overridden by specific CSS.
574 * The default sizing is (24px, 24px).
575 * @param {number=} viewBoxSize Sets the width and height of the viewBox for an icon or an icon set.
576 * All icons in a set should be the same size. The default value is 24.
577 *
578 * @returns {obj} an `$mdIconProvider` reference; used to support method call chains for the API
579 *
580 * @usage
581 * <hljs lang="js">
582 *   app.config(function($mdIconProvider) {
583    *
584    *     // Configure URLs for icons specified by [set:]id.
585    *
586    *     $mdIconProvider
587    *          .defaultViewBoxSize(36)   // Register a default icon size (width == height)
588    *   });
589 * </hljs>
590 *
591 */
592
593var config = {
594  defaultViewBoxSize: 24,
595  defaultFontSet: 'material-icons',
596  fontSets: []
597};
598
599function MdIconProvider() {
600}
601
602MdIconProvider.prototype = {
603  icon: function(id, url, viewBoxSize) {
604    if (id.indexOf(':') == -1) id = '$default:' + id;
605
606    config[id] = new ConfigurationItem(url, viewBoxSize);
607    return this;
608  },
609
610  iconSet: function(id, url, viewBoxSize) {
611    config[id] = new ConfigurationItem(url, viewBoxSize);
612    return this;
613  },
614
615  defaultIconSet: function(url, viewBoxSize) {
616    var setName = '$default';
617
618    if (!config[setName]) {
619      config[setName] = new ConfigurationItem(url, viewBoxSize);
620    }
621
622    config[setName].viewBoxSize = viewBoxSize || config.defaultViewBoxSize;
623
624    return this;
625  },
626
627  defaultViewBoxSize: function(viewBoxSize) {
628    config.defaultViewBoxSize = viewBoxSize;
629    return this;
630  },
631
632  /**
633   * Register an alias name associated with a font-icon library style ;
634   */
635  fontSet: function fontSet(alias, className) {
636    config.fontSets.push({
637      alias: alias,
638      fontSet: className || alias
639    });
640    return this;
641  },
642
643  /**
644   * Specify a default style name associated with a font-icon library
645   * fallback to Material Icons.
646   *
647   */
648  defaultFontSet: function defaultFontSet(className) {
649    config.defaultFontSet = !className ? '' : className;
650    return this;
651  },
652
653  defaultIconSize: function defaultIconSize(iconSize) {
654    config.defaultIconSize = iconSize;
655    return this;
656  },
657
658  $get: ['$templateRequest', '$q', '$log', '$mdUtil', '$sce', function($templateRequest, $q, $log, $mdUtil, $sce) {
659    return MdIconService(config, $templateRequest, $q, $log, $mdUtil, $sce);
660  }]
661};
662
663/**
664 *  Configuration item stored in the Icon registry; used for lookups
665 *  to load if not already cached in the `loaded` cache
666 */
667function ConfigurationItem(url, viewBoxSize) {
668  this.url = url;
669  this.viewBoxSize = viewBoxSize || config.defaultViewBoxSize;
670}
671
672/**
673 * @ngdoc service
674 * @name $mdIcon
675 * @module material.components.icon
676 *
677 * @description
678 * The `$mdIcon` service is a function used to lookup SVG icons.
679 *
680 * @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
681 * 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
682 * performed. The Id may be a unique icon ID or may include an iconSet ID prefix.
683 *
684 * For the **id** query to work properly, this means that all id-to-URL mappings must have been previously configured
685 * using the `$mdIconProvider`.
686 *
687 * @returns {angular.$q.Promise} A promise that gets resolved to a clone of the initial SVG DOM element; which was
688 * created from the SVG markup in the SVG data file. If an error occurs (e.g. the icon cannot be found) the promise
689 * will get rejected.
690 *
691 * @usage
692 * <hljs lang="js">
693 * function SomeDirective($mdIcon) {
694  *
695  *   // See if the icon has already been loaded, if not
696  *   // then lookup the icon from the registry cache, load and cache
697  *   // it for future requests.
698  *   // NOTE: ID queries require configuration with $mdIconProvider
699  *
700  *   $mdIcon('android').then(function(iconEl)    { element.append(iconEl); });
701  *   $mdIcon('work:chair').then(function(iconEl) { element.append(iconEl); });
702  *
703  *   // Load and cache the external SVG using a URL
704  *
705  *   $mdIcon('img/icons/android.svg').then(function(iconEl) {
706  *     element.append(iconEl);
707  *   });
708  * };
709 * </hljs>
710 *
711 * > <b>Note:</b> The `<md-icon>` directive internally uses the `$mdIcon` service to query, loaded,
712 *   and instantiate SVG DOM elements.
713 */
714
715/* ngInject */
716function MdIconService(config, $templateRequest, $q, $log, $mdUtil, $sce) {
717  var iconCache = {};
718  var svgCache = {};
719  var urlRegex = /[-\w@:%\+.~#?&//=]{2,}\.[a-z]{2,4}\b(\/[-\w@:%\+.~#?&//=]*)?/i;
720  var dataUrlRegex = /^data:image\/svg\+xml[\s*;\w\-\=]*?(base64)?,(.*)$/i;
721
722  Icon.prototype = {clone: cloneSVG, prepare: prepareAndStyle};
723  getIcon.fontSet = findRegisteredFontSet;
724
725  // Publish service...
726  return getIcon;
727
728  /**
729   * Actual $mdIcon service is essentially a lookup function
730   */
731  function getIcon(id) {
732    id = id || '';
733
734    // If the "id" provided is not a string, the only other valid value is a $sce trust wrapper
735    // over a URL string. If the value is not trusted, this will intentionally throw an error
736    // because the user is attempted to use an unsafe URL, potentially opening themselves up
737    // to an XSS attack.
738    if (!angular.isString(id)) {
739      id = $sce.getTrustedUrl(id);
740    }
741
742    // If already loaded and cached, use a clone of the cached icon.
743    // Otherwise either load by URL, or lookup in the registry and then load by URL, and cache.
744
745    if (iconCache[id]) {
746      return $q.when(transformClone(iconCache[id]));
747    }
748
749    if (urlRegex.test(id) || dataUrlRegex.test(id)) {
750      return loadByURL(id).then(cacheIcon(id));
751    }
752
753    if (id.indexOf(':') == -1) {
754      id = '$default:' + id;
755    }
756
757    var load = config[id] ? loadByID : loadFromIconSet;
758    return load(id)
759      .then(cacheIcon(id));
760  }
761
762  /**
763   * Lookup registered fontSet style using its alias...
764   * If not found,
765   */
766  function findRegisteredFontSet(alias) {
767    var useDefault = angular.isUndefined(alias) || !(alias && alias.length);
768    if (useDefault) return config.defaultFontSet;
769
770    var result = alias;
771    angular.forEach(config.fontSets, function(it) {
772      if (it.alias == alias) result = it.fontSet || result;
773    });
774
775    return result;
776  }
777
778  function transformClone(cacheElement) {
779    var clone = cacheElement.clone();
780    var cacheSuffix = '_cache' + $mdUtil.nextUid();
781
782    // We need to modify for each cached icon the id attributes.
783    // This is needed because SVG id's are treated as normal DOM ids
784    // and should not have a duplicated id.
785    if (clone.id) clone.id += cacheSuffix;
786    angular.forEach(clone.querySelectorAll('[id]'), function(item) {
787      item.id += cacheSuffix;
788    });
789
790    return clone;
791  }
792
793  /**
794   * Prepare and cache the loaded icon for the specified `id`
795   */
796  function cacheIcon(id) {
797
798    return function updateCache(icon) {
799      iconCache[id] = isIcon(icon) ? icon : new Icon(icon, config[id]);
800
801      return iconCache[id].clone();
802    };
803  }
804
805  /**
806   * Lookup the configuration in the registry, if !registered throw an error
807   * otherwise load the icon [on-demand] using the registered URL.
808   *
809   */
810  function loadByID(id) {
811    var iconConfig = config[id];
812    return loadByURL(iconConfig.url).then(function(icon) {
813      return new Icon(icon, iconConfig);
814    });
815  }
816
817  /**
818   *    Loads the file as XML and uses querySelector( <id> ) to find
819   *    the desired node...
820   */
821  function loadFromIconSet(id) {
822    var setName = id.substring(0, id.lastIndexOf(':')) || '$default';
823    var iconSetConfig = config[setName];
824
825    return !iconSetConfig ? announceIdNotFound(id) : loadByURL(iconSetConfig.url).then(extractFromSet);
826
827    function extractFromSet(set) {
828      var iconName = id.slice(id.lastIndexOf(':') + 1);
829      var icon = set.querySelector('#' + iconName);
830      return icon ? new Icon(icon, iconSetConfig) : announceIdNotFound(id);
831    }
832
833    function announceIdNotFound(id) {
834      var msg = 'icon ' + id + ' not found';
835      $log.warn(msg);
836
837      return $q.reject(msg || id);
838    }
839  }
840
841  /**
842   * Load the icon by URL (may use the $templateCache).
843   * Extract the data for later conversion to Icon
844   */
845  function loadByURL(url) {
846    /* Load the icon from embedded data URL. */
847    function loadByDataUrl(url) {
848      var results = dataUrlRegex.exec(url);
849      var isBase64 = /base64/i.test(url);
850      var data = isBase64 ? window.atob(results[2]) : results[2];
851
852      return $q.when(angular.element(data)[0]);
853    }
854
855    /* Load the icon by URL using HTTP. */
856    function loadByHttpUrl(url) {
857      return $q(function(resolve, reject) {
858        // Catch HTTP or generic errors not related to incorrect icon IDs.
859        var announceAndReject = function(err) {
860            var msg = angular.isString(err) ? err : (err.message || err.data || err.statusText);
861            $log.warn(msg);
862            reject(err);
863          },
864          extractSvg = function(response) {
865            if (!svgCache[url]) {
866              svgCache[url] = angular.element('<div>').append(response)[0].querySelector('svg');
867            }
868            resolve(svgCache[url]);
869          };
870
871        $templateRequest(url, true).then(extractSvg, announceAndReject);
872      });
873    }
874
875    return dataUrlRegex.test(url)
876      ? loadByDataUrl(url)
877      : loadByHttpUrl(url);
878  }
879
880  /**
881   * Check target signature to see if it is an Icon instance.
882   */
883  function isIcon(target) {
884    return angular.isDefined(target.element) && angular.isDefined(target.config);
885  }
886
887  /**
888   *  Define the Icon class
889   */
890  function Icon(el, config) {
891    if (el && el.tagName != 'svg') {
892      el = angular.element('<svg xmlns="http://www.w3.org/2000/svg">').append(el.cloneNode(true))[0];
893    }
894
895    // Inject the namespace if not available...
896    if (!el.getAttribute('xmlns')) {
897      el.setAttribute('xmlns', "http://www.w3.org/2000/svg");
898    }
899
900    this.element = el;
901    this.config = config;
902    this.prepare();
903  }
904
905  /**
906   *  Prepare the DOM element that will be cached in the
907   *  loaded iconCache store.
908   */
909  function prepareAndStyle() {
910    var viewBoxSize = this.config ? this.config.viewBoxSize : config.defaultViewBoxSize;
911    angular.forEach({
912      'fit': '',
913      'height': '100%',
914      'width': '100%',
915      'preserveAspectRatio': 'xMidYMid meet',
916      'viewBox': this.element.getAttribute('viewBox') || ('0 0 ' + viewBoxSize + ' ' + viewBoxSize),
917      'focusable': false // Disable IE11s default behavior to make SVGs focusable
918    }, function(val, attr) {
919      this.element.setAttribute(attr, val);
920    }, this);
921  }
922
923  /**
924   * Clone the Icon DOM element.
925   */
926  function cloneSVG() {
927    // If the element or any of its children have a style attribute, then a CSP policy without
928    // 'unsafe-inline' in the style-src directive, will result in a violation.
929    return this.element.cloneNode(true);
930  }
931
932}
933
934ngmaterial.components.icon = angular.module("material.components.icon");