icon.js 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812
  1. /*!
  2. * Angular Material Design
  3. * https://github.com/angular/material
  4. * @license MIT
  5. * v0.11.4
  6. */
  7. (function( window, angular, undefined ){
  8. "use strict";
  9. /**
  10. * @ngdoc module
  11. * @name material.components.icon
  12. * @description
  13. * Icon
  14. */
  15. angular.module('material.components.icon', [
  16. 'material.core'
  17. ]);
  18. angular
  19. .module('material.components.icon')
  20. .directive('mdIcon', ['$mdIcon', '$mdTheming', '$mdAria', mdIconDirective]);
  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 consider 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` let's 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, let's 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 use font-icons, developers must following three (3) simple steps:
  60. *
  61. * <ol>
  62. * <li>Load the font library. e.g.<br/>
  63. * &lt;link href="https://fonts.googleapis.com/icon?family=Material+Icons"
  64. * rel="stylesheet"&gt;
  65. * </li>
  66. * <li> Use either (a) font-icon class names or (b) font ligatures to render the font glyph by using its textual name</li>
  67. * <li> Use &lt;md-icon md-font-icon="classname" /&gt; or <br/>
  68. * use &lt;md-icon md-font-set="font library classname or alias"&gt; textual_name &lt;/md-icon&gt; or <br/>
  69. * use &lt;md-icon md-font-set="font library classname or alias"&gt; numerical_character_reference &lt;/md-icon&gt;
  70. * </li>
  71. * </ol>
  72. *
  73. * Full details for these steps can be found:
  74. *
  75. * <ul>
  76. * <li>http://google.github.io/material-design-icons/</li>
  77. * <li>http://google.github.io/material-design-icons/#icon-font-for-the-web</li>
  78. * </ul>
  79. *
  80. * The Material Design icon style <code>.material-icons</code> and the icon font references are published in
  81. * Material Design Icons:
  82. *
  83. * <ul>
  84. * <li>http://www.google.com/design/icons/</li>
  85. * <li>https://www.google.com/design/icons/#ic_accessibility</li>
  86. * </ul>
  87. *
  88. * <h2 id="material_design_icons">Material Design Icons</h2>
  89. * Using the Material Design Icon-Selector, developers can easily and quickly search for a Material Design font-icon and
  90. * determine its textual name and character reference code. Click on any icon to see the slide-up information
  91. * panel with details regarding a SVG download or information on the font-icon usage.
  92. *
  93. * <a href="https://www.google.com/design/icons/#ic_accessibility" target="_blank" style="border-bottom:none;">
  94. * <img src="https://cloud.githubusercontent.com/assets/210413/7902490/fe8dd14c-0780-11e5-98fb-c821cc6475e6.png"
  95. * aria-label="Material Design Icon-Selector" style="max-width:75%;padding-left:10%">
  96. * </a>
  97. *
  98. * <span class="image_caption">
  99. * Click on the image above to link to the
  100. * <a href="https://www.google.com/design/icons/#ic_accessibility" target="_blank">Material Design Icon-Selector</a>.
  101. * </span>
  102. *
  103. * @param {string} md-font-icon String name of CSS icon associated with the font-face will be used
  104. * to render the icon. Requires the fonts and the named CSS styles to be preloaded.
  105. * @param {string} md-font-set CSS style name associated with the font library; which will be assigned as
  106. * the class for the font-icon ligature. This value may also be an alias that is used to lookup the classname;
  107. * internally use `$mdIconProvider.fontSet(<alias>)` to determine the style name.
  108. * @param {string} md-svg-src String URL (or expression) used to load, cache, and display an
  109. * external SVG.
  110. * @param {string} md-svg-icon md-svg-icon String name used for lookup of the icon from the internal cache;
  111. * interpolated strings or expressions may also be used. Specific set names can be used with
  112. * the syntax `<set name>:<icon name>`.<br/><br/>
  113. * To use icon sets, developers are required to pre-register the sets using the `$mdIconProvider` service.
  114. * @param {string=} aria-label Labels icon for accessibility. If an empty string is provided, icon
  115. * will be hidden from accessibility layer with `aria-hidden="true"`. If there's no aria-label on the icon
  116. * nor a label on the parent element, a warning will be logged to the console.
  117. * @param {string=} alt Labels icon for accessibility. If an empty string is provided, icon
  118. * will be hidden from accessibility layer with `aria-hidden="true"`. If there's no alt on the icon
  119. * nor a label on the parent element, a warning will be logged to the console.
  120. *
  121. * @usage
  122. * When using SVGs:
  123. * <hljs lang="html">
  124. *
  125. * <!-- Icon ID; may contain optional icon set prefix; icons must registered using $mdIconProvider -->
  126. * <md-icon md-svg-icon="social:android" aria-label="android " ></md-icon>
  127. *
  128. * <!-- Icon urls; may be preloaded in templateCache -->
  129. * <md-icon md-svg-src="/android.svg" aria-label="android " ></md-icon>
  130. * <md-icon md-svg-src="{{ getAndroid() }}" aria-label="android " ></md-icon>
  131. *
  132. * </hljs>
  133. *
  134. * Use the <code>$mdIconProvider</code> to configure your application with
  135. * svg iconsets.
  136. *
  137. * <hljs lang="js">
  138. * angular.module('appSvgIconSets', ['ngMaterial'])
  139. * .controller('DemoCtrl', function($scope) {})
  140. * .config(function($mdIconProvider) {
  141. * $mdIconProvider
  142. * .iconSet('social', 'img/icons/sets/social-icons.svg', 24)
  143. * .defaultIconSet('img/icons/sets/core-icons.svg', 24);
  144. * });
  145. * </hljs>
  146. *
  147. *
  148. * When using Font Icons with classnames:
  149. * <hljs lang="html">
  150. *
  151. * <md-icon md-font-icon="android" aria-label="android" ></md-icon>
  152. * <md-icon class="icon_home" aria-label="Home" ></md-icon>
  153. *
  154. * </hljs>
  155. *
  156. * When using Material Font Icons with ligatures:
  157. * <hljs lang="html">
  158. * <!-- For Material Design Icons -->
  159. * <!-- The class '.material-icons' is auto-added if a style has NOT been specified -->
  160. * <md-icon> face </md-icon>
  161. * <md-icon md-font-set="material-icons"> face </md-icon>
  162. * <md-icon> #xE87C; </md-icon>
  163. * <!-- The class '.material-icons' must be manually added if other styles are also specified-->
  164. * <md-icon class="material-icons md-light md-48"> face </md-icon>
  165. * </hljs>
  166. *
  167. * When using other Font-Icon libraries:
  168. *
  169. * <hljs lang="js">
  170. * // Specify a font-icon style alias
  171. * angular.config(function($mdIconProvider) {
  172. * $mdIconProvider.fontSet('fa', 'fontawesome');
  173. * });
  174. * </hljs>
  175. *
  176. * <hljs lang="html">
  177. * <md-icon md-font-set="fa">email</md-icon>
  178. * </hljs>
  179. *
  180. */
  181. function mdIconDirective($mdIcon, $mdTheming, $mdAria ) {
  182. return {
  183. scope: {
  184. fontSet : '@mdFontSet',
  185. fontIcon: '@mdFontIcon',
  186. svgIcon : '@mdSvgIcon',
  187. svgSrc : '@mdSvgSrc'
  188. },
  189. restrict: 'E',
  190. link : postLink
  191. };
  192. /**
  193. * Directive postLink
  194. * Supports embedded SVGs, font-icons, & external SVGs
  195. */
  196. function postLink(scope, element, attr) {
  197. $mdTheming(element);
  198. prepareForFontIcon();
  199. // If using a font-icon, then the textual name of the icon itself
  200. // provides the aria-label.
  201. var label = attr.alt || scope.fontIcon || scope.svgIcon || element.text();
  202. var attrName = attr.$normalize(attr.$attr.mdSvgIcon || attr.$attr.mdSvgSrc || '');
  203. if ( !attr['aria-label'] ) {
  204. if (label != '' && !parentsHaveText() ) {
  205. $mdAria.expect(element, 'aria-label', label);
  206. $mdAria.expect(element, 'role', 'img');
  207. } else if ( !element.text() ) {
  208. // If not a font-icon with ligature, then
  209. // hide from the accessibility layer.
  210. $mdAria.expect(element, 'aria-hidden', 'true');
  211. }
  212. }
  213. if (attrName) {
  214. // Use either pre-configured SVG or URL source, respectively.
  215. attr.$observe(attrName, function(attrVal) {
  216. element.empty();
  217. if (attrVal) {
  218. $mdIcon(attrVal).then(function(svg) {
  219. element.append(svg);
  220. });
  221. }
  222. });
  223. }
  224. function parentsHaveText() {
  225. var parent = element.parent();
  226. if (parent.attr('aria-label') || parent.text()) {
  227. return true;
  228. }
  229. else if(parent.parent().attr('aria-label') || parent.parent().text()) {
  230. return true;
  231. }
  232. return false;
  233. }
  234. function prepareForFontIcon() {
  235. if (!scope.svgIcon && !scope.svgSrc) {
  236. if (scope.fontIcon) {
  237. element.addClass('md-font ' + scope.fontIcon);
  238. }
  239. element.addClass($mdIcon.fontSet(scope.fontSet));
  240. }
  241. }
  242. }
  243. }
  244. angular
  245. .module('material.components.icon' )
  246. .provider('$mdIcon', MdIconProvider);
  247. /**
  248. * @ngdoc service
  249. * @name $mdIconProvider
  250. * @module material.components.icon
  251. *
  252. * @description
  253. * `$mdIconProvider` is used only to register icon IDs with URLs. These configuration features allow
  254. * icons and icon sets to be pre-registered and associated with source URLs **before** the `<md-icon />`
  255. * directives are compiled.
  256. *
  257. * If using font-icons, the developer is responsible for loading the fonts.
  258. *
  259. * If using SVGs, loading of the actual svg files are deferred to on-demand requests and are loaded
  260. * internally by the `$mdIcon` service using the `$http` service. When an SVG is requested by name/ID,
  261. * the `$mdIcon` service searches its registry for the associated source URL;
  262. * that URL is used to on-demand load and parse the SVG dynamically.
  263. *
  264. * @usage
  265. * <hljs lang="js">
  266. * app.config(function($mdIconProvider) {
  267. *
  268. * // Configure URLs for icons specified by [set:]id.
  269. *
  270. * $mdIconProvider
  271. * .defaultFontSet( 'fontawesome' )
  272. * .defaultIconSet('my/app/icons.svg') // Register a default set of SVG icons
  273. * .iconSet('social', 'my/app/social.svg') // Register a named icon set of SVGs
  274. * .icon('android', 'my/app/android.svg') // Register a specific icon (by name)
  275. * .icon('work:chair', 'my/app/chair.svg'); // Register icon in a specific set
  276. * });
  277. * </hljs>
  278. *
  279. * SVG icons and icon sets can be easily pre-loaded and cached using either (a) a build process or (b) a runtime
  280. * **startup** process (shown below):
  281. *
  282. * <hljs lang="js">
  283. * app.config(function($mdIconProvider) {
  284. *
  285. * // Register a default set of SVG icon definitions
  286. * $mdIconProvider.defaultIconSet('my/app/icons.svg')
  287. *
  288. * })
  289. * .run(function($http, $templateCache){
  290. *
  291. * // Pre-fetch icons sources by URL and cache in the $templateCache...
  292. * // subsequent $http calls will look there first.
  293. *
  294. * var urls = [ 'imy/app/icons.svg', 'img/icons/android.svg'];
  295. *
  296. * angular.forEach(urls, function(url) {
  297. * $http.get(url, {cache: $templateCache});
  298. * });
  299. *
  300. * });
  301. *
  302. * </hljs>
  303. *
  304. * NOTE: the loaded SVG data is subsequently cached internally for future requests.
  305. *
  306. */
  307. /**
  308. * @ngdoc method
  309. * @name $mdIconProvider#icon
  310. *
  311. * @description
  312. * Register a source URL for a specific icon name; the name may include optional 'icon set' name prefix.
  313. * These icons will later be retrieved from the cache using `$mdIcon( <icon name> )`
  314. *
  315. * @param {string} id Icon name/id used to register the icon
  316. * @param {string} url specifies the external location for the data file. Used internally by `$http` to load the
  317. * data or as part of the lookup in `$templateCache` if pre-loading was configured.
  318. * @param {number=} viewBoxSize Sets the width and height the icon's viewBox.
  319. * It is ignored for icons with an existing viewBox. Default size is 24.
  320. *
  321. * @returns {obj} an `$mdIconProvider` reference; used to support method call chains for the API
  322. *
  323. * @usage
  324. * <hljs lang="js">
  325. * app.config(function($mdIconProvider) {
  326. *
  327. * // Configure URLs for icons specified by [set:]id.
  328. *
  329. * $mdIconProvider
  330. * .icon('android', 'my/app/android.svg') // Register a specific icon (by name)
  331. * .icon('work:chair', 'my/app/chair.svg'); // Register icon in a specific set
  332. * });
  333. * </hljs>
  334. *
  335. */
  336. /**
  337. * @ngdoc method
  338. * @name $mdIconProvider#iconSet
  339. *
  340. * @description
  341. * Register a source URL for a 'named' set of icons; group of SVG definitions where each definition
  342. * has an icon id. Individual icons can be subsequently retrieved from this cached set using
  343. * `$mdIcon(<icon set name>:<icon name>)`
  344. *
  345. * @param {string} id Icon name/id used to register the iconset
  346. * @param {string} url specifies the external location for the data file. Used internally by `$http` to load the
  347. * data or as part of the lookup in `$templateCache` if pre-loading was configured.
  348. * @param {number=} viewBoxSize Sets the width and height of the viewBox of all icons in the set.
  349. * It is ignored for icons with an existing viewBox. All icons in the icon set should be the same size.
  350. * Default value is 24.
  351. *
  352. * @returns {obj} an `$mdIconProvider` reference; used to support method call chains for the API
  353. *
  354. *
  355. * @usage
  356. * <hljs lang="js">
  357. * app.config(function($mdIconProvider) {
  358. *
  359. * // Configure URLs for icons specified by [set:]id.
  360. *
  361. * $mdIconProvider
  362. * .iconSet('social', 'my/app/social.svg') // Register a named icon set
  363. * });
  364. * </hljs>
  365. *
  366. */
  367. /**
  368. * @ngdoc method
  369. * @name $mdIconProvider#defaultIconSet
  370. *
  371. * @description
  372. * Register a source URL for the default 'named' set of icons. Unless explicitly registered,
  373. * subsequent lookups of icons will failover to search this 'default' icon set.
  374. * Icon can be retrieved from this cached, default set using `$mdIcon(<name>)`
  375. *
  376. * @param {string} url specifies the external location for the data file. Used internally by `$http` to load the
  377. * data or as part of the lookup in `$templateCache` if pre-loading was configured.
  378. * @param {number=} viewBoxSize Sets the width and height of the viewBox of all icons in the set.
  379. * It is ignored for icons with an existing viewBox. All icons in the icon set should be the same size.
  380. * Default value is 24.
  381. *
  382. * @returns {obj} an `$mdIconProvider` reference; used to support method call chains for the API
  383. *
  384. * @usage
  385. * <hljs lang="js">
  386. * app.config(function($mdIconProvider) {
  387. *
  388. * // Configure URLs for icons specified by [set:]id.
  389. *
  390. * $mdIconProvider
  391. * .defaultIconSet( 'my/app/social.svg' ) // Register a default icon set
  392. * });
  393. * </hljs>
  394. *
  395. */
  396. /**
  397. * @ngdoc method
  398. * @name $mdIconProvider#defaultFontSet
  399. *
  400. * @description
  401. * When using Font-Icons, Angular Material assumes the the Material Design icons will be used and automatically
  402. * configures the default font-set == 'material-icons'. Note that the font-set references the font-icon library
  403. * class style that should be applied to the `<md-icon>`.
  404. *
  405. * Configuring the default means that the attributes
  406. * `md-font-set="material-icons"` or `class="material-icons"` do not need to be explicitly declared on the
  407. * `<md-icon>` markup. For example:
  408. *
  409. * `<md-icon> face </md-icon>`
  410. * will render as
  411. * `<span class="material-icons"> face </span>`, and
  412. *
  413. * `<md-icon md-font-set="fa"> face </md-icon>`
  414. * will render as
  415. * `<span class="fa"> face </span>`
  416. *
  417. * @param {string} name of the font-library style that should be applied to the md-icon DOM element
  418. *
  419. * @usage
  420. * <hljs lang="js">
  421. * app.config(function($mdIconProvider) {
  422. * $mdIconProvider.defaultFontSet( 'fontawesome' );
  423. * });
  424. * </hljs>
  425. *
  426. */
  427. /**
  428. * @ngdoc method
  429. * @name $mdIconProvider#defaultViewBoxSize
  430. *
  431. * @description
  432. * While `<md-icon />` markup can also be style with sizing CSS, this method configures
  433. * the default width **and** height used for all icons; unless overridden by specific CSS.
  434. * The default sizing is (24px, 24px).
  435. * @param {number=} viewBoxSize Sets the width and height of the viewBox for an icon or an icon set.
  436. * All icons in a set should be the same size. The default value is 24.
  437. *
  438. * @returns {obj} an `$mdIconProvider` reference; used to support method call chains for the API
  439. *
  440. * @usage
  441. * <hljs lang="js">
  442. * app.config(function($mdIconProvider) {
  443. *
  444. * // Configure URLs for icons specified by [set:]id.
  445. *
  446. * $mdIconProvider
  447. * .defaultViewBoxSize(36) // Register a default icon size (width == height)
  448. * });
  449. * </hljs>
  450. *
  451. */
  452. var config = {
  453. defaultViewBoxSize: 24,
  454. defaultFontSet: 'material-icons',
  455. fontSets : [ ]
  456. };
  457. function MdIconProvider() { }
  458. MdIconProvider.prototype = {
  459. icon : function (id, url, viewBoxSize) {
  460. if ( id.indexOf(':') == -1 ) id = '$default:' + id;
  461. config[id] = new ConfigurationItem(url, viewBoxSize );
  462. return this;
  463. },
  464. iconSet : function (id, url, viewBoxSize) {
  465. config[id] = new ConfigurationItem(url, viewBoxSize );
  466. return this;
  467. },
  468. defaultIconSet : function (url, viewBoxSize) {
  469. var setName = '$default';
  470. if ( !config[setName] ) {
  471. config[setName] = new ConfigurationItem(url, viewBoxSize );
  472. }
  473. config[setName].viewBoxSize = viewBoxSize || config.defaultViewBoxSize;
  474. return this;
  475. },
  476. defaultViewBoxSize : function (viewBoxSize) {
  477. config.defaultViewBoxSize = viewBoxSize;
  478. return this;
  479. },
  480. /**
  481. * Register an alias name associated with a font-icon library style ;
  482. */
  483. fontSet : function fontSet(alias, className) {
  484. config.fontSets.push({
  485. alias : alias,
  486. fontSet : className || alias
  487. });
  488. return this;
  489. },
  490. /**
  491. * Specify a default style name associated with a font-icon library
  492. * fallback to Material Icons.
  493. *
  494. */
  495. defaultFontSet : function defaultFontSet(className) {
  496. config.defaultFontSet = !className ? '' : className;
  497. return this;
  498. },
  499. defaultIconSize : function defaultIconSize(iconSize) {
  500. config.defaultIconSize = iconSize;
  501. return this;
  502. },
  503. preloadIcons: function ($templateCache) {
  504. var iconProvider = this;
  505. var svgRegistry = [
  506. {
  507. id : 'md-tabs-arrow',
  508. url: 'md-tabs-arrow.svg',
  509. svg: '<svg version="1.1" x="0px" y="0px" viewBox="0 0 24 24"><g><polygon points="15.4,7.4 14,6 8,12 14,18 15.4,16.6 10.8,12 "/></g></svg>'
  510. },
  511. {
  512. id : 'md-close',
  513. url: 'md-close.svg',
  514. svg: '<svg version="1.1" x="0px" y="0px" viewBox="0 0 24 24"><g><path d="M19 6.41l-1.41-1.41-5.59 5.59-5.59-5.59-1.41 1.41 5.59 5.59-5.59 5.59 1.41 1.41 5.59-5.59 5.59 5.59 1.41-1.41-5.59-5.59z"/></g></svg>'
  515. },
  516. {
  517. id: 'md-cancel',
  518. url: 'md-cancel.svg',
  519. svg: '<svg version="1.1" x="0px" y="0px" viewBox="0 0 24 24"><g><path d="M12 2c-5.53 0-10 4.47-10 10s4.47 10 10 10 10-4.47 10-10-4.47-10-10-10zm5 13.59l-1.41 1.41-3.59-3.59-3.59 3.59-1.41-1.41 3.59-3.59-3.59-3.59 1.41-1.41 3.59 3.59 3.59-3.59 1.41 1.41-3.59 3.59 3.59 3.59z"/></g></svg>'
  520. },
  521. {
  522. id: 'md-menu',
  523. url: 'md-menu.svg',
  524. svg: '<svg version="1.1" x="0px" y="0px" viewBox="0 0 24 24"><path d="M3,6H21V8H3V6M3,11H21V13H3V11M3,16H21V18H3V16Z" /></svg>'
  525. },
  526. {
  527. id: 'md-toggle-arrow',
  528. url: 'md-toggle-arrow-svg',
  529. svg: '<svg version="1.1" x="0px" y="0px" viewBox="0 0 48 48"><path d="M24 16l-12 12 2.83 2.83 9.17-9.17 9.17 9.17 2.83-2.83z"/><path d="M0 0h48v48h-48z" fill="none"/></svg>'
  530. },
  531. {
  532. id: 'md-calendar',
  533. url: 'md-calendar.svg',
  534. svg: '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M19 3h-1V1h-2v2H8V1H6v2H5c-1.11 0-1.99.9-1.99 2L3 19c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H5V8h14v11zM7 10h5v5H7z"/></svg>'
  535. }
  536. ];
  537. svgRegistry.forEach(function(asset){
  538. iconProvider.icon(asset.id, asset.url);
  539. $templateCache.put(asset.url, asset.svg);
  540. });
  541. },
  542. $get : ['$http', '$q', '$log', '$templateCache', function($http, $q, $log, $templateCache) {
  543. this.preloadIcons($templateCache);
  544. return MdIconService(config, $http, $q, $log, $templateCache);
  545. }]
  546. };
  547. /**
  548. * Configuration item stored in the Icon registry; used for lookups
  549. * to load if not already cached in the `loaded` cache
  550. */
  551. function ConfigurationItem(url, viewBoxSize) {
  552. this.url = url;
  553. this.viewBoxSize = viewBoxSize || config.defaultViewBoxSize;
  554. }
  555. /**
  556. * @ngdoc service
  557. * @name $mdIcon
  558. * @module material.components.icon
  559. *
  560. * @description
  561. * The `$mdIcon` service is a function used to lookup SVG icons.
  562. *
  563. * @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
  564. * 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
  565. * performed. The Id may be a unique icon ID or may include an iconSet ID prefix.
  566. *
  567. * For the **id** query to work properly, this means that all id-to-URL mappings must have been previously configured
  568. * using the `$mdIconProvider`.
  569. *
  570. * @returns {obj} Clone of the initial SVG DOM element; which was created from the SVG markup in the SVG data file.
  571. *
  572. * @usage
  573. * <hljs lang="js">
  574. * function SomeDirective($mdIcon) {
  575. *
  576. * // See if the icon has already been loaded, if not
  577. * // then lookup the icon from the registry cache, load and cache
  578. * // it for future requests.
  579. * // NOTE: ID queries require configuration with $mdIconProvider
  580. *
  581. * $mdIcon('android').then(function(iconEl) { element.append(iconEl); });
  582. * $mdIcon('work:chair').then(function(iconEl) { element.append(iconEl); });
  583. *
  584. * // Load and cache the external SVG using a URL
  585. *
  586. * $mdIcon('img/icons/android.svg').then(function(iconEl) {
  587. * element.append(iconEl);
  588. * });
  589. * };
  590. * </hljs>
  591. *
  592. * NOTE: The `<md-icon /> ` directive internally uses the `$mdIcon` service to query, loaded, and instantiate
  593. * SVG DOM elements.
  594. */
  595. /* ngInject */
  596. function MdIconService(config, $http, $q, $log, $templateCache) {
  597. var iconCache = {};
  598. var urlRegex = /[-a-zA-Z0-9@:%_\+.~#?&//=]{2,256}\.[a-z]{2,4}\b(\/[-a-zA-Z0-9@:%_\+.~#?&//=]*)?/i;
  599. Icon.prototype = { clone : cloneSVG, prepare: prepareAndStyle };
  600. getIcon.fontSet = findRegisteredFontSet;
  601. // Publish service...
  602. return getIcon;
  603. /**
  604. * Actual $mdIcon service is essentially a lookup function
  605. */
  606. function getIcon(id) {
  607. id = id || '';
  608. // If already loaded and cached, use a clone of the cached icon.
  609. // Otherwise either load by URL, or lookup in the registry and then load by URL, and cache.
  610. if ( iconCache[id] ) return $q.when( iconCache[id].clone() );
  611. if ( urlRegex.test(id) ) return loadByURL(id).then( cacheIcon(id) );
  612. if ( id.indexOf(':') == -1 ) id = '$default:' + id;
  613. var load = config[id] ? loadByID : loadFromIconSet;
  614. return load(id)
  615. .then( cacheIcon(id) );
  616. }
  617. /**
  618. * Lookup registered fontSet style using its alias...
  619. * If not found,
  620. */
  621. function findRegisteredFontSet(alias) {
  622. var useDefault = angular.isUndefined(alias) || !(alias && alias.length);
  623. if ( useDefault ) return config.defaultFontSet;
  624. var result = alias;
  625. angular.forEach(config.fontSets, function(it){
  626. if ( it.alias == alias ) result = it.fontSet || result;
  627. });
  628. return result;
  629. }
  630. /**
  631. * Prepare and cache the loaded icon for the specified `id`
  632. */
  633. function cacheIcon( id ) {
  634. return function updateCache( icon ) {
  635. iconCache[id] = isIcon(icon) ? icon : new Icon(icon, config[id]);
  636. return iconCache[id].clone();
  637. };
  638. }
  639. /**
  640. * Lookup the configuration in the registry, if !registered throw an error
  641. * otherwise load the icon [on-demand] using the registered URL.
  642. *
  643. */
  644. function loadByID(id) {
  645. var iconConfig = config[id];
  646. return loadByURL(iconConfig.url).then(function(icon) {
  647. return new Icon(icon, iconConfig);
  648. });
  649. }
  650. /**
  651. * Loads the file as XML and uses querySelector( <id> ) to find
  652. * the desired node...
  653. */
  654. function loadFromIconSet(id) {
  655. var setName = id.substring(0, id.lastIndexOf(':')) || '$default';
  656. var iconSetConfig = config[setName];
  657. return !iconSetConfig ? announceIdNotFound(id) : loadByURL(iconSetConfig.url).then(extractFromSet);
  658. function extractFromSet(set) {
  659. var iconName = id.slice(id.lastIndexOf(':') + 1);
  660. var icon = set.querySelector('#' + iconName);
  661. return !icon ? announceIdNotFound(id) : new Icon(icon, iconSetConfig);
  662. }
  663. function announceIdNotFound(id) {
  664. var msg = 'icon ' + id + ' not found';
  665. $log.warn(msg);
  666. return $q.reject(msg || id);
  667. }
  668. }
  669. /**
  670. * Load the icon by URL (may use the $templateCache).
  671. * Extract the data for later conversion to Icon
  672. */
  673. function loadByURL(url) {
  674. return $http
  675. .get(url, { cache: $templateCache })
  676. .then(function(response) {
  677. return angular.element('<div>').append(response.data).find('svg')[0];
  678. }).catch(announceNotFound);
  679. }
  680. /**
  681. * Catch HTTP or generic errors not related to incorrect icon IDs.
  682. */
  683. function announceNotFound(err) {
  684. var msg = angular.isString(err) ? err : (err.message || err.data || err.statusText);
  685. $log.warn(msg);
  686. return $q.reject(msg);
  687. }
  688. /**
  689. * Check target signature to see if it is an Icon instance.
  690. */
  691. function isIcon(target) {
  692. return angular.isDefined(target.element) && angular.isDefined(target.config);
  693. }
  694. /**
  695. * Define the Icon class
  696. */
  697. function Icon(el, config) {
  698. if (el && el.tagName != 'svg') {
  699. el = angular.element('<svg xmlns="http://www.w3.org/2000/svg">').append(el)[0];
  700. }
  701. // Inject the namespace if not available...
  702. if ( !el.getAttribute('xmlns') ) {
  703. el.setAttribute('xmlns', "http://www.w3.org/2000/svg");
  704. }
  705. this.element = el;
  706. this.config = config;
  707. this.prepare();
  708. }
  709. /**
  710. * Prepare the DOM element that will be cached in the
  711. * loaded iconCache store.
  712. */
  713. function prepareAndStyle() {
  714. var viewBoxSize = this.config ? this.config.viewBoxSize : config.defaultViewBoxSize;
  715. angular.forEach({
  716. 'fit' : '',
  717. 'height': '100%',
  718. 'width' : '100%',
  719. 'preserveAspectRatio': 'xMidYMid meet',
  720. 'viewBox' : this.element.getAttribute('viewBox') || ('0 0 ' + viewBoxSize + ' ' + viewBoxSize)
  721. }, function(val, attr) {
  722. this.element.setAttribute(attr, val);
  723. }, this);
  724. angular.forEach({
  725. 'pointer-events' : 'none',
  726. 'display' : 'block'
  727. }, function(val, style) {
  728. this.element.style[style] = val;
  729. }, this);
  730. }
  731. /**
  732. * Clone the Icon DOM element.
  733. */
  734. function cloneSVG(){
  735. return this.element.cloneNode(true);
  736. }
  737. }
  738. MdIconService.$inject = ["config", "$http", "$q", "$log", "$templateCache"];
  739. })(window, window.angular);