You searched for: 'native'

Thursday, August 19th, 2010

Will Native Mobile Applications Wither Away?

Category: Mobile


James Pearce has started a fascinating series, called WhitherApps.com, trying to rewrite the BBC iPhone application and other native mobile apps using HTML5. From the kickoff blog post:

WhitherApps is a bandwagon-busting experiment. I believe there are far too many native client apps which could have been far better written as mobile web apps. What we’re going to try and do is take a few examples, apply a little reverse-engineering, and rewrite them, warts and all, with web technologies.

James has already produced three blog posts rewriting the BBC iPhone app but with HTML5 (Part I, Part II, Part III). I encourage you to read them. He’s already gotten impressively far; here is a screenshot of the HTML5 app so far:

[via kenguish]

Posted by Brad Neuberg at 5:00 am
17 Comments

+++--
3 rating from 3 votes

Tuesday, July 13th, 2010

An alternative way to addEventListener

Category: Examples, JavaScript, Standards, W3C

I can’t believe none of us knew DOM2

This is how a tweet from @SubtleGradient, re-tweeted by @jdalton, has been able to steal my rest tonight … and this post is the consequence …

What’s new in a nutshell

There is a W3C Recommendation about addEventListener behavior, which clearly specify the second argument as an EventListener.
The new part is that no library I know has ever used a proper EventListener interface, preferring the classic attached callback instead.

javascript
< view plain text >
  1. // this is how it is
  2. document.addEventListener(
  3.     "click",
  4.     function (evt) { /* stuff */ },
  5.     false
  6. );
  7.  
  8. // this is how it could be as well
  9. var listener = {
  10.     handleEvent: function (evt) {
  11.  
  12.         this === listener; // true
  13.  
  14.         // and evt === classic event object
  15.  
  16.     }
  17. };
  18.  
  19. document.addEventListener("click", listener, false);

Benefits

The most common case that may disappear is well explained in this MDC addEventListener page.
Rather than bind inline or add anonymous functions to make our object call context preserved, we can simply add an handleEvent method to whatever object and pass it as EventListener.
Moreover, being close to full ES5 support and “use strict” directive where arguments.callee disappears, it may be more than handy to be able to perform such operation:

javascript
< view plain text >
  1. document.addEventListener("click", {
  2.     handleEvent: function (evt) {
  3.         // 1 shot callback event example
  4.         switch (evt.target.nodeType) {
  5.             case 1:
  6.             case 9:
  7.                 evt.target.removeEventListener(
  8.                     evt.type,
  9.                     this, // here we are!
  10.                     false
  11.                 );
  12.                 break;
  13.         }
  14.     }
  15. }, false);

An opened door for custom listeners

As I have recently posted, custom listeners implementation can be truly handy when we are dealing with events driven applications, but as soon as I have read the tweet, I had to rewrite a fresh new way to create a listener. Please note that following code is assuming that the browser supports both DOM Level 2 and Array extras, which is true for all modern browsers, mobile oriented included.

javascript
< view plain text >
  1. function createEventListener() {
  2.  
  3.     /*! Andrea Giammarchi for Ajaxian - Mit Style */
  4.  
  5.     // a function declaration reused internally
  6.     function notifyEvent(callback, i, stack) {
  7.         // use DOM Level 0 events strategy
  8.         //  to stop the loop if necessary
  9.         // checking if the result is exactly false
  10.         if (callback.call(
  11.             // the curent object as context
  12.             this,
  13.             // the classic event as first argument
  14.             event,
  15.             // the called callback (life easier)
  16.             callback,
  17.             // again the current context
  18.             // if the callback has been bound
  19.             this
  20.         ) === false) {
  21.             // if false, reassign the current stack ...
  22.             eventListener["@"+event.type] = stack.slice();
  23.             // ... and break the current forEach loop
  24.             // (or, for the record, whatever Array.extras)
  25.             stack.length = 0;
  26.         }
  27.     }
  28.  
  29.     var
  30.         // local scoped object, reachable internally
  31.         // usable as mixin so instances won't be polluted
  32.         // with all possible event types
  33.         // the type is prefixed in any case
  34.         // so that name clashes should be
  35.         // really rare however we use the object
  36.         eventListener = {
  37.  
  38.             // we attach to a proper stack
  39.             addEvent: function (type, callback) {
  40.                 var
  41.                     // try to retrieve the stack ...
  42.                     stack = (
  43.                         // if already there ...
  44.                         eventListener["@" + type] ||
  45.                         // otherwise we create it once
  46.                         (eventListener["@" + type] = [])
  47.                     ),
  48.                     // as addEventListener, don't attach
  49.                     // the same event twice
  50.                     i = stack.indexOf(callback)
  51.                 ;
  52.                 // so if it was not there ...
  53.                 if (-1 === i) {
  54.                     // FIFO order via stack
  55.                     stack.push(callback);
  56.                 }
  57.             },
  58.  
  59.             // called via addEventListener
  60.             // the "this" reference will be
  61.             // the eventListener object,
  62.             // or the current instance
  63.             // if used as "class" mixin
  64.             // or via Object.create / clone / merge
  65.             handleEvent: function (e) {
  66.                 // retrieve the stack
  67.                 var stack = eventListener["@" + e.type];
  68.                 // and if present ...
  69.                 if (stack) {
  70.                     // set temporarily the local event var
  71.                     event = e;
  72.                     // notify all registered callbacks
  73.                     // using current this reference
  74.                     // as forEach context
  75.                     stack.forEach(notifyEvent, this);
  76.                     // let the GC handle the memory later
  77.                     event = null;
  78.                 }
  79.             },
  80.  
  81.             // how we remove the event, if any ...
  82.             removeEvent: function (type, callback) {
  83.                 var
  84.                     // try to retrieve the stack ...
  85.                     stack = eventListener["@" + type],
  86.                     // find the index ...
  87.                     i
  88.                 ;
  89.                 // if the stack is present
  90.                 if (stack && ~(
  91.                     i = stack.indexOf(callback)
  92.                 )) {
  93.                     // remove it
  94.                     stack.splice(i, 1);
  95.                 }
  96.             }
  97.         },
  98.  
  99.         // I could have called this variable tmp
  100.         // but it's actually the current event
  101.         // once assigned ... so ...
  102.         event
  103.     ;
  104.  
  105.     // ready to go!
  106.     return eventListener;
  107.  
  108. }

