2012-04-30 14 views
14

¿Hay alguna manera de tener elementos DOM seleccionables a través de objetos?jquery usando objetos como filtros

Por ejemplo, yo quiero ser capaz de asociar objetos a los elementos DOM, así:

var obj = { a: 1, b:2 }; 
$('a').click(function() { this.selectThing = obj }); 

Y más adelante ...

$.something(obj); 

O aún mejor:

$('a|selectThing?=', obj); 

Algo así. Puede ver que quiero asociar un objeto a un elemento DOM de tal forma que pueda agarrar el elemento con el objeto.

Sé que esto se puede hacer con el método filter(), mi pregunta es si hay una manera más elegante que no usa filter() para hacer esto.

EDIT:

Para aclarar, yo quiero ser capaz de utilizar un objeto como una especie de selector, por lo que se puede hacer algo parecido a este $(obj) obviamente eso no va a funcionar, pero se obtiene la idea (espero)

editar # 2:

Quiero ser capaz de hacer algo como esto:

var obj = { prop: 'prop' }; 
$('a').bindTo(obj); 
$.retreive(obj) // should equal $('a') 

No quiero que altere obj de ninguna manera (obj debe seguir siendo {prop: 'prop'} solamente).

+0

¿Puede agregar un ejemplo del uso del método de filtro para lograr esto? No tengo idea de lo que intentas hacer de otra manera. – Esailija

+0

¿Marcó la respuesta que sugerí http://stackoverflow.com/questions/2891452/jquery-data-selector/2895933#2895933? – Meligy

+0

@MohamedMeligy: sí, pero una vez más eso no está utilizando un objeto en el selector, sino que está seleccionando con datos asociados con el elemento DOM en su lugar. – qwertymk

Respuesta

1

Extender jQuery con tres métodos:

jQuery.bindObj(data) 
jQuery.unbindObj(data) 
$.retrieve(data) 

Su código es el siguiente:

$('a').bindObj({blorg: 'shmorg'}); 
console.log($.retrieve({blorg: 'shmorg'})); // logs live result of $('a'); 

fuente completo: http://jsfiddle.net/nUUSV/6/.

El truco de esta solución es almacenar los selectores/identificadores basados ​​en el constructor jQuery en una matriz, y los objetos vinculados a esos selectores/identificadores en otra matriz, luego usando $.inArray para obtener el índice del objeto al recuperarlos y usando ese índice para tomar la colección jQuery encuadernada.

+0

Esto es lo que estaba buscando. Gracias – qwertymk

+0

Tenga en cuenta que el rendimiento de esto es significativamente peor que una simple búsqueda hash. –

2

Está buscando $.data. Este método asocia cualquier objeto o primitiva de JavaScript con un elemento DOM. Debajo del capó, no está agregando los datos como una expansión al elemento DOM o cualquier cosa, en cambio, jQuery mantiene su propio caché de objetos de elementos DOM y hashes de datos. Pero eso está bajo el capó; el punto es que creo que es exactamente lo que estás buscando.

$('#example').data('foo', { bar: 'quux' }); // returns the jquery object containing '#example', like most jQuery methods 

Luego, más tarde:

console.log($('#example').data('foo')); // returns {bar: 'quux'} 
+2

Esto no responde a la pregunta – qwertymk

8

demo

var $div1 = $('.box1'); 
var $div2 = $('.box2'); 
var obj = { a: $div1, b: $div2 }; 


obj.a.css({background:'red'}); 


O el camino corto: var obj = { a: $('.box1'), b: $('.box2') };


demo jsBin 2

var obj = $('.box1, .box2'); // store objects 
obj.css({background:'red'}); // access collection 
+1

+1 por ser la única respuesta que responde a la pregunta. – tobyodavies

+0

@tobyodavies: Estoy buscando una forma de usar un objeto para obtener un elemento, no guardar elementos en un objeto. Lo que quiero es similar a tener un selector que puede ser un objeto – qwertymk

+0

¿No es esta solución exactamente eso? El objeto no está realmente "guardando" elementos dentro de sí mismo, sino que el objeto contiene 2 objetos jquery que hacen referencia a elementos DOM. Si quiere hacer $ (obj), entonces obj debe ser una cadena con un selector de jquery. Supongo que ¿cuál es la naturaleza del objeto obj? Siempre puedes anular la función "toString" del objeto para imprimir un selector, supongo ... Todavía no estoy seguro de lo que estás tratando de hacer. Tal vez un poco de elaboración está en orden? – Kasapo

