<!DOCTYPE html>
<html ng-app="app">

<head>

    <link href="//netdna.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet" />
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.3/angular.js"></script>
    <script src="//code.angularjs.org/1.4.8/angular-sanitize.js"></script>
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.3/angular-animate.js"></script>
    <script src="//angular-ui.github.io/bootstrap/ui-bootstrap-tpls-1.3.3.js"></script>
    <script src="app.js"></script>
    <script src="popup.service.min.js"></script>
</head>

<body>
    <div ng-controller="appCtrl as vm" class="fluid panel-body">
        <h2>Dialoge Box using UI Bootstrap</h2>
        <h5>Inspired by <a href="http://ionicframework.com/docs/v1/api/service/$ionicPopup/" target="_blank">Ionic Popup</a></h5>
        <div style=" padding-bottom: 10px;">
           <strong class="text-danger mark">Launch in full window(or extend size of this window) to see the modal size effect.</strong>
        </div>
        <div>
            <button class="btn btn-info" ng-click="vm.showConfirmWithOptions()">
                Complex Confirm
            </button>
            <button class="btn btn-primary" ng-click="vm.showConfirm()">
                Simple Confirm
            </button>
             <button class="btn btn-success" ng-click="vm.showAlert()">
                Alert
            </button>
            <button class="btn btn-success" ng-click="vm.showAndClose()">
                Alert (Close after 2  Sec)
            </button>

        </div>

        <!--<button class="button button-dark" ng-click="vm.showPopup()">-->
        <!--      show-->
        <!--  </button>-->
        <form>
            <div class="form-group">
                <label for="text1">Message Body </label>
                <input type="text" class="form-control" id="text1" ng-model="vm.body">
            </div>
            <div class="form-group">
                <label for="text2">Title </label>
                <input type="text" class="form-control" id="text2" ng-model="vm.title">
            </div>
            <div class="form-group">
                <label for="text3">Sub Title </label>
                <input type="text" class="form-control" id="text3" ng-model="vm.subTitle">
            </div>
            <div class="alert alert-success">
                All input supports html snippet as well!!
            </div>
        </form>
        <hr>
    </div>
</body>

</html>
angular.module('app', ['ngAnimate', 'ui.bootstrap', 'ngSanitize', 'popup'])
    .controller('appCtrl', ['$scope', '$injector', appCtrl])
    .config(['PopupSvcProvider', function(PopupSvcProvider) { //optionally configure popup svc

        PopupSvcProvider.setDefaults({
            //okText: 'Dismiss'
        });
    }]);