Here a usage example:

javascript
< view plain text >
  1. var lst = createEventListener();
  2.  
  3. /** mixin example (add a slash before this line to test)
  4.  
  5. function MyEventListener() {}
  6. MyEventListener.prototype.addEvent = lst.addEvent;
  7. MyEventListener.prototype.handleEvent = lst.handleEvent;
  8. MyEventListener.prototype.removeEvent = lst.removeEvent;
  9.  
  10. lst = new MyEventListener;
  11.  
  12. // */
  13.  
  14. document.addEventListener("click", lst, false);
  15.  
  16. lst.addEvent("click", function click(e, callback, object){
  17.  
  18.     alert([
  19.         callback === click, // true
  20.         this === lst,       // true
  21.         this === object,    // true
  22.         e.type === "click"  // true
  23.     ]);
  24.  
  25.     // test that furthermore this
  26.     // callback won't be fired again
  27.     this.removeEvent("click", callback);
  28.  
  29.     // add delayed a callback
  30.     // without any valid reason :-)
  31.     setTimeout(function (self) {
  32.         // test addEvent again
  33.         self.addEvent("click", function () {
  34.             alert(2);
  35.         });
  36.     }, 0, this);
  37.  
  38.     // block the current notification
  39.     return false;
  40. });
  41.  
  42. // the event fired only the second click
  43. lst.addEvent("click", function () {
  44.     alert(1);
  45. });
  46.  
  47. /** de-comment the mixin example to test
  48. //   that no @click is attached ;-)
  49. for (var key in lst) {
  50.     alert(key);
  51. }
  52. // */

Advantages

  • both evt.stopPropagation() and evt.preventDefault() are not able to break the current notification of all attached listeners, if added to the same node, and while the FIFO order gives to the node “owner” or creator the ability to pollute the event object with some flag such evt.pleaseDontDoAnyOtherActionHere = true, not every library, script, or framework, may respect or understand this flag. With custom events we can adopt better strategies to actually avoid any other operation if this is what we meant, because we arrived before over the node and we may like to be that privileged
  • being custom, we can also decide which argument should be passed for each callback, simplifying most common problems we may have when dealing with listeners
  • we can better decouple DOM and listeners, being able to remove whatever amount of callbacks simply calling once node.removeEventListener(evt.type, this, false); inside any kind of notification
  • being based on standard and modern browsers, we can use native power, in this case provided by forEach and indexOf operations, so that performances will be best possible
  • thanks to automatic context injection, we can still reuse callbacks for different listeners, through bind, or simply considering the current context once called (or in this case the third argument by reference, if the context is different)

Last but not least, if we would like to fire an event we can bypass DOM initialization using handleEvent directly, e.g.

javascript
< view plain text >
  1. lst.handleEvent({
  2.     target: document.querySelector("#myid"),
  3.     type: "click",
  4.  
  5.     // custom properties
  6.     pageX: 0,
  7.     pageY: 0,
  8.  
  9.     // stubbed methods
  10.     preventDefault: function () {},
  11.     stopPropagation: function () {}
  12. });

Compatibility ?

Apparently both W3C behavior and provided examples are compatible with every modern browser with DOM Level 2 support, and I believe this is great.
The only one behind here is IE9 pre 3, but again @jdalton has acted at speed light, thanks!

Posted by webreflection at 8:00 am
11 Comments

++++-
4 rating from 10 votes

Thursday, June 17th, 2010

Sencha Touch: The end of native; A new touch framework for the Web

Category: JavaScript, Library, Mobile, Sencha

As I walked around Moscone last week, I saw some prophets speaking of a future that isn’t all Native. A future where the Web is the platform. Others saw it too:

I pondered who would be behind the act and smiled as I had a good idea. The group behind this all is the newly named Sencha (formerly Ext JS). On the back of news of the new company and Sencha Labs, we get a glimpse of their new product: Sencha Touch:

Sencha Touch allows your web apps to look and feel like native apps. Beautiful user interface components and rich data management, all powered by the latest HTML5 and CSS3 web standards and ready for Android and Apple iOS devices. Keep them web-based or wrap them for distribution on mobile app stores.

There are some good demos of apps such as GeoCongress, which shows off:

  • HTML5 Geolocation
  • Sench Touch icon set
  • JSONP Proxy
  • YQL Data Proxy
  • Momentum scrolling
  • Scroll touch event
  • Pop-up Overlays
  • Mobile form elements
  • CSS3 Gradients
  • CSS3 Transitions
  • Multi-Card Layout
  • Tab Panel Component
  • Scrollable list view
  • Swappable headers

