Contenido

Añadiendo xPath a $()

11 Dic

+ 1

Considero que $() es la función más interesante de Javascript ya que en ella se han volcado las más grandes librerías con tal de conseguir una función potente y flexible. Actualmente jQuery dispone de una versión con xPath bastante elegante, lo cual te permite seleccionar elementos del DOM mediante una simple expresión xPath.

La función

Si vemos la función $() genérica, vemos que nos permite solicitar N argumentos y que en cada uno de ellos comprobamos si se trata de un String o no.

function $() {
	var elements = new Array();
	for (var i = 0; i < arguments.length; i++) {
		var element = arguments[i];
		if (typeof element == 'string')
			element = document.getElementById(element);
		if (arguments.length == 1)
			return element;
		elements.push(element);
	}
	return elements;
}

Aprovechando esta base, vamos a comprobar si lo que estamos pasando es el  ID de un elemento o una expresión xPath. Para esta función que está destinada a devolvernos los objetos solicitados de dentro del arbol DOM de nuestra página, useré document como nodo padre y la expresión comenzará como (//) que nos indica un descenso recursivo.


function $() {
	var elements = new Array();
	for (var i = 0; i < arguments.length; i++) {
		var element = arguments[i];
		if (typeof element == 'string') {
			if(element.substring(0,2) =='//') { //xPath
				var iterator = document.evaluate(element, document, null, XPathResult.ANY_TYPE, null );
				try {
				  while (thisNode = iterator.iterateNext())
					elements.push(thisNode);
				} catch (e) {
				   throw 'Error: Document tree modified during iteraton ' + e ;
				}
			} else { //ID
				element = document.getElementById(element);
				if (arguments.length == 1) return element;
				else elements.push(element);
			}
		} else {
			elements.push(element);
		}
	}
	return elements;
}

Ahora tenemos una función $() que nos permite obtener cualquier elemento directamente mediante su ID, además de cualquier otro elemento dado una expresión xPath. De esta forma podemos recuperar por ejemplo.


var negrita = $('//p[@class="negrita"]'); // Todos los párrafos con class "negrita"
var wikipedia = $(//a[contains(@href ,"wikipedia")]); // Todos los enlaces hacia la wikipedia.

Tambien podemos hacer algo muy elegante, práctico y cómodo como añadir al todos los elementos de la página, una nueva funcionalidad que llamaremos xpath, con la cual podremos buscar a partir de él y sobre su descendecia. Para ello había pensado usar el objeto Object, y ampliarlo mediante prototype, pero en IE no funcionó, así que me fui a la especificación y encontré HTMLElement que viene a ser el padre de todos los elementos que nos encontramos en la página, pero en IE siguió son funcionar y eso que es del DOM Level 1 del año 1998… Así que vosotros mismos. 

Para el objeto Object 


Object.prototype.xpath = function() {
	var elements = new Array();
		for (var i = 0; i < arguments.length; i++) {
			alert(arguments[i]);
			var iterator = document.evaluate(arguments[i], this, null, XPathResult.ANY_TYPE, null );
				try {
				  while (thisNode = iterator.iterateNext())
					elements.push(thisNode);
				} catch (e) {
				   throw 'Error: Document tree modified during iteraton ' + e ;
				}	
		}
		return elements;
}

Para el objeto HTMLElements 


HTMLElements.prototype.xpath = function() {
	var elements = new Array();
		for (var i = 0; i < arguments.length; i++) {
			alert(arguments[i]);
			var iterator = document.evaluate(arguments[i], this, null, XPathResult.ANY_TYPE, null );
				try {
				  while (thisNode = iterator.iterateNext())
					elements.push(thisNode);
				} catch (e) {
				   throw 'Error: Document tree modified during iteraton ' + e ;
				}	
		}
		return elements;
}

Modo de empleo

Sin importar el objeto que tenga la funcionalidad, usaremos el método de la siguiente forma:


var parrafo = document.getElementById("id_de_mi_parrafo");
var enlaces = parrafo.xpath("//a"); //Me encontrará todos los enlaces dentro de id_de_mi_parrafo.

for(var x=0; x

Comentar

#

Me reservo el derecho de eliminar y/o modificar los comentarios que contengan lenguaje inapropiado, spam u otras conductas no apropiadas en una comunidad civilizada. Si tu comentario no aparece, puede ser que akismet lo haya capturado, cada día lo reviso y lo coloco en su lugar. Siento las molestias.