function appCtrl($scope, $injector) {
    var vm = this;

    vm.body = "<span class='text-success'>Hey!!</span>Modal width automatically adjust as per Message body length when you simply pass the string";
    vm.title = "Attention!";
    vm.subTitle = "You bet";

    var PopupSvc = $injector.get('PopupSvc');

    vm.showAlert = function() {
        var modal = PopupSvc.alert(vm.body);
        modal.then(function(response) {
            vm.response = response;
        });
    };

    vm.showAndClose = function() {
        var modal = PopupSvc.alert(vm.body);
        window.setTimeout(modal.close, 2000);
    };

    vm.showConfirm = function() {
        PopupSvc.confirm(vm.body).then(function(response) {
            vm.response = response;
        });
    };

    vm.showConfirmWithOptions = function() {
        PopupSvc.confirm({
            title: vm.title,
            subTitle: vm.subTitle,
            body: vm.body,
            okText: 'Agree',
            cancelClass: 'btn-danger'
        }).then(function(response) {
            vm.response = response;
        });
    };
}
(function() {
    /* popup.service.js by Amitesh Kumar*/
    angular.module('popup', [])
        .provider('PopupSvc', PopupProviderFunction);

    function PopupProviderFunction() {

        var DEFAULTS = {
            //title, subTitle and body are not a part of configuration
            // title: '', // String (optional). The title of the popup.
            // subTitle: '', // String (optional). The sub-title of the popup. only applicable when title provided
            // body: '', //String or html template to place in the popup body.

            okText: 'OK', //text for OK button
            okClass: 'btn-info', //class(es) to be added to OK button; e.g 'btn-info btn-small'
            cancelText: 'Cancel', //not applicable for alert
            cancelClass: 'btn-secondary',

            headerClass: 'text-center', //class to be added to bootstrap modal-header
            bodyClass: '', //class for bootstrap modal-body
            footerClass: '', //class for bootstrap modal-footer

            //Below are the three uibModal related properties, see uibModal Bootstrap documentation for details

            backdrop: 'static', //Controls presence of a backdrop. Allowed values: true (default), false (no backdrop), 'static' (disables modal closing by click on the backdrop).

            keyboard: false, //Indicates whether the dialog should be closable by hitting the ESC key.
            size: 'sm', //modal or popup size, default is small

            /*NOTE: Below are the app level configuration applicable when input parameter is string. It can be set during angular config phase.
             */

            showStringAs: 'body', //it will display the text as modal body(left aligned smaller font text). Other value is 'title' (center aligned h5 element)
            enableDynamicSize: true, //show medium size popup when input string extends the below character limit
            extendSizeCharLength: 300
        };

        this.setDefaults = function(userDefaults) {
            angular.extend(DEFAULTS, userDefaults);
        };

        this.$get = ["$uibModal", function($uibModal) {
            return new PopupSvc(DEFAULTS, $uibModal);
        }];

    }

    function PopupSvc(DEFAULTS, $uibModal) {
        /* jshint -W043 */
        var POPUP_TEMPLATE = '\
        <div>\
            <div class="modal-header" ng-class="vm.headerClass" ng-if="vm.title" style="border:none; padding-bottom: 0;">\
                <h3 class="modal-title" ng-bind-html="vm.title"></h3>\
                <h5 class="modal-sub-title" ng-bind-html="vm.subTitle" ng-if="vm.subTitle"></h5>\
            </div>\
            <div class="modal-body" ng-if="vm.body" ng-class="vm.bodyClass">\
                <div ng-bind-html="vm.body"></div>\
            </div>\
            <div class="modal-footer" ng-class="vm.footerClass" style="text-align: center; padding-top: 10px; padding-bottom: 15px; border: none">\
                <div xclass="btn-group">\
                    <button ng-repeat="button in vm.buttons" ng-click="vm.onButtonClick(button, $index)" style="min-width: 70px;" class="btn" ng-class="button.className" ng-bind-html="button.text"></button>\
                </div>\
            </div>\
        </div>';

        return {
            alert: _alert,
            confirm: _confirm
            //prompt: _prompt,
            //show: _show//generic one which can show multiple buttons
        };

        function _alert(opts) {
            return _showPopup(extend([{
                text: opts.okText || DEFAULTS.okText,
                className: opts.okClass || DEFAULTS.okClass,
                handler: function() {
                    return true;
                }
            }], opts || {}));
        }

        function _confirm(opts) {
            return _showPopup(extend([{
                text: opts.cancelText || DEFAULTS.cancelText,
                className: opts.cancelClass || DEFAULTS.cancelClass,
                handler: function() {
                    return false;
                }
            }, {
                text: opts.okText || DEFAULTS.okText,
                className: opts.okClass || DEFAULTS.okClass,
                handler: function() {
                    return true;
                }
            }], opts || {}));
        }

        function extend(buttons, userOpts) {
            var options = angular.copy(DEFAULTS);
            userOpts = userOpts || 'You there?';
            if (typeof userOpts === 'string') {
                var obj = {};
                obj[DEFAULTS.showStringAs] = userOpts;
                if (DEFAULTS.enableDynamicSize && userOpts.length > DEFAULTS.extendSizeCharLength) {
                    obj.size = 'md';
                }
                userOpts = obj;
            }
            options.buttons = buttons;
            return angular.extend(options, userOpts);
        }


        function _showPopup(options) {
            var modalInstance = $uibModal.open({
                template: POPUP_TEMPLATE,
                size: options.size,
                backdrop: options.backdrop,
                keyboard: options.keyboard,
                bindToController: true,
                controllerAs: 'vm',
                controller: ['$injector', 'options', ModelController],
                resolve: {
                    options: function() {
                        return options;
                    }
                }
            });

            var obj = modalInstance.result; //returned promise
            obj.close = modalInstance.close; //augment close method

            return obj;
        }

        function ModelController($injector, options) {
            var vm = this;
            sanitizeInput(options);
            angular.extend(vm, options);

            vm.onButtonClick = function(button, $index) {
                var response = button.handler(); //true for alert,  true and false for confirm
                vm.$close(response);
            };

            function sanitizeInput(options) {
                if ($injector.has('$sanitize')) {
                    return; //no need to sanitize
                }

                var $sce = $injector.get('$sce');

                options.title = $sce.trustAsHtml(options.title);
                options.subTitle = $sce.trustAsHtml(options.subTitle);
                options.body = $sce.trustAsHtml(options.body);
                options.buttons.forEach(function(button, index, buttons) {
                    button.text = $sce.trustAsHtml(button.text);
                });
            }
        }
    }
})();
/*! popup.service.min.js by Amitesh Kumar - 2017-06-25. Visit  https://github.com/amiteshhh/utilities/angular/popup */
!function(){function t(){var t={okText:"OK",okClass:"btn-info",cancelText:"Cancel",cancelClass:"btn-secondary",headerClass:"text-center",bodyClass:"",footerClass:"",backdrop:"static",keyboard:!1,size:"sm",showStringAs:"body",enableDynamicSize:!0,extendSizeCharLength:300};this.setDefaults=function(n){angular.extend(t,n)},this.$get=["$uibModal",function(e){return new n(t,e)}]}function n(t,n){function e(n){return a(s([{text:n.okText||t.okText,className:n.okClass||t.okClass,handler:function(){return!0}}],n||{}))}function o(n){return a(s([{text:n.cancelText||t.cancelText,className:n.cancelClass||t.cancelClass,handler:function(){return!1}},{text:n.okText||t.okText,className:n.okClass||t.okClass,handler:function(){return!0}}],n||{}))}function s(n,e){var o=angular.copy(t);if("string"==typeof(e=e||"You there?")){var s={};s[t.showStringAs]=e,t.enableDynamicSize&&e.length>t.extendSizeCharLength&&(s.size="md"),e=s}return o.buttons=n,angular.extend(o,e)}function a(t){var e=n.open({template:i,size:t.size,backdrop:t.backdrop,keyboard:t.keyboard,bindToController:!0,controllerAs:"vm",controller:["$injector","options",l],resolve:{options:function(){return t}}}),o=e.result;return o.close=e.close,o}function l(t,n){var e=this;!function(n){if(!t.has("$sanitize")){var e=t.get("$sce");n.title=e.trustAsHtml(n.title),n.subTitle=e.trustAsHtml(n.subTitle),n.body=e.trustAsHtml(n.body),n.buttons.forEach(function(t,n,o){t.text=e.trustAsHtml(t.text)})}}(n),angular.extend(e,n),e.onButtonClick=function(t,n){var o=t.handler();e.$close(o)}}var i='        <div>            <div class="modal-header" ng-class="vm.headerClass" ng-if="vm.title" style="border:none; padding-bottom: 0;">                <h3 class="modal-title" ng-bind-html="vm.title"></h3>                <h5 class="modal-sub-title" ng-bind-html="vm.subTitle" ng-if="vm.subTitle"></h5>            </div>            <div class="modal-body" ng-if="vm.body" ng-class="vm.bodyClass">                <div ng-bind-html="vm.body"></div>            </div>            <div class="modal-footer" ng-class="vm.footerClass" style="text-align: center; padding-top: 10px; padding-bottom: 15px; border: none">                <div xclass="btn-group">                    <button ng-repeat="button in vm.buttons" ng-click="vm.onButtonClick(button, $index)" style="min-width: 70px;" class="btn" ng-class="button.className" ng-bind-html="button.text"></button>                </div>            </div>        </div>';return{alert:e,confirm:o}}angular.module("popup",[]).provider("PopupSvc",t)}();
# Angular Bootstrap Popup


