nextwebgen.com

The Next Generation Web Now

Prototypify: Running Prototype code with legacy code

Filed under: Front Page,JavaScript,Library,Prototype,Web 2.0 News — Dion Almaer at 2:55 pm on Thursday, July 27, 2006

Aaron Newton, Product Manager at CNET sent us an email about his issues of using Prototype in production at a large company like CNET:

I've made a lot of use of Prototype but using it has been a bit of a controversy here at our network. Specifically, the extensions that are inherent in Prototype often create problems for (poorly written) legacy code and advertising javascript that we must include in our environment to make a buck.

Because it's not reasonable for our technical producers to regress every ad that runs on our site, I hired a good friend (and far more talented programmer) to help me find a solution. He, one Alex Cruikshank, authored a chunk of code (2.25K) for us that I think could be of great use to those out there who avoid Prototype because of the way it alters Arrays and Objects; specifically, those trying to use your library in an environment where they do not control 100% of the javascript included.

The code, all 3K of it, is a wrapper of sorts that removes all the extensions to Array and Object from Prototype. Then, when you want to make use of Prototype, you just apply this wrapper to your code.

We have put the code up for Prototypify along with the documentation.

JAVASCRIPT:
  1.  
  2. Prototypify = function() {
  3.  
  4. }
  5.  
  6. Prototypify.prototypified = false;
  7.  
  8. // store then remove functions from prototypes of native objects
  9. Prototypify.arrayFunctionHolder = new Object()
  10. for (x in Array.prototype)
  11. {
  12.   Prototypify.arrayFunctionHolder[x] = Array.prototype[x];
  13.   delete Array.prototype[x];
  14. }
  15.  
  16. Prototypify.stringFunctionHolder = new Object()
  17. for (x in String.prototype)
  18. {
  19.   Prototypify.stringFunctionHolder[x] = String.prototype[x];
  20.   delete String.prototype[x];
  21. }
  22.  
  23. Prototypify.numberFunctionHolder = new Object()
  24. for (x in Number.prototype)
  25. {
  26.   Prototypify.numberFunctionHolder[x] = Number.prototype[x];
  27.   delete Number.prototype[x];
  28. }
  29.  
  30.  
  31. Prototypify.proxy = function( f, proxyArguments )
  32. {
  33.   return function()
  34.     {
  35.       var needsPrototypes = ! Prototypify.prototypified;
  36.       if ( needsPrototypes )
  37.       {
  38.         Prototypify.prototypified = true;
  39.         for (x in Prototypify.arrayFunctionHolder)
  40.           Array.prototype[x] = Prototypify.arrayFunctionHolder[x];
  41.         for (x in Prototypify.stringFunctionHolder)
  42.           String.prototype[x] = Prototypify.stringFunctionHolder[x];
  43.         for (x in Prototypify.numberFunctionHolder)
  44.           Number.prototype[x] = Prototypify.numberFunctionHolder[x];
  45.       }
  46.  
  47.       if ( proxyArguments )
  48.       {
  49.         for ( var i=0; i <arguments.length; i++ )
  50.           if ( typeof arguments[i] == 'function' )
  51.             arguments[i] = Prototypify.proxy( arguments[i], proxyArguments );
  52.       }
  53.  
  54.       var out = f.apply( this, arguments );
  55.  
  56.       if ( needsPrototypes )
  57.       {
  58.         for ( x in Array.prototype )
  59.           delete Array.prototype[x];
  60.         for ( x in String.prototype )
  61.           delete String.prototype[x];
  62.         for ( x in Number.prototype )
  63.           delete Number.prototype[x];
  64.         Prototypify.prototypified = false;
  65.       }
  66.       return out
  67.     }
  68. }
  69.  
  70. Prototypify.instrument = function( clazz, proxyArguments )
  71. {
  72.   for ( prop in clazz.prototype )
  73.   {
  74.     if ( typeof clazz.prototype[prop] == 'function' )
  75.       clazz.prototype[ prop ] = Prototypify.proxy( clazz.prototype[ prop ], proxyArguments );
  76.   }
  77. }
  78.  
  79. Prototypify.instrumentStatic = function( clazz, proxyArguments )
  80. {
  81.   for ( prop in clazz )
  82.   {
  83.     if ( typeof clazz[prop] == 'function' )
  84.       clazz[ prop ] = Prototypify.proxy( clazz[ prop ], proxyArguments );
  85.   }
  86. }
  87.  

Copyright

Copyright (c) 2006 CNET Networks, Inc.

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Pains of document.domain in FireFox 1.5

