From d563f21ac85062918b65952a4e4a1832e9dda701 Mon Sep 17 00:00:00 2001 From: Gino Heyman Date: Wed, 14 Nov 2012 21:37:55 +0100 Subject: [PATCH 1/3] feat(dialog): merged feature branch into master --- docs/dialog.html | 231 ++++++++++++++++++++++++++++ docs/docco.css | 192 +++++++++++++++++++++++ src/bootstrap.js | 28 ++++ src/dialog/README.md | 92 +++++++++++ src/dialog/demo/app.js | 51 +++++++ src/dialog/demo/index.html | 71 +++++++++ src/dialog/dialog.js | 267 ++++++++++++++++++++++++++++++++ src/dialog/test/dialog.js | 285 +++++++++++++++++++++++++++++++++++ template/dialog/message.html | 9 ++ 9 files changed, 1226 insertions(+) create mode 100644 docs/dialog.html create mode 100644 docs/docco.css create mode 100644 src/bootstrap.js create mode 100644 src/dialog/README.md create mode 100644 src/dialog/demo/app.js create mode 100644 src/dialog/demo/index.html create mode 100644 src/dialog/dialog.js create mode 100644 src/dialog/test/dialog.js create mode 100644 template/dialog/message.html diff --git a/docs/dialog.html b/docs/dialog.html new file mode 100644 index 0000000000..3265f044e5 --- /dev/null +++ b/docs/dialog.html @@ -0,0 +1,231 @@ + dialog.js

dialog.js

The $dialogProvider can be used to configure global defaults for your +$dialog service.

var dialogModule = angular.module('ui.bootstrap.dialog', []);
+
+dialogModule.controller('MessageBoxController', ['$scope', 'dialog', 'model', function($scope, dialog, model){
+  $scope.title = model.title;
+  $scope.message = model.message;
+  $scope.buttons = model.buttons;
+  $scope.close = function(res){
+    dialog.close(res);
+  };
+}]);
+
+dialogModule.provider("$dialog", function(){

The default options for all dialogs.

  var defaults = {
+    backdrop: true,
+    modalClass: '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
+    /* other options: template, templateUrl, controller */
+  };
+
+  var globalOptions = {};

The options({}) allows global configuration of all dialogs in the application.

+ +
 var app = angular.module('App', ['ui.bootstrap.dialog'], function($dialogProvider){
+   // don't close dialog when backdrop is clicked by default
+   $dialogProvider.options({backdropClick: false});
+ });
+
  this.options = function(value){
+    globalOptions = value;
+  };

Returns the actual $dialog service that is injected in controllers

  this.$get = ["$http", "$document", "$compile", "$rootScope", "$controller", "$templateCache", "$q", function ($http, $document, $compile, $rootScope, $controller, $templateCache, $q) {
+
+    var body = $document.find('body');
+
+    function createElement(clazz) {
+      var el = angular.element("<div>");
+      el.addClass(clazz);
+      return el;
+    }

The Dialog class represents a modal dialog. The dialog class can be invoked by providing an options object +containing at lest template or templateUrl and controller:

+ +
var d = new Dialog({templateUrl: 'foo.html', controller: 'BarController'});
+
+ +

Dialogs can also be created using templateUrl and controller as distinct arguments:

+ +
var d = new Dialog('path/to/dialog.html', MyDialogController);
+
    function Dialog(opts) {
+
+      var self = this, options = this.options = angular.extend({}, defaults, globalOptions, opts);
+
+      this.backdropEl = createElement(options.backdropClass);
+      if(options.backdropFade){
+        this.backdropEl.addClass(options.transitionClass);
+        this.backdropEl.removeClass(options.triggerClass);
+      }
+
+      this.modalEl = createElement(options.modalClass);
+      if(options.modalFade){
+        this.modalEl.addClass(options.transitionClass);
+        this.modalEl.removeClass(options.triggerClass);
+      }
+
+      this.handledEscapeKey = function(e) {
+        if (e.which === 27) {
+          self.close();
+          e.preventDefault();
+          self.$scope.$apply();
+        }
+      };
+
+      this.handleBackDropClick = function(e) {
+        self.close();
+        e.preventDefault();
+        self.$scope.$apply();
+      };
+    }

The isOpen() method returns wether the dialog is currently visible.

    Dialog.prototype.isOpen = function(){
+      return this._open;
+    };

The open(templateUrl, controller) method opens the dialog. +Use the templateUrl and controller arguments if specifying them at dialog creation time is not desired.

    Dialog.prototype.open = function(templateUrl, controller){
+      var self = this, options = this.options;
+
+      if(templateUrl){
+        options.templateUrl = templateUrl;
+      }
+      if(controller){
+        options.controller = controller;
+      }
+      
+      if(!(options.template || options.templateUrl)) {
+        throw new Error('Dialog.open expected template or templateUrl, neither found. Use options or open method to specify them.');
+      }
+
+      this._loadResolves().then(function(locals) {
+        var $scope = locals.$scope = self.$scope = $rootScope.$new();
+
+        self.modalEl.html(locals.$template);
+
+        if (self.options.controller) {
+          var ctrl = $controller(self.options.controller, locals);
+          self.modalEl.contents().data('ngControllerController', ctrl);
+        }
+
+        $compile(self.modalEl.contents())($scope);
+        self._addElementsToDom();

trigger tranisitions

        setTimeout(function(){
+          if(self.options.modalFade){ self.modalEl.addClass(self.options.triggerClass); }
+          if(self.options.backdropFade){ self.backdropEl.addClass(self.options.triggerClass); }
+        });
+
+        self._bindEvents();
+      });
+
+      this.deferred = $q.defer();
+      return this.deferred.promise;
+    };

closes the dialog and resolves the promise returned by the open method with the specified result.

    Dialog.prototype.close = function(result){
+      var self = this;
+      var fadingEl = this._getFirstFadingElement();
+
+      function transitionHandler(e) {
+        self.modalEl.unbind(angularUI.getTransitionEndEventName(), transitionHandler);
+        self._onCloseComplete(result);
+      }
+
+      if(fadingEl){
+        this.modalEl.bind(angularUI.getTransitionEndEventName(), transitionHandler);
+        
+        if(this.options.modalFade){
+          this.modalEl.removeClass(this.options.triggerClass);
+
+          if(this.options.backdropFade){
+            this.backdropEl.removeClass(this.options.triggerClass);
+          }
+          return;
+        }
+      }
+
+      this._onCloseComplete(result);
+    };
+
+    Dialog.prototype._getFirstFadingElement = function(){
+      return this.options.modalFade ? this.modalEl : this.options.backdropFade ? this.backdropEl : null;
+    };
+
+    Dialog.prototype._fadingEnabled = function(){
+      return this.options.modalFade || this.options.backdropFade;
+    };
+
+    Dialog.prototype._bindEvents = function() {
+      if(this.options.keyboard){ body.bind('keydown', this.handledEscapeKey); }
+      if(this.options.backdrop && this.options.backdropClick){ this.backdropEl.bind('click', this.handleBackDropClick); }
+    };
+
+    Dialog.prototype._unbindEvents = function() {
+      if(this.options.keyboard){ body.unbind('keydown', this.handledEscapeKey); }
+      if(this.options.backdrop && this.options.backdropClick){ this.backdropEl.unbind('click', this.handleBackDropClick); }
+    };
+
+    Dialog.prototype._onCloseComplete = function(result) {
+      this._removeElementsFromDom();
+      this._unbindEvents();
+
+      this.deferred.resolve(result);
+
+      if(this._fadingEnabled()){
+        this.$scope.$apply();
+      }
+    };
+
+    Dialog.prototype._addElementsToDom = function(){
+      body.append(this.modalEl);
+      if(this.options.backdrop) { body.append(this.backdropEl); }
+      this._open = true;
+    };
+
+    Dialog.prototype._removeElementsFromDom = function(){
+      this.modalEl.remove();
+      if(this.options.backdrop) { this.backdropEl.remove(); }
+      this._open = false;
+    };

Loads all options.resolve members to be used as locals for the controller associated with the dialog.

    Dialog.prototype._loadResolves = function(){
+      var values = [], keys = [], template, self = this;
+
+      if (template = this.options.template) {
+      } else if (template = this.options.templateUrl) {
+        template = $http.get(this.options.templateUrl, {cache:$templateCache})
+        .then(function(response) { return response.data; });
+      }
+
+      angular.forEach(this.options.resolve || [], function(value, key) {
+        keys.push(key);
+        values.push(value);
+      });
+
+      keys.push('$template');
+      values.push(template);
+
+      return $q.all(values).then(function(values) {
+        var locals = {};
+        angular.forEach(values, function(value, index) {
+          locals[keys[index]] = value;
+        });
+        locals.dialog = self;
+        return locals;
+      });
+    };

The actual $dialog service that is injected in controllers.

    return {

Creates a new Dialog with the specified options.

      dialog: function(opts){
+        return new Dialog(opts);
+      },

creates a new Dialog tied to the default message box template and controller.

+ +

Arguments title and message are rendered in the modal header and body sections respectively. +The buttons array holds an object with the following members for each button to include in the +modal footer section:

+ +
    +
  • result: the result to pass to the close method of the dialog when the button is clicked
  • +
  • label: the label of the button
  • +
  • cssClass: additional css class(es) to apply to the button for styling
  • +
      messageBox: function(title, message, buttons){
+        return new Dialog({templateUrl: 'template/dialog/message.html', controller: 'MessageBoxController', resolve: {model: {
+          title: title,
+          message: message,
+          buttons: buttons
+        }}});
+      }
+    };
+  }];
+});
+
+
\ No newline at end of file diff --git a/docs/docco.css b/docs/docco.css new file mode 100644 index 0000000000..04cc7ecb8a --- /dev/null +++ b/docs/docco.css @@ -0,0 +1,192 @@ +/*--------------------- Layout and Typography ----------------------------*/ +body { + font-family: 'Palatino Linotype', 'Book Antiqua', Palatino, FreeSerif, serif; + font-size: 15px; + line-height: 22px; + color: #252519; + margin: 0; padding: 0; +} +a { + color: #261a3b; +} + a:visited { + color: #261a3b; + } +p { + margin: 0 0 15px 0; +} +h1, h2, h3, h4, h5, h6 { + margin: 0px 0 15px 0; +} + h1 { + margin-top: 40px; + } +hr { + border: 0 none; + border-top: 1px solid #e5e5ee; + height: 1px; + margin: 20px 0; +} +#container { + position: relative; +} +#background { + position: fixed; + top: 0; left: 525px; right: 0; bottom: 0; + background: #f5f5ff; + border-left: 1px solid #e5e5ee; + z-index: -1; +} +#jump_to, #jump_page { + background: white; + -webkit-box-shadow: 0 0 25px #777; -moz-box-shadow: 0 0 25px #777; + -webkit-border-bottom-left-radius: 5px; -moz-border-radius-bottomleft: 5px; + font: 10px Arial; + text-transform: uppercase; + cursor: pointer; + text-align: right; +} +#jump_to, #jump_wrapper { + position: fixed; + right: 0; top: 0; + padding: 5px 10px; +} + #jump_wrapper { + padding: 0; + display: none; + } + #jump_to:hover #jump_wrapper { + display: block; + } + #jump_page { + padding: 5px 0 3px; + margin: 0 0 25px 25px; + } + #jump_page .source { + display: block; + padding: 5px 10px; + text-decoration: none; + border-top: 1px solid #eee; + } + #jump_page .source:hover { + background: #f5f5ff; + } + #jump_page .source:first-child { + } +table td { + border: 0; + outline: 0; +} + td.docs, th.docs { + max-width: 450px; + min-width: 450px; + min-height: 5px; + padding: 10px 25px 1px 50px; + overflow-x: hidden; + vertical-align: top; + text-align: left; + } + .docs pre { + margin: 15px 0 15px; + padding-left: 15px; + } + .docs p tt, .docs p code { + background: #f8f8ff; + border: 1px solid #dedede; + font-size: 12px; + padding: 0 0.2em; + } + .pilwrap { + position: relative; + } + .pilcrow { + font: 12px Arial; + text-decoration: none; + color: #454545; + position: absolute; + top: 3px; left: -20px; + padding: 1px 2px; + opacity: 0; + -webkit-transition: opacity 0.2s linear; + } + td.docs:hover .pilcrow { + opacity: 1; + } + td.code, th.code { + padding: 14px 15px 16px 25px; + width: 100%; + vertical-align: top; + background: #f5f5ff; + border-left: 1px solid #e5e5ee; + } + pre, tt, code { + font-size: 12px; line-height: 18px; + font-family: Menlo, Monaco, Consolas, "Lucida Console", monospace; + margin: 0; padding: 0; + } + + +/*---------------------- Syntax Highlighting -----------------------------*/ +td.linenos { background-color: #f0f0f0; padding-right: 10px; } +span.lineno { background-color: #f0f0f0; padding: 0 5px 0 5px; } +body .hll { background-color: #ffffcc } +body .c { color: #408080; font-style: italic } /* Comment */ +body .err { border: 1px solid #FF0000 } /* Error */ +body .k { color: #954121 } /* Keyword */ +body .o { color: #666666 } /* Operator */ +body .cm { color: #408080; font-style: italic } /* Comment.Multiline */ +body .cp { color: #BC7A00 } /* Comment.Preproc */ +body .c1 { color: #408080; font-style: italic } /* Comment.Single */ +body .cs { color: #408080; font-style: italic } /* Comment.Special */ +body .gd { color: #A00000 } /* Generic.Deleted */ +body .ge { font-style: italic } /* Generic.Emph */ +body .gr { color: #FF0000 } /* Generic.Error */ +body .gh { color: #000080; font-weight: bold } /* Generic.Heading */ +body .gi { color: #00A000 } /* Generic.Inserted */ +body .go { color: #808080 } /* Generic.Output */ +body .gp { color: #000080; font-weight: bold } /* Generic.Prompt */ +body .gs { font-weight: bold } /* Generic.Strong */ +body .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ +body .gt { color: #0040D0 } /* Generic.Traceback */ +body .kc { color: #954121 } /* Keyword.Constant */ +body .kd { color: #954121; font-weight: bold } /* Keyword.Declaration */ +body .kn { color: #954121; font-weight: bold } /* Keyword.Namespace */ +body .kp { color: #954121 } /* Keyword.Pseudo */ +body .kr { color: #954121; font-weight: bold } /* Keyword.Reserved */ +body .kt { color: #B00040 } /* Keyword.Type */ +body .m { color: #666666 } /* Literal.Number */ +body .s { color: #219161 } /* Literal.String */ +body .na { color: #7D9029 } /* Name.Attribute */ +body .nb { color: #954121 } /* Name.Builtin */ +body .nc { color: #0000FF; font-weight: bold } /* Name.Class */ +body .no { color: #880000 } /* Name.Constant */ +body .nd { color: #AA22FF } /* Name.Decorator */ +body .ni { color: #999999; font-weight: bold } /* Name.Entity */ +body .ne { color: #D2413A; font-weight: bold } /* Name.Exception */ +body .nf { color: #0000FF } /* Name.Function */ +body .nl { color: #A0A000 } /* Name.Label */ +body .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */ +body .nt { color: #954121; font-weight: bold } /* Name.Tag */ +body .nv { color: #19469D } /* Name.Variable */ +body .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */ +body .w { color: #bbbbbb } /* Text.Whitespace */ +body .mf { color: #666666 } /* Literal.Number.Float */ +body .mh { color: #666666 } /* Literal.Number.Hex */ +body .mi { color: #666666 } /* Literal.Number.Integer */ +body .mo { color: #666666 } /* Literal.Number.Oct */ +body .sb { color: #219161 } /* Literal.String.Backtick */ +body .sc { color: #219161 } /* Literal.String.Char */ +body .sd { color: #219161; font-style: italic } /* Literal.String.Doc */ +body .s2 { color: #219161 } /* Literal.String.Double */ +body .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */ +body .sh { color: #219161 } /* Literal.String.Heredoc */ +body .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */ +body .sx { color: #954121 } /* Literal.String.Other */ +body .sr { color: #BB6688 } /* Literal.String.Regex */ +body .s1 { color: #219161 } /* Literal.String.Single */ +body .ss { color: #19469D } /* Literal.String.Symbol */ +body .bp { color: #954121 } /* Name.Builtin.Pseudo */ +body .vc { color: #19469D } /* Name.Variable.Class */ +body .vg { color: #19469D } /* Name.Variable.Global */ +body .vi { color: #19469D } /* Name.Variable.Instance */ +body .il { color: #666666 } /* Literal.Number.Integer.Long */ \ No newline at end of file diff --git a/src/bootstrap.js b/src/bootstrap.js new file mode 100644 index 0000000000..d550663843 --- /dev/null +++ b/src/bootstrap.js @@ -0,0 +1,28 @@ +var angularUI = {}; + +angularUI.getTransitionEndEventName = (function(){ + + var transitionEndEventName; + + return function () { + if(transitionEndEventName) { + return transitionEndEventName; + } + + var el = document.createElement('trans'); + var transEndEventNames = { + 'WebkitTransition': 'webkitTransitionEnd', + 'MozTransition': 'transitionend', + 'OTransition': 'oTransitionEnd', + 'msTransition': 'MSTransitionEnd', + 'transition': 'transitionend' + }; + + for (var name in transEndEventNames){ + if (el.style[name] !== undefined) { + transitionEndEventName = transEndEventNames[name]; + } + } + return transitionEndEventName; + }; +})(); \ No newline at end of file diff --git a/src/dialog/README.md b/src/dialog/README.md new file mode 100644 index 0000000000..169fa0b15e --- /dev/null +++ b/src/dialog/README.md @@ -0,0 +1,92 @@ +# $dialogProvider (service in ui.bootstrap) + +## Description + +Used for configuring global options for dialogs. + +### Methods + +#### `options(opts)` + +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' +* `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' +* `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 +* `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 + +Example: + + var app = angular.module('App', ['ui.bootstrap.dialog'] , function($dialogProvider){ + $dialogProvider.options({backdropClick: false, modalFade: true}); + }); + +# $dialog service + +## Description + +Allows you to open dialogs from within you controller. + +### Methods + +#### `dialog([templateUrl[, controller]])` + +Creates a new dialog, optionally setting the `templateUrl`, and `controller` options. + +Example: + + app.controller('MainCtrl', function($dialog, $scope) { + $scope.openItemEditor = function(item){ + var d = $dialog.dialog({modalFade: false, resolve: {item: angular.copy(item) }}); + d.open('dialogs/item-editor.html', 'EditItemController'); + }; + }); + + // note that the resolved item as well as the dialog are injected in the dialog's controller + app.controller('EditItemController', ['$scope', 'dialog', 'item', function($scope, dialog, item){ + $scope.item = item; + $scope.submit = function(){ + dialog.close('ok'); + }; + }]); + +#### `message(title, message, buttons)` + +Opens a message box with the specified `title`, `message` ang a series of `buttons` can be provided, every button can specify: + +* `label`: the label of the button +* `result`: the result used to invoke the close method of the dialog +* `cssClass`: optinal, the CSS class (e.g. btn-primary) to apply to the button + +Example: + + app.controller('MainCtrl', function($dialog, $scope) { + $scope.deleteItem = function(item){ + var msgbox = $dialog.message('Delete Item', 'Are you sure?', [{label:'Yes, I'm sure, result: 'yes'},{label:'Nope', result: 'no'}]); + msgbox.open().then(function(result){ + if(result === 'yes') {deleteItem(item);} + }); + }; + }); + +## Dialog class + +The dialog object returned by the `$dialog` service methods `open` and `message`. + +### Methods + +#### `open` + +(Re)Opens the dialog and returns a promise. + +#### `close([result])` + +Closes the dialog. Optionally a result can be specified. The result is used to resolve the promise returned by the `open` method. + diff --git a/src/dialog/demo/app.js b/src/dialog/demo/app.js new file mode 100644 index 0000000000..d7cea71354 --- /dev/null +++ b/src/dialog/demo/app.js @@ -0,0 +1,51 @@ + +var demo = angular.module('DialogDemo', ['ui.bootstrap.dialog', 'template/dialog/message.html'], function(){}); + +demo.controller('DialogController', ['$scope', '$dialog', function($scope, $dialog){ + + var t = ''+ +''+ +''; + + $scope.dialogOptions = { + backdrop: true, + keyboard: true, + backdropClick: true, + template: t, + controller: 'TestDialogController' + }; + + $scope.msgbox = {}; + + $scope.open = function(){ + var d = $dialog.dialog($scope.dialogOptions); + d.open().then(function(result){ + if(result) { alert('dialog closed with result: ' + result); } + }); + }; + + $scope.messageBox = function(){ + var m = $dialog.messageBox( + $scope.msgbox.title || 'This is a message box', + $scope.msgbox.message || 'This is the message. Please click buttons below to confirm or dismiss.', + [ + {result:'cancel', label:'Cancel'}, + {result:'ok', label:'Ok', cssClass:'btn-primary'}]); + m.open().then(function(result){ + if(result) { alert('message box closed with result: ' + result); } + }); + }; +}]); + +demo.controller('TestDialogController',['$scope', 'dialog', function ($scope, dialog){ + $scope.d = dialog; + $scope.close = function(result){ + dialog.close(result); + }; +}]); \ No newline at end of file diff --git a/src/dialog/demo/index.html b/src/dialog/demo/index.html new file mode 100644 index 0000000000..b5e4a3840b --- /dev/null +++ b/src/dialog/demo/index.html @@ -0,0 +1,71 @@ + + + $dialogProvider demo + + + + + + + + + +
+
+
+ Dialog Options +

+ Change options at will and press button below +

+ + + +
+ + +
+ +
+
+
+ Message Box +
+
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+
+ +
+
+ + + \ No newline at end of file diff --git a/src/dialog/dialog.js b/src/dialog/dialog.js new file mode 100644 index 0000000000..6907889725 --- /dev/null +++ b/src/dialog/dialog.js @@ -0,0 +1,267 @@ +// The `$dialogProvider` can be used to configure global defaults for your +// `$dialog` service. +var dialogModule = angular.module('ui.bootstrap.dialog', ['ui.bootstrap.transition']); + +dialogModule.controller('MessageBoxController', ['$scope', 'dialog', 'model', function($scope, dialog, model){ + $scope.title = model.title; + $scope.message = model.message; + $scope.buttons = model.buttons; + $scope.close = function(res){ + dialog.close(res); + }; +}]); + +dialogModule.provider("$dialog", function(){ + + // The default options for all dialogs. + var defaults = { + backdrop: true, + modalClass: '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 + /* other options: template, templateUrl, controller */ + }; + + var globalOptions = {}; + + // The `options({})` allows global configuration of all dialogs in the application. + // + // var app = angular.module('App', ['ui.bootstrap.dialog'], function($dialogProvider){ + // // don't close dialog when backdrop is clicked by default + // $dialogProvider.options({backdropClick: false}); + // }); + this.options = function(value){ + globalOptions = value; + }; + + // Returns the actual `$dialog` service that is injected in controllers + this.$get = ["$http", "$document", "$compile", "$rootScope", "$controller", "$templateCache", "$q", "$transition", + function ($http, $document, $compile, $rootScope, $controller, $templateCache, $q, $transition) { + + var body = $document.find('body'); + + function createElement(clazz) { + var el = angular.element("
"); + el.addClass(clazz); + return el; + } + + // The `Dialog` class represents a modal dialog. The dialog class can be invoked by providing an options object + // containing at lest template or templateUrl and controller: + // + // var d = new Dialog({templateUrl: 'foo.html', controller: 'BarController'}); + // + // Dialogs can also be created using templateUrl and controller as distinct arguments: + // + // var d = new Dialog('path/to/dialog.html', MyDialogController); + function Dialog(opts) { + + var self = this, options = this.options = angular.extend({}, defaults, globalOptions, opts); + + this.backdropEl = createElement(options.backdropClass); + if(options.backdropFade){ + this.backdropEl.addClass(options.transitionClass); + this.backdropEl.removeClass(options.triggerClass); + } + + this.modalEl = createElement(options.modalClass); + if(options.modalFade){ + this.modalEl.addClass(options.transitionClass); + this.modalEl.removeClass(options.triggerClass); + } + + this.handledEscapeKey = function(e) { + if (e.which === 27) { + self.close(); + e.preventDefault(); + self.$scope.$apply(); + } + }; + + this.handleBackDropClick = function(e) { + self.close(); + e.preventDefault(); + self.$scope.$apply(); + }; + } + + // The `isOpen()` method returns wether the dialog is currently visible. + Dialog.prototype.isOpen = function(){ + return this._open; + }; + + // The `open(templateUrl, controller)` method opens the dialog. + // Use the `templateUrl` and `controller` arguments if specifying them at dialog creation time is not desired. + Dialog.prototype.open = function(templateUrl, controller){ + var self = this, options = this.options; + + if(templateUrl){ + options.templateUrl = templateUrl; + } + if(controller){ + options.controller = controller; + } + + if(!(options.template || options.templateUrl)) { + throw new Error('Dialog.open expected template or templateUrl, neither found. Use options or open method to specify them.'); + } + + this._loadResolves().then(function(locals) { + var $scope = locals.$scope = self.$scope = $rootScope.$new(); + + self.modalEl.html(locals.$template); + + if (self.options.controller) { + var ctrl = $controller(self.options.controller, locals); + self.modalEl.contents().data('ngControllerController', ctrl); + } + + $compile(self.modalEl.contents())($scope); + self._addElementsToDom(); + + // trigger tranisitions + setTimeout(function(){ + if(self.options.modalFade){ self.modalEl.addClass(self.options.triggerClass); } + if(self.options.backdropFade){ self.backdropEl.addClass(self.options.triggerClass); } + }); + + self._bindEvents(); + }); + + this.deferred = $q.defer(); + return this.deferred.promise; + }; + + // closes the dialog and resolves the promise returned by the `open` method with the specified result. + Dialog.prototype.close = function(result){ + var self = this; + var fadingElements = this._getFadingElements(); + + if(fadingElements.length > 0){ + for (var i = fadingElements.length - 1; i >= 0; i--) { + $transition(fadingElements[i], removeTriggerClass).then(onCloseComplete); + } + return; + } + + this._onCloseComplete(result); + + function removeTriggerClass(el){ + el.removeClass(self.options.triggerClass); + } + + function onCloseComplete(){ + if(self._open){ + self._onCloseComplete(result); + } + } + }; + + Dialog.prototype._getFadingElements = function(){ + var elements = []; + if(this.options.modalFade){ + elements.push(this.modalEl); + } + if(this.options.backdropFade){ + elements.push(this.backdropEl); + } + + return elements; + }; + + Dialog.prototype._fadingEnabled = function(){ + return this.options.modalFade || this.options.backdropFade; + }; + + Dialog.prototype._bindEvents = function() { + if(this.options.keyboard){ body.bind('keydown', this.handledEscapeKey); } + if(this.options.backdrop && this.options.backdropClick){ this.backdropEl.bind('click', this.handleBackDropClick); } + }; + + Dialog.prototype._unbindEvents = function() { + if(this.options.keyboard){ body.unbind('keydown', this.handledEscapeKey); } + if(this.options.backdrop && this.options.backdropClick){ this.backdropEl.unbind('click', this.handleBackDropClick); } + }; + + Dialog.prototype._onCloseComplete = function(result) { + this._removeElementsFromDom(); + this._unbindEvents(); + + this.deferred.resolve(result); + + if(this._fadingEnabled()){ + this.$scope.$apply(); + } + }; + + Dialog.prototype._addElementsToDom = function(){ + body.append(this.modalEl); + if(this.options.backdrop) { body.append(this.backdropEl); } + this._open = true; + }; + + Dialog.prototype._removeElementsFromDom = function(){ + this.modalEl.remove(); + if(this.options.backdrop) { this.backdropEl.remove(); } + this._open = false; + }; + + // Loads all `options.resolve` members to be used as locals for the controller associated with the dialog. + Dialog.prototype._loadResolves = function(){ + var values = [], keys = [], template, self = this; + + if (template = this.options.template) { + } else if (template = this.options.templateUrl) { + template = $http.get(this.options.templateUrl, {cache:$templateCache}) + .then(function(response) { return response.data; }); + } + + angular.forEach(this.options.resolve || [], function(value, key) { + keys.push(key); + values.push(value); + }); + + keys.push('$template'); + values.push(template); + + return $q.all(values).then(function(values) { + var locals = {}; + angular.forEach(values, function(value, index) { + locals[keys[index]] = value; + }); + locals.dialog = self; + return locals; + }); + }; + + // The actual `$dialog` service that is injected in controllers. + return { + // Creates a new `Dialog` with the specified options. + dialog: function(opts){ + return new Dialog(opts); + }, + // creates a new `Dialog` tied to the default message box template and controller. + // + // Arguments `title` and `message` are rendered in the modal header and body sections respectively. + // The `buttons` array holds an object with the following members for each button to include in the + // modal footer section: + // + // * `result`: the result to pass to the `close` method of the dialog when the button is clicked + // * `label`: the label of the button + // * `cssClass`: additional css class(es) to apply to the button for styling + messageBox: function(title, message, buttons){ + return new Dialog({templateUrl: 'template/dialog/message.html', controller: 'MessageBoxController', resolve: {model: { + title: title, + message: message, + buttons: buttons + }}}); + } + }; + }]; +}); diff --git a/src/dialog/test/dialog.js b/src/dialog/test/dialog.js new file mode 100644 index 0000000000..f6d8493bc7 --- /dev/null +++ b/src/dialog/test/dialog.js @@ -0,0 +1,285 @@ +describe('Given ui.bootstrap.dialog', function(){ + + var $document, $compile, $scope, $rootScope, $dialog, q, provider; + var template = '
I\'m a template
'; + + beforeEach(module('ui.bootstrap.dialog')); + beforeEach(module('template/dialog/message.html')); + + beforeEach(function(){ + module(function($dialogProvider){ + provider = $dialogProvider; + }); + inject(function(_$document_, _$compile_, _$rootScope_, _$dialog_, _$q_){ + $document = _$document_; + $compile = _$compile_; + $scope = _$rootScope_.$new(); + $rootScope = _$rootScope_; + $dialog = _$dialog_; + q = _$q_; + }); + }); + + // clean-up after ourselves + afterEach(function(){ + closeDialog(); + clearGlobalOptions(); + }); + + it('provider service should be injected', function(){ + expect(provider).toBeDefined(); + }); + + it('dialog service should be injected', function(){ + expect($dialog).toBeDefined(); + }); + + var dialog; + + var createDialog = function(opts){ + dialog = $dialog.dialog(opts); + }; + + var openDialog = function(templateUrl, controller){ + dialog.open(templateUrl, controller); + $rootScope.$apply(); + }; + + var closeDialog = function(result){ + if(dialog){ + dialog.close(result); + $rootScope.$apply(); + } + }; + + var setGlobalOptions = function(opts){ + provider.options(opts); + }; + + var clearGlobalOptions = function(){ + provider.options({}); + }; + + var dialogShouldBeClosed = function(){ + it('should not include a backdrop in the DOM', function(){ + expect($document.find('body > div.modal-backdrop').length).toBe(0); + }); + + it('should not include the modal in the DOM', function(){ + expect($document.find('body > div.modal').length).toBe(0); + }); + + it('should return false for isOpen()', function(){ + expect(dialog.isOpen()).toBe(false); + }); + }; + + var dialogShouldBeOpen = function(){ + it('the dialog.isOpen() should be true', function(){ + expect(dialog.isOpen()).toBe(true); + }); + + it('the backdrop should be displayed', function(){ + expect($document.find('body > div.modal-backdrop').css('display')).toBe('block'); + }); + + it('the modal should be displayed', function(){ + expect($document.find('body > div.modal').css('display')).toBe('block'); + }); + }; + + describe('Given global option', function(){ + + var useDialogWithGlobalOption = function(opts){ + beforeEach(function(){ + setGlobalOptions(opts); + createDialog({template:template}); + openDialog(); + }); + }; + + describe('backdrop:false', function(){ + useDialogWithGlobalOption({backdrop: false}); + + it('should not include a backdrop in the DOM', function(){ + expect($document.find('body > div.modal-backdrop').length).toBe(0); + }); + + it('should include the modal in the DOM', function(){ + expect($document.find('body > div.modal').length).toBe(1); + }); + }); + + describe('modalClass:foo, backdropClass:bar', function(){ + useDialogWithGlobalOption({modalClass: 'foo', backdropClass: 'bar'}); + + it('backdrop class should be changed', function(){ + expect($document.find('body > div.bar').length).toBe(1); + }); + + it('the modal should be change', function(){ + expect($document.find('body > div.foo').length).toBe(1); + }); + }); + + /* + describe('modalFade:true, backdropFade:true', function(){ + useDialogWithGlobalOption({modalFade:true, backdropFade:true}); + + it('backdrop class should be changed', function(){ + expect($document.find('body > div.modal.fade').length).toBe(1); + }); + + it('the modal should be change', function(){ + expect($document.find('body > div.modal-backdrop.fade').length).toBe(1); + }); + });*/ + }); + + describe('Opening a dialog', function(){ + + beforeEach(function(){ + createDialog({template:template}); + openDialog(); + }); + + dialogShouldBeOpen(); + }); + + describe('When opening a dialog with a controller', function(){ + + var resolvedDialog; + function Ctrl(dialog){ + resolvedDialog = dialog; + } + + beforeEach(function(){ + createDialog({template:template, controller: Ctrl}); + openDialog(); + }); + + dialogShouldBeOpen(); + + it('should inject the current dialog in the controller', function(){ + expect(resolvedDialog).toBe(dialog); + }); + }); + + describe('When opening a dialog with resolves', function(){ + + var resolvedFoo, resolvedBar, deferred; + function Ctrl(foo, bar){ + resolvedFoo = foo; + resolvedBar = bar; + } + + beforeEach(function(){ + deferred = q.defer(); + createDialog({template:template, resolve: {foo: 'foo', bar: deferred.promise}, controller: Ctrl}); + deferred.resolve('bar'); + openDialog(); + }); + + dialogShouldBeOpen(); + + it('should inject resolved promises in the controller', function(){ + expect(resolvedBar).toBe('bar'); + }); + + it('should inject simple values in the controller', function(){ + expect(resolvedFoo).toBe('foo'); + }); + }); + + describe('when closing a dialog', function(){ + + beforeEach(function(){ + createDialog({template:template}); + openDialog(); + closeDialog(); + }); + + dialogShouldBeClosed(); + + describe('When opening it again', function(){ + beforeEach(function(){ + expect($document.find('body > div.modal-backdrop').length).toBe(0); + openDialog(); + }); + + dialogShouldBeOpen(); + }); + }); + + describe('when closing a dialog with a result', function(){ + var res; + beforeEach(function(){ + createDialog({template:template}); + dialog.open().then(function(result){ res = result; }); + $rootScope.$apply(); + + closeDialog('the result'); + }); + + dialogShouldBeClosed(); + + it('should call the then method with the specified result', function(){ + expect(res).toBe('the result'); + }); + }); + + describe('when closing a dialog with backdrop click', function(){ + beforeEach(function(){ + createDialog({template:'foo'}); + openDialog(); + $document.find('body > div.modal-backdrop').click(); + }); + + dialogShouldBeClosed(); + }); + + describe('when closing a dialog with escape key', function(){ + beforeEach(function(){ + createDialog({template:'foo'}); + openDialog(); + var e = $.Event('keydown'); + e.which = 27; + $document.find('body').trigger(e); + }); + + dialogShouldBeClosed(); + }); + + describe('When opening a dialog with a template url', function(){ + + beforeEach(function(){ + createDialog({templateUrl:'template/dialog/message.html'}); + openDialog(); + }); + + dialogShouldBeOpen(); + }); + + describe('When opening a dialog by passing template and controller to open method', function(){ + + var controllerIsCreated; + function Controller($scope, dialog){ + controllerIsCreated = true; + } + + beforeEach(function(){ + createDialog({templateUrl:'this/will/not/be/used.html', controller: 'foo'}); + openDialog('template/dialog/message.html', Controller); + }); + + dialogShouldBeOpen(); + + it('should used the specified controller', function(){ + expect(controllerIsCreated).toBe(true); + }); + + it('should use the specified template', function(){ + expect($document.find('body > div.modal > div.modal-header').length).toBe(1); + }); + }); +}); diff --git a/template/dialog/message.html b/template/dialog/message.html new file mode 100644 index 0000000000..062c820151 --- /dev/null +++ b/template/dialog/message.html @@ -0,0 +1,9 @@ + + + From 9f27f79c8caf71ed9f47d8acc637eaa86cf0ab74 Mon Sep 17 00:00:00 2001 From: Gino Heyman Date: Thu, 3 Jan 2013 15:10:29 +0100 Subject: [PATCH 2/3] feat(dialog) removed obsolete files and added demo page files removed docco /docs files and /src/bootstrap.js and added /src/dialog/docs files for the demo page. --- docs/dialog.html | 231 ------------------------------------- docs/docco.css | 192 ------------------------------ src/bootstrap.js | 28 ----- src/dialog/demo/app.js | 51 -------- src/dialog/demo/index.html | 71 ------------ src/dialog/docs/demo.html | 39 +++++++ src/dialog/docs/demo.js | 50 ++++++++ src/dialog/docs/readme.md | 6 + 8 files changed, 95 insertions(+), 573 deletions(-) delete mode 100644 docs/dialog.html delete mode 100644 docs/docco.css delete mode 100644 src/bootstrap.js delete mode 100644 src/dialog/demo/app.js delete mode 100644 src/dialog/demo/index.html create mode 100644 src/dialog/docs/demo.html create mode 100644 src/dialog/docs/demo.js create mode 100644 src/dialog/docs/readme.md diff --git a/docs/dialog.html b/docs/dialog.html deleted file mode 100644 index 3265f044e5..0000000000 --- a/docs/dialog.html +++ /dev/null @@ -1,231 +0,0 @@ - dialog.js

dialog.js

The $dialogProvider can be used to configure global defaults for your -$dialog service.

var dialogModule = angular.module('ui.bootstrap.dialog', []);
-
-dialogModule.controller('MessageBoxController', ['$scope', 'dialog', 'model', function($scope, dialog, model){
-  $scope.title = model.title;
-  $scope.message = model.message;
-  $scope.buttons = model.buttons;
-  $scope.close = function(res){
-    dialog.close(res);
-  };
-}]);
-
-dialogModule.provider("$dialog", function(){

The default options for all dialogs.

  var defaults = {
-    backdrop: true,
-    modalClass: '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
-    /* other options: template, templateUrl, controller */
-  };
-
-  var globalOptions = {};

The options({}) allows global configuration of all dialogs in the application.

- -
 var app = angular.module('App', ['ui.bootstrap.dialog'], function($dialogProvider){
-   // don't close dialog when backdrop is clicked by default
-   $dialogProvider.options({backdropClick: false});
- });
-
  this.options = function(value){
-    globalOptions = value;
-  };

Returns the actual $dialog service that is injected in controllers

  this.$get = ["$http", "$document", "$compile", "$rootScope", "$controller", "$templateCache", "$q", function ($http, $document, $compile, $rootScope, $controller, $templateCache, $q) {
-
-    var body = $document.find('body');
-
-    function createElement(clazz) {
-      var el = angular.element("<div>");
-      el.addClass(clazz);
-      return el;
-    }

The Dialog class represents a modal dialog. The dialog class can be invoked by providing an options object -containing at lest template or templateUrl and controller:

- -
var d = new Dialog({templateUrl: 'foo.html', controller: 'BarController'});
-
- -

Dialogs can also be created using templateUrl and controller as distinct arguments:

- -
var d = new Dialog('path/to/dialog.html', MyDialogController);
-
    function Dialog(opts) {
-
-      var self = this, options = this.options = angular.extend({}, defaults, globalOptions, opts);
-
-      this.backdropEl = createElement(options.backdropClass);
-      if(options.backdropFade){
-        this.backdropEl.addClass(options.transitionClass);
-        this.backdropEl.removeClass(options.triggerClass);
-      }
-
-      this.modalEl = createElement(options.modalClass);
-      if(options.modalFade){
-        this.modalEl.addClass(options.transitionClass);
-        this.modalEl.removeClass(options.triggerClass);
-      }
-
-      this.handledEscapeKey = function(e) {
-        if (e.which === 27) {
-          self.close();
-          e.preventDefault();
-          self.$scope.$apply();
-        }
-      };
-
-      this.handleBackDropClick = function(e) {
-        self.close();
-        e.preventDefault();
-        self.$scope.$apply();
-      };
-    }

The isOpen() method returns wether the dialog is currently visible.

    Dialog.prototype.isOpen = function(){
-      return this._open;
-    };

The open(templateUrl, controller) method opens the dialog. -Use the templateUrl and controller arguments if specifying them at dialog creation time is not desired.

    Dialog.prototype.open = function(templateUrl, controller){
-      var self = this, options = this.options;
-
-      if(templateUrl){
-        options.templateUrl = templateUrl;
-      }
-      if(controller){
-        options.controller = controller;
-      }
-      
-      if(!(options.template || options.templateUrl)) {
-        throw new Error('Dialog.open expected template or templateUrl, neither found. Use options or open method to specify them.');
-      }
-
-      this._loadResolves().then(function(locals) {
-        var $scope = locals.$scope = self.$scope = $rootScope.$new();
-
-        self.modalEl.html(locals.$template);
-
-        if (self.options.controller) {
-          var ctrl = $controller(self.options.controller, locals);
-          self.modalEl.contents().data('ngControllerController', ctrl);
-        }
-
-        $compile(self.modalEl.contents())($scope);
-        self._addElementsToDom();

trigger tranisitions

        setTimeout(function(){
-          if(self.options.modalFade){ self.modalEl.addClass(self.options.triggerClass); }
-          if(self.options.backdropFade){ self.backdropEl.addClass(self.options.triggerClass); }
-        });
-
-        self._bindEvents();
-      });
-
-      this.deferred = $q.defer();
-      return this.deferred.promise;
-    };

closes the dialog and resolves the promise returned by the open method with the specified result.

    Dialog.prototype.close = function(result){
-      var self = this;
-      var fadingEl = this._getFirstFadingElement();
-
-      function transitionHandler(e) {
-        self.modalEl.unbind(angularUI.getTransitionEndEventName(), transitionHandler);
-        self._onCloseComplete(result);
-      }
-
-      if(fadingEl){
-        this.modalEl.bind(angularUI.getTransitionEndEventName(), transitionHandler);
-        
-        if(this.options.modalFade){
-          this.modalEl.removeClass(this.options.triggerClass);
-
-          if(this.options.backdropFade){
-            this.backdropEl.removeClass(this.options.triggerClass);
-          }
-          return;
-        }
-      }
-
-      this._onCloseComplete(result);
-    };
-
-    Dialog.prototype._getFirstFadingElement = function(){
-      return this.options.modalFade ? this.modalEl : this.options.backdropFade ? this.backdropEl : null;
-    };
-
-    Dialog.prototype._fadingEnabled = function(){
-      return this.options.modalFade || this.options.backdropFade;
-    };
-
-    Dialog.prototype._bindEvents = function() {
-      if(this.options.keyboard){ body.bind('keydown', this.handledEscapeKey); }
-      if(this.options.backdrop && this.options.backdropClick){ this.backdropEl.bind('click', this.handleBackDropClick); }
-    };
-
-    Dialog.prototype._unbindEvents = function() {
-      if(this.options.keyboard){ body.unbind('keydown', this.handledEscapeKey); }
-      if(this.options.backdrop && this.options.backdropClick){ this.backdropEl.unbind('click', this.handleBackDropClick); }
-    };
-
-    Dialog.prototype._onCloseComplete = function(result) {
-      this._removeElementsFromDom();
-      this._unbindEvents();
-
-      this.deferred.resolve(result);
-
-      if(this._fadingEnabled()){
-        this.$scope.$apply();
-      }
-    };
-
-    Dialog.prototype._addElementsToDom = function(){
-      body.append(this.modalEl);
-      if(this.options.backdrop) { body.append(this.backdropEl); }
-      this._open = true;
-    };
-
-    Dialog.prototype._removeElementsFromDom = function(){
-      this.modalEl.remove();
-      if(this.options.backdrop) { this.backdropEl.remove(); }
-      this._open = false;
-    };

Loads all options.resolve members to be used as locals for the controller associated with the dialog.

    Dialog.prototype._loadResolves = function(){
-      var values = [], keys = [], template, self = this;
-
-      if (template = this.options.template) {
-      } else if (template = this.options.templateUrl) {
-        template = $http.get(this.options.templateUrl, {cache:$templateCache})
-        .then(function(response) { return response.data; });
-      }
-
-      angular.forEach(this.options.resolve || [], function(value, key) {
-        keys.push(key);
-        values.push(value);
-      });
-
-      keys.push('$template');
-      values.push(template);
-
-      return $q.all(values).then(function(values) {
-        var locals = {};
-        angular.forEach(values, function(value, index) {
-          locals[keys[index]] = value;
-        });
-        locals.dialog = self;
-        return locals;
-      });
-    };

The actual $dialog service that is injected in controllers.

    return {

Creates a new Dialog with the specified options.

      dialog: function(opts){
-        return new Dialog(opts);
-      },

creates a new Dialog tied to the default message box template and controller.

- -

Arguments title and message are rendered in the modal header and body sections respectively. -The buttons array holds an object with the following members for each button to include in the -modal footer section:

- -
    -
  • result: the result to pass to the close method of the dialog when the button is clicked
  • -
  • label: the label of the button
  • -
  • cssClass: additional css class(es) to apply to the button for styling
  • -
      messageBox: function(title, message, buttons){
-        return new Dialog({templateUrl: 'template/dialog/message.html', controller: 'MessageBoxController', resolve: {model: {
-          title: title,
-          message: message,
-          buttons: buttons
-        }}});
-      }
-    };
-  }];
-});
-
-
\ No newline at end of file diff --git a/docs/docco.css b/docs/docco.css deleted file mode 100644 index 04cc7ecb8a..0000000000 --- a/docs/docco.css +++ /dev/null @@ -1,192 +0,0 @@ -/*--------------------- Layout and Typography ----------------------------*/ -body { - font-family: 'Palatino Linotype', 'Book Antiqua', Palatino, FreeSerif, serif; - font-size: 15px; - line-height: 22px; - color: #252519; - margin: 0; padding: 0; -} -a { - color: #261a3b; -} - a:visited { - color: #261a3b; - } -p { - margin: 0 0 15px 0; -} -h1, h2, h3, h4, h5, h6 { - margin: 0px 0 15px 0; -} - h1 { - margin-top: 40px; - } -hr { - border: 0 none; - border-top: 1px solid #e5e5ee; - height: 1px; - margin: 20px 0; -} -#container { - position: relative; -} -#background { - position: fixed; - top: 0; left: 525px; right: 0; bottom: 0; - background: #f5f5ff; - border-left: 1px solid #e5e5ee; - z-index: -1; -} -#jump_to, #jump_page { - background: white; - -webkit-box-shadow: 0 0 25px #777; -moz-box-shadow: 0 0 25px #777; - -webkit-border-bottom-left-radius: 5px; -moz-border-radius-bottomleft: 5px; - font: 10px Arial; - text-transform: uppercase; - cursor: pointer; - text-align: right; -} -#jump_to, #jump_wrapper { - position: fixed; - right: 0; top: 0; - padding: 5px 10px; -} - #jump_wrapper { - padding: 0; - display: none; - } - #jump_to:hover #jump_wrapper { - display: block; - } - #jump_page { - padding: 5px 0 3px; - margin: 0 0 25px 25px; - } - #jump_page .source { - display: block; - padding: 5px 10px; - text-decoration: none; - border-top: 1px solid #eee; - } - #jump_page .source:hover { - background: #f5f5ff; - } - #jump_page .source:first-child { - } -table td { - border: 0; - outline: 0; -} - td.docs, th.docs { - max-width: 450px; - min-width: 450px; - min-height: 5px; - padding: 10px 25px 1px 50px; - overflow-x: hidden; - vertical-align: top; - text-align: left; - } - .docs pre { - margin: 15px 0 15px; - padding-left: 15px; - } - .docs p tt, .docs p code { - background: #f8f8ff; - border: 1px solid #dedede; - font-size: 12px; - padding: 0 0.2em; - } - .pilwrap { - position: relative; - } - .pilcrow { - font: 12px Arial; - text-decoration: none; - color: #454545; - position: absolute; - top: 3px; left: -20px; - padding: 1px 2px; - opacity: 0; - -webkit-transition: opacity 0.2s linear; - } - td.docs:hover .pilcrow { - opacity: 1; - } - td.code, th.code { - padding: 14px 15px 16px 25px; - width: 100%; - vertical-align: top; - background: #f5f5ff; - border-left: 1px solid #e5e5ee; - } - pre, tt, code { - font-size: 12px; line-height: 18px; - font-family: Menlo, Monaco, Consolas, "Lucida Console", monospace; - margin: 0; padding: 0; - } - - -/*---------------------- Syntax Highlighting -----------------------------*/ -td.linenos { background-color: #f0f0f0; padding-right: 10px; } -span.lineno { background-color: #f0f0f0; padding: 0 5px 0 5px; } -body .hll { background-color: #ffffcc } -body .c { color: #408080; font-style: italic } /* Comment */ -body .err { border: 1px solid #FF0000 } /* Error */ -body .k { color: #954121 } /* Keyword */ -body .o { color: #666666 } /* Operator */ -body .cm { color: #408080; font-style: italic } /* Comment.Multiline */ -body .cp { color: #BC7A00 } /* Comment.Preproc */ -body .c1 { color: #408080; font-style: italic } /* Comment.Single */ -body .cs { color: #408080; font-style: italic } /* Comment.Special */ -body .gd { color: #A00000 } /* Generic.Deleted */ -body .ge { font-style: italic } /* Generic.Emph */ -body .gr { color: #FF0000 } /* Generic.Error */ -body .gh { color: #000080; font-weight: bold } /* Generic.Heading */ -body .gi { color: #00A000 } /* Generic.Inserted */ -body .go { color: #808080 } /* Generic.Output */ -body .gp { color: #000080; font-weight: bold } /* Generic.Prompt */ -body .gs { font-weight: bold } /* Generic.Strong */ -body .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ -body .gt { color: #0040D0 } /* Generic.Traceback */ -body .kc { color: #954121 } /* Keyword.Constant */ -body .kd { color: #954121; font-weight: bold } /* Keyword.Declaration */ -body .kn { color: #954121; font-weight: bold } /* Keyword.Namespace */ -body .kp { color: #954121 } /* Keyword.Pseudo */ -body .kr { color: #954121; font-weight: bold } /* Keyword.Reserved */ -body .kt { color: #B00040 } /* Keyword.Type */ -body .m { color: #666666 } /* Literal.Number */ -body .s { color: #219161 } /* Literal.String */ -body .na { color: #7D9029 } /* Name.Attribute */ -body .nb { color: #954121 } /* Name.Builtin */ -body .nc { color: #0000FF; font-weight: bold } /* Name.Class */ -body .no { color: #880000 } /* Name.Constant */ -body .nd { color: #AA22FF } /* Name.Decorator */ -body .ni { color: #999999; font-weight: bold } /* Name.Entity */ -body .ne { color: #D2413A; font-weight: bold } /* Name.Exception */ -body .nf { color: #0000FF } /* Name.Function */ -body .nl { color: #A0A000 } /* Name.Label */ -body .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */ -body .nt { color: #954121; font-weight: bold } /* Name.Tag */ -body .nv { color: #19469D } /* Name.Variable */ -body .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */ -body .w { color: #bbbbbb } /* Text.Whitespace */ -body .mf { color: #666666 } /* Literal.Number.Float */ -body .mh { color: #666666 } /* Literal.Number.Hex */ -body .mi { color: #666666 } /* Literal.Number.Integer */ -body .mo { color: #666666 } /* Literal.Number.Oct */ -body .sb { color: #219161 } /* Literal.String.Backtick */ -body .sc { color: #219161 } /* Literal.String.Char */ -body .sd { color: #219161; font-style: italic } /* Literal.String.Doc */ -body .s2 { color: #219161 } /* Literal.String.Double */ -body .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */ -body .sh { color: #219161 } /* Literal.String.Heredoc */ -body .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */ -body .sx { color: #954121 } /* Literal.String.Other */ -body .sr { color: #BB6688 } /* Literal.String.Regex */ -body .s1 { color: #219161 } /* Literal.String.Single */ -body .ss { color: #19469D } /* Literal.String.Symbol */ -body .bp { color: #954121 } /* Name.Builtin.Pseudo */ -body .vc { color: #19469D } /* Name.Variable.Class */ -body .vg { color: #19469D } /* Name.Variable.Global */ -body .vi { color: #19469D } /* Name.Variable.Instance */ -body .il { color: #666666 } /* Literal.Number.Integer.Long */ \ No newline at end of file diff --git a/src/bootstrap.js b/src/bootstrap.js deleted file mode 100644 index d550663843..0000000000 --- a/src/bootstrap.js +++ /dev/null @@ -1,28 +0,0 @@ -var angularUI = {}; - -angularUI.getTransitionEndEventName = (function(){ - - var transitionEndEventName; - - return function () { - if(transitionEndEventName) { - return transitionEndEventName; - } - - var el = document.createElement('trans'); - var transEndEventNames = { - 'WebkitTransition': 'webkitTransitionEnd', - 'MozTransition': 'transitionend', - 'OTransition': 'oTransitionEnd', - 'msTransition': 'MSTransitionEnd', - 'transition': 'transitionend' - }; - - for (var name in transEndEventNames){ - if (el.style[name] !== undefined) { - transitionEndEventName = transEndEventNames[name]; - } - } - return transitionEndEventName; - }; -})(); \ No newline at end of file diff --git a/src/dialog/demo/app.js b/src/dialog/demo/app.js deleted file mode 100644 index d7cea71354..0000000000 --- a/src/dialog/demo/app.js +++ /dev/null @@ -1,51 +0,0 @@ - -var demo = angular.module('DialogDemo', ['ui.bootstrap.dialog', 'template/dialog/message.html'], function(){}); - -demo.controller('DialogController', ['$scope', '$dialog', function($scope, $dialog){ - - var t = ''+ -''+ -''; - - $scope.dialogOptions = { - backdrop: true, - keyboard: true, - backdropClick: true, - template: t, - controller: 'TestDialogController' - }; - - $scope.msgbox = {}; - - $scope.open = function(){ - var d = $dialog.dialog($scope.dialogOptions); - d.open().then(function(result){ - if(result) { alert('dialog closed with result: ' + result); } - }); - }; - - $scope.messageBox = function(){ - var m = $dialog.messageBox( - $scope.msgbox.title || 'This is a message box', - $scope.msgbox.message || 'This is the message. Please click buttons below to confirm or dismiss.', - [ - {result:'cancel', label:'Cancel'}, - {result:'ok', label:'Ok', cssClass:'btn-primary'}]); - m.open().then(function(result){ - if(result) { alert('message box closed with result: ' + result); } - }); - }; -}]); - -demo.controller('TestDialogController',['$scope', 'dialog', function ($scope, dialog){ - $scope.d = dialog; - $scope.close = function(result){ - dialog.close(result); - }; -}]); \ No newline at end of file diff --git a/src/dialog/demo/index.html b/src/dialog/demo/index.html deleted file mode 100644 index b5e4a3840b..0000000000 --- a/src/dialog/demo/index.html +++ /dev/null @@ -1,71 +0,0 @@ - - - $dialogProvider demo - - - - - - - - - -
-
-
- Dialog Options -

- Change options at will and press button below -

- - - -
- - -
- -
-
-
- Message Box -
-
- -
- -
-
-
-
-
- -
- -
-
-
-
- -
-
- - - \ No newline at end of file diff --git a/src/dialog/docs/demo.html b/src/dialog/docs/demo.html new file mode 100644 index 0000000000..595118639a --- /dev/null +++ b/src/dialog/docs/demo.html @@ -0,0 +1,39 @@ +
+
+ + + +
+ + +
+
+

+ Change options at will and press the open dialog button below! +

+

+ +

+

+ Alternatively open a simple message box: +

+

+ +

+
+
diff --git a/src/dialog/docs/demo.js b/src/dialog/docs/demo.js new file mode 100644 index 0000000000..c7486add8c --- /dev/null +++ b/src/dialog/docs/demo.js @@ -0,0 +1,50 @@ +function DialogDemoCtrl($scope, $dialog){ + + // Inlined template for demo + var t = ''+ + ''+ + ''; + + $scope.opts = { + backdrop: true, + keyboard: true, + backdropClick: true, + template: t, // OR: templateUrl: 'path/to/view.html', + controller: 'TestDialogController' + }; + + $scope.openDialog = function(){ + var d = $dialog.dialog($scope.opts); + d.open().then(function(result){ + if(result) + { + alert('dialog closed with result: ' + result); + } + }); + }; + + $scope.openMessageBox = function(){ + var title = 'This is a message box'; + var msg = 'This is the content of the message box'; + var btns = [{result:'cancel', label: 'Cancel'}, {result:'ok', label: 'OK', cssClass: 'btn-primary'}]; + + $dialog.messageBox(title, msg, btns) + .open() + .then(function(result){ + alert('dialog closed with result: ' + result); + }); + }; +} + +// the dialog is injected in the specified controller +function TestDialogController($scope, dialog){ + $scope.close = function(result){ + dialog.close(result); + }; +} diff --git a/src/dialog/docs/readme.md b/src/dialog/docs/readme.md new file mode 100644 index 0000000000..57e7b93439 --- /dev/null +++ b/src/dialog/docs/readme.md @@ -0,0 +1,6 @@ +The `$dialog` service allows you to open dialogs and message boxes from within your controllers. Very useful in case loading dialog content in the DOM up-front is tedious or not desired. + +Creating custom dialogs is straightforward create a partial view, its controller and reference them when using the service. +Generic message boxes (title, message and buttons) are also provided for your convenience. + +For more information, see the [dialog readme](https://github.com/angular-ui/bootstrap/src/dialog/README.md) on github. \ No newline at end of file From eb0a2402229b13d7a28b15c5b9202766374b807c Mon Sep 17 00:00:00 2001 From: Gino Heyman Date: Sun, 6 Jan 2013 13:17:25 +0100 Subject: [PATCH 3/3] Fixed testacular issue Added an afterEach to the modal directive tests that removes all modal-backdrop divs from the DOM. They sometimes interfere with the dialog tests (making 13 of them fail), probably due to a testacular glitch. --- src/modal/test/modalSpec.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/modal/test/modalSpec.js b/src/modal/test/modalSpec.js index bb6d8b0fcb..ca04e8ac22 100644 --- a/src/modal/test/modalSpec.js +++ b/src/modal/test/modalSpec.js @@ -7,6 +7,10 @@ describe('modal', function() { $compile = _$compile_; })); + afterEach(function(){ + $('.modal-backdrop').remove(); + }); + function modal(options, expr, closeExpr) { scope.modalOpts = options; return $compile('