Just some painful web lessons I thought I'd share for similarly-beleaguered web developers who are wondering if their browsers (or their clients' browsers) are possessed of evil spirits.
Blank Page, No Errors in IE 8
A fraction of IE8 users reported a blank white page with no errors and a "done" loading message. It was completely unreproducible in any of my VMs, but through some searching, I found others suggesting the problem was tied to Compatibility View. When IE8 was released, my boss asked me to find a way to get rid of the IE8 Compatibility button, so I was using <meta http-equiv="X-UA-Compatible" content="IE=Edge" /> in my templates to force ultra-super-futuristic behavior (under the theory that IE is *always* behind the times). However, one of the pages had no doctype (see prior Web Tricks for why that was necessary and not within my power to remedy). And apparently the combination of those two (future spiffiness and pathetic quirks mode past) freaks IE8 out... or about 1% of IE8, at least. And thus... the oh-so-helpful blank page.
Anyway, removing the X-UA-Compatible meta tag fixed it. You could also set it to IE=7 or IE=EmulateIE7, but at that point I figured I'd leave the choice to the user on that page. If you already don't have X-UA-Compatible set, look for the Compatibility View button in the client browser and change it for the problem page.
More reading on Compatibility View: FarukAt.eş: IE8 and the X-UA-Compatible situation and IEBlog: Just The Facts: Recap of Compatibility View.
Firefox Hover Missing In "Quirks" Mode
On the same page, we noticed that the hovers were not behaving as expected in Firefox. Turns out, when you are in Quirks Mode (the no-doctype mode), Firefox does not support CSS :hover on list elements. You didn't know Firefox even had Quirks Mode? Me too. I thought that kind of asinine behavior was reserved for IE, but apparently Firefox has jumped on that mess. Joy.
I know I put down IE a lot on my site. As a web developer, it has made my life a living hell for the last 4 years. Some people prefer to point the finger at Firefox for starting all these compatibility issues, but for the most part it is IE that deviates from CSS specifications (and sometimes ECMAScript specs too!).
However there is one issue where Firefox is wrong. Dead wrong. So painfully wrong that I have been complaining about it for years. See, Firefox ignores CSS spec on pixel font sizes. Its reasoning is that people have misused pixel font sizes all over the web and wouldn't it be nice if old granny's could read those pages anyway? But this kind of thinking is what put IE in the mess that it's in now. You can't just ignore spec because people made their pages wrong. They are WRONG.
The reason why pixel fonts are and should be absolute is because there are times when you really need text to be absolute. When it's aligning with an image, or needs to fit inside a box. Scaling it so the user can read it may make them happier, but it makes my page look really ugly and can break a lot of other elements depending on that one to stay in its own damn area. When we say we want a box to be 300 pixels wide, you don't go scaling that, now do you, Firefox? If we wanted it scaled, we would have used "em" or percent. Don't make us use a text graphic just to force the size!
And apparently this will now be causing grief to more developers thanks to the new all-in-one advertising tool from google's adsense:
http://groups.google.com/
You might say that google could make their banners scalable to overcome this, but banners have traditionally been of a fixed size and few websites can accommodate scaling sizes. The fact is, we as designers should be able to say that we want our text in some circumstances to be *just the right size*. And I am pissed off that Firefox won't let me do it. And Safari. Opera, thank god you decided to just add Zoom and skip the whole font-sizing thing. You are awesome. :)
So I just ran into a really annoying float bug in Firefox (ironically discovered when trying to fix the header navigation of the Drupal SpreadFirefox theme). When you do a double-float right, or a float right inside an absolutely positioned div, the top-most container becomes a screen-filling monstrosity.
See the following:
<style type="text/css">
#floated {position:relative;float:right;
color:black;background:#999;border:1px solid black;opacity:0.5}
#floated div {position:relative;float:right;
border:1px solid black;padding:2px;margin:.5em;}
</style>
<div id="floated">
<div>test 1</div>
<div>test 2</div>
</div>
In Safari, test 1 and test 2 float right, with the containing div surrounding them in a nice discrete little box. In Firefox, the containing div fills the whole width of the page.
Note that when test 1 and test 2 float left, it works as expected in Firefox - regardless of the containing div's float or absolute positioning:
But unfortunately this would reverse the tabs in Drupal SpreadFirefox without other code-level alterations.
I recently posted an entry on making static hierarchies in MovableType. I came up with a much better way of doing this, so I am replacing that entry with this one.
First off, let's create a relationship between a category and the entry which is going to represent it. Create a new category "About Me" and save it. Now create a new entry and call it ".About Me" - the period in UNIX syntax for hidden files, and we are going to hijack it here. :) Attach the entry to category "About Me." You can set this entry to allow comments and trackbacks - it's up to you. You may not like the look of comments at the bottom of a long page of blog entries.
Now we get to alter the templates! First, open Archive Template "Entry Listing" and add the following code to the top of the code:
<MTSetVar name="cat_desc" value=""> <MTSetVar name="cat_extra" value=""> <MTSetVar name="use_short_list" value="0"> <MTSetVar name="use_no_list" value="0"> <MTIfArchiveType archive_type="Category"> <MTEntries> <MTSetVarBlock name="keywords"><$MTEntryKeywords$> </MTSetVarBlock> <MTIf name="keywords" like="_shortlist"> <MTSetVar name="use_short_list" value="1"> </MTIf> <MTIf name="keywords" like="_nolist"> <MTSetVar name="use_no_list" value="1"> </MTIf> <MTSetVarBlock name="title"> <$MTEntryTitle$> </MTSetVarBlock> <MTSetVarBlock name="cat_title"> .<$MTArchiveCategory$> </MTSetVarBlock> <MTIf name="title" eq="$cat_title"> <MTSetVarBlock name="cat_desc"> <$MTInclude module="Entry Detail"$> </MTSetVarBlock> <MTSetVarBlock name="cat_extra"> <$MTInclude module="TrackBacks"$> <$MTInclude module="Comments"$> </MTSetVarBlock> </MTIf> </MTEntries> </MTIfArchiveType>
This establishes our basic variable values if we are dealing with a category entry. Then scroll down and look for the section that prints out the entries. It should look something like this:
<MTIf name="datebased_archive">
<MTEntries>
<$MTEntryTrackbackData$>
<$MTInclude module="Entry Summary"$>
</MTEntries>
<MTElse>
<MTEntries limit="auto">
<$MTEntryTrackbackData$>
<$MTInclude module="Entry Summary"$>
</MTEntries>
</MTIf>
We are going to edit the second bit inside the <MTElse>. Basically take everything from <MTEntries> to </MTEntries> and replace it with this:
<MTVar name="cat_desc"> <MTUnless name="use_no_list"> <!--print out entries inside category:--> <MTIf name="use_short_list"><ul class="cat-short-list"> <MTElse><hr /></MTIf> <MTEntries limit="auto"> <MTSetVarBlock name="title"> <$MTEntryTitle$> </MTSetVarBlock> <MTUnless name="title" like="^\."> <MTIf name="use_short_list"> <li><a href="<$MTEntryPermalink$>"> <$MTEntryTitle$> </a></li> <MTElse> <$MTEntryTrackbackData$> <$MTInclude module="Entry Summary"$> </MTIf> </MTUnless> </MTEntries> <MTIf name="use_short_list"></ul></MTIf> </MTUnless>
And then tack on the following just below the last </MTIf> from <MTIf name="datebased_archive">:
<MTVar name="cat_extra"><!--:comments and trackbacks if selected-->
You can save the "Entry Listing" template now and republish your site. If you go to category "About Me" now, you should see the entry you created for ".About Me" at the top, followed by a horizontal separator and any other entries you may have listed in that category, blog-style. There are a few things that may still be bothering you. First, your page says "Recently in About Me Category." Just go back to "Entry Listing" and look for where that is printed in the template and replace "Recently in <em><$MTArchiveTitle$></em> Category" with just "<$MTArchiveTitle$>" - that should fix that. Second, you may not like all your entries listed blog-style up against your pretty category entry. Since this is entirely a matter of preference, I set this up as a per-category option. If you add "_shortlist" to the keywords field in the ".About Me" entry, then it will print out the entries as a short list of linked titles instead. If you add "_nolist" to the keywords, it will not print the entries out all (and you can add them to the entry itself in any order or format you like).
You could also easily alter the "Entry Listing" template to always do one of these options - just set the default value to "1" in the first <MTSetVar> at the top of the template code.
So now we have an entry that is tied one-to-one with a category. There's one problem still. Movable Type published the entry in addition to the entry-category. If you click "View Published Entry" from ".About Me," you can see that there is a duplicate page there, which we don't want. This is also the landing page after a user leaves a comment (if you have set up ".About Me" to allow comments). So we are going to edit another template to fix this. Open Archive Template "Entry" now and put this code at the very top of that template:
<MTSetVar name="redirect" value="0"> <MTSetVarBlock name="title"><$MTEntryTitle$> </MTSetVarBlock> <MTIf name="title" like="^\."> <MTSetVarBlock name="redirect"> <$MTBlogURL$> </MTSetVarBlock> </MTIf> <MTIf name="redirect"> <MTEntryCategories> <MTSetVarBlock name="cat_title"> .<$MTArchiveCategory$> </MTSetVarBlock> <MTIf name="title" eq="$cat_title"> <MTSetVarBlock name="redirect"> <$MTCategoryArchiveLink$> </MTSetVarBlock> </MTIf> </MTEntryCategories> </MTIf> <MTIf name="redirect"> <HTML><HEAD><TITLE> <$MTBlogName$> </TITLE> <META HTTP-EQUIV=REFRESH CONTENT="0;URL= <MTVar name="redirect">"> </HEAD> <BODY><script type="text/javascript"> location.replace("<MTVar name="redirect">"); </script> </BODY></HTML> <MTElse>
You'll want to throw in a final </MTIf> at the very bottom on the template as well. Save this change and republish.
Now when you go to the url for ".About Me," it automatically redirects you back to the category-entry "About Me."
There is one caveat to my solution here: all the category-entries are listed in archives. I wanted it that way, because I view them as entries in their own right (why I set mine up to allow comments). You may not feel the same way. Unfortunately, due to the way most archives are published, I could not find a way to set this on a per-category level. If you want to block/hide all category-entries from archives, edit "Entry Listing" to look like this:
<MTIf name="datebased_archive"> <MTEntries> <MTSetVarBlock name="title"><$MTEntryTitle$> </MTSetVarBlock> <MTUnless name="title" like="^\."> <$MTEntryTrackbackData$> <$MTInclude module="Entry Summary"$> </MTUnless> </MTEntries>
And edit the Individual Template "Archives" as well. Search for "<li" wherever it mentions "<$MTArchiveTitle$>" and wrap it up like this:
<MTSetVarBlock name="title"><$MTArchiveTitle $> </MTSetVarBlock> <MTUnless name="title" like="^\."> <li class="archive-list-item"> <$MTArchiveDate format="%Y.%m.%d"$>: <a href="<$MTArchiveLink$>"> <$MTArchiveTitle$> </a></li> </MTUnless>
You won't need to change every archive option - I think only Individual actually lists each entry. Per-month archives are handled in "Entry listing" instead.
Anyway, I hope this helps someone. It was a lot of fun to create and I am much happier with MovableType now. Version 4 is really pretty damn good!
Resources: MovableType 4 Templating, MovableType Template Tag Reference
If you are using regular Pear SOAP, it doesn't work in document/literal. I tried. So I turned to NuSOAP, which unfortunately has very little in the way of documented examples, especially in document/literal. I am including the server that worked for me (discovered largely through trial and error), as well as a test client. This is designed to mirror Pear SOAP as much as possible (since I was converting from one to the other). Note: document/literal in NuSOAP does not verify data types, so int, string, boolean, etc. are all converted to strings between the client and server.
SERVER:
require_once("nusoap/nusoap.php");
$server = new soap_server;
$server->configureWSDL( 'servicename', 'urn:servicename', '', 'document');
myRegister($server,'DoSomething',array(
'in' => array('Name' => 'xsd:string',
'Age' => 'xsd:int'),
'out' => array('Pass' => 'xsd:boolean')
));
//if in safe mode, raw post data not set:
if (!isset($HTTP_RAW_POST_DATA)) $HTTP_RAW_POST_DATA = implode("\r\n", file('php://input'));
$server->service( $HTTP_RAW_POST_DATA);
function myRegister( &$server, $methodname, $params) {
$server->register($methodname, $params["in"], $params["out"],
'urn:servicename', // namespace
$server->wsdl->endpoint .'#'. $methodname, // soapaction
'document', // style
'literal', // use
'N/A' // documentation
);
}
function DoSomething($Name,$Age) {
$result=false;
if ($Name=="mleiv" && $Age==35) $result=true;
return array('Pass'=>$result);
}
CLIENT:
require_once( "nusoap/nusoap.php" );
$ns="urn:servicename";
$client = new soapclient('http://localhost/ wherever/ SOAPServer.php?wsdl','wsdl');
if ( $client->getError() ) {
print "<h2>Soap Constructor Error:</h2><pre>".
$client->getError()."</pre>";
}
$params=array("Name"=>"mleiv", "Age"=>35);
$result = $client->call( "DoSomething", array("parameters"=>$params), $ns);
if ($client->fault) { //soap_fault
print "<h2>Soap Fault: </h2><pre>(". $client->fault->faultcode .") ".
$client->fault->faultstring. "</pre>";
}
elseif ( $client->getError() ) {
print "<h2>Soap Error: </h2><pre>". $client->getError() ."</pre>";
}
else {
print "<h2>Result: </h2><pre>". $result["Pass"] ."</pre>";
}
print '<h2>Details:</h2><hr />'.
'<h3>Request</h3><pre>' .
htmlspecialchars( $client->request, ENT_QUOTES) .'</pre>'.
'<h3>Response</h3><pre>' .
htmlspecialchars( $client->response, ENT_QUOTES) .'</pre>'.
'<h3>Debug</h3><pre>' .
htmlspecialchars( $client->debug_str, ENT_QUOTES) .'</pre>';
Issue: In IE, when using links with display:block overtop of images, the block setting disappears and only the link text is clickable.
There are a few CSS tricks running around these days to replace the old image maps (which are a big pain in the ass to write). My personal favorite is to write a text link, then hide the text, size it, and place it over the image-to-be-mapped. Then the html makes complete sense and you always know which link is which. And people without css can still navigate. Excellent all around.
I created the following ultra-simplified example of my image-map substitute below. The blue-bordered area is a relatively-positioned wrapper div. The image inside is absolutely-positioned, and the red-bordered link is relatively positioned on top. You could reverse this: I didn't see a difference in the results. The link is set to be a block (not inline) so it will fill the dimensions specified. A span surrounds the text inside the link and that span is set display:none.
Sample #1: (initial attempt)This works in all browsers but IE, where the image covers up the link. At first I thought this was a z-index issue (which IE has some well-documented issues with). But after exploring that for several hours, I found that this was not the case. When I set the background color of the link, it shows above the image (proving it is above the image in z-index).
Sample #2: (with background color)I thought this might be one of those IE things where you can fix the element by setting width or display:inline-block. But not the case. Nothing helped but background-color. Then I let the text become visible again to see what would happen. This is really entertaining.
Sample #3: (showing text)If you hover (in IE) over the text, it becomes immediately apparent that the block status of the link is being ignored - you can only click on the text area of the link. But this is only true in the area where the lower-level image is visible. So basically, IE will only see visible stuff inside the link (background-color or link text) and ignores the link block otherwise. Joy. So it was a quick matter to find an invisible element that IE sees as visible in order to overcome this problem: a blank gif! It doesn't matter if you use it as a background image or an inline-element set to the right size: IE sees this as a link object and shows the link. Yay!
Fix #4: (fixed - with blank background image in CSS) Fix #5: (fixed, with inline blank image)If you would like to see these 5 simplified examples with no other interfering html see the IE Display Block Link Test Page.
It appears that in Firefox one must do somersaults to use javascript-opened windows and AJAX. There is a conflict between window.close() and AJAX and a delayed window.close() is prevented by a second Firefox bug where the window reference becomes corrupted in some way. The final solution appears to be to delay the AJAX call instead, using setTimeout().
One of my major gripes with IE has always been with the way it passive-aggressively recodes the html on every page it loads. Just take a look at view source. That's not my code. My code is pretty and lower-case with proper xhtml quotes on all attribute values.
IE does this so it can create the DOM tree (other browsers create the DOM tree just fine without mucking up code, but I guess this argument has never really been a motivator over at MS headquarters). And this is probably also why IE has so many problems with its DOM.
For instance, I've had lots of fun trying to change the select element's name through DOM in IE. Why would I want to do this, you ask? Well, I created a generic filepath dropdown on the server which I wanted to clone and insert into various parts of the form via DOM and rename "oldpath" and "newpath" and such. If I do it this way, it sort of works:
var x=document.getElementById("x"); //x is a select list with name and id "x"
var x2=x.cloneNode(true);
x2.id=x2.name="x2";
document.forms[0].appendChild(x2);
In this case, the innerHTML is wrong (the name remains "x") - and it remains wrong throughtout the life of the page and from every element's innerHTML in the page - but IE still sends the correct name in the form. And if you ever edit the page using innerHTML, it breaks (sends the incorrect name in the form).
document.forms[0].innerHTML+="New list:"+x2.outerHTML; //this does not work
So, you say, never use innerHTML in IE? It's not so easy. Some values can only be retrieved correctly from the innerHTML text. Try accessing href and src using getAttribute() and you will get a mucked-up absolute pathname. You have to parse it out of innerHTML to get the correct pathname.
And when you clone a select list, IE resets its selectedIndex to 0. Even the innerHTML is wrong here. You
have to manually reset the selectedIndex of the cloned list using the
selectedIndex of the original list using DOM. I have a sneaky suspicion that IE thinks this is desired behavior.
If this doesn't make your DOM life miserable enough, IE has several distressing DOM memory issues:
Understanding and Exploring Internet Explorer Leak Patterns
(http://msdn.microsoft.com/library/default.asp?url=/library/en-us/IETechCol/dnwebgen/ie_leak_patterns.asp)
Note that they never express any of these leaks as bugs. They are exactly the way things should be, and every JavaScript developer out there should be doing their aggressive DOM garbage collection or it's their own damn fault.
Yup, I love that browser.
OK, I understand IE's whole DOCTYPE quirks vs. standards (or strict) CSS variations (I don't agree, but I understand). But when did they decide to change their javascript as well (without backwards compatibility)?
http://aranea.zuavra.net/index.php/5 and http://www.quirksmode.org/js/doctypes.html
Basically, when you switch to standards mode, some of the IE proprietary javascript properties move from document.body to document.documentElement. document.body.scrollTop is now always 0 on a standards-compliant page, and the value can be found in document.documentElement.scrollTop instead.
Really, would it have been so hard to leave the document.body.scrollTop value? I know that the IE freaks love to tell us we should develop a million separate CSS files for each damn browser version they throw at us, but having to develop separate javascript as well is enough to make me want to jump up and down and scream violent profanities at my monitor.
« Writing | Programming | About Me »


