PageRenderTime 27ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 0ms

/ajax/libs/ng-dialog/0.3.11/js/ngDialog.js

https://gitlab.com/Mirros/cdnjs
JavaScript | 449 lines | 337 code | 71 blank | 41 comment | 89 complexity | 0d5c6f3f7c39d9135862507f4ae05487 MD5 | raw file
  1. /*
  2. * ngDialog - easy modals and popup windows
  3. * http://github.com/likeastore/ngDialog
  4. * (c) 2013-2015 MIT License, https://likeastore.com
  5. */
  6. (function (root, factory) {
  7. if (typeof module !== 'undefined' && module.exports) {
  8. // CommonJS
  9. module.exports = factory(require('angular'));
  10. } else if (typeof define === 'function' && define.amd) {
  11. // AMD
  12. define(['angular'], factory);
  13. } else {
  14. // Global Variables
  15. factory(root.angular);
  16. }
  17. }(this, function (angular, undefined) {
  18. 'use strict';
  19. var m = angular.module('ngDialog', []);
  20. var $el = angular.element;
  21. var isDef = angular.isDefined;
  22. var style = (document.body || document.documentElement).style;
  23. var animationEndSupport = isDef(style.animation) || isDef(style.WebkitAnimation) || isDef(style.MozAnimation) || isDef(style.MsAnimation) || isDef(style.OAnimation);
  24. var animationEndEvent = 'animationend webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend';
  25. var forceBodyReload = false;
  26. var scope;
  27. m.provider('ngDialog', function () {
  28. var defaults = this.defaults = {
  29. className: 'ngdialog-theme-default',
  30. plain: false,
  31. showClose: true,
  32. closeByDocument: true,
  33. closeByEscape: true,
  34. closeByNavigation: false,
  35. appendTo: false,
  36. preCloseCallback: false,
  37. overlay: true,
  38. cache: true
  39. };
  40. this.setForceBodyReload = function (_useIt) {
  41. forceBodyReload = _useIt || false;
  42. };
  43. this.setDefaults = function (newDefaults) {
  44. angular.extend(defaults, newDefaults);
  45. };
  46. var globalID = 0, dialogsCount = 0, closeByDocumentHandler, defers = {};
  47. this.$get = ['$document', '$templateCache', '$compile', '$q', '$http', '$rootScope', '$timeout', '$window', '$controller',
  48. function ($document, $templateCache, $compile, $q, $http, $rootScope, $timeout, $window, $controller) {
  49. var $body = $document.find('body');
  50. if (forceBodyReload) {
  51. $rootScope.$on('$locationChangeSuccess', function () {
  52. $body = $document.find('body');
  53. });
  54. }
  55. var privateMethods = {
  56. onDocumentKeydown: function (event) {
  57. if (event.keyCode === 27) {
  58. publicMethods.close('$escape');
  59. }
  60. },
  61. setBodyPadding: function (width) {
  62. var originalBodyPadding = parseInt(($body.css('padding-right') || 0), 10);
  63. $body.css('padding-right', (originalBodyPadding + width) + 'px');
  64. $body.data('ng-dialog-original-padding', originalBodyPadding);
  65. },
  66. resetBodyPadding: function () {
  67. var originalBodyPadding = $body.data('ng-dialog-original-padding');
  68. if (originalBodyPadding) {
  69. $body.css('padding-right', originalBodyPadding + 'px');
  70. } else {
  71. $body.css('padding-right', '');
  72. }
  73. },
  74. performCloseDialog: function ($dialog, value) {
  75. var id = $dialog.attr('id');
  76. if (typeof $window.Hammer !== 'undefined') {
  77. var hammerTime = scope.hammerTime;
  78. hammerTime.off('tap', closeByDocumentHandler);
  79. hammerTime.destroy && hammerTime.destroy();
  80. delete scope.hammerTime;
  81. } else {
  82. $dialog.unbind('click');
  83. }
  84. if (dialogsCount === 1) {
  85. $body.unbind('keydown');
  86. }
  87. if (!$dialog.hasClass("ngdialog-closing")){
  88. dialogsCount -= 1;
  89. }
  90. $rootScope.$broadcast('ngDialog.closing', $dialog);
  91. dialogsCount = dialogsCount < 0 ? 0: dialogsCount;
  92. if (animationEndSupport) {
  93. scope.$destroy();
  94. $dialog.unbind(animationEndEvent).bind(animationEndEvent, function () {
  95. $dialog.remove();
  96. if (dialogsCount === 0) {
  97. $body.removeClass('ngdialog-open');
  98. privateMethods.resetBodyPadding();
  99. }
  100. $rootScope.$broadcast('ngDialog.closed', $dialog);
  101. }).addClass('ngdialog-closing');
  102. } else {
  103. scope.$destroy();
  104. $dialog.remove();
  105. if (dialogsCount === 0) {
  106. $body.removeClass('ngdialog-open');
  107. privateMethods.resetBodyPadding();
  108. }
  109. $rootScope.$broadcast('ngDialog.closed', $dialog);
  110. }
  111. if (defers[id]) {
  112. defers[id].resolve({
  113. id: id,
  114. value: value,
  115. $dialog: $dialog,
  116. remainingDialogs: dialogsCount
  117. });
  118. delete defers[id];
  119. }
  120. },
  121. closeDialog: function ($dialog, value) {
  122. var preCloseCallback = $dialog.data('$ngDialogPreCloseCallback');
  123. if (preCloseCallback && angular.isFunction(preCloseCallback)) {
  124. var preCloseCallbackResult = preCloseCallback.call($dialog, value);
  125. if (angular.isObject(preCloseCallbackResult)) {
  126. if (preCloseCallbackResult.closePromise) {
  127. preCloseCallbackResult.closePromise.then(function () {
  128. privateMethods.performCloseDialog($dialog, value);
  129. });
  130. } else {
  131. preCloseCallbackResult.then(function () {
  132. privateMethods.performCloseDialog($dialog, value);
  133. }, function () {
  134. return;
  135. });
  136. }
  137. } else if (preCloseCallbackResult) {
  138. privateMethods.performCloseDialog($dialog, value);
  139. }
  140. } else {
  141. privateMethods.performCloseDialog($dialog, value);
  142. }
  143. }
  144. };
  145. var publicMethods = {
  146. /*
  147. * @param {Object} options:
  148. * - template {String} - id of ng-template, url for partial, plain string (if enabled)
  149. * - plain {Boolean} - enable plain string templates, default false
  150. * - scope {Object}
  151. * - controller {String}
  152. * - className {String} - dialog theme class
  153. * - showClose {Boolean} - show close button, default true
  154. * - closeByEscape {Boolean} - default true
  155. * - closeByDocument {Boolean} - default true
  156. * - preCloseCallback {String|Function} - user supplied function name/function called before closing dialog (if set)
  157. *
  158. * @return {Object} dialog
  159. */
  160. open: function (opts) {
  161. var self = this;
  162. var options = angular.copy(defaults);
  163. opts = opts || {};
  164. angular.extend(options, opts);
  165. globalID += 1;
  166. self.latestID = 'ngdialog' + globalID;
  167. var defer;
  168. defers[self.latestID] = defer = $q.defer();
  169. scope = angular.isObject(options.scope) ? options.scope.$new() : $rootScope.$new();
  170. var $dialog, $dialogParent;
  171. $q.when(loadTemplate(options.template || options.templateUrl)).then(function (template) {
  172. $templateCache.put(options.template || options.templateUrl, template);
  173. if (options.showClose) {
  174. template += '<div class="ngdialog-close"></div>';
  175. }
  176. self.$result = $dialog = $el('<div id="ngdialog' + globalID + '" class="ngdialog"></div>');
  177. $dialog.html((options.overlay ?
  178. '<div class="ngdialog-overlay"></div><div class="ngdialog-content">' + template + '</div>' :
  179. '<div class="ngdialog-content">' + template + '</div>'));
  180. if (options.data && angular.isString(options.data)) {
  181. var firstLetter = options.data.replace(/^\s*/, '')[0];
  182. scope.ngDialogData = (firstLetter === '{' || firstLetter === '[') ? angular.fromJson(options.data) : options.data;
  183. } else if (options.data && angular.isObject(options.data)) {
  184. scope.ngDialogData = options.data;
  185. }
  186. if (options.controller && (angular.isString(options.controller) || angular.isArray(options.controller) || angular.isFunction(options.controller))) {
  187. var controllerInstance = $controller(options.controller, {
  188. $scope: scope,
  189. $element: $dialog
  190. });
  191. $dialog.data('$ngDialogControllerController', controllerInstance);
  192. }
  193. if (options.className) {
  194. $dialog.addClass(options.className);
  195. }
  196. if (options.appendTo && angular.isString(options.appendTo)) {
  197. $dialogParent = angular.element(document.querySelector(options.appendTo));
  198. } else {
  199. $dialogParent = $body;
  200. }
  201. if (options.preCloseCallback) {
  202. var preCloseCallback;
  203. if (angular.isFunction(options.preCloseCallback)) {
  204. preCloseCallback = options.preCloseCallback;
  205. } else if (angular.isString(options.preCloseCallback)) {
  206. if (scope) {
  207. if (angular.isFunction(scope[options.preCloseCallback])) {
  208. preCloseCallback = scope[options.preCloseCallback];
  209. } else if (scope.$parent && angular.isFunction(scope.$parent[options.preCloseCallback])) {
  210. preCloseCallback = scope.$parent[options.preCloseCallback];
  211. } else if ($rootScope && angular.isFunction($rootScope[options.preCloseCallback])) {
  212. preCloseCallback = $rootScope[options.preCloseCallback];
  213. }
  214. }
  215. }
  216. if (preCloseCallback) {
  217. $dialog.data('$ngDialogPreCloseCallback', preCloseCallback);
  218. }
  219. }
  220. scope.closeThisDialog = function (value) {
  221. privateMethods.closeDialog($dialog, value);
  222. };
  223. $timeout(function () {
  224. $compile($dialog)(scope);
  225. var widthDiffs = $window.innerWidth - $body.prop('clientWidth');
  226. $body.addClass('ngdialog-open');
  227. var scrollBarWidth = widthDiffs - ($window.innerWidth - $body.prop('clientWidth'));
  228. if (scrollBarWidth > 0) {
  229. privateMethods.setBodyPadding(scrollBarWidth);
  230. }
  231. $dialogParent.append($dialog);
  232. if (options.name) {
  233. $rootScope.$broadcast('ngDialog.opened', {dialog: $dialog, name: options.name});
  234. } else {
  235. $rootScope.$broadcast('ngDialog.opened', $dialog);
  236. }
  237. });
  238. if (options.closeByEscape) {
  239. $body.bind('keydown', privateMethods.onDocumentKeydown);
  240. }
  241. if (options.closeByNavigation) {
  242. $rootScope.$on('$locationChangeSuccess', function () {
  243. privateMethods.closeDialog($dialog);
  244. });
  245. }
  246. closeByDocumentHandler = function (event) {
  247. var isOverlay = options.closeByDocument ? $el(event.target).hasClass('ngdialog-overlay') : false;
  248. var isCloseBtn = $el(event.target).hasClass('ngdialog-close');
  249. if (isOverlay || isCloseBtn) {
  250. publicMethods.close($dialog.attr('id'), isCloseBtn ? '$closeButton' : '$document');
  251. }
  252. };
  253. if (typeof $window.Hammer !== 'undefined') {
  254. var hammerTime = scope.hammerTime = $window.Hammer($dialog[0]);
  255. hammerTime.on('tap', closeByDocumentHandler);
  256. } else {
  257. $dialog.bind('click', closeByDocumentHandler);
  258. }
  259. dialogsCount += 1;
  260. return publicMethods;
  261. });
  262. return {
  263. id: 'ngdialog' + globalID,
  264. closePromise: defer.promise,
  265. close: function (value) {
  266. privateMethods.closeDialog($dialog, value);
  267. }
  268. };
  269. function loadTemplateUrl (tmpl, config) {
  270. return $http.get(tmpl, (config || {})).then(function(res) {
  271. return res.data || '';
  272. });
  273. }
  274. function loadTemplate (tmpl) {
  275. if (!tmpl) {
  276. return 'Empty template';
  277. }
  278. if (angular.isString(tmpl) && options.plain) {
  279. return tmpl;
  280. }
  281. if (typeof options.cache === 'boolean' && !options.cache) {
  282. return loadTemplateUrl(tmpl, {cache: false});
  283. }
  284. return $templateCache.get(tmpl) || loadTemplateUrl(tmpl, {cache: true});
  285. }
  286. },
  287. /*
  288. * @param {Object} options:
  289. * - template {String} - id of ng-template, url for partial, plain string (if enabled)
  290. * - plain {Boolean} - enable plain string templates, default false
  291. * - name {String}
  292. * - scope {Object}
  293. * - controller {String}
  294. * - className {String} - dialog theme class
  295. * - showClose {Boolean} - show close button, default true
  296. * - closeByEscape {Boolean} - default false
  297. * - closeByDocument {Boolean} - default false
  298. * - preCloseCallback {String|Function} - user supplied function name/function called before closing dialog (if set); not called on confirm
  299. *
  300. * @return {Object} dialog
  301. */
  302. openConfirm: function (opts) {
  303. var defer = $q.defer();
  304. var options = {
  305. closeByEscape: false,
  306. closeByDocument: false
  307. };
  308. angular.extend(options, opts);
  309. options.scope = angular.isObject(options.scope) ? options.scope.$new() : $rootScope.$new();
  310. options.scope.confirm = function (value) {
  311. defer.resolve(value);
  312. var $dialog = $el(document.getElementById(openResult.id));
  313. privateMethods.performCloseDialog($dialog, value);
  314. };
  315. var openResult = publicMethods.open(options);
  316. openResult.closePromise.then(function (data) {
  317. if (data) {
  318. return defer.reject(data.value);
  319. }
  320. return defer.reject();
  321. });
  322. return defer.promise;
  323. },
  324. /*
  325. * @param {String} id
  326. * @return {Object} dialog
  327. */
  328. close: function (id, value) {
  329. var $dialog = $el(document.getElementById(id));
  330. if ($dialog.length) {
  331. privateMethods.closeDialog($dialog, value);
  332. } else {
  333. publicMethods.closeAll(value);
  334. }
  335. return publicMethods;
  336. },
  337. closeAll: function (value) {
  338. var $all = document.querySelectorAll('.ngdialog');
  339. angular.forEach($all, function (dialog) {
  340. privateMethods.closeDialog($el(dialog), value);
  341. });
  342. },
  343. getDefaults: function () {
  344. return defaults;
  345. }
  346. };
  347. return publicMethods;
  348. }];
  349. });
  350. m.directive('ngDialog', ['ngDialog', function (ngDialog) {
  351. return {
  352. restrict: 'A',
  353. scope : {
  354. ngDialogScope : '='
  355. },
  356. link: function (scope, elem, attrs) {
  357. elem.on('click', function (e) {
  358. e.preventDefault();
  359. var ngDialogScope = angular.isDefined(scope.ngDialogScope) ? scope.ngDialogScope : 'noScope';
  360. angular.isDefined(attrs.ngDialogClosePrevious) && ngDialog.close(attrs.ngDialogClosePrevious);
  361. var defaults = ngDialog.getDefaults();
  362. ngDialog.open({
  363. template: attrs.ngDialog,
  364. className: attrs.ngDialogClass || defaults.className,
  365. controller: attrs.ngDialogController,
  366. scope: ngDialogScope,
  367. data: attrs.ngDialogData,
  368. showClose: attrs.ngDialogShowClose === 'false' ? false : (attrs.ngDialogShowClose === 'true' ? true : defaults.showClose),
  369. closeByDocument: attrs.ngDialogCloseByDocument === 'false' ? false : (attrs.ngDialogCloseByDocument === 'true' ? true : defaults.closeByDocument),
  370. closeByEscape: attrs.ngDialogCloseByEscape === 'false' ? false : (attrs.ngDialogCloseByEscape === 'true' ? true : defaults.closeByEscape),
  371. preCloseCallback: attrs.ngDialogPreCloseCallback || defaults.preCloseCallback
  372. });
  373. });
  374. }
  375. };
  376. }]);
  377. return m;
  378. }));