Amongst the reactions to Google's release of Chrome was the developer's howl of pain at the thought of another major browser on which to do compatibility testing. Google's generally asserts that Safari compatibility results should be the same as Chrome's, but Nathan Hammond stumbled across a divergence that he finds troubling and which Google shows no inclination to fix. Says Nathan:
There exists a bug in Google Chrome that breaks most history managers. Most all current historymanagers rely upon form-based storage to repopulate their history stack after navigating away from and returning to the present document object, but Chrome doesn't refill form fields when that happens. The result of that is that Google Chrome is currently incompatible with websites using the current generation of history management plugins, and, if their issue tracker has anything to say about it, will remain that way. The bug was closed as "wontfix" due to a misunderstanding. However, it still needs to be addressed to meet the goal of Chrome as I heard at The Ajax Experience 2008: a goal of not fracturing the web and creating yet another browser we developers have to test in and code around.
A nice component model based on OSGi bundles and the Dojo module system
Request-time “building” of many fine-grained JavaScript files into monolithic files for faster download based on the introspected relationships between the files - i.e. no developer effort required for fast code loading other than writing good code
Making a subset of the Eclipse extension registry available in the web page and queryable via JavaScript APIs modeled off of the org.eclipse.core.runtime extension registry Java APIs, allowing for open-ended extensibility using the Eclipse extensibility model
A simple framework for demarcating UI states that made the back button, history, and page titles work seamlessly within the Ajax page, even when a user gesture resulted in crossing a component boundary (e.g. loading and displaying a new virtual “page” from a different component)
Dynamic, transparent loading of missing code in response to a user gesture that required it
He then goes on to explain the architecture of reusable building blocks, and a realization:
My recent realization (which seems obvious in hindsight) is that the useful functionality provided by frameworks and libraries need not be mutually exclusive. For instance, in our Ajax framework’s dynamic build system, rather than requiring applications to run within our framework to enjoy this capability, we could have created a simple callable library to perform dynamic optimization on a set of files, and then created a framework that simply used this same library.
Over the past month or so we’ve been refactoring our Ajax framework to extract the useful building blocks into simple callable libraries and making the framework proper smaller by delegating to these libraries. We’ve done this in the hopes that our code will be useful to other IBM teams but as a result of the exercise, we’ve gained a deeper knowledge of our software and the software’s quality has improved as we’ve decoupled the framework aspects from the building blocks aspects.
Going forward, it’s my intention that our team will generally start with building blocks first and then consider if we should provide some higher-level framework that uses these building blocks. I only wish we had taken this approach from the beginning but you know, live and learn.
Any kind of heavy packaging systems haven't done hugely well in the Ajax community as a-whole, but there is a huge problem with components and being able to reuse them. The fact that someone builds a great jQuery plugin, that then gets ported to Prototype and Dojo and .... is frustrating (one example, it happens N times, with the original framework changing).
This is the week of the plugin. First we had the launch of Silverlight 2, and then, quickly on the back of that we get Adobe Flash 10 at the same time as the entire Creative Suite 4 (which has great Flash authoring tools of course).
One of the security features in Flash 10 is the requirement for the user to act on a Flash movie to be able to access certain APIs. This has caused some Flash upload components to break (ones that use a hidden Flash movie, such as SWFUploadFlickrsFancyUpoad). The solution is quite simple, you need to make the button that launches the upload a Flash control itself (versus an HTML button for example).
You can check out the showcase and do a view source to see that the link is not a link :)
What else is in Flash 10? Here are the top features that Adobe mentions:
3D effects
Create more intuitive, engaging interfaces using built-in support for 3D effects. Get started quickly without being a 3D master by designing in 2D and easily transforming and animating in 3D. Fast, extremely lightweight, and simple-to-use APIs, along with 3D tools in Adobe® Flash® CS4 Professional software, make motion that was previously accessible only to expert users via ActionScript® language or custom third-party libraries available to everyone.
Custom filters and effects
Create high-performance, real-time effects for cinematic experiences that quickly engage users. With new Adobe Pixel Bender™, the same technology behind many filters and effects in Adobe After Effects® software, these dynamic and interactive effects can be used both in production with After Effects CS4 and live with Flash Player 10. The Pixel Bender just-in- time (JIT) compiler can also be used to process other types of data, such as sound or mathematical functions, asynchronously in a separate thread.
Advanced text support
Take advantage of a new, flexible text layout engine that brings print-quality publishing to the web, building on more than 25 years of Adobe expertise in typography. Gain more control over text layout using an extensible library of ActionScript 3.0 text components to flow text and sophisticated typographic elements such as ligatures across multiple columns, around inline images, bidirectionally, vertically, or chained together. Create multilingual rich Internet applications (RIAs) using device fonts that can now be anti-aliased, rotated, and styled, or build your own unique text components.
Dynamic sound generation
Use enhanced sound APIs to dynamically generate audio and create new types of audio applications such as music mixers and sequencers, real-time audio for games, and even audio visualizers. Work with loaded MP3 audio at a lower level by extracting audio data and supplying it to the sound buffer. Process, filter, and mix audio in real time through the Pixel Bender JIT compiler to extend creative freedom beyond the visual experience.
Drawing API
Perform runtime drawing more easily with restyleable properties, 3D APIs, and a new way of drawing sophisticated shapes without having to code them line by line. Developers can tweak parts of curves, change styling, replace parts, and use custom filters and effects, delivering improved throughput, creative control, and greater productivity. Enhancements to the Drawing API add the z dimension, real perspective, textured meshes in 3D space, a retained graphics model, read/write rendering, and triangle drawing with UV coordinates, while adding memory and improving performance.
Hardware acceleration
Use the hardware processing power of the graphics card to paint SWF files into the browser and accelerate compositing calculations of bitmaps, filters, blend modes, and video overlays faster than would be performed in software.
Vector data type
Use the new typed array class for better performance, efficiency, and error checking of data.
Dynamic Streaming
Show exceptional video with streams that automatically adjust to changing network conditions. Leverage new quality-of-service metrics to provide a better streaming experience.
Speex audio codec
Take advantage of the new, high-fidelity and open source Speex voice codec, which offers a low-latency alternative for voice encoding. Flash Player also supports ADPCM, HE-AAC, MP3, and Nellymoser audio.
File upload and download APIs
Bring users into the experience by letting them load and save files from your web application. New file reference runtime access allows local processing of data without roundtripping to the server.
Blackbird, G. Scott Olson's JavaScript logging library, truly has a catchy slogan. The slogan "Say hello to Blackbird and 'goodbye' to alert()" definitely captures what the Blackbird library aims to do; make logging messages in JavaScript extremely easy. And setup is very easy. By incorporating the following lines of code, you've now added the ability to set checkpoints which will display specific data you're interested in:
The video above by Ron Brinkmann is his mockup of a non-euclidean browser UI which looks a touch like the magnifying glass tool on the iPhone, and aims to give you your data in a readable way, while still showing the larger context:
The reason why I think an interface like this can be superior in many ways is that it allows you to specify an area of interest where you get full, detailed information yet you can still see the full document/page/object at the same time. Which means that one is able to avoid the zoom(in/out)-scroll-zoom(in/out)-scroll paradigm that you often get stuck in when using, for example, the iphone. In many ways it gives the user an analogue to the way peripheral vision works in the ‘real world’. You have an area of interest that you can focus on but then you’re also aware of the surroundings and glean information from that as well.
(The mockup I did above just shows a single point-of-interest but it’s certainly expandable to multiple points if you’ve got a touchscreen or other such device. And there’s all sort of little refinements you’d want to implement if you really wanted to make it swank - drag&drop from one place to another might want to keep the source area zoomed but also follow the dragged object with a zoom-region until you get to the appropriate destination. This all gets even sexier once eye-tracking becomes more available - the area you’re looking at would bubble up to full resolution but you’d still be able to quickly scan the entire page and re-target the area of interest. Somebody get busy on this, okay?)
In his post, Ron then shows other subtle examples, such as mapping this to peripheral vision.
Isn't it great that a browser point release these days adds so many features? We are starting to see this from Firefox, Opera, WebKit and others, and it is exciting!
The labs team got Geode out there, and quickly we have seen the addition of the W3C Geolocation API added to the Firefox core. I can test Where Are You with a native implementation.
@font-face
WebKit lead with their @font-face implementation, and getting browser #2 to support it is huge. Now you can load up a font using same-origin rules via simple CSS:
We now have lots of examples testing out the video and audio tags with support for both OGG Theora and OGG Vorbis.
This is something that the Web really needs to work out. The codec game is far from Open, and with native support we get to do cool things such as integrating media with canvas, svg, and plain old HTML. Take a video, add transparency, and skew it a little.... and add an overlay message.
XHR Updates
XHR Progress Notification
We’ve added a better way to get progress notifications for XML HTTP Requests. We’ve implemented the W3C Draft Spec on progress events. In Firefox 3 the events available on the XHR object were progress, uploadprogress, load, abort and error. For 3.1 we now support the loadstart, progress, load, abort and error events. (uploadprogress is also supported, but is deprecated.)
We’ve implemented the draft specification for access-control for cross-site requests. Web developers have long wanted to be able to get data from one site on another but same-origin restrictions on many types of requests prevent many developers from mashing up content. This new access control mechanism offers the ability for servers, content and web clients to cooperate to make a lot of new things possible on an opt-in basis. The spec is complex, and support is new, so if you’re interested reading the spec is probably the best thing to do. It contains examples and uses cases.
Fast JavaScript VM
An early version of TraceMonkey is here:
Beta 1 does include TraceMonkey, our super-fast JavaScript engine, but it’s not turned on by default. If you do want to turn it on, go to about:config, set javascript.options.jit.content to True, restart your browser and try it out.
This is an early beta, of course, so there will be issues. Please file bugs if you find sites that don’t work or cause crashes or hangs. The more testing we get, the better it will be when we turn it on.
Phew, good times for browsers == good times for Web developers.
UPDATE
More browser news, Flock 2.0 is out there, providing a very social browsing experience.
Ryan Stewart of Adobe joined us for episode 5 of the Open Web Podcast. We really want to be pragmatic Open Web citizens, so thought it would be good to hear from Ryan and get his point of view on what Adobe, and he, are thinking with respect to the Web as a-whole.
AIR: Ryan talked about how he sees AIR fitting into the landscape, and how he personally would love to see Geolocation APIs added
Open Source: Ryan shares his insight on the experience Adobe has gotten from their Open Source projects (Tamarin, Flex, ...)
It was a real pleasure to have Ryan come into the lions den. He is very honest with what he does and doesn't know from within, and doesn't hold back on his own thoughts.
Steve Souders posted on Runtime Page Optimizer a tool that you can think of as a performance proxy. It sits on the server side, and cleans up content before it is sent back to the browser.
What can it do? Steve let us know:
RPO automatically implements many of the best practices from my book and YSlow, so the guys from Aptimize contacted me and showed me an early version. Here are the performance improvements RPO delivers:
minifies, combines and compresses JavaScript files
minifies, combines and compresses stylesheets
combines images into CSS sprites
inlines images inside the stylesheet
turns on gzip compression
sets far future Expires headers
loads scripts asynchronously
RPO reduces the number of HTTP requests as well as reducing the amount of data that is transmitted, resulting in a page that loads faster. In doing this the big question is, how much overhead does this add at runtime? RPO caches the resources it generates (combined scripts, combined stylesheets, sprites). The primary realtime cost is changing the HTML markup. Static pages, after they are massaged, are also cached. Dynamic HTML can be optimized without a significant slowdown, much less than what’s gained by adding these performance benefits.
Steve had another couple of interesting posts recently:
Say no to IE6 discusses how we need to do something to help upgrade IE6 users (to IE7 is fine!)
Raising the bar talks about results from Steve's UA Profiler tests and how new browsers are pushing forward
As always with Dav, the utility comes with a full API and documentation, features useful methods like fryBacon() and stopFryBacon() and there are several clever custom events (baconReady, baconDone, baconStart) to subscribe to.
If you dive deeper into the workings of bacon you also find hidden messages of what the future might hold: void cook() An override method for extending this class to maybe fry eggs too.
I am now waiting for jQuery cocktail sausage and protoype T-Bone.
With Dojo 1.2, the build system can generate a 5.5KB gzipped (13KB ungzipped) dojo.js file, via the customBase layer option. Useful for iPhone development if you want to get under the 25KB uncompressed size limits for the Mobile Safari cache. That small dojo.js is basically just the loader and some bootstrap functions, but it allows you then to tune your build layers to meet the 25KB and dynamically load what you need as you go.
Also, the djConfig options afterOnLoad/require/addOnLoad allows loading Dojo after the page is loaded. Great for making progressively enhanced pages render even faster.
The event object contains two properties: .clientRects and .boundingClientRect, both of which refer to the result of the associated DOM methods.
In a nutshell, boundingClientRect gives you a single rectangle encompassing the entire area in which a paint operation could've taken place whereas clientRects gives you a number of rectangles, each encompassing an individual area that was drawn.