toast.js 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. /*!
  2. * Angular Material Design
  3. * https://github.com/angular/material
  4. * @license MIT
  5. * v0.11.4
  6. */
  7. goog.provide('ng.material.components.toast');
  8. goog.require('ng.material.components.button');
  9. goog.require('ng.material.core');
  10. /**
  11. * @ngdoc module
  12. * @name material.components.toast
  13. * @description
  14. * Toast
  15. */
  16. angular.module('material.components.toast', [
  17. 'material.core',
  18. 'material.components.button'
  19. ])
  20. .directive('mdToast', MdToastDirective)
  21. .provider('$mdToast', MdToastProvider);
  22. /* ngInject */
  23. function MdToastDirective($mdToast) {
  24. return {
  25. restrict: 'E',
  26. link: function postLink(scope, element, attr) {
  27. // When navigation force destroys an interimElement, then
  28. // listen and $destroy() that interim instance...
  29. scope.$on('$destroy', function() {
  30. $mdToast.destroy();
  31. });
  32. }
  33. };
  34. }
  35. MdToastDirective.$inject = ["$mdToast"];
  36. /**
  37. * @ngdoc service
  38. * @name $mdToast
  39. * @module material.components.toast
  40. *
  41. * @description
  42. * `$mdToast` is a service to build a toast notification on any position
  43. * on the screen with an optional duration, and provides a simple promise API.
  44. *
  45. *
  46. * ## Restrictions on custom toasts
  47. * - The toast's template must have an outer `<md-toast>` element.
  48. * - For a toast action, use element with class `md-action`.
  49. * - Add the class `md-capsule` for curved corners.
  50. *
  51. * @usage
  52. * <hljs lang="html">
  53. * <div ng-controller="MyController">
  54. * <md-button ng-click="openToast()">
  55. * Open a Toast!
  56. * </md-button>
  57. * </div>
  58. * </hljs>
  59. *
  60. * <hljs lang="js">
  61. * var app = angular.module('app', ['ngMaterial']);
  62. * app.controller('MyController', function($scope, $mdToast) {
  63. * $scope.openToast = function($event) {
  64. * $mdToast.show($mdToast.simple().content('Hello!'));
  65. * // Could also do $mdToast.showSimple('Hello');
  66. * };
  67. * });
  68. * </hljs>
  69. */
  70. /**
  71. * @ngdoc method
  72. * @name $mdToast#showSimple
  73. *
  74. * @description
  75. * Convenience method which builds and shows a simple toast.
  76. *
  77. * @returns {promise} A promise that can be resolved with `$mdToast.hide()` or
  78. * rejected with `$mdToast.cancel()`.
  79. *
  80. */
  81. /**
  82. * @ngdoc method
  83. * @name $mdToast#simple
  84. *
  85. * @description
  86. * Builds a preconfigured toast.
  87. *
  88. * @returns {obj} a `$mdToastPreset` with the chainable configuration methods:
  89. *
  90. * - $mdToastPreset#content(string) - sets toast content to string
  91. * - $mdToastPreset#action(string) - adds an action button. If clicked the promise (returned from `show()`) will resolve
  92. * with value 'ok'; otherwise it promise is resolved with 'true' after a hideDelay timeout.
  93. * - $mdToastPreset#highlightAction(boolean) - sets action button to be highlighted
  94. * - $mdToastPreset#capsule(boolean) - adds 'md-capsule' class to the toast (curved corners)
  95. * - $mdToastPreset#theme(string) - sets the theme on the toast to theme (default is `$mdThemingProvider`'s default theme)
  96. */
  97. /**
  98. * @ngdoc method
  99. * @name $mdToast#updateContent
  100. *
  101. * @description
  102. * Updates the content of an existing toast. Useful for updating things like counts, etc.
  103. *
  104. */
  105. /**
  106. * @ngdoc method
  107. * @name $mdToast#build
  108. *
  109. * @description
  110. * Creates a custom `$mdToastPreset` that you can configure.
  111. *
  112. * @returns {obj} a `$mdToastPreset` with the chainable configuration methods for shows' options (see below).
  113. */
  114. /**
  115. * @ngdoc method
  116. * @name $mdToast#show
  117. *
  118. * @description Shows the toast.
  119. *
  120. * @param {object} optionsOrPreset Either provide an `$mdToastPreset` returned from `simple()`
  121. * and `build()`, or an options object with the following properties:
  122. *
  123. * - `templateUrl` - `{string=}`: The url of an html template file that will
  124. * be used as the content of the toast. Restrictions: the template must
  125. * have an outer `md-toast` element.
  126. * - `template` - `{string=}`: Same as templateUrl, except this is an actual
  127. * template string.
  128. * - `scope` - `{object=}`: the scope to link the template / controller to. If none is specified, it will create a new child scope.
  129. * This scope will be destroyed when the toast is removed unless `preserveScope` is set to true.
  130. * - `preserveScope` - `{boolean=}`: whether to preserve the scope when the element is removed. Default is false
  131. * - `hideDelay` - `{number=}`: How many milliseconds the toast should stay
  132. * active before automatically closing. Set to 0 or false to have the toast stay open until
  133. * closed manually. Default: 3000.
  134. * - `position` - `{string=}`: Where to place the toast. Available: any combination
  135. * of 'bottom', 'left', 'top', 'right', 'fit'. Default: 'bottom left'.
  136. * - `controller` - `{string=}`: The controller to associate with this toast.
  137. * The controller will be injected the local `$mdToast.hide( )`, which is a function
  138. * used to hide the toast.
  139. * - `locals` - `{string=}`: An object containing key/value pairs. The keys will
  140. * be used as names of values to inject into the controller. For example,
  141. * `locals: {three: 3}` would inject `three` into the controller with the value
  142. * of 3.
  143. * - `bindToController` - `bool`: bind the locals to the controller, instead of passing them in. These values will not be available until after initialization.
  144. * - `resolve` - `{object=}`: Similar to locals, except it takes promises as values
  145. * and the toast will not open until the promises resolve.
  146. * - `controllerAs` - `{string=}`: An alias to assign the controller to on the scope.
  147. * - `parent` - `{element=}`: The element to append the toast to. Defaults to appending
  148. * to the root element of the application.
  149. *
  150. * @returns {promise} A promise that can be resolved with `$mdToast.hide()` or
  151. * rejected with `$mdToast.cancel()`. `$mdToast.hide()` will resolve either with a Boolean
  152. * value == 'true' or the value passed as an argument to `$mdToast.hide()`.
  153. * And `$mdToast.cancel()` will resolve the promise with a Boolean value == 'false'
  154. */
  155. /**
  156. * @ngdoc method
  157. * @name $mdToast#hide
  158. *
  159. * @description
  160. * Hide an existing toast and resolve the promise returned from `$mdToast.show()`.
  161. *
  162. * @param {*=} response An argument for the resolved promise.
  163. *
  164. * @returns {promise} a promise that is called when the existing element is removed from the DOM.
  165. * The promise is resolved with either a Boolean value == 'true' or the value passed as the
  166. * argument to `.hide()`.
  167. *
  168. */
  169. /**
  170. * @ngdoc method
  171. * @name $mdToast#cancel
  172. *
  173. * @description
  174. * Hide the existing toast and reject the promise returned from
  175. * `$mdToast.show()`.
  176. *
  177. * @param {*=} response An argument for the rejected promise.
  178. *
  179. * @returns {promise} a promise that is called when the existing element is removed from the DOM
  180. * The promise is resolved with a Boolean value == 'false'.
  181. *
  182. */
  183. function MdToastProvider($$interimElementProvider) {
  184. // Differentiate promise resolves: hide timeout (value == true) and hide action clicks (value == ok).
  185. var ACTION_RESOLVE = 'ok';
  186. var activeToastContent;
  187. var $mdToast = $$interimElementProvider('$mdToast')
  188. .setDefaults({
  189. methods: ['position', 'hideDelay', 'capsule', 'parent' ],
  190. options: toastDefaultOptions
  191. })
  192. .addPreset('simple', {
  193. argOption: 'content',
  194. methods: ['content', 'action', 'highlightAction', 'theme', 'parent'],
  195. options: /* ngInject */ ["$mdToast", "$mdTheming", function($mdToast, $mdTheming) {
  196. var opts = {
  197. template: [
  198. '<md-toast md-theme="{{ toast.theme }}" ng-class="{\'md-capsule\': toast.capsule}">',
  199. '<span flex>{{ toast.content }}</span>',
  200. '<md-button class="md-action" ng-if="toast.action" ng-click="toast.resolve()" ng-class="{\'md-highlight\': toast.highlightAction}">',
  201. '{{ toast.action }}',
  202. '</md-button>',
  203. '</md-toast>'
  204. ].join(''),
  205. controller: /* ngInject */ ["$scope", function mdToastCtrl($scope) {
  206. var self = this;
  207. $scope.$watch(function() { return activeToastContent; }, function() {
  208. self.content = activeToastContent;
  209. });
  210. this.resolve = function() {
  211. $mdToast.hide( ACTION_RESOLVE );
  212. };
  213. }],
  214. theme: $mdTheming.defaultTheme(),
  215. controllerAs: 'toast',
  216. bindToController: true
  217. };
  218. return opts;
  219. }]
  220. })
  221. .addMethod('updateContent', function(newContent) {
  222. activeToastContent = newContent;
  223. });
  224. toastDefaultOptions.$inject = ["$animate", "$mdToast", "$mdUtil"];
  225. return $mdToast;
  226. /* ngInject */
  227. function toastDefaultOptions($animate, $mdToast, $mdUtil) {
  228. var SWIPE_EVENTS = '$md.swipeleft $md.swiperight';
  229. return {
  230. onShow: onShow,
  231. onRemove: onRemove,
  232. position: 'bottom left',
  233. themable: true,
  234. hideDelay: 3000
  235. };
  236. function onShow(scope, element, options) {
  237. activeToastContent = options.content;
  238. element = $mdUtil.extractElementByName(element, 'md-toast', true);
  239. options.onSwipe = function(ev, gesture) {
  240. //Add swipeleft/swiperight class to element so it can animate correctly
  241. element.addClass('md-' + ev.type.replace('$md.',''));
  242. $mdUtil.nextTick($mdToast.cancel);
  243. };
  244. options.openClass = toastOpenClass(options.position);
  245. // 'top left' -> 'md-top md-left'
  246. options.parent.addClass(options.openClass);
  247. element.on(SWIPE_EVENTS, options.onSwipe);
  248. element.addClass(options.position.split(' ').map(function(pos) {
  249. return 'md-' + pos;
  250. }).join(' '));
  251. return $animate.enter(element, options.parent);
  252. }
  253. function onRemove(scope, element, options) {
  254. element.off(SWIPE_EVENTS, options.onSwipe);
  255. options.parent.removeClass(options.openClass);
  256. return (options.$destroy == true) ? element.remove() : $animate.leave(element);
  257. }
  258. function toastOpenClass(position) {
  259. return 'md-toast-open-' +
  260. (position.indexOf('top') > -1 ? 'top' : 'bottom');
  261. }
  262. }
  263. }
  264. MdToastProvider.$inject = ["$$interimElementProvider"];
  265. ng.material.components.toast = angular.module("material.components.toast");