Eli Grey

Array methods for XML lists

I have created an open source library that implements every array method for E4X XML lists in JavaScript named e4x-array-methods.js. The methods output XML as opposed to arrays to make the output directly usable with other XML. To get the array representation of an XML list, use slice. This returns XML when used to slice out ranges from XML but if no arguments are passed or a third argument is specified which is equivalent to true, it will convert an XML list to an array instead. For example, xmllist.slice(3, 5) returns an XML list and xmllist.slice(3, 5, true) returns an array.

Download

You can download e4x-array-methods.js at it’s github repository. If you wish to minify the library yourself, make sure that your minification tool supports the E4X used in this library. Rhino-based minifiers fail, throwing syntax errors, and /packer/ errantly minifies all of the public methods names preceded by .function::.

Example

The following example demonstrate the usefulness of having array methods for XML lists. If you want to try out the example in a JavaScript shell, make sure XML.prettyPrinting is set to false, which removes any unnecessary whitespace from xml.toString() and xml.toXMLString().

XML.prettyPrinting = false; // for simplifying the comparisons below
 
var foo = <></>; // XMLList literal
foo.push(<n>0</n>, 1, 5, 3, 2, 6, 4);
foo.toXMLString() === "<n>0</n><n>1</n><n>5</n><n>3</n><n>2</n><n>6</n><n>4</n>";
foo.sort(function(a, b) {
    return a - b;
}).toXMLString() === "<n>0</n><n>1</n><n>2</n><n>3</n><n>4</n><n>5</n><n>6</n>";
foo.filter(function(x) { // filter out integers less then 3
    if (!(x < 3))
        return true;
}).toXMLString() === "<n>3</n><n>4</n><n>5</n><n>6</n>";
foo.slice(2, 5).toXMLString() === "<n>2</n><n>3</n><n>4</n>";
foo.splice(2, 1, <n>9</n>, <n>8</n>).toXMLString() === "<n>2</n>";
foo.slice(2, 5).toXMLString() === "<n>3</n><n>9</n><n>8</n>";
foo.pop().toXMLString() === "<n>6</n>";
foo.shift().toXMLString() === "<n>0</n>";
foo.shift().toXMLString() === "<n>1</n>";
foo.unshift(<bar/>);
foo.toXMLString() === "<bar/><n>3</n><n>9</n><n>8</n><n>4</n><n>5</n>";
foo.map(parseFloat).forEach(function(n){ print(n) }) // prints NaN, 3, 9, 8, 4, 5
foo.some(function(x) { // some are greater than 5
    if (x > 5) return true;
}) === true;
foo.every(function(x) { // all are numbers
    if (typeof x == "number") return true
}) === false;

ECMAScript 5 accessors

A while ago, I created a JavaScript library named Xccessors, which implemented the legacy non-standard accessor (getter and setter) methods in IE8. I initially created two different libraries and decided that the library that implemented the legacy methods would be more useful at the time due to no changes needed in a JavaScript program’s code to add accessor support for IE. I never released the second one that implements the ECMAScript 5 (formerly 3.1) standard accessor methods so I’m releasing it now. There can’t be two different libraries with the same “Xccessors” name, so I am also renaming the libraries accordingly to what they implement. The new names are Xccessors Legacy and Xccessors Standard.

Here are two examples of using Object.defineProperty and Object.getOwnPropertyDescriptor:

Using accessors

(function() {
// this creates a document.foo accessor
    var foo = 0;
    Object.defineProperty(document, "foo", {
        get: function() { return foo },
        set: function(x) { return foo += x }
    });
})();
 
document.foo = 5;
(document.foo = 4) === 9;
//Object.getOwnPropertyDescriptor(document, "foo") is {set:[...], get:[...]}

Setting a property

// this is the equivalent of window.foo = "bar";
Object.defineProperty(window, "foo", {value: "bar"});
window.foo === "bar";
Object.getOwnPropertyDescriptor(window, "foo").value === "bar";
window.x = 0;
Object.getOwnPropertyDescriptor(window, "x").value === 0;

CiteDrag WordPress plugin and UserScript

Due to Ajaxian recently featuring my CiteDrag JavaScript library and a suggestion in the comments, I went ahead and made a CiteDrag UserScript that applies CiteDrag to every website and a WordPress plugin that includes CiteDrag on every page of a WordPress-powered website. If you’re using Firefox, you can install the UserScript with Greasemonkey.

You may be thinking that if you visit a page that already uses CiteDrag and have the userscript installed, that the citations would be doubled. This won’t happen though because CiteDrag stores the original data for the text/html and text/plain data types in the text/x-original-html and text/x-original-plain data types. If the UserScript detects that these data types are set, it will use them instead of the already-cited data.

Extending Object.prototype.toString

Object.prototype.toString is a great way to find the “class” of an object, but it only works for the native constructors like String, Function, ect. Due to this limitation, I have created an open source JavaScript library named toStringX which adds support for non-native constructors so things like the string representation of new Foo are [object Foo] instead of [object Object]. I have also made some examples that you can run to see the toStringX library in action that you can find in the toStringX repository README.

Why you shouldn’t use XDomainRequest

I just recently installed Windows and downloaded IE8 again and it seems that pmxdr works fine with the exception of one small MessageEvent.source bug in the host library that I fixed in version 0.0.5.

I went to check out if the XDomainRequest examples I created worked, and to my astonisment, they ALL failed except for the simplest example. It turns out, contrary to what I assumed of it only not supporting responseXML, XDomainRequest also doesn’t support much of the basic HTTP header functionality offered in XMLHttpRequest, such as setRequestHeader, getResponseHeader, and getAllResponseHeaders. This means that my implementation of XDomainRequest actually offered more functionality than IE8’s implementation.

Due to this, I have changed the XXDomainRequest library to implement a generic XDR constructor and I have renamed the library from XXDomainRequest to libxdr. The examples have been changed to use new XDR() instead of new XDomainRequest() so now every example works in IE8.

XDomainRequest is no longer IE-only

XDomainRequest is Internet Explorer 8’s cross-domain request function. It would be easy to add support for it in Firefox 3.5 using native cross-domain XMLHttpRequests, but that wouldn’t work in Firefox 3, Opera 9.6-10, and Safari 4. I have created a library named XXDomainRequest (means “Cross-browser XDomainRequest”) that builds on the pmxdr client library to create a fully API compatible version of XDomainRequest. Go to the XXDomainRequest project page to see (and run) the examples that request resources on code.eligrey.com.

Reusable pmxdr instances

I just released version 0.0.4 of the pmxdr client code to support reusable instances where the same iframe can be used for mutiple pmxdr requests to a domain. It’s still the same interface, but you need to call pmxdr.request() instead of pmxdr() to do a normal request. Instances are created with new pmxdr(host) where host is any URI from the website you want to request (pmxdr figures out where the API is located automatically). Then just call the request method on the instance once the interface iframe has loaded, which you can find out when instance calls it’s onload method once it’s loaded if you set it. The request method now also accepts an array of requests. To start loading the instance, you call it’s init method. To remove the interface frame, you call it’s unload method. Another thing added is the ability to completely remove pmxdr using its destruct method, which removes all event listeners and deletes the pmxdr variable. This does not delete any still-existing interface frames so don’t forget to unload them when you are done to avoid memory leaks.

Using reusable instances saves much more overhead than repeatedly re-requesting a website’s pmxdr host api. When I updated the demo to use a single instance for requesting eligrey.com, it started finishing a multitude of times faster. This is an example of using a reusable instance that uses one interface to make three requests:

var exampleDotCom = new pmxdr("http://example.com");
exampleDotCom.onload = function() {
  this.request([
    {
      uri     : "/foo.html",
      callback: responseHandlers.foo
    },{
      uri     : "/bar.html",
      callback: responseHandlers.bar
    },{
      uri     : "/baz.html",
      callback: responseHandlers.baz
    }
  ]);
};
exampleDotCom.init()
// after all responseHandlers[x] are called, call exampleDotCom.unload()

pmxdr standard documented

I decided to make some detailed documentation on the pmxdr standard used for pmxdr client and host interaction. You may use the standard to implement your own pmxdr client and host libraries. This is particularly useful for websites that don’t want to follow any HTTP access control headers and want to make their own host library implementation use different methods of verification than the reference implementations. The standard is dedicated to the public domain just like every standard I have released so far.

I also modified the demo to automatically do every test so you don’t have to click any buttons to initiate tests.

pmxdr: postMessage cross-domain request library

pmxdr is a cross-domain HTTP request JavaScript library. pmxdr stands for postMessage cross-domain requester. As the name implies, it makes use of the HTML5 postMessage API to make HTTP requests. It requires that a pmxdr host be on the target domain and it respects all HTTP access control headers, even on browsers that don’t support them but do support postMessage, like Firefox 3.

You can download the pmxdr client library and the pmxdr host library (includes an example .htaccess file to help Apache users with PHP set it up) under the latest GNU GPL license and an MIT-style license. The host library must be able to be accessed from /pmxdr/api to be able to interact with the client library.

Read more at the pmxdr project page and try out the demo of it in action.

The following is a very simple example of how to use pmxdr to do a cross-domain POST request (impossible with the normal method of inserting a script tag):

// The requesting domain is example.net
// example.net doesn't want to give any control to example.com
pmxdr.request({
  method   : "post",
  uri      : "http://example.com/search.json",
  data     : "q=foo",
  callback : loadSearchJSON
})

Usually, in this hypothetical example, example.net would have to put a script tag with an src of http://example.com/search.json?q=foo&callback=loadSearchJSON and give example.com full control of example.net. This provides a secure cross-domain way to use APIs like this.

APNG feature detection

I have made a simple script that utilizes the HTML5 <canvas> API in only 9 functional lines of JavaScript to detect if a browser supports APNG images. It can be useful for deciding when to serve a client browser APNG images instead of GIF images.
This will set the variable, apng_supported to true if the browser supports APNG.
I have also created a demo that uses this script.

(function() {
	"use strict";
	var apngTest = new Image(),
	ctx = document.createElement("canvas").getContext("2d");
	apngTest.onload = function () {
		ctx.drawImage(apngTest, 0, 0);
		self.apng_supported = ctx.getImageData(0, 0, 1, 1).data[3] === 0;
	};
	apngTest.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAACGFjVEwAAAABAAAAAcMq2TYAAAANSURBVAiZY2BgYPgPAAEEAQB9ssjfAAAAGmZjVEwAAAAAAAAAAQAAAAEAAAAAAAAAAAD6A+gBAbNU+2sAAAARZmRBVAAAAAEImWNgYGBgAAAABQAB6MzFdgAAAABJRU5ErkJggg==";
	// frame 1 (skipped on apng-supporting browsers): [0, 0, 0, 255]
	// frame 2: [0, 0, 0, 0]
}());