Matt Snider JavaScript Resource

Understanding JavaScript and Frameworks

Friday, November 16, 2007

Convert Array-Like Objects To Arrays

I am attending a surprise party tonight and have a wedding to attend this weekend, so this will be a short post today.

In my recent post, Batch Function, I introduce a technique that can be used to turn arguments into Arrays. You use the Slice Function attached to the prototype of Array to convert Array-like objects into Arrays. For example:

// arguments var getArgumentsAsArray() { return Array.prototype.slice.call(arguments, 0); } // nodelist var getElementsByTagName(el, tagName) { return Array.prototype.slice.call(el.getElementsByTagName(tagName), 0); }

Mostly, I use this this technique to reduce elements from the front of a collection, by change the ‘0′ to the first index in the collection that I want. However, I recently realized that IE 6 does not support this technique on nodeLists (childNodes and lists returned by getElementsByTagName). In fact it will break you JavaScript code and throw an exception.

I played with various techniques to see if there was another Hack that worked for IE, but nothing did. In the end I came up with this x-browser safe function:

var convertToArray(obj, n) { if (! obj.length) {return [];} // length must be set on the object, or it is not iterable var a = []; try { a = Array.prototype.slice.call(obj, n); } // IE 6 and posssibly other browsers will throw an exception, so catch it and use brute force catch(e) { Core.batch(obj, function(o, i) { if (n <= i) { a[i - n] = o; } }); } return a; };

Where ‘n’ is the number of elements you want to skip. So, if I want to skip the first two elements of the collection, then “n = 2″, and if I do not want to skip any, then “n = 0″.

posted by Matt Snider at 6:09 pm  

Friday, November 9, 2007

Support Multiple Safari Versions

Not enough time today to finish my event package article, but will do so tomorrow. Today, I wanted to share the multiple safari project. Many Mac designers have probably upgraded to Leopard and no longer have Safari 2. However, Safari 2 is still the dominant Safari browser and needs to be supported. The multiple safari project allows you to run different Safari instances in order to properly test each browser version.

http://michelf.com/projects/multi-safari/

posted by Matt Snider at 5:00 pm  

Friday, September 28, 2007

Xbrowser Event Handling

On of the most powerful features of almost every Framework is x-browser Event management. This is important because standards dictate that you SHOULD ALWAYS separate implementation from design by leveraging the JavaScript DOM event management, instead of writing events inline. The problem arises from the browser wars, when the yahoos over at Microsoft decided to come up with a non-standard event model, making x-browser event management painful. Each Framework has their own implementation that wraps the two event systems, sometimes including additional bells and whistles, such as: scope adjustment, deferred loading, caching, cleanup, custom events, and more. However, the event management system of most Frameworks is so complex you have to wonder if it is all necessary and how coders managed events before Frameworks.

The reality is that most people do not need the extras, just a couple simple event handler functions that wrap the x-browser methods. Many programmers do not yet understand the power of the JavaScript event handlers. Therefore, often when I give advice to new coders and ask them how they handle x-browser events, I am usually greeted with blank stares. Most beginners do not take the time to fully understand JavaScript, because it is so simple to pick up and start working with. Plus, searching the net only overwhelms one with nearly endless examples of crap code, by people who also did not take the time to properly understand JavaScript and/or good design principles.

As I said at the beginning of this article, “You SHOULD be using JavaScript event handlers, instead of writing events inline.” Managing events is not all that complex, when you only need a plain interface wrapping the x-browser methods (just annoying). Here is the simplest way to manage events:

var attachFunc = ”, detachFunc = ”; // Create the Event Function wrappers if (window.addEventListener) { // standards compliant method attachFunc = function(el, eType, fn, capture) { el.addEventListener(eType, fn, (capture)); }; detachFunc = function (el, eType, fn, capture) { el.removeEventListener(eType, fn, capture); }; } else if (window.attachEvent) { // microsoft compliant method attachFunc = function(el, eType, fn, capture) { el.attachEvent(”on” + eType, fn, capture); }; detachFunc = function (el, eType, fn, capture) { el.detachEvent(”on” + eType, fn, capture); }; } else { // event handlers unsupported attachFunc = function() {}; detachFunc = function() {}; }

This code sample will attach the appropriate event handling function to attachFunc and the appropraite event removal function to detachFunc. Put this anywhere in your code library before you start attaching events and it will simplify event management. I recommend you wrap this function into a namespace, such as “Event”, but you can use them as is. So anytime you want to attach an event (”click”, “keydown”, etc.) to an element, instead of writing something like “<a href=”#” id=”myAnchor” onclick=”someFunction();”>clickMe</a>”, you would write the following directly in your JavaScript code:

var link = document.getElementById(”myAnchor”); attachFunc(link, ‘click’, someFunction);

You can safely ignore the capture option, unless you know what the capture phase is.

For some more information on x-browser event support, check out Peter Paul Koch’s article: Advanced Event Registration.

posted by Matt Snider at 10:44 am  

Wednesday, September 26, 2007

CSS Frameworks And Removing X-browser Variations

There is a lot of hype on the web right now around CSS Frameworks; a lot like there used to be around JavaScript Frameworks, before they became so popular. It is important to understand what they are and why they will (or will not) be helpful to you.

What is a CSS Framework

“[A CSS Framework is] a set of tools, libraries, conventions, and best practices that attempt to abstract routine tasks into generic modules that can be reused. The goal here is to allow the designer or developer to focus on tasks that are unique to a given project, rather than reinventing the wheel each time around.” [Framework For Designers, by Jeff Croft]

That is a lofty goal and I believe that most CSS Frameworks endeavor to simplify your life. However, I do not think they usually do. Where CSS Frameworks excel is normalizing styles, especially x-browser variations and typography. Where they fail (or become cumbersome) is when they try to do too much such as: every layout under the sun, rigid design, large code-bases (bloating), etc. If a Framework does too much, then you end up needing to learn what it is doing and why, and without prolific commenting CSS can quickly become confusing and you wonder why a particular property might be necessary.

Despite the downsides, I recommend using a Framework, or at least part of a Framework. The most important effect from using a Framework is reseting browser specific styles, so that 1 stylesheet can be used for all browsers, instead of 1 stylesheet for each browser (or worse, a bunch of browser specific hacks). Most commonly, the browser variations are the default ways they apply padding, margins, and/or fonts to elements.

I personally, never use a complete Framework, because I prefer to have control over my layout and typography, but I always use a CSS Framework to reset browser styles. If you are not a designer and need a quick solution, or find CSS Frameworks helpful, then you should leverage them. Here are the few that I modeled my “reset.css” stylesheet from, which I use as a foundation for all my projects (and hopefully, on this blog as soon as I get some free-time):

  • Tripoli: tries to remain simple by mostly just resetting styles, but also applies some optimal changes to typography and layout
  • YAML: very well documented, multi-column layout builder with all the bells and whistles
  • YUI : lots of layout variety and optimized for integration with the YUI JavaScript Library

Smashing Magazine also wrote a great article about this topic where they cover more details about each CSS Framework listed here, and several others.

Normally, I would probably taut how much I like what YUI has done, but not this time. Although, I do really like their “reset.css”, I find the rest of the Framework to be heavy-handed, with too many options and not enough documentation. Also, the Framework includes styles for some parts of the JS Framework that I do not use. YAML, does a great job, but has a lot of options and extra features that you probably won’t leverage. Tripoli, has the simplest and most unobtrusive styles, and if I was to just to throw a Framework onto a site without modifying it, I would use this one.

In the end I just wanted a set of styles to reset browser specific formatting, and I modeled this by looking at the afore mentioned Frameworks:

/** * Copyright (c) 2007, Matt Snider, LLC. All rights reserved. * version: 1.0.0 */ /* remove default element padding */ body, div, dl, dt, dd, ul, ol, li, h1, h2, h3, h4, h5, h6, pre, code, form, fieldset, legend, input, textarea, p, blockquote, th, td { margin: 0; padding: 0; } /* default color scheme */ html body { background: #fff; color: #000; } /* remove borders and possible underlining */ a, img, a img, iframe, form, fieldset, abbr, acronym, object, applet { border: none; font-variant: normal; } /* remove stylized font-variations */ address, caption, cite, code, dfn, em, strong, th, var, i, b { font-style: normal; font-weight: normal; } /* table and center elements should always be top left aligned */ caption, th, td, center { text-align: left; vertical-align: top; } q:before, q:after { content: ”; } /* remove cellpadding and cellspacing */ table { border-collapse: collapse; border-spacing: 0; } /* clear possible list-styles; should override in design */ ul, ol, dir, menu, li { list-style: none; } /* clear possible heading styles; should override in design */ h1, h2, h3, h4, h5, h6 { font-size: 100%; font-weight: normal; } /* prevent default browser coloring of links */ a { color: inherit; } /* reset position of sup and sub */ sup, sub { vertical-align: text-top; } /* clear form field font settings */ input, textarea, select { font-family: inherit; font-size: inherit; font-weight: inherit; }

This is available for download at http://www.mattsnider.com/assets/css/reset.css.

What does this have to do with JavaScript

JavaScript and CSS are closely linked, especially when you consider animation and all the times you have to apply a style on the fly. It is important for JavaScript developers to understand CSS and it is also important that when they apply a style to an element, that element behaves as expected in all browsers. This blog will continue to focus on JavaScript, but every couple weeks, I will write a something important about CSS so we address more complex issues and widgets involving CSS and JavaScript.

posted by Matt Snider at 12:03 am  

Friday, September 14, 2007

Two Helpful IE Hacks

For a change of pace, below is a short article about CSS.

* (star) or Holly Hack

In most browsers the CSS root tag is ‘html’, so you might write:

html body { font-size: 12px; }

In, IE (version 6 and lower) Holly (Bergevin, i think), found that the DOM actually starts with ‘*’, so you might write:

* html body { font-size: 12px; }

Because only IE 6 and lower understands the ‘*’, all other browsers (including IE 7) ignore style declarations beginning with star. Because of this, many designers use this hack to apply styles needed only for IE6. Most commonly this is as a result of IE Box Model issue, however, if you build your DOM carefully and don’t apply heights or widths to elements with margins or paddings then you won’t have Box Model issues.

PNG Transparency

Lately, I have been using the holly hack, because IE 6 does not support PNG transparency. If you find yourself forced to use transparent PNGs, then you can use the holly hack to target the element and apply this Microsoft only filter:

* html a.png { background: #FFF; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src=’relative/path/to/my/png’, sizingMethod=’scale’); }

The filter is a Microsoft only transformation that applies the alpha or index transparency filter for the image. I found with strict doctypes that the filter only works if you explicitly declare a background color, otherwise if you inherit a color, it seems to ignore the filter.

posted by Matt Snider at 6:31 pm  

Wednesday, August 8, 2007

Safari 2.0 Regex Bug Crashes Browser

Several of my projects have reported that my JSON objects were not working properly in Safari 2.0 and less. Namely, the browser completely crashes when trying to parse the server returned JSON object. I always use Douglas Crockfords ‘Json.js‘ file to sanitize my JSON messages and could not figure out what was wrong. After some digging and some debugging on a friend’s mac, I learned that Safari does not support regular expression evaluations on data larger than ~5k. The only solution is to not sanitize the JSON in Safari browsers.

Tobie Langel also wrote a blog post about this entitled “Yet Another Safari Bug“. He is focusing on how to leverage the Prototype Framework to do this and has modified the regex to allow slightly larger data set.

I choose to do the following browser detection, because I could not find/write a non-browser detection solution that targeted only Safari and stop the browser from crashing.

if (Core.Client.browser == “Safari”) { return (jsonResponse) ? eval(jsonResponse) : []; } else { return (jsonResponse) ? jsonResponse.parseJSON() : []; }

This leverages the browser detection functions in Core.js.

Update 10/29/2007: On Saturday (10/27/2007) I spoke with Douglas Crockford at the Code Camp conference and he has found the limit to exist in Strings 5000 to 7000 characters long, depending on your machine. Unfortunately, he doesn’t plan to update JSON.js, anytime in the near future, to handle Safari 2, as the browser is being phased out.

Also, Steve @ blog.stevenlevithan.com has written a better Regex Object XRegExp 0.2. I have not spent much time working with it, but it is supposed to defeat the Safari Bug and generally improve JavaScript Regex support.

posted by Matt Snider at 2:05 pm  

Monday, July 2, 2007

jQuery, iFirebug, and iPhone Programming

Some important events happened in the JavaScript community this past week: new jQuery release, Joe Hewitt wrote an iPhone extension for Firebug, and developing for the iPhone is getting a lot of hype. Here are some articles that do a great job covering this:

posted by Matt Snider at 2:31 pm  

Friday, May 11, 2007

Opacity

Today, I experimented with the YUI Animation widget and experienced difficulty getting the opacity style to apply correctly in IE 6. It was fine in IE 7, Firefox, and Opera, but IE 6 seemed to ignore the opacity style changes. A quick web search revealed that in IE 6 opaque elements need a height and width, otherwise the opacity style will be ignored.

IE6 Opacity Filter Caveat

posted by Matt Snider at 12:38 am  

Friday, April 27, 2007

JavaScript Memory Leaks

On one of my projects, http://www.mint.com, I recently noticed severe performance degradation in IE6 the longer I kept the browser open. As it turns out a lot of the techniques used by JavaScript Frameworks, and even my own JavaScript architecture, causes memory leaks. This is especially prominent in IE6, because its memory manager has poor heuristics for detecting JavaScript leaks. It’s not as important in better browsers like, Firefox, but I do notice that Firefox slowly eats up memory as well (although this may be a documented browser memory leak). It was particularly noticeable on Mint because our JavaScript library has become bloated to well over 15,000 lines of code and IE6 just can’t handle so much leakage.

CORRECTION - Firefox memory leak, is actual a feature and not a bug. If you want to prevent Firefox from using too much memory, read this article:
http://forevergeek.com/open_source/debunking_another_myth_firefoxs_memory_leak_bug.php

Some things to improve performance are: avoid using closures, don’t do circular references, and when appending DOM elements always build from the document deep. That’s all I’m going to say, because this is a very complicated issue and I don’t have the time to do the proper analysis. However, these three articles cover everything you really need to know:

IE Leak Patterns
Closures and Circular References
Leak Patterns

posted by Matt Snider at 12:23 am  

Powered by WordPress