Once you see what the framework can do with examples, what better way to get a deeper look than walking though as much of it as possible? Michael Mullany, VP Products, sat down and gave us just that. Sencha Touch comes with a “kitchen sink” demo that shows off much of its abilities. Here we see Michael showing off said demo:

After seeing this at work, we asked Michael some questions about the new product:

How are Ext JS, jQTouch, and Sencha Touch related?

We talked about some of this in the Sencha name change post. Jonathan Stark is taking over jQTouch maintainership, Dave Kaneda will remain involved but he’s been spending most of his energy on Sencha Touch. Sencha Touch has some Ext JS DNA (OO javascript, a lot of the data package is common), but the UI components are completely different.

Having David part of Sencha Touch has been incredibly important. That’s one of the reasons why the UI components are staggeringly beautiful, and there’s been so much attention to ease of styling.

With respect to jQTouch vs. Sencha Touch. jQTouch is a good solution for people who need some progressive enhancement of web content, but it’s not a full application framework.

What is the licensing plan for Sencha Touch?

The initial beta is under a GPLv3 + FLOSS license. We’d like to give open source folks the benefit before we introduce a commercial trial license. And we’d like to take the opportunity to emphasize something that many people miss: that we have Free and Open Source exceptions as part of our GPLv3 license. So if you want to, you can include Sencha Touch in your Apache and OSI approved licensed projects without triggering the GPL’ing of your project.

Can I make native looking controls for the particular platform at runtime?

In the beta, you can build multiple themes easily (for example, our Android theme is 20 lines of customized SASS), and serve them up to different clients based on user agent. We do want to provide a client-side switcher by release time. SASS is really an extraordinary technology. This would be far, far harder without it.

Are there any differences between it running on various platforms?

There are some minor differences, for example CSS 3D Transitions don’t work on Android, for example (no cube transitions). And Apple GPU accelerates more stuff. You can look at our demo apps across iPhone and Android. They really do work cross-platform.

How do I do layout with Sencha Touch?

We think most people will use fairly simple layouts with the built-in components since the screen sizes are small. Tabs, carousels, lists. If they want to get more complex, they can use the more complex layouts or just extend the built-in classes.

Can I create native apps from these? How do I access native services on the device?

Right now, you’re going to take Sencha and wrap it with phone-gap. But about two third of non-game apps don’t do any special device access, and camera access is on its way.

How does Sencha Touch feel to program (e.g. just like Ext?)

It’s still object oriented javascript but it’s really very simple. People can just look at the source to the demo apps (which are reasonably rich apps) and make their own decision.

Can I progressively enhance a mobile Web app and sprinkle in some of this goodness?

I think the success of iPhone native mobile apps shows that for mobile factors, it’s better if you think about layout and navigation first, then pour content into your containers & paths. In many ways, I think it’s the reverse of the desktop web. Desktop web apps can be random access in their user pathing, mobile apps have to be hierarchical or otherwise constrained — because you don’t have a lot of space and you can’t waste it on navigation controls.

Posted by Dion Almaer at 8:00 am
21 Comments

++---
2.8 rating from 6 votes

Wednesday, May 12th, 2010

Native Client now comes with an actual SDK

Category: Google

A year after the initial Native Client release we have a more polished Native Client SDK for developers.

The Native Client SDK preview, in contrast, includes just the basics you need to get started writing an app in minutes: a GCC-based compiler for creating x86-32 or x86-64 binaries from C or C++ source code, ports of popular open source projects like zlib, Lua, and libjpeg, and a few samples that will help you get you started developing with the NPAPI Pepper Extensions. Taken together, the SDK lets you write C/C++ code that works seamlessly in Chromium and gives you access to powerful APIs to build your web app.

Salt and Pepper indeed. A friend at a browser vendor was looking into Pepper and thought that the specs were definitely….. thorough shall we say? Take Pepper Audio by itself. A bit of a beast! :)

It is interesting to watch Google give C/C++ developers (and legacy code) a different path to the Web (beyond NPAPI and… ActiveX!). You can imagine this being increasingly important when you think about Chrome OS.

Ideally, the Web platform itself evolves fast enough that this project is always an onramp for legacy code…. what do you think?

@hbridge has an interesting view:

Pepper is very much a work in progress and we expect it to change — that’s why this is a preview! Feedback welcome :)

ActiveX was designed to provide unrestricted access to native APIs so it wound up being a security nightmare.

NaCl is designed to give access to native code performance, but only to APIs similar to what JS offers, so security model is same.

Posted by Dion Almaer at 1:12 pm
3 Comments

++---
2 rating from 2 votes

Tuesday, May 11th, 2010

Firefox 4: HTML5 and Native JSON Store

Category: Browsers, Firefox

Mike Beltzner, Director of Firefox and all-round top chap, gave an open presentation on what is coming in Firefox 4:

The full video is also available which goes into detail on the main themes of the next release of Firefox (3.7 is dead, long live 4!)

  • Fast: making Firefox super-duper fast
  • Powerful: enabling new open, standard Web technologies (HTML5 and beyond!),
  • Empowering: putting users in full control of their browser, data, and Web experience.

What do developers get?

  • Bidirectionally connected apps (Web Sockets)
  • Better Ajax-y interactions (PushState)
  • New interactions (gesture + multi-touch)
  • Easier layout and styling (CSS3)
  • HTML5 Parser
  • Content creation (contentEditable, HTML5 forms)
  • Structured data storage (IndexedDB)

