Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jquery using objects as filters

Is there any way to have DOM elements selectable through objects?

For example I want to be able to associate objects to DOM elements like so:

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

And later on...

$.something(obj);

Or even better:

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

Something like that. You can see that I want to associate an object to a DOM element in such a way that I can grab the element with the object.

I know this can be done with the filter() method, my question is if there's a more elegant way that doesn't use filter() to do this.

EDIT:

To clarify, I want to be able to use an object kind of like a selector, so I can do something similar to this $(obj) obviously that won't work, but you get the idea (I hope)

EDIT #2:

I want to be able to do something like this:

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

I don't want it to alter obj in any way though (obj should still be {prop: 'prop'} only).

like image 625
qwertymk Avatar asked Apr 30 '12 00:04

qwertymk


People also ask

Can we apply filter on object?

JavaScript's Objects are not iterable like arrays or strings, so we can't make use of the filter() method directly on an Object .

How do we filter out elements using jQuery?

The filter() method returns elements that match a certain criteria. This method lets you specify a criteria. Elements that do not match the criteria are removed from the selection, and those that match will be returned. This method is often used to narrow down the search for an element in a group of selected elements.

How do you filter data objects?

One can use filter() function in JavaScript to filter the object array based on attributes. The filter() function will return a new array containing all the array elements that pass the given condition. If no elements pass the condition it returns an empty array.

How do you filter objects by key?

JavaScript objects don't have a filter() method, you must first turn the object into an array to use array's filter() method. You can use the Object. keys() function to convert the object's keys into an array, and accumulate the filtered keys into a new object using the reduce() function as shown below.


4 Answers

demo

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


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


Or the short way: var obj = { a: $('.box1'), b: $('.box2') };

demo jsBin 2

var obj = $('.box1, .box2'); // store objects
obj.css({background:'red'}); // access collection
like image 152
Roko C. Buljan Avatar answered Oct 20 '22 00:10

Roko C. Buljan


You're looking for $.data. This method associates any JavaScript object or primitive with a DOM element. Under the hood, it's not adding the data as an expando to the DOM element or anything--instead, jQuery maintains its own object cache of DOM elements and data hashes. But that's under the hood; the point is, I think it's exactly what you're looking for.

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

Then, later:

console.log($('#example').data('foo')); // returns {bar: 'quux'}
like image 32
zetlen Avatar answered Oct 19 '22 22:10

zetlen


I dont think this is easily achievable. Let me clarify:

To achieve what you want you would require a hashmap that allows objects in the position of keys. JavaScript does not (yet) support objects as keys in hashmaps though. So, for example, the following does not work:

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

map[key] = data;

There are other solutions to achieve this in current javascript implementations, eg. a double lookup:

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;

This implementation however is of a terrible performance. There is a proposal for a so called WeakMap in JavaScript Harmony. Firefox I believe is currently the only browser implementing them, though. Since the feature required is not widely available and workarounds are of poor performance I would recommend trying to figure out a different way of achieving what you are trying to.

like image 27
Daniel Baulig Avatar answered Oct 19 '22 22:10

Daniel Baulig


Extend jQuery with three methods:

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

Your code looks like:

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

Full source: http://jsfiddle.net/nUUSV/6/.

The trick to this solution is storing the selectors/identifiers based to the jQuery constructor in one array, and the objects bound to those selectors/identifiers in another array, then using $.inArray to get the index of the object upon retrieval and using that index to grab the bound jQuery collection.

like image 45
benastan Avatar answered Oct 20 '22 00:10

benastan