1
0

toastify.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  1. /*!
  2. * Toastify js 1.6.1
  3. * https://github.com/apvarun/toastify-js
  4. * @license MIT licensed
  5. *
  6. * Copyright (C) 2018 Varun A P
  7. */
  8. (function(root, factory) {
  9. if (typeof module === "object" && module.exports) {
  10. module.exports = factory();
  11. } else {
  12. root.Toastify = factory();
  13. }
  14. })(this, function(global) {
  15. // Object initialization
  16. var Toastify = function(options) {
  17. // Returning a new init object
  18. return new Toastify.lib.init(options);
  19. },
  20. // Library version
  21. version = "1.6.1";
  22. // Defining the prototype of the object
  23. Toastify.lib = Toastify.prototype = {
  24. toastify: version,
  25. constructor: Toastify,
  26. // Initializing the object with required parameters
  27. init: function(options) {
  28. // Verifying and validating the input object
  29. if (!options) {
  30. options = {};
  31. }
  32. // Creating the options object
  33. this.options = {};
  34. this.toastElement = null;
  35. // Validating the options
  36. this.options.text = options.text || "Hi there!"; // Display message
  37. this.options.duration = options.duration || 3000; // Display duration
  38. this.options.selector = options.selector; // Parent selector
  39. this.options.callback = options.callback || function() {}; // Callback after display
  40. this.options.destination = options.destination; // On-click destination
  41. this.options.newWindow = options.newWindow || false; // Open destination in new window
  42. this.options.close = options.close || false; // Show toast close icon
  43. this.options.gravity = options.gravity == "bottom" ? "toastify-bottom" : "toastify-top"; // toast position - top or bottom
  44. this.options.positionLeft = options.positionLeft || false; // toast position - left or right
  45. this.options.position = options.position || ''; // toast position - left or right
  46. this.options.backgroundColor = options.backgroundColor; // toast background color
  47. this.options.avatar = options.avatar || ""; // img element src - url or a path
  48. this.options.className = options.className || ""; // additional class names for the toast
  49. this.options.stopOnFocus = options.stopOnFocus === undefined? true: options.stopOnFocus; // stop timeout on focus
  50. this.options.onClick = options.onClick; // Callback after click
  51. // Returning the current object for chaining functions
  52. return this;
  53. },
  54. // Building the DOM element
  55. buildToast: function() {
  56. // Validating if the options are defined
  57. if (!this.options) {
  58. throw "Toastify is not initialized";
  59. }
  60. // Creating the DOM object
  61. var divElement = document.createElement("div");
  62. divElement.className = "toastify on " + this.options.className;
  63. // Positioning toast to left or right or center
  64. if (!!this.options.position) {
  65. divElement.className += " toastify-" + this.options.position;
  66. } else {
  67. // To be depreciated in further versions
  68. if (this.options.positionLeft === true) {
  69. divElement.className += " toastify-left";
  70. console.warn('Property `positionLeft` will be depreciated in further versions. Please use `position` instead.')
  71. } else {
  72. // Default position
  73. divElement.className += " toastify-right";
  74. }
  75. }
  76. // Assigning gravity of element
  77. divElement.className += " " + this.options.gravity;
  78. if (this.options.backgroundColor) {
  79. divElement.style.background = this.options.backgroundColor;
  80. }
  81. // Adding the toast message
  82. divElement.innerHTML = this.options.text;
  83. if (this.options.avatar !== "") {
  84. var avatarElement = document.createElement("img");
  85. avatarElement.src = this.options.avatar;
  86. avatarElement.className = "toastify-avatar";
  87. if (this.options.position == "left" || this.options.positionLeft === true) {
  88. // Adding close icon on the left of content
  89. divElement.appendChild(avatarElement);
  90. } else {
  91. // Adding close icon on the right of content
  92. divElement.insertAdjacentElement("beforeend", avatarElement);
  93. }
  94. }
  95. // Adding a close icon to the toast
  96. if (this.options.close === true) {
  97. // Create a span for close element
  98. var closeElement = document.createElement("span");
  99. closeElement.innerHTML = "✖";
  100. closeElement.className = "toast-close";
  101. // Triggering the removal of toast from DOM on close click
  102. closeElement.addEventListener(
  103. "click",
  104. function(event) {
  105. event.stopPropagation();
  106. this.removeElement(event.target.parentElement);
  107. window.clearTimeout(event.target.parentElement.timeOutValue);
  108. }.bind(this)
  109. );
  110. // Clear timeout while toast is focused
  111. if (this.options.stopOnFocus && this.options.duration > 0) {
  112. const self = this;
  113. // stop countdown
  114. divElement.addEventListener(
  115. "mouseover",
  116. function(event) {
  117. window.clearTimeout(divElement.timeOutValue);
  118. }
  119. )
  120. // add back the timeout
  121. divElement.addEventListener(
  122. "mouseleave",
  123. function() {
  124. divElement.timeOutValue = window.setTimeout(
  125. function() {
  126. // Remove the toast from DOM
  127. self.removeElement(divElement);
  128. },
  129. self.options.duration
  130. )
  131. }
  132. )
  133. }
  134. //Calculating screen width
  135. var width = window.innerWidth > 0 ? window.innerWidth : screen.width;
  136. // Adding the close icon to the toast element
  137. // Display on the right if screen width is less than or equal to 360px
  138. if ((this.options.position == "left" || this.options.positionLeft === true) && width > 360) {
  139. // Adding close icon on the left of content
  140. divElement.insertAdjacentElement("afterbegin", closeElement);
  141. } else {
  142. // Adding close icon on the right of content
  143. divElement.appendChild(closeElement);
  144. }
  145. }
  146. // Adding an on-click destination path
  147. if (typeof this.options.destination !== "undefined") {
  148. divElement.addEventListener(
  149. "click",
  150. function(event) {
  151. event.stopPropagation();
  152. if (this.options.newWindow === true) {
  153. window.open(this.options.destination, "_blank");
  154. } else {
  155. window.location = this.options.destination;
  156. }
  157. }.bind(this)
  158. );
  159. }
  160. if (typeof this.options.onClick === "function" && typeof this.options.destination === "undefined") {
  161. divElement.addEventListener(
  162. "click",
  163. function(event) {
  164. event.stopPropagation();
  165. this.options.onClick();
  166. }.bind(this)
  167. );
  168. }
  169. // Returning the generated element
  170. return divElement;
  171. },
  172. // Displaying the toast
  173. showToast: function() {
  174. // Creating the DOM object for the toast
  175. this.toastElement = this.buildToast();
  176. // Getting the root element to with the toast needs to be added
  177. var rootElement;
  178. if (typeof this.options.selector === "undefined") {
  179. rootElement = document.body;
  180. } else {
  181. rootElement = document.getElementById(this.options.selector);
  182. }
  183. // Validating if root element is present in DOM
  184. if (!rootElement) {
  185. throw "Root element is not defined";
  186. }
  187. // Adding the DOM element
  188. rootElement.insertBefore(this.toastElement, rootElement.firstChild);
  189. // Repositioning the toasts in case multiple toasts are present
  190. Toastify.reposition();
  191. if (this.options.duration > 0) {
  192. this.toastElement.timeOutValue = window.setTimeout(
  193. function() {
  194. // Remove the toast from DOM
  195. this.removeElement(this.toastElement);
  196. }.bind(this),
  197. this.options.duration
  198. ); // Binding `this` for function invocation
  199. }
  200. // Supporting function chaining
  201. return this;
  202. },
  203. hideToast: function() {
  204. if (this.toastElement.timeOutValue) {
  205. clearTimeout(this.toastElement.timeOutValue);
  206. }
  207. this.removeElement(this.toastElement);
  208. },
  209. // Removing the element from the DOM
  210. removeElement: function(toastElement) {
  211. // Hiding the element
  212. // toastElement.classList.remove("on");
  213. toastElement.className = toastElement.className.replace(" on", "");
  214. // Removing the element from DOM after transition end
  215. window.setTimeout(
  216. function() {
  217. // Remove the elemenf from the DOM
  218. toastElement.parentNode.removeChild(toastElement);
  219. // Calling the callback function
  220. this.options.callback.call(toastElement);
  221. // Repositioning the toasts again
  222. Toastify.reposition();
  223. }.bind(this),
  224. 400
  225. ); // Binding `this` for function invocation
  226. },
  227. };
  228. // Positioning the toasts on the DOM
  229. Toastify.reposition = function() {
  230. // Top margins with gravity
  231. var topLeftOffsetSize = {
  232. top: 15,
  233. bottom: 15,
  234. };
  235. var topRightOffsetSize = {
  236. top: 15,
  237. bottom: 15,
  238. };
  239. var offsetSize = {
  240. top: 15,
  241. bottom: 15,
  242. };
  243. // Get all toast messages on the DOM
  244. var allToasts = document.getElementsByClassName("toastify");
  245. var classUsed;
  246. // Modifying the position of each toast element
  247. for (var i = 0; i < allToasts.length; i++) {
  248. // Getting the applied gravity
  249. if (containsClass(allToasts[i], "toastify-top") === true) {
  250. classUsed = "toastify-top";
  251. } else {
  252. classUsed = "toastify-bottom";
  253. }
  254. var height = allToasts[i].offsetHeight;
  255. classUsed = classUsed.substr(9, classUsed.length-1)
  256. // Spacing between toasts
  257. var offset = 15;
  258. var width = window.innerWidth > 0 ? window.innerWidth : screen.width;
  259. // Show toast in center if screen with less than or qual to 360px
  260. if (width <= 360) {
  261. // Setting the position
  262. allToasts[i].style[classUsed] = offsetSize[classUsed] + "px";
  263. offsetSize[classUsed] += height + offset;
  264. } else {
  265. if (containsClass(allToasts[i], "toastify-left") === true) {
  266. // Setting the position
  267. allToasts[i].style[classUsed] = topLeftOffsetSize[classUsed] + "px";
  268. topLeftOffsetSize[classUsed] += height + offset;
  269. } else {
  270. // Setting the position
  271. allToasts[i].style[classUsed] = topRightOffsetSize[classUsed] + "px";
  272. topRightOffsetSize[classUsed] += height + offset;
  273. }
  274. }
  275. }
  276. // Supporting function chaining
  277. return this;
  278. };
  279. function containsClass(elem, yourClass) {
  280. if (!elem || typeof yourClass !== "string") {
  281. return false;
  282. } else if (
  283. elem.className &&
  284. elem.className
  285. .trim()
  286. .split(/\s+/gi)
  287. .indexOf(yourClass) > -1
  288. ) {
  289. return true;
  290. } else {
  291. return false;
  292. }
  293. }
  294. // Setting up the prototype for the init object
  295. Toastify.lib.init.prototype = Toastify.lib;
  296. // Returning the Toastify function to be assigned to the window object/module
  297. return Toastify;
  298. });