You would have guessed at most of these, but maybe not the WebSimpleDB/IndexedDB one. If a project has “simple” in the name, it normally isn’t…. just like when a project has “open” in the name. It is a strange name since we have simple storage through localStorage and friends.

IndexedDB is a better name, and it is interesting stuff. Instead of the SQL databases that require standardizing on a version of SQLite (which is insane) it is JSON native. You work with the data store like this:

and you can go native JSON with the object store:

Take a look at all of the low level cursor code and you may cry a little :)

Back to Firefox 4. The media loves a binary black vs. white view of the world. Flash is Dead. HTML5 is saviour. Chrome is “the winner”. IE is over. Regardless of any actual numbers.

Alpha geeks are big on Chrome these days, but Firefox has massive numbers and is still doing well, despite the fact that, in my opinion, better days are to come. Firefox will catch up on the technology side with multi-process and their new JagerMonkey VM work. Performance will become table stakes yet commodity. Where Firefox can shine is where no other browser will go. Mozilla is mission based and cares about users in a more holistic way. This is the empower goal. You should own your data. Your browser should do more for you (not just get out of the way). Firefox is uniquely positioned for this, and you can see the start of the work via the Contacts work from Mike Hansen.

Also note how the team is discussing Firefox 4. Totally in the open. What will Safari 5 have? Chrome 6 has platform status, IE9 is doing a better job…. but no one does it as well as Mozilla IMO.

I look forward to the continued browser competition. Great news for us developers!

Posted by Dion Almaer at 10:06 am
16 Comments

++---
2.7 rating from 3 votes

Monday, May 10th, 2010

Apple isn’t developing a Flash alternative named Gianduia

Category: Apple

Apple Insider has a strong headline: Apple developing Flash alternative named Gianduia that gets you clicking.

You quickly learn that Gianduia is:

  1. Not like Flash at all (e.g. not a plugin that brings a new development model to a rectangle in a browser)
  2. Old news (shown “last summer at WOWODC (World of WebObjects Developer Conference)”)
  3. a JavaScript framework.

It is allegedly the framework behind Apple projects such as their Concierge:

They say more:

Gianduia, named after an Italian hazelnut chocolate, is “essentially is browser-side Cocoa (including CoreData) + WebObjects, written in JavaScript by non-js-haters,” according to a tweet by developer Jonathan “Wolf” Rentzsch. “Jaw dropped.”

After watching the NDA demo Apple gave for the new framework at WOWODC last year, Rentzch also tweeted, “Blown away by Gianduia. Cappuccino, SproutCore and JavascriptMVC have serious competition. Serious.”

Like Cappuccino, Gianduia takes a Cocoa-inspired name (Cocoa is itself a Java-inspired name) to describe its role as a way for Cocoa developers to bring their skills to rich online applications built using web standards, with no need for a proprietary web plugin like Flash or Silverlight.

Apple is large, and has a lot of web presences. We have seen them use various open source outside frameworks, as well as ones they work on (SproutCore, Coherent in the past, etc) and we also hear about PastryKit and that other one for the iPad. A lot of developers. A lot of different code.

I very much hope we get the opportunity to see Gianduia in the future, as well as more of PastryKit and other frameworks that they use. Apple does a fantastic job with UX, and if they have amazing tools for building rich HTML5 applications, I am sure we are all ears.

Posted by Dion Almaer at 6:22 am
3 Comments

++---
2.3 rating from 3 votes

Tuesday, March 23rd, 2010

A Google-y Post: ANGLE, Native Client and Skipfish

Category: Google

It was a busy day for Google news for web developers, in very different areas.

ANGLE

This is exciting. On the Chromium blog Henry Bridge announced a new open source project called ANGLE which is implementing OpenGL ES 2.0 on top of Microsoft Direct3D APIs for Windows folk. This is a big deal as you can’t assume good OpenGL drivers on Windows… but with ANGLE live could be better.

Why is this related to Chromium? WebGL:

We’re open-sourcing ANGLE under the BSD license as an early work-in-progress, but when complete, it will enable browsers like Google Chrome to run WebGL content on Windows computers without having to rely on OpenGL drivers.

Current browser implementations of WebGL need to be able to issue graphics commands to desktop OpenGL to render content. This requirement isn’t a problem on computers running OS X or Linux, where OpenGL is the primary 3D API and therefore enjoys solid support. On Windows, however, most graphics-intensive apps use Microsoft Direct3D APIs instead of OpenGL, so OpenGL drivers are not always available. Unfortunately, this situation means that even if they have powerful graphics hardware, many Windows machines can’t render WebGL content because they don’t have the necessary OpenGL drivers installed. ANGLE will allow Windows users to run WebGL content without having to find and install new drivers for their system.

Because ANGLE aims to implement most of the OpenGL ES 2.0 API, the project may also be useful for developers who are working on applications for mobile and embedded devices. ANGLE should make it simpler to prototype these applications on Windows, and also gives developers new options for deploying production versions of their code to the desktop.

Check out the source.

Native Client is ARM’d

NaCl allows you to gcc some code and have it run in a browser. Wooah :) The big news from that camp is new support for ARM which means NaCl for mobile….. and Chrome OS:

When we first released Native Client a year ago, we supported all popular operating systems (Windows, Mac OS X, and Linux) but only on machines with x86 processors. Today, we’re happy to say that you can build and run Native Client binaries for all of the most popular processor architectures: x86-32, x86-64, and ARM. Even better, our initial benchmarks indicate that Native Client executables perform at 97% of the speed of an unmodified executable on both ARM and x86-64 processors. These results indicate that a browser running on virtually any modern computer or cell phone could run a fast, performance-sensitive Native Client application.

