04/02/2011

Hack Fix For typeface.js JavaScript Error " 'undefined' is null or not an object"

In IE the following JavaScript error is thrown in circumstances where there is no match for an individual character code in your font glyph map (you know that file you generated for your font):

Error " 'undefined' is null or not an object"
Line: 601 (uncompressed source code).

At time of posting I am using typeface-0.14.js.

The visual result of this error is the sudden disappearance of all headings after the heading which contains the erroneous character on your page. If you inspect your markup, you will notice your missing head tags ALL contain style="visible: hidden" yet have no VML content. This is a result of typeface hiding markup elements before ensuring it can successfully emit the resulting vml syntax & an error.

The Hack fix, which merely seeks to allow typeface to continue processing all "non-corrupt" words on the page (rather than an ugly fail & missing headings) is to modify typeface.js with the following:

1) In the _renderWord method, wrap all calls to: "this.renderGlyph" in a try catch statement.
2) If an Exception occurs return null.

You will find renderGlyph is invoked VIA the renderWord & recursively VIA the renderGlyph method(s). Fortunately for us, the method that calls renderWord (getRenderedText) performs a null check on the renderWord result. If the return from the renderWord method is null, the word will be "ignored" by the portion of the method responsible for creating the VML, and therefore will NOT cause a catastrophic failure in typeface enabling rendering of subsequent words & headings.

So that's the solution. It works. To be honest, I don't like this solution for a bunch of reasons:

1) I don't like try ... catch oriented programming. If there is an error, I want to be told of it so I can treat its root cause rather than at its symptoms. However, circumstances do arise which make it difficult to ensure issues are treated for root cause (EX// CMS Systems which do not impose such limitations on user generated content).

2) The primary reason: This is a 3rd party library for my app. Inevitably, at some point in the SDLC, someone smart is going to take over this project and say: "I can't believe they are using typeface-0.14.js, don't they know it's at version 3 right now". Other than the fact the file is named typeface-0.14-CUSTOM.js & loaded with customization comments, there is no indication to developers that this file has been customized (devs tend to look at code & runtime behavior vs ReadMe files & comments). And you know the rest of the story that starts with: I,E,6; Ends with: "hack fix"; and resounds in a high pitched user saying: "Everything was working fine until your last deployment".

3) A "JavaScript plugin" with such a pervasive behaviors, to a certain degree could be better programmed to isolate and tolerate faults. NO, this is not a contradiction to #1 above, but rather, represents an authors conscious decision to say: "Ok, with respect to what I'm trying to do, I CAN tolerate this fault, but I CANNOT tolerate that fault". In the case of this fix, I have made a conscious decision to say: "It's better if I just fail this one word than risk failing every subsequently unprocessed heading and word on the document".

4) 1#: I am in no way speaking down or pointing a finger at the typespace developers. I think everyone in the community owes them a stand up applause. Seriously. Amazing work & great contribution guys! I have contributed this fix. But in developing a site, and having to decide on how typography would be handled, and being in an " obviously IT" time crunch, I really don't have time for errors like this. More specifically, having written & proofed an opposable dynamic font solution to typeface, when I saw these errors, I immediately sought to rip typeface out of my application. This developer decision directly contradicts mass adoption of these technologies. Let's be honest, with the typeface source code, and a web browser, it's pretty easy to figure out this work around, but for the 90% of users that don't have the skill, it's a three point shot into the garbage bin. In not patching this gap, the door swings open (insert firm kick from behind) for developers to consider alternatives & for this to never truly mature. For example my train of thought: P - "undefined error in typeface (3rd party js lib??)" -- TOT - "another hack library not doing null checks" -- R - "ctrl+f5 on browser" -- NEXT - P "undefined error in typeface" -- TOT - "this is a third party library, is it even reasonable to try to crack the hood?" -- R - "build new matrix of reasons I'm using typeface and not my guaranteed image based solution" -- NEXT -- P "is typeface the right tool for this?" -- TOT "evaluate guaranteed solution vs. unexplored option" -- R "how much time required to fix" -- NEXT -- P "what is the quickest means to an end: risk debugging typeface VS. introducing jQuery convention" -- TOT "I can justify spending 10mins debugging typeface, after that, I'm pulling out and inserting my fontSprite". OUTCOME: typeface is a really well designed script that is easy to diagnose and repair problems in therefore 10 mins spent investing and repairing problem in typeface source was worth the effort. I conclude this is true ONLY because the resolution was simple. And this is my reservation: we use these scripts to gain a level footing on different platforms. When platform comparability issues are prevalent in X-Platform platforms, it's difficult to remain confident about that platform. Aren't the five lines of code required to implement this fix / ensure failure is logged (nice logging BTW) worth the end user inconvenience even if it is merely makeup? The vs. personality of the algorithm/argument is: "Nice headings dude, but, but, but, a word isn't printed because a) it contains illegal characters, b) etc. reasons. Sorry dude, I tried my best." vs. "Rookie Undefined Error dude. LOL - you seriously want me printing mo headings after that BS!". IE sucks, but the point of using typeface is to eliminate this issue. I don't think putting this fix on hold or on me is the way it should be. I get the point.

At EOD, typeface was used and the project was a success. However, it is unrealistic to expect shops to jump into 3rd party JavaScript libraries & build custom fixes. I fully understand the philosophy behind not fixing this problem however, I fail to see how not fixing this problem works in the best interest of typeface or the JS community.

Moreover, and to set the record straight for concerned readers: this problem is really uncommon. In any controlled environment it would be completely avoidable. This is a manifestation of how our lazy CMS (SharePoint 2010) emits character data with hexadecimal encoding (you know those invisible characters with "" values and character codes in the 80k range).

Typeface is there for you on the 99.9% side, my point merely talks to one specific circumstance in what is otherwise a really amazing product.

Over and Out.

Matt