Daniel Aquino - DOM.Find-1.00
NAME
DOM.Find - Tools for searching DOM trees.
SYNOPSIS
// get all input elements of type text in document var textInputs = getElementsByAttributes({ tagName: 'input', type: 'text' }, document);
DESCRIPTION
Finds DOM elements matching given criteria relating to their attributes.
DOM.Find does not export any methods by default,
but allows you to export either of the methods described below.
EXAMPLES
General
<script type="text/javascript">
// Define the attributes we are looking for
var attributes = {
'tagName':'DIV', // scalar Test
'id':(new RegExp('^car_[0-9]+$','i')), // RegExp Test
'className':(function(value){ // Function Test
if(value.indexOf('car') == -1){
return false;
}
return true;
})
}
// Define where in the DOM we want to start the search
var startAt = document.getElementByid('cars');
// Find the Nodes!
var results = getElementsByAttributes(attributes, startAt, undefined, 1);
// Do something with the result set
for(var x = 0; x < results.length; x++){
var element = results[x];
element.style.display = 'none';
}
</script>
'Elements By Id IndexOf'
// Use 'indexOf' to speed up simple "String Matches"...
var attributes = {'className':function(value){
return (value.indexOf('car') != -1) ? true : false ;
}}
'Elements By Id Regex'
var attributes = {'id':(new RegExp('^car_[0-9]+$','i'))}
'Elements by ClassName'
var attributes = {'className':(new RegExp('car','i'))}
'Elements By Input Type'
var attributes = { tagName: 'input', type: 'text' }
Package Methods
checkAttributes(<tests:Object, <node:Node>)>
Checks DOM element against {proptery: value} pairs...
<tests:Object>
Properties:
A DOM Node property.
Examples: 'className', 'id', 'style.marginLeft', 'style.position' etc...
Values:
Either a Scalar, RegExp, or Function.
Scalar
If neither a RegExp or Function is detected.
Then the value will be processed via a Scalar test.
Example: `{'id':'car_50'}`
RegExp
Must be a RegExp Object...
Example: `{'id':(new RegExp('^car_[0-9]+$','i'))}`
Function
Must be a refence to a Function...
It must explicitly return true/false...
Absence of either will result in false!
Property's "value" will be passed as a single argument.
Example: `{'id':(function(value){return value.indexOf('car') != -1})}`
<node:Node> DOM element in question.
getElementsByAttributes(<tests:Object, <startAt:Node>, <resultsLimit:integer>, <depthLimit:integer>)>
Searches DOM for elements tested against {proptery: value} pairs...
<tests:Object> (See below for more details) [<startAt:Node>] The DOM starting point, defaults to `document`. [<resultsLimit:integer>] Stops searching for further nodes once it has reached the limit. [<depthLimit:integer>] Will not proceed deeper into the DOM heirarchy.
geba(<tests:Object, <startAt:Node>, <resultsLimit:integer>, <depthLimit:integer>)>
This function is an alias for getElementsByAttributes.
AUTHOR
Daniel, Aquino <mr.danielaquino@gmail.com>.
COPYRIGHT
Copyright (c) 2007 Daniel Aquino.
Released under the Perl Licence:
http://dev.perl.org/licenses/
/*
=head1 NAME
DOM.Find - Tools for searching DOM trees.
=head1 SYNOPSIS
// get all input elements of type text in document
var textInputs = getElementsByAttributes({ tagName: 'input', type: 'text' }, document);
=head1 DESCRIPTION
Finds DOM elements matching given criteria relating to their attributes.
C<DOM.Find> does not export any methods by default, but allows you to export either of the
methods described below.
=head3 EXAMPLES
General
<script type="text/javascript">
// Define the attributes we are looking for
var attributes = {
'tagName':'DIV', // scalar Test
'id':(new RegExp('^car_[0-9]+$','i')), // RegExp Test
'className':(function(value){ // Function Test
if(value.indexOf('car') == -1){
return false;
}
return true;
})
}
// Define where in the DOM we want to start the search
var startAt = document.getElementByid('cars');
// Find the Nodes!
var results = getElementsByAttributes(attributes, startAt, undefined, 1);
// Do something with the result set
for(var x = 0; x < results.length; x++){
var element = results[x];
element.style.display = 'none';
}
</script>
'Elements By Id IndexOf'
// Use 'indexOf' to speed up simple "String Matches"...
var attributes = {'className':function(value){
return (value.indexOf('car') != -1) ? true : false ;
}}
'Elements By Id Regex'
var attributes = {'id':(new RegExp('^car_[0-9]+$','i'))}
'Elements by ClassName'
var attributes = {'className':(new RegExp('car','i'))}
'Elements By Input Type'
var attributes = { tagName: 'input', type: 'text' }
=head2 Package Methods
=cut
*/
if ( typeof DOM == "undefined") DOM = {};
DOM.Find = {
VERSION: 1.00,
EXPORT: [ 'checkAttributes','getElementsByAttributes', 'geba' ],
/*
=head3 C<checkAttributes(<tests:Object>, <node:Node>)>
Checks DOM element against {proptery: value} pairs...
<tests:Object>
Properties:
A DOM Node property.
Examples: 'className', 'id', 'style.marginLeft', 'style.position' etc...
Values:
Either a Scalar, RegExp, or Function.
Scalar
If neither a RegExp or Function is detected.
Then the value will be processed via a Scalar test.
Example: `{'id':'car_50'}`
RegExp
Must be a RegExp Object...
Example: `{'id':(new RegExp('^car_[0-9]+$','i'))}`
Function
Must be a refence to a Function...
It must explicitly return true/false...
Absence of either will result in false!
Property's "value" will be passed as a single argument.
Example: `{'id':(function(value){return value.indexOf('car') != -1})}`
<node:Node>
DOM element in question.
=cut
*/
checkAttributes: function(hash,el){
// Check that passed arguments make sense
if( el === undefined || el === null )
throw("Second argument to checkAttributes should be a DOM node or the ID of a DOM Node");
if( el.constructor === String )
el = document.getElementById(el);
if( el === null || !el.nodeType ) // Make sure el is a Node
throw("Second argument to checkAttributes should be a DOM node or the ID of a DOM Node");
if(! (hash instanceof Object))
throw("First argument to checkAttributes should be an Object of attribute/test pairs. See the documentation for more information.");
// If we're still here, check the test pairs
for(key in hash){
/*
Prepare the "pointer"
*/
// Check to make sure property chain is valled
// Provides easy declaration of nested propteries
// Example: {'style.position':'absolute'}
var pointer = el // pointer
var last = null; // last pointer used to aplly() later
var pieces = key.split('.'); // break up the property chain
for(var i=0; i<pieces.length; i++){ // loop property chain
// There can be no match
// if the attribute does not exist
if(!pointer[pieces[i]]) return false; // test the pointer exists
// Save the current pointer
last = pointer; // backup current pointer
// Develope the pointer
pointer = pointer[pieces[i]]; // stack the pointer
}
// Check if the pointer is actually a function
// Provides easy declaration of methods
// Example: {'hasChildNodes':true}
// Example: {'firstChild.hasChildNodes':true}
// Does not work in IE
// IE returns Object instead of Function
if( pointer instanceof Function )
try {
pointer = pointer.apply(last);
}catch(error){
throw("First agrument to checkAttributes included a Function Refrence which caused an ERROR: " + error);
}
/*
Test "pointer" against "value"
*/
// Perform one of 3 tests
// Regex, Function, Scalar
// Check against a regex
if( hash[key] instanceof RegExp ){
if( !hash[key].test( pointer ) )
return false;
// Check against a function
}else if( hash[key] instanceof Function ){
if( !hash[key]( pointer ) )
return false;
// Or check against a scalar value
}else if( hash[key] != pointer ){
return false;
}
}
return true;
},
/*
=head3 C<getElementsByAttributes(<tests:Object>, <startAt:Node>, <resultsLimit:integer>, <depthLimit:integer>)>
Searches DOM for elements tested against {proptery: value} pairs...
<tests:Object>
(See below for more details)
[<startAt:Node>]
The DOM starting point, defaults to `document`.
[<resultsLimit:integer>]
Stops searching for further nodes once it has reached the limit.
[<depthLimit:integer>]
Will not proceed deeper into the DOM heirarchy.
=cut
*/
getElementsByAttributes: function( searchAttributes, startAt, resultsLimit, depthLimit ) {
// if we haven't been deep enough yet
if(depthLimit !== undefined && depthLimit <= 0) return [];
// if no startAt is provided use document as default
if(startAt === undefined){
startAt = document;
// if startAt is a string convert it to a domref
}else if(typeof startAt == 'string'){
startAt = document.getElementById(startAt);
}
// check the startAt element
var results = checkAttributes(searchAttributes, startAt) ? [ startAt ] : [];
// return the results right away if they only want 1 result
if(resultsLimit == 1 && results.length > 0) return results;
// Scan the childNodes of startAt
if (startAt.childNodes)
for( var i = 0; i < startAt.childNodes.length; i++){
// concat onto results any childNodes that match
results = results.concat(
getElementsByAttributes( searchAttributes, startAt.childNodes[i], (resultsLimit) ? resultsLimit - results.length : undefined, (depthLimit) ? depthLimit -1 : undefined )
)
if (resultsLimit !== undefined && results.length >= resultsLimit) break;
}
return results;
},
/*
=head3 C<geba(<tests:Object>, <startAt:Node>, <resultsLimit:integer>, <depthLimit:integer>)>
This function is an alias for C<getElementsByAttributes>.
=cut
*/
geba: DOM.Find.getElementsByAttributes
}
/*
=head1 AUTHOR
Daniel, Aquino <mr.danielaquino@gmail.com>.
=head1 COPYRIGHT
Copyright (c) 2007 Daniel Aquino.
Released under the Perl Licence:
http://dev.perl.org/licenses/
=cut
Creation Date Roughly: 07/10/06
Last Update: 1/06/07
*/