2

no creo que esto es fácilmente alcanzable. Permítanme aclarar:

Para lograr lo que desea, necesitaría un hashmap que permita objetos en la posición de las teclas. JavaScript no (todavía) admite objetos como claves en hashmaps.Así que, por ejemplo, lo siguiente no funciona:

var key = {value: 'key'}; 
var data {value: 'data'}; 
var map = {}; 

map[key] = data; 

Existen otras soluciones para lograr esto en las implementaciones de javascript actuales, por ej. una doble búsqueda:

var key = {value: 'key'}; 
var data {value: 'data'}; 
var map = { keys: [], data: [], get: function (key) { 
    var k = this.keys.indexOf(key); 
    if (k >= 0) { 
    return this.data[k]; 
    } else return undefined; 
}, set: function (key, val) { 
    var k = this.keys.indexOf(key); 
    if (k < 0) { 
    k = this.keys.push(k) - 1; 
    } 
    this.data[k] = val; 
} }; 

map.set(key, data); 
map.get(key).value; 

Sin embargo, esta implementación es de un rendimiento terrible. Hay una propuesta para el llamado WeakMap en JavaScript Harmony. Sin embargo, creo que Firefox es actualmente el único navegador que los implementa. Dado que la función requerida no está ampliamente disponible y las soluciones provisionales son de bajo rendimiento, recomendaría tratar de encontrar una forma diferente de lograr lo que está tratando de lograr.

1

Según tengo entendido, está buscando una manera sencilla de ejecutar múltiples búsquedas con nombre en el DOM y filtrar los resultados en un objeto de espacio de nombres.

Si es así, supongo que la siguiente extensión de jQuery podría ser atento a que:

$.fn.seek = function (selectors) { 
    var container = this, 
    found = {}; 

    $.each(selectors, function (name) { 
    if ($.isPlainObject(selectors[name])) { 
     found[name] = $(container).seek(selectors[name]); 
    } 
    else if ($.type(selectors[name]) === 'string') { 
     found[name] = $(container).find(selectors[name]); 
    } 
    }); 

    return found; 
} 

Y aquí está el ejemplo de cómo la extensión anterior podría ser aplicable a los casos:

var res = $('body').seek({ 
    links: 'a', 
    headers: 'h1,h2,h3,h4,h5,h6' 
}); 

$(res.links).css({ color: 'green' }); 
$(res.headers).css({ color: 'red' }); 

I Espero que esto te ayude.

1

No estoy seguro si esto es lo que está buscando. Tal vez podría escribir un selector personalizado basado en el selector de jquery, que maneja los objetos con una propiedad selector de la manera que desee. Un objeto seleccionable se vería

var objSelector = {'selector' : '#select-me', 'a' : 'somestring', 'b' : 1243}; 

lo que son libres de usarlo como cualquier otro objeto, pero hay que añadir la propiedad de selección. Que se agrega el selector personalizado:

$$ = (function($) { 
    return function(el, tag) { 
     if (typeof el === 'object' && el.selector !== undefined) { 
      return $(el.selector);     
     } 
     return $(el); 
    } 
}($)); 

Ahora usted puede hacer cosas como

$$(objSelector).css({'border':'1px solid red'}); 

Ver una implementación en http://jsfiddle.net/JXcnJ/

1

Si he entendido correctamente, entonces, creo que es necesario definir una propiedad y diga enumerable como falso. Véase más adelante,

Nota: abajo es sólo un ejemplo para demostrar y no precisamente la intención de hacer este tipo de cosas,

DEMO

$(function() { 

    $.fn.bindTo = function(o) { 
     var _that = this; 

     Object.defineProperty(o, 'myFx', { 
      value: function() { return $(_that); }, 
      writable: true, 
      enumerable: false, 
      configurable: true 
     }); 
    } 

    $.retrieve = function(obj) { 
     return obj.myFx(); 
    } 

    var obj = { 
     prop: 'prop' 
    }; 

    $('#test').bindTo(obj); 

    $($.retrieve(obj)).html('Test'); 

    //below is for proof 
    for (i in obj) { 
     alert(obj[i]); 
    } 
}); 

Referencia:http://yehudakatz.com/2011/08/12/understanding-prototypes-in-javascript/

Cuestiones relacionadas