Metaobjects 1.0 Released Today – updated

Metaobjects is a jQuery plugin for setting properties of DOM elements by means of metaobjects (OBJECT elements with a ‘metaobject’ class).

Metadata plugin

There is an official Metadata plugin which lets you add metadata to elements by means of three alternative methods, always providing a JSON object to plug the data in:

Class attribute
<p id="one" class="some_class {width: 400, height: 'auto'}">
	Hello World
</p>
Custom attribute
<p id="one" class="some_class" data="{width: 400, height: 'auto'}">
	Hello World
</p>
Element content
<p id="one" class="some_class">
	<script>
		{width: 400, height: 'auto'}
	</script>
	Hello World
</p>
Access

To access a piece of metadata, you write something like this

$( function() { 
	var p1 = $('#one')[0];
	$( 'body' )
		.append( 
			  '<p>' 
			+ 'width = ' + p1.width
			+ '<br />'
			+ 'height = ' + p1.height
			+ '</p>'
		);
} );

Drawbacks

Each method available in the Metadata plugin has a drawback.

  1. The ‘class attribute’ method may generate a conflict with an existing class declaration. In fact any word in any position inside the JSON object (be it the name or value of a JSON property it doesn’t matter) is treated by the browser as a class name. A careful wording mitigates the problem, though. Instead of { a : “b” }, which could clash with an ‘a’ class, you write { a: “b” }. But if you need { a: “b is a char” }, this method is not safe, because it can clash with an ‘a’ and an ‘is’ classes.
  2. The ‘custom attribute’ method generates markup which is not valid XHTML, unless you use an attribute which is defined for the element, but in that case you are exposed to any sort of clashes.
  3. The ‘element content’ method is easily used with a SCRIPT element, because its content stays automatically hidden, but it can clash with your regular scripts. So it should be used with an element like a SPAN whose style be ‘display:none’, but you must remember to add a class or an inline style to each. Another problem is the DOM pollution: if you use this feature frequently then your meta element is like spam for your DOM, you simply cannot take care of all of them.

Metaobjects plugin

My metaobjects.js plugin tries to solve all those problems introducing metaobjects, i.e. OBJECT elements with a ‘metaobject’ class.

The metadata is added to the XHTML page by means of metaobjects whose PARAM elements define name/value pairs. The given ‘value’ attribute is evaluated and added to the metaobject’s parent as a property with the given ‘name’ attribute. Finally the metaobject is removed from the DOM.

One of the best positions to place the call to the metaobjects() function is inside the jQuery “document ready” setup, possibly before any use of a clean DOM.

Exampe 1

Here is how you make jQuery load metadata and clean the DOM afterwards

$( function() { 
	$.metaobjects(); 
... 
} );
Before executing $.metaobjects()
<html><head><title>Hi There</title>
...
</head><body>
<p id="one">
	<object class="metaobject">
	<param   name='meta_size' 
		value='{ width: 400, height: "auto" }' />
	<param   name='title' 
		value='document.title' />
	</object>
	Hello World
</p>
</body></html>
After executing $.metaobjects()
<html><head><title>Hi There</title>
...
</head><body>
<p id="one" title="Hi There">
	Hello World
</p>
</body></html>
Access

To access a piece of metadata, you write something like this

$( function() { 
	var p1 = $('#one')[0];
	$( 'body' )
		.append( 
			  '<p>' 
			+ 'width = ' + p1.meta_size.width
			+ '<br />'
			+ 'height = ' + p1.meta_size.height
			+ '</p>'
		);
} );

Signature

/* jQuery */ $.metaobjects( 
	/* Object */ options = {
		/* Element */ context: document, 
		/* Boolean */ clean: true
	} 
)

The metaobjects() function gets a JSON options argument, with members context and clean. context is a DOM element whose metaobjects you want to process. clean is a boolean which tells wether the metaobjects are to be removed (true) or not (false). options is an optional argument and it defaults to { context: document, clean: true }

The metaobjects() function returns an array containing processed metaobjects (DOM elements) belonging to context. If clean was true, then the metaobjects returned have been removed from the DOM. Else if clean was false, you have a chance to hide() them (e.g. if you didn’t add a CSS definition like “.metaobject {display: none;}”)

Example 2

Here is how you make jQuery load metadata without cleaning the DOM afterwards. In this case you also hide() the objects (in IE you need to, but in FF they’re already hidden)

$( function() { 
	$.metaobjects( {clean: false} ).hide(); 
... 
} );

Code of Metaobjects 1.0

There is a bug (#750) in jQuery 1.0.4 (Rev 696) that makes this plugin not usable. I’ve found a simple fix, though.

Find the following snippet in the source (lines 49-56)

// See if an extra function was provided
	var fn = arguments[ arguments.length - 1 ];

	// If so, execute it in context
	if ( fn && typeof fn == "function" )
		this.each(fn);

	return this;

and make it like this one

// See if an extra function was provided
	var fn = arguments[ arguments.length - 1 ];

	// If so, execute it in context
	if ( fn && typeof fn == "function" && fn.nodeType == undefined )
		this.each(fn);

	return this;

2 Replies to “Metaobjects 1.0 Released Today – updated”

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.