However, we recognize that just running on today’s most popular architectures isn’t enough; if a new processor architecture emerges, it should be able to run all Native Client modules already released without requiring developers to recompile their code. That’s why we’re also developing technology that will enable developers to distribute a portable representation of Native Client programs using LLVM bitcode. Using this technology, a browser running on any type of processor could translate the portable representation into a native binary without access to the source code of the program.

Skipfish

For the security concerned …. how about running Skipfish “a fully automated, active web application security reconnaissance tool.”:

  • High speed: pure C code, highly optimized HTTP handling, minimal CPU footprint – easily achieving 2000 requests per second with responsive targets.
  • Ease of use: heuristics to support a variety of quirky web frameworks and mixed-technology sites, with automatic learning capabilities, on-the-fly wordlist creation, and form autocompletion.
  • Cutting-edge security logic: high quality, low false positive, differential security checks, capable of spotting a range of subtle flaws, including blind injection vectors.

Some cool news all around…. all Web… and all open source.

Posted by Dion Almaer at 6:54 am
2 Comments

+++--
3.8 rating from 19 votes

Friday, January 22nd, 2010

De-fusing JavaScript Natives with the Fusebox

Category: JavaScript, Library

John-David Dalton has released Fusebox, a library that allows you to sandbox natives:

Extending JavaScript natives gives you the power to customize the language to fit your needs. You can add convenience methods like “hello world”.capitalize() or implement missing functionality like [1,2,3].indexOf(2) in JScript. The problem is that frameworks / libraries / third-party scripts may overwrite native methods or each other’s custom methods resulting in unpredictable outcomes. Fusebox, a limited version of the sandboxing component found in FuseJS, avoids these issues by creating sandboxed natives which can be extended without affecting the document natives.

For example:

javascript
< view plain text >
  1. var fb = Fusebox();
  2.   fb.Array.prototype.hai = function() {
  3.     return "Oh hai, we have " + this.length + " items.";
  4.   };
  5.  
  6.   fb.Array(1,2,3).hai(); // "Oh hai, we have 3 items."
  7.   typeof window.Array.prototype.hai; // undefined

John has a series of short screencasts to introduce the topic of sandboxed natives, how to use them, and the techniques used to make it all happen:

  1. Sandboxed Natives 101: Screencast One
  2. How to create a sandbox: Screencast Two
  3. How to create a Fusebox: Screencast Three
  4. The Final Countdown: Screencast Four

Great to learn from. It is a shame that you have to remember to use a very different way to access the types of course and that you have to do all of this magic…. but with JavaScript, it is what it is!

Posted by Dion Almaer at 2:17 am
12 Comments

++++-
4.2 rating from 32 votes

Friday, August 28th, 2009

Creating a querySelector for IE that runs at “native speed”

Category: Browsers, CSS

Hello Ajaxians, my name is Paul Young and I am the co-founder of Skybound Software. We’re the company behind Stylizer, which is a real-time CSS editing tool. We’re taking a pretty radical approach to CSS editing, and as such, a lot of what I do is “web technology research”, which is looking for better ways of doing things with a web browser, ultimately so that Stylizer can automate more of the web development process. This has allowed me the chance to discover a few things that have had significant impact on a web developer’s workflow, as was the case with State Scope Image Replacement.

In conducting some research for a future version of Stylizer I found a way to create a querySelector method for IE 7 and lower. querySelector is a very useful feature of newer web browsers. It takes a CSS selector as string parameter and returns an array containing the HTML elements that match the selector. Unfortunately it doesn’t work in IE 7 and lower… until now :)

My querySelector technique works in IE7 back to IE4 (although I only tested it back to version 6). It’s only 327 characters minified, and runs ultra-fast because it doesn’t parse strings or traverse the DOM. Keep in mind though that it’s using the CSS selector engine built into the browser, which means no funky CSS 3 selector features will work, as they weren’t implemented old versions of IE.

In order to explain how it works, I’ll need to first cover something else I discovered: Single Execution CSS Expressions (SECEs). These are an enormously powerful technique that unfortunately has been made impossible in IE8. We’re using these extensively in the built-in CSS reset feature in Stylizer to eradicate bugs and to add critical but missing features in IE 6 and 7.

About CSS Expressions

The problem with IE’s CSS expressions feature is that because they’re recalculated hundreds of times per second, they’re notoriously slow. Fortunately, I’ve found a way to ensure they’re only executed once per matched element. Examine the code below:

  1. DIV { -singlex: expression(this.singlex ? 0 : (function(t) { alert(t.tagName); t.singlex = 0; } )(this)); }

There are 3 things you need to know to understand how this works:

  • CSS expressions are executed regardless of whether the CSS property name is valid. So “-singlex” is just an arbitrary name.
  • CSS expressions are executed on every matched element. So in the case above, on every div on the page.
  • Inside a CSS expression, the “this” keyword refers to the current matched HTML element.
  • The code above checks to see if the matched element has a property called “singlex”. If it does, it just returns 0. Otherwise, it executes an inline function, passing it a reference to the matched element. Inside that function, we can perform whatever processing we want. At the end, we set a flag on the element to ensure that the function won’t be executed again.