A simple and elegant angular service inspired by [ionic popup](http://ionicframework.com/docs/v1/api/service/$ionicPopup) to show popup(or dialogue) window for `alert` and `confirm` with custom content and look.

PopupSvc exposes two methods `alert` and `confirm` which takes one parameter either string/html template or an [option](#advance-usage) object for customized look and feel.
These methods returns [promise](https://docs.angularjs.org/api/ng/service/$q) which is resolved when the popup is dismissed. It also returns `close` method to programmatically close it.


## Dependency

[Angular](https://code.angularjs.org/1.5.3/docs/api) (tested on v1.5.3)

[Angular UI Bootstrap](http://angular-ui.github.io/bootstrap/versioned-docs/1.3.3/) (tested on v1.3.3)

> PopupSvc should work fine with any Angular/UI Bootstrap version supporting [ControllerAs](https://johnpapa.net/angularjss-controller-as-and-the-vm-variable/) syntax.

## Demo

Check out the demo at [Plunker](https://plnkr.co/edit/SNhye1/)


## Usage 

```javascript
angular.module('myApp', ['popup']);//add popup module dependency
angular.controller('myCtrl', ['PopupSvc', function(PopupSvc){//Inject the PopupSvc service into your controller

    //1. Basic Usage
    PopupSvc.alert("<strong>Hey!</strong> How you doing");//html string
    PopupSvc.confirm("Are you sure?");//normal text

    //2. Reacting on popup dismissal/button click
    var popup = PopupSvc.alert("Hey! How you doing");
    popup.then(function(){
        console.log('Alert dismissed');
    });

    PopupSvc.confirm("Hey! How you doing").then(function(response){
        if(response){
            console.log('Primary/OK button clicked');
        }else{
            console.log('Secondary/Cancel button clicked');
        }    
    });

    //Programmatically closing the popup using `close` method
    //close method must be executed in next tick as popup creation is asynchronous
    var popup = PopupSvc.alert("Hey! How you doing");
    window.setTimeout(popup.close, 3000);

    //3. Customized popup
    var popupOption = {//only fewer options here
        title: 'Confirm',
        subTitle: '<span style="color: red;">Are you sure?</span>',
        body: 'Operation can not be reverted',
        okText: 'Delete',
        okClass: 'btn-danger',
        size: 'md'//show a medium size modal popup
    };
    PopupSvc.confirm(popupOption);
}]);

```

## Install

Download the script file directly from Github and add `script` reference to your html.

Once done, add `popup` module as dependency. Now you can use `PopupSvc` service.

Github Link: https://raw.githubusercontent.com/amiteshhh/utilities/master/angular/popup/popup.service.min.js


## Advance Usage

To have a custom look and feel (e.g button texts etc.) use below option as a parameter to `alert` or `confirm`. All of the option properties are optional. But Of course you will provide value for `body` or `title` to render some text.


> popup is created using bootstrap $uibModal hence there are few properties related to that as well

```javascript
{
    title: '', // String. The title of the popup.
    subTitle: '', // String. The sub-title of the popup. only applicable when title provided
    body: '',//String to place in the popup body.

    okText: 'OK',//text for OK button
    okClass: 'btn-info',//class(es) to be added to OK button; e.g 'btn-info btn-small'
    cancelText: 'Cancel',//not applicable for alert
    cancelClass: 'btn-secondary',
    
    headerClass: 'text-center',//class to be added to bootstrap modal-header
    bodyClass: '',//class for bootstrap modal-body
    footerClass: '',//class for bootstrap modal-footer

    //Below are the three uibModal related properties, see uibModal Bootstrap documentation for details

    backdrop: 'static',//Controls presence of a backdrop. Allowed values: true (default), false (no backdrop), 'static' (disables modal closing by click on the backdrop).

    keyboard: false,//Indicates whether the dialog should be closable by hitting the ESC key.
    size: 'sm',//modal or popup size, default is small

    /*NOTE: Below are the app level configuration applicable when input parameter is string. It can be set during angular config phase.
    */

    showStringAs: 'body',//it will display the text as modal body(left aligned smaller font text). Other value is 'title' (center aligned h5 element)
    enableDynamicSize: true,//show medium size popup when input string extends the below character limit
    extendSizeCharLength: 300
};

```

> Moreover all applicable string inputs can be `html string` hence you can easily control the style.

## Default Configuration

You can easily configure the default popup option for the application during config phase using `PopupSvcProvider` as below.

However the inline option will still take precedence over app level configuration.

```javascript
angular.module('myApp', ['popup'])
    .config(['PopupSvcProvider', function(PopupSvcProvider){
         PopupSvcProvider.setDefaults({
            okText: 'Dismiss',//Now instead of 'OK' popup will show button with text 'Dismiss' 
            okClass: 'btn-primary',
            cancelText: 'Close',
            keyboard: true//popup can be closed now with ESC key.
        });
    }]);
```


## License

MIT