РЕЗЮМЕ:
Здесь я предоставляю кросс-браузерную возможность no-jQuery для настольных и мобильных устройств, чтобы последовательно реагировать на взаимодействия диапазона / ползунка, что невозможно в современных браузерах. По сути, это заставляет все браузеры эмулировать on("change"...
события IE11 для их on("change"...
или для on("input"...
событий. Новая функция ...
function onRangeChange(r,f) {
var n,c,m;
r.addEventListener("input",function(e){n=1;c=e.target.value;if(c!=m)f(e);m=c;});
r.addEventListener("change",function(e){if(!n)f(e);});
}
... где r
ваш элемент ввода диапазона и f
ваш слушатель. Слушатель будет вызываться после любого взаимодействия, которое изменяет значение диапазона / ползунка, но не после взаимодействий, которые не изменяют это значение, включая начальные взаимодействия мыши или касания в текущей позиции ползунка или после перемещения с любого конца ползунка.
Проблема:
По состоянию на начало июня 2016 года разные браузеры различаются с точки зрения того, как они реагируют на использование диапазона / слайдера. Пять сценариев актуальны:
- начальное нажатие мыши (или сенсорный запуск) в текущей позиции ползунка
- начальное нажатие мыши (или сенсорный запуск) в новой позиции ползунка
- любое последующее движение мыши (или касание) после 1 или 2 вдоль ползунка
- любое последующее движение мыши (или касание) после 1 или 2 после любого конца ползунка
- окончательное наведение мыши (или касание)
В следующей таблице показано, как, по крайней мере, три разных настольных браузера отличаются по своему поведению в зависимости от того, на какой из приведенных выше сценариев они реагируют:
Решение:
onRangeChange
Функция обеспечивает последовательную и предсказуемую реакцию кросс-браузер для диапазона / слайдер взаимодействий. Это заставляет все браузеры вести себя согласно следующей таблице:
В IE11 код, по существу, позволяет всему работать в соответствии со статус-кво, то есть он позволяет "change"
событию функционировать стандартным образом, и "input"
событие не имеет значения, так как оно никогда не срабатывает. В других браузерах "change"
событие эффективно отключается (для предотвращения запуска дополнительных, а иногда и не совсем очевидных событий). В дополнение"input"
событие вызывает слушателя только при изменении значения диапазона / ползунка. В некоторых браузерах (например, Firefox) это происходит потому, что слушатель эффективно отключается в сценариях 1, 4 и 5 из приведенного выше списка.
(Если вы действительно хотите, чтобы слушатель был активирован в любом из сценариев 1, 4 и / или 5, вы можете попробовать включить события "mousedown"
/ "touchstart"
, "mousemove"
/ "touchmove"
и / или "mouseup"
/ "touchend"
. Такое решение выходит за рамки этого ответа.)
Функциональность в мобильных браузерах:
Я тестировал этот код в настольных браузерах, но не в мобильных браузерах. Однако в другом ответе на этой странице MBourne показал, что мое решение здесь "... похоже, работает в любом браузере, который я смог найти (Win Desktop: IE, Chrome, Opera, FF; Android Chrome, Opera и FF, iOS Safari) " . (Спасибо, MBourne.)
Использование:
Чтобы использовать это решение, onRangeChange
включите функцию из приведенного выше резюме (упрощенного / минимизированного) или приведенного ниже фрагмента демонстрационного кода (функционально идентичного, но более понятного) в свой собственный код. Вызовите это следующим образом:
onRangeChange(myRangeInputElmt, myListener);
где myRangeInputElmt
- ваш желаемый <input type="range">
элемент DOM и myListener
функция прослушивателя / обработчика, для которой вы хотите вызвать"change"
подобных событиях.
При желании ваш слушатель может не иметь параметров или использовать event
параметр, т. Е. Может работать любое из следующих действий в зависимости от ваших потребностей:
var myListener = function() {...
или
var myListener = function(evt) {...
(Удаление слушателя события из input
элемента (например, использование removeEventListener
) не рассматривается в этом ответе.)
Демо Описание:
В приведенном ниже фрагменте кода функция onRangeChange
предоставляет универсальное решение. Остальная часть кода является просто примером, демонстрирующим его использование. Любая переменная, которая начинается сmy...
имеет отношения к универсальному решению и присутствует только для демонстрации.
Демонстрационные показывает значение диапазона / слайдер, а также количество раз стандартных "change"
, "input"
и пользовательские "onRangeChange"
события обстреляли (строки A, B и C соответственно). При запуске этого фрагмента в разных браузерах обратите внимание на следующее при взаимодействии с диапазоном / ползунком:
- В IE11 значения в строках A и C изменяются в сценариях 2 и 3 выше, в то время как строка B никогда не изменяется.
- В Chrome и Safari значения в строках B и C изменяются в сценариях 2 и 3, а строка A изменяется только для сценария 5.
- В Firefox значение в строке A изменяется только для сценария 5, строка B изменяется для всех пяти сценариев, а строка C изменяется только для сценариев 2 и 3.
- Во всех вышеперечисленных браузерах изменения в строке C (предлагаемое решение) идентичны, т.е. только для сценариев 2 и 3.
Демо-код:
// main function for emulating IE11's "change" event:
function onRangeChange(rangeInputElmt, listener) {
var inputEvtHasNeverFired = true;
var rangeValue = {current: undefined, mostRecent: undefined};
rangeInputElmt.addEventListener("input", function(evt) {
inputEvtHasNeverFired = false;
rangeValue.current = evt.target.value;
if (rangeValue.current !== rangeValue.mostRecent) {
listener(evt);
}
rangeValue.mostRecent = rangeValue.current;
});
rangeInputElmt.addEventListener("change", function(evt) {
if (inputEvtHasNeverFired) {
listener(evt);
}
});
}
// example usage:
var myRangeInputElmt = document.querySelector("input" );
var myRangeValPar = document.querySelector("#rangeValPar" );
var myNumChgEvtsCell = document.querySelector("#numChgEvtsCell");
var myNumInpEvtsCell = document.querySelector("#numInpEvtsCell");
var myNumCusEvtsCell = document.querySelector("#numCusEvtsCell");
var myNumEvts = {input: 0, change: 0, custom: 0};
var myUpdate = function() {
myNumChgEvtsCell.innerHTML = myNumEvts["change"];
myNumInpEvtsCell.innerHTML = myNumEvts["input" ];
myNumCusEvtsCell.innerHTML = myNumEvts["custom"];
};
["input", "change"].forEach(function(myEvtType) {
myRangeInputElmt.addEventListener(myEvtType, function() {
myNumEvts[myEvtType] += 1;
myUpdate();
});
});
var myListener = function(myEvt) {
myNumEvts["custom"] += 1;
myRangeValPar.innerHTML = "range value: " + myEvt.target.value;
myUpdate();
};
onRangeChange(myRangeInputElmt, myListener);
table {
border-collapse: collapse;
}
th, td {
text-align: left;
border: solid black 1px;
padding: 5px 15px;
}
<input type="range"/>
<p id="rangeValPar">range value: 50</p>
<table>
<tr><th>row</th><th>event type </th><th>number of events </th><tr>
<tr><td>A</td><td>standard "change" events </td><td id="numChgEvtsCell">0</td></tr>
<tr><td>B</td><td>standard "input" events </td><td id="numInpEvtsCell">0</td></tr>
<tr><td>C</td><td>new custom "onRangeChange" events</td><td id="numCusEvtsCell">0</td></tr>
</table>
Кредит:
Хотя реализация здесь в значительной степени моя собственная, она была вдохновлена ответом MBourne . Этот другой ответ предполагал, что события «input» и «change» можно объединить и что полученный код будет работать как в настольных, так и в мобильных браузерах. Однако код в этом ответе приводит к запуску скрытых «лишних» событий, что само по себе проблематично, а возникающие события различаются в разных браузерах, что является еще одной проблемой. Моя реализация здесь решает эти проблемы.
Ключевые слова:
События ползунка диапазона ввода типа JavaScript изменяют совместимость ввода в браузере кросс-браузерный рабочий стол mobile no-jQuery
onchange
не срабатывает. Именно в устранении неполадок этой проблемы я нашел этот вопрос.