Details | Last modification | View Log | RSS feed
| Rev | Author | Line No. | Line |
|---|---|---|---|
| 1 | espaco | 1 | /* =========================================================== |
| 2 | * bootstrap-modal.js v2.2.5 |
||
| 3 | * =========================================================== |
||
| 4 | * Copyright 2012 Jordan Schroter |
||
| 5 | * |
||
| 6 | * Licensed under the Apache License, Version 2.0 (the "License"); |
||
| 7 | * you may not use this file except in compliance with the License. |
||
| 8 | * You may obtain a copy of the License at |
||
| 9 | * |
||
| 10 | * http://www.apache.org/licenses/LICENSE-2.0 |
||
| 11 | * |
||
| 12 | * Unless required by applicable law or agreed to in writing, software |
||
| 13 | * distributed under the License is distributed on an "AS IS" BASIS, |
||
| 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||
| 15 | * See the License for the specific language governing permissions and |
||
| 16 | * limitations under the License. |
||
| 17 | * ========================================================== */ |
||
| 18 | |||
| 19 | |||
| 20 | !function ($) { |
||
| 21 | |||
| 22 | "use strict"; // jshint ;_; |
||
| 23 | |||
| 24 | /* MODAL CLASS DEFINITION |
||
| 25 | * ====================== */ |
||
| 26 | |||
| 27 | var Modal = function (element, options) { |
||
| 28 | this.init(element, options); |
||
| 29 | }; |
||
| 30 | |||
| 31 | Modal.prototype = { |
||
| 32 | |||
| 33 | constructor: Modal, |
||
| 34 | |||
| 35 | init: function (element, options) { |
||
| 36 | var that = this; |
||
| 37 | |||
| 38 | this.options = options; |
||
| 39 | |||
| 40 | this.$element = $(element) |
||
| 41 | .delegate('[data-dismiss="modal"]', 'click.dismiss.modal', $.proxy(this.hide, this)); |
||
| 42 | |||
| 43 | this.options.remote && this.$element.find('.modal-body').load(this.options.remote, function () { |
||
| 44 | var e = $.Event('loaded'); |
||
| 45 | that.$element.trigger(e); |
||
| 46 | }); |
||
| 47 | |||
| 48 | var manager = typeof this.options.manager === 'function' ? |
||
| 49 | this.options.manager.call(this) : this.options.manager; |
||
| 50 | |||
| 51 | manager = manager.appendModal ? |
||
| 52 | manager : $(manager).modalmanager().data('modalmanager'); |
||
| 53 | |||
| 54 | manager.appendModal(this); |
||
| 55 | }, |
||
| 56 | |||
| 57 | toggle: function () { |
||
| 58 | return this[!this.isShown ? 'show' : 'hide'](); |
||
| 59 | }, |
||
| 60 | |||
| 61 | show: function () { |
||
| 62 | var e = $.Event('show'); |
||
| 63 | |||
| 64 | if (this.isShown) return; |
||
| 65 | |||
| 66 | this.$element.trigger(e); |
||
| 67 | |||
| 68 | if (e.isDefaultPrevented()) return; |
||
| 69 | |||
| 70 | this.escape(); |
||
| 71 | |||
| 72 | this.tab(); |
||
| 73 | |||
| 74 | this.options.loading && this.loading(); |
||
| 75 | }, |
||
| 76 | |||
| 77 | hide: function (e) { |
||
| 78 | e && e.preventDefault(); |
||
| 79 | |||
| 80 | e = $.Event('hide'); |
||
| 81 | |||
| 82 | this.$element.trigger(e); |
||
| 83 | |||
| 84 | if (!this.isShown || e.isDefaultPrevented()) return; |
||
| 85 | |||
| 86 | this.isShown = false; |
||
| 87 | |||
| 88 | this.escape(); |
||
| 89 | |||
| 90 | this.tab(); |
||
| 91 | |||
| 92 | this.isLoading && this.loading(); |
||
| 93 | |||
| 94 | $(document).off('focusin.modal'); |
||
| 95 | |||
| 96 | this.$element |
||
| 97 | .removeClass('in') |
||
| 98 | .removeClass('animated') |
||
| 99 | .removeClass(this.options.attentionAnimation) |
||
| 100 | .removeClass('modal-overflow') |
||
| 101 | .attr('aria-hidden', true); |
||
| 102 | |||
| 103 | $.support.transition && this.$element.hasClass('fade') ? |
||
| 104 | this.hideWithTransition() : |
||
| 105 | this.hideModal(); |
||
| 106 | }, |
||
| 107 | |||
| 108 | layout: function () { |
||
| 109 | var prop = this.options.height ? 'height' : 'max-height', |
||
| 110 | value = this.options.height || this.options.maxHeight; |
||
| 111 | |||
| 112 | if (this.options.width){ |
||
| 113 | this.$element.css('width', this.options.width); |
||
| 114 | |||
| 115 | var that = this; |
||
| 116 | this.$element.css('margin-left', function () { |
||
| 117 | if (/%/ig.test(that.options.width)){ |
||
| 118 | return -(parseInt(that.options.width) / 2) + '%'; |
||
| 119 | } else { |
||
| 120 | return -($(this).width() / 2) + 'px'; |
||
| 121 | } |
||
| 122 | }); |
||
| 123 | } else { |
||
| 124 | this.$element.css('width', ''); |
||
| 125 | this.$element.css('margin-left', ''); |
||
| 126 | } |
||
| 127 | |||
| 128 | this.$element.find('.modal-body') |
||
| 129 | .css('overflow', '') |
||
| 130 | .css(prop, ''); |
||
| 131 | |||
| 132 | if (value){ |
||
| 133 | this.$element.find('.modal-body') |
||
| 134 | .css('overflow', 'auto') |
||
| 135 | .css(prop, value); |
||
| 136 | } |
||
| 137 | |||
| 138 | var modalOverflow = $(window).height() - 10 < this.$element.height(); |
||
| 139 | |||
| 140 | if (modalOverflow || this.options.modalOverflow) { |
||
| 141 | this.$element |
||
| 142 | .css('margin-top', 0) |
||
| 143 | .addClass('modal-overflow'); |
||
| 144 | } else { |
||
| 145 | this.$element |
||
| 146 | .css('margin-top', 0 - this.$element.height() / 2) |
||
| 147 | .removeClass('modal-overflow'); |
||
| 148 | } |
||
| 149 | }, |
||
| 150 | |||
| 151 | tab: function () { |
||
| 152 | var that = this; |
||
| 153 | |||
| 154 | if (this.isShown && this.options.consumeTab) { |
||
| 155 | this.$element.on('keydown.tabindex.modal', '[data-tabindex]', function (e) { |
||
| 156 | if (e.keyCode && e.keyCode == 9){ |
||
| 157 | var elements = [], |
||
| 158 | tabindex = Number($(this).data('tabindex')); |
||
| 159 | |||
| 160 | that.$element.find('[data-tabindex]:enabled:visible:not([readonly])').each(function (ev) { |
||
| 161 | elements.push(Number($(this).data('tabindex'))); |
||
| 162 | }); |
||
| 163 | elements.sort(function(a,b){return a-b}); |
||
| 164 | |||
| 165 | var arrayPos = $.inArray(tabindex, elements); |
||
| 166 | if (!e.shiftKey){ |
||
| 167 | arrayPos < elements.length-1 ? |
||
| 168 | that.$element.find('[data-tabindex='+elements[arrayPos+1]+']').focus() : |
||
| 169 | that.$element.find('[data-tabindex='+elements[0]+']').focus(); |
||
| 170 | } else { |
||
| 171 | arrayPos == 0 ? |
||
| 172 | that.$element.find('[data-tabindex='+elements[elements.length-1]+']').focus() : |
||
| 173 | that.$element.find('[data-tabindex='+elements[arrayPos-1]+']').focus(); |
||
| 174 | } |
||
| 175 | |||
| 176 | e.preventDefault(); |
||
| 177 | } |
||
| 178 | }); |
||
| 179 | } else if (!this.isShown) { |
||
| 180 | this.$element.off('keydown.tabindex.modal'); |
||
| 181 | } |
||
| 182 | }, |
||
| 183 | |||
| 184 | escape: function () { |
||
| 185 | var that = this; |
||
| 186 | if (this.isShown && this.options.keyboard) { |
||
| 187 | if (!this.$element.attr('tabindex')) this.$element.attr('tabindex', -1); |
||
| 188 | |||
| 189 | this.$element.on('keyup.dismiss.modal', function (e) { |
||
| 190 | e.which == 27 && that.hide(); |
||
| 191 | }); |
||
| 192 | } else if (!this.isShown) { |
||
| 193 | this.$element.off('keyup.dismiss.modal') |
||
| 194 | } |
||
| 195 | }, |
||
| 196 | |||
| 197 | hideWithTransition: function () { |
||
| 198 | var that = this |
||
| 199 | , timeout = setTimeout(function () { |
||
| 200 | that.$element.off($.support.transition.end); |
||
| 201 | that.hideModal(); |
||
| 202 | }, 500); |
||
| 203 | |||
| 204 | this.$element.one($.support.transition.end, function () { |
||
| 205 | clearTimeout(timeout); |
||
| 206 | that.hideModal(); |
||
| 207 | }); |
||
| 208 | }, |
||
| 209 | |||
| 210 | hideModal: function () { |
||
| 211 | var prop = this.options.height ? 'height' : 'max-height'; |
||
| 212 | var value = this.options.height || this.options.maxHeight; |
||
| 213 | |||
| 214 | if (value){ |
||
| 215 | this.$element.find('.modal-body') |
||
| 216 | .css('overflow', '') |
||
| 217 | .css(prop, ''); |
||
| 218 | } |
||
| 219 | |||
| 220 | this.$element |
||
| 221 | .hide() |
||
| 222 | .trigger('hidden'); |
||
| 223 | }, |
||
| 224 | |||
| 225 | removeLoading: function () { |
||
| 226 | this.$loading.remove(); |
||
| 227 | this.$loading = null; |
||
| 228 | this.isLoading = false; |
||
| 229 | }, |
||
| 230 | |||
| 231 | loading: function (callback) { |
||
| 232 | callback = callback || function () {}; |
||
| 233 | |||
| 234 | var animate = this.$element.hasClass('fade') ? 'fade' : ''; |
||
| 235 | |||
| 236 | if (!this.isLoading) { |
||
| 237 | var doAnimate = $.support.transition && animate; |
||
| 238 | |||
| 239 | this.$loading = $('<div class="loading-mask ' + animate + '">') |
||
| 240 | .append(this.options.spinner) |
||
| 241 | .appendTo(this.$element); |
||
| 242 | |||
| 243 | if (doAnimate) this.$loading[0].offsetWidth; // force reflow |
||
| 244 | |||
| 245 | this.$loading.addClass('in'); |
||
| 246 | |||
| 247 | this.isLoading = true; |
||
| 248 | |||
| 249 | doAnimate ? |
||
| 250 | this.$loading.one($.support.transition.end, callback) : |
||
| 251 | callback(); |
||
| 252 | |||
| 253 | } else if (this.isLoading && this.$loading) { |
||
| 254 | this.$loading.removeClass('in'); |
||
| 255 | |||
| 256 | var that = this; |
||
| 257 | $.support.transition && this.$element.hasClass('fade')? |
||
| 258 | this.$loading.one($.support.transition.end, function () { that.removeLoading() }) : |
||
| 259 | that.removeLoading(); |
||
| 260 | |||
| 261 | } else if (callback) { |
||
| 262 | callback(this.isLoading); |
||
| 263 | } |
||
| 264 | }, |
||
| 265 | |||
| 266 | focus: function () { |
||
| 267 | var $focusElem = this.$element.find(this.options.focusOn); |
||
| 268 | |||
| 269 | $focusElem = $focusElem.length ? $focusElem : this.$element; |
||
| 270 | |||
| 271 | $focusElem.focus(); |
||
| 272 | }, |
||
| 273 | |||
| 274 | attention: function (){ |
||
| 275 | // NOTE: transitionEnd with keyframes causes odd behaviour |
||
| 276 | |||
| 277 | if (this.options.attentionAnimation){ |
||
| 278 | this.$element |
||
| 279 | .removeClass('animated') |
||
| 280 | .removeClass(this.options.attentionAnimation); |
||
| 281 | |||
| 282 | var that = this; |
||
| 283 | |||
| 284 | setTimeout(function () { |
||
| 285 | that.$element |
||
| 286 | .addClass('animated') |
||
| 287 | .addClass(that.options.attentionAnimation); |
||
| 288 | }, 0); |
||
| 289 | } |
||
| 290 | |||
| 291 | |||
| 292 | this.focus(); |
||
| 293 | }, |
||
| 294 | |||
| 295 | |||
| 296 | destroy: function () { |
||
| 297 | var e = $.Event('destroy'); |
||
| 298 | |||
| 299 | this.$element.trigger(e); |
||
| 300 | |||
| 301 | if (e.isDefaultPrevented()) return; |
||
| 302 | |||
| 303 | this.$element |
||
| 304 | .off('.modal') |
||
| 305 | .removeData('modal') |
||
| 306 | .removeClass('in') |
||
| 307 | .attr('aria-hidden', true); |
||
| 308 | |||
| 309 | if (this.$parent !== this.$element.parent()) { |
||
| 310 | this.$element.appendTo(this.$parent); |
||
| 311 | } else if (!this.$parent.length) { |
||
| 312 | // modal is not part of the DOM so remove it. |
||
| 313 | this.$element.remove(); |
||
| 314 | this.$element = null; |
||
| 315 | } |
||
| 316 | |||
| 317 | this.$element.trigger('destroyed'); |
||
| 318 | } |
||
| 319 | }; |
||
| 320 | |||
| 321 | |||
| 322 | /* MODAL PLUGIN DEFINITION |
||
| 323 | * ======================= */ |
||
| 324 | |||
| 325 | $.fn.modal = function (option, args) { |
||
| 326 | return this.each(function () { |
||
| 327 | var $this = $(this), |
||
| 328 | data = $this.data('modal'), |
||
| 329 | options = $.extend({}, $.fn.modal.defaults, $this.data(), typeof option == 'object' && option); |
||
| 330 | |||
| 331 | if (!data) $this.data('modal', (data = new Modal(this, options))); |
||
| 332 | if (typeof option == 'string') data[option].apply(data, [].concat(args)); |
||
| 333 | else if (options.show) data.show() |
||
| 334 | }) |
||
| 335 | }; |
||
| 336 | |||
| 337 | $.fn.modal.defaults = { |
||
| 338 | keyboard: true, |
||
| 339 | backdrop: true, |
||
| 340 | loading: false, |
||
| 341 | show: true, |
||
| 342 | width: null, |
||
| 343 | height: null, |
||
| 344 | maxHeight: null, |
||
| 345 | modalOverflow: false, |
||
| 346 | consumeTab: true, |
||
| 347 | focusOn: null, |
||
| 348 | replace: false, |
||
| 349 | resize: false, |
||
| 350 | attentionAnimation: 'shake', |
||
| 351 | manager: 'body', |
||
| 352 | spinner: '<div class="loading-spinner" style="width: 200px; margin-left: -100px;"><div class="progress progress-striped active"><div class="bar" style="width: 100%;"></div></div></div>', |
||
| 353 | backdropTemplate: '<div class="modal-backdrop" />' |
||
| 354 | }; |
||
| 355 | |||
| 356 | $.fn.modal.Constructor = Modal; |
||
| 357 | |||
| 358 | |||
| 359 | /* MODAL DATA-API |
||
| 360 | * ============== */ |
||
| 361 | |||
| 362 | $(function () { |
||
| 363 | $(document).off('click.modal').on('click.modal.data-api', '[data-toggle="modal"]', function ( e ) { |
||
| 364 | var $this = $(this), |
||
| 365 | href = $this.attr('href'), |
||
| 366 | $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))), //strip for ie7 |
||
| 367 | option = $target.data('modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data()); |
||
| 368 | |||
| 369 | e.preventDefault(); |
||
| 370 | $target |
||
| 371 | .modal(option) |
||
| 372 | .one('hide', function () { |
||
| 373 | $this.focus(); |
||
| 374 | }) |
||
| 375 | }); |
||
| 376 | }); |
||
| 377 | |||
| 378 | }(window.jQuery); |