The Metaobjects plugin is going to become a jQuery official plugin, starting from the next jQuery 1.1 release, due out in a week or so. Meanwhile I’ve come up with some improvements that I’m going to share with you, releasing a new version of Metaobjects.
Changes
- Added a new option for selecting the metaobjects to process. The option name is “selector” and its value is a jQuery selector, which defaults to “object.metaobject”, i.e. an OBJECT element with a ‘metaobject’ class (the metaobject definition).
Example: process metaobjects selected by “object.bar”
$.metaobjects({selector: 'object.bar'});
- Added the concept of metaparam for configuring options local to a metaobject. If a PARAM element is given the ‘metaparam’ id, then it is treated as a configuration element, not a metadata element. Either one or none of the PARAM elements can be a metaparam. Its name is needed but not used. A good choice could be ‘options’ or ‘configuration’, anyway the ‘metaparam’ id garantees that it won’t clash with a metadata name you might need.
- Fixed a bug that didn’t allow metaobjects to add metadata to elements without a closing tag, like images (thanks to John Resig for pointing it out). Now this is possible by means of the ‘target’ metaparam option, whose value is a jQuery selector, which defaults to the parent of the metaobject. The selector takes the document as its context.
Example: add this metadata to all the elements selected by “img.foo”
<div><object class="metaobject bar">
<param name='options' value='{target: "img.foo"}' id='metaparam' />
<param name='title' value='"What a Foo!"' />
</object></div>
Code of Metaobjects 1.1
/*
===============================================================================
Metaobjects is a jQuery plugin for setting properties of DOM elements by means
of metaobjects (OBJECT elements with a 'metaobject' class)
...............................................................................
Copyright 2007 / Andrea Ercolino
-------------------------------------------------------------------------------
LICENSE: http://www.opensource.org/licenses/mit-license.php UPDATES:
http://noteslog.com/metaobjects/
===============================================================================
*/
/**
* 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.
*
* Is possible to configure the target of a metaobject by means of a metaparam,
* i.e. a PARAM element with a 'metaparam' id, (one for each metaobject). The name
* of the metaparam is required, but currently not used, so it can be anything not
* null, like 'options'. The value of the metaparam must be an object like this:
* {target: selector}. The selector is a jQuery selector used for finding the
* target inside the document. For example this is used for targeting all the
* images in the current document
*
* <param id='metaparam' name='options' value='{target: "img"}'>
*
* @signature
* |* jQuery *| $.metaobjects(
* |* Object *| options = {
* |* Element *| context: document,
* |* Boolean *| clean: true,
* |* String *| selector: "object.metaobject"
* }
* )
*
* @type
* jQuery
* @name
* $.metaobjects
* @param
* Object options = {context: document, clean: true, selector: "object.metaobject"}
* @option
* Element context The context where the metaobjects are
* @option
* Boolean clean True means 'remove metaobjects after processing'
* @option
* String selector The jQuery selector used for finding metaobjects to process
* @cat
* Plugins/Metadata
*
* @example
* $.metaobjects();
* @desc
* load meta data from all of the meta objects in the document and remove them
*
* @before
* <html><head><title>Hi There</title>
* ...
* <script type="text/javascript">
* $( function() {
* $.metaobjects();
* var p1 = $('#one')[0];
* $( 'body' )
* .append(
* '<p>'
* + 'width = ' + p1.meta_size.width
* + '<br />'
* + 'height = ' + p1.meta_size.height
* + '</p>'
* );
* } );
* </script>
* </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
* <html><head><title>Hi There</title>
* ...
* <script type="text/javascript">
* ...
* </script>
* </head><body>
* <p id="one" title="Hi There">
* Hello World
* </p>
* <p>
* width = 400
* <br/>
* height = auto
* </p>
* </body></html>
*
* @author Andrea Ercolino (http://noteslog.com/)
* @version 1.1
*/
( function($) {
$.metaobjects = function( options ) {
function getParam( elem ) {
var $param = $( elem );
var pName = $param.attr( 'name' );
if ( '' == pName) return null;
var pValue = $param.attr( 'value' );
var data;
eval( 'data = ' + pValue + ';' );
return { name: pName, value: data };
}
var global_settings = {
context: document
, clean: true
, selector: 'object.metaobject'
};
$.extend( global_settings, options );
var $metaobjects = $( global_settings.selector, global_settings.context );
$metaobjects.each( function() {
var settings = {};
$( '> param#metaparam', this )
.each( function() {
var p = getParam( this );
if( ! p ) return;
$.extend( settings, p.value );
} );
var $target;
if( settings.target ) {
$target = $( settings.target );
if( 0 == $target.length ) {
return;
}
}
else {
$target = $( this.parentNode );
}
$( '> param', this )
.not( '#metaparam' )
.each( function() {
var p = getParam( this );
if( ! p ) return;
$.map( $target.get(), function( elem ) {
elem[ p.name ] = p.value;
return elem;
} );
} );
if( global_settings.clean ) {
$( this ).remove();
}
} );
return $metaobjects;
}
} ) ( jQuery );
Tests
These tests show what happens when the metaobjects() function is called with different options on the same page. (only the name of the file changes)
- test.hml
- test1.hml
- test2.hml
- test3.hml
XHTML page
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3c.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html><head><title>Hi There</title>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<script type="text/javascript" src="jquery-891.pack.js"></script>
<script type="text/javascript" src="metaobjects.js"></script>
<script type="text/javascript" src="setup.js"></script>
<style type="text/css">
p#comment {
border: 1px dashed silver;
padding: 10px;
}
</style>
</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>
<p><img class="foo" src="jquery-icon.png" alt="jquery icon" /></p>
<p id="two">
<object class="metaobject bar">
<param name='meta_size' value='{ width: "auto", height: 300 }' />
<param name='title' value='"Goodbye!"' />
</object>
See you soon
</p>
<div><object class="metaobject bar">
<param name='options' value='{target: "img.foo"}' id='metaparam' />
<param name='title' value='"What a Foo!"' />
</object></div>
<p id="comment"></p>
<p>
<a href="http://validator.w3.org/check?uri=referer"><img
src="http://www.w3.org/Icons/valid-xhtml10"
alt="Valid XHTML 1.0 Strict" height="31" width="88" /></a>
</p>
</body></html>
setup.js
$( function() {
var loc = document.location.href;
$( '#comment' ).html( "what happens if $.metaobjects() is not called" );
if( loc.indexOf( "test1.html" ) >= 0 ) {
$( '#comment' ).html( "what happens after calling: $.metaobjects()" );
$.metaobjects();
// $.metaobjects({selector: 'object.bar'});
// $.metaobjects({clean: false}).hide();
var p1 = $('#one')[0];
var p2 = $('#two')[0];
$( 'body' )
.append( '<p>' + 'width = ' + p1.meta_size.width + '<br />'
+ 'height = ' + p1.meta_size.height + '</p>'
)
.append( '<p>' + 'width = ' + p2.meta_size.width + '<br />'
+ 'height = ' + p2.meta_size.height + '</p>'
)
;
}
if( loc.indexOf( "test2.html" ) >= 0 ) {
$( '#comment' ).html( "what happens after calling: $.metaobjects({selector: 'object.bar'});" );
// $.metaobjects();
$.metaobjects({selector: 'object.bar'});
// $.metaobjects({clean: false}).hide();
var p1 = $('#one')[0];
var p2 = $('#two')[0];
$( 'body' )
// .append( '<p>' + 'width = ' + p1.meta_size.width + '<br />'
// + 'height = ' + p1.meta_size.height + '</p>'
// )
.append( '<p>' + 'width = ' + p2.meta_size.width + '<br />'
+ 'height = ' + p2.meta_size.height + '</p>'
)
;
}
if( loc.indexOf( "test3.html" ) >= 0 ) {
$( '#comment' ).html( "what happens after calling: $.metaobjects({clean: false}).hide();" );
// $.metaobjects();
// $.metaobjects({selector: 'object.bar'});
$.metaobjects({clean: false}).hide();
var p1 = $('#one')[0];
var p2 = $('#two')[0];
$( 'body' )
.append( '<p>' + 'width = ' + p1.meta_size.width + '<br />'
+ 'height = ' + p1.meta_size.height + '</p>'
)
.append( '<p>' + 'width = ' + p2.meta_size.width + '<br />'
+ 'height = ' + p2.meta_size.height + '</p>'
)
;
}
} );