From 56e299d4137053a8395760b765418f0ea7e6e6ee Mon Sep 17 00:00:00 2001 From: Naomi Date: Mon, 7 Apr 2014 16:47:52 -0400 Subject: [PATCH] CC-5778 : Improving Builder Rendering Time upgrading blockUI. check-builder-feed always caused the table to be drawn twice on first load. moved this check to builder.js since you can add to the now playing show on the calendar page as well. --- .../public/js/airtime/showbuilder/builder.js | 279 ++--- .../js/airtime/showbuilder/main_builder.js | 37 +- .../public/js/blockui/jquery.blockUI.js | 1026 +++++++++-------- 3 files changed, 682 insertions(+), 660 deletions(-) diff --git a/airtime_mvc/public/js/airtime/showbuilder/builder.js b/airtime_mvc/public/js/airtime/showbuilder/builder.js index 4dcc4334d..fbb9812f2 100644 --- a/airtime_mvc/public/js/airtime/showbuilder/builder.js +++ b/airtime_mvc/public/js/airtime/showbuilder/builder.js @@ -7,90 +7,77 @@ var AIRTIME = (function(AIRTIME){ $sbContent, $sbTable, $toolbar, - $ul, $lib, - cursors = [], - cursorIds = [], - showInstanceIds = [], - headerFooter = []; + internalTimestamp = -1, + internalShowInstances = [], + hasGottenFirstAjax = false; if (AIRTIME.showbuilder === undefined) { AIRTIME.showbuilder = {}; } mod = AIRTIME.showbuilder; - - function checkError(json) { - if (json.error !== undefined) { - alert(json.error); - } + + mod.timeout = undefined; + + function resetTimestamp() { + + internalTimestamp = -1; } - mod.timeout = undefined; - mod.timestamp = -1; - mod.showInstances = []; - - mod.resetTimestamp = function() { + function setTimestamp(timestamp) { - mod.timestamp = -1; - }; - - mod.setTimestamp = function(timestamp) { + internalTimestamp = timestamp; + } + + function getTimestamp() { - mod.timestamp = timestamp; - }; - - mod.updateCalendarStatusIcon = function(json) { - //make sure we are only executing this code on the calendar view, not - //the Now Playing view. - if (window.location.pathname.toLowerCase().indexOf("schedule") < 0) { - return; - } - - - var instance_id = json.schedule[0].instance; - - var lastElem = json.schedule[json.schedule.length-1]; - var $elem = $("#fc-show-instance-"+instance_id); - - //if the show is linked, then replace $elem to reference all linked - //instances - if ($elem.data("show-linked") == "1") { - var show_id = $elem.data("show-id"); - $elem = $('*[data-show-id="'+show_id+'"]'); - } - - $elem.find(".show-empty, .show-partial-filled").remove(); - if (json.schedule[1].empty) { - $elem - .find(".fc-event-inner") - .append(''); - } else if (lastElem["fRuntime"][0] == "-") { - $elem - .find(".fc-event-inner") - .append(''); - } + return internalTimestamp; }; - mod.getTimestamp = function() { - - if (mod.timestamp !== undefined) { - return mod.timestamp; - } - else { - return -1; - } + function setShowInstances(showInstances) { + internalShowInstances = showInstances; }; - mod.setShowInstances = function(showInstances) { - mod.showInstances = showInstances; + function getShowInstances() { + return internalShowInstances; }; - mod.getShowInstances = function() { - return mod.showInstances; - }; + function checkScheduleUpdates() { + var data = {}, + oTable = $('#show_builder_table').dataTable(), + fn = oTable.fnSettings().fnServerData, + start = fn.start, + end = fn.end; + + data["format"] = "json"; + data["start"] = start; + data["end"] = end; + data["timestamp"] = getTimestamp(); + data["instances"] = getShowInstances(); + + if (fn.hasOwnProperty("ops")) { + data["myShows"] = fn.ops.myShows; + data["showFilter"] = fn.ops.showFilter; + data["showInstanceFilter"] = fn.ops.showInstanceFilter; + } + + $.ajax( { + "dataType" : "json", + "type" : "GET", + "url" : baseUrl+"showbuilder/check-builder-feed", + "data" : data, + "success" : function(json) { + if (json.update === true) { + console.log("need to update builder table."); + oTable.fnDraw(); + } + setTimeout(checkScheduleUpdates, 5000); + } + }); + } mod.refresh = function(schedId) { - mod.resetTimestamp(); + resetTimestamp(); if (schedId > 0) { oSchedTable.fnDraw(); @@ -239,7 +226,7 @@ var AIRTIME = (function(AIRTIME){ }; mod.disableUI = function() { - + $lib.block({ message: "", theme: true, @@ -257,55 +244,20 @@ var AIRTIME = (function(AIRTIME){ $lib.unblock(); $sbContent.unblock(); - - //Block UI changes the postion to relative to display the messages. - $lib.css("position", "static"); - $sbContent.css("position", "static"); }; - mod.fnItemCallback = function(json) { - checkError(json); - - mod.getSelectedCursors(); + mod.fnRedrawSchedule = function(json) { + oSchedTable.fnDraw(); - mod.enableUI(); - //$("#library_content").find("#library_display").dataTable().fnStandingRedraw(); }; - mod.getSelectedCursors = function() { - cursorIds = []; - - /* We need to keep record of which show the cursor belongs to - * in the case where more than one show is displayed in the show builder - * because header and footer rows have the same id - */ - showInstanceIds = []; - - /* Keeps track if the row is a footer. We need to do this because - * header and footer rows have the save cursorIds and showInstanceId - * so both will be selected in the draw callback - */ - headerFooter = []; - - cursors = $(".cursor-selected-row"); - for (i = 0; i < cursors.length; i++) { - cursorIds.push(($(cursors.get(i)).attr("id"))); - showInstanceIds.push(($(cursors.get(i)).attr("si_id"))); - if ($(cursors.get(i)).hasClass("sb-footer")) { - headerFooter.push("f"); - } else { - headerFooter.push("n"); - } - } - }; - mod.fnAdd = function(aMediaIds, aSchedIds) { mod.disableUI(); $.post(baseUrl+"showbuilder/schedule-add", {"format": "json", "mediaIds": aMediaIds, "schedIds": aSchedIds}, - mod.fnItemCallback + mod.fnRedrawSchedule ); }; @@ -315,7 +267,7 @@ var AIRTIME = (function(AIRTIME){ $.post(baseUrl+"showbuilder/schedule-move", {"format": "json", "selectedItem": aSelect, "afterItem": aAfter}, - mod.fnItemCallback + mod.fnRedrawSchedule ); }; @@ -325,9 +277,10 @@ var AIRTIME = (function(AIRTIME){ if (confirm($.i18n._("Delete selected item(s)?"))) { $.post( baseUrl+"showbuilder/schedule-remove", {"items": aItems, "format": "json"}, - mod.fnItemCallback + mod.fnRedrawSchedule ); - }else{ + } + else { mod.enableUI(); } }; @@ -348,9 +301,11 @@ var AIRTIME = (function(AIRTIME){ }; mod.fnServerData = function fnBuilderServerData( sSource, aoData, fnCallback ) { + + console.log("getting builder feed."); - aoData.push( { name: "timestamp", value: mod.getTimestamp()} ); - aoData.push( { name: "instances", value: mod.getShowInstances()} ); + aoData.push( { name: "timestamp", value: getTimestamp()} ); + aoData.push( { name: "instances", value: getShowInstances()} ); aoData.push( { name: "format", value: "json"} ); if (mod.fnServerData.hasOwnProperty("start")) { @@ -371,11 +326,23 @@ var AIRTIME = (function(AIRTIME){ "url": sSource, "data": aoData, "success": function(json) { - mod.updateCalendarStatusIcon(json) - mod.setTimestamp(json.timestamp); - mod.setShowInstances(json.instances); - mod.getSelectedCursors(); - fnCallback(json); + if (json.error !== undefined) { + alert(json.error); + } + else { + fnCallback(json); + setTimestamp(json.timestamp); + setShowInstances(json.instances); + + if (!hasGottenFirstAjax) { + + hasGottenFirstAjax = true; + + //start this timeout + //check if the timeline view needs updating. + checkScheduleUpdates(); + } + } } }); }; @@ -389,14 +356,13 @@ var AIRTIME = (function(AIRTIME){ var currentTop = current.offset().top; $scroll.scrollTop(currentTop - scrollingTop + scrolled); - } + }; mod.builderDataTable = function() { $sbContent = $('#show_builder'); $lib = $("#library_content"), $sbTable = $sbContent.find('table'); - var isInitialized = false; - + oSchedTable = $sbTable.dataTable( { "aoColumns": [ /* checkbox */ {"mDataProp": "allowed", "sTitle": "", "sWidth": "15px", "sClass": "sb-checkbox"}, @@ -482,13 +448,18 @@ var AIRTIME = (function(AIRTIME){ $image, $div, headerIcon, - $wrapper; + $wrapper, + $marker; //http://stackoverflow.com/a/6119684 $wrapper = $("
", { "class": "innerWrapper" }); + $marker = $("
", { + "class": "marker" + }); + $node = $(nRow.children[0]); $node.html($wrapper); @@ -571,7 +542,9 @@ var AIRTIME = (function(AIRTIME){ //putting the cursor on the screen if (aData.allowed && $lib.length > 0 && $lib.filter(":visible").length > 0) { - $wrapper.append('
'); + //using this input just for cursor positioning purposes. + $wrapper.append(''); + $wrapper.append($marker); } sSeparatorHTML = ''+$.i18n._("Show Empty")+''; @@ -621,11 +594,11 @@ var AIRTIME = (function(AIRTIME){ } if (aData.allowed === true && aData.scheduled >= 1) { - $wrapper.html(''); + $wrapper.append(''); //putting the cursor on the screen if ($lib.length > 0 && $lib.filter(":visible").length > 0) { - $wrapper.append('
'); + $wrapper.append($marker); } } } @@ -698,58 +671,24 @@ var AIRTIME = (function(AIRTIME){ $("#draggingContainer").remove(); }, "fnDrawCallback": function fnBuilderDrawCallback(oSettings, json) { - var isInitialized = false; //var timer1 = new Date().getTime(); + + var aData, + elements, + i, length, temp, + $cursorRows, + $table = $(this); - if (!isInitialized) { - //when coming to 'Now Playing' page we want the page - //to jump to the current track - if ($(this).find("."+NOW_PLAYING_CLASS).length > 0) { - mod.jumpToCurrentTrack(); - } - } - - isInitialized = true; - var aData, - elements, - i, length, temp, - $cursorRows, - $table = $(this); + if ($(this).find("."+NOW_PLAYING_CLASS).length > 0) { + mod.jumpToCurrentTrack(); + } clearTimeout(mod.timeout); //only create the cursor arrows if the library is on the page. if ($lib.length > 0 && $lib.filter(":visible").length > 0) { - //$cursorRows = $sbTable.find("tbody tr.sb-future.sb-allowed:not(.sb-header, .sb-empty)"); $cursorRows = $sbTable.find("div.marker").parents("tr"); - - //re-highlight selected cursors before draw took place - /* - for (i = 0; i < cursorIds.length; i++) { - if (headerFooter[i] == "f") { - $tr = $table.find("tbody tr.sb-footer[id="+cursorIds[i]+"][si_id="+showInstanceIds[i]+"]"); - } else { - $tr = $table.find("tr[id="+cursorIds[i]+"][si_id="+showInstanceIds[i]+"]"); - } - - // If the currently playing track's cursor is selected, - //and that track is deleted, the cursor position becomes - //unavailble. We have to check the position is available - // before re-highlighting it. - // - if ($tr.find(".sb-checkbox").children().hasClass("innerWrapper")) { - mod.selectCursor($tr); - - // If the selected cursor is the footer row we need to - //explicitly select it because that row does not have - // innerWrapper class - // - } else if ($tr.hasClass("sb-footer")) { - mod.selectCursor($tr); - } - } - */ //if there is only 1 cursor on the page highlight it by default. if ($cursorRows.length === 1) { @@ -773,7 +712,7 @@ var AIRTIME = (function(AIRTIME){ // setTimeout allows only up to (2^31)-1 millisecs timeout value maxRefreshInterval = Math.pow(2, 31) - 1; refreshInterval = aData.refresh * 1000; - if(refreshInterval > maxRefreshInterval){ + if (refreshInterval > maxRefreshInterval){ refreshInterval = maxRefreshInterval; } mod.timeout = setTimeout(function() {mod.refresh(aData.id)}, refreshInterval); //need refresh in milliseconds @@ -1027,8 +966,8 @@ var AIRTIME = (function(AIRTIME){ $toolbar.append($menu); $menu = undefined; - $('#timeline-sa').click(function(){mod.selectAll();}); - $('#timeline-sn').click(function(){mod.selectNone();}); + $('#timeline-sa').click(mod.selectAll); + $('#timeline-sn').click(mod.selectNone); //cancel current show $toolbar.find('.sb-cancel').click(function() { @@ -1167,13 +1106,13 @@ var AIRTIME = (function(AIRTIME){ } //only show the cursor selecting options if the library is visible on the page. - if ($tr.next().find('.marker').length === 0) { + if ($tr.find('.marker').length === 0) { delete oItems.selCurs; delete oItems.delCurs; } //check to include either select or remove cursor. else { - if ($tr.next().hasClass(cursorClass)) { + if ($tr.hasClass(cursorClass)) { delete oItems.selCurs; } else { diff --git a/airtime_mvc/public/js/airtime/showbuilder/main_builder.js b/airtime_mvc/public/js/airtime/showbuilder/main_builder.js index 1d81a8f95..5ce3c375e 100644 --- a/airtime_mvc/public/js/airtime/showbuilder/main_builder.js +++ b/airtime_mvc/public/js/airtime/showbuilder/main_builder.js @@ -130,6 +130,7 @@ AIRTIME = (function(AIRTIME) { AIRTIME.showbuilder.fnServerData.start = oRange.start; AIRTIME.showbuilder.fnServerData.end = oRange.end; + console.log("calling builder datatable"); AIRTIME.showbuilder.builderDataTable(); $libWrapper = $lib.find(".ui-tabs-nav"); @@ -218,42 +219,6 @@ AIRTIME = (function(AIRTIME) { showSearchSubmit(); }); - - function checkScheduleUpdates() { - var data = {}, - oTable = $('#show_builder_table').dataTable(), - fn = oTable.fnSettings().fnServerData, - start = fn.start, - end = fn.end; - - data["format"] = "json"; - data["start"] = start; - data["end"] = end; - data["timestamp"] = AIRTIME.showbuilder.getTimestamp(); - data["instances"] = AIRTIME.showbuilder.getShowInstances(); - - if (fn.hasOwnProperty("ops")) { - data["myShows"] = fn.ops.myShows; - data["showFilter"] = fn.ops.showFilter; - data["showInstanceFilter"] = fn.ops.showInstanceFilter; - } - - $.ajax( { - "dataType" : "json", - "type" : "GET", - "url" : baseUrl+"showbuilder/check-builder-feed", - "data" : data, - "success" : function(json) { - if (json.update === true) { - oTable.fnDraw(); - } - setTimeout(checkScheduleUpdates, 5000); - } - }); - } - - //check if the timeline view needs updating. - checkScheduleUpdates(); }; return AIRTIME; diff --git a/airtime_mvc/public/js/blockui/jquery.blockUI.js b/airtime_mvc/public/js/blockui/jquery.blockUI.js index e3c394a26..ddf7ae364 100644 --- a/airtime_mvc/public/js/blockui/jquery.blockUI.js +++ b/airtime_mvc/public/js/blockui/jquery.blockUI.js @@ -1,10 +1,10 @@ /*! * jQuery blockUI plugin - * Version 2.39 (23-MAY-2011) - * @requires jQuery v1.2.3 or later + * Version 2.66.0-2013.10.09 + * Requires jQuery v1.7 or later * * Examples at: http://malsup.com/jquery/block/ - * Copyright (c) 2007-2010 M. Alsup + * Copyright (c) 2007-2013 M. Alsup * Dual licensed under the MIT and GPL licenses: * http://www.opensource.org/licenses/mit-license.php * http://www.gnu.org/licenses/gpl.html @@ -12,490 +12,608 @@ * Thanks to Amir-Hossein Sobhi for some excellent contributions! */ -;(function($) { +;(function() { +/*jshint eqeqeq:false curly:false latedef:false */ +"use strict"; -/* -if (/1\.(0|1|2)\.(0|1|2)/.test($.fn.jquery) || /^1.1/.test($.fn.jquery)) { - alert('blockUI requires jQuery v1.2.3 or later! You are using v' + $.fn.jquery); - return; -} -*/ + function setup($) { + $.fn._fadeIn = $.fn.fadeIn; -$.fn._fadeIn = $.fn.fadeIn; + var noOp = $.noop || function() {}; -var noOp = function() {}; + // this bit is to ensure we don't call setExpression when we shouldn't (with extra muscle to handle + // confusing userAgent strings on Vista) + var msie = /MSIE/.test(navigator.userAgent); + var ie6 = /MSIE 6.0/.test(navigator.userAgent) && ! /MSIE 8.0/.test(navigator.userAgent); + var mode = document.documentMode || 0; + var setExpr = $.isFunction( document.createElement('div').style.setExpression ); -// this bit is to ensure we don't call setExpression when we shouldn't (with extra muscle to handle -// retarded userAgent strings on Vista) -var mode = document.documentMode || 0; -var setExpr = $.browser.msie && (($.browser.version < 8 && !mode) || mode < 8); -var ie6 = $.browser.msie && /MSIE 6.0/.test(navigator.userAgent) && !mode; + // global $ methods for blocking/unblocking the entire page + $.blockUI = function(opts) { install(window, opts); }; + $.unblockUI = function(opts) { remove(window, opts); }; -// global $ methods for blocking/unblocking the entire page -$.blockUI = function(opts) { install(window, opts); }; -$.unblockUI = function(opts) { remove(window, opts); }; + // convenience method for quick growl-like notifications (http://www.google.com/search?q=growl) + $.growlUI = function(title, message, timeout, onClose) { + var $m = $('
'); + if (title) $m.append('

'+title+'

'); + if (message) $m.append('

'+message+'

'); + if (timeout === undefined) timeout = 3000; -// convenience method for quick growl-like notifications (http://www.google.com/search?q=growl) -$.growlUI = function(title, message, timeout, onClose) { - var $m = $('
'); - if (title) $m.append('

'+title+'

'); - if (message) $m.append('

'+message+'

'); - if (timeout == undefined) timeout = 3000; - $.blockUI({ - message: $m, fadeIn: 700, fadeOut: 1000, centerY: false, - timeout: timeout, showOverlay: false, - onUnblock: onClose, - css: $.blockUI.defaults.growlCSS - }); -}; + // Added by konapun: Set timeout to 30 seconds if this growl is moused over, like normal toast notifications + var callBlock = function(opts) { + opts = opts || {}; -// plugin method for blocking element content -$.fn.block = function(opts) { - return this.unblock({ fadeOut: 0 }).each(function() { - if ($.css(this,'position') == 'static') - this.style.position = 'relative'; - if ($.browser.msie) - this.style.zoom = 1; // force 'hasLayout' - install(this, opts); - }); -}; + $.blockUI({ + message: $m, + fadeIn : typeof opts.fadeIn !== 'undefined' ? opts.fadeIn : 700, + fadeOut: typeof opts.fadeOut !== 'undefined' ? opts.fadeOut : 1000, + timeout: typeof opts.timeout !== 'undefined' ? opts.timeout : timeout, + centerY: false, + showOverlay: false, + onUnblock: onClose, + css: $.blockUI.defaults.growlCSS + }); + }; -// plugin method for unblocking element content -$.fn.unblock = function(opts) { - return this.each(function() { - remove(this, opts); - }); -}; + callBlock(); + var nonmousedOpacity = $m.css('opacity'); + $m.mouseover(function() { + callBlock({ + fadeIn: 0, + timeout: 30000 + }); -$.blockUI.version = 2.39; // 2nd generation blocking at no extra cost! + var displayBlock = $('.blockMsg'); + displayBlock.stop(); // cancel fadeout if it has started + displayBlock.fadeTo(300, 1); // make it easier to read the message by removing transparency + }).mouseout(function() { + $('.blockMsg').fadeOut(1000); + }); + // End konapun additions + }; -// override these in your code to change the default behavior and style -$.blockUI.defaults = { - // message displayed when blocking (use null for no message) - message: '

Please wait...

', - - title: null, // title string; only used when theme == true - draggable: true, // only used when theme == true (requires jquery-ui.js to be loaded) - - theme: false, // set to true to use with jQuery UI themes - - // styles for the message when blocking; if you wish to disable - // these and use an external stylesheet then do this in your code: - // $.blockUI.defaults.css = {}; - css: { - padding: 0, - margin: 0, - width: '30%', - top: '40%', - left: '35%', - textAlign: 'center', - color: '#000', - border: '3px solid #aaa', - backgroundColor:'#fff', - cursor: 'wait' - }, - - // minimal style set used when themes are used - themedCSS: { - width: '30%', - top: '40%', - left: '35%' - }, - - // styles for the overlay - overlayCSS: { - backgroundColor: '#000', - opacity: 0.6, - cursor: 'wait' - }, - - // styles applied when using $.growlUI - growlCSS: { - width: '350px', - top: '10px', - left: '', - right: '10px', - border: 'none', - padding: '5px', - opacity: 0.6, - cursor: 'default', - color: '#fff', - backgroundColor: '#000', - '-webkit-border-radius': '10px', - '-moz-border-radius': '10px', - 'border-radius': '10px' - }, - - // IE issues: 'about:blank' fails on HTTPS and javascript:false is s-l-o-w - // (hat tip to Jorge H. N. de Vasconcelos) - iframeSrc: /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank', - - // force usage of iframe in non-IE browsers (handy for blocking applets) - forceIframe: false, - - // z-index for the blocking overlay - baseZ: 1000, - - // set these to true to have the message automatically centered - centerX: true, // <-- only effects element blocking (page block controlled via css above) - centerY: true, - - // allow body element to be stetched in ie6; this makes blocking look better - // on "short" pages. disable if you wish to prevent changes to the body height - allowBodyStretch: true, - - // enable if you want key and mouse events to be disabled for content that is blocked - bindEvents: true, - - // be default blockUI will supress tab navigation from leaving blocking content - // (if bindEvents is true) - constrainTabKey: true, - - // fadeIn time in millis; set to 0 to disable fadeIn on block - fadeIn: 200, - - // fadeOut time in millis; set to 0 to disable fadeOut on unblock - fadeOut: 400, - - // time in millis to wait before auto-unblocking; set to 0 to disable auto-unblock - timeout: 0, - - // disable if you don't want to show the overlay - showOverlay: true, - - // if true, focus will be placed in the first available input field when - // page blocking - focusInput: true, - - // suppresses the use of overlay styles on FF/Linux (due to performance issues with opacity) - applyPlatformOpacityRules: true, - - // callback method invoked when fadeIn has completed and blocking message is visible - onBlock: null, - - // callback method invoked when unblocking has completed; the callback is - // passed the element that has been unblocked (which is the window object for page - // blocks) and the options that were passed to the unblock call: - // onUnblock(element, options) - onUnblock: null, - - // don't ask; if you really must know: http://groups.google.com/group/jquery-en/browse_thread/thread/36640a8730503595/2f6a79a77a78e493#2f6a79a77a78e493 - quirksmodeOffsetHack: 4, - - // class name of the message block - blockMsgClass: 'blockMsg' -}; - -// private data and functions follow... - -var pageBlock = null; -var pageBlockEls = []; - -function install(el, opts) { - var full = (el == window); - var msg = opts && opts.message !== undefined ? opts.message : undefined; - opts = $.extend({}, $.blockUI.defaults, opts || {}); - opts.overlayCSS = $.extend({}, $.blockUI.defaults.overlayCSS, opts.overlayCSS || {}); - var css = $.extend({}, $.blockUI.defaults.css, opts.css || {}); - var themedCSS = $.extend({}, $.blockUI.defaults.themedCSS, opts.themedCSS || {}); - msg = msg === undefined ? opts.message : msg; - - // remove the current block (if there is one) - if (full && pageBlock) - remove(window, {fadeOut:0}); - - // if an existing element is being used as the blocking content then we capture - // its current place in the DOM (and current display style) so we can restore - // it when we unblock - if (msg && typeof msg != 'string' && (msg.parentNode || msg.jquery)) { - var node = msg.jquery ? msg[0] : msg; - var data = {}; - $(el).data('blockUI.history', data); - data.el = node; - data.parent = node.parentNode; - data.display = node.style.display; - data.position = node.style.position; - if (data.parent) - data.parent.removeChild(node); - } - - $(el).data('blockUI.onUnblock', opts.onUnblock); - var z = opts.baseZ; - - // blockUI uses 3 layers for blocking, for simplicity they are all used on every platform; - // layer1 is the iframe layer which is used to supress bleed through of underlying content - // layer2 is the overlay layer which has opacity and a wait cursor (by default) - // layer3 is the message content that is displayed while blocking - - var lyr1 = ($.browser.msie || opts.forceIframe) - ? $('') - : $(''); - - var lyr2 = opts.theme - ? $('') - : $(''); - - var lyr3, s; - if (opts.theme && full) { - s = ''; - } - else if (opts.theme) { - s = ''; - } - else if (full) { - s = ''; - } - else { - s = ''; - } - lyr3 = $(s); - - // if we have a message, style it - if (msg) { - if (opts.theme) { - lyr3.css(themedCSS); - lyr3.addClass('ui-widget-content'); - } - else - lyr3.css(css); - } - - // style the overlay - if (!opts.theme && (!opts.applyPlatformOpacityRules || !($.browser.mozilla && /Linux/.test(navigator.platform)))) - lyr2.css(opts.overlayCSS); - lyr2.css('position', full ? 'fixed' : 'absolute'); - - // make iframe layer transparent in IE - if ($.browser.msie || opts.forceIframe) - lyr1.css('opacity',0.0); - - //$([lyr1[0],lyr2[0],lyr3[0]]).appendTo(full ? 'body' : el); - var layers = [lyr1,lyr2,lyr3], $par = full ? $('body') : $(el); - $.each(layers, function() { - this.appendTo($par); - }); - - if (opts.theme && opts.draggable && $.fn.draggable) { - lyr3.draggable({ - handle: '.ui-dialog-titlebar', - cancel: 'li' - }); - } - - // ie7 must use absolute positioning in quirks mode and to account for activex issues (when scrolling) - var expr = setExpr && (!$.boxModel || $('object,embed', full ? null : el).length > 0); - if (ie6 || expr) { - // give body 100% height - if (full && opts.allowBodyStretch && $.boxModel) - $('html,body').css('height','100%'); - - // fix ie6 issue when blocked element has a border width - if ((ie6 || !$.boxModel) && !full) { - var t = sz(el,'borderTopWidth'), l = sz(el,'borderLeftWidth'); - var fixT = t ? '(0 - '+t+')' : 0; - var fixL = l ? '(0 - '+l+')' : 0; - } - - // simulate fixed position - $.each([lyr1,lyr2,lyr3], function(i,o) { - var s = o[0].style; - s.position = 'absolute'; - if (i < 2) { - full ? s.setExpression('height','Math.max(document.body.scrollHeight, document.body.offsetHeight) - (jQuery.boxModel?0:'+opts.quirksmodeOffsetHack+') + "px"') - : s.setExpression('height','this.parentNode.offsetHeight + "px"'); - full ? s.setExpression('width','jQuery.boxModel && document.documentElement.clientWidth || document.body.clientWidth + "px"') - : s.setExpression('width','this.parentNode.offsetWidth + "px"'); - if (fixL) s.setExpression('left', fixL); - if (fixT) s.setExpression('top', fixT); + // plugin method for blocking element content + $.fn.block = function(opts) { + if ( this[0] === window ) { + $.blockUI( opts ); + return this; } - else if (opts.centerY) { - 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"'); - s.marginTop = 0; + var fullOpts = $.extend({}, $.blockUI.defaults, opts || {}); + this.each(function() { + var $el = $(this); + if (fullOpts.ignoreIfBlocked && $el.data('blockUI.isBlocked')) + return; + $el.unblock({ fadeOut: 0 }); + }); + + return this.each(function() { + if ($.css(this,'position') == 'static') { + this.style.position = 'relative'; + $(this).data('blockUI.static', true); + } + this.style.zoom = 1; // force 'hasLayout' in ie + install(this, opts); + }); + }; + + // plugin method for unblocking element content + $.fn.unblock = function(opts) { + if ( this[0] === window ) { + $.unblockUI( opts ); + return this; } - else if (!opts.centerY && full) { - var top = (opts.css && opts.css.top) ? parseInt(opts.css.top) : 0; - var expression = '((document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + '+top+') + "px"'; - s.setExpression('top',expression); + return this.each(function() { + remove(this, opts); + }); + }; + + $.blockUI.version = 2.66; // 2nd generation blocking at no extra cost! + + // override these in your code to change the default behavior and style + $.blockUI.defaults = { + // message displayed when blocking (use null for no message) + message: '

Please wait...

', + + title: null, // title string; only used when theme == true + draggable: true, // only used when theme == true (requires jquery-ui.js to be loaded) + + theme: false, // set to true to use with jQuery UI themes + + // styles for the message when blocking; if you wish to disable + // these and use an external stylesheet then do this in your code: + // $.blockUI.defaults.css = {}; + css: { + padding: 0, + margin: 0, + width: '30%', + top: '40%', + left: '35%', + textAlign: 'center', + color: '#000', + border: '3px solid #aaa', + backgroundColor:'#fff', + cursor: 'wait' + }, + + // minimal style set used when themes are used + themedCSS: { + width: '30%', + top: '40%', + left: '35%' + }, + + // styles for the overlay + overlayCSS: { + backgroundColor: '#000', + opacity: 0.6, + cursor: 'wait' + }, + + // style to replace wait cursor before unblocking to correct issue + // of lingering wait cursor + cursorReset: 'default', + + // styles applied when using $.growlUI + growlCSS: { + width: '350px', + top: '10px', + left: '', + right: '10px', + border: 'none', + padding: '5px', + opacity: 0.6, + cursor: 'default', + color: '#fff', + backgroundColor: '#000', + '-webkit-border-radius':'10px', + '-moz-border-radius': '10px', + 'border-radius': '10px' + }, + + // IE issues: 'about:blank' fails on HTTPS and javascript:false is s-l-o-w + // (hat tip to Jorge H. N. de Vasconcelos) + /*jshint scripturl:true */ + iframeSrc: /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank', + + // force usage of iframe in non-IE browsers (handy for blocking applets) + forceIframe: false, + + // z-index for the blocking overlay + baseZ: 1000, + + // set these to true to have the message automatically centered + centerX: true, // <-- only effects element blocking (page block controlled via css above) + centerY: true, + + // allow body element to be stetched in ie6; this makes blocking look better + // on "short" pages. disable if you wish to prevent changes to the body height + allowBodyStretch: true, + + // enable if you want key and mouse events to be disabled for content that is blocked + bindEvents: true, + + // be default blockUI will supress tab navigation from leaving blocking content + // (if bindEvents is true) + constrainTabKey: true, + + // fadeIn time in millis; set to 0 to disable fadeIn on block + fadeIn: 200, + + // fadeOut time in millis; set to 0 to disable fadeOut on unblock + fadeOut: 400, + + // time in millis to wait before auto-unblocking; set to 0 to disable auto-unblock + timeout: 0, + + // disable if you don't want to show the overlay + showOverlay: true, + + // if true, focus will be placed in the first available input field when + // page blocking + focusInput: true, + + // elements that can receive focus + focusableElements: ':input:enabled:visible', + + // suppresses the use of overlay styles on FF/Linux (due to performance issues with opacity) + // no longer needed in 2012 + // applyPlatformOpacityRules: true, + + // callback method invoked when fadeIn has completed and blocking message is visible + onBlock: null, + + // callback method invoked when unblocking has completed; the callback is + // passed the element that has been unblocked (which is the window object for page + // blocks) and the options that were passed to the unblock call: + // onUnblock(element, options) + onUnblock: null, + + // callback method invoked when the overlay area is clicked. + // setting this will turn the cursor to a pointer, otherwise cursor defined in overlayCss will be used. + onOverlayClick: null, + + // don't ask; if you really must know: http://groups.google.com/group/jquery-en/browse_thread/thread/36640a8730503595/2f6a79a77a78e493#2f6a79a77a78e493 + quirksmodeOffsetHack: 4, + + // class name of the message block + blockMsgClass: 'blockMsg', + + // if it is already blocked, then ignore it (don't unblock and reblock) + ignoreIfBlocked: false + }; + + // private data and functions follow... + + var pageBlock = null; + var pageBlockEls = []; + + function install(el, opts) { + var css, themedCSS; + var full = (el == window); + var msg = (opts && opts.message !== undefined ? opts.message : undefined); + opts = $.extend({}, $.blockUI.defaults, opts || {}); + + if (opts.ignoreIfBlocked && $(el).data('blockUI.isBlocked')) + return; + + opts.overlayCSS = $.extend({}, $.blockUI.defaults.overlayCSS, opts.overlayCSS || {}); + css = $.extend({}, $.blockUI.defaults.css, opts.css || {}); + if (opts.onOverlayClick) + opts.overlayCSS.cursor = 'pointer'; + + themedCSS = $.extend({}, $.blockUI.defaults.themedCSS, opts.themedCSS || {}); + msg = msg === undefined ? opts.message : msg; + + // remove the current block (if there is one) + if (full && pageBlock) + remove(window, {fadeOut:0}); + + // if an existing element is being used as the blocking content then we capture + // its current place in the DOM (and current display style) so we can restore + // it when we unblock + if (msg && typeof msg != 'string' && (msg.parentNode || msg.jquery)) { + var node = msg.jquery ? msg[0] : msg; + var data = {}; + $(el).data('blockUI.history', data); + data.el = node; + data.parent = node.parentNode; + data.display = node.style.display; + data.position = node.style.position; + if (data.parent) + data.parent.removeChild(node); } - }); - } - // show the message - if (msg) { - if (opts.theme) - lyr3.find('.ui-widget-content').append(msg); - else - lyr3.append(msg); - if (msg.jquery || msg.nodeType) - $(msg).show(); - } + $(el).data('blockUI.onUnblock', opts.onUnblock); + var z = opts.baseZ; - if (($.browser.msie || opts.forceIframe) && opts.showOverlay) - lyr1.show(); // opacity is zero - if (opts.fadeIn) { - var cb = opts.onBlock ? opts.onBlock : noOp; - var cb1 = (opts.showOverlay && !msg) ? cb : noOp; - var cb2 = msg ? cb : noOp; - if (opts.showOverlay) - lyr2._fadeIn(opts.fadeIn, cb1); - if (msg) - lyr3._fadeIn(opts.fadeIn, cb2); - } - else { - if (opts.showOverlay) - lyr2.show(); - if (msg) - lyr3.show(); - if (opts.onBlock) - opts.onBlock(); - } + // blockUI uses 3 layers for blocking, for simplicity they are all used on every platform; + // layer1 is the iframe layer which is used to supress bleed through of underlying content + // layer2 is the overlay layer which has opacity and a wait cursor (by default) + // layer3 is the message content that is displayed while blocking + var lyr1, lyr2, lyr3, s; + if (msie || opts.forceIframe) + lyr1 = $(''); + else + lyr1 = $(''); - // bind key and mouse events - bind(1, el, opts); + if (opts.theme) + lyr2 = $(''); + else + lyr2 = $(''); - if (full) { - pageBlock = lyr3[0]; - pageBlockEls = $(':input:enabled:visible',pageBlock); - if (opts.focusInput) - setTimeout(focus, 20); - } - else - center(lyr3[0], opts.centerX, opts.centerY); + if (opts.theme && full) { + s = ''; + } + else if (opts.theme) { + s = ''; + } + else if (full) { + s = ''; + } + else { + s = ''; + } + lyr3 = $(s); - if (opts.timeout) { - // auto-unblock - var to = setTimeout(function() { - full ? $.unblockUI(opts) : $(el).unblock(opts); - }, opts.timeout); - $(el).data('blockUI.timeout', to); - } -}; + // if we have a message, style it + if (msg) { + if (opts.theme) { + lyr3.css(themedCSS); + lyr3.addClass('ui-widget-content'); + } + else + lyr3.css(css); + } -// remove the block -function remove(el, opts) { - var full = (el == window); - var $el = $(el); - var data = $el.data('blockUI.history'); - var to = $el.data('blockUI.timeout'); - if (to) { - clearTimeout(to); - $el.removeData('blockUI.timeout'); - } - opts = $.extend({}, $.blockUI.defaults, opts || {}); - bind(0, el, opts); // unbind events + // style the overlay + if (!opts.theme /*&& (!opts.applyPlatformOpacityRules)*/) + lyr2.css(opts.overlayCSS); + lyr2.css('position', full ? 'fixed' : 'absolute'); - if (opts.onUnblock === null) { - opts.onUnblock = $el.data('blockUI.onUnblock'); - $el.removeData('blockUI.onUnblock'); - } + // make iframe layer transparent in IE + if (msie || opts.forceIframe) + lyr1.css('opacity',0.0); - var els; - if (full) // crazy selector to handle odd field errors in ie6/7 - els = $('body').children().filter('.blockUI').add('body > .blockUI'); - else - els = $('.blockUI', el); + //$([lyr1[0],lyr2[0],lyr3[0]]).appendTo(full ? 'body' : el); + var layers = [lyr1,lyr2,lyr3], $par = full ? $('body') : $(el); + $.each(layers, function() { + this.appendTo($par); + }); - if (full) - pageBlock = pageBlockEls = null; + if (opts.theme && opts.draggable && $.fn.draggable) { + lyr3.draggable({ + handle: '.ui-dialog-titlebar', + cancel: 'li' + }); + } - if (opts.fadeOut) { - els.fadeOut(opts.fadeOut); - setTimeout(function() { reset(els,data,opts,el); }, opts.fadeOut); - } - else - reset(els, data, opts, el); -}; + // ie7 must use absolute positioning in quirks mode and to account for activex issues (when scrolling) + var expr = setExpr && (!$.support.boxModel || $('object,embed', full ? null : el).length > 0); + if (ie6 || expr) { + // give body 100% height + if (full && opts.allowBodyStretch && $.support.boxModel) + $('html,body').css('height','100%'); -// move blocking element back into the DOM where it started -function reset(els,data,opts,el) { - els.each(function(i,o) { - // remove via DOM calls so we don't lose event handlers - if (this.parentNode) - this.parentNode.removeChild(this); - }); + // fix ie6 issue when blocked element has a border width + if ((ie6 || !$.support.boxModel) && !full) { + var t = sz(el,'borderTopWidth'), l = sz(el,'borderLeftWidth'); + var fixT = t ? '(0 - '+t+')' : 0; + var fixL = l ? '(0 - '+l+')' : 0; + } - if (data && data.el) { - data.el.style.display = data.display; - data.el.style.position = data.position; - if (data.parent) - data.parent.appendChild(data.el); - $(el).removeData('blockUI.history'); - } + // simulate fixed position + $.each(layers, function(i,o) { + var s = o[0].style; + s.position = 'absolute'; + if (i < 2) { + if (full) + s.setExpression('height','Math.max(document.body.scrollHeight, document.body.offsetHeight) - (jQuery.support.boxModel?0:'+opts.quirksmodeOffsetHack+') + "px"'); + else + s.setExpression('height','this.parentNode.offsetHeight + "px"'); + if (full) + s.setExpression('width','jQuery.support.boxModel && document.documentElement.clientWidth || document.body.clientWidth + "px"'); + else + s.setExpression('width','this.parentNode.offsetWidth + "px"'); + if (fixL) s.setExpression('left', fixL); + if (fixT) s.setExpression('top', fixT); + } + else if (opts.centerY) { + 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"'); + s.marginTop = 0; + } + else if (!opts.centerY && full) { + var top = (opts.css && opts.css.top) ? parseInt(opts.css.top, 10) : 0; + var expression = '((document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + '+top+') + "px"'; + s.setExpression('top',expression); + } + }); + } - if (typeof opts.onUnblock == 'function') - opts.onUnblock(el,opts); -}; + // show the message + if (msg) { + if (opts.theme) + lyr3.find('.ui-widget-content').append(msg); + else + lyr3.append(msg); + if (msg.jquery || msg.nodeType) + $(msg).show(); + } -// bind/unbind the handler -function bind(b, el, opts) { - var full = el == window, $el = $(el); + if ((msie || opts.forceIframe) && opts.showOverlay) + lyr1.show(); // opacity is zero + if (opts.fadeIn) { + var cb = opts.onBlock ? opts.onBlock : noOp; + var cb1 = (opts.showOverlay && !msg) ? cb : noOp; + var cb2 = msg ? cb : noOp; + if (opts.showOverlay) + lyr2._fadeIn(opts.fadeIn, cb1); + if (msg) + lyr3._fadeIn(opts.fadeIn, cb2); + } + else { + if (opts.showOverlay) + lyr2.show(); + if (msg) + lyr3.show(); + if (opts.onBlock) + opts.onBlock(); + } - // don't bother unbinding if there is nothing to unbind - if (!b && (full && !pageBlock || !full && !$el.data('blockUI.isBlocked'))) - return; - if (!full) - $el.data('blockUI.isBlocked', b); + // bind key and mouse events + bind(1, el, opts); - // don't bind events when overlay is not in use or if bindEvents is false - if (!opts.bindEvents || (b && !opts.showOverlay)) - return; + if (full) { + pageBlock = lyr3[0]; + pageBlockEls = $(opts.focusableElements,pageBlock); + if (opts.focusInput) + setTimeout(focus, 20); + } + else + center(lyr3[0], opts.centerX, opts.centerY); - // bind anchors and inputs for mouse and key events - var events = 'mousedown mouseup keydown keypress'; - b ? $(document).bind(events, opts, handler) : $(document).unbind(events, handler); - -// former impl... -// var $e = $('a,:input'); -// b ? $e.bind(events, opts, handler) : $e.unbind(events, handler); -}; - -// event handler to suppress keyboard/mouse events when blocking -function handler(e) { - // allow tab navigation (conditionally) - if (e.keyCode && e.keyCode == 9) { - if (pageBlock && e.data.constrainTabKey) { - var els = pageBlockEls; - var fwd = !e.shiftKey && e.target === els[els.length-1]; - var back = e.shiftKey && e.target === els[0]; - if (fwd || back) { - setTimeout(function(){focus(back)},10); - return false; + if (opts.timeout) { + // auto-unblock + var to = setTimeout(function() { + if (full) + $.unblockUI(opts); + else + $(el).unblock(opts); + }, opts.timeout); + $(el).data('blockUI.timeout', to); } } + + // remove the block + function remove(el, opts) { + var count; + var full = (el == window); + var $el = $(el); + var data = $el.data('blockUI.history'); + var to = $el.data('blockUI.timeout'); + if (to) { + clearTimeout(to); + $el.removeData('blockUI.timeout'); + } + opts = $.extend({}, $.blockUI.defaults, opts || {}); + bind(0, el, opts); // unbind events + + if (opts.onUnblock === null) { + opts.onUnblock = $el.data('blockUI.onUnblock'); + $el.removeData('blockUI.onUnblock'); + } + + var els; + if (full) // crazy selector to handle odd field errors in ie6/7 + els = $('body').children().filter('.blockUI').add('body > .blockUI'); + else + els = $el.find('>.blockUI'); + + // fix cursor issue + if ( opts.cursorReset ) { + if ( els.length > 1 ) + els[1].style.cursor = opts.cursorReset; + if ( els.length > 2 ) + els[2].style.cursor = opts.cursorReset; + } + + if (full) + pageBlock = pageBlockEls = null; + + if (opts.fadeOut) { + count = els.length; + els.stop().fadeOut(opts.fadeOut, function() { + if ( --count === 0) + reset(els,data,opts,el); + }); + } + else + reset(els, data, opts, el); + } + + // move blocking element back into the DOM where it started + function reset(els,data,opts,el) { + var $el = $(el); + if ( $el.data('blockUI.isBlocked') ) + return; + + els.each(function(i,o) { + // remove via DOM calls so we don't lose event handlers + if (this.parentNode) + this.parentNode.removeChild(this); + }); + + if (data && data.el) { + data.el.style.display = data.display; + data.el.style.position = data.position; + if (data.parent) + data.parent.appendChild(data.el); + $el.removeData('blockUI.history'); + } + + if ($el.data('blockUI.static')) { + $el.css('position', 'static'); // #22 + } + + if (typeof opts.onUnblock == 'function') + opts.onUnblock(el,opts); + + // fix issue in Safari 6 where block artifacts remain until reflow + var body = $(document.body), w = body.width(), cssW = body[0].style.width; + body.width(w-1).width(w); + body[0].style.width = cssW; + } + + // bind/unbind the handler + function bind(b, el, opts) { + var full = el == window, $el = $(el); + + // don't bother unbinding if there is nothing to unbind + if (!b && (full && !pageBlock || !full && !$el.data('blockUI.isBlocked'))) + return; + + $el.data('blockUI.isBlocked', b); + + // don't bind events when overlay is not in use or if bindEvents is false + if (!full || !opts.bindEvents || (b && !opts.showOverlay)) + return; + + // bind anchors and inputs for mouse and key events + var events = 'mousedown mouseup keydown keypress keyup touchstart touchend touchmove'; + if (b) + $(document).bind(events, opts, handler); + else + $(document).unbind(events, handler); + + // former impl... + // var $e = $('a,:input'); + // b ? $e.bind(events, opts, handler) : $e.unbind(events, handler); + } + + // event handler to suppress keyboard/mouse events when blocking + function handler(e) { + // allow tab navigation (conditionally) + if (e.type === 'keydown' && e.keyCode && e.keyCode == 9) { + if (pageBlock && e.data.constrainTabKey) { + var els = pageBlockEls; + var fwd = !e.shiftKey && e.target === els[els.length-1]; + var back = e.shiftKey && e.target === els[0]; + if (fwd || back) { + setTimeout(function(){focus(back);},10); + return false; + } + } + } + var opts = e.data; + var target = $(e.target); + if (target.hasClass('blockOverlay') && opts.onOverlayClick) + opts.onOverlayClick(e); + + // allow events within the message content + if (target.parents('div.' + opts.blockMsgClass).length > 0) + return true; + + // allow events for content that is not being blocked + return target.parents().children().filter('div.blockUI').length === 0; + } + + function focus(back) { + if (!pageBlockEls) + return; + var e = pageBlockEls[back===true ? pageBlockEls.length-1 : 0]; + if (e) + e.focus(); + } + + function center(el, x, y) { + var p = el.parentNode, s = el.style; + var l = ((p.offsetWidth - el.offsetWidth)/2) - sz(p,'borderLeftWidth'); + var t = ((p.offsetHeight - el.offsetHeight)/2) - sz(p,'borderTopWidth'); + if (x) s.left = l > 0 ? (l+'px') : '0'; + if (y) s.top = t > 0 ? (t+'px') : '0'; + } + + function sz(el, p) { + return parseInt($.css(el,p),10)||0; + } + } - var opts = e.data; - // allow events within the message content - if ($(e.target).parents('div.' + opts.blockMsgClass).length > 0) - return true; - // allow events for content that is not being blocked - return $(e.target).parents().children().filter('div.blockUI').length == 0; -}; -function focus(back) { - if (!pageBlockEls) - return; - var e = pageBlockEls[back===true ? pageBlockEls.length-1 : 0]; - if (e) - e.focus(); -}; + /*global define:true */ + if (typeof define === 'function' && define.amd && define.amd.jQuery) { + define(['jquery'], setup); + } else { + setup(jQuery); + } -function center(el, x, y) { - var p = el.parentNode, s = el.style; - var l = ((p.offsetWidth - el.offsetWidth)/2) - sz(p,'borderLeftWidth'); - var t = ((p.offsetHeight - el.offsetHeight)/2) - sz(p,'borderTopWidth'); - if (x) s.left = l > 0 ? (l+'px') : '0'; - if (y) s.top = t > 0 ? (t+'px') : '0'; -}; - -function sz(el, p) { - return parseInt($.css(el,p))||0; -}; - -})(jQuery); +})(); \ No newline at end of file