Событие OnMouseOver и сохранение значений переменных

0

Я динамически генерирую таблицу HTML с использованием JavaScript. Один из столбцов таблицы содержит событие onmouseover, и когда курсор мыши находится над определенной ячейкой, я хочу отображать информацию, относящуюся к ячейке.

В моем случае я хочу показать значение nPos через вызов alert() как это было во время построения таблицы.

Упрощенный пример создания моей таблицы:

for (var iLoop = 0 ; iLoop < nHitsPerPage ; iLoop++) {
    var nPos = (nCurrentPageParam * SearchResults.nMaximumHitsPage) + iLoop;

    //...

    var cellInfo = tableResultsRow.insertCell(6);

    //...

    cellInfo.className = "noWrapCell";
    cellInfo.innerHTML = "?";
    cellInfo.style.cursor = "pointer";

    // The line below is important - I need to store nPos value during the table consturction
    cellInfo.onmouseover = function(){alert("nPos = " + nPos)};
    cellInfo.onmousemove = function(){FileResort.LightboxShortInfo.update(event)};
    cellInfo.onmouseout = function(){FileResort.LightboxShortInfo.hide(event)};
}

Как вы можете видеть из приведенного выше примера, я итеративно создал таблицу внутри цикла for(). Я хочу сохранить значение nPos в каждой строке (записи), которая отличается для каждой строки (записи).

Моя проблема заключается в том, что, как только я навешиваю эту конкретную ячейку, я получаю одно и то же значение nPos для каждой строки (записи), а nPos - текущее значение nPos в конкретном состоянии приложения.

Я не могу найти способ записи значения nPos как это было во время выполнения for(), что важно для меня при определении того, какая запись хранится в конкретной строке.

Есть ли способ захватить или сохранить значение nPos для каждой строки (записи) во время начальной конструкции таблицы?

Теги:
javascript-events

2 ответа

1
Лучший ответ

Вы еще одна жертва закрывающего монстра :)

Посмотри на это:

cellInfo.onmouseover = function(){alert("nPos = " + nPos)};

функция здесь - пусть назовет ее lambda - придется найти значение переменной nPos. Поскольку nPos не объявляется внутри lambda, он будет искать его в функции верхнего уровня, то есть в функции, где создается nPos.

Когда произойдет событие mouseover, код, который объявляет и устанавливает nPos, уже будет запущен, поэтому nPos будет иметь значение nHitsPerPage.

Именно это отобразит lambda. К сожалению, это не то, что вы хотите :).


Чтобы преодолеть это, вам нужно создать (лексическое) закрытие, то есть предоставить lambda значение nPos которое соответствует вашим потребностям.

Способ сделать это в Javascript выглядит следующим образом:

cellInfo.onmouseover = function(p){
    return function () { alert("nPos = " + p)};
    } (nPos);

позвоните nu новой функции (той, которая принимает p как параметр). Мы изменили lambda так что теперь она относится к p вместо nPos.

Это означает, что когда событие mouseover будет срабатывать, lambda будет искать p в своей верхней функции, которая теперь равна nu. И он действительно найдет p там, как параметр nu.

p - параметр функции, поэтому он получает копию nPos в момент ее nPos. Это означает, что lambda будет ссылаться на другой экземпляр контекста вызова nu для каждого экземпляра cellInfo.

Каждый экземпляр обработчика события mouseover теперь будет содержать копию p которая установлена на нужное значение nPos.

  • 0
    какой блестящий ответ. Большое спасибо! Я уже проверил это, и это работает отлично. Несмотря на то, что я понимаю все ваши объяснения, вся конструкция выглядит немного сложной. Будете ли вы так добры и объясните это немного подробнее? В частности, необходимо иметь так много функций. Почему я не могу просто использовать cellInfo.onmouseover = alert("my output"); Во-вторых, мне не нужно return function () в вашем примере. В любом случае, большое спасибо за отличное объяснение в вашем ответе выше.
  • 1
    Благодарю. Возможно, вы захотите взглянуть на этот ответ на похожую проблему . Замыкания немного странны в JavaScript, потому что, в отличие от большинства других языков, видимость переменных не ограничивается блоком кода, в котором они определены, а «поднимается» до начала функции, в которой они объявлены. виды необычных последствий, одним из которых является то, что вам нужно объявить функцию просто для того, чтобы получить новую область видимости для переменной (функция nu в вашем случае).
Показать ещё 2 комментария
0

Быстрый код Psuedo:

var nPosArray = [];
var itemsArray = [];

for (var iLoop = 0 ; iLoop < nHitsPerPage ; iLoop++)
{
    var nPos = (nCurrentPageParam * SearchResults.nMaximumHitsPage) + iLoop;

    //...

    var cellInfo = tableResultsRow.insertCell(6);

    //...

    cellInfo.className = "noWrapCell";
    cellInfo.innerHTML = "?";
    cellInfo.style.cursor = "pointer";

    // The line below is important - I need to store nPos value during the table consturction
    nPosArray.push(nPos);
    cellInfo.addEventListener('mouseout', cellMouseOut(event));

    cellInfo.onmousemove = function(){FileResort.LightboxShortInfo.update(event)};
    cellInfo.onmouseout = function(){FileResort.LightboxShortInfo.hide(event)};
    itemsArray.push(cellInfo);
}

function cellMouseOut(e)
{
    for(iLoop = 0 ; iLoop < cellInfo.length; iLoop++)
    {
        if(e.target.id == cellInfo[iLoop].id)
        {
            alert('NPos: ' + nPosArray[iLoop]);
        }
    }
}
  • 0
    Мммм ... Есть ли закон против создания функций внутри цикла? По сравнению с тем, что делает ваше обычное приложение JQuery до того, как пользовательский код даже начинает выполняться, настройка нескольких обработчиков событий кажется мне относительно безвредной. Или мне чего-то не хватает?
  • 0
    @kuroineko По мнению многих IDE
Показать ещё 3 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню