PageRenderTime 30ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

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

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