This is how you can do complex processing inside a CSS expression without having to worry about a performance hit. The function only executes on the first execution of the expression, and then on every subsequent execution, 0 is returned instantly. The performance cost of running an if test and returning 0 is negligible, even if you’re doing it thousands of times per second. If you paste that CSS into a page with 3 div elements on it, in IE it will alert “DIV” 3 times.

The things you can do with SECE’s are basically limited only by your imagination. Here is an example of using one to fake the CSS content property in IE 7 and lower:

  1. /* Newer browsers */ DIV:after { content: "Generated content!"; } /* IE 7 and lower */ DIV { -singlex: expression(this.singlex ? 0 : (function(t) { t.innerHTML += "Generated content!"; this.singlex = 0; } )(this)); }

You can use SECEs to fake all sorts of things like generated content, min-width and min-height, CSS counters, CSS outlines, and more. But most importantly, you can…

Create a querySelector method with Single Execution CSS Expressions!

Creating a querySelector method is just a matter of dynamically adding a SECE to a page that copies a reference to each matched HTML element into a globally accessible array, and then returning that array. Examine the code below:

javascript
< view plain text >
  1. /*@cc_on if (!document.querySelector) document.querySelector = function(selector) { // Add a new style sheet to the page var head = document.documentElement.firstChild; var styleTag = document.createElement("STYLE"); head.appendChild(styleTag); // Create a globally accessible element array document.__qsResult = []; // Create the SECE that copies all matched // elements to document.__qsResult. styleTag.styleSheet.cssText = selector + "{qs: expression(this.__qs?0:(function(t){document.__qsResult.push(t);t.__qs=0;})(this));}"; // Reflow the page. Without this, the SECE won't execute. window.scrollBy(0, 0); // Clean up and return head.removeChild(styleTag); return document.__qsResult; } @*/

There you have it! The function is wrapped in a conditional compilation comment to make sure only IE 7 and lower can see it. Here is a minified version for convenience:

javascript
< view plain text >
  1. /*@cc_on if(!document.querySelector)document.querySelector=function(s){d=document;h=d.documentElement.firstChild;t=d.createElement("STYLE");h.appendChild(t);d.__q=[];t.styleSheet.cssText=s+"{x:expression(this.__q?0:(function(t){document.__q.push(t);t.__q=0;})(this));}";window.scrollBy(0, 0);h.removeChild(t);return d.__q;}@*/

I hope you can make use of SECEs and this querySelector method. Maybe it even has a place in jQuery? I don’t know. (John Resig, are you reading? :)

UPDATE

After thinking this through a little further, I realized that you don’t need to use a SECE at all for this, just a CSS expression added with JavaScript will do. Also, one of the commenters (Jordan1) pointed out that the code wouldn’t return elements that had already been queried once. I’ve posted an update to the code below that should rectify the issue:

javascript
< view plain text >
  1. /*@cc_on if (!document.querySelector)
  2.         document.querySelector = function(selector)
  3.         {
  4.             var head = document.documentElement.firstChild;
  5.             var styleTag = document.createElement("STYLE");
  6.             head.appendChild(styleTag);
  7.             document.__qsResult = [];
  8.            
  9.             styleTag.styleSheet.cssText = selector + "{x:expression(document.__qsResult.push(this))}";
  10.             window.scrollBy(0, 0);
  11.             head.removeChild(styleTag);
  12.            
  13.             var result = [];
  14.             for (var i in document.__qsResult)
  15.                 result.push(document.__qsResult[i]);
  16.             return result;
  17.         }
  18.     @*/

NOTE: Fancy writing a guest post for Ajaxian? Got some tips on content that we haven’t covered? Please email us, or tweet me :)

Posted by Dion Almaer at 6:13 am
31 Comments

++++-
4 rating from 53 votes

Monday, February 16th, 2009

Native JSON in Firefox 3.1; Joins IE 8

Category: Browsers, JSON

The native JSON API is part of the upcoming 3.1 revision of ECMAScript, so we should see it adopted in browsers pretty quickly. It’s also API compatible with json2.js, as you note, so many many web users will get the performance win without apps needing to update.

I suspect that the performance advantage for native JSON is even more pronounced on the encoding side, but I don’t have tests to hand to back it up.

This was a comment by Mike Shaver, VP of Engineering at Mozilla (disclaimer: where I work).

The comment related to the post on the native JSON support in Firefox 3.1:

In case you haven’t heard, one of Firefox 3.1’s awesome new features will be native JSON support. This is totally sweet for two reasons:

  1. eval’ing JSON in the browser is unsafe. Using native JSON parsing protects you against possible code execution.
  2. Safely eval’ing JSON with a 3rd party library can be orders of magnitude slower. Native JSON parsing is much faster.

How does native JSON work compared to plain old eval? Simple:

var jsonString = '{"name":"Ryan", "address":"Mountain View, CA"}';
var person = JSON.parse(jsonString);
// 'person' is now a JavaScript object with 2 properties; name and address

Pretty easy huh? And here’s how to get a JSON string from an object:

var personString = JSON.stringify(person);
// 'personString' now holds the string '{"name":"Ryan", "address":"Mountain View, CA"}'

“But wait!”, you say. “How is it safer? How much faster is it compared to eval?”. Ok, I’ll show you.

Gotta love it when browsers implement something that just starts to make apps faster without potentially knowing about it.

Posted by Dion Almaer at 4:05 am
8 Comments

++++-
4.3 rating from 33 votes

Monday, February 9th, 2009

Building an isNative method

Category: JavaScript

If you want to test if a method is “native” in that the host provided the methods, versus a third party method (including one that has overridden a native function) it can be tricky.

