Просмотр полной версии : Как записать все елементы в массив, чтобы потом применить ко всем сразу событие?
Как записать все элементы в массив (или объект), чтобы потом применить ко всем ним какое-нибудь событие?
Т.е. нужно что-то навроде
var masel = [];
masel[1] = document.getElementById("id1");
masel[2] = document.getElementById("id2");
masel["onclick"] = function.....
for (var i = 1, m = masel.length; i < m; i++) {
masel[i].onclick = ..............
}
Спасибо за ответ. А сразу ко всем никак нельзя? Получается, что мне в каждом методе необходимо сделать цикл.
platedz,
Есть Вариант отслеживания событий на общем родителе, с последующим определением элемена клика
Спасибо за ответ. А сразу ко всем никак нельзя? Получается, что мне в каждом методе необходимо сделать цикл.
http://learn.javascript.ru/event-delegation
А почему так не выходит?
<div id="id1">id1</div><div id="id2">id2</div>
<script> alert(document.getElementById("id1","id2").innerHTML); </script>
А почему так не выходит?
<div id="id1">id1</div><div id="id2">id2</div>
<script> alert(document.getElementById("id1","id2").innerHTML); </script>
Функция document.getElementById принимает только 1 параметр.
Спасибо за ответ. Думаю попробовать с помощью elem.querySelectorAll(css). Вроде написано что ie8 он поддерживает, а на более низкие я уже особо не ориентируюсь.
Если я правильно понимаю, при делегировании событий идет обход всех дочерних элементов начиная с текущего, пока он не достигнет установленного родителя.
Т.е. чтобы обратиться к любому элементу на странице мне необходимо по идее записывать или document.onclick = function(){и здесь осуществлять проверку на то, произошло ли данное событие на нужном мне элементе}
Я верно понимаю.
platedz,
лучше делегировать с ближайшей обертки всех этих элементов (или создатьеё спецом
Смысл в том, чтобы к массиву элементов применить какое-нибудь одно действие.
Т.е. чтобы при нажатии на id1,id2 или id3, выполнялась какая-нибудь одна фукнция, а один точнее метод.
topmenu = (function(window) {
var elements = {};
return {
Sattr: function(name)
{
try{ elements = document.querySelectorAll(name);}catch(e){}
return this;
},
functio: function()
{
for(var i = 0; i<elements.length;i++) elements[i].parentNode.removeChild(elements[i]);
return this;
}
}
}(window));
topmenu.Sattr(".eror").functio();
Сейчас получается так, что к в каждом методе мне необходимо сделать цикл, что как-то очень неудобно. Может есть какой-то способ сделать так, чтобы применяемый метод вызывался для каждого элемента массива. Может через функцию внутри метода, или какой-нибудь калбек. Или еще как?
Можно сделать через встроенный метод Array.prototype.forEach (правда, не для IE<9):
topmenu = (function(window) {
var elements = {};
return {
Sattr: function(name)
{
try{ elements = document.querySelectorAll(name);}catch(e){}
return this;
},
functio: function () {
Array.prototype.forEach.call(elements, function(v)
{
v.parentNode.removeChild(v);
});
return this;
}
}
}(window));
topmenu.Sattr(".eror").functio();
Спасибо за ответ. Но я так понимаю, разницы особой нет. Array.prototype.forEach нужно добавлять в каждый объект.
Хотелось чтобы это было както так
element(element).parentNode.removeChild(element(el ement));
или так
element.functio : function(){....}
или так
for() return{
......
}
Или я не знаю как. Как-то чтобы не писать цикл в каждом методе.
Может Sattr вынести куда-то и как-то по другому обратиться к объекту.
В моём примере ведь не используется цикл, только функция в качестве аргумента к Array.prototype.forEach.call. Если это писать долго, можно поставить этот forEach в NodeList.prototype:
NodeList.prototype.forEach=Array.prototype.forEach ;
...
functio: function () {
elements.forEach(function(v)
{
v.parentNode.removeChild(v);
});
return this;
}
Спасибо за пример. Я в основном писал на jquery, сейчас стараюсь отходить и больше писать на чистом javascript.
К сожалению опп у меня хромает, а с прототипами и вовсе плохо. Поэтому Ваш пример мне не до конца понятен, из-за плохого понимания прототипов.
В любом случае, в нем используется перебор, хоть и в виде метода, forEach - это ведь по большому счету то же цикл.
В общем-то это не главное. Главное, что этот перебор необходимо вставлять в каждый метод. Т.е. в каждом методе делать обертку ....какой_то_перебор {а тут уже сама функция}.
Я хочу избавиться непосредственно от вложенности, т.к. везде приходится делать примерно так
method: function(){
try{
for(){
и только тут уже сама функция.
}
}
}
Хотелось бы вынести перебор в отдельное место, или применить ко всем методам сразу.
Есди я правильно понял, нужно избавиться от лишнего уровня вложенности. Тогда можно так:
topmenu = (function(window) {
var elements = {};
var result={
functio: function (el) {
el.parentNode.removeChild(el);
},
//...
};
function f(callback) {
Array.prototype.forEach.call(elements, callback);
return this;
}
for (var method in result)
result[method]=f.bind(topmenu, result[method]);
result.Sattr=function(name)
{
try{ elements = document.querySelectorAll(name);}catch(e){}
return this;
},
return result;
}(window));
topmenu.Sattr(".eror").functio();
Спасибо, по идее то, что надо, но у меня не работает. А самое обидное, что я его почти не понимаю.
А самое обидное, что я его почти не понимаю.
Какую именно строчку вы не понимаете?
Array.prototype.forEach.call(elements, callback);
Вот эта больше всего.
for (var method in result)
result[method]=f.bind(topmenu, result[method]);
И эта тоже не очень понятна
Вообще я сделал так
topmenu= (function(window) {
var elements = {};
var result={
functio: function () {
alert(elements);
}
};
function f(callback) {
Array.prototype.forEach.call(elements, callback);
return this;
}
for (var method in result)
result[method]=f.bind(topmenu, result[method]);
result.Sattr=function(name)
{
try{ elements = document.querySelectorAll(name);}catch(e){}
return this;
},
return result;
}(window));
topmenu.Sattr("div").functio();
Т.е. получается нужно сделать так чтобы functio вывела столько alert(элемент), сколько элементов.
Если бы код работал, то было бы проще его разобрать, а так я даже не понимаю где ошибка?
Нужно писать вместо
functio: function () {
alert(elements);
}
так:
functio: function (el) {
alert(el);
}
Спасибо за ответ.
но
Так тоже не работает
topmenu = (function(window) {
var elements = {};
var result={
functio: function (elements) {
alert(elements);
}
};
function f(callback) {
Array.prototype.forEach.call(elements, callback);
return this;
}
for (var method in result)
result[method]=f.bind(topmenu, result[method]);
result.Sattr=function(name)
{
try{ elements = document.querySelectorAll(name);}catch(e){}
return this;
},
return result;
}(window));
topmenu.Sattr("div").functio();
Извиняюсь, я не раньше не тестировал этот код, а сейчас сделал это и оказались 2 ошибки:
1) запятая вместо точки запятой в 20-й строчке;
2) обращение к переменной topmenu идёт перед тем, как её определили (если вы её в другом месте не определили).
Так уже работает:
<!DOCTYPE html>
<html><head>
<meta http-equiv="Content-Type" content="application/xhtml+xml;charset=UTF-8" /><title></title>
</head>
<body>
<div></div>
<div></div>
<script>
var topmenu = (function(window) {
var elements = {};
var result={
functio: function (elements) {
alert(elements);
}
};
function f(callback) {
Array.prototype.forEach.call(elements, callback);
return this;
}
for (var method in result)
result[method]=f.bind(result, result[method]);
result.Sattr=function(name)
{
try{ elements = document.querySelectorAll(name);}catch(e){}
return this;
};
return result;
}(window));
topmenu.Sattr("div").functio();
</script>
</body>
</html>
Спасибо большое. Буду разбираться. Еще бы от bind избавиться, раз он только под ie9. Читал, что его можно эмулировать, но пока не пробовал.
Объясните пожалуйста, чем отличается эта запись
Array.prototype.forEach.call(elements, function(item){ alert(item); });
от этой
elements.forEach(function(item){ alert(item); });
Последняя возвращает
Object #<NodeList> has no method 'forEach'
потому что это разные типы.
Array и NodeList.
они имеют сходства внешне, но внутренне они различны.
Спасибо за пояснение, но можно как-то поподробнее.
Насколько я понимаю forEach работает только с массивами.
При этом используя конструкцию Array.prototype мы преобразуем объект NodeList в массив. При этом не очень понятно, что же происходит на самом деле, и вообще очень плохо понимаю прототипы и как они работают.
И есть ли какая-нибудь разница между NodeList объектом и массивом состоящим из тех же элементов?
Array.prototype мы преобразуем объект NodeList в массив
нет. мы просто заимствуем метод у массива. А т.к. у NodeList есть свойство length, да и свойства пронумерованы от нуля, то forEach схавает его, как массив.
в forEach примерно такой код:
for (var i = 0; i < this.length; i++) {
callback( this[i], i, this );
}
И есть ли какая-нибудь разница между NodeList объектом и массивом состоящим из тех же элементов
да - nodeList живой.
http://habrahabr.ru/post/121803/#comment_3985850
Спасибо за пояснение.
Вышеуказанный код заработал, но я так и не смог разобраться чтоже в нем все-таки происходит.
Особенно интересуют следующая часть кода
function f(callback) {
Array.prototype.forEach.call(elements, callback);
return this;
}
for (var method in result)
result[method]=f.bind(result, result[method]);
Больше всего мне непонятно, что же происходит здесь, и как после всего этого выглядит result в итоге
for (var method in result)
result[method]=f.bind(result, result[method]);
мы не телепаты. Учитесь пользоваться консолью.
Да нет все работает. Просто я не понимаю принцип работы кода.
http://es5.javascript.ru/x15.3.html#x15.3.4.5
Да и от bind не мешало бы избавиться, т.к. тогда весь код не будет работать в ie8
Немного переделал так
var topmenu= (function(window) {
var elements = [];
var result={
functio: function () {
alert(arguments[0].innerHTML);
}
};
function f(callback) {
elements.forEach(callback);
return this;
}
for (var method in result)
result[method]=f.bind(result, result[method]);
result.Sattr=function(name)
{
try{ elements = Array.prototype.slice.apply(document.querySelector All(name));}catch(e){}
return this;
};
return result;
}(window));
topmenu.Sattr("div").functio().functio();
Сложнее всего до моего понимания доходит эта строка
for (var method in result) result[method]=f.bind(result, result[method]);
Насколько я понимаю,
1) мы передаем текущий объект в функцию f
2) в ней через foreach применяем к каждому отдельному элементу массива callback, которым является каждый метод текущего объекта т.е. result[method]
При этом мне вовсе не яcно, как функция вообще получает elements. Т.к. попытка вызвать его вне метода не дает результата.
Т.е. если перед циклом for поставить alert(elements.length); толку не будет.
Что как бы говорит о том, что все указанные действия вне методов вызываются либо сразу, либо при каждом обращении к объекту через его метод.
Кроме прочего насколько я понимаю bind - это своего рода внутренняя функция, которую можно повторить и в устаревших браузерах.
В общем, второй день сижу, пытаясь разобраться, что да как, запутался уже. Помогите, пожалуйста, разобраться, и заодно симулировать bind.
1) мы передаем текущий объект в функцию f
текущий объект - это this. а в коде передаётся result.
При этом мне вовсе не яcно, как функция вообще получает elements. Т.к. попытка вызвать его вне метода не дает результата.
посредством замыкания.
Кроме прочего насколько я понимаю bind - это своего рода внутренняя функция, которую можно повторить и в устаревших браузерах.
функция, которая имеет примерно такой код (словами объяснять долго):
кроме того, bind имеет некоторые особенности, которые не реализуемы посредством JavaScript (другими словами, полного костыля не получится создать.).. об особенностях посмотрите в интернете.
/* ---------- ОПИСАНИЕ ---------- */
Function.prototype._bind = function (context /*, arg0, arg1, ... argN */) {
// сохраним переданные аргументы в замыкании. Именно "1", потому что нулевой элемент - контекст.
var args = Array.prototype.slice.call(arguments, 1);
// сохраним текущую функцию в замыкании, ибо ...
var func = this;
// ... в этой функции this уже будет window (по-умолчанию, во всех функциях так).
return function () {
// преобразуем объект текущих аргументов в массив
var newArgs = Array.prototype.slice.call(arguments);
// добавим к переданным вначале аргументам переданные сейчас.
newArgs = args.concat(newArgs);
// и вызовем apply, передав контекст, и аргументы.
func.apply( context, newArgs );
};
};
/* ---------- ТЕСТИРОВАНИЕ ---------- */
// функция просто выведет алертом свойство "FOO" своего контекста, добавив к нему первый аргумент, и второй.
// this сейчас равен window (по-умолчанию).
var test = function (first, second) { alert( this.FOO + first + second ); };
// объект со свойством "FOO"
var obj = { "FOO": "Hello" };
// применим связывание.
// this в test_binded будет равен obj.
// а первый аргумент ( first в функции "test" ) будет равен строке ", "
var test_binded = test._bind( obj, ", " );
// вызовем связанную функцию, передав ей ещё один аргумент ( это уже будет "second" )
test_binded( "World!" );
// Связывание и вызов связанной функции аналогичны этой строке :
test.call( obj, ", ", "World!" );
melky,
спасибо. Здесь https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Function/bind есть ещё костыль для bind (в разделе Compatibility).
Большое всем спасибо, буду разбираться.
Интерестно, а foreach какие версии браузеров поддерживают?
Кстати, вот хорошая ссылка по прототипам. Помогла мне разобраться. http://habrahabr.ru/post/120193/
vBulletin® v3.6.7, Copyright ©2000-2025, Jelsoft Enterprises Ltd. Перевод: zCarot