Socket
Socket
Sign inDemoInstall

ng-dialog

Package Overview
Dependencies
Maintainers
1
Versions
39
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

ng-dialog - npm Package Compare versions

Comparing version 0.3.12 to 0.4.0

.eslintrc

13

bower.json
{
"name": "ngDialog",
"version": "0.3.12",
"version": "0.4.0",
"homepage": "https://github.com/likeastore/ngDialog",
"description": "Modal dialogs and popups provider for Angular.js applications",
"main": [
"js/ngDialog.js",
"css/ngDialog.css",
"css/ngDialog-theme-default.css"
"js/ngDialog.js",
"css/ngDialog.css",
"css/ngDialog-theme-default.css"
],

@@ -36,4 +36,7 @@ "keywords": [

"dependencies": {
"angular": "~1"
"angular": "~1.3.x"
},
"devDependencies": {
"angular-mocks": "~1.3.14"
}
}

@@ -0,1 +1,14 @@

# 0.4.0
- [x] new `resolve` option for defining locals for ngDialog controller by [@rur](https://github.com/rur) ([PR-182](https://github.com/likeastore/ngDialog/pull/182))
- [x] support for `controllerAs` pattern by [@andrewogburn](https://github.com/andrewogburn) and [@sprbikkel](https://github.com/sprbikkel) ([PR-205](https://github.com/likeastore/ngDialog/pull/205), [PR-224](https://github.com/likeastore/ngDialog/pull/224))
- [x] added accessibility improvements (keyboard focus management / ARIA attribute) by [@richardszalay](https://github.com/richardszalay) ([PR-166](https://github.com/likeastore/ngDialog/pull/166))
- [x] added `isOpen(id)` public method by [@kasimoglou](https://github.com/kasimoglou) ([PR-219](https://github.com/likeastore/ngDialog/pull/219))
- [x] fix for `esc` should only close top dialog by [@jemise111](https://github.com/jemise111) ([PR-226](https://github.com/likeastore/ngDialog/pull/226))
- [x] fix for flickering dialogs in Internet Explorer by [@MvHMontySCOUT](https://github.com/MvHMontySCOUT) ([PR-207](https://github.com/likeastore/ngDialog/pull/207), discussion - [ISSUE-142](https://github.com/likeastore/ngDialog/issues/142))
- [x] fix issue when opening multiple dialogs simultaneously by [@bchelli](https://github.com/bchelli) ([PR-221](https://github.com/likeastore/ngDialog/pull/221))
- [x] various minor bug fixes, general improvements and examples updates
Thanks everybody, you're awesome! :dancer: :+1:
# 0.3.12

@@ -6,8 +19,11 @@

# 0.3.11
- [x] prevent the modal from closing if preCloseCallback returns a falsy value
# 0.3.10
- [x] fix negative dialogs count
# 0.3.9
- [x] fix destroy scope with animation for multiple dialog [ISSUE-125](https://github.com/likeastore/ngDialog/issues/125)

@@ -14,0 +30,0 @@

module.exports = function (grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
uglify: {
options: {
banner: '/*! <%= pkg.name %> - v<%= pkg.version %> (<%= pkg.homepage %>) */\n'
},
ngDialog: {
files: {
'./js/ngDialog.min.js': ['./js/ngDialog.js']
}
}
},
jshint: {
options: {
ignores: ['./js/ngDialog.min.js']
},
files: ['*.js']
},
myth: {
dist: {
files: {
'./css/ngDialog.css': './css/myth/ngDialog.css',
'./css/ngDialog-theme-default.css': './css/myth/ngDialog-theme-default.css',
'./css/ngDialog-theme-plain.css': './css/myth/ngDialog-theme-plain.css'
}
}
},
cssmin: {
options: {
banner: '/*! <%= pkg.name %> - v<%= pkg.version %> (<%= pkg.homepage %>) */\n'
},
minify:{
files: {
'css/ngDialog.min.css': ['css/ngDialog.css'],
'css/ngDialog-theme-default.min.css': ['css/ngDialog-theme-default.css'],
'css/ngDialog-theme-plain.min.css': ['css/ngDialog-theme-plain.css']
}
}
}
});
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
uglify: {
options: {
banner: '/*! <%= pkg.name %> - v<%= pkg.version %> (<%= pkg.homepage %>) */\n'
},
ngDialog: {
files: {
'./js/ngDialog.min.js': ['./js/ngDialog.js']
}
}
},
jshint: {
options: {
ignores: ['./js/ngDialog.min.js']
},
files: ['*.js']
},
myth: {
dist: {
files: {
'./css/ngDialog.css': './css/myth/ngDialog.css',
'./css/ngDialog-theme-default.css': './css/myth/ngDialog-theme-default.css',
'./css/ngDialog-theme-plain.css': './css/myth/ngDialog-theme-plain.css'
}
}
},
cssmin: {
options: {
banner: '/*! <%= pkg.name %> - v<%= pkg.version %> (<%= pkg.homepage %>) */\n'
},
minify: {
files: {
'css/ngDialog.min.css': ['css/ngDialog.css'],
'css/ngDialog-theme-default.min.css': ['css/ngDialog-theme-default.css'],
'css/ngDialog-theme-plain.min.css': ['css/ngDialog-theme-plain.css']
}
}
}
});
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-myth');
grunt.loadNpmTasks('grunt-contrib-cssmin');
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-myth');
grunt.loadNpmTasks('grunt-contrib-cssmin');
grunt.registerTask('default', ['jshint']);
grunt.registerTask('build', ['uglify', 'myth', 'cssmin']);
grunt.registerTask('css', ['myth', 'cssmin']);
};
grunt.registerTask('default', ['jshint']);
grunt.registerTask('build', ['uglify', 'myth', 'cssmin']);
grunt.registerTask('css', ['myth', 'cssmin']);
};

@@ -18,433 +18,718 @@ /*

}
}(this, function (angular, undefined) {
'use strict';
}(this, function (angular) {
'use strict';
var m = angular.module('ngDialog', []);
var m = angular.module('ngDialog', []);
var $el = angular.element;
var isDef = angular.isDefined;
var style = (document.body || document.documentElement).style;
var animationEndSupport = isDef(style.animation) || isDef(style.WebkitAnimation) || isDef(style.MozAnimation) || isDef(style.MsAnimation) || isDef(style.OAnimation);
var animationEndEvent = 'animationend webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend';
var forceBodyReload = false;
var scope;
var $el = angular.element;
var isDef = angular.isDefined;
var style = (document.body || document.documentElement).style;
var animationEndSupport = isDef(style.animation) || isDef(style.WebkitAnimation) || isDef(style.MozAnimation) || isDef(style.MsAnimation) || isDef(style.OAnimation);
var animationEndEvent = 'animationend webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend';
var focusableElementSelector = 'a[href], area[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), iframe, object, embed, *[tabindex], *[contenteditable]';
var forceBodyReload = false;
var scopes = {};
var openIdStack = [];
var keydownIsBound = false;
m.provider('ngDialog', function () {
var defaults = this.defaults = {
className: 'ngdialog-theme-default',
plain: false,
showClose: true,
closeByDocument: true,
closeByEscape: true,
closeByNavigation: false,
appendTo: false,
preCloseCallback: false,
overlay: true,
cache: true
};
m.provider('ngDialog', function () {
var defaults = this.defaults = {
className: 'ngdialog-theme-default',
plain: false,
showClose: true,
closeByDocument: true,
closeByEscape: true,
closeByNavigation: false,
appendTo: false,
preCloseCallback: false,
overlay: true,
cache: true,
trapFocus: true,
preserveFocus: true,
ariaAuto: true,
ariaRole: null,
ariaLabelledById: null,
ariaLabelledBySelector: null,
ariaDescribedById: null,
ariaDescribedBySelector: null
};
this.setForceBodyReload = function (_useIt) {
forceBodyReload = _useIt || false;
};
this.setForceBodyReload = function (_useIt) {
forceBodyReload = _useIt || false;
};
this.setDefaults = function (newDefaults) {
angular.extend(defaults, newDefaults);
};
this.setDefaults = function (newDefaults) {
angular.extend(defaults, newDefaults);
};
var globalID = 0, dialogsCount = 0, closeByDocumentHandler, defers = {};
var globalID = 0, dialogsCount = 0, closeByDocumentHandler, defers = {};
this.$get = ['$document', '$templateCache', '$compile', '$q', '$http', '$rootScope', '$timeout', '$window', '$controller',
function ($document, $templateCache, $compile, $q, $http, $rootScope, $timeout, $window, $controller) {
var $body = $document.find('body');
if (forceBodyReload) {
$rootScope.$on('$locationChangeSuccess', function () {
$body = $document.find('body');
});
}
this.$get = ['$document', '$templateCache', '$compile', '$q', '$http', '$rootScope', '$timeout', '$window', '$controller', '$injector',
function ($document, $templateCache, $compile, $q, $http, $rootScope, $timeout, $window, $controller, $injector) {
var $body = $document.find('body');
if (forceBodyReload) {
$rootScope.$on('$locationChangeSuccess', function () {
$body = $document.find('body');
});
}
var privateMethods = {
onDocumentKeydown: function (event) {
if (event.keyCode === 27) {
publicMethods.close('$escape');
}
},
var privateMethods = {
onDocumentKeydown: function (event) {
if (event.keyCode === 27) {
publicMethods.close('$escape');
}
},
setBodyPadding: function (width) {
var originalBodyPadding = parseInt(($body.css('padding-right') || 0), 10);
$body.css('padding-right', (originalBodyPadding + width) + 'px');
$body.data('ng-dialog-original-padding', originalBodyPadding);
},
activate: function($dialog) {
var options = $dialog.data('$ngDialogOptions');
resetBodyPadding: function () {
var originalBodyPadding = $body.data('ng-dialog-original-padding');
if (originalBodyPadding) {
$body.css('padding-right', originalBodyPadding + 'px');
} else {
$body.css('padding-right', '');
}
},
if (options.trapFocus) {
$dialog.on('keydown', privateMethods.onTrapFocusKeydown);
performCloseDialog: function ($dialog, value) {
var id = $dialog.attr('id');
// Catch rogue changes (eg. after unfocusing everything by clicking a non-focusable element)
$body.on('keydown', privateMethods.onTrapFocusKeydown);
}
},
if (typeof $window.Hammer !== 'undefined') {
var hammerTime = scope.hammerTime;
hammerTime.off('tap', closeByDocumentHandler);
hammerTime.destroy && hammerTime.destroy();
delete scope.hammerTime;
} else {
$dialog.unbind('click');
}
deactivate: function ($dialog) {
$dialog.off('keydown', privateMethods.onTrapFocusKeydown);
$body.off('keydown', privateMethods.onTrapFocusKeydown);
},
if (dialogsCount === 1) {
$body.unbind('keydown');
}
deactivateAll: function () {
angular.forEach(function(el) {
var $dialog = angular.element(el);
privateMethods.deactivate($dialog);
});
},
if (!$dialog.hasClass("ngdialog-closing")){
dialogsCount -= 1;
}
setBodyPadding: function (width) {
var originalBodyPadding = parseInt(($body.css('padding-right') || 0), 10);
$body.css('padding-right', (originalBodyPadding + width) + 'px');
$body.data('ng-dialog-original-padding', originalBodyPadding);
},
$rootScope.$broadcast('ngDialog.closing', $dialog);
dialogsCount = dialogsCount < 0 ? 0: dialogsCount;
if (animationEndSupport) {
scope.$destroy();
$dialog.unbind(animationEndEvent).bind(animationEndEvent, function () {
$dialog.remove();
if (dialogsCount === 0) {
$body.removeClass('ngdialog-open');
privateMethods.resetBodyPadding();
}
$rootScope.$broadcast('ngDialog.closed', $dialog);
}).addClass('ngdialog-closing');
} else {
scope.$destroy();
$dialog.remove();
if (dialogsCount === 0) {
$body.removeClass('ngdialog-open');
privateMethods.resetBodyPadding();
}
$rootScope.$broadcast('ngDialog.closed', $dialog);
}
if (defers[id]) {
defers[id].resolve({
id: id,
value: value,
$dialog: $dialog,
remainingDialogs: dialogsCount
});
delete defers[id];
}
},
resetBodyPadding: function () {
var originalBodyPadding = $body.data('ng-dialog-original-padding');
if (originalBodyPadding) {
$body.css('padding-right', originalBodyPadding + 'px');
} else {
$body.css('padding-right', '');
}
},
closeDialog: function ($dialog, value) {
var preCloseCallback = $dialog.data('$ngDialogPreCloseCallback');
performCloseDialog: function ($dialog, value) {
var id = $dialog.attr('id');
var scope = scopes[id];
if (preCloseCallback && angular.isFunction(preCloseCallback)) {
if (!scope) {
// Already closed
return;
}
var preCloseCallbackResult = preCloseCallback.call($dialog, value);
if (typeof $window.Hammer !== 'undefined') {
var hammerTime = scope.hammerTime;
hammerTime.off('tap', closeByDocumentHandler);
hammerTime.destroy && hammerTime.destroy();
delete scope.hammerTime;
} else {
$dialog.unbind('click');
}
if (angular.isObject(preCloseCallbackResult)) {
if (preCloseCallbackResult.closePromise) {
preCloseCallbackResult.closePromise.then(function () {
privateMethods.performCloseDialog($dialog, value);
});
} else {
preCloseCallbackResult.then(function () {
privateMethods.performCloseDialog($dialog, value);
}, function () {
return;
});
}
} else if (preCloseCallbackResult !== false) {
privateMethods.performCloseDialog($dialog, value);
}
} else {
privateMethods.performCloseDialog($dialog, value);
}
}
};
if (dialogsCount === 1) {
$body.unbind('keydown');
}
var publicMethods = {
if (!$dialog.hasClass('ngdialog-closing')){
dialogsCount -= 1;
}
/*
* @param {Object} options:
* - template {String} - id of ng-template, url for partial, plain string (if enabled)
* - plain {Boolean} - enable plain string templates, default false
* - scope {Object}
* - controller {String}
* - className {String} - dialog theme class
* - showClose {Boolean} - show close button, default true
* - closeByEscape {Boolean} - default true
* - closeByDocument {Boolean} - default true
* - preCloseCallback {String|Function} - user supplied function name/function called before closing dialog (if set)
*
* @return {Object} dialog
*/
open: function (opts) {
var self = this;
var options = angular.copy(defaults);
var previousFocus = $dialog.data('$ngDialogPreviousFocus');
if (previousFocus) {
previousFocus.focus();
}
opts = opts || {};
angular.extend(options, opts);
$rootScope.$broadcast('ngDialog.closing', $dialog);
dialogsCount = dialogsCount < 0 ? 0 : dialogsCount;
if (animationEndSupport) {
scope.$destroy();
$dialog.unbind(animationEndEvent).bind(animationEndEvent, function () {
$dialog.remove();
if (dialogsCount === 0) {
$body.removeClass('ngdialog-open');
privateMethods.resetBodyPadding();
}
$rootScope.$broadcast('ngDialog.closed', $dialog);
}).addClass('ngdialog-closing');
} else {
scope.$destroy();
$dialog.remove();
if (dialogsCount === 0) {
$body.removeClass('ngdialog-open');
privateMethods.resetBodyPadding();
}
$rootScope.$broadcast('ngDialog.closed', $dialog);
}
if (defers[id]) {
defers[id].resolve({
id: id,
value: value,
$dialog: $dialog,
remainingDialogs: dialogsCount
});
delete defers[id];
}
if (scopes[id]) {
delete scopes[id];
}
openIdStack.splice(openIdStack.indexOf(id), 1);
if (!openIdStack.length) {
$body.unbind('keydown', privateMethods.onDocumentKeydown);
keydownIsBound = false;
}
},
globalID += 1;
closeDialog: function ($dialog, value) {
var preCloseCallback = $dialog.data('$ngDialogPreCloseCallback');
self.latestID = 'ngdialog' + globalID;
if (preCloseCallback && angular.isFunction(preCloseCallback)) {
var defer;
defers[self.latestID] = defer = $q.defer();
var preCloseCallbackResult = preCloseCallback.call($dialog, value);
scope = angular.isObject(options.scope) ? options.scope.$new() : $rootScope.$new();
var $dialog, $dialogParent;
if (angular.isObject(preCloseCallbackResult)) {
if (preCloseCallbackResult.closePromise) {
preCloseCallbackResult.closePromise.then(function () {
privateMethods.performCloseDialog($dialog, value);
});
} else {
preCloseCallbackResult.then(function () {
privateMethods.performCloseDialog($dialog, value);
}, function () {
return;
});
}
} else if (preCloseCallbackResult !== false) {
privateMethods.performCloseDialog($dialog, value);
}
} else {
privateMethods.performCloseDialog($dialog, value);
}
},
$q.when(loadTemplate(options.template || options.templateUrl)).then(function (template) {
onTrapFocusKeydown: function(ev) {
var el = angular.element(ev.currentTarget);
var $dialog;
$templateCache.put(options.template || options.templateUrl, template);
if (el.hasClass('ngdialog')) {
$dialog = el;
} else {
$dialog = privateMethods.getActiveDialog();
if (options.showClose) {
template += '<div class="ngdialog-close"></div>';
}
if ($dialog === null) {
return;
}
}
self.$result = $dialog = $el('<div id="ngdialog' + globalID + '" class="ngdialog"></div>');
$dialog.html((options.overlay ?
'<div class="ngdialog-overlay"></div><div class="ngdialog-content">' + template + '</div>' :
'<div class="ngdialog-content">' + template + '</div>'));
var isTab = (ev.keyCode === 9);
var backward = (ev.shiftKey === true);
if (options.data && angular.isString(options.data)) {
var firstLetter = options.data.replace(/^\s*/, '')[0];
scope.ngDialogData = (firstLetter === '{' || firstLetter === '[') ? angular.fromJson(options.data) : options.data;
} else if (options.data && angular.isObject(options.data)) {
scope.ngDialogData = options.data;
}
if (isTab) {
privateMethods.handleTab($dialog, ev, backward);
}
},
if (options.controller && (angular.isString(options.controller) || angular.isArray(options.controller) || angular.isFunction(options.controller))) {
var controllerInstance = $controller(options.controller, {
$scope: scope,
$element: $dialog
});
$dialog.data('$ngDialogControllerController', controllerInstance);
}
handleTab: function($dialog, ev, backward) {
var focusableElements = privateMethods.getFocusableElements($dialog);
if (options.className) {
$dialog.addClass(options.className);
}
if (focusableElements.length === 0) {
if (document.activeElement) {
document.activeElement.blur();
}
return;
}
if (options.appendTo && angular.isString(options.appendTo)) {
$dialogParent = angular.element(document.querySelector(options.appendTo));
} else {
$dialogParent = $body;
}
var currentFocus = document.activeElement;
var focusIndex = Array.prototype.indexOf.call(focusableElements, currentFocus);
if (options.preCloseCallback) {
var preCloseCallback;
var isFocusIndexUnknown = (focusIndex === -1);
var isFirstElementFocused = (focusIndex === 0);
var isLastElementFocused = (focusIndex === focusableElements.length - 1);
if (angular.isFunction(options.preCloseCallback)) {
preCloseCallback = options.preCloseCallback;
} else if (angular.isString(options.preCloseCallback)) {
if (scope) {
if (angular.isFunction(scope[options.preCloseCallback])) {
preCloseCallback = scope[options.preCloseCallback];
} else if (scope.$parent && angular.isFunction(scope.$parent[options.preCloseCallback])) {
preCloseCallback = scope.$parent[options.preCloseCallback];
} else if ($rootScope && angular.isFunction($rootScope[options.preCloseCallback])) {
preCloseCallback = $rootScope[options.preCloseCallback];
}
}
}
var cancelEvent = false;
if (preCloseCallback) {
$dialog.data('$ngDialogPreCloseCallback', preCloseCallback);
}
}
if (backward) {
if (isFocusIndexUnknown || isFirstElementFocused) {
focusableElements[focusableElements.length - 1].focus();
cancelEvent = true;
}
} else {
if (isFocusIndexUnknown || isLastElementFocused) {
focusableElements[0].focus();
cancelEvent = true;
}
}
scope.closeThisDialog = function (value) {
privateMethods.closeDialog($dialog, value);
};
if (cancelEvent) {
ev.preventDefault();
ev.stopPropagation();
}
},
$timeout(function () {
$compile($dialog)(scope);
var widthDiffs = $window.innerWidth - $body.prop('clientWidth');
$body.addClass('ngdialog-open');
var scrollBarWidth = widthDiffs - ($window.innerWidth - $body.prop('clientWidth'));
if (scrollBarWidth > 0) {
privateMethods.setBodyPadding(scrollBarWidth);
}
$dialogParent.append($dialog);
autoFocus: function($dialog) {
var dialogEl = $dialog[0];
if (options.name) {
$rootScope.$broadcast('ngDialog.opened', {dialog: $dialog, name: options.name});
} else {
$rootScope.$broadcast('ngDialog.opened', $dialog);
}
});
// Browser's (Chrome 40, Forefix 37, IE 11) don't appear to honor autofocus on the dialog, but we should
var autoFocusEl = dialogEl.querySelector('*[autofocus]');
if (autoFocusEl !== null) {
autoFocusEl.focus();
if (options.closeByEscape) {
$body.bind('keydown', privateMethods.onDocumentKeydown);
}
if (document.activeElement === autoFocusEl) {
return;
}
if (options.closeByNavigation) {
$rootScope.$on('$locationChangeSuccess', function () {
privateMethods.closeDialog($dialog);
});
}
// Autofocus element might was display: none, so let's continue
}
closeByDocumentHandler = function (event) {
var isOverlay = options.closeByDocument ? $el(event.target).hasClass('ngdialog-overlay') : false;
var isCloseBtn = $el(event.target).hasClass('ngdialog-close');
var focusableElements = privateMethods.getFocusableElements($dialog);
if (isOverlay || isCloseBtn) {
publicMethods.close($dialog.attr('id'), isCloseBtn ? '$closeButton' : '$document');
}
};
if (focusableElements.length > 0) {
focusableElements[0].focus();
return;
}
if (typeof $window.Hammer !== 'undefined') {
var hammerTime = scope.hammerTime = $window.Hammer($dialog[0]);
hammerTime.on('tap', closeByDocumentHandler);
} else {
$dialog.bind('click', closeByDocumentHandler);
}
// We need to focus something for the screen readers to notice the dialog
var contentElements = privateMethods.filterVisibleElements(dialogEl.querySelectorAll('h1,h2,h3,h4,h5,h6,p,span'));
dialogsCount += 1;
if (contentElements.length > 0) {
var contentElement = contentElements[0];
$el(contentElement).attr('tabindex', '-1').css('outline', '0');
contentElement.focus();
}
},
return publicMethods;
});
getFocusableElements: function ($dialog) {
var dialogEl = $dialog[0];
return {
id: 'ngdialog' + globalID,
closePromise: defer.promise,
close: function (value) {
privateMethods.closeDialog($dialog, value);
}
};
var rawElements = dialogEl.querySelectorAll(focusableElementSelector);
function loadTemplateUrl (tmpl, config) {
return $http.get(tmpl, (config || {})).then(function(res) {
return res.data || '';
});
}
return privateMethods.filterVisibleElements(rawElements);
},
function loadTemplate (tmpl) {
if (!tmpl) {
return 'Empty template';
}
filterVisibleElements: function (els) {
var visibleFocusableElements = [];
if (angular.isString(tmpl) && options.plain) {
return tmpl;
}
for (var i = 0; i < els.length; i++) {
var el = els[i];
if (typeof options.cache === 'boolean' && !options.cache) {
return loadTemplateUrl(tmpl, {cache: false});
}
if (el.offsetWidth > 0 || el.offsetHeight > 0) {
visibleFocusableElements.push(el);
}
}
return $templateCache.get(tmpl) || loadTemplateUrl(tmpl, {cache: true});
}
},
return visibleFocusableElements;
},
/*
* @param {Object} options:
* - template {String} - id of ng-template, url for partial, plain string (if enabled)
* - plain {Boolean} - enable plain string templates, default false
* - name {String}
* - scope {Object}
* - controller {String}
* - className {String} - dialog theme class
* - showClose {Boolean} - show close button, default true
* - closeByEscape {Boolean} - default false
* - closeByDocument {Boolean} - default false
* - preCloseCallback {String|Function} - user supplied function name/function called before closing dialog (if set); not called on confirm
*
* @return {Object} dialog
*/
openConfirm: function (opts) {
var defer = $q.defer();
getActiveDialog: function () {
var dialogs = document.querySelectorAll('.ngdialog');
var options = {
closeByEscape: false,
closeByDocument: false
};
angular.extend(options, opts);
if (dialogs.length === 0) {
return null;
}
options.scope = angular.isObject(options.scope) ? options.scope.$new() : $rootScope.$new();
options.scope.confirm = function (value) {
defer.resolve(value);
var $dialog = $el(document.getElementById(openResult.id));
privateMethods.performCloseDialog($dialog, value);
};
// TODO: This might be incorrect if there are a mix of open dialogs with different 'appendTo' values
return $el(dialogs[dialogs.length - 1]);
},
var openResult = publicMethods.open(options);
openResult.closePromise.then(function (data) {
if (data) {
return defer.reject(data.value);
}
return defer.reject();
});
applyAriaAttributes: function ($dialog, options) {
if (options.ariaAuto) {
if (!options.ariaRole) {
var detectedRole = (privateMethods.getFocusableElements($dialog).length > 0) ?
'dialog' :
'alertdialog';
return defer.promise;
},
options.ariaRole = detectedRole;
}
/*
* @param {String} id
* @return {Object} dialog
*/
close: function (id, value) {
var $dialog = $el(document.getElementById(id));
if (!options.ariaLabelledBySelector) {
options.ariaLabelledBySelector = 'h1,h2,h3,h4,h5,h6';
}
if ($dialog.length) {
privateMethods.closeDialog($dialog, value);
} else {
publicMethods.closeAll(value);
}
if (!options.ariaDescribedBySelector) {
options.ariaDescribedBySelector = 'article,section,p';
}
}
return publicMethods;
},
if (options.ariaRole) {
$dialog.attr('role', options.ariaRole);
}
closeAll: function (value) {
var $all = document.querySelectorAll('.ngdialog');
privateMethods.applyAriaAttribute(
$dialog, 'aria-labelledby', options.ariaLabelledById, options.ariaLabelledBySelector);
angular.forEach($all, function (dialog) {
privateMethods.closeDialog($el(dialog), value);
});
},
privateMethods.applyAriaAttribute(
$dialog, 'aria-describedby', options.ariaDescribedById, options.ariaDescribedBySelector);
},
getDefaults: function () {
return defaults;
}
};
applyAriaAttribute: function($dialog, attr, id, selector) {
if (id) {
$dialog.attr(attr, id);
}
return publicMethods;
}];
});
if (selector) {
var dialogId = $dialog.attr('id');
m.directive('ngDialog', ['ngDialog', function (ngDialog) {
return {
restrict: 'A',
scope : {
ngDialogScope : '='
},
link: function (scope, elem, attrs) {
elem.on('click', function (e) {
e.preventDefault();
var firstMatch = $dialog[0].querySelector(selector);
var ngDialogScope = angular.isDefined(scope.ngDialogScope) ? scope.ngDialogScope : 'noScope';
angular.isDefined(attrs.ngDialogClosePrevious) && ngDialog.close(attrs.ngDialogClosePrevious);
if (!firstMatch) {
return;
}
var defaults = ngDialog.getDefaults();
var generatedId = dialogId + '-' + attr;
ngDialog.open({
template: attrs.ngDialog,
className: attrs.ngDialogClass || defaults.className,
controller: attrs.ngDialogController,
scope: ngDialogScope,
data: attrs.ngDialogData,
showClose: attrs.ngDialogShowClose === 'false' ? false : (attrs.ngDialogShowClose === 'true' ? true : defaults.showClose),
closeByDocument: attrs.ngDialogCloseByDocument === 'false' ? false : (attrs.ngDialogCloseByDocument === 'true' ? true : defaults.closeByDocument),
closeByEscape: attrs.ngDialogCloseByEscape === 'false' ? false : (attrs.ngDialogCloseByEscape === 'true' ? true : defaults.closeByEscape),
preCloseCallback: attrs.ngDialogPreCloseCallback || defaults.preCloseCallback
});
});
}
};
}]);
$el(firstMatch).attr('id', generatedId);
return m;
$dialog.attr(attr, generatedId);
return generatedId;
}
}
};
var publicMethods = {
/*
* @param {Object} options:
* - template {String} - id of ng-template, url for partial, plain string (if enabled)
* - plain {Boolean} - enable plain string templates, default false
* - scope {Object}
* - controller {String}
* - controllerAs {String}
* - className {String} - dialog theme class
* - showClose {Boolean} - show close button, default true
* - closeByEscape {Boolean} - default true
* - closeByDocument {Boolean} - default true
* - preCloseCallback {String|Function} - user supplied function name/function called before closing dialog (if set)
*
* @return {Object} dialog
*/
open: function (opts) {
var options = angular.copy(defaults);
var localID = ++globalID;
var dialogID = 'ngdialog' + localID;
openIdStack.push(dialogID);
opts = opts || {};
angular.extend(options, opts);
var defer;
defers[dialogID] = defer = $q.defer();
var scope;
scopes[dialogID] = scope = angular.isObject(options.scope) ? options.scope.$new() : $rootScope.$new();
var $dialog, $dialogParent;
var resolve = angular.extend({}, options.resolve);
angular.forEach(resolve, function (value, key) {
resolve[key] = angular.isString(value) ? $injector.get(value) : $injector.invoke(value, null, null, key);
});
$q.all({
template: loadTemplate(options.template || options.templateUrl),
locals: $q.all(resolve)
}).then(function (setup) {
var template = setup.template,
locals = setup.locals;
$templateCache.put(options.template || options.templateUrl, template);
if (options.showClose) {
template += '<div class="ngdialog-close"></div>';
}
$dialog = $el('<div id="ngdialog' + localID + '" class="ngdialog"></div>');
$dialog.html((options.overlay ?
'<div class="ngdialog-overlay"></div><div class="ngdialog-content" role="document">' + template + '</div>' :
'<div class="ngdialog-content" role="document">' + template + '</div>'));
$dialog.data('$ngDialogOptions', options);
if (options.data && angular.isString(options.data)) {
var firstLetter = options.data.replace(/^\s*/, '')[0];
scope.ngDialogData = (firstLetter === '{' || firstLetter === '[') ? angular.fromJson(options.data) : options.data;
} else if (options.data && angular.isObject(options.data)) {
scope.ngDialogData = options.data;
}
if (options.controller && (angular.isString(options.controller) || angular.isArray(options.controller) || angular.isFunction(options.controller))) {
var ctrl = options.controller;
if (options.controllerAs && angular.isString(options.controllerAs)) {
ctrl += ' as ' + options.controllerAs;
}
var controllerInstance = $controller(ctrl, angular.extend(
locals,
{
$scope: scope,
$element: $dialog
}
));
$dialog.data('$ngDialogControllerController', controllerInstance);
}
if (options.className) {
$dialog.addClass(options.className);
}
if (options.appendTo && angular.isString(options.appendTo)) {
$dialogParent = angular.element(document.querySelector(options.appendTo));
} else {
$dialogParent = $body;
}
privateMethods.applyAriaAttributes($dialog, options);
if (options.preCloseCallback) {
var preCloseCallback;
if (angular.isFunction(options.preCloseCallback)) {
preCloseCallback = options.preCloseCallback;
} else if (angular.isString(options.preCloseCallback)) {
if (scope) {
if (angular.isFunction(scope[options.preCloseCallback])) {
preCloseCallback = scope[options.preCloseCallback];
} else if (scope.$parent && angular.isFunction(scope.$parent[options.preCloseCallback])) {
preCloseCallback = scope.$parent[options.preCloseCallback];
} else if ($rootScope && angular.isFunction($rootScope[options.preCloseCallback])) {
preCloseCallback = $rootScope[options.preCloseCallback];
}
}
}
if (preCloseCallback) {
$dialog.data('$ngDialogPreCloseCallback', preCloseCallback);
}
}
scope.closeThisDialog = function (value) {
privateMethods.closeDialog($dialog, value);
};
$timeout(function () {
var $activeDialogs = document.querySelectorAll('.ngdialog');
privateMethods.deactivateAll($activeDialogs);
$compile($dialog)(scope);
var widthDiffs = $window.innerWidth - $body.prop('clientWidth');
$body.addClass('ngdialog-open');
var scrollBarWidth = widthDiffs - ($window.innerWidth - $body.prop('clientWidth'));
if (scrollBarWidth > 0) {
privateMethods.setBodyPadding(scrollBarWidth);
}
$dialogParent.append($dialog);
privateMethods.activate($dialog);
if (options.trapFocus) {
privateMethods.autoFocus($dialog);
}
if (options.name) {
$rootScope.$broadcast('ngDialog.opened', {dialog: $dialog, name: options.name});
} else {
$rootScope.$broadcast('ngDialog.opened', $dialog);
}
});
if (!keydownIsBound) {
$body.bind('keydown', privateMethods.onDocumentKeydown);
keydownIsBound = true;
}
if (options.closeByNavigation) {
$rootScope.$on('$locationChangeSuccess', function () {
privateMethods.closeDialog($dialog);
});
}
if (options.preserveFocus) {
$dialog.data('$ngDialogPreviousFocus', document.activeElement);
}
closeByDocumentHandler = function (event) {
var isOverlay = options.closeByDocument ? $el(event.target).hasClass('ngdialog-overlay') : false;
var isCloseBtn = $el(event.target).hasClass('ngdialog-close');
if (isOverlay || isCloseBtn) {
publicMethods.close($dialog.attr('id'), isCloseBtn ? '$closeButton' : '$document');
}
};
if (typeof $window.Hammer !== 'undefined') {
var hammerTime = scope.hammerTime = $window.Hammer($dialog[0]);
hammerTime.on('tap', closeByDocumentHandler);
} else {
$dialog.bind('click', closeByDocumentHandler);
}
dialogsCount += 1;
return publicMethods;
});
return {
id: dialogID,
closePromise: defer.promise,
close: function (value) {
privateMethods.closeDialog($dialog, value);
}
};
function loadTemplateUrl (tmpl, config) {
return $http.get(tmpl, (config || {})).then(function(res) {
return res.data || '';
});
}
function loadTemplate (tmpl) {
if (!tmpl) {
return 'Empty template';
}
if (angular.isString(tmpl) && options.plain) {
return tmpl;
}
if (typeof options.cache === 'boolean' && !options.cache) {
return loadTemplateUrl(tmpl, {cache: false});
}
return $templateCache.get(tmpl) || loadTemplateUrl(tmpl, {cache: true});
}
},
/*
* @param {Object} options:
* - template {String} - id of ng-template, url for partial, plain string (if enabled)
* - plain {Boolean} - enable plain string templates, default false
* - name {String}
* - scope {Object}
* - controller {String}
* - controllerAs {String}
* - className {String} - dialog theme class
* - showClose {Boolean} - show close button, default true
* - closeByEscape {Boolean} - default false
* - closeByDocument {Boolean} - default false
* - preCloseCallback {String|Function} - user supplied function name/function called before closing dialog (if set); not called on confirm
*
* @return {Object} dialog
*/
openConfirm: function (opts) {
var defer = $q.defer();
var options = {
closeByEscape: false,
closeByDocument: false
};
angular.extend(options, opts);
options.scope = angular.isObject(options.scope) ? options.scope.$new() : $rootScope.$new();
options.scope.confirm = function (value) {
defer.resolve(value);
var $dialog = $el(document.getElementById(openResult.id));
privateMethods.performCloseDialog($dialog, value);
};
var openResult = publicMethods.open(options);
openResult.closePromise.then(function (data) {
if (data) {
return defer.reject(data.value);
}
return defer.reject();
});
return defer.promise;
},
isOpen: function(id) {
var $dialog = $el(document.getElementById(id));
return $dialog.length > 0;
},
/*
* @param {String} id
* @return {Object} dialog
*/
close: function (id, value) {
var $dialog = $el(document.getElementById(id));
if ($dialog.length) {
privateMethods.closeDialog($dialog, value);
} else {
if (id === '$escape') {
var topDialogId = openIdStack[openIdStack.length - 1];
$dialog = $el(document.getElementById(topDialogId));
if ($dialog.data('$ngDialogOptions').closeByEscape) {
privateMethods.closeDialog($dialog, value);
}
}
}
return publicMethods;
},
closeAll: function (value) {
var $all = document.querySelectorAll('.ngdialog');
// Reverse order to ensure focus restoration works as expected
for (var i = $all.length - 1; i >= 0; i--) {
var dialog = $all[i];
privateMethods.closeDialog($el(dialog), value);
}
},
getDefaults: function () {
return defaults;
}
};
return publicMethods;
}];
});
m.directive('ngDialog', ['ngDialog', function (ngDialog) {
return {
restrict: 'A',
scope: {
ngDialogScope: '='
},
link: function (scope, elem, attrs) {
elem.on('click', function (e) {
e.preventDefault();
var ngDialogScope = angular.isDefined(scope.ngDialogScope) ? scope.ngDialogScope : 'noScope';
angular.isDefined(attrs.ngDialogClosePrevious) && ngDialog.close(attrs.ngDialogClosePrevious);
var defaults = ngDialog.getDefaults();
ngDialog.open({
template: attrs.ngDialog,
className: attrs.ngDialogClass || defaults.className,
controller: attrs.ngDialogController,
controllerAs: attrs.ngDialogControllerAs,
scope: ngDialogScope,
data: attrs.ngDialogData,
showClose: attrs.ngDialogShowClose === 'false' ? false : (attrs.ngDialogShowClose === 'true' ? true : defaults.showClose),
closeByDocument: attrs.ngDialogCloseByDocument === 'false' ? false : (attrs.ngDialogCloseByDocument === 'true' ? true : defaults.closeByDocument),
closeByEscape: attrs.ngDialogCloseByEscape === 'false' ? false : (attrs.ngDialogCloseByEscape === 'true' ? true : defaults.closeByEscape),
preCloseCallback: attrs.ngDialogPreCloseCallback || defaults.preCloseCallback
});
});
}
};
}]);
return m;
}));