Kangax posted on the issue where he took a note Diego Perini on an impl:

javascript
< view plain text >
  1. // detect native method in object
  2. // not same scope of isHostObject
  3. var isNative = function(object, method) {
  4.   return object && method in object &&
  5.     typeof object[method] != 'string' &&
  6.     // IE &amp; W3C browser return "[native code]"
  7.     // Safari < = 2.0.4 will return "[function]"
  8.     (/{\s*[native code]\s*}|^[function]$/).test(object[method]);
  9. }

and then shows how it can easily create false positives.

Kangax then shows one solution:

The solution I came up with is not perfect. It doesn’t rely on any specified behavior either; That’s because there doesn’t seem to be any standard, describing what built-in host method should be like / act like / represent itself like. The most robust solution seems to be to test for a presence of a method in a different DOM context. For example, to check whether native window.addEventListener is present, we could use something along these lines:

javascript
< view plain text >
  1. var isNativeWindowAddEventListenerPresent = (function(global){
  2.   // feature test following methods as needed
  3.   var el = document.createElement('iframe');
  4.   var root = document.body || document.documentElement;
  5.   root.appendChild(el);
  6.   var frame = global.frames[global.frames.length-1];
  7.   var result = (typeof frame.addEventListener != "undefined");
  8.   root.removeChild(el);
  9.   el = null;
  10.   return result;
  11. })(this);

In all browsers I tested, same-named methods from any of two non-modified DOM contexts behave identically. This means that if window.addEventListener is present in one non-modified context, it will be present in another non-modified context. It will also function identically. This seems to be a de-facto standard; unlike string representation, all browsers seem to be pretty consistent in this regard.

Posted by Dion Almaer at 3:49 am
14 Comments

++---
2.3 rating from 22 votes

Tuesday, December 9th, 2008

Native Client: Open ActiveX?

Category: Google

Google has released a cool research project called Native Client, a new browser plugin (how many plugins now? gears, toolbar, lively [for awhile], earth, …) that allows you to compile with a special GCC compiler down to x86 that can run in the browser. IE is missing so far, but remember this is a research preview (not sure how 64 bit comes in here etc).

Joel Webber had an interesting comment:

“We ported an internal implementation of H.264 video decoding […] Performance of the original and NaCl versions were comparable and limited by video frame-rate”. Think about this for a second — it makes it entirely feasible to download untrusted software video codecs (among other things) to the browser. I don’t care how fast you make Javascript; I’m pretty sure it will never be able to do this.

Others are talking about a marketplace for addons. It seems like the first demos are always the porting of games. We saw the same thing with Alchemy which allows C/C++ to run in the Flash VM.

With JavaScript speeding up, and our abstractions getting better and better, I don’t see people writing entire Web applications in C, however this is a new extension mechanism that has been added to the toolbox. If you need to integrate with legacy code, or need access in a way you couldn’t get done before, this could be for you.

Maybe it will be a good bridge technology that we can use, at least before we get richer and richer APIs into the browser itself (e.g. implement some of HTML 5 and new APIs using this until browser support).

What do you think?

Posted by Dion Almaer at 12:10 am
5 Comments

+++--
3.4 rating from 23 votes

Monday, July 21st, 2008

iPhone Native Apps vs. iPhone Web Apps

Category: iPhone

John Allsop wrote a long piece over at Web Directions South with some thoughts on writing native iPhone apps versus web-based iPhone apps.

The obvious flaw in his piece is that he only looked at free iPhone applications and from that subset concluded that almost everything the native apps do could be done with web applications (he explicitly ignored Apple’s Remote app; implicitly he must have also ignored Evernote, Pandora, PhoneSaber, Midomi, NetNewsWire–in that it works off-line, Graffitio–which interfaces with the GPS hardware, etc.).

If you’ve spent some time with some of the amazing free and for-pay iPhone apps as I have, just ignore the bit about those apps not being impressive compared to iPhone web apps and skip to the core of his piece where he makes an interesting assertion: the math of trying to profit from selling small apps in the iPhone store doesn’t make sense when compared with (a) the costs of learning the devtools, (b) porting to different phone architectures (vs. one web app code base), and (c) the revenue stream from 37signals-style subscriptions.

Let’s say you sell your App for $1.95. You’ll need to sell 25,000 copies to make $50KUSD. Hang on, Apple takes about 30% so you’ll need to sell 30% more. That’s 36,500 copies. If you look at a typical conversion rate of say 3% of downloads to sales (in my experience, good Mac apps can get that kind of conversion), if this were a desktop shareware app, you’d need to have 1.2 million downloads. That’s more than 10% of the entire projected iPhone user base for the end of 2008 interested in your app.

OK, let’s think about higher price points – at $5, you need to sell 14,000 copies to make $50KUSD, with a theoretical download of 476,000 demo copies. Up this to $10, and we are looking at 7,000 sales, and 233,000 demo downloads. And that’s for a single developer. Double this for 2 developers, triple it for a team of three, and so on.

Now, let’s compare the “sell the app” business model with the increasingly common “subscribing to a service” model. Let’s say we only have customers paying $5 a month. They are already paying $60 a year! So to make our $50KUSD, we’ll need around 1000 customers (about 14% of the number of sales of a $10 app). And I’ve factored in about 12% costs here (transaction and hosting costs, based on personal experience).

Coupled with John “Daring Fireballs” Gruber’s recent measurements of increased WebKit Mobile speed, do you agree with John that iPhone Web Apps are a much better business model than native apps?

