We are working hard to improve the Gadget framework documentation. In the meantime (and as we improve documentation), I am working on a series of short tutorials, tips, and highlights introducing how to use the Gadget framework and the underlying APIs.
I am going to start with our compatibility layer. After exploring various third-party gadgets being developed for Live.com, I discovered that many developers are still struggling with the API differences between Firefox and Internet Explorer. Most common, I see various tricks to handle the event model differences where IE uses a global event object and Firefox passes the event object as an argument to your handler.
This is not necessary when you build Gadgets. Instead, you should be leveraging the underlying compatibility layer that is part of the overall Gadget framework.
As I posted last September, as we develop our properties, almost none of our application logic contains browser specific code. Instead, we develop once to the Internet Explorer API and our code runs without modification in Firefox. This occurs because we download a special script that emulates the most useful IE’isms inside of Firefox and in a few cases, Firefox/W3C’isms in Internet Explorer. In this article I highlight the most useful methods and properties of this layer (I promise we will develop a full reference in the near future).
Event Model
This is easy – always attach events using attachEvent and detachEvent. Do not assign event handlers using function references (e.g., myElement.onclick = doThis) nor use the addEventListener approach.
In your event handlers, don’t worry – you will always get the global event object. For example:
function doClick()
{
alert("You clicked on a " + event.srcElement.tagName +
" element");
}
document.body.attachEvent(“onclick”,doClick);
Also, as a general practice (I will cover this more in later articles but this is extremely important), when writing Gadgets, be sure to detach any event handlers in your dispose handler. Otherwise, your Gadget will leak memory due to known browser issues.
What can you do with this event object? You can check out the MSDN reference as most properties are exposed. In addition to the standard properties, below are the list of properties we added to Firefox:
- srcElement
- cancelBubble
- offsetX
- offsetY
- x
- y
- returnValue
- button (few issues as Firefox does not properly distinguish between the left button and no button)
- fromElement
- toElement
We have also gone further and extended Firefox with the very useful mouseenter and mouseleave events. As long as you attach these events using the attachEvent and detachEvent methods, these events fire just as they do in Internet Explorer. These events are very useful for quickly and easily detecting when a mouse enters or leaves a specific element. Again, check out the MSDN reference for more details.
We even have a reasonable emulation of mouse capturing. However, this is most useful in the context of an entire web-page not within a simple gadget. This is because mouse capturing in Firefox only fires within the context of the browser client area. Regardless, when using mouse capturing (setCapture and releaseCapture methods), the mouse events fire properly on the correct elements.
We also fixed the Firefox onclick event to only fire for the left mouse button (Firefox fired for all mouse buttons). This little difference could cause you grief in your application. (For those of you who noticed that we also accidentally prevented the ability to open pages in new tabs via the middle button, that will be fixed real soon).
Useful Element Methods
Internet Explorer also supports a number of very helpful methods and properties on every element. These APIs simplify day-to-day programming and are very useful for building your application. Below are the list of element functions we added to Firefox. Again, check out MSDN for the details (linked for each item below) on how they work.
The currentStyle property returns the value actually being applied to the element. We currently support a subset of CSS attributes that we have found useful: border, margin, padding for Top, Left, Right, and Bottom; position; height; width; zIndex; color; and direction. We will most likely extend this list over time.
Useful style properties
We also extended the properties available on the style object with the extremely useful pixel* properties. These allow you to easily manipulate the dimensions of the element (assuming you are working with pixels). We also added the cssText property which gives you a serialized representation inline style.
XPath Expressions
When dealing with XML documents the ability to query for specific nodes is especially useful. Trying to decipher the difference between IE and Firefox for querying XML can be extremely painful. So, we provided support for two very straighforward IE methods, selectSingleNode and selectNodes.
Creating xmlHttp Objects
When you need to create a new XML Http Object, you can now simply use the standard approach, var y = new xmlHttpRequest(). However, as I will cover in future articles, I highly recommend you leverage our built-in network stack for all your network requests.
Parsing XML
Last, but not least, you have a string that you want to load into an XML DOM - just use the standard DOM Parser object:
var dp = new DOMParser();
var xmlDom = dp.parseFromString(yourXMLString);
This concludes my very brief and fast introduction to our compatibility layer. We are continually expanding the functionality. For example, we have basic IE filter support (alpha filters assigned via script will also apply in Firefox). I will cover these in later posts. For now, resist the urge in your Gadgets to author code differently for each browser. Instead, take the easy road and let our compatibility layer do all your heavy lifting.
Last, since it will inevitably come up, see the following post on why we support or don't support other browsers (while the post talks about start.com it is relevant to all properties on our framework).