@@ -1,2 +0,2 @@

/*! ng-dialog - v0.3.12 (https://github.com/likeastore/ngDialog) */
!function(a,b){"undefined"!=typeof module&&module.exports?module.exports=b(require("angular")):"function"==typeof define&&define.amd?define(["angular"],b):b(a.angular)}(this,function(a){"use strict";var b,c=a.module("ngDialog",[]),d=a.element,e=a.isDefined,f=(document.body||document.documentElement).style,g=e(f.animation)||e(f.WebkitAnimation)||e(f.MozAnimation)||e(f.MsAnimation)||e(f.OAnimation),h="animationend webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend",i=!1;return c.provider("ngDialog",function(){var c=this.defaults={className:"ngdialog-theme-default",plain:!1,showClose:!0,closeByDocument:!0,closeByEscape:!0,closeByNavigation:!1,appendTo:!1,preCloseCallback:!1,overlay:!0,cache:!0};this.setForceBodyReload=function(a){i=a||!1},this.setDefaults=function(b){a.extend(c,b)};var e,f=0,j=0,k={};this.$get=["$document","$templateCache","$compile","$q","$http","$rootScope","$timeout","$window","$controller",function(l,m,n,o,p,q,r,s,t){var u=l.find("body");i&&q.$on("$locationChangeSuccess",function(){u=l.find("body")});var v={onDocumentKeydown:function(a){27===a.keyCode&&w.close("$escape")},setBodyPadding:function(a){var b=parseInt(u.css("padding-right")||0,10);u.css("padding-right",b+a+"px"),u.data("ng-dialog-original-padding",b)},resetBodyPadding:function(){var a=u.data("ng-dialog-original-padding");a?u.css("padding-right",a+"px"):u.css("padding-right","")},performCloseDialog:function(a,c){var d=a.attr("id");if("undefined"!=typeof s.Hammer){var f=b.hammerTime;f.off("tap",e),f.destroy&&f.destroy(),delete b.hammerTime}else a.unbind("click");1===j&&u.unbind("keydown"),a.hasClass("ngdialog-closing")||(j-=1),q.$broadcast("ngDialog.closing",a),j=0>j?0:j,g?(b.$destroy(),a.unbind(h).bind(h,function(){a.remove(),0===j&&(u.removeClass("ngdialog-open"),v.resetBodyPadding()),q.$broadcast("ngDialog.closed",a)}).addClass("ngdialog-closing")):(b.$destroy(),a.remove(),0===j&&(u.removeClass("ngdialog-open"),v.resetBodyPadding()),q.$broadcast("ngDialog.closed",a)),k[d]&&(k[d].resolve({id:d,value:c,$dialog:a,remainingDialogs:j}),delete k[d])},closeDialog:function(b,c){var d=b.data("$ngDialogPreCloseCallback");if(d&&a.isFunction(d)){var e=d.call(b,c);a.isObject(e)?e.closePromise?e.closePromise.then(function(){v.performCloseDialog(b,c)}):e.then(function(){v.performCloseDialog(b,c)},function(){}):e!==!1&&v.performCloseDialog(b,c)}else v.performCloseDialog(b,c)}},w={open:function(g){function h(a,b){return p.get(a,b||{}).then(function(a){return a.data||""})}function i(b){return b?a.isString(b)&&x.plain?b:"boolean"!=typeof x.cache||x.cache?m.get(b)||h(b,{cache:!0}):h(b,{cache:!1}):"Empty template"}var l=this,x=a.copy(c);g=g||{},a.extend(x,g),f+=1,l.latestID="ngdialog"+f;var y;k[l.latestID]=y=o.defer(),b=a.isObject(x.scope)?x.scope.$new():q.$new();var z,A;return o.when(i(x.template||x.templateUrl)).then(function(c){if(m.put(x.template||x.templateUrl,c),x.showClose&&(c+='<div class="ngdialog-close"></div>'),l.$result=z=d('<div id="ngdialog'+f+'" class="ngdialog"></div>'),z.html(x.overlay?'<div class="ngdialog-overlay"></div><div class="ngdialog-content">'+c+"</div>":'<div class="ngdialog-content">'+c+"</div>"),x.data&&a.isString(x.data)){var g=x.data.replace(/^\s*/,"")[0];b.ngDialogData="{"===g||"["===g?a.fromJson(x.data):x.data}else x.data&&a.isObject(x.data)&&(b.ngDialogData=x.data);if(x.controller&&(a.isString(x.controller)||a.isArray(x.controller)||a.isFunction(x.controller))){var h=t(x.controller,{$scope:b,$element:z});z.data("$ngDialogControllerController",h)}if(x.className&&z.addClass(x.className),A=x.appendTo&&a.isString(x.appendTo)?a.element(document.querySelector(x.appendTo)):u,x.preCloseCallback){var i;a.isFunction(x.preCloseCallback)?i=x.preCloseCallback:a.isString(x.preCloseCallback)&&b&&(a.isFunction(b[x.preCloseCallback])?i=b[x.preCloseCallback]:b.$parent&&a.isFunction(b.$parent[x.preCloseCallback])?i=b.$parent[x.preCloseCallback]:q&&a.isFunction(q[x.preCloseCallback])&&(i=q[x.preCloseCallback])),i&&z.data("$ngDialogPreCloseCallback",i)}if(b.closeThisDialog=function(a){v.closeDialog(z,a)},r(function(){n(z)(b);var a=s.innerWidth-u.prop("clientWidth");u.addClass("ngdialog-open");var c=a-(s.innerWidth-u.prop("clientWidth"));c>0&&v.setBodyPadding(c),A.append(z),x.name?q.$broadcast("ngDialog.opened",{dialog:z,name:x.name}):q.$broadcast("ngDialog.opened",z)}),x.closeByEscape&&u.bind("keydown",v.onDocumentKeydown),x.closeByNavigation&&q.$on("$locationChangeSuccess",function(){v.closeDialog(z)}),e=function(a){var b=x.closeByDocument?d(a.target).hasClass("ngdialog-overlay"):!1,c=d(a.target).hasClass("ngdialog-close");(b||c)&&w.close(z.attr("id"),c?"$closeButton":"$document")},"undefined"!=typeof s.Hammer){var k=b.hammerTime=s.Hammer(z[0]);k.on("tap",e)}else z.bind("click",e);return j+=1,w}),{id:"ngdialog"+f,closePromise:y.promise,close:function(a){v.closeDialog(z,a)}}},openConfirm:function(b){var c=o.defer(),e={closeByEscape:!1,closeByDocument:!1};a.extend(e,b),e.scope=a.isObject(e.scope)?e.scope.$new():q.$new(),e.scope.confirm=function(a){c.resolve(a);var b=d(document.getElementById(f.id));v.performCloseDialog(b,a)};var f=w.open(e);return f.closePromise.then(function(a){return a?c.reject(a.value):c.reject()}),c.promise},close:function(a,b){var c=d(document.getElementById(a));return c.length?v.closeDialog(c,b):w.closeAll(b),w},closeAll:function(b){var c=document.querySelectorAll(".ngdialog");a.forEach(c,function(a){v.closeDialog(d(a),b)})},getDefaults:function(){return c}};return w}]}),c.directive("ngDialog",["ngDialog",function(b){return{restrict:"A",scope:{ngDialogScope:"="},link:function(c,d,e){d.on("click",function(d){d.preventDefault();var f=a.isDefined(c.ngDialogScope)?c.ngDialogScope:"noScope";a.isDefined(e.ngDialogClosePrevious)&&b.close(e.ngDialogClosePrevious);var g=b.getDefaults();b.open({template:e.ngDialog,className:e.ngDialogClass||g.className,controller:e.ngDialogController,scope:f,data:e.ngDialogData,showClose:"false"===e.ngDialogShowClose?!1:"true"===e.ngDialogShowClose?!0:g.showClose,closeByDocument:"false"===e.ngDialogCloseByDocument?!1:"true"===e.ngDialogCloseByDocument?!0:g.closeByDocument,closeByEscape:"false"===e.ngDialogCloseByEscape?!1:"true"===e.ngDialogCloseByEscape?!0:g.closeByEscape,preCloseCallback:e.ngDialogPreCloseCallback||g.preCloseCallback})})}}}]),c});
/*! ng-dialog - v0.4.0 (https://github.com/likeastore/ngDialog) */
!function(a,b){"undefined"!=typeof module&&module.exports?module.exports=b(require("angular")):"function"==typeof define&&define.amd?define(["angular"],b):b(a.angular)}(this,function(a){"use strict";var b=a.module("ngDialog",[]),c=a.element,d=a.isDefined,e=(document.body||document.documentElement).style,f=d(e.animation)||d(e.WebkitAnimation)||d(e.MozAnimation)||d(e.MsAnimation)||d(e.OAnimation),g="animationend webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend",h="a[href], area[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), iframe, object, embed, *[tabindex], *[contenteditable]",i=!1,j={},k=[],l=!1;return b.provider("ngDialog",function(){var b=this.defaults={className:"ngdialog-theme-default",plain:!1,showClose:!0,closeByDocument:!0,closeByEscape:!0,closeByNavigation:!1,appendTo:!1,preCloseCallback:!1,overlay:!0,cache:!0,trapFocus:!0,preserveFocus:!0,ariaAuto:!0,ariaRole:null,ariaLabelledById:null,ariaLabelledBySelector:null,ariaDescribedById:null,ariaDescribedBySelector:null};this.setForceBodyReload=function(a){i=a||!1},this.setDefaults=function(c){a.extend(b,c)};var d,e=0,m=0,n={};this.$get=["$document","$templateCache","$compile","$q","$http","$rootScope","$timeout","$window","$controller","$injector",function(o,p,q,r,s,t,u,v,w,x){var y=o.find("body");i&&t.$on("$locationChangeSuccess",function(){y=o.find("body")});var z={onDocumentKeydown:function(a){27===a.keyCode&&A.close("$escape")},activate:function(a){var b=a.data("$ngDialogOptions");b.trapFocus&&(a.on("keydown",z.onTrapFocusKeydown),y.on("keydown",z.onTrapFocusKeydown))},deactivate:function(a){a.off("keydown",z.onTrapFocusKeydown),y.off("keydown",z.onTrapFocusKeydown)},deactivateAll:function(){a.forEach(function(b){var c=a.element(b);z.deactivate(c)})},setBodyPadding:function(a){var b=parseInt(y.css("padding-right")||0,10);y.css("padding-right",b+a+"px"),y.data("ng-dialog-original-padding",b)},resetBodyPadding:function(){var a=y.data("ng-dialog-original-padding");a?y.css("padding-right",a+"px"):y.css("padding-right","")},performCloseDialog:function(a,b){var c=a.attr("id"),e=j[c];if(e){if("undefined"!=typeof v.Hammer){var h=e.hammerTime;h.off("tap",d),h.destroy&&h.destroy(),delete e.hammerTime}else a.unbind("click");1===m&&y.unbind("keydown"),a.hasClass("ngdialog-closing")||(m-=1);var i=a.data("$ngDialogPreviousFocus");i&&i.focus(),t.$broadcast("ngDialog.closing",a),m=0>m?0:m,f?(e.$destroy(),a.unbind(g).bind(g,function(){a.remove(),0===m&&(y.removeClass("ngdialog-open"),z.resetBodyPadding()),t.$broadcast("ngDialog.closed",a)}).addClass("ngdialog-closing")):(e.$destroy(),a.remove(),0===m&&(y.removeClass("ngdialog-open"),z.resetBodyPadding()),t.$broadcast("ngDialog.closed",a)),n[c]&&(n[c].resolve({id:c,value:b,$dialog:a,remainingDialogs:m}),delete n[c]),j[c]&&delete j[c],k.splice(k.indexOf(c),1),k.length||(y.unbind("keydown",z.onDocumentKeydown),l=!1)}},closeDialog:function(b,c){var d=b.data("$ngDialogPreCloseCallback");if(d&&a.isFunction(d)){var e=d.call(b,c);a.isObject(e)?e.closePromise?e.closePromise.then(function(){z.performCloseDialog(b,c)}):e.then(function(){z.performCloseDialog(b,c)},function(){}):e!==!1&&z.performCloseDialog(b,c)}else z.performCloseDialog(b,c)},onTrapFocusKeydown:function(b){var c,d=a.element(b.currentTarget);if(d.hasClass("ngdialog"))c=d;else if(c=z.getActiveDialog(),null===c)return;var e=9===b.keyCode,f=b.shiftKey===!0;e&&z.handleTab(c,b,f)},handleTab:function(a,b,c){var d=z.getFocusableElements(a);if(0===d.length)return document.activeElement&&document.activeElement.blur(),void 0;var e=document.activeElement,f=Array.prototype.indexOf.call(d,e),g=-1===f,h=0===f,i=f===d.length-1,j=!1;c?(g||h)&&(d[d.length-1].focus(),j=!0):(g||i)&&(d[0].focus(),j=!0),j&&(b.preventDefault(),b.stopPropagation())},autoFocus:function(a){var b=a[0],d=b.querySelector("*[autofocus]");if(null===d||(d.focus(),document.activeElement!==d)){var e=z.getFocusableElements(a);if(e.length>0)return e[0].focus(),void 0;var f=z.filterVisibleElements(b.querySelectorAll("h1,h2,h3,h4,h5,h6,p,span"));if(f.length>0){var g=f[0];c(g).attr("tabindex","-1").css("outline","0"),g.focus()}}},getFocusableElements:function(a){var b=a[0],c=b.querySelectorAll(h);return z.filterVisibleElements(c)},filterVisibleElements:function(a){for(var b=[],c=0;c<a.length;c++){var d=a[c];(d.offsetWidth>0||d.offsetHeight>0)&&b.push(d)}return b},getActiveDialog:function(){var a=document.querySelectorAll(".ngdialog");return 0===a.length?null:c(a[a.length-1])},applyAriaAttributes:function(a,b){if(b.ariaAuto){if(!b.ariaRole){var c=z.getFocusableElements(a).length>0?"dialog":"alertdialog";b.ariaRole=c}b.ariaLabelledBySelector||(b.ariaLabelledBySelector="h1,h2,h3,h4,h5,h6"),b.ariaDescribedBySelector||(b.ariaDescribedBySelector="article,section,p")}b.ariaRole&&a.attr("role",b.ariaRole),z.applyAriaAttribute(a,"aria-labelledby",b.ariaLabelledById,b.ariaLabelledBySelector),z.applyAriaAttribute(a,"aria-describedby",b.ariaDescribedById,b.ariaDescribedBySelector)},applyAriaAttribute:function(a,b,d,e){if(d&&a.attr(b,d),e){var f=a.attr("id"),g=a[0].querySelector(e);if(!g)return;var h=f+"-"+b;return c(g).attr("id",h),a.attr(b,h),h}}},A={open:function(f){function g(a,b){return s.get(a,b||{}).then(function(a){return a.data||""})}function h(b){return b?a.isString(b)&&i.plain?b:"boolean"!=typeof i.cache||i.cache?p.get(b)||g(b,{cache:!0}):g(b,{cache:!1}):"Empty template"}var i=a.copy(b),o=++e,B="ngdialog"+o;k.push(B),f=f||{},a.extend(i,f);var C;n[B]=C=r.defer();var D;j[B]=D=a.isObject(i.scope)?i.scope.$new():t.$new();var E,F,G=a.extend({},i.resolve);return a.forEach(G,function(b,c){G[c]=a.isString(b)?x.get(b):x.invoke(b,null,null,c)}),r.all({template:h(i.template||i.templateUrl),locals:r.all(G)}).then(function(b){var e=b.template,f=b.locals;if(p.put(i.template||i.templateUrl,e),i.showClose&&(e+='<div class="ngdialog-close"></div>'),E=c('<div id="ngdialog'+o+'" class="ngdialog"></div>'),E.html(i.overlay?'<div class="ngdialog-overlay"></div><div class="ngdialog-content" role="document">'+e+"</div>":'<div class="ngdialog-content" role="document">'+e+"</div>"),E.data("$ngDialogOptions",i),i.data&&a.isString(i.data)){var g=i.data.replace(/^\s*/,"")[0];D.ngDialogData="{"===g||"["===g?a.fromJson(i.data):i.data}else i.data&&a.isObject(i.data)&&(D.ngDialogData=i.data);if(i.controller&&(a.isString(i.controller)||a.isArray(i.controller)||a.isFunction(i.controller))){var h=i.controller;i.controllerAs&&a.isString(i.controllerAs)&&(h+=" as "+i.controllerAs);var j=w(h,a.extend(f,{$scope:D,$element:E}));E.data("$ngDialogControllerController",j)}if(i.className&&E.addClass(i.className),F=i.appendTo&&a.isString(i.appendTo)?a.element(document.querySelector(i.appendTo)):y,z.applyAriaAttributes(E,i),i.preCloseCallback){var k;a.isFunction(i.preCloseCallback)?k=i.preCloseCallback:a.isString(i.preCloseCallback)&&D&&(a.isFunction(D[i.preCloseCallback])?k=D[i.preCloseCallback]:D.$parent&&a.isFunction(D.$parent[i.preCloseCallback])?k=D.$parent[i.preCloseCallback]:t&&a.isFunction(t[i.preCloseCallback])&&(k=t[i.preCloseCallback])),k&&E.data("$ngDialogPreCloseCallback",k)}if(D.closeThisDialog=function(a){z.closeDialog(E,a)},u(function(){var a=document.querySelectorAll(".ngdialog");z.deactivateAll(a),q(E)(D);var b=v.innerWidth-y.prop("clientWidth");y.addClass("ngdialog-open");var c=b-(v.innerWidth-y.prop("clientWidth"));c>0&&z.setBodyPadding(c),F.append(E),z.activate(E),i.trapFocus&&z.autoFocus(E),i.name?t.$broadcast("ngDialog.opened",{dialog:E,name:i.name}):t.$broadcast("ngDialog.opened",E)}),l||(y.bind("keydown",z.onDocumentKeydown),l=!0),i.closeByNavigation&&t.$on("$locationChangeSuccess",function(){z.closeDialog(E)}),i.preserveFocus&&E.data("$ngDialogPreviousFocus",document.activeElement),d=function(a){var b=i.closeByDocument?c(a.target).hasClass("ngdialog-overlay"):!1,d=c(a.target).hasClass("ngdialog-close");(b||d)&&A.close(E.attr("id"),d?"$closeButton":"$document")},"undefined"!=typeof v.Hammer){var n=D.hammerTime=v.Hammer(E[0]);n.on("tap",d)}else E.bind("click",d);return m+=1,A}),{id:B,closePromise:C.promise,close:function(a){z.closeDialog(E,a)}}},openConfirm:function(b){var d=r.defer(),e={closeByEscape:!1,closeByDocument:!1};a.extend(e,b),e.scope=a.isObject(e.scope)?e.scope.$new():t.$new(),e.scope.confirm=function(a){d.resolve(a);var b=c(document.getElementById(f.id));z.performCloseDialog(b,a)};var f=A.open(e);return f.closePromise.then(function(a){return a?d.reject(a.value):d.reject()}),d.promise},isOpen:function(a){var b=c(document.getElementById(a));return b.length>0},close:function(a,b){var d=c(document.getElementById(a));if(d.length)z.closeDialog(d,b);else if("$escape"===a){var e=k[k.length-1];d=c(document.getElementById(e)),d.data("$ngDialogOptions").closeByEscape&&z.closeDialog(d,b)}return A},closeAll:function(a){for(var b=document.querySelectorAll(".ngdialog"),d=b.length-1;d>=0;d--){var e=b[d];z.closeDialog(c(e),a)}},getDefaults:function(){return b}};return A}]}),b.directive("ngDialog",["ngDialog",function(b){return{restrict:"A",scope:{ngDialogScope:"="},link:function(c,d,e){d.on("click",function(d){d.preventDefault();var f=a.isDefined(c.ngDialogScope)?c.ngDialogScope:"noScope";a.isDefined(e.ngDialogClosePrevious)&&b.close(e.ngDialogClosePrevious);var g=b.getDefaults();b.open({template:e.ngDialog,className:e.ngDialogClass||g.className,controller:e.ngDialogController,controllerAs:e.ngDialogControllerAs,scope:f,data:e.ngDialogData,showClose:"false"===e.ngDialogShowClose?!1:"true"===e.ngDialogShowClose?!0:g.showClose,closeByDocument:"false"===e.ngDialogCloseByDocument?!1:"true"===e.ngDialogCloseByDocument?!0:g.closeByDocument,closeByEscape:"false"===e.ngDialogCloseByEscape?!1:"true"===e.ngDialogCloseByEscape?!0:g.closeByEscape,preCloseCallback:e.ngDialogPreCloseCallback||g.preCloseCallback})})}}}]),b});
{
"name": "ng-dialog",
"version": "0.3.12",
"version": "0.4.0",
"homepage": "https://github.com/likeastore/ngDialog",
"description": "Modal dialogs and popups provider for Angular.js applications",
"main": "./js/ngDialog.js",
"scripts": {
"test": "./node_modules/karma/bin/karma start --single-run --browsers PhantomJS"
},
"directories": {
"test": "tests"
},
"keywords": [

@@ -30,2 +36,5 @@ "angular.js",

"license": "MIT",
"dependencies": {
"angular": "1.3.x"
},
"devDependencies": {

@@ -37,2 +46,6 @@ "grunt": "~0.4.2",

"grunt-myth": "~0.1.0",
"jasmine-core": "^2.2.0",
"karma": "^0.12.31",
"karma-jasmine": "^0.3.5",
"karma-phantomjs-launcher": "^0.1.4",
"myth": "~0.1.6",

@@ -39,0 +52,0 @@ "network-address": "0.0.4",

# ngDialog
Modal dialogs and popups provider for [Angular.js](http://angularjs.org/) applications.
[![build status](http://img.shields.io/travis/likeastore/ngDialog.svg)](https://travis-ci.org/likeastore/ngDialog)
[![npm version](http://badge.fury.io/js/ng-dialog.svg)](http://badge.fury.io/js/ng-dialog)
[![github tag](https://img.shields.io/github/tag/likeastore/ngDialog.svg)](https://github.com/likeastore/ngDialog/tags)
[![Download Count](https://img.shields.io/npm/dm/ng-dialog.svg)](http://www.npmjs.com/package/ng-dialog)
> Modal dialogs and popups provider for [Angular.js](http://angularjs.org/) applications.
ngDialog is small (~2Kb), has minimalistic API, highly customizable through themes and has only Angular.js as dependency.

@@ -31,5 +36,5 @@

app.controller('MainCtrl', function ($scope, ngDialog) {
$scope.clickToOpen = function () {
ngDialog.open({ template: 'popupTmpl.html' });
};
$scope.clickToOpen = function () {
ngDialog.open({ template: 'popupTmpl.html' });
};
});

@@ -56,4 +61,4 @@ ```

<script type="text/ng-template" id="templateId">
<h1>Template heading</h1>
<p>Content goes here</p>
<h1>Template heading</h1>
<p>Content goes here</p>
</script>

@@ -74,4 +79,4 @@ ```

ngDialog.open({
template: '<p>my template</p>',
plain: true
template: '<p>my template</p>',
plain: true
});

@@ -86,4 +91,4 @@ ```

ngDialog.open({
template: 'externalTemplate.html',
controller: 'SomeController'
template: 'externalTemplate.html',
controller: 'SomeController'
});

@@ -96,9 +101,37 @@ ```

ngDialog.open({
template: 'externalTemplate.html',
controller: ['$scope', 'otherService', function($scope, otherService) {
// controller logic
}]
template: 'externalTemplate.html',
controller: ['$scope', 'otherService', function($scope, otherService) {
// controller logic
}]
});
```
##### ``resolve {Object.<string, function>=}``
An optional map of dependencies which should be injected into the controller.
If any of these dependencies are promises, ngDialog will wait for them all to be resolved
or one to be rejected before the controller is instantiated.
If all the promises are resolved successfully, the values of the resolved promises are
injected.
The map object
is:
- `key` – `{string}`: a name of a dependency to be injected into the controller.
- `factory` - `{string|function}`: If `string` then it is an alias for a service.
Otherwise if function, then it is injected using `$injector.invoke` and the return
value is treated as the dependency. If the result is a promise, it is resolved
before its value is injected into the controller.
```javascript
ngDialog.open({
controller: function Ctrl(dep) {/*...*/},
resolve: {
dep: function depFactory() {
return 'dep value';
}
}
});
```
##### ``scope {Object}``

@@ -112,5 +145,5 @@

ngDialog.open({
template: 'externalTemplate.html',
className: 'ngdialog-theme-plain',
scope: $scope
template: 'externalTemplate.html',
className: 'ngdialog-theme-plain',
scope: $scope
});

@@ -131,4 +164,4 @@ ```

<div class="dialog-contents">
<input type="text"/>
<input type="button" value="OK" ng-click="checkInput() && closeThisDialog('Some value')"/>
<input type="text"/>
<input type="button" value="OK" ng-click="checkInput() && closeThisDialog('Some value')"/>
</div>

@@ -151,4 +184,4 @@ ```

ngDialog.open({
template: 'templateId',
className: 'ngdialog-theme-default'
template: 'templateId',
className: 'ngdialog-theme-default'
});

@@ -187,3 +220,3 @@ ```

Give a name for a dialog instance. It is useful for identifying specific dialog if there are multiple dialog boxes opened.
Give a name for a dialog instance. It is useful for identifying specific dialog if there are multiple dialog boxes opened.

@@ -202,8 +235,8 @@ ##### ``preCloseCallback {String} | {Function}``

ngDialog.open({
preCloseCallback: function(value) {
if(confirm('Are you sure you want to close without saving your changes?')) {
return true;
}
return false;
}
preCloseCallback: function(value) {
if(confirm('Are you sure you want to close without saving your changes?')) {
return true;
}
return false;
}
});

@@ -216,19 +249,63 @@ ```

ngDialog.open({
preCloseCallback: function(value) {
var nestedConfirmDialog = ngDialog.openConfirm({
template:'\
<p>Are you sure you want to close the parent dialog?</p>\
<div class="ngdialog-buttons">\
<button type="button" class="ngdialog-button ngdialog-button-secondary" ng-click="closeThisDialog(0)">No</button>\
<button type="button" class="ngdialog-button ngdialog-button-primary" ng-click="confirm(1)">Yes</button>\
</div>',
plain: true
});
preCloseCallback: function(value) {
var nestedConfirmDialog = ngDialog.openConfirm({
template:'\
<p>Are you sure you want to close the parent dialog?</p>\
<div class="ngdialog-buttons">\
<button type="button" class="ngdialog-button ngdialog-button-secondary" ng-click="closeThisDialog(0)">No</button>\
<button type="button" class="ngdialog-button ngdialog-button-primary" ng-click="confirm(1)">Yes</button>\
</div>',
plain: true
});
// NOTE: return the promise from openConfirm
return nestedConfirmDialog;
}
// NOTE: return the promise from openConfirm
return nestedConfirmDialog;
}
});
```
##### ``trapFocus {Boolean}``
When ``true``, ensures that the focused element remains within the dialog to conform to accessibility recommendations. Default value is ``true``
##### ``preserveFocus {Boolean}``
When ``true``, closing the dialog restores focus to the element that launched it. Designed to improve keyboard accessibility. Default value is ``true``
##### ``ariaAuto {Boolean}``
When ``true``, automatically selects appropriate values for any unspecified accessibility attributes. Default value is ``true``
See [Accessibility](#Accessibility) for more information.
##### ``ariaRole {String}``
Specifies the value for the ``role`` attribute that should be applied to the dialog element. Default value is ``null`` (unspecified)
See [Accessibility](#Accessibility) for more information.
##### ``ariaLaballedById {String}``
Specifies the value for the ``aria-labelledby`` attribute that should be applied to the dialog element. Default value is ``null`` (unspecified)
If specified, the value is not validated against the DOM. See [Accessibility](#Accessibility) for more information.
##### ``ariaLaballedBySelector {String}``
Specifies the CSS selector for the element to be referenced by the ``aria-labelledby`` attribute on the dialog element. Default value is ``null`` (unspecified)
If specified, the first matching element is used. See [Accessibility](#Accessibility) for more information.
##### ``ariaDescribedById {String}``
Specifies the value for the ``aria-describedby`` attribute that should be applied to the dialog element. Default value is ``null`` (unspecified)
If specified, the value is not validated against the DOM. See [Accessibility](#Accessibility) for more information.
##### ``ariaDescribedBySelector {String}``
Specifies the CSS selector for the element to be referenced by the ``aria-describedby`` attribute on the dialog element. Default value is ``null`` (unspecified)
If specified, the first matching element is used. See [Accessibility](#Accessibility) for more information.
===

@@ -243,9 +320,9 @@

app.config(['ngDialogProvider', function (ngDialogProvider) {
ngDialogProvider.setDefaults({
className: 'ngdialog-theme-default',
plain: true,
showClose: true,
closeByDocument: true,
closeByEscape: true
});
ngDialogProvider.setDefaults({
className: 'ngdialog-theme-default',
plain: true,
showClose: true,
closeByDocument: true,
closeByEscape: true
});
}]);

@@ -276,7 +353,7 @@ ```

var dialog = ngDialog.open({
template: 'templateId'
template: 'templateId'
});
dialog.closePromise.then(function (data) {
console.log(data.id + ' has been dismissed.');
console.log(data.id + ' has been dismissed.');
});

@@ -303,5 +380,5 @@ ```

<div class="dialog-contents">
Some message
<button ng-click="closeThisDialog()">Cancel</button>
<button ng-click="confirm()">Confirm</button>
Some message
<button ng-click="closeThisDialog()">Cancel</button>
<button ng-click="confirm()">Confirm</button>
</div>

@@ -316,2 +393,8 @@ ```

### ``.isOpen(id)``
Method accepts dialog's ``id`` and returns a ``Boolean`` value indicating whether the specified dialog is open.
===
### ``.close(id, value)``

@@ -337,3 +420,3 @@

app.config(function (ngDialogProvider) {
ngDialogProvider.setForceBodyReload(true);
ngDialogProvider.setForceBodyReload(true);
});

@@ -350,11 +433,11 @@ ```

<button type="button"
ng-dialog="templateId.html"
ng-dialog-class="ngdialog-theme-flat"
ng-dialog-controller="ModalCtrl"
ng-dialog-close-previous>
Open modal text
ng-dialog="templateId.html"
ng-dialog-class="ngdialog-theme-flat"
ng-dialog-controller="ModalCtrl"
ng-dialog-close-previous>
Open modal text
</button>
```
Directive contains one more additional but very useful option, it's an attribute named ``ng-dialog-close-previous``. It allows you to close previously opened dialogs automaticly.
Directive contains one more additional but very useful option, it's an attribute named ``ng-dialog-close-previous``. It allows you to close previously opened dialogs automatically.

@@ -375,3 +458,3 @@ ## Events

$rootScope.$on('ngDialog.opened', function (e, $dialog) {
console.log('ngDialog opened: ' + $dialog.attr('id'));
console.log('ngDialog opened: ' + $dialog.attr('id'));
});

@@ -386,11 +469,39 @@ ```

## Accessibility
ngDialog supports accessible keyboard navigation via the ``trapFocus`` and ``preserveFocus`` options.
The ``role``, ``aria-labelledby`` and ``aria-describedby`` attributes are also supported, and are rendered as follows.
Dialog ``role`` attribute:
* ``options.ariaRole``, if specified
* "dialog" if ``options.ariaAuto`` is ``true`` and the dialog contains any focusable elements
* "alertdialog" is ``options.ariaAuto`` is ``true`` and the dialog does *not* contain any focusable elements
Dialog ``aria-labelledby`` attribute:
* ``options.ariaLabelledById``, if specified
* If ``options.ariaLabelledBySelector`` is specified, the first matching element will be found and assigned an id (if required) and that id will be used
* If ``options.ariaAuto`` is ``true``, the first heading element in the dialog (h1-6) will be found and processed as per ``ariaLabelledBySelector``
Dialog ``aria-describedby`` attribute:
* ``options.ariaDescribedById``, if specified
* If ``options.ariaDescribedBySelector`` is specified, the first matching element will be found and assigned an id (if required) and that id will be used
* If ``options.ariaAuto`` is ``true``, the first content element in the dialog (article,section,p) will be found and processed as per ``ariaDescribedBySelector``
Dialog Content ``role`` attribute:
* Always assigned a value of "document"
## CDN
_ngDialog_ is available for public on [cdnjs](http://cdnjs.com/libraries/ng-dialog). For example, please use following urls for version ``0.3.7``.
_ngDialog_ is available for public on [cdnjs](http://cdnjs.com/libraries/ng-dialog). For example, please use following urls for version ``0.3.12``.
```html
//cdnjs.cloudflare.com/ajax/libs/ng-dialog/0.3.7/css/ngDialog.min.css
//cdnjs.cloudflare.com/ajax/libs/ng-dialog/0.3.7/css/ngDialog-theme-default.min.css
//cdnjs.cloudflare.com/ajax/libs/ng-dialog/0.3.7/css/ngDialog-theme-plain.min.css
//cdnjs.cloudflare.com/ajax/libs/ng-dialog/0.3.7/js/ngDialog.min.js
//cdnjs.cloudflare.com/ajax/libs/ng-dialog/0.3.12/css/ngDialog.min.css
//cdnjs.cloudflare.com/ajax/libs/ng-dialog/0.3.12/css/ngDialog-theme-default.min.css
//cdnjs.cloudflare.com/ajax/libs/ng-dialog/0.3.12/css/ngDialog-theme-plain.min.css
//cdnjs.cloudflare.com/ajax/libs/ng-dialog/0.3.12/js/ngDialog.min.js
```

@@ -397,0 +508,0 @@

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc