Jquery Selectors For Plain Javascript Objects Instead Of Dom Elements
Solution 1:
Here's a proof-of-concept implementation for getting jQuery itself work on objects. Through an object wrapper (FakeNode
), you can trick jQuery into using its built-in selector engine (Sizzle) on plain JavaScript objects:
functionFakeNode(obj, name, parent) {
this.obj = obj;
this.nodeName = name;
this.nodeType = name ? 1 : 9; // element or documentthis.parentNode = parent;
}
FakeNode.prototype = {
documentElement: { nodeName: "fake" },
getElementsByTagName: function (tagName) {
var nodes = [];
for (var p inthis.obj) {
var node = newFakeNode(this.obj[p], p, this);
if (p === tagName) {
nodes.push(node);
}
Array.prototype.push.apply(nodes,
node.getElementsByTagName(tagName));
}
return nodes;
}
};
function$$(sel, context) {
return $(sel, newFakeNode(context));
}
And the usage would be:
var obj = {
foo: 1,
bar: 2,
child: {
baz: [ 3, 4, 5 ],
bar: {
bar: 3
}
}
};
functiontest(selector) {
document.write("Selector: " + selector + "<br>");
$$(selector, obj).each(function () {
document.write("- Found: " + this.obj + "<br>");
});
}
test("child baz");
test("bar");
Giving the output:
Selector: child baz - Found: 3,4,5 Selector: bar - Found: 2 - Found: [object Object] - Found: 3
Of course, you'd have to implement a lot more than the above to support more complex selectors.
BTW, have you seen jLinq?
Solution 2:
The array object has some methods that you can use:
last = obj.child.baz.slice(-1)[0];
Some other examples:
first = obj.child.baz.slice(0,1)[0];allExceptFirst = obj.child.baz.slice(1);allExceptLast = obj.child.baz.(0,-1);
Solution 3:
Well, I'd personally say that pure object access looks better than jQuery-like queries. One thing that would be neat would be slicing and other filtering techniques.
If you really wanted to play with object access queries, the following would be some possibilities (think XPath):
var obj = {
foo: 1,
bar: 2,
child: {
foo: {
baz: [3, {a: 1}, {a: 2, b: 3}]},
bar: {
baz: [42, {a: 123}, {a: -1}]},
baz: null}};
// Implicitly start in the Global object, unless a context is provided.// Keys in JavaScript objects are essentially stored in order (not valid for// *all* flavors, but it's close to standard. So you could do slicing on keys.)// Selects (does not return them)// obj.child.foo.baz[1].a// obj.child.foo.baz[2].a// obj.child.bar.baz[1].a// obj.child.bar.baz[2].a// Then performs an aggregate that returns value 125.
$('obj.child[:2].baz[1:].a').sum()
// Selects obj.foo, obj.bar, obj.child.foo.baz[0] and obj.child.bar.baz[0]
$('obj *[typeof(number)]')
// Selects obj.foo and obj.child.foo
$('obj foo')
// Other possible methods: delete(), set(), get() (as an array of values),// min(), max(), avg(), merge() etc etc.
In the end though, I don't see how this is very useful. But eh, it's an idea I guess =)
Solution 4:
simplest and easiest way is to wrap the element with jquery and then loop it by each
var obj = { 'foo': 1, 'bar': 2,
'child': { 'baz': [3, 4, 5] }
};
$(obj).each(function(){
console.log(this);
if(this.hasOwnProperty('foo'))
{
console.log("hey i found " + this.foo );
}
});
Post a Comment for "Jquery Selectors For Plain Javascript Objects Instead Of Dom Elements"