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>  </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"></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");