Jquery с использованием объектов в качестве фильтров
Есть ли способ выбрать элементы DOM через объекты?
Например, я хочу иметь возможность связывать объекты с элементами DOM следующим образом:
var obj = { a: 1, b:2 };
$('a').click(function() { this.selectThing = obj });
И позже...
$.something(obj);
Или даже лучше:
$('a|selectThing?=', obj);
Что-то вроде этого. Вы можете видеть, что я хочу связать объект с элементом DOM таким образом, чтобы я мог захватить элемент с объектом.
Я знаю, что это можно сделать с помощью метода filter()
, мой вопрос в том, есть ли более элегантный способ, который не использует filter()
для этого.
EDIT:
Чтобы уточнить, я хочу использовать объект типа типа селектора, поэтому я могу сделать что-то похожее на это $(obj)
, очевидно, что это не сработает, но вы получите идею (надеюсь)
ИЗМЕНИТЬ № 2:
Я хочу сделать что-то вроде этого:
var obj = { prop: 'prop' };
$('a').bindTo(obj);
$.retreive(obj) // should equal $('a')
Я не хочу, чтобы он менял obj
каким-либо образом, хотя (obj
должен быть только {prop: 'prop'}
).
Ответы
Ответ 1
Расширьте jQuery тремя способами:
jQuery.bindObj(data)
jQuery.unbindObj(data)
$.retrieve(data)
Ваш код выглядит так:
$('a').bindObj({blorg: 'shmorg'});
console.log($.retrieve({blorg: 'shmorg'})); // logs live result of $('a');
Полный источник: http://jsfiddle.net/nUUSV/6/.
Уловкой для этого решения является хранение селекторов/идентификаторов, основанных на конструкторе jQuery в одном массиве, и объекты, привязанные к этим селекторам/идентификаторам в другом массиве, а затем используя $.inArray
, чтобы получить индекс объекта после извлечения и используя этот индекс для захвата связанной коллекции jQuery.
Ответ 2
var $div1 = $('.box1');
var $div2 = $('.box2');
var obj = { a: $div1, b: $div2 };
obj.a.css({background:'red'});
Или короткий путь: var obj = { a: $('.box1'), b: $('.box2') };
var obj = $('.box1, .box2'); // store objects
obj.css({background:'red'}); // access collection
Ответ 3
Вы ищете $.data
. Этот метод связывает любой объект JavaScript или примитив с элементом DOM. Под капотом он не добавляет данные в качестве expando в элемент DOM или что-то еще - вместо этого jQuery поддерживает свой собственный кеш объектов DOM-элементов и хэшей данных. Но это под капотом; Дело в том, что я думаю, это именно то, что вы ищете.
$('#example').data('foo', { bar: 'quux' }); // returns the jquery object containing '#example', like most jQuery methods
Затем, позже:
console.log($('#example').data('foo')); // returns {bar: 'quux'}
Ответ 4
Я не думаю, что это легко достижимо. Позвольте пояснить:
Для достижения желаемого вам понадобится хэш-карта, которая позволяет объекты в позиции клавиш. Однако JavaScript не поддерживает объекты как ключи в хэшмапах. Так, например, следующее не работает:
var key = {value: 'key'};
var data {value: 'data'};
var map = {};
map[key] = data;
В существующих реализациях javascript есть другие решения, например. двойной поиск:
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;
Эта реализация, однако, имеет ужасную производительность. В JavaScript Harmony есть предложение для так называемого WeakMap. Firefox, я считаю, в настоящее время является единственным браузером, реализующим их. Поскольку требуемая функция не является широко доступной, и обходные решения имеют низкую производительность, я бы рекомендовал попытаться выяснить другой способ достижения того, что вы пытаетесь сделать.
Ответ 5
Как я понимаю, вы ищете какой-то сахарный способ запуска нескольких именованных поисков в DOM и результаты отфильтровываются в объекте пространства имен.
Если это так, я думаю, для вас может быть полезно следующее расширение jquery:
$.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;
}
И вот пример того, как указанное расширение может быть применимо к вашим случаям:
var res = $('body').seek({
links: 'a',
headers: 'h1,h2,h3,h4,h5,h6'
});
$(res.links).css({ color: 'green' });
$(res.headers).css({ color: 'red' });
Надеюсь, это поможет вам.
Ответ 6
Не уверен, что это то, что вы ищете. Возможно, вы можете написать пользовательский селектор, основанный на селекторе jquery, который обрабатывает объекты с помощью свойства selector, как вам нравится. Выбираемый объект будет выглядеть как
var objSelector = {'selector' : '#select-me', 'a' : 'somestring', 'b' : 1243};
Таким образом, вы можете использовать его как любой другой объект, но вам нужно добавить свойство selector. Чем вы добавляете свой пользовательский селектор:
$$ = (function($) {
return function(el, tag) {
if (typeof el === 'object' && el.selector !== undefined) {
return $(el.selector);
}
return $(el);
}
}($));
Теперь вы можете делать что-то вроде
$$(objSelector).css({'border':'1px solid red'});
См. реализацию на http://jsfiddle.net/JXcnJ/
Ответ 7
Если я правильно понял, я думаю, вам нужно определить свойство и сказать enumerable
как false. См. Ниже,
Примечание: Ниже приведен пример, демонстрирующий и не предназначенный для этого,
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]);
}
});
Ссылка: http://yehudakatz.com/2011/08/12/understanding-prototypes-in-javascript/