Filed under: Front Page,JavaScript,Tip,Web 2.0 News — Dion Almaer at 1:55 pm on Thursday, July 27, 2006

Alexander Kirk has written about a problem with XHR, responseXML and document.domain in FireFox:

This will work in IE, Safari, and Opera.
This will not work in Firefox 1.0. This is very awkward but at least it has been fixed in 1.5.
So it will work in Firefox 1.5. But:

The responseXML object is useless. You can’t access it, you receive a Permission Denied when trying to access it’s content (e.g. documentElement). Very annoying.
Even stranger that responseText is still readable. What’s the reason for this? Is there some security risk i am unaware of or is it a plain bug?

As the responseText is available there is a pretty simple fix: re-parse the XML, which is kinda stupid and cpu intense if you have a lot of them. (something like: var doc =
(new DOMParser()).parseFromString(req.responseText, “text/xml”);
)

Javascript Boot Camp Tutorial

Filed under: Conferences,Front Page,JavaScript,Web 2.0 News — Chris Cornutt at 7:59 am on Thursday, July 27, 2006

Whether you’re a “back to basics” kind of person or are just starting out and want to catch up quick on your Javascript skills, you might want to check out this great resource from a talk/tutuorial given by Amy Hoy at this year’s OSCON - a Javascript Boot Camp.

Even though AJAX wouldn’t ever have become so popular if the Javascript world hadn’t suddenly exploded with mature development and testing tools, there’s little information on how to be a really good Javascript programmer. This talk is for everyone who feels their Javascript skills just aren’t up to snuff.

She’s provided all of the materials in the post on her website, including:

  • Downloads - the source code and the slides (PDF)
  • Links to specific libraries mentioned
  • Web site reference links
  • Del.icio.us tagged items for Javascript and this tutorial

Link Thumbnail: Photo Mouse Over

Filed under: Front Page,JavaScript,Library,UI,Web 2.0 News — Dion Almaer at 9:24 am on Tuesday, July 25, 2006

When Ben and I were at an “Under the Radar” O’Reilly event, one of the companies was trying to push a product that allowed you to mouseover a link and see what comes next.

People doubted whether a company could be made around that idea, and now we are seeing more and more ways where developers can add that functionality.

The latest is Link Thumbnail which is:

A little bit JavaScript, a little bit CSS and a little bit clairvoyance, Link Thumbnail shows users that are about to leave your site exactly where they’re going. When that curious mouse pointer hovers over a link pointing to somewhere outside of your site, the script displays a small image of the destination page. It’s a nice visual cue that serves a very real purpose: providing a clearer picture (no pun intended) of what’s ahead.

Link Thumbnail

JavaScript and Mouse Wheels

Filed under: Front Page,JavaScript,Web 2.0 News — Dion Almaer at 9:15 am on Tuesday, July 25, 2006

Adomas Paltanavicius has written about handling mouse wheel events in JavaScript.

JAVASCRIPT:
  1.  
  2. /** This is high-level function; REPLACE IT WITH YOUR CODE.
  3. * It must react to delta being more/less than zero.
  4. */
  5. function handle(delta) {
  6.         if (delta <0)
  7.                 /* something. */;
  8.         else
  9.                 /* something. */;
  10. }
  11.  
  12. function wheel(event){
  13.         var delta = 0;
  14.         if (!event) event = window.event;
  15.         if (event.wheelDelta) {
  16.                 delta = event.wheelDelta/120;
  17.                 if (window.opera) delta = -delta;
  18.         } else if (event.detail) {
  19.                 delta = -event.detail/3;
  20.         }
  21.         if (delta)
  22.                 handle(delta);
  23. }
  24.  
  25. /* Initialization code. */
  26. if (window.addEventListener)
  27.         window.addEventListener('DOMMouseScroll', wheel, false);
  28. window.onmousewheel = document.onmousewheel = wheel;
  29.  

Of course, the real question is when would you want to actually use this. We are trained to know that the mouse wheel scrolls the page up and down in the browser (or whatever you have it set to).

We need a good reason to intercept the events and do something else.

Breaking User Interfaces for Fun and Profit

Filed under: Front Page,JavaScript,UI,Usability,Web 2.0 News — Chris Cornutt at 7:26 am on Tuesday, July 25, 2006

For all of the good uses of Ajax out there, there are still some really really (*really*) bad ones that come to mind. Unfortunately, some site developers just don’t quite know when to stop, and this post on SitePoint.com today (by Alex Walker) points out just such a perpetrator - Art.com.

