요약:
나는 현재 브라우저에서 불가능한 범위 / 슬라이더 상호 작용에 일관되게 응답 할 수있는 jQuery가없는 브라우저 간 데스크탑 및 모바일 기능을 제공합니다. 기본적으로 모든 브라우저가 IE11의 on("change"...
이벤트 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 년 6 월 초 현재, 브라우저마다 범위 / 슬라이더 사용에 응답하는 방식이 다릅니다. 다섯 가지 시나리오가 관련됩니다.
- 현재 슬라이더 위치에서 초기 마우스 다운 (또는 터치 시작)
- 새로운 슬라이더 위치에서 초기 마우스 다운 (또는 터치 시작)
- 슬라이더를 따라 1 또는 2 이후의 후속 마우스 (또는 터치) 움직임
- 슬라이더의 한쪽 끝을지나 1 또는 2 이후의 후속 마우스 (또는 터치) 이동
- 최종 마우스 업 (또는 터치 엔드)
다음 표는 응답하는 위의 시나리오와 관련하여 적어도 3 개의 서로 다른 데스크탑 브라우저의 동작이 어떻게 다른지 보여줍니다.
해결책:
이 onRangeChange
기능은 범위 / 슬라이더 상호 작용에 일관되고 예측 가능한 크로스 브라우저 응답을 제공합니다. 다음 표에 따라 모든 브라우저가 작동하도록합니다.
IE11에서이 코드는 기본적으로 모든 현상이 현상에 따라 작동 할 수 있도록합니다. 즉, "change"
표준 방식으로 이벤트가 작동 하도록 허용 하며 "input"
이벤트는 결코 발생하지 않으므로 관련이 없습니다. 다른 브라우저에서는 "change"
이벤트가 효과적으로 묵음 처리됩니다 (추가적이고 때로는 준비되지 않은 이벤트가 발생하지 않도록). 또한 "input"
이벤트는 범위 / 슬라이더의 값이 변경 될 때만 리스너를 시작합니다. 일부 브라우저 (예 : Firefox)의 경우 위 목록의 시나리오 1, 4 및 5에서 리스너가 효과적으로 침묵하기 때문에이 문제가 발생합니다.
(시나리오 1, 4 및 / 또는 5에서 리스너를 활성화해야하는 경우 "mousedown"
/ "touchstart"
, "mousemove"
/ "touchmove"
및 / 또는 "mouseup"
/ "touchend"
이벤트를 통합 할 수 있습니다. 이러한 솔루션은이 답변의 범위를 벗어납니다.)
모바일 브라우저의 기능 :
데스크톱 브라우저에서는이 코드를 테스트했지만 모바일 브라우저에서는 테스트하지 않았습니다. 그러나이 페이지의 또 다른 대답에서 MBourne은 여기에서 내 솔루션이 "... 모든 브라우저에서 작동하는 것으로 보입니다 (Win 데스크톱 : IE, Chrome, Opera, FF; Android Chrome, Opera 및 FF, iOS Safari) " . (MBourne 감사합니다.)
용법:
이 솔루션을 사용하려면 onRangeChange
자신의 코드에 위의 요약 (간체 / 최소화) 또는 아래의 데모 코드 스 니펫 (기능적으로 동일하지만 더 자명 한)의 함수를 포함 시키십시오. 다음과 같이 호출하십시오.
onRangeChange(myRangeInputElmt, myListener);
where myRangeInputElmt
는 원하는 <input type="range">
DOM 요소이며 -like 이벤트에서 myListener
호출하려는 리스너 / 핸들러 함수 "change"
입니다.
청취자는 원하는 경우 매개 변수가 없거나 event
매개 변수를 사용할 수 있습니다. 즉, 필요에 따라 다음 중 하나가 작동합니다.
var myListener = function() {...
또는
var myListener = function(evt) {...
( input
요소 에서 이벤트 리스너 제거 (예 :) 사용 removeEventListener
)는이 답변에서 다루지 않습니다.
데모 설명 :
아래 코드 스 니펫에서이 함수 onRangeChange
는 범용 솔루션을 제공합니다. 나머지 코드는 그 사용법을 보여주는 예제 일뿐입니다. 로 시작하는 모든 변수 my...
는 범용 솔루션과 관련이 없으며 데모를 위해서만 존재합니다.
데모 범위 / 슬라이더 값뿐만 아니라 시간 기준 횟수 방송 "change"
, "input"
커스텀 "onRangeChange"
이벤트를 소성 한 (행 각각 A, B 및 C). 다른 브라우저에서이 스 니펫을 실행할 때 범위 / 슬라이더와 상호 작용할 때 다음 사항에 유의하십시오.
- IE11에서는 위의 시나리오 2와 3에서 행 A와 C의 값이 모두 변경되지만 행 B는 변경되지 않습니다.
- Chrome과 Safari에서 행 B와 C의 값은 시나리오 2와 3에서 모두 변경되지만 행 A는 시나리오 5에서만 변경됩니다.
- Firefox에서 행 A의 값은 시나리오 5에 대해서만 변경되고 행 B는 5 개의 시나리오 모두에 대해 변경되며 행 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의 대답 에서 영감을 얻었습니다 . 다른 답변은 "입력"및 "변경"이벤트를 병합 할 수 있으며 결과 코드는 데스크톱 및 모바일 브라우저 모두에서 작동 할 것이라고 제안했습니다. 그러나이 답변의 코드를 사용하면 숨겨진 "추가"이벤트가 발생하며 그 자체로 문제가 발생하며 발생하는 이벤트는 브라우저마다 다릅니다. 내 구현은 이러한 문제를 해결합니다.
키워드 :
JavaScript 입력 유형 범위 슬라이더 이벤트 변경 입력 브라우저 호환성 크로스 브라우저 데스크탑 모바일 no-jQuery
onchange
발생하지 않습니다. 이 질문을 찾은 것은 해당 문제를 해결하는 데있었습니다.