Blog
May 15th, 2008
There's been a lot of interest in yesterday's release of Google Doctype. The primary focus of the release is on documentation (specifically "documenting the Open Web") however there's also two extra, hidden, additions: A Google-released JavaScript library and an Open Web test suite. Let's break down the parts of this release.
Documentation
On the main Google Doctype site they provide a link to Browse Google Doctype which takes you to a JavaScript-laden site through which you can read the various articles that they provide. If, instead, you'd prefer to read something a little more static (and sanely linkable, bookmarkable) you can just go straight for the Google Doctype Wiki instead.
The documentation falls into 2 realms:
DOM and CSS
These are sort of API references to all the DOM and CSS properties. However, browsing through, they don't seem to be terribly useful. At best, these references are programmatically generated (seeded with initial values). It's not completely clear what its setting out to achieve but my guess is something like "if we put all the information in a wiki, maybe people will come and fill it out," which seems a little awkward (especially since it's already been done before).
The primary original content provided by this reference is related to the 'browser compatibility' section of each item. For example, examine the background-postition CSS property page. There's a whole bunch of information being tested for - and a whole lot of 'N's in the columns - in fact there's even a couple rows that contain nothing but 'N's. This says to me a couple things:
- When every browser fails a test then you're probably testing the wrong thing.
- The fact that the actual return values aren't shown makes this extra frustrating (every browser fails background-position: left - but what do they fail with? what are they returning, instead?).
- There doesn't seem to be any attempt to test for compliance. Overwhelmingly the test values appear to be "the value that goes in should be the value that comes out" - which is rarely the case. Granted, it's much easier to write tests of this nature (just generate them programmatically) but the end result doesn't really help anyone.
How-To Guides
The final portion of the documentation centers around a number of articles relating to JavaScript/DOM programming.
A number of these articles are quite good (such as the Web Security section and a couple of the other articles). However, the rest of the articles are quite... confusing. They appear to be documentation for methods of a Google JavaScript library, however they're presented as Copy-and-Paste examples that developers can use. I think most developers will be quite disappointed when they find out that it's not possible.
On the article pages the Google JavaScript library is never mentioned, nor linked to. You can eventually find it if you go to source, browse the SVN (to the right directory), and download the individual files of the library.
I think I can safely say that this is the first time that documentation for a JavaScript library has been released before the library itself.
Google JavaScript Library
The second portion of the Google Doctype release was the public unveiling of the (for lack of a better name) "Google JavaScript Library." It, currently, only existing in Google SVN. There doesn't appear to be an API reference, either - beyond the various articles provided in the above How-Tos.
Digging through the code there appears to be a huge depth of coverage for some... rather obscure JavaScript topics. If anything has been shown during the last couple years of JavaScript library development (in that the functionality that users have been asking for, and using) is that DOM traversing, DOM manipulation, Events, Ajax, and Animations are fundamental. While the Google JavaScript library does provide some DOM manipulation and Events they completely ignore all other aspects of JavaScript development. Instead they delve off into the land of object traversal, string manipulation, math helpers, and data structures.
If I had to pick a library that this one was closest to I'd have to say MochiKit. I wasn't very surprised then to find out that the Google JavaScript library's DOM helpers were heavily inspired by MochiKit.
No offense to MochiKit or the Google JavaScript library but if past history is any indicator - developers are not clamoring for another MochiKit.
Open Web Tests
The final portion of this release is related to the programmatically-generated Open Web API reference. This is a full suite of tests that cover HTML elements, JavaScript/DOM methods, and CSS properties.
Thankfully raw dumps of the results are provided for each browser so we can use this as an opportunity to see what tests are being performed (and how the results compare).
Taking a look at the JavaScript/DOM results for Firefox 3 we see a lot of 'existence' tests. The vast majority of the tests appear to be checking to see if particular methods, or properties, exist. Scroll through we see some puzzling error messages:
3. document/document-attachEvent-typeof-test.html:testTypeOf failed
"[DocumentAttacheventMethod] typeOf(document.attachEvent) != 'undefined'"
Expected not to be <undefined> (String)
Firefox 3 is failing this test because it doesn't have Internet Explorer's proprietary attachEvent method? If you continue through the results you'll see similar indicators all throughout. If you were to open Internet Explorer's results you would see a number of fails for Netscape-specific methods/properties.
Opening up the HTML Firefox 3 results we see a similar situation. In this case the HTML tests appear to focus on the availability of attribute expandos on DOM elements. For example, here's one failing test from Firefox 3:
293. attributes/ilayer-above-reflection-test.html:testReflection failed
"[IlayerAboveAttribute] ilayer.above reflects <ilayer above="foo">"
Expected <foo> (String) but was <undefined>
The ilayer element was a Netscape-specific HTML extension. Testing for its DOM compliance (and, by extension, its existence) seems quite futile.
If I had to guess as to how these tests were generated I'd say "open up a browser, spider every DOM property (or HTML attribute), and turn those into existence tests."
This raises an important point: This suite is not built for any sort of standards compliance - at all - it's simply designed to check for compatibility between browsers. Looking at this suite as a compatibility suite we can start to see some use - but it's still terribly limited (only checking for existence is hardly a good-enough indicator of a browser's proper support of a property or method).
If there's one over-arching theme to the Google Doctype release it's been "whatever we can generate automatically, or release with the least amount of fuss, let's do that, no matter how simple it may be." I'm definitely looking forward to when a full release comes along, but this doesn't appear to be it.
Tags: html, css, google, documentation, javascript, library
31 Comments on 'Google Doctype'
November 12th, 2006
After some recent discussion concerning the use of document.write() in XHTML documents served with the doctype "application/xhtml+xml" I decided to revisit the problem. An issue with the solutions proposed by Sam and Ajaxian is that they aren't really solutions - just a lot of hand waving (not that that's bad, it's just that the problem is a lot harder than what they propose).
So I sat down and decided to write a semi-complete document.write() replacement for Firefox 1.5+, Opera 9, and Safari 2+ - all handling straight XHTML documents served with an "application/xhtml+xml" content-type.
Note: Notice that I completely ignore Internet Explorer. Since IE doesn't even know to render XHTML pages (served with the correct mimetype), I'm assuming that you're doing some form of browser sniffing in your code (on the server). If that's the case, then you may be serving a different version of the page, and not include the (at this point) unnecessary document.write() hack. If you want to serve only one version of the code, then I suggest that you use conditional comments, or do some client-side browser sniffing to serve the hack to those that need it. (This is mostly because I have yet to find a way to reliably detect a broken document.write() implementation.)
I had a couple of goals for my solution:
- It should be as faithful to the normal document.write() as possible. (This means arbitrary injection of XHTML into the DOM)
- It should inject the XHTML into the document at the current DOM position.
- It should correct for basic weird things that people do (like using write to add invalid XHTML to a document - and writing out closing tags). Stuff like this:
document.write("<iframe src='test.html'>");
// ... some code ...
document.write("</iframe>");
- It should make Google Adsense work, with no code modification.
I'll start by saying that solving this problem in Mozilla "isn't that bad" nor is it in Opera. Safari is a royal PITA, which I'll talk about, more, later.
The vast majority of the cross-browser issues that occur relate to how innerHTML works in XHTML documents. In order to make document.write() work as you would expect it to, you need to write out straight (X)HTML. This topic has been discussed extensively by some of the great JavaScript and standards developers in the industry.
A Solution
So I've developed a basic solution to the document.write()/XHTML problem. The full code for which can found found below, along with a demo of it in action here:
http://ejohn.org/apps/write.xhtml
document.
write =
function(str
){
var moz = !window.
opera && !
/Apple/.
test(navigator.
vendor);
// Watch for writing out closing tags, we just
// ignore these (as we auto-generate our own)
if ( str.
match(/^<\
//) ) return;
// Make sure & are formatted properly, but Opera
// messes this up and just ignores it
if ( !window.opera )
str = str.replace(/&(?![#a-z0-9]+;)/g, "&");
// Watch for when no closing tag is provided
// (Only does one element, quite weak)
str = str.replace(/<([a-z]+)(.*[^\/])>$/, "<$1$2></$1>");
// Mozilla assumes that everything in XHTML innerHTML
// is actually XHTML - Opera and Safari assume that it's XML
if ( !moz )
str = str.replace(/(<[a-z]+)/g, "$1 xmlns='http://www.w3.org/1999/xhtml'");
// The HTML needs to be within a XHTML element
var div = document.createElementNS("http://www.w3.org/1999/xhtml","div");
div.innerHTML = str;
// Find the last element in the document
var pos;
// Opera and Safari treat getElementsByTagName("*") accurately
// always including the last element on the page
if ( !moz ) {
pos = document.getElementsByTagName("*");
pos = pos[pos.length - 1];
// Mozilla does not, we have to traverse manually
} else {
pos = document;
while ( pos.lastChild && pos.lastChild.nodeType == 1 )
pos = pos.lastChild;
}
// Add all the nodes in that position
var nodes = div.childNodes;
while ( nodes.length )
pos.parentNode.appendChild( nodes[0] );
};
It's important to note what this solution does - and does not - work for.
- The code will work perfectly for well-formed XHTML markup. This code only does basic "crappy HTML" checks. For example, if you do: document.write("<img src='foo.jpg'>") it'll correct it to become XHTML compliant (with the extra / at the end). However, doing document.write("<img src='foo.jpg'> <img src='bar.jpg'>"); will break - as only the last element in the document.write() is "fixed". (And even then, the fixing isn't very smart - it just adds a closing tag, which may not always be correct.) Much of this can be fixed with some smarter regular expressions. I took a stab at it, but cross-browser support for variable negative lookaheads seems to be shaky, at best.
- When using innerHTML in an XML document in Opera and Safari, it assumes that all elements are just XML elements. For this reason the code forcefully puts all elements in the XHTML namespace. Again, this is pretty crude and may break some of your markup, but it's worked well for me so far.
- The only extra purification that's performed is the conversion of ampersands (&) to their entity code (&) - where appropriate. If you have other symbols (like < or >, then I can't make any guarantees.)
- It's also interesting to note that two completely different methods of traversing the document had to be used. Mozilla-based browsers start acting really strange when you do getElementsByTagName("*") inline in an XHTML document. It will always work fine for the first document.write(), but all subsequent calls will revert back to the position of the last inline <script/>.
- In the end, this is still not as good as document.write() since with .write() you can write out stuff like table rows, options, partial HTML, script elements, all without blinking an eye. The code to handle all of this is quite significant (having written the code to do it for jQuery, you can take my word for it). I don't plan on re-writing all of that special-case code, so please only use this solution for simple fixes.
Ok, so now that that's out of the way - let's see how well this works in the different browsers.
|
Firefox 1.5+ |
Opera 9 |
Safari 2 |
Webkit (Safari 3) |
| Simple Text Insertion |
Pass |
Pass |
Fail |
Pass |
| Simple HTML Insertion |
Pass |
Pass |
Fail |
Pass |
| Google Adsense |
Pass |
Pass |
Fail |
Sort-of Fail |
So here's the dirt on Safari. I spent many hours banging my head against the keyboard and finally admitted defeat in Webkit for Adsense and anything in Safari 2.0. Here's the issues:
- Safari 2.0 completely rejects any attempts to use innerHTML in an XHTML document. It throws exceptions and simply will not let you do it. For this reason, Safari (as it is currently available) is a lost cause.
- Webkit Nightlites (Safari 3.0) on the other hand, fixed the innerHTML problems - allowing it to work nearly flawlessly. You can see that on the demo page (in a Webkit Nightly) that the Google Adsense IFrame is inserted into the page - and a URL is even requested - however the Adsense script seems to be fundamentally flawed. Looking at the URL generated for Webkit vs. the URL generated for Firefox or Opera, it is apparent that the Adsense script simply isn't working correctly. So while, technically, Adsense does not (currently) work in the Webkit Nightly, with this hack, it seems like it's not by a fault of mine.
In all, this hack was an interesting experience - considering that every browser seems to behave in some sort of nonsensical fashion (in one way or another). I'm glad that there's, at least, a solution now for two of the major browsers (and possibly the next version of Safari too, after some more tinkering). I was, perhaps, most pleasantly surprised by Firefox's innerHTML/XHTML implementation. You feed it valid XHTML, it inserts it into the document. Any other value throws an exception. Very simple and logical.
As a side note: I'm going to try and feed some of this code back into jQuery, so that stuff like $(...).append("
") will work as you might expect it to in the major browsers.
It's pretty obvious that writing XHTML documents with the preferred mimetype is still a ways off from real-world usage, however I'm more hopeful now than I was before - which is good, to say the least.
Tags: adsense, javascript, google, xhtml
22 Comments on 'XHTML, document.write, and Adsense'
February 7th, 2006
Google just rolled out transcripts of chat conversations within Gmail, here's a quick screenshot:

They mention that a new in-browser chat tool is coming too, although I don't see it yet. Currently, chats are saved like emails, and you can reply to the person you were chatting with, like in an email - a very neat combination of two mediums. Check it out and drop me an IM.
Tags: gmail, mail, chat, google
6 Comments on 'Gmail Chat'
December 14th, 2005
Yesterday, I sat down and played around with the new Google Homepage API, which is interesting, in and of itself. I found the development to be most like developing a widget (for Dashboard or Konfabulator).
A couple observations:
- By default, your module is contained within a fixed height IFrame, but it's possible to actually embed your widget straight into the Google Homepage itself.
- My first worry was over the possibility of XSS attacks, but all modules run on a different domain, gmodules.com. (I'm not sure what happens if you embed it in the page, my guess is that they're far more restrictive, if you want your module to run free like that)
- The have a server-side proxy that's on the same domain as the modules - which means that you can do cross-domain XMLHttpRequests - a very smart move (at least from a developers perspective, not sure about security, though).

My first test module is rather simple, it's just the current list of links from del.icio.us popular, auto-updating every hour. To run it for yourself, go to your Google Homepage, click the 'Add Content' link and enter the following URL into the 'Create A Section' textfield:
http://ejohn.org/apps/igdel/
If you're worried about running foreign modules on your homepage, you can feel free to look at the source code - it's completely harmless.
The majority of the code, for the frontend of the module, was borrowed from two places:
The final bit, that made this module work, I'll discuss tomorrow - it's a dynamic RSS to JSON convertor, that's incredibly cool. (If you're feeling adventurous, you can look at the module source code and find it hidden in there.)
Tags: javascript, json, programming, api, homepage, google, rss
11 Comments on 'Google Homepage API'
October 18th, 2005
I could give a thousand excuses, but I'm not entirely sure if they'd mean anything. September and October have been an incredibly busy time for me, school, moving, sickness, work - it's just piled on top of each other. Although, this doesn't mean that I've been slacking - I just haven't had time to make blog posts. Amusingly, according to my stats, there are now over 900 of you reading this weblog via RSS - which is pretty slick.
Here's a quick recap of some of the things that happened these past two months:
Today I won the Quirksmode addEvent re-coding contest. This particular contest was to write an implementation of addEvent and removeEvent that was completely cross-browser and usable. I like my submission, simply due to its brevity, and so did the judges.
Some of my past research, into Instant Messaging, was mentioned in the RIT Reporter (my school newspaper). It's kind of light and 'fluffy', but a good starter piece. If you're interested in this sort of thing, contact me, or check out the project page.
I was mentioned, in passing, in The Economist, concerning the recent trend in mash-up applications, specificially concerning the Yahoo Traffic RSS feed. I think the article is no longer accessible - but may be if you get a login.
Finally, one of my Google Maps projects went live - it was for a newspaper in Florida, the Herald Tribune, concerning the Save Our Homes initiative. My particular application allowed users to browse through their homes and see how their tax rates compared to their neighbors. From everything that I've heard, it's been quite successful. It makes me happy to bring cool technology (Google Maps) to people who wouldn't have used/seen it otherwise.
I'm going to be releasing a full-blown product within the next week, or so - it's very simple, but exciting, nonetheless. I hope people will get a kick out of it.
Tags: maps, google, news, im, javascript, rss, magazine
Comment on 'Fall Recap'
August 19th, 2005
This is the final part of a week long series featuring code for the Google Maps API.
For the last day of this series (don't worry, this isn't the end of me having fun with Google Maps - there's still much more to come!) I decided to implement two things.
The first new feature is a sane version of the afformentioned Mouse Wheel Zooming. This version is completely streamlined, tied straight into the GEvent API, and isn't limited to only zooming.
Moving the mouse wheel code over to the GEvent API was rather simple - what was more complex was attempting to fix a rather serious (in my opinion) usability issue with the mouse wheel zooming. My first intuition, when using the wheel-zooming, was to position my mouse cursor over where I wanted to zoom to then flick the mouse wheel up. However, moving the mouse wheel up causes the map to zoom in into the current map position - completely ignoring the position of the mouse. I've added the code to correctly capture the current lat/long of the cursor and pass it into the GEvent.
However, one issue still arises: Zooming in to the point you had your mouse over re-positions that point to the center of the screen - not where your mouse is. This means that you then have to move your mouse back to the center of the screen to continue zooming in. To fix this, I've written a method that can be used to properly scale the points to where they should be - this will even help the 'click zoom' code that I developed earlier this week. You can see this for yourself in this demo. In that demo I use the following code to capture the mouse wheel movements and zoom in correctly:
GEvent.
addListener( map,
"wheelup",
function(p
){
if ( map.
getZoomLevel() >
0 ) {
map.
centerAndZoom(
p.
scaleRelative( map.
getCenterLatLng() ),
map.
getZoomLevel() -
1
);
}
});
GEvent.addListener( map, "wheeldown", function(p){
if ( map.getZoomLevel() <= 16 )
map.centerAndZoom(
p.scaleRelative( map.getCenterLatLng(), -1 ),
map.getZoomLevel() + 1
);
});
The next feature is purely fun: Map in Map Support. Similar, in concept, to having 'Window in Window' on a TV screen, this displays a small, zoomed out, map in the corner of your main map.
Really, a demo would probably best illustrate this concept.
This was a test, for me, to see how easy/hard it would be to 1) Embed HTML on top of a map and 2) Put a Map in that HTML. The answer to both is: Easy and Very Easy. It took a little bit of poking around in the API to try and figure out how to get the HTML onto the map (looking at the code for similar functions, such as GSmallMapControls, helped a lot) - but once that was solved, adding a Map on top was as easy as 'new GMap()'.
eJohn.org RSS Readers

06/01
153 to 08/19
305
Now, a question to my readers (and if my recent analysis is correct, there's over 300 of you): Did you enjoy this week long feature - looking at Google Maps? If you did/didn't what specifically did you like/not care for? Any input would be greatly appreciated! Thanks in advance - I'm looking forward to do this again, very soon!
Tags: maps, javascript, google, programming, api
28 Comments on 'One Week of Google Maps - Part 7'
August 18th, 2005
This is Part 6 of a week long series featuring code for the Google Maps API.
The theme for today is Animation (per the request of Ralph). For programmers who want to make a walkthrough of their town, or a tutorial - play-by-play animation is an important feature to have - and one that is missing from the default API.
I've added the functionality to the API such that you can animate the user's map view based upon:
- An array of points.
- An array of markers.
- An array of markers and points.
- A Polyline.
In addition to this, if you wish to use markers in your animation - and if you've bound a function to the "click" event of the marker - then that click will be triggered, displaying an info window (for example).
Using all of these features together, in tandem, you can create a pretty convincing slideshow. To see a demo of the animation at work, click here.
To interface with this, here is the function that you need to call:
map.animate( points, closeFunction, pointWait, markerWait );
points - is a GPolyline or an Array of GMarkers and/or GPoints.
closeFunction (optional) - this function will be called whenever the animation has been completed.
pointWait - this is the amount of time to wait at a point (or a marker without a 'click' event). The default is 3000 milliseconds.
markerWait - if you've bound a function to the click event of a marker then this is how long you wish to wait (for example, if you want to give a user time to read an Info Window). The default is 6000 milliseconds.
To use the above code, simply include this file in the header of your code - after you've included your Google Map API file - and you should be ready to go! Happy animating!
Tags: maps, javascript, google, programming, api
5 Comments on 'One Week of Google Maps - Part 6'
August 17th, 2005
This is Part 5 of a week long series featuring code for the Google Maps API.
After loading address latitude/longitude information, the next most desired feature for a Google Maps developer is the ability, for the end-user, to link to a particular map that they're viewing. I've taken this concept one step further:
- A link, to the current view of the map, can be provided to the user. Additionally, the link can be automatically updated everytime the user moves the map or zooms in/out.
- The last view that a user was looking at, on your map, is automatically loaded the next time they visit your site.
- A new info window is available which, when revealed, provides the user with a way to link to that specific marker's coordinates.
These features, once combined, add a lot of much-needed usability to the API. Using this code is fairly foolproof too. Below is a chunk of code taken from the demo, demonstrating all the important features of this addition to the API.
// If the user has been here before, load the last point they were at
// "testmap" is the name of this particular map - you'll need a unique
// name for each map you make, per domain
if ( ! map.
loadPos("testmap") )
// If the user has never been here before, show the default point/zoom
map.
centerAndZoom(new GPoint
(-
122.
1419,
37.
4419),
4);
// Update this link everytime the user moves/zooms the map
map.updateLink( document.getElementById("link") );
// A sample marker
var m = new GMarker( new GPoint(-122.1419, 37.4419) );
map.addOverlay( m );
GEvent.addListener( m, "click", function() {
// Show an Info Window with a link in it
m.openLinkWindowHtml( "a test window!" );
});
To view a demo of these features, please click here.
The Javascript file can be downloaded here
Tags: maps, javascript, google, programming, api
68 Comments on 'One Week of Google Maps - Part 5'
·
« Previous entries