2 * jQuery blockUI plugin
3 * Version 2.56.0-2013.01.31
4 * @requires jQuery v1.7 or later
6 * Examples at: http://malsup.com/jquery/block/
7 * Copyright (c) 2007-2013 M. Alsup
8 * Dual licensed under the MIT and GPL licenses:
9 * http://www.opensource.org/licenses/mit-license.php
10 * http://www.gnu.org/licenses/gpl.html
12 * Thanks to Amir-Hossein Sobhi for some excellent contributions!
19 $.fn
._fadeIn
= $.fn
.fadeIn
;
21 var noOp
= $.noop
|| function() {};
23 // this bit is to ensure we don't call setExpression when we shouldn't (with extra muscle to handle
24 // retarded userAgent strings on Vista)
25 var msie
= /MSIE/.test(navigator
.userAgent
);
26 var ie6
= /MSIE 6.0/.test(navigator
.userAgent
) && ! /MSIE 8.0/.test(navigator
.userAgent
);
27 var mode
= document
.documentMode
|| 0;
28 // var setExpr = msie && (($.browser.version < 8 && !mode) || mode < 8);
29 var setExpr
= $.isFunction( document
.createElement('div').style
.setExpression
);
31 // global $ methods for blocking/unblocking the entire page
32 $.blockUI = function(opts
) { install(window
, opts
); };
33 $.unblockUI = function(opts
) { remove(window
, opts
); };
35 // convenience method for quick growl-like notifications (http://www.google.com/search?q=growl)
36 $.growlUI = function(title
, message
, timeout
, onClose
) {
37 var $m
= $('<div class="growlUI"></div>');
38 if (title
) $m
.append('<h1>'+title
+'</h1>');
39 if (message
) $m
.append('<h2>'+message
+'</h2>');
40 if (timeout
=== undefined) timeout
= 3000;
42 message
: $m
, fadeIn
: 700, fadeOut
: 1000, centerY
: false,
43 timeout
: timeout
, showOverlay
: false,
45 css
: $.blockUI
.defaults
.growlCSS
49 // plugin method for blocking element content
50 $.fn
.block = function(opts
) {
51 var fullOpts
= $.extend({}, $.blockUI
.defaults
, opts
|| {});
52 this.each(function() {
54 if (fullOpts
.ignoreIfBlocked
&& $el
.data('blockUI.isBlocked'))
56 $el
.unblock({ fadeOut
: 0 });
59 return this.each(function() {
60 if ($.css(this,'position') == 'static') {
61 this.style
.position
= 'relative';
62 $(this).data('blockUI.static', true);
64 this.style
.zoom
= 1; // force 'hasLayout' in ie
69 // plugin method for unblocking element content
70 $.fn
.unblock = function(opts
) {
71 return this.each(function() {
76 $.blockUI
.version
= 2.56; // 2nd generation blocking at no extra cost!
78 // override these in your code to change the default behavior and style
79 $.blockUI
.defaults
= {
80 // message displayed when blocking (use null for no message)
81 message
: '<h1>Please wait...</h1>',
83 title
: null, // title string; only used when theme == true
84 draggable
: true, // only used when theme == true (requires jquery-ui.js to be loaded)
86 theme
: false, // set to true to use with jQuery UI themes
88 // styles for the message when blocking; if you wish to disable
89 // these and use an external stylesheet then do this in your code:
90 // $.blockUI.defaults.css = {};
99 border
: '3px solid #aaa',
100 backgroundColor
:'#fff',
104 // minimal style set used when themes are used
111 // styles for the overlay
113 backgroundColor
: '#000',
118 // style to replace wait cursor before unblocking to correct issue
119 // of lingering wait cursor
120 cursorReset
: 'default',
122 // styles applied when using $.growlUI
133 backgroundColor
: '#000',
134 '-webkit-border-radius':'10px',
135 '-moz-border-radius': '10px',
136 'border-radius': '10px'
139 // IE issues: 'about:blank' fails on HTTPS and javascript:false is s-l-o-w
140 // (hat tip to Jorge H. N. de Vasconcelos)
141 /*jshint scripturl:true */
142 iframeSrc
: /^https/i.test(window
.location
.href
|| '') ? 'javascript:false' : 'about:blank',
144 // force usage of iframe in non-IE browsers (handy for blocking applets)
147 // z-index for the blocking overlay
150 // set these to true to have the message automatically centered
151 centerX
: true, // <-- only effects element blocking (page block controlled via css above)
154 // allow body element to be stetched in ie6; this makes blocking look better
155 // on "short" pages. disable if you wish to prevent changes to the body height
156 allowBodyStretch
: true,
158 // enable if you want key and mouse events to be disabled for content that is blocked
161 // be default blockUI will supress tab navigation from leaving blocking content
162 // (if bindEvents is true)
163 constrainTabKey
: true,
165 // fadeIn time in millis; set to 0 to disable fadeIn on block
168 // fadeOut time in millis; set to 0 to disable fadeOut on unblock
171 // time in millis to wait before auto-unblocking; set to 0 to disable auto-unblock
174 // disable if you don't want to show the overlay
177 // if true, focus will be placed in the first available input field when
181 // suppresses the use of overlay styles on FF/Linux (due to performance issues with opacity)
182 // no longer needed in 2012
183 // applyPlatformOpacityRules: true,
185 // callback method invoked when fadeIn has completed and blocking message is visible
188 // callback method invoked when unblocking has completed; the callback is
189 // passed the element that has been unblocked (which is the window object for page
190 // blocks) and the options that were passed to the unblock call:
191 // onUnblock(element, options)
194 // callback method invoked when the overlay area is clicked.
195 // setting this will turn the cursor to a pointer, otherwise cursor defined in overlayCss will be used.
196 onOverlayClick
: null,
198 // don't ask; if you really must know: http://groups.google.com/group/jquery-en/browse_thread/thread/36640a8730503595/2f6a79a77a78e493#2f6a79a77a78e493
199 quirksmodeOffsetHack
: 4,
201 // class name of the message block
202 blockMsgClass
: 'blockMsg',
204 // if it is already blocked, then ignore it (don't unblock and reblock)
205 ignoreIfBlocked
: false
208 // private data and functions follow...
210 var pageBlock
= null;
211 var pageBlockEls
= [];
213 function install(el
, opts
) {
215 var full
= (el
== window
);
216 var msg
= (opts
&& opts
.message
!== undefined ? opts
.message
: undefined);
217 opts
= $.extend({}, $.blockUI
.defaults
, opts
|| {});
219 if (opts
.ignoreIfBlocked
&& $(el
).data('blockUI.isBlocked'))
222 opts
.overlayCSS
= $.extend({}, $.blockUI
.defaults
.overlayCSS
, opts
.overlayCSS
|| {});
223 css
= $.extend({}, $.blockUI
.defaults
.css
, opts
.css
|| {});
224 if (opts
.onOverlayClick
)
225 opts
.overlayCSS
.cursor
= 'pointer';
227 themedCSS
= $.extend({}, $.blockUI
.defaults
.themedCSS
, opts
.themedCSS
|| {});
228 msg
= msg
=== undefined ? opts
.message
: msg
;
230 // remove the current block (if there is one)
231 if (full
&& pageBlock
)
232 remove(window
, {fadeOut
:0});
234 // if an existing element is being used as the blocking content then we capture
235 // its current place in the DOM (and current display style) so we can restore
236 // it when we unblock
237 if (msg
&& typeof msg
!= 'string' && (msg
.parentNode
|| msg
.jquery
)) {
238 var node
= msg
.jquery
? msg
[0] : msg
;
240 $(el
).data('blockUI.history', data
);
242 data
.parent
= node
.parentNode
;
243 data
.display
= node
.style
.display
;
244 data
.position
= node
.style
.position
;
246 data
.parent
.removeChild(node
);
249 $(el
).data('blockUI.onUnblock', opts
.onUnblock
);
252 // blockUI uses 3 layers for blocking, for simplicity they are all used on every platform;
253 // layer1 is the iframe layer which is used to supress bleed through of underlying content
254 // layer2 is the overlay layer which has opacity and a wait cursor (by default)
255 // layer3 is the message content that is displayed while blocking
256 var lyr1
, lyr2
, lyr3
, s
;
257 if (msie
|| opts
.forceIframe
)
258 lyr1
= $('<iframe class="blockUI" style="z-index:'+ (z
++) +';display:none;border:none;margin:0;padding:0;position:absolute;width:100%;height:100%;top:0;left:0" src="'+opts
.iframeSrc
+'"></iframe>');
260 lyr1
= $('<div class="blockUI" style="display:none"></div>');
263 lyr2
= $('<div class="blockUI blockOverlay ui-widget-overlay" style="z-index:'+ (z
++) +';display:none"></div>');
265 lyr2
= $('<div class="blockUI blockOverlay" style="z-index:'+ (z
++) +';display:none;border:none;margin:0;padding:0;width:100%;height:100%;top:0;left:0"></div>');
267 if (opts
.theme
&& full
) {
268 s
= '<div class="blockUI ' + opts
.blockMsgClass
+ ' blockPage ui-dialog ui-widget ui-corner-all" style="z-index:'+(z
+10)+';display:none;position:fixed">';
270 s
+= '<div class="ui-widget-header ui-dialog-titlebar ui-corner-all blockTitle">'+(opts
.title
|| ' ')+'</div>';
272 s
+= '<div class="ui-widget-content ui-dialog-content"></div>';
275 else if (opts
.theme
) {
276 s
= '<div class="blockUI ' + opts
.blockMsgClass
+ ' blockElement ui-dialog ui-widget ui-corner-all" style="z-index:'+(z
+10)+';display:none;position:absolute">';
278 s
+= '<div class="ui-widget-header ui-dialog-titlebar ui-corner-all blockTitle">'+(opts
.title
|| ' ')+'</div>';
280 s
+= '<div class="ui-widget-content ui-dialog-content"></div>';
284 s
= '<div class="blockUI ' + opts
.blockMsgClass
+ ' blockPage" style="z-index:'+(z
+10)+';display:none;position:fixed"></div>';
287 s
= '<div class="blockUI ' + opts
.blockMsgClass
+ ' blockElement" style="z-index:'+(z
+10)+';display:none;position:absolute"></div>';
291 // if we have a message, style it
295 lyr3
.addClass('ui-widget-content');
302 if (!opts
.theme
/*&& (!opts.applyPlatformOpacityRules)*/)
303 lyr2
.css(opts
.overlayCSS
);
304 lyr2
.css('position', full
? 'fixed' : 'absolute');
306 // make iframe layer transparent in IE
307 if (msie
|| opts
.forceIframe
)
308 lyr1
.css('opacity',0.0);
310 //$([lyr1[0],lyr2[0],lyr3[0]]).appendTo(full ? 'body' : el);
311 var layers
= [lyr1
,lyr2
,lyr3
], $par
= full
? $('body') : $(el
);
312 $.each(layers
, function() {
316 if (opts
.theme
&& opts
.draggable
&& $.fn
.draggable
) {
318 handle
: '.ui-dialog-titlebar',
323 // ie7 must use absolute positioning in quirks mode and to account for activex issues (when scrolling)
324 var expr
= setExpr
&& (!$.support
.boxModel
|| $('object,embed', full
? null : el
).length
> 0);
326 // give body 100% height
327 if (full
&& opts
.allowBodyStretch
&& $.support
.boxModel
)
328 $('html,body').css('height','100%');
330 // fix ie6 issue when blocked element has a border width
331 if ((ie6
|| !$.support
.boxModel
) && !full
) {
332 var t
= sz(el
,'borderTopWidth'), l
= sz(el
,'borderLeftWidth');
333 var fixT
= t
? '(0 - '+t
+')' : 0;
334 var fixL
= l
? '(0 - '+l
+')' : 0;
337 // simulate fixed position
338 $.each(layers
, function(i
,o
) {
340 s
.position
= 'absolute';
343 s
.setExpression('height','Math.max(document.body.scrollHeight, document.body.offsetHeight) - (jQuery.support.boxModel?0:'+opts
.quirksmodeOffsetHack
+') + "px"');
345 s
.setExpression('height','this.parentNode.offsetHeight + "px"');
347 s
.setExpression('width','jQuery.support.boxModel && document.documentElement.clientWidth || document.body.clientWidth + "px"');
349 s
.setExpression('width','this.parentNode.offsetWidth + "px"');
350 if (fixL
) s
.setExpression('left', fixL
);
351 if (fixT
) s
.setExpression('top', fixT
);
353 else if (opts
.centerY
) {
354 if (full
) s
.setExpression('top','(document.documentElement.clientHeight || document.body.clientHeight) / 2 - (this.offsetHeight / 2) + (blah = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + "px"');
357 else if (!opts
.centerY
&& full
) {
358 var top
= (opts
.css
&& opts
.css
.top
) ? parseInt(opts
.css
.top
, 10) : 0;
359 var expression
= '((document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + '+top
+') + "px"';
360 s
.setExpression('top',expression
);
368 lyr3
.find('.ui-widget-content').append(msg
);
371 if (msg
.jquery
|| msg
.nodeType
)
375 if ((msie
|| opts
.forceIframe
) && opts
.showOverlay
)
376 lyr1
.show(); // opacity is zero
378 var cb
= opts
.onBlock
? opts
.onBlock
: noOp
;
379 var cb1
= (opts
.showOverlay
&& !msg
) ? cb
: noOp
;
380 var cb2
= msg
? cb
: noOp
;
381 if (opts
.showOverlay
)
382 lyr2
._fadeIn(opts
.fadeIn
, cb1
);
384 lyr3
._fadeIn(opts
.fadeIn
, cb2
);
387 if (opts
.showOverlay
)
395 // bind key and mouse events
400 pageBlockEls
= $(':input:enabled:visible',pageBlock
);
402 setTimeout(focus
, 20);
405 center(lyr3
[0], opts
.centerX
, opts
.centerY
);
409 var to
= setTimeout(function() {
415 $(el
).data('blockUI.timeout', to
);
420 function remove(el
, opts
) {
421 var full
= (el
== window
);
423 var data
= $el
.data('blockUI.history');
424 var to
= $el
.data('blockUI.timeout');
427 $el
.removeData('blockUI.timeout');
429 opts
= $.extend({}, $.blockUI
.defaults
, opts
|| {});
430 bind(0, el
, opts
); // unbind events
432 if (opts
.onUnblock
=== null) {
433 opts
.onUnblock
= $el
.data('blockUI.onUnblock');
434 $el
.removeData('blockUI.onUnblock');
438 if (full
) // crazy selector to handle odd field errors in ie6/7
439 els
= $('body').children().filter('.blockUI').add('body > .blockUI');
441 els
= $el
.find('>.blockUI');
444 if ( opts
.cursorReset
) {
445 if ( els
.length
> 1 )
446 els
[1].style
.cursor
= opts
.cursorReset
;
447 if ( els
.length
> 2 )
448 els
[2].style
.cursor
= opts
.cursorReset
;
452 pageBlock
= pageBlockEls
= null;
455 els
.fadeOut(opts
.fadeOut
);
456 setTimeout(function() { reset(els
,data
,opts
,el
); }, opts
.fadeOut
);
459 reset(els
, data
, opts
, el
);
462 // move blocking element back into the DOM where it started
463 function reset(els
,data
,opts
,el
) {
465 els
.each(function(i
,o
) {
466 // remove via DOM calls so we don't lose event handlers
468 this.parentNode
.removeChild(this);
471 if (data
&& data
.el
) {
472 data
.el
.style
.display
= data
.display
;
473 data
.el
.style
.position
= data
.position
;
475 data
.parent
.appendChild(data
.el
);
476 $el
.removeData('blockUI.history');
479 if ($el
.data('blockUI.static')) {
480 $el
.css('position', 'static'); // #22
483 if (typeof opts
.onUnblock
== 'function')
484 opts
.onUnblock(el
,opts
);
486 // fix issue in Safari 6 where block artifacts remain until reflow
487 var body
= $(document
.body
), w
= body
.width(), cssW
= body
[0].style
.width
;
488 body
.width(w
-1).width(w
);
489 body
[0].style
.width
= cssW
;
492 // bind/unbind the handler
493 function bind(b
, el
, opts
) {
494 var full
= el
== window
, $el
= $(el
);
496 // don't bother unbinding if there is nothing to unbind
497 if (!b
&& (full
&& !pageBlock
|| !full
&& !$el
.data('blockUI.isBlocked')))
500 $el
.data('blockUI.isBlocked', b
);
502 // don't bind events when overlay is not in use or if bindEvents is false
503 if (!opts
.bindEvents
|| (b
&& !opts
.showOverlay
))
506 // bind anchors and inputs for mouse and key events
507 var events
= 'mousedown mouseup keydown keypress keyup touchstart touchend touchmove';
509 $(document
).bind(events
, opts
, handler
);
511 $(document
).unbind(events
, handler
);
514 // var $e = $('a,:input');
515 // b ? $e.bind(events, opts, handler) : $e.unbind(events, handler);
518 // event handler to suppress keyboard/mouse events when blocking
519 function handler(e
) {
520 // allow tab navigation (conditionally)
521 if (e
.keyCode
&& e
.keyCode
== 9) {
522 if (pageBlock
&& e
.data
.constrainTabKey
) {
523 var els
= pageBlockEls
;
524 var fwd
= !e
.shiftKey
&& e
.target
=== els
[els
.length
-1];
525 var back
= e
.shiftKey
&& e
.target
=== els
[0];
527 setTimeout(function(){focus(back
);},10);
533 var target
= $(e
.target
);
534 if (target
.hasClass('blockOverlay') && opts
.onOverlayClick
)
535 opts
.onOverlayClick();
537 // allow events within the message content
538 if (target
.parents('div.' + opts
.blockMsgClass
).length
> 0)
541 // allow events for content that is not being blocked
542 return target
.parents().children().filter('div.blockUI').length
=== 0;
545 function focus(back
) {
548 var e
= pageBlockEls
[back
===true ? pageBlockEls
.length
-1 : 0];
553 function center(el
, x
, y
) {
554 var p
= el
.parentNode
, s
= el
.style
;
555 var l
= ((p
.offsetWidth
- el
.offsetWidth
)/2) - sz(p
,'borderLeftWidth');
556 var t
= ((p
.offsetHeight
- el
.offsetHeight
)/2) - sz(p
,'borderTopWidth');
557 if (x
) s
.left
= l
> 0 ? (l
+'px') : '0';
558 if (y
) s
.top
= t
> 0 ? (t
+'px') : '0';
562 return parseInt($.css(el
,p
),10)||0;
568 /*global define:true */
569 if (typeof define
=== 'function' && define
.amd
&& define
.amd
.jQuery
) {
570 define(['jquery'], setup
);