Как записать все елементы в массив, чтобы потом применить ко всем сразу событие?
Как записать все элементы в массив (или объект), чтобы потом применить ко всем ним какое-нибудь событие?
Т.е. нужно что-то навроде 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,
Есть Вариант отслеживания событий на общем родителе, с последующим определением элемена клика |
Цитата:
|
А почему так не выходит?
<div id="id1">id1</div><div id="id2">id2</div> <script> alert(document.getElementById("id1","id2").innerHTML); </script> |
Потому что так сделали
|
Цитата:
|
Спасибо за ответ. Думаю попробовать с помощью 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 объектом и массивом состоящим из тех же элементов? |
Цитата:
в forEach примерно такой код: for (var i = 0; i < this.length; i++) { callback( this[i], i, this ); } Цитата:
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]); |
мы не телепаты. Учитесь пользоваться консолью.
|
Да нет все работает. Просто я не понимаю принцип работы кода.
|
|
Да и от 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.querySelectorAll(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. |
Цитата:
Цитата:
Цитата:
кроме того, 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/.../Function/bind есть ещё костыль для bind (в разделе Compatibility). |
Большое всем спасибо, буду разбираться.
|
Интерестно, а foreach какие версии браузеров поддерживают?
|
Часовой пояс GMT +3, время: 11:03. |