- Recent
- Popular
- Tags (1)
- Subscribers (7)
- Cross-Browser Event Handling and Memory LeaksDecember 9 2006
-
In the "old-style" event registration model, you would typically register events by assigning functions to the onevent property of DOM elements:
elem.onclick = function() { alert("You clicked me"); }The problem with that approach is that you can only assign a single event handler function to any given event. All modern browsers support more advanced event registration mechanisms so you can attach multiple event listeners to any given event, though, as usual, those mechanisms vary across platforms. This recipe can be used to register and unregister event listeners in all modern browsers:
function addEventListener(instance, eventName, listener) { var listenerFn = listener; if (instance.addEventListener) { instance.addEventListener(eventName, listenerFn, false); } else if (instance.attachEvent) { listenerFn = function() { listener(window.event); } instance.attachEvent("on" + eventName, listenerFn); } else { throw new Error("Event registration not supported"); } return { instance: instance, name: eventName, listener: listenerFn }; } function removeEventListener(event) { var instance = event.instance; if (instance.removeEventListener) { instance.removeEventListener(event.name, event.listener, false); } else if (instance.detachEvent) { instance.detachEvent("on" + event.name, event.listener); } }The usage model f
- Canceling and Stopping Browser EventsDecember 8 2006
-
If your Ajax application is graphically intensive, it probably uses a lot of CSS absolute positioned elements and the CSS z-order attribute extensively. The problem with overlapping elements is that events automatically bubble up from foreground elements to background elements, so if you blindly capture events like click in background elements, you may receive them when you are not expecting them. For example, if you have a div element floating above other elements, events will automatically bubble up to background elements, often leading to your application inadvertently handling the event in both the foreground div and the background div.
If you want to prevent events from bubbling up to background elements, you can capture the event with this recipe:
function stopEvent(e) { if (!e) e = window.event; if (e.stopPropagation) { e.stopPropagation(); } else { e.cancelBubble = true; } }For example, to prevent the container of a link to receive a click event when the link is clicked, you would use the function above like this:
var link = document.getElementById("link"); link.onclick = stopEvent;The snippet above will prevent the background of the link from receiving a click event, but how do you prevent the link itself from getting the click event? This recipe completely cancels an event, whic
- JavaScript Debug LogDecember 3 2006
-
Even with the most advanced debugging tools, every program requires a little "printf debugging": run your program, print out state as it executes, and visually verify that everything is working properly. Unfortunately, there is no built in console to print debug messages to in JavaScript, forcing many JavaScript programmers to revert to calling alert() in their code. alert is completely infeasible for a function that gets called a lot, as it halts execution until you click an OK button. This recipe creates a simple debug log window that does not halt execution:
function log(message) { if (!log.window_ || log.window_.closed) { var win = window.open("", null, "width=400,height=200," + "scrollbars=yes,resizable=yes,status=no," + "location=no,menubar=no,toolbar=no"); if (!win) return; var doc = win.document; doc.write("<html><head><title>Debug Log</title></head>" + "<body></body></html>"); doc.close(); log.window_ = win; } var logLine = log.window_.document.createElement("div"); logLine.appendChild(log.window_.document.createTextNode(message)); log.window_.document.body.appendChild(logLine); }To print log messages, you just call log() within your code:
for (var i = 0; i < 10; i++) { log("This is log message #" + i); }When you push your code to production, y
- Disabling the Browser Context MenuDecember 3 2006
-
You can disable the browser context menu for an element in your DOM with the following JavaScript recipe:
function disableContextMenu(element) { element.oncontextmenu = function() { return false; } }For example, to disable the context menu over a photo on your page, you could use:
disableContextMenu(document.getElementById("photo"));Browsers like Firefox do not always allow web pages to disable the context menu (this option is a setting in Firefox), so this recipe will not work 100% of the time in all browsers.
- Currying JavaScript FunctionsOctober 5 2006
-
Currying a function is the act of transforming a function that takes n arguments into a function that takes n - 1 arguments. Essentially, currying is the act of binding the first argument of a function to a specific value, creating a new function that takes the remaining arguments. Here's a simple example:
function add(x, y) { return x + y; } // produces 7 add(3, 4); // produces a function with x bound to 3 that takes y as an argument var add3 = curry(add, 3); // produces 7 add3(4);In this example, we curry the add(x, y) function to produce the add3(y) function that always adds 3 to its only argument. While this may seem useless initially, currying is very useful in the context of Ajax callbacks. For example, say you want to add a constant amount 4 to a counter every time a button is clicked? Just curry!
button.onclick = curry(callback(this, addToTotal), 4);Thanks to the functional parts of JavaScript and the ability to access JavaScript function arguments as an array with the arguments variable, implementing the curry function is easy, as this recipe illustrates:
function curry(method) { var curried = []; for (var i = 1; i < arguments.length; i++) { curried.push(arguments[i]); } return function() { var args = []; for (var i = 0; i < curried.length; i++) { args.push(curried[i]); } for (
