I’ve been bumping up against an interesting bug in Internet Explorer recently, and, having just found the solution, thought I’d share it with you.
The problem is that in Internet Explorer (tested 7 & 8), when your document is in quirks mode, uploading a file sometimes just sends through the file name, without the actual body of the request. Put the document into standards mode, and it all works. It should be noted that this is when you’re dynamically setting up the elements used with JavaScript.
The cause? In quirks mode, the enctype attribute isn’t supported. So whilst setting “encType” on the form element to the correct “multipart/form-data” will indeed set this attribute, it won’t actually cause the upload to include the file. Instead, you need to set the encoding attribute to this value, too. It certainly doesn’t help that the MSDN article on the <input type=”file”> element tells you to set “enctype”, but makes no mention of “encoding”.
Sometimes, you’ll want to allow users the ability to print only a part of your page; for example, a table but not the various links around the page. It’s possible to use a printing stylesheet, but this can cause severe headaches when you need different parts printed at different times. Really, we want to be able to just say element.printElement(), and have it just work. That’s what the MooTools function below does. It’s loosely based around the concepts outlined at this website.
Element.implement({
printElement: function() {
var strName = 'printer-' + (new Date()).getTime(),
styles = $$('link[type=text/css]').clone(),
title = document.title,
that = this,
iframe = new IFrame({
name: strName,
styles: {
width: 1,
height: 1,
position: 'absolute',
left: -9999
},
events: {
load: function() {
var doc = this.contentDocument || window.frames[strName].document;
doc.title = title;
$(doc.body).adopt(styles, that.clone());
this.contentWindow.focus(); // IE requires us to focus before printing, or the parent prints.
this.contentWindow.print();
}
}
}).inject($(document.body));
iframe.dispose.delay(15000); // Destroy the iframe in 15s so that it doesn't hang around.
}
});
When styling text <input> elements, it’s fairly common to run into a serious problem: they don’t behave like block-level elements.
Note: In all of the examples, the container element is filled with blue, and the <input> itself is filled with red and has an opacity of 50% so that you can see it under- or over-flowing the container.
You can see how the input doesn’t automatically flow to full width, as the “display: block” style suggests it should. The kneejerk response is to set the width to 100%:
But notice now how the input overflows its container’s boundaries because of the left padding. At this point, people may resort to non-semantic markup (removing the padding on the <input> and putting it inside a padded <div>) or JavaScript solutions that set the pixel width whenever the container’s width changes (by the addition of scrollbars, for example).
The (semantic) solution
But wait! There is a way to achieve this effect without resorting to an extra <div> or JavaScript:
Do you see what I did there? I removed the horizontal padding on the <input>, so the 100% width now works correctly, and replaced it with “text-indent”. To the user, this looks no different, and it has the advantage of requiring no extraneous markup or tedious scripting.
Drawbacks
Should the user enter a long string, their text will bump up against the right edge. But I think that that’s a boundary condition that I can live with.
Any vertical borders on the <input> will cause it to overflow its container. Personally, if I want a full-width <input>, though, I generally don’t want any borders on its left or right other than those of its container.
Often, you will need to prevent users from entering data that doesn’t conform to a specific pattern. For example, you may want to allow users to enter only numbers or only valid email addresses. To this end, I’ve written a little utility function that returns the “standardised” version of a string, according to the regex you supply.
Basically, the function takes the result of evaluating the regular expression on the string, converts it into an array if it isn’t one, and then joins the array’s elements together with an empty string.
Examples:
console.log("12345".limitContent(/.{4}/)); // Only allow four characters
console.log("joe@mail.com".limitContent(/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}/)); // Only allow email addresses