Art.com is a large, commerical art site selling prints to the public—over 300,000 of them, framed, mounted or otherwise. Their display pages are a model of efficient elegance—not dissimilar in style to Flickr in some ways—generally letting the artwork speak for itself.

But apparently, there wasn’t enough ‘wow-factor’. “We’re paying these developers—get them to come up with something that’s cool or hot or sick or whatever it is the kids want to be these days”.

So, what exactly is it that makes their implementation a pain? Try something out - go to this page and try to use the drop-down list. Fun, huh? It’s a good idea to break a web standard and use a custom solution when all someone wants is a simple option. Plus, the grow effect causes some distortion in Firefox (and other issues, try dragging the window too. and don’t get me started on what happens if Javascript is disabled) .

Okay, so we can all agree that Ajax is cool, and yes, there are some cool user interface additions that can be made with its help, but if you make a drop-down box, make it work like a drop-down box. Web users look for interface items they know and like to use them - don’t mess with that.

XN Test: The next Unit Testing project?

Filed under: Front Page,JavaScript,Library,Utility,Web 2.0 News — Dion Almaer at 9:47 am on Monday, July 24, 2006

Brian McCallister is up to his usual tricks. This time he didn't like JsUnit for a certain use case, so he created the embryo for a new test framework in JavaScript: For now let's call it XN.

With it you can end up with a test API such as:

JAVASCRIPT:
  1.  
  2.   s.test("Asynch test which succeeds", function(t) {           
  3.     t.async();
  4.    
  5.     dojo.io.bind({
  6.       url: "/Give-Me-A-404", // 404
  7.       error: function(type, thing) {
  8.         t.succeed();
  9.       }
  10.     });
  11.    
  12.   });
  13.  
  14.   s.test("Async test which should fail", function(t) {           
  15.     t,async();
  16.    
  17.     dojo.io.bind({
  18.       url: "/Give-Me-A-404", // 404
  19.       error: function(type, thing) {
  20.         t.fail("Failure is on purpose");
  21.       }
  22.     });
  23.    
  24.   });
  25.  

A lot of where the design veers from standard XUnit form it is to accommodate JavaScript idiosyncrasies. For instance, if we look at the test() function we see a variable being passed in! This variable is the instance of the test case, which is also, as it so happens, the value of this in the test function.

JavaScript's scoping bizarrity makes it much more practical to pass the test case in as an argument, that way you don't have to capture the correct value of this, or pass around this as a context to other calls when using anonymous functions. Handy. The same thing applies to suite.

Defining it as a Dojo module is also handy, it makes building a real suite pretty easy, you just require each of the "suites" -- which is why I think I'll rename it to group or even testCase, but I hate the camel casing, so will think a bit :-)

Reporting success and failure is easy to override, the default just creates a definition list and plugs results in, like so. Not pretty, but easy to make pretty as time goes on.

The API exploration test cases are all online, but not especially polished. We'll see where this goes. I kind of like the feel of how it is coming together. A couple things I definitely need to do though are changing failure to raise an exception rather than allow the rest of the test to continue, which will make stack trace generation for tracking down failures more useful; and add some more assertion helper functions (oh, and add the one-argument form, always including an explanation is annoying once you have stack traces to see where it came from).

It is very cool that it plugs right into Dojo and could be a nice dojo.xn library for us to use. Obviously, it is early days, but thanks for the ride Brian and keep it up!

CSS Browser Selector

Filed under: Front Page,JavaScript,Library,Web 2.0 News — Dion Almaer at 3:13 pm on Friday, July 21, 2006

Rafael Lima took inspiration from 37 Signals browser selector idea and created it. "It" being a JS library that allows you to create browser specific CSS to be merged into your normal classes.

Example

You can prefix browser specific elements (available codes: ie, gecko, opera, konqueror, safari) and the library will make sure that the correct items are added in for a particular browser.

This can be considered cleaner than some of the really ugly hacks that you normally face.

HTML:
  1.  
  2. <style type="text/css">
  3. .ie .example {
  4.   background-color: yellow
  5. }
  6. .gecko .example {
  7.   background-color: gray
  8. }
  9. .opera .example {
  10.   background-color: green
  11. }
  12. .konqueror .example {
  13.   background-color: blue
  14. }
  15. .safari .example {
  16.   background-color: black
  17. }
  18. .example {
  19.   width: 100px;
  20.   height: 100px;
  21. }
  22. </style>
  23.  

CSS Browser Selector

Next Page »