Archive for the ‘Web design’ category

Canvas Swarms

2010-03-18 – 9:27am

I’ve been meaning to start playing with the HTML5 <canvas> element for a while now, and yesterday I took the opportunity. I translated a Processing sketch I made a while ago into JavaScript (with a few minor enhancements).

Essentially, 1 to 3 swarms of particles move around the canvas, reproducing when the conditions are just right, and dying of old age. Quite simple, but the patterns produced can be really quite pretty.

One interesting thing that I discovered whilst doing this is that you can’t pass around a canvas’ context at the instantiation of a MooTools class — it complains about wrapped natives. That’s why, if you like in the source JavaScript, you’ll see me pass the actual context around to various functions. I’d be interested in hearing if anyone has a workaround for this, because this is, well, a bit clunky.

HTML: IE file submission

2010-02-23 – 4:57pm

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”.

I couldn’t find any reference to this problem on the intertubes (although maybe I just didn’t look hard enough), so hopefully this will help someone.

Javascript: Print a single element

2010-02-16 – 5:18pm

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(docTitle) {
		var strName = 'printer-' + (new Date()).getTime();
		var styles = [];
		$$('link[type=text/css]').each(function(style) {
			styles.push('<link rel="stylesheet" type="text/css" href="' + style.get('href') + '"/>');
		});
		var title = docTitle || document.title;
		var that = this.getParent();
		var iframe = new IFrame({
			name: strName,
			styles: {
				width: 1,
				height: 1,
				position: 'absolute',
				left: -9999
			},
			events: {
				load: function() {
					var doc = window.frames[strName].document,
							win = window.frames[strName],
					f = function() {
						if (!doc.head) {
							f.delay(10);
							return;
						}

						// We need to delay printing so that styles are applied.
						(function() {
							doc.title = title;
							// IE7 won't let us adopt() here for some reason, and we can't do anything to the head.
							doc.body.innerHTML = styles.join('') + that.innerHTML;
							(function() {
								win.focus(); // IE needs the window to be focused.
								win.print();
							}).delay(100);
						}).delay(200);
					};
					f();
				}
			}
		}).inject($(document.body));
		(function() {
			iframe.dispose();
		}).delay(30000);
	}
});

The problem

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.

<div  style="background: blue; width:200px;">
  <input  style="display:block; padding:4px; background: red; opacity:0.5; border:0;" type="text" value="text input"/>
</div>

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%:

<div  style="background: blue; width:200px;">
  <input  style="display:block; padding:4px; background: red; opacity:0.5; width:100%; border:0;" type="text" value="text input"/>
</div>

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:

<div  style="background: blue; width:200px;">
  <input  style="display:block; padding:4px 0; background: red; opacity:0.5; width:100%; border:0; text-indent:4px;" type="text" value="text input"/>
</div>

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

  1. 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.
  2. 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.