CSS Horizontal Menu: Firefox whitespace bug
So I came across the most baffling bug the other day that locked me up for a good three hours. I thought maybe I’d just put down what I discovered here on the outer reaches of the blogosphere in case anyone else happens to hit that magical combination of Google keywords and a link to this page comes up.
To describe the problem succinctly: when you’re trying to create a horizontal menu using unordered lists (<ul> and inline <li>), for some reason, in Firefox (2 - I don’t know about 3 which just came out last week), if there is any whitespace between a closing </li> tag and the opening <li> tag of the next item, that whitespace actually displays. At first it looks like a margin spacing issue, but after some tests it’s clearly not. In fact, what baffles me is that ANY text between the closing </li> and the opening <li>, that text actually gets displayed inline! Which makes no sense, because I didn’t think that the <ul> element could have a text node as a direct child. Apparently it can, in Firefox at any rate.
The solution, as I have discovered is to set your <ul>’s display attribute to “table”. I don’t believe IE7 and certainly not IE6 understand display:table, so this is a non-IE fix, but then again, IE wasn’t exhibiting the whitespace behaviour. Here’s some sample code.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Untitled Document</title>
<style type="text/css">
* { margin:0; padding:0; }
ul {
list-style-type:none;
list-style-position:inside;
margin:0px; padding:0px;
display:table; /* This is used for firefox */
/* to avoid the horizontal whitespace bug */
}
li {
border:1px solid black;
display:inline;
margin:0px; padding:0px;
border-collapse:collapse;
}
a {
}
</style>
</head>
<body>
<ul>
<li><a href="#">Line 1</a></li>
<li><a href="#">Line 2</a></li>
<li><a href="#">Line 3</a></li>
</ul>
<p>Other stuff....</p>
</body>
</html>
Interoperability between two Flash EXE Projectors (or how to dynamically read SharedObjects across two SWFs)
So here’s a real doozie that came from a question someone asked on ExpertsExchange: he had two separate Flash Projectors (EXEs) - that needed to be able to intercommunicate (the first projector needed to know when the second projector had actually finished loading). Since we’re dealing with external projector files that have no dependencies (rather than using the movieClipLoader to load an external SWF into the parent movie), the only thing I could think of that would work reliably was local SharedObjects.
As I put together a solution for this brave soul, I encountered a few interesting challenges, and a few frustrations. Thought I’d document it here because I couldn’t find anyone else who had addresses the intricacies of having two SWF share a SharedObject and monitor the status of that shared SharedObject so they could respond to a change in status.
Here’s the basic principle:
- Application 1 creates a local SharedObject and sets an initial status
- Application 1 also registers an enterFrame event listener that listens for a status change on the SO
- Application 2 accesses the same SO and at some point, changes the status
- Application 1’s enterFrame handler detects the status change, and responds to the event.
As I write this, I see there’s an opportunity for a custom event class that does all this, but I’m going to leave that to the real gurus. I don’t pretend to have that intimate a knowledge of ActionScript to be able to pull that off. I should also point out at this time that the original EE user’s question was for AS2, so this solution is only tested in AS2, though since the issues I was running into were related to variable scope, I would only imaging that an AS3 implementation would be easier, if anything.
Here are the challenges I encountered:
- how to launch one EXE Projector from another EXE Projector
- how to share a SharedObject between two Flash movies (SWFs)
- how to continuously monitor the value of a shared SharedObject
Creating a pop-up window that only displays once per user
This was a question I answered recently on experts-exchange, and, considering the verbosity of it all, I thought I’d capture it for anyone that might find it useful.
The poster wanted to create a popup window using HTML and JavaScript that would open when the page first loaded, but then, if the user navigates away from that page, and then came back, would not bother them by popping up again.
Here’s the solution:
The command for a popup window is:
window.open();
To make the window open when the user first comes to your page, you put the popup in the HTML <body> tag like this:
<body onLoad=”window.open();”>
There are some additional parameters you can pass to window.open() to do things like set the name, the size etc.
If you want to make sure the popup only happens once per session for a user (so it doesn’t pop up every time) you need to set a session cookie.
The session cookie is stored on the person’s computer and is erased once they close their browser window. This is useful for making sure that the NEXT time they visit the site, they will see the popup again.
If you don’t want the user to ever see the popup again after the first time, use a regular cookie that doesn’t expire, or expires in a very long time.
These are some excellent tutorials on setting and reading cookies. You’ll have to brush up on your JavaScript skills a little.
http://www.quirksmode.org/js/cookies.htm
http://www.w3schools.com/js/js_cookies.a
For a general tutorial on JavaScript, check these guys out:
http://www.w3schools.com/js/default.asp
Here are all the parameters you can pass to window.open to do all sorts of neat things with the popup window. This page is a little technical, so maybe wait until you’ve got a basic window working before trying to tweak the popup window with help from this link:
http://www.w3schools.com/htmldom/met_win
Cookies will probably be the hardest part for you to implement. So I’m just going to copy and paste some code here, straight out of the w3schools tutorial, with a bit of explanation and some specific code for you:
first, in the <head> of your HTML page, start with your <script> tag:
<script type=”text/javascript” language=”JavaScript”>
// the rest will go inside here (see below)
</script>
Okay, now, copy and paste the following functions into the area we’ve left for the Script tags.
function mySetCookie(c_name,value,expiredays)
{var exdate=new Date()exdate.setDate(exdate.getDate()+ex
document.cookie=c_name+ “=” +escape(value)+
((expiredays==null) ? “” : “;expires=”+exdate.toGMTString())
}
function myGetCookie(c_name)
{
if (document.cookie.length>0)
{
c_start=document.cookie.indexOf(c_name + “=”)
if (c_start!=-1)
{
c_start=c_start + c_name.length+1
c_end=document.cookie.indexOf(”;”,c_star
if (c_end==-1) c_end=document.cookie.length
return unescape(document.cookie.substring(c_sta
}
}
return “”
}
// —————————————-
Okay, those are the functions we’ll use to set and retrieve the cookie to see if the user has already seen the popup window.
Now here’s the custom code that you’ll put after the code you just copied and pasted (still inside the SCRIPT tags). We want to check if the user has already got a cookie. If so, it means the user has already been to this page and (presumably) seen the popup already, so we don’t display it again. Otherwise, we display it.
function showPopupOnce() {
var hasSeenPopup = myGetCookie(”has_seen_popup”);
if (hasSeenPopup == null || hasSeenPopup == “”){
// the user has never seen the popup, so show him!
window.open(”http://mywebsite.com/popup.
}
// either way, set the cookie so the user will never see the window again
mySetCookie(”has_seen_popup”, “true”, 365); // 365 days = 1 year
}
// ——————————
Okay, great, now the only thing to do is make sure that the showPopupOnce() function runs whenever the page loads. Go into the <body> tag and change it to this:
<body onLoad=”showPopupOnce();”>
That should do the trick.
Tom