User Experience Engineering

Thursday, April 14, 2011

 

Mootools intrudes on native JSON and Crockford's json2.js

I recently upgraded an application to use JSON2. When it was used in an environment containing Mootools 1.2.4, the application broke, throwing an error, "failed to deserialized json object". The application is portable, and has to play nicely in polluted waters. The object to be serialized client side had an attribute that was a two-dimensional array, constructed as array literals:
    "foo": [[1, "string", "anotherstring" {object:true}]] 
I expect output like this from JSON.stringify:
    "foo":[[1, \"string\", \"anotherstring\" {object:true}]] 
And I get it, from native JSON, from json2.js, and from the older YAHOO.lang.JSON. Mootools returned:
    "foo":"[[1, \"string\", \"anotherstring\" {object:true}]]"
The object attribute was represented as a string! So, I dug into the reasons why the shiny new JSON2 library had this issue, and only with Mootools present. Here is some history, and results of debugging.
  1. Collisions between Mootools JSON.js and browser-native JSON were tragically ignored by mootools devs in February 2009: https://mootools.lighthouseapp.com/projects/2706/tickets/607-native-json-support-in-firefox-31
  2. Another collision report (November 2009) was closed wontfix after sitting a year: https://mootools.lighthouseapp.com/projects/2706/tickets/796-mootools-jsonencode-vs-json2-jsonorg-jsonstringify
  3. Some effort was made to address issues in Mootools 1.3.1, February 15, 2011: http://mootools-users.660466.n2.nabble.com/Moo-Native-JSON-encoding-and-decoding-td6019259.html
To summarize the thread, Mootools users complained that a) Mootools does not use native JSON when available, and b) Mootools JSON does not support ECMA 5 standard method names "parse" and "stringify". Mootools developers argued that they "MooTools had the JSON object before it was specified" and that they did not like the names "parse" and "stringify". Mootools developers ended up apologizing, but not for the fundamental flaw: that of modifying native JavaScript Objects in the first place. It would seem that my application's issue were solve because Mootools 1.3 has not tacked .toJSON onto the array-like [] object.
    typeof value.toJSON === 'function') { 
       // (JSON2's test now returns false, so the serialization is handled by JSON, not Mootools)
Below is the nitty gritty of how Mootools 1.2.4 can break JSON2. Mootools 1.2.4 Here's the line where Crockford's JSON2.js tries to optimize by using a native method:
    function str(key, holder) {
        ...
// If the value has a toJSON method, call it to obtain a replacement value.

        if (value && typeof value === 'object' &&
                typeof value.toJSON === 'function') {
            value = value.toJSON(key);
        }
Execution steps into Mootools' intrusive method:
Native.implement([Hash, Array, String, Number], {
 toJSON: function(){
  return JSON.encode(this);
 }
});
Mootools $type function returns 'array' for a literal []. (Standard typeof operator returns 'object')
     obj.$family.name // property $family was added by Mootools 

Comments: Post a Comment

Links to this post:

Create a Link

Thursday, September 16, 2010

 

LinkedIn.com Naked. Again.

I've seen this a few times in the past 3 weeks. Thought it was an intermittent glitch, connection problem, CDN. Today, I've seen it in Chrome and Firefox (FireBug enabled and Firebug disabled).

The everyday user sees something like screenshot 1.

The FireBug-using developer types can see that LinkedIn's CDN, and the JavaScript that calls it, are in a world of hurt.


LI_WCT is not defined
[Break on this error] LI_WCT([
nhome (line 619)
LI is not defined
[Break on this error] LI.i18n.register( 'share-dialog-title', 'Share' );
nhome (line 2850)
LI is not defined
[Break on this error] LI.i18n.register( 'Dialog-closeWindow', 'Close this window' );
nhome (line 4116)
ChameleonService is not defined
[Break on this error] ChameleonService.setPanel('1', {div: d...panel-01'),txId: '0', maxSlots: 15});
nhome (line 10635)
LI is not defined
[Break on this error] 
nhome (line 10804)
LI is not defined
[Break on this error] 
nhome (line 10805)
LI_WCT is not defined
[Break on this error] LI_WCT([
nhome (line 11008)
LI is not defined
[Break on this error] LI.Controls.processQueue();
nhome (line 11160)
YEvent is not defined
[Break on this error] YEvent.onDOMReady(function() {
nhome (line 11244)
LI is not defined
[Break on this error] 
nhome (line 11286)
YEvent is not defined
[Break on this error] YEvent.on( window, 'load', function() {
nhome (line 11310)
YEvent is not defined
[Break on this error] YEvent.on( window, 'load', function() {
nhome (line 11339)
appendTryNewEditorButton is not defined
[Break on this error] appendTryNewEditorButton(); 

Labels: , ,


Comments: Post a Comment

Links to this post:

Create a Link

Thursday, July 22, 2010

 

Mind Mapping on iPad: Enough Room for Thinking?

Do you like mind mapping? I find it a good way to expand thinking about complex problems. Often, looking at the mark i just made results in a visual association, and a new but related idea.

Companies are adapting their iPhone mind mappper apps to iPad. Here is a video demo of one.


I'm not convinced that you can get your mind outside-the-box by working on a little box. There's also a disconnect that occurs, I think of a new node. Then I must switch to gizmo-futzing mode in order to create the node container. Then typing mode. The keyboard grabs up about half the screen. These "not-conceptualizing" steps disrupt the free association and flow of the exercise.

Seems like stylus and tablet would be a more natural and rapid combination. And it's hard to beat markers on vast expanses of craft paper.

iThoughtsHD
http://www.ipadmindmap.com/iPadMindmap/Welcome.html

I ran this as an app trial for iPhone and found it to be cool, but the maps are too complex and sprawling for the iPhone display. Two positive points: First, It can explore and some thoughts when you are in tight quarters, like a waiting room or airplane seat. Second, it was the only mind mapping app I kept on my iPhone.

MindMeister for iPad
http://itunes.apple.com/app/mindmeister-for-ipad/id381073026?mt=8 They ported it to iPad. Work locally until in-range of wifi, then it auto-syncs with server. First few reviews are mixed.

Labels: , ,


Comments: Post a Comment

Links to this post:

Create a Link

Wednesday, May 26, 2010

 

Output a List of Firefox Extensions

There are extensions that print out your list of Firefox extensions as text. Yeah... um, that's going the wrong direction, imho. If you need that list, you are debugging a problem. No need to introduce another variable. Here's how:
  1. Type about:config into your address bar
  2. (You may get "void warranty" warnings. Proceed.)
  3. In the Filter box, type extensions.enabledItems
  4. Right-click on the result, and Copy.
  5. Paste into a text file.
You now have a comma delimited list of extensions that are enabled.
extensions.enabledItems;firebug@software.joehewitt.com:1.5.4,{3d7eb24f-2740-49df-
8937-200b1cc08f8a}:1.5.13,{d10d0bf8-f5b5-c8b4-a8b2-2b9879e08c5d}:1.2,{3112ca9c-
de6d-4884-
a869-9855de68056c}:7.1.20100408Mb1,foxmarks@kei.com:3.6.15,checkplaces@andyhalford.com:
2.2.1,{3c6e1eed-a07e-4c80-9cf3-66ea0bf40b37}:2.2,yslow@yahoo-inc.com:2.0.7,{AB7308B2-
C13C-4eba-
AC78-2AD55B96EE09}:3.0.0,csscoverage@spaghetticoder.org:0.2.1,closureinspector@google.com:0.9.5,{e3f6c2cc-
d8db-498c-af6c-499fb211db97}:1.8.1,{972ce4c6-7e08-4474-
a285-3208198ce6fd}:3.6.3
For Extra Credit, Go into vi and make the list more readable:
vi the_list.txt
:% s/[,]/\r/g

extensions.enabledItems
firebug@software.joehewitt.com:1.5.4{3d7eb24f-2740-49df-8937-200b1cc08f8a}:1.5.13
{d10d0bf8-f5b5-c8b4-a8b2-2b9879e08c5d}:1.2
{3112ca9c-de6d-4884-a869-9855de68056c}:7.1.20100408Mb1
foxmarks@kei.com:3.6.15
checkplaces@andyhalford.com:2.2.1
{3c6e1eed-a07e-4c80-9cf3-66ea0bf40b37}:2.2
yslow@yahoo-inc.com:2.0.7
{AB7308B2-C13C-4eba-AC78-2AD55B96EE09}:3.0.0
csscoverage@spaghetticoder.org:0.2.1
closureinspector@google.com:0.9.5
{e3f6c2cc-d8db-498c-af6c-499fb211db97}:1.8.1
{972ce4c6-7e08-4474-a285-3208198ce6fd}:3.6.3

Comments: Post a Comment

Links to this post:

Create a Link

Tuesday, May 18, 2010

 

Debugger-Friendly JavaScript Compression

For a rapidly-evolving application, sometimes it is necessary to sacrifice a bit of compression for the sake of debugger-friendly code. If you know of a javascript debugger or FireBug plug-in that is able to decompress-and-debug on the fly, please let me know.
A Conscious Trade-off
It's common knowledge that such tools as Yahoo Compressor can achieve optimal compression, with as much or as little obfuscation as you desire. A recognized best practice dictates "debug on your development server and compress for production." However, troubleshooting a live issue with ultra-compressed JavaScript is problematic. It can be a big hurdle for a solutions management department. Super-compression may be appropriate, depending on the application. How rapidly is the application evolving? How diverse its uses? In how many environments must it excel? If your answers are "fast", "very" and "many", a trade-off may be worthwhile.
Debuggers and Compressors
Firebug, WebKit Inspector provide some traditional debugging tools; you can set breakpoints, and do the usual step-through process. There are serious limitations.
My first step toward balance was to use Yahoo Compressor's "preserve line feed" feature. Here is an invocation of the Yahoo Compressor --line-break option.
java -jar yuicompressor-x.y.z.jar -line-break 0
However, the FireBug debugger / Yahoo Compressor combination is broken as follows.
  • Separate logical statements end up on the same line.
  • Breakpoints stop at declaration time. Function declarations and the first statement or two in their closures are on the same line. Whereas the developer intends to stop on a line in the function at runtime, FireBug will stop when the script loads.
  • Convenient Watches unusable. Normally you may hover cursor over a variable name, to see its value. This feature becomes difficult to use.
  • Breakpoints on extremely long lines are unusable... ...unless you can scroll sideways, and follow the bouncing highlighter.
If you follow the module pattern, and use object literal notation, you'll find even more compression and debugger limitations.
  • JavaScript Object Literals become single-line monstrosities. One complex object declaration became a string of 8000+ characters with no line feeds! This appears to be a side-effect of Yahoo's 1-linefeed-per-semicolon approach; the statements in an object literal are comma-delimited.
Next, I'll explore some alternatives.

Comments: Post a Comment

Links to this post:

Create a Link

Monday, April 19, 2010

 

Google Chrome Incompatible with Google Sites

I've been using Google Chrome browser for email, calendar, and bug tracking, the mainstays of office/administration work. Chrome Pros: That nicely keeps it separate from my debugging work, which occurs primarily in Firefox. I like Chrome a lot better than its WebKit sister, Safari. In most cases, it just gets out of my way. No "did you really want to close 9 tabs?" Close em. We'll reopen them if you change your mind. Cons: You would think that Google would go out of their way to assure that their browser is compatible their online apps. Here are some deficits:
  1. Google Maps: Traffic fails to appear when switched on. I use Google maps once a day to check my traffic commute. Why does it work in Firefox, and on my iPhone, and not in the browser over which Google has full control?
  2. Gmail and Incognito Mode: Chrome's privacy mode is incompatible with Gmail login. I'd like to add incognito to https to further secure my business and personal email and calendar. Login for personal email failed on three attempts. After opening in a regular Chrome window, it worked. Corporate Gmail worked in Incognito mode after 2 attempts.
Has anyone else observed breakage of Google sites or apps under Chrome?

Comments: Post a Comment

Links to this post:

Create a Link

Friday, August 29, 2008

 

Stop Firefox 3.1 Event Propagation

Some legacy JavaScript code broke in Firefox 3.1 recently. An endless loop was formed, causing a "too much recursion" error and browser crashes. Here's a brief summary of how the loop was formed, and how I broke out of it. I grossly simplified the code for the example.

this.htmlBuffer += '<input type="radio" onclick="doStuff();repaintForm();"';
this.htmlBuffer += '/>';
// Some other inputs
someDiv.innerHTML = this.htmlBuffer;

All tested browsers that came before Firefox 3 stopped propagation of the click event. Firefox 3 continued to propagate the click event after the form was repainted, so it effectively added a new event listener with each iteration.

I did some reading on the subject, at whirlpool and eyeOS. I tried various means of stopping the event, including...

e.stopPropagation(); // Mozilla
e.preventDefault();  // Mozilla
e.cancelBubble = true;// IE
e.returnValue = false;// IE

None worked.

The Solution

Adding "return false;" to the XHTML text of the onclick stopped event propagation in Firefox 3. It had no ill effects in Firefox 2, Safari 3, IE7, or IE6.

this.htmlBuffer += '<input type="radio" onclick="doStuff(this);repaintForm();return false;"';
this.htmlBuffer += '/>';
// Some other inputs
someDiv.innerHTML = this.htmlBuffer;

Clearly, a better solution would include use of DOM methods to construct objects, instead of innerHTML. However, this solution fixed the problem in a hurry. If your existing application seems to get caught in an endless loop only in Firefox 3, the "return false" solution may help.

Labels: , ,


Comments: Post a Comment

Links to this post:

Create a Link

Archives

March 2006   May 2006   July 2006   August 2006   January 2007   March 2007   April 2007   August 2007   March 2008   April 2008   August 2008   April 2010   May 2010   July 2010   September 2010   April 2011  

This page is powered by Blogger. Isn't yours?