Posted by Ben Galbraith at 8:40 am
6 Comments

++++-
4.1 rating from 19 votes

Wednesday, May 21st, 2008

Stack: A native Array wrapper that works

Category: JavaScript, Library, Performance

Andrea Giammarchi has created a native array wrapper that works across browsers. He is excited:

I do not know how many times, during this years, JavaScript Ninjas have tried to subclass the native Array to create libraries over its powerful methods without losing performance. I have finally discovered the way to remove the locked length from Internet Explorer 8, and to solve problems with every other browser.

He ended up with the Stack class:

javascript
< view plain text >
  1. /**
  2.  * Choose a name for subclassed Array
  3.  */
  4. Stack = (function(){ // (C) Andrea Giammarchi - Mit Style License
  5.  
  6.     /**
  7.      * Your personal Array constructor
  8.      */
  9.     function Stack(length){
  10.         if(arguments.length === 1 && typeof length === "number")
  11.             this.length = -1 < length && length === length << 1 >> 1 ? length : this.push(length);
  12.         else if(arguments.length)
  13.             this.push.apply(this, arguments);
  14.     };
  15.  
  16.     // Solution 1:
  17.     //      Declaration of generic function
  18.     //      with an array as prototype
  19.     function Array(){};
  20.     Array.prototype = [];
  21.  
  22.     // Solution 2:
  23.     //      use the prototype chain to inherit
  24.     //      Array constructor and its native prototype
  25.     Stack.prototype = new Array;
  26.  
  27.     // Solution 3:
  28.     //      overwrite inherited length with zero value
  29.     Stack.prototype.length = 0;
  30.  
  31.     // Solution 4:
  32.     //      redeclare toString method in this way
  33.     //      to let JScript core feel better
  34.     Stack.prototype.toString = function(){
  35.         return  this.slice(0).toString();
  36.     };
  37.  
  38.     /**
  39.      * Return and assign subclassed Array
  40.      */
  41.     Stack.prototype.constructor = Stack;
  42.     return  Stack;
  43.  
  44. })();

Posted by Dion Almaer at 10:00 am
10 Comments

++++-
4.2 rating from 21 votes

Monday, February 11th, 2008

Native CSS selectors with querySelector

Category: Browsers, CSS, WebKit

David Smith of WebKit posted about their native implementation of querySelector and querySelectorAll from the W3C Selectors API.

Native CSS selectors in the browsers is going to be a huge boon for us and the Ajax libraries that will be able to use them.

You can use the standard via:

javascript
< view plain text >
  1. /*
  2.    * Get all the elements with class "hot" (duplicating getElementsByClassName)
  3.    * A common use for this is as a toggle;
  4.    * for example, a search feature might tag results with a class
  5.    */
  6.   document.querySelectorAll(".hot");
  7.  
  8.   /*
  9.    * Get the currently hovered element
  10.    */
  11.   document.querySelector(":hover");
  12.  
  13.   /*
  14.    * Get every other element in the <li> with id "large"
  15.    * This is mostly useful for doing "zebra stripe" alternating rows.
  16.    * Once CSS3 becomes more widespread, doing this directly via CSS will be more practical
  17.    */
  18.   document.querySelectorAll("#large:nth-child(even)");

Our favourite libraries can implement the same API and do the hard work in JavaScript if the browser doesn’t support it.

Point your new Webkit build at the performance test that they use (based on the mootools one) to see how fast you can be if you are native. Vroom vroom.

Posted by Dion Almaer at 7:08 am
6 Comments

++++-
4 rating from 27 votes

Friday, January 18th, 2008

Native Comet Support for Browsers

Category: Comet

As JavaScript developers, we are used to years of hacks, as we try to push forward without browsers updating and helping us out. We are so stuck in this pragmatic thinking that we sometimes forget to pick our heads up.

Kris Zyp has taken some time to think about Comet, and instead of thinking about the next good hack, he takes that step back and dreams:

What if I had commit privileges on all the major browsers, the competence to add functionality in all the code bases, and wanted to add native Comet support in a form that was easily accessible to developers?

He ends up with a proposal that adds to good ole XHR:

With only a few simple XMLHttpRequest API additions, Comet communication could be realized with a native implementation that supports fast and efficient standards-based two-way asynchronous communication, with true server-delivered HTTP streaming and simple subscription requests, with the added benefit of client-delivered streaming and cached resource until updated capability. Developers could create Comet applications with a standard API without hacks. Communication could be standards-based, allowing current servers to easily implement the necessary features to handle communication.

It would look something like this:

javascript
< view plain text >
  1. var cometXHR = new XMLHttpRequest;
  2. cometXHR.open('POST','comet',true);
  3.  
  4. var xhr1 = new XMLHttpRequest;
  5. cometXHR.addHttpChunk(xhr1);
  6. xhr1.onreadystatechange=function(){...}
  7. xhr.open('GET','/ticker1',true);
  8. xhr.send();
  9.  
  10. var xhr2 = new XMLHttpRequest;
  11. cometXHR.addHttpChunk(xhr2);
  12. xhr2.onreadystatechange=function(){...}
  13. xhr.open('GET','/ticker2',true);
  14. xhr.send();

Kris gets into many of the details, and makes me with that someone would implement this as a Google Gear, so it could get pushed into the fabric of the Web by being on all browsers.

Posted by Dion Almaer at 9:26 am
7 Comments

+++--
3.7 rating from 29 votes