Details | Last modification | View Log | RSS feed
| Rev | Author | Line No. | Line |
|---|---|---|---|
| 1 | espaco | 1 | /*! |
| 2 | * Bootstrap Confirmation |
||
| 3 | * Copyright 2013 Nimit Suwannagate <ethaizone@hotmail.com> |
||
| 4 | * Copyright 2014 Damien "Mistic" Sorel <http://www.strangeplanet.fr> |
||
| 5 | * Licensed under the Apache License, Version 2.0 (the "License") |
||
| 6 | */ |
||
| 7 | |||
| 8 | (function ($) { |
||
| 9 | 'use strict'; |
||
| 10 | |||
| 11 | // Confirmation extends popover.js |
||
| 12 | if (!$.fn.popover) throw new Error('Confirmation requires popover.js'); |
||
| 13 | |||
| 14 | // CONFIRMATION PUBLIC CLASS DEFINITION |
||
| 15 | // =============================== |
||
| 16 | var Confirmation = function (element, options) { |
||
| 17 | this.init('confirmation', element, options); |
||
| 18 | |||
| 19 | var that = this; |
||
| 20 | |||
| 21 | if (!this.options.selector) { |
||
| 22 | // get existing href and target |
||
| 23 | if (this.$element.attr('href')) { |
||
| 24 | this.options.href = this.$element.attr('href'); |
||
| 25 | this.$element.removeAttr('href'); |
||
| 26 | if (this.$element.attr('target')) { |
||
| 27 | this.options.target = this.$element.attr('target'); |
||
| 28 | } |
||
| 29 | } |
||
| 30 | |||
| 31 | // cancel original event |
||
| 32 | this.$element.on(that.options.trigger, function(e, ack) { |
||
| 33 | if (!ack) { |
||
| 34 | e.preventDefault(); |
||
| 35 | e.stopPropagation(); |
||
| 36 | e.stopImmediatePropagation(); |
||
| 37 | } |
||
| 38 | }); |
||
| 39 | |||
| 40 | // trigger original event on confirm |
||
| 41 | this.$element.on('confirmed.bs.confirmation', function(e) { |
||
| 42 | $(this).trigger(that.options.trigger, [true]); |
||
| 43 | }); |
||
| 44 | |||
| 45 | // manage singleton |
||
| 46 | this.$element.on('show.bs.confirmation', function(e) { |
||
| 47 | if (that.options.singleton) { |
||
| 48 | // close all other popover already initialized |
||
| 49 | $(that.options._selector).not($(this)).filter(function() { |
||
| 50 | return $(this).data('bs.confirmation') !== undefined; |
||
| 51 | }).confirmation('hide'); |
||
| 52 | } |
||
| 53 | }); |
||
| 54 | } |
||
| 55 | |||
| 56 | if (!this.options._isDelegate) { |
||
| 57 | // manage popout |
||
| 58 | this.eventBody = false; |
||
| 59 | this.uid = this.$element[0].id || this.getUID('group_'); |
||
| 60 | |||
| 61 | this.$element.on('shown.bs.confirmation', function(e) { |
||
| 62 | if (that.options.popout && !that.eventBody) { |
||
| 63 | var $this = $(this); |
||
| 64 | that.eventBody = $('body').on('click.bs.confirmation.'+that.uid, function(e) { |
||
| 65 | if ($(that.options._selector).is(e.target)) { |
||
| 66 | return; |
||
| 67 | } |
||
| 68 | |||
| 69 | // close all popover already initialized |
||
| 70 | $(that.options._selector).filter(function() { |
||
| 71 | return $(this).data('bs.confirmation') !== undefined; |
||
| 72 | }).confirmation('hide'); |
||
| 73 | |||
| 74 | $('body').off('click.bs.'+that.uid); |
||
| 75 | that.eventBody = false; |
||
| 76 | }); |
||
| 77 | } |
||
| 78 | }); |
||
| 79 | } |
||
| 80 | }; |
||
| 81 | |||
| 82 | Confirmation.DEFAULTS = $.extend({}, $.fn.popover.Constructor.DEFAULTS, { |
||
| 83 | placement: 'top', |
||
| 84 | title: 'Are you sure?', |
||
| 85 | html: true, |
||
| 86 | href: false, |
||
| 87 | popout: false, |
||
| 88 | singleton: false, |
||
| 89 | target: '_self', |
||
| 90 | onConfirm: $.noop, |
||
| 91 | onCancel: $.noop, |
||
| 92 | btnOkClass: 'btn-xs btn-primary', |
||
| 93 | btnOkIcon: 'glyphicon glyphicon-ok', |
||
| 94 | btnOkLabel: 'Yes', |
||
| 95 | btnCancelClass: 'btn-xs btn-default', |
||
| 96 | btnCancelIcon: 'glyphicon glyphicon-remove', |
||
| 97 | btnCancelLabel: 'No', |
||
| 98 | template: |
||
| 99 | '<div class="popover confirmation">' + |
||
| 100 | '<div class="arrow"></div>' + |
||
| 101 | '<h3 class="popover-title"></h3>' + |
||
| 102 | '<div class="popover-content text-center">'+ |
||
| 103 | '<div class="btn-group">'+ |
||
| 104 | '<a class="btn" data-apply="confirmation"></a>'+ |
||
| 105 | '<a class="btn" data-dismiss="confirmation"></a>'+ |
||
| 106 | '</div>'+ |
||
| 107 | '</div>'+ |
||
| 108 | '</div>' |
||
| 109 | }); |
||
| 110 | |||
| 111 | Confirmation.prototype = $.extend({}, $.fn.popover.Constructor.prototype); |
||
| 112 | |||
| 113 | Confirmation.prototype.constructor = Confirmation; |
||
| 114 | |||
| 115 | Confirmation.prototype.getDefaults = function () { |
||
| 116 | return Confirmation.DEFAULTS; |
||
| 117 | }; |
||
| 118 | |||
| 119 | // custom init keeping trace of selectors |
||
| 120 | Confirmation.prototype.init = function(type, element, options) { |
||
| 121 | $.fn.popover.Constructor.prototype.init.call(this, type, element, options); |
||
| 122 | |||
| 123 | this.options._isDelegate = false; |
||
| 124 | if (options.selector) { // container of buttons |
||
| 125 | this.options._selector = this._options._selector = options._root_selector +' '+ options.selector; |
||
| 126 | } |
||
| 127 | else if (options._selector) { // children of container |
||
| 128 | this.options._selector = options._selector; |
||
| 129 | this.options._isDelegate = true; |
||
| 130 | } |
||
| 131 | else { // standalone |
||
| 132 | this.options._selector = options._root_selector; |
||
| 133 | } |
||
| 134 | }; |
||
| 135 | |||
| 136 | Confirmation.prototype.setContent = function () { |
||
| 137 | var that = this, |
||
| 138 | $tip = this.tip(), |
||
| 139 | o = this.options; |
||
| 140 | |||
| 141 | $tip.find('.popover-title')[o.html ? 'html' : 'text'](this.getTitle()); |
||
| 142 | |||
| 143 | // configure 'ok' button |
||
| 144 | $tip.find('[data-apply="confirmation"]') |
||
| 145 | .addClass(o.btnOkClass) |
||
| 146 | .html(o.btnOkLabel) |
||
| 147 | .prepend($('<i></i>').addClass(o.btnOkIcon), ' ') |
||
| 148 | .off('click') |
||
| 149 | .one('click', function(e) { |
||
| 150 | that.getOnConfirm.call(that).call(that.$element); |
||
| 151 | that.$element.trigger('confirmed.bs.confirmation'); |
||
| 152 | that.leave(that); |
||
| 153 | }); |
||
| 154 | |||
| 155 | // add href to confirm button if needed |
||
| 156 | if (o.href && o.href != "#") { |
||
| 157 | $tip.find('[data-apply="confirmation"]').attr({ |
||
| 158 | href: o.href, |
||
| 159 | target: o.target |
||
| 160 | }); |
||
| 161 | } |
||
| 162 | |||
| 163 | // configure 'cancel' button |
||
| 164 | $tip.find('[data-dismiss="confirmation"]') |
||
| 165 | .addClass(o.btnCancelClass) |
||
| 166 | .html(o.btnCancelLabel) |
||
| 167 | .prepend($('<i></i>').addClass(o.btnCancelIcon), ' ') |
||
| 168 | .off('click') |
||
| 169 | .one('click', function(e) { |
||
| 170 | that.getOnCancel.call(that).call(that.$element); |
||
| 171 | that.$element.trigger('canceled.bs.confirmation'); |
||
| 172 | that.leave(that); |
||
| 173 | }); |
||
| 174 | |||
| 175 | $tip.removeClass('fade top bottom left right in'); |
||
| 176 | |||
| 177 | // IE8 doesn't accept hiding via the `:empty` pseudo selector, we have to do |
||
| 178 | // this manually by checking the contents. |
||
| 179 | if (!$tip.find('.popover-title').html()) { |
||
| 180 | $tip.find('.popover-title').hide(); |
||
| 181 | } |
||
| 182 | }; |
||
| 183 | |||
| 184 | Confirmation.prototype.getOnConfirm = function() { |
||
| 185 | if (this.$element.attr('data-on-confirm')) { |
||
| 186 | return getFunctionFromString(this.$element.attr('data-on-confirm')); |
||
| 187 | } |
||
| 188 | else { |
||
| 189 | return this.options.onConfirm; |
||
| 190 | } |
||
| 191 | }; |
||
| 192 | |||
| 193 | Confirmation.prototype.getOnCancel = function() { |
||
| 194 | if (this.$element.attr('data-on-cancel')) { |
||
| 195 | return getFunctionFromString(this.$element.attr('data-on-cancel')); |
||
| 196 | } |
||
| 197 | else { |
||
| 198 | return this.options.onCancel; |
||
| 199 | } |
||
| 200 | }; |
||
| 201 | |||
| 202 | /* |
||
| 203 | * Generates an anonymous function from a function name |
||
| 204 | * function name may contain dots (.) to navigate through objects |
||
| 205 | * root context is window |
||
| 206 | */ |
||
| 207 | function getFunctionFromString(functionName) { |
||
| 208 | var context = window, |
||
| 209 | namespaces = functionName.split('.'), |
||
| 210 | func = namespaces.pop(); |
||
| 211 | |||
| 212 | for (var i=0, l=namespaces.length; i<l; i++) { |
||
| 213 | context = context[namespaces[i]]; |
||
| 214 | } |
||
| 215 | |||
| 216 | return function() { |
||
| 217 | context[func].call(this); |
||
| 218 | }; |
||
| 219 | } |
||
| 220 | |||
| 221 | |||
| 222 | // CONFIRMATION PLUGIN DEFINITION |
||
| 223 | // ========================= |
||
| 224 | |||
| 225 | var old = $.fn.confirmation; |
||
| 226 | |||
| 227 | $.fn.confirmation = function (option) { |
||
| 228 | var options = (typeof option == 'object' && option) || {}; |
||
| 229 | options._root_selector = this.selector; |
||
| 230 | |||
| 231 | return this.each(function () { |
||
| 232 | var $this = $(this), |
||
| 233 | data = $this.data('bs.confirmation'); |
||
| 234 | |||
| 235 | if (!data && option == 'destroy') { |
||
| 236 | return; |
||
| 237 | } |
||
| 238 | if (!data) { |
||
| 239 | $this.data('bs.confirmation', (data = new Confirmation(this, options))); |
||
| 240 | } |
||
| 241 | if (typeof option == 'string') { |
||
| 242 | data[option](); |
||
| 243 | } |
||
| 244 | }); |
||
| 245 | }; |
||
| 246 | |||
| 247 | $.fn.confirmation.Constructor = Confirmation; |
||
| 248 | |||
| 249 | |||
| 250 | // CONFIRMATION NO CONFLICT |
||
| 251 | // =================== |
||
| 252 | |||
| 253 | $.fn.confirmation.noConflict = function () { |
||
| 254 | $.fn.confirmation = old; |
||
| 255 | return this; |
||
| 256 | }; |
||
| 257 | |||
| 258 | }(jQuery)); |