#javascript #arrays
#javascript #массивы
Вопрос:
Пожалуйста, помогите мне найти решение, которое использует обычный javascript (я не могу использовать внешние фреймворки). Кроме того, CSS: указатель наведения не будет работать для реализации в реальном мире.
Что-то, происходящее с зарегистрированным событием, устанавливает все вызовы последнего элемента массива зарегистрированных событий.
<body>
<p>When you hover over amp;<divamp;> tags 0-2, that amp;<divamp;> tag should highlight in red. Why do all of the amp;<divamp;> tags only affect the last amp;<divamp;>?</p>
<div class="test"></div>
<div class="test"></div>
<div class="test"></div>
<p>The same results for amp;<pamp;> tags.</p>
<p class="test"></p>
<p class="test"></p>
<p class="test"></p>
<script type="text/javascript">
//create arrays
var divArr = new Array();
var pArr = new Array();
//call function to populate arrays
divArr = getElementsByClassName('div','test');
pArr = getElementsByClassName('p','test');
//call function to register arrays elements events
registerArrayElementsEvents(divArr,'div');
registerArrayElementsEvents(pArr,'p');
//retrieve elements that match the passed tag and class
function getElementsByClassName(myTag,myClass) {
//load all elements into array
var elems = document.getElementsByTagName(myTag);
//create new array placeholder
var newArr = new Array();
//iterate through elements array
for (var i = 0; i < elems.length; i ) {
//check to see if element class matches parameter
if (elems[i].className == myClass){
//add matched element to new array
newArr.push(elems[i]);
}
}
//return array of matched elements
return newArr;
}
//register events to every element in the passed array
function registerArrayElementsEvents(arr,type){
//create object placeholder
var currentObj = new Object();
//iterate through the objects array
for (var i = 0; i < arr.length; i ) {
//assign current object corresponding to loop counter
currentObj = arr[i];
//write element index to element
currentObj.innerHTML = 'This is amp;<' type 'amp;> ' i;
//add mouseover event to element
addEvent(currentObj,'mouseover',function(){
//set current element color to red
currentObj.style.color = '#f00'
});
//add mouseout event to element
addEvent(currentObj,'mouseout',function(){
//set current element color to black
currentObj.style.color = '#000'
});
}
}
//register functions to events for objects
function addEvent(obj,evt,fn){
//if not IE
if (obj.addEventListener)
obj.addEventListener(evt,fn,false);
//if IE
else if (obj.attachEvent)
obj.attachEvent('on' evt,fn);
}
</script>
</body>
Комментарии:
1. Во-первых, будьте вежливы, когда просите о помощи, во-вторых, задавайте актуальный вопрос, а не расплывчатое «что-то происходит». Если у вас есть ограничения, укажите их.
2. Честно говоря, я не понимаю, почему вы не можете использовать jQuery. В наши дни это практически обязательно для разработки Javascript (или, по крайней мере, эквивалента jQuery)
3. @Codemonkey — Я бы поставил вам 1, но я не могу найти плагин jQuery для этого…
4. У вас проблемы с замыканиями, см., например mennovanslooten.nl/blog/post/62
5. @Codemonkey Я ненавижу тебя за то, что ты это говоришь. Это неправильно не только в корне, но и идеологически. JQUERY — ЭТО НЕ ОЧЕНЬ ХОРОШИЙ КОД. Это минималистичная ОБОЛОЧКА на JavaScript для любителей скриптов, которые не могут написать свои собственные. jQuery способствует плохому программированию. БУДЬТЕ ОСТОРОЖНЫ.
Ответ №1:
Происходит то, что область действия currentObj
in registerArrayElementsEvents
ограничена registerArrayElementsEvents
, а не функцией каждого события. Вам нужно поместить currentObj
в область видимости каждой функции следующим образом:
addEvent(currentObj, 'mouseover', (function (obj) {
return function () {
obj.style.color = '#f00';
};
})(currentObj));
В принципе, JavaScript определяет области видимости только на основе функций, а не блоков. Это означает, что
for (...) { var x = arr[i] }
точно такой же, как:
var x;
for (...) {x = arr[i]}
Это означает, что после завершения цикла x
устанавливается на последний элемент массива. Если вы ссылаетесь x
на функцию, когда она переходит к поиску x
после завершения цикла (например, после события), она получает самое новое значение x
. Чтобы преодолеть это, вы можете создавать замыкание каждый раз при выполнении цикла, используя анонимную функцию, как это сделал я.
Ответ №2:
//create arrays
var divArr = new Array();
var pArr = new Array();
//call function to populate arrays
divArr = getElementsByClassName('div','test');
pArr = getElementsByClassName('p','test');
Присваивая новые значения divArr
и pArr
, вы перезаписываете массивы, назначенные изначально. Это не ваша проблема, это просто означает, что исходное назначение бесполезно.
У ТИхона есть один ответ, другой способ — избежать закрытия с помощью this
:
addEvent(currentObj, 'mouseover', function () {
this.style.color = '#f00';
});
но вам придется изменить addEvent
функцию для того, чтобы attachEvent
правильно установить this
so. Я добавлю это в ближайшее время…