It is precisely in knowing its limits that Philosophy existsImmanuel Kant
Also relates to Exploder
This is a reminder to self (since this trap keeps stinging me!) that IE 5.01 does not support the principle Array object methods in Javascript. A way around this problem is to test for the presence of these methods in the Array prototype property and if they do not exist define them. Here are examples for Array.push and Array.splice which I find myself using regularly in DOM based scripts.
if (typeof Array.prototype.push == "undefined") {
Array.prototype.push = function(str) {
this[this.length] = str;
}
}
if (typeof Array.prototype.splice == "undefined") {
Array.prototype.splice = function(offset, length) {
var temp = [];
for (var i = this.length - 1; i >= 0; i–) {
if (i < offset || i > (offset + length - 1)) {
temp[temp.length] = this[i];
}
this.length–;
}
for (i = temp.length - 1; i >= 0; i–) {
this[this.length] = temp[i];
}
}
}
Posted on Aug 13, 2004 at 05:07:03. [Comments for Array Prototyping for Legacy Support- 2]
Also relates to CSS Design
Just been having a little play with alpha transparencies and event handling for customised tool tips using DHTML and CSS. Just another reason why Internet Exploder should be laid to rest!
So, here is the first run at accessible DHTML transparency tool tips. There is more to develop to make this accessible to the widest possible audience, so will hopefully come back to it at the turn of the tide
…
Posted on Jul 11, 2004 at 04:29:06. [Comments for Experiments With DHTML Tooltips- 0]
Also relates to Peregrinations
The age old problem - spam! While I patiently wait for that elusive Gmail invite, I am still running a couple of old webmail accounts that have been active for several years. I would be content to disable them except for the occassional critical email I receive. So once every 5 or 10 days I will log into the accounts and spend the best part of half an hour selecting and deleting anywhere from 1000 to 2000 spam emails just to find those few important messages. Fortunately the Inbox can display 1000 messages on a page and, accompanied by the select all button, this speeds up the process slightly, but I still have to deselect all the archived messages. This seemed like the perfect opportunity to write a boomarklet to speed things up a bit.
Of course this bookmarklet is proprietary with the DOM navigation specific (and quite cumbersome!) to the layout of my Webmail Inbox, but perhaps you may find it useful for editing to your requirements?
javascript:(
function(){
var a = confirm(%22Do you wish to select?%22);
var rn = prompt(%22Enter range of cells to %22 +
((a) ? %22select%22 : %22deselect%22));
var r = rn.split('-');
var rows = window.frames[3].document. _
getElementsByTagName('table'). _
item(0).getElementsByTagName('tr');
var min = parseInt(r[0]) + 2, max;
max = (r.length == 1) ? rows.length : parseInt(r[1]) + 3;
for (i = min; i < max; i++) {
rows.item(i).getElementsByTagName(%22a%22).item(0). _
nextSibling.checked = a;
}
}
)();
Note, the _ character is just a line continuation. Has made my webmail routine that bit easier, more efficient and fulfilling :)
Posted on Jul 10, 2004 at 16:42:59. [Comments for Webmail Management Bookmarklet- 0]
Also relates to Accessibility
One of the stumbling blocks for achieving Triple A Conformance of the WCAG 1.0 is Checkpoint 10.4 regarding placeholder text for form controls:
Until user agents handle empty controls correctly, include default, place-holding characters in edit boxes and text areas.Checkpoint 10.4 Web Content Accessibility Guidelines 1.0
This is actually an interim solution to accomodate certain legacy assistive technologies that can not handle empty form controls. However, accessibility can be improved if, in meeting this checkpoint, the placeholder text is informative text that assists the user with the information they should enter. For example:
<input type="text" id="name" name="name"
value="Please enter your name"/>
<input type="text" id="tel" name="tel"
value="Your Phone Number - 01234 123123"/>
This information can be valuable to the user where a complex form is layed out with tables and the label may be detached from the field it relates to. To ease the form completion process a Javascript event may be attached to the form field to clear the placeholder text when focus is received.
<input type="text" id="name" name="name"
value="Your name"/
onfocus="if(this.value=='Your name')this.value=''"/>
With a multi-field form the inclusion of a large number of onfocus event handlers will bloat the HTML so this behaviour should be defined in a separate script file.
var helpers = ['Please enter your name', '…', … ];
function addFieldListeners() {
var elems = document.forms[0].elements;
for (var i = 0; i < elems.length; i++) {
if (elems[i].type == "submit") {continue;}
elems[i].onfocus = function(evt) {
evt = (evt) ? evt :
(window.event) ? window.event : null;
if (evt) {
var elem = (evt.target) ? evt.target :
(evt.srcElement) ? evt.srcElement : null;
if (elem) {
var value = elem.value;
for (var i = 0, m = helpers.length; i < m; i++) {
if (value == helpers[i]) {
elem.value = "";
}
}
}
}
}
}
}
Here an anonymous function is assigned to each form field and when focus is recieved the value is
tested against an array of predefined placeholder text strings. This code could be cleaned up by assigning a
new array search function to the Array object prototype property, and a global function for retreiving the element that
received the event (since other behaviour in the document may require this). This solution will suffice, with
new placeholders just added to the helpers array, but in larger projects this in itself can
become quite a tiresome process - take a content management system as an obvious example.
Working on a CMS solution just the other day I thought about using the title attribute of the input field to store the placeholder text. My initial thinking was that this could still provide the helper information to the user after they had set focus on the field. If they were jumping around a large form, the user should not be expected to remember the helper text once it has been cleared. Plus the purpose of the title attribute is to provide additional information for the element - exactly what the helper/placeholder text is doing in this scenario. So, this time, using the closure technique discussed previously, the following:
<input type="text" id="name" name="name"
accesskey="n"
title="Please enter your name"
value="Please enter your name" />
could be handled with the following field listener:
function FieldListener(elem) {
this.elem = elem;
this.helper = "";
var me = this;
this.init = function() {
this.helper = this.elem.getAttribute('title');
// Scott Andrew's addEvent method at
// www.scottandrew.com/weblog/articles/cbs-events
addEvent(this.elem, "focus", this.clear);
addEvent(this.elem, "blur", this.redisplay);
}
this.clear = function(evt) {
if (me.helper == me.elem.value) {
me.elem.value = "";
}
}
this.redisplay = function(evt) {
if (me.elem.value == "") {
me.elem.value = me.helper;
}
}
}
The FieldListener object stores the title attribute value in a member variable when it is instantiated, then when the field receives focus, the field value is compared against this member variable. Functionality can be extended by redisplaying the placeholder text if the field is still empty when the user moves focus elsewhere - the FieldListener.redisplay() function achieves this. This event listener can be bound to each form field (along with other behaviours - eg pseudo CSS, validation) as follows:
function register(collection) {
var i, elem, listener;
for (i = 0; elem = collection.item(i++); ) {
if (elem.nodeName == "INPUT" &&
elem.getAttribute("type") != "text")
{continue;}
listener = new FieldListener(elem);
listener.init();
}
}
function __init() {
if (document.getElementsByTagName) {
var input_flds = document.getElementsByTagName('input');
register(input_flds);
var textarea_flds = document.getElementsByTagName('textarea');
register(textarea_flds);
}
else {
nastyHackToHandleNonW3CDom();
}
}
// see Simon Willison's addLoadEvent entry at
// http://simon.incutio.com/archive/2004/05/26/addLoadEvent
addLoadEvent(__init);
An alternative function would need to be provided for legacy browsers that do not support DOM2 (Netscape 4.x, MSIE 4.x). Perhaps just selecting the placeholder text on field focus so the user can delete it if they wish to (DOMElement.select()) may suffice. To round off, this modular solution provides a simple automated approach to handling placeholder text that does not require the author to expicitly register the text within the Javascript code - the whole process is automated based on the value of the title attribute.
Posted on Jul 01, 2004 at 16:34:43. [Comments for Automating Placeholder Text In HTML Forms- 4]
Also relates to Accessibility
Thanks to Simon Willison's interesting post on closures in Javascript I recently rediscovered
W3Future's article on applying closures to event handling methods. This article provides a very illuminating resolution
to the common problem in separating the behaviour of a web page from the structure - the method assigned as the event handler to an object does not contain a reference to the object itself (at least not in IE).
Traditionally this could be solved with a cross browser concoction of event.target, window.event.srcElement and bubble management.
The closure paradigm is a very adaptable and dynamic solution, that not only allows clean cross browser access to the source element, but is readily extensible in an object oriented environment:
function EventHandler(elem) {
this.elem = elem;
this.evt = "";
this.register = function(handler, fn) {
addEvent(this.elem, handler, fn);
}
this.invoke = function(evt) {}
this.cancel = function() {}
}
function FieldHandler(elem) {
var me = this;
this.base = EventHandler;
this.base(elem);
this.mouseon = function(evt) {
me.invoke(evt);
}
this.mouseoff = function(evt) {
me.invoke(evt);
}
}
FieldHandler.prototype = new EventHandler;
handle = new FieldHandler(DOMElement);
handle.register('mouseover', handle.mouseon);
handle.register('mouseout', handle.mouseoff);
The me variable provides access each instance of the FieldHandler object, which would otherwise be unavailable. (Note EventHandler::register it uses Scott Andrew's
Cross Browser Event Handling routine
to assign the event listeners.) Another use might be to assign the callback function for the event at runtime based on the event type:
function EventHandler(elem, me) {
var me = this || null;
// …
this.invoke = function(evt) {
me.evt = (evt) ? evt :
((window.event) ? window.event : null);
me.assign();
}
this.assign() = function() {}
// …
}
function FieldHandler(elem) {
this.base(elem, me);
// …
this.assign() = function() {
switch(this.evt.type) {
case 'mouseover':
this.mouseon();
break;
case 'mouseout':
this.mouseout();
break;
}
}
// …
}
// …
handle.register('mouseover', handle.invoke);
handle.register('mouseout', handle.invoke);
The one stumbling block I fell over briefly was the cancelling of an event. A typical example being a stylesheet switcher where a link is supplied to switch the CSS on
the server where Javascript is not available. In a Javascript environment the HTTP request should be cancelled. Sadly, using event attachment to assign handlers, return false will not cancel the operation.
Information on this hurdle appears to be lacking on the web, but fortunately the solution was nestled in the DOM2 Events Specification:
this.cancel = function() {
if (this.evt) {
if (this.evt.preventDefault) {
this.evt.preventDefault();
}
this.evt.returnValue = false;
}
}
In the W3C event model preventDefault called anywhere within an event processing tree will cancel the default event. For the Exploders falsify the returnValue property for the event.
These are very basic examples, but just in an afternoon I discovered immense power in this method without the need to hack cross browser
scripts (I have tested the method successfully across all the major PC browsers - IE5.x, IE6, Moz, Opera). I have started work on integrating the EventHandler class
into my form validation scripts and will hopefully present this as a more detailed and explanatory article when I find more time. The biggest benefit of the method is it allows for
the behavioural scripts to be totally detached from the mark-up for a web document, thus only serving javascript content where it can be handled while achieving a more lightweight document.
Posted on Jun 20, 2004 at 03:39:51. [Comments for Accessible Javascript Event Handling- 6]