nextwebgen.com

The Next Generation Web Now

Prototypify: Running Prototype code with legacy code

Filed under: Web 2.0 News, Front Page, JavaScript, Library, Prototype — 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.

Link Thumbnail: Photo Mouse Over

Filed under: Web 2.0 News, Front Page, JavaScript, Library, UI — 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

XN Test: The next Unit Testing project?

Filed under: Web 2.0 News, Front Page, JavaScript, Library, Utility — 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!

JSSoundKit: Super-Easy Sound API

Filed under: Web 2.0 News, Front Page, Library, Flash — Michael Mahemoff at 5:14 am on Saturday, July 22, 2006

JSSoundKit is wraps the Flash Sound object, making it easy to incorporate sound into your Ajax apps. Really easy, in fact:

JAVASCRIPT:
  1.  
  2. var mysound = new Sound();
  3. mysound.loadSound("http://www.archive.org/download/Behind/SyncFilmicoBehind.mp3", true);
  4. mysound.setVolume(30);
  5.  

Sound is a great example of using Flash to achieve progressive enhancement - enhance the expertience in those browsers that support the functionality and degrade gracefully for those that don't ... sound is often a nice-to-have rather than a necessity (unless you're building an MP3 player of course!).

We've seen a number of comms libraries that wrap Flash in similar vein, for comms, local storage, etc. As most web developers remain Flash-illiterate, it's great to see these capabilities unlocked for the masses. If we want, we can build standard web UIs, and pull in Flash for specialized, typically non-presentational, functionality.

CSS Browser Selector

Filed under: Web 2.0 News, Front Page, JavaScript, Library — 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

Asteroid: Seaside Comet Implementation

Filed under: Web 2.0 News, Front Page, Library, Comet — Dion Almaer at 9:46 am on Friday, July 21, 2006

Diego Gomez Deck has written an Comet implementation in Seaside (Smalltalk continuations based web framework) called Asteroid.

Features

  • JSON-rpc implementation
  • disconnection handled in browsers
    • manual reconnection
    • automatic reconnection working in IE
  • visual feedback (using script.aculo.us)
    • rpc
    • connection/disconnection
    • events reception

View a demo

Json.NET 1.1: Converting between XML and JSON

Filed under: Web 2.0 News, Front Page, JavaScript, Library — Dion Almaer at 8:21 am on Tuesday, July 18, 2006

James Newton-King has updated his Json.NET library to version 1.1.

The major new feature is that you can now almost seamlessly convert between XML and JSON:

XmlDocument doc = new XmlDocument();
doc.LoadXml(@"<?xml version=""1.0"" standalone=""no""?>
<root>
  <person id="
"1"">
    <name>Alan</name>
    <url>http://www.google.com</url>
  </person>
  <person id="
"2"">
    <name>Louis</name>
    <url>http://www.yahoo.com</url>
  </person>
</root>"
);
 
string jsonText = JavaScriptConvert.SerializeXmlNode(doc);
//{
//  "?xml": {
//    "@version": "1.0",
//    "@standalone": "no"
//  },
//  "root": {
//    "person": [
//      {
//        "@id": "1",
//        "name": "Alan",
//        "url": "http://www.google.com"
//      },
//      {
//        "@id": "2",
//        "name": "Louis",
//        "url": "http://www.yahoo.com"
//      }
//    ]
//  }
//}
 
XmlDocument newDoc = (XmlDocument)JavaScriptConvert.DeerializeXmlNode(jsonText);
 
Assert.AreEqual(doc.InnerXml, newDoc.InnerXml);
 

Adobe Spry and PHP/MySQL

Filed under: Web 2.0 News, Front Page, JavaScript, Library, Articles — Dion Almaer at 8:20 am on Wednesday, July 12, 2006

Mike Kornienko took Adobe's Spry Framework for a spin.

He has written up his thoughts on integrating it with a PHP/MySQL backend:

Spry is Adobe's Ajax library for manipulating XML data. It has some very unique and pretty useful functions like regions handling, related auto-updating data and stuff like that. For example, you can load XML file into your HTML document, created a template-like markup for with some spry: tags in it, and Spry will do the rest - will read the XML file and output it into your web-page in the format you have defined. Not only that. You can have several connected data sets so that when you select a row in the main table generated by Spry, and if you have a region on your web-page which is somehow depends on selected row in main table, this region will be updated automatically.

The article shows the XML that you give to Spry, the libraries involved, and the HTML components:

<input type="button" value="sort id" onclick="dsTest.sort('id','toggle')""/>
<input type="button" value="sort title" onclick="dsTest.sort('title','toggle')""/>

<input type="button" value="sort content" onclick="dsTest.sort('content','toggle')""/>

<div spry:region="dsTest">
<table border="1">
<tr spry:repeat="dsTest">
<td>{@id}</td>
<td>{name}</td>
<td>{place}</td>
</tr>
</table>
</div>
 

Next Page »