Skip to content
This repository has been archived by the owner on May 29, 2019. It is now read-only.

Commit

Permalink
refactor(modal,dialog): Harmonize $dialog and modal
Browse files Browse the repository at this point in the history
Closes #128, #13
  • Loading branch information
SidhNor authored and pkozlowski-opensource committed Feb 20, 2013
1 parent 2e5802a commit ec796ec
Show file tree
Hide file tree
Showing 9 changed files with 269 additions and 197 deletions.
5 changes: 3 additions & 2 deletions src/dialog/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,15 @@ Used for configuring global options for dialogs.
Sets the default global options for your application. Options can be overridden when opening dialogs. Available options are:

* `backdrop`: a boolean value indicating whether a backdrop should be used or not.
* `modalClass`: the css class for the modal div, defaults to 'modal'
* `dialogClass`: the css class for the modal div, defaults to 'modal'
* `backdropClass`: the css class for the backdrop, defaults to 'modal-backdrop'
* `transitionClass`: the css class that applies transitions to the nodal and backdrop, defaults to 'fade'
* `triggerClass`: the css class that triggers the transitions. default to 'in'
* `dialogOpenClass`: the css class that is added to body when dialog is opened, defaults to 'modal-open'
* `resolve`: members that will be resolved and passed to the controller as locals
* `controller`: the controller to associate with the included partial view
* `backdropFade`: a boolean value indicating whether the backdrop should fade in and out using a CSS transition, defaults to false
* `modalFade`: a boolean value indicating whether the nodal should fade in and out using a CSS transition, defaults to false
* `dialogFade`: a boolean value indicating whether the nodal should fade in and out using a CSS transition, defaults to false
* `keyboard`: indicates whether the dialog should be closable by hitting the ESC key, defaults to true
* `backdropClick`: indicates whether the dialog should be closable by clicking the backdrop area, defaults to true

