I have a page with multiple tabs. The content of each tab is loaded from an external file. The contents of each tab has links to externally loaded content that will display as a lightbox style popup. My trouble is getting the popup vertically centered since the height of this element is not being reliably provided. If an alert is inserted (see code below) then the height seems to be reliably computed. That is, there seems to be a race condition of some kind but I don’t know what it is or how to fix it.
I apologize for the amount of code listed. I whittled it down as I could while still having a “working” example. Below is the main source file, the source for the first tab, and the source for a popup.
Here’s the main source file:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>JQuery Issue</title>
<link type="text/css" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.13/themes/start/jquery-ui.css" rel="stylesheet" />
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js"></script>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.13/jquery-ui.min.js"></script>
<script type="text/javascript">
$(document).ready(function(){
// Accordion
$("#accordion").accordion({ header: "h3" });
$("#accordion").accordion({ fillSpace: true });
// Tabs
$('#tabs').tabs();
$('#tabs').tabs({ selected: 0 });
//hover states on the static widgets
$('#dialog_link, ul#icons li').hover(
function() { $(this).addClass('ui-state-hover'); },
function() { $(this).removeClass('ui-state-hover'); }
);
$(document).delegate('a.poplight','click', function() {
var popID = $(this).attr('rel'); //Get Popup Name
var popURL = $(this).attr('href'); //Get Popup href to define size
//Pull Query & Variables from href URL
var query = popURL.split('?');
var remoteURL = query[0];
var dim = query[1].split('&');
var popWidth = dim[0].split('=')[1]; //Gets the first query string value
if ( remoteURL !== "#" ) {
var r = remoteURL.substring(0, remoteURL.length - 1);
$('#' + popID).load( r, function( response, status, xhr ) {
if (status == "error") {
$("#error").html("Error: " + xhr.status + " " + xhr.statusText);
}
});
}
// Comment this alert and the loaded popup height ( $('#' + popID).height() ) will be 0.
// Uncomment this alert and the height will suddenly be correct.
// Also controls the appearance of the close button on loaded content.
// alert("Loaded popup content should work now.");
//Fade in the Popup and add close button
$("#" + popID).fadeIn();
$('#' + popID).css({ 'width': Number( popWidth ) })
$('#' + popID).prepend('<a href="#" class="close"><img src="img/close_pop.png" border="0" class="btn_close" title="Close Window" alt="Close" /></a>');
// Define margin for center alignment (vertical, horizontal).
// Add 80px to the height/width to accomodate for the
// padding and border width defined in the css.
var popMargTop = ($('#' + popID).height() + 80) / 2;
var popMargLeft = ($('#' + popID).width() + 80) / 2;
// Sometimes right, mostly wrong in my tests. Feels like a race condition.
var poplen = $('#' + popID).length;
alert("popID = " + popID + ", length = " + poplen + ", popMargTop = " + popMargTop);
//Apply Margin to Popup
$('#' + popID).css({
'margin-top' : -popMargTop,
'margin-left' : -popMargLeft
});
//Fade in Background
$('body').append('<div id="fade"></div>');
$('#fade').css({'filter' : 'alpha(opacity=80)'}).fadeIn(); // Fade in the fade layer - css filter used to fix the IE Bug on fading transparencies
return false;
});
//Close Popups and Fade Layer
$(document).delegate('a.close, #fade','click', function() {
$('#fade , .popup_block').fadeOut(function() {
$('#fade, a.close').remove(); //fade them both out
});
return false;
});
});
</script>
<style type="text/css">
body{ font: 62.5% "Trebuchet MS", sans-serif; margin: 20px 50px;}
div.popup_block h2 {
color: #0000ff;
font-weight: bold;
}
#fade {
display: none; /*--hidden by default--*/
background: #000;
position: fixed; left: 0; top: 0;
width: 100%; height: 100%;
opacity: .80;
z-index: 9999;
}
.popup_block {
display: none; /*--hidden by default--*/
background: #fff;
padding: 20px;
border: 20px solid #ddd;
float: left;
font-size: 1.2em;
position: fixed;
top: 50%; left: 50%;
z-index: 99999;
/*--CSS3 Box Shadows--*/
-webkit-box-shadow: 0px 0px 20px #000;
-moz-box-shadow: 0px 0px 20px #000;
box-shadow: 0px 0px 20px #000;
/*--CSS3 Rounded Corners--*/
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
border-radius: 10px;
}
img.btn_close {
float: right;
margin: -55px -55px 0 0;
}
/*--Making IE6 Understand Fixed Positioning--*/
*html #fade {
position: absolute;
}
*html .popup_block {
position: absolute;
}
</style>
</head>
<body>
<h1>JQuery race condition (?) issue</h1>
<!-- Tabs -->
<div id="tabs">
<ul>
<li><a href="tab0.html" title="tabs0">Tab 0</a></li>
<li><a href="tab1.html" title="tabs1">Tab 1</a></li>
</ul>
<div id="tabs0"> Loading... </div>
<div id="tabs1"> Loading... </div>
</div>
</body>
</html>
Here’s tab0.html:
<div id="tab0-contents">
<h3>Contents of Tab 0</h3>
<a href="tab0_pop0.html#?w=700" rel="pop_t0p0" class="poplight">Popup external file tab0_pop0.html</a>
<br/>
<a href="#?w=700" rel="pop_t0p1" class="poplight">Popup inside tab0.html</a>
<br/>
<div id="pop_t0p0" class="popup_block"></div>
<div id="pop_t0p1" class="popup_block">
<h2>Popup div lives inside tab0.html</h2>
<p>Lorem ispum etcetera.</p>
<p>Lorem ispum etcetera.</p>
<p>Lorem ispum etcetera.</p>
<p>Lorem ispum etcetera.</p>
</div>
</div>
Finally, here’s tab0_pop0.html
<div id="tab0_pop0_contents">
<h2>Popup in tab0_pop0.html<h2>
<p>Lorem ipsum salts.</p>
<p>Lorem ipsum salts.</p>
<p>Lorem ipsum salts.</p>
<p>Lorem ipsum salts.</p>
<p>Lorem ipsum salts.</p>
<p>Lorem ipsum salts.</p>
<p>Lorem ipsum salts.</p>
<p>Lorem ipsum salts.</p>
<p>Lorem ipsum dolor amit.</p>
<p>Lorem ipsum salts con carne.</p>
</div>
In case anyone is wondering, I switched to using delegate instead of live after reading this article. I’ve also tried inserting delays and timeouts but without success.
Any help would be much appreciated. Thanks.
Can you modify this so that the popup is setup and shown in its onload condition? I already see a $(‘#’ + popID).load, so putting the rest of its showing code would make the height work, since it has already been loaded. I ran into a similar race condition in the last jquery library I wrote, and was forced to make the same changes.