Expand Down
50 changes: 34 additions & 16 deletions src/dialog/dialog.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,22 +14,25 @@ dialogModule.controller('MessageBoxController', ['$scope', 'dialog', 'model', fu
dialogModule.provider("$dialog", function(){

// The default options for all dialogs.
var defaults = {
backdrop: true,
modalClass: 'modal',
backdropClass: 'modal-backdrop',
var defaults = {
backdrop: true,
dialogClass: 'modal',
backdropClass: 'modal-backdrop',
transitionClass: 'fade',
triggerClass: 'in',
resolve:{},
backdropFade: false,
modalFade:false,
keyboard: true, // close with esc key
backdropClick: true // only in conjunction with backdrop=true
dialogOpenClass: 'modal-open',
resolve:{},
backdropFade: false,
dialogFade:false,
keyboard: true, // close with esc key
backdropClick: true // only in conjunction with backdrop=true
/* other options: template, templateUrl, controller */
};

var globalOptions = {};

var activeBackdrops = {value : 0};

// The `options({})` allows global configuration of all dialogs in the application.
//
// var app = angular.module('App', ['ui.bootstrap.dialog'], function($dialogProvider){
Expand Down Expand Up @@ -70,8 +73,8 @@ dialogModule.provider("$dialog", function(){
this.backdropEl.removeClass(options.triggerClass);
}

this.modalEl = createElement(options.modalClass);
if(options.modalFade){
this.modalEl = createElement(options.dialogClass);
if(options.dialogFade){
this.modalEl.addClass(options.transitionClass);
this.modalEl.removeClass(options.triggerClass);
}
Expand Down Expand Up @@ -113,7 +116,7 @@ dialogModule.provider("$dialog", function(){
}

this._loadResolves().then(function(locals) {
var $scope = locals.$scope = self.$scope = $rootScope.$new();
var $scope = locals.$scope = self.$scope = locals.$scope ? locals.$scope : $rootScope.$new();

self.modalEl.html(locals.$template);

Expand All @@ -124,10 +127,11 @@ dialogModule.provider("$dialog", function(){

$compile(self.modalEl)($scope);
self._addElementsToDom();
body.addClass(self.options.dialogOpenClass);

// trigger tranisitions
setTimeout(function(){
if(self.options.modalFade){ self.modalEl.addClass(self.options.triggerClass); }
if(self.options.dialogFade){ self.modalEl.addClass(self.options.triggerClass); }
if(self.options.backdropFade){ self.backdropEl.addClass(self.options.triggerClass); }
});

Expand All @@ -143,6 +147,7 @@ dialogModule.provider("$dialog", function(){
var self = this;
var fadingElements = this._getFadingElements();

body.removeClass(self.options.dialogOpenClass);
if(fadingElements.length > 0){
for (var i = fadingElements.length - 1; i >= 0; i--) {
$transition(fadingElements[i], removeTriggerClass).then(onCloseComplete);
Expand All @@ -165,7 +170,7 @@ dialogModule.provider("$dialog", function(){

Dialog.prototype._getFadingElements = function(){
var elements = [];
if(this.options.modalFade){
if(this.options.dialogFade){
elements.push(this.modalEl);
}
if(this.options.backdropFade){
Expand Down Expand Up @@ -194,13 +199,26 @@ dialogModule.provider("$dialog", function(){

Dialog.prototype._addElementsToDom = function(){
body.append(this.modalEl);
if(this.options.backdrop) { body.append(this.backdropEl); }

if(this.options.backdrop) {
if (activeBackdrops.value === 0) {
body.append(this.backdropEl);
}
activeBackdrops.value++;
}

this._open = true;
};

Dialog.prototype._removeElementsFromDom = function(){
this.modalEl.remove();
if(this.options.backdrop) { this.backdropEl.remove(); }

if(this.options.backdrop) {
activeBackdrops.value--;
if (activeBackdrops.value === 0) {
this.backdropEl.remove();
}
}
this._open = false;
};

Expand Down
2 changes: 1 addition & 1 deletion src/dialog/docs/demo.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<div class="row-fluid">
<div class="span6">
<label class="checkbox"><input type=checkbox ng-model="opts.backdrop">Show backdrop</label>
<label class="checkbox"><input type=checkbox ng-model="opts.modalFade">Fade modal dialog </label>
<label class="checkbox"><input type=checkbox ng-model="opts.dialogFade">Fade modal dialog </label>
<label class="checkbox"><input type=checkbox ng-disabled="!opts.backdrop" ng-model="opts.backdropFade">Fade Backdrop</label>
<hr>
<label class="checkbox"><input type=checkbox ng-model="opts.keyboard">Close on Escape</label>
Expand Down
10 changes: 5 additions & 5 deletions src/dialog/test/dialog.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ describe('Given ui.bootstrap.dialog', function(){

var openDialog = function(templateUrl, controller){
dialog.open(templateUrl, controller);
$rootScope.$apply();
$scope.$apply();
};

var closeDialog = function(result){
Expand Down Expand Up @@ -110,8 +110,8 @@ describe('Given ui.bootstrap.dialog', function(){
});
});

describe('modalClass:foo, backdropClass:bar', function(){
useDialogWithGlobalOption({modalClass: 'foo', backdropClass: 'bar'});
describe('dialogClass:foo, backdropClass:bar', function(){
useDialogWithGlobalOption({dialogClass: 'foo', backdropClass: 'bar'});

it('backdrop class should be changed', function(){
expect($document.find('body > div.bar').length).toBe(1);
Expand All @@ -123,8 +123,8 @@ describe('Given ui.bootstrap.dialog', function(){
});

/*
describe('modalFade:true, backdropFade:true', function(){
useDialogWithGlobalOption({modalFade:true, backdropFade:true});
describe('dialogFade:true, backdropFade:true', function(){
useDialogWithGlobalOption({dialogFade:true, backdropFade:true});
it('backdrop class should be changed', function(){
expect($document.find('body > div.modal.fade').length).toBe(1);
Expand Down
6 changes: 4 additions & 2 deletions src/modal/docs/demo.html
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
<div ng-controller="ModalDemoCtrl">
<button class="btn" ng-click="open()">Open me!</button>
<div modal="shouldBeOpen" close="close()">
<div modal="shouldBeOpen" close="close()" options="opts">
<div class="modal-header">
<h4>I'm a modal!</h4>
</div>
<div class="modal-body">
with some content...
<ul>
<li ng-repeat="item in items">{{item}}</li>
</ul>
</div>
<div class="modal-footer">
<button class="btn btn-warning cancel" ng-click="close()">Cancel</button>
Expand Down
28 changes: 18 additions & 10 deletions src/modal/docs/demo.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
var ModalDemoCtrl = function ($scope) {

$scope.open = function () {
$scope.shouldBeOpen = true;
};

$scope.close = function () {
$scope.closeMsg = 'I was closed at: ' + new Date();
$scope.shouldBeOpen = false;
};
var ModalDemoCtrl = function ($scope) {

$scope.open = function () {
$scope.shouldBeOpen = true;
};

$scope.close = function () {
$scope.closeMsg = 'I was closed at: ' + new Date();
$scope.shouldBeOpen = false;
};

$scope.items = ['item1', 'item2'];

$scope.opts = {
backdropFade: true,
dialogFade:true
};

};
6 changes: 5 additions & 1 deletion src/modal/docs/readme.md
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
Bootstrap's modal directive.
`modal` is a directive that reuses `$dialog` service to provide simple creation of modals that are already in your DOM without the hassle of creating partial views and controllers.

The directive shares `$dialog` global options.

For more information, see the [dialog readme](https://github.com/angular-ui/bootstrap/blob/master/src/dialog/README.md) on github.
83 changes: 27 additions & 56 deletions src/modal/modal.js
Original file line number Diff line number Diff line change
@@ -1,78 +1,49 @@
angular.module('ui.bootstrap.modal', [])
.constant('modalConfig', {
backdrop: true,
escape: true
})
.directive('modal', ['$parse', 'modalConfig', function($parse, modalConfig) {
angular.module('ui.bootstrap.modal', ['ui.bootstrap.dialog'])
.directive('modal', ['$parse', '$dialog', function($parse, $dialog) {
var backdropEl;
var body = angular.element(document.getElementsByTagName('body')[0]);
return {
restrict: 'EA',
terminal: true,
link: function(scope, elm, attrs) {
var opts = angular.extend({}, modalConfig, scope.$eval(attrs.uiOptions || attrs.bsOptions || attrs.options));
var opts = angular.extend({}, scope.$eval(attrs.uiOptions || attrs.bsOptions || attrs.options));
var shownExpr = attrs.modal || attrs.show;
var setClosed;

// Create a dialog with the template as the contents of the directive
// Add the current scope as the resolve in order to make the directive scope as a dialog controller scope
opts = angular.extend(opts, {
template: elm.html(),
resolve: { $scope: function() { return scope; } }
});
var dialog = $dialog.dialog(opts);

elm.remove();

if (attrs.close) {
setClosed = function() {
scope.$apply(attrs.close);
$parse(attrs.close)(scope);
};
} else {
setClosed = function() {
scope.$apply(function() {
$parse(shownExpr).assign(scope, false);
});
};
}
elm.addClass('modal');

if (opts.backdrop && !backdropEl) {
backdropEl = angular.element('<div class="modal-backdrop"></div>');
backdropEl.css('display','none');
body.append(backdropEl);
}

function setShown(shown) {
scope.$apply(function() {
model.assign(scope, shown);
});
}

function escapeClose(evt) {
if (evt.which === 27) { setClosed(); }
}
function clickClose() {
setClosed();
}

function close() {
if (opts.escape) { body.unbind('keyup', escapeClose); }
if (opts.backdrop) {
backdropEl.css('display', 'none').removeClass('in');
backdropEl.unbind('click', clickClose);
}
elm.css('display', 'none').removeClass('in');
body.removeClass('modal-open');
}
function open() {
if (opts.escape) { body.bind('keyup', escapeClose); }
if (opts.backdrop) {
backdropEl.css('display', 'block').addClass('in');
if(opts.backdrop != "static") {
backdropEl.bind('click', clickClose);
setClosed = function() {
if (angular.isFunction($parse(shownExpr).assign)) {
$parse(shownExpr).assign(scope, false);
}
}
elm.css('display', 'block').addClass('in');
body.addClass('modal-open');
};
}

scope.$watch(shownExpr, function(isShown, oldShown) {
if (isShown) {
open();
dialog.open().then(function(){
setClosed();
});
} else {
close();
//Make sure it is not opened
if (dialog.isOpen()){
dialog.close();
}
}
});
}
};
}]);
}]);
Loading

0 comments on commit ec796ec

Please sign in to comment.