html5 audio bind timeupdate before element exists - javascript

im trying to bind the "timeupdate" event from an audio tag, which doesn't exist yet. I was used to do it this way:
$("body").on("click","#selector", function(e) {
});
I tried this with the audio tag:
$("body").on("timeupdate", ".audioPlayerJS audio", function(e) {
alert("test");
console.log($(".audioPlayerJS audio").prop("currentTime"));
$(".audioPlayerJS span.current-time").html($(".audioPlayerJS audio").prop("currentTime"));
});
This doesn't work though. Is this supposed to work? Or what am I doing wrong?
Any help is highly appreciated.
There is a fiddel for you: jsfiddel

Apparently media events( those specifically belonging to audio or video like play, pause, timeupdate, etc) do not get bubbled. you can find the explanation for that in the answer to this question.
So using their solution, I captured the timeupdate event,
$.createEventCapturing(['timeupdate']);
$('body').on('timeupdate', '.audioPlayerJS audio', updateTime); // now this would work.
JSFiddle demo
the code for event capturing( taken from the other SO answer):
$.createEventCapturing = (function () {
var special = $.event.special;
return function (names) {
if (!document.addEventListener) {
return;
}
if (typeof names == 'string') {
names = [names];
}
$.each(names, function (i, name) {
var handler = function (e) {
e = $.event.fix(e);
return $.event.dispatch.call(this, e);
};
special[name] = special[name] || {};
if (special[name].setup || special[name].teardown) {
return;
}
$.extend(special[name], {
setup: function () {
this.addEventListener(name, handler, true);
},
teardown: function () {
this.removeEventListener(name, handler, true);
}
});
});
};
})();

Related

How to detect DOM modification event

I have been trying to get listen to DOM change event for a several hours, however still cannot get it working.
I need to detect events that are showed in Chrome Debug Tools as changes displayed as pink color.
Here is what I've tried
function listenForDomModified(node, listener) {
node.addEventListener("DOMSubtreeModified", listener, false);
var iframes = node.getElementsByTagName("iframe");
for (var i = 0, len = iframes.length, doc; i < len; ++i) {
// Catch and ignore errors caused by iframes from other domains
try {
doc = iframes[i].contentDocument || iframes[i].contentWindow.document;
doc.addEventListener("DOMSubtreeModified", listener, false);
} catch (ex) {}
}
}
var findElements = function () {
elements.iframeBlock = $(SELECTOR.IFRAME_BLOCK);
};
var onIframeChange = function (e) {
console.log("CHANGE !!!");
alert("DOM CHANGES");
};
var setListeners = function () {
listenForDomModified(elements.iframeBlock[0],onIframeChange);
elements.iframeBlock.bind('DOMSubtreeModified', function(e) {
if (e.target.innerHTML.length > 0) {
alert("ON CHANGE");
}
alert("ON CHANGE");
});
//elements.iframeBlock.change(onIframeChange);
};
Please note, I tried these methods separately.
But still cannot get my function called. However Chrome displays these changes.
I would be grateful for any help.
Thanks
Have you tried
$(document).on('change', function () { /*code*/ });
Try this jQuery approach:
$("iframe").contents().find('body').on("change", function() {
alert("DOM CHANGES");
});
not tested...

Apply multi-event do same function on same element [duplicate]

So my dilemma is that I don't want to write the same code twice. Once for the click event and another for the touchstart event.
Here is the original code:
document.getElementById('first').addEventListener('touchstart', function(event) {
do_something();
});
document.getElementById('first').addEventListener('click', function(event) {
do_something();
});
How can I compact this? There HAS to be a simpler way!
I thought some might find this approach useful; it could be applied to any similarly repetitive code:
ES6
['click','ontouchstart'].forEach( evt =>
element.addEventListener(evt, dosomething, false)
);
ES5
['click','ontouchstart'].forEach( function(evt) {
element.addEventListener(evt, dosomething, false);
});
You can just define a function and pass it. Anonymous functions are not special in any way, all functions can be passed around as values.
var elem = document.getElementById('first');
elem.addEventListener('touchstart', handler, false);
elem.addEventListener('click', handler, false);
function handler(event) {
do_something();
}
Maybe you can use a helper function like this:
// events and args should be of type Array
function addMultipleListeners(element,events,handler,useCapture,args){
if (!(events instanceof Array)){
throw 'addMultipleListeners: '+
'please supply an array of eventstrings '+
'(like ["click","mouseover"])';
}
//create a wrapper to be able to use additional arguments
var handlerFn = function(e){
handler.apply(this, args && args instanceof Array ? args : []);
}
for (var i=0;i<events.length;i+=1){
element.addEventListener(events[i],handlerFn,useCapture);
}
}
function handler(e) {
// do things
};
// usage
addMultipleListeners(
document.getElementById('first'),
['touchstart','click'],
handler,
false);
[Edit nov. 2020] This answer is pretty old. The way I solve this nowadays is by using an actions object where handlers are specified per event type, a data-attribute for an element to indicate which action should be executed on it and one generic document wide handler method (so event delegation).
const firstElemHandler = (elem, evt) =>
elem.textContent = `You ${evt.type === "click" ? "clicked" : "touched"}!`;
const actions = {
click: {
firstElemHandler,
},
touchstart: {
firstElemHandler,
},
mouseover: {
firstElemHandler: elem => elem.textContent = "Now ... click me!",
outerHandling: elem => {
console.clear();
console.log(`Hi from outerHandling, handle time ${
new Date().toLocaleTimeString()}`);
},
}
};
Object.keys(actions).forEach(key => document.addEventListener(key, handle));
function handle(evt) {
const origin = evt.target.closest("[data-action]");
return origin &&
actions[evt.type] &&
actions[evt.type][origin.dataset.action] &&
actions[evt.type][origin.dataset.action](origin, evt) ||
true;
}
[data-action]:hover {
cursor: pointer;
}
<div data-action="outerHandling">
<div id="first" data-action="firstElemHandler">
<b>Hover, click or tap</b>
</div>
this is handled too (on mouse over)
</div>
For large numbers of events this might help:
var element = document.getElementById("myId");
var myEvents = "click touchstart touchend".split(" ");
var handler = function (e) {
do something
};
for (var i=0, len = myEvents.length; i < len; i++) {
element.addEventListener(myEvents[i], handler, false);
}
Update 06/2017:
Now that new language features are more widely available you could simplify adding a limited list of events that share one listener.
const element = document.querySelector("#myId");
function handleEvent(e) {
// do something
}
// I prefer string.split because it makes editing the event list slightly easier
"click touchstart touchend touchmove".split(" ")
.map(name => element.addEventListener(name, handleEvent, false));
If you want to handle lots of events and have different requirements per listener you can also pass an object which most people tend to forget.
const el = document.querySelector("#myId");
const eventHandler = {
// called for each event on this element
handleEvent(evt) {
switch (evt.type) {
case "click":
case "touchstart":
// click and touchstart share click handler
this.handleClick(e);
break;
case "touchend":
this.handleTouchend(e);
break;
default:
this.handleDefault(e);
}
},
handleClick(e) {
// do something
},
handleTouchend(e) {
// do something different
},
handleDefault(e) {
console.log("unhandled event: %s", e.type);
}
}
el.addEventListener(eventHandler);
Update 05/2019:
const el = document.querySelector("#myId");
const eventHandler = {
handlers: {
click(e) {
// do something
},
touchend(e) {
// do something different
},
default(e) {
console.log("unhandled event: %s", e.type);
}
},
// called for each event on this element
handleEvent(evt) {
switch (evt.type) {
case "click":
case "touchstart":
// click and touchstart share click handler
this.handlers.click(e);
break;
case "touchend":
this.handlers.touchend(e);
break;
default:
this.handlers.default(e);
}
}
}
Object.keys(eventHandler.handlers)
.map(eventName => el.addEventListener(eventName, eventHandler))
Unless your do_something function actually does something with any given arguments, you can just pass it as the event handler.
var first = document.getElementById('first');
first.addEventListener('touchstart', do_something, false);
first.addEventListener('click', do_something, false);
Simplest solution for me was passing the code into a separate function and then calling that function in an event listener, works like a charm.
function somefunction() { ..code goes here ..}
variable.addEventListener('keyup', function() {
somefunction(); // calling function on keyup event
})
variable.addEventListener('keydown', function() {
somefunction(); //calling function on keydown event
})
I have a small solution that attaches to the prototype
EventTarget.prototype.addEventListeners = function(type, listener, options,extra) {
let arr = type;
if(typeof type == 'string'){
let sp = type.split(/[\s,;]+/);
arr = sp;
}
for(let a of arr){
this.addEventListener(a,listener,options,extra);
}
};
Allows you to give it a string or Array. The string can be separated with a space(' '), a comma(',') OR a Semicolon(';')
I just made this function (intentionally minified):
((i,e,f)=>e.forEach(o=>i.addEventListener(o,f)))(element, events, handler)
Usage:
((i,e,f)=>e.forEach(o=>i.addEventListener(o,f)))(element, ['click', 'touchstart'], (event) => {
// function body
});
The difference compared to other approaches is that the handling function is defined only once and then passed to every addEventListener.
EDIT:
Adding a non-minified version to make it more comprehensible. The minified version was meant just to be copy-pasted and used.
((element, event_names, handler) => {
event_names.forEach( (event_name) => {
element.addEventListener(event_name, handler)
})
})(element, ['click', 'touchstart'], (event) => {
// function body
});
I'm new at JavaScript coding, so forgive me if I'm wrong.
I think you can create an object and the event handlers like this:
const myEvents = {
click: clickOnce,
dblclick: clickTwice,
};
function clickOnce() {
console.log("Once");
}
function clickTwice() {
console.log("Twice");
}
Object.keys(myEvents).forEach((key) => {
const myButton = document.querySelector(".myButton")
myButton.addEventListener(key, myEvents[key]);
});
<h1 class="myButton">Button</h1>
And then click on the element.
document.getElementById('first').addEventListener('touchstart',myFunction);
document.getElementById('first').addEventListener('click',myFunction);
function myFunction(e){
e.preventDefault();e.stopPropagation()
do_something();
}
You should be using e.stopPropagation() because if not, your function will fired twice on mobile
This is my solution in which I deal with multiple events in my workflow.
let h2 = document.querySelector("h2");
function addMultipleEvents(eventsArray, targetElem, handler) {
eventsArray.map(function(event) {
targetElem.addEventListener(event, handler, false);
}
);
}
let counter = 0;
function countP() {
counter++;
h2.innerHTML = counter;
}
// magic starts over here...
addMultipleEvents(['click', 'mouseleave', 'mouseenter'], h2, countP);
<h1>MULTI EVENTS DEMO - If you click, move away or enter the mouse on the number, it counts...</h1>
<h2 style="text-align:center; font: bold 3em comic; cursor: pointer">0</h2>
What about something like this:
['focusout','keydown'].forEach( function(evt) {
self.slave.addEventListener(evt, function(event) {
// Here `this` is for the slave, i.e. `self.slave`
if ((event.type === 'keydown' && event.which === 27) || event.type === 'focusout') {
this.style.display = 'none';
this.parentNode.querySelector('.master').style.display = '';
this.parentNode.querySelector('.master').value = this.value;
console.log('out');
}
}, false);
});
// The above is replacement of:
/* self.slave.addEventListener("focusout", function(event) { })
self.slave.addEventListener("keydown", function(event) {
if (event.which === 27) { // Esc
}
})
*/
You can simply do it iterating an Object. This can work with a single or multiple elements. This is an example:
const ELEMENTS = {'click': element1, ...};
for (const [key, value] of Object.entries(ELEMENTS)) {
value.addEventListener(key, () => {
do_something();
});
}
When key is the type of event and value is the element when you are adding the event, so you can edit ELEMENTS adding your elements and the type of event.
Semi-related, but this is for initializing one unique event listener specific per element.
You can use the slider to show the values in realtime, or check the console.
On the <input> element I have a attr tag called data-whatever, so you can customize that data if you want to.
sliders = document.querySelectorAll("input");
sliders.forEach(item=> {
item.addEventListener('input', (e) => {
console.log(`${item.getAttribute("data-whatever")} is this value: ${e.target.value}`);
item.nextElementSibling.textContent = e.target.value;
});
})
.wrapper {
display: flex;
}
span {
padding-right: 30px;
margin-left: 5px;
}
* {
font-size: 12px
}
<div class="wrapper">
<input type="range" min="1" data-whatever="size" max="800" value="50" id="sliderSize">
<em>50</em>
<span>Size</span>
<br>
<input type="range" min="1" data-whatever="OriginY" max="800" value="50" id="sliderOriginY">
<em>50</em>
<span>OriginY</span>
<br>
<input type="range" min="1" data-whatever="OriginX" max="800" value="50" id="sliderOriginX">
<em>50</em>
<span>OriginX</span>
</div>
//catch volume update
var volEvents = "change,input";
var volEventsArr = volEvents.split(",");
for(var i = 0;i<volknob.length;i++) {
for(var k=0;k<volEventsArr.length;k++) {
volknob[i].addEventListener(volEventsArr[k], function() {
var cfa = document.getElementsByClassName('watch_televised');
for (var j = 0; j<cfa.length; j++) {
cfa[j].volume = this.value / 100;
}
});
}
}
'onclick' in the html works for both touch and click event. Here's the example.
This mini javascript libary (1.3 KB) can do all these things
https://github.com/Norair1997/norjs/
nor.event(["#first"], ["touchstart", "click"], [doSomething, doSomething]);

WinJS gestureRecognizer - how to trap multiple gestures

I've been using this article (and some others) to try and implement a gesture recognition in my app, and it does work. However, what I want to do is to detect multiple gestures; for example, a swipe, and a touch. What i don't seem to be able to do is to establish whether the MouseUp event is caused by the end of a gesture, or by a single touch.
function processUpEvent(e) {
lastElement = e.currentTarget;
gestureRecognizer.processUpEvent(e.currentPoint);
processTouchEvent(e.currentPoint);
}
What happens currently is it processed both. How can I detect whether the user has 'let go' of the screen for a swipe, or a touch?
EDIT:
var recognizer = new Windows.UI.Input.GestureRecognizer();
recognizer.gestureSettings = Windows.UI.Input.GestureSettings.manipulationTranslateX
recognizer.addEventListener('manipulationcompleted', function (e) {
var dx = e.cumulative.translation.x
//Do something with direction here
});
var processUp = function (args) {
try {
recognizer.processUpEvent(args.currentPoint);
}
catch (e) { }
}
canvas.addEventListener('MSPointerDown', function (args) {
try {
recognizer.processDownEvent(args.currentPoint);
}
catch (e) { }
}, false);
canvas.addEventListener('MSPointerMove', function (args) {
try {
recognizer.processMoveEvents(args.intermediatePoints);
}
catch (e) { }
}, false);
canvas.addEventListener('MSPointerUp', processUp, false);
canvas.addEventListener('MSPointerCancel', processUp, false);
So I need to handle both processUp and manipulationcompleted, but one or the other.
You can have a look at my "input" demo in codeSHOW. Just install the codeSHOW app (http://aka.ms/codeshowapp) and look at the Pointer Input demo and "see the code" or just go to the source code on CodePlex.
Hope that helps.
I've found a way to do this, but it's not pretty:
var eventFlag = 0;
var processUp = function (args) {
try {
recognizer.processUpEvent(args.currentPoint);
if (eventFlag == 0) {
// do stuff
} else {
eventFlag = 0;
}
}
catch (e) { }
}
recognizer.gestureSettings = Windows.UI.Input.GestureSettings.manipulationTranslateX
recognizer.addEventListener('manipulationcompleted', function (e) {
var dx = e.cumulative.translation.x
//Do something with direction here
eventFlag = 1;
});

adding multiple event listeners to one element

So my dilemma is that I don't want to write the same code twice. Once for the click event and another for the touchstart event.
Here is the original code:
document.getElementById('first').addEventListener('touchstart', function(event) {
do_something();
});
document.getElementById('first').addEventListener('click', function(event) {
do_something();
});
How can I compact this? There HAS to be a simpler way!
I thought some might find this approach useful; it could be applied to any similarly repetitive code:
ES6
['click','ontouchstart'].forEach( evt =>
element.addEventListener(evt, dosomething, false)
);
ES5
['click','ontouchstart'].forEach( function(evt) {
element.addEventListener(evt, dosomething, false);
});
You can just define a function and pass it. Anonymous functions are not special in any way, all functions can be passed around as values.
var elem = document.getElementById('first');
elem.addEventListener('touchstart', handler, false);
elem.addEventListener('click', handler, false);
function handler(event) {
do_something();
}
Maybe you can use a helper function like this:
// events and args should be of type Array
function addMultipleListeners(element,events,handler,useCapture,args){
if (!(events instanceof Array)){
throw 'addMultipleListeners: '+
'please supply an array of eventstrings '+
'(like ["click","mouseover"])';
}
//create a wrapper to be able to use additional arguments
var handlerFn = function(e){
handler.apply(this, args && args instanceof Array ? args : []);
}
for (var i=0;i<events.length;i+=1){
element.addEventListener(events[i],handlerFn,useCapture);
}
}
function handler(e) {
// do things
};
// usage
addMultipleListeners(
document.getElementById('first'),
['touchstart','click'],
handler,
false);
[Edit nov. 2020] This answer is pretty old. The way I solve this nowadays is by using an actions object where handlers are specified per event type, a data-attribute for an element to indicate which action should be executed on it and one generic document wide handler method (so event delegation).
const firstElemHandler = (elem, evt) =>
elem.textContent = `You ${evt.type === "click" ? "clicked" : "touched"}!`;
const actions = {
click: {
firstElemHandler,
},
touchstart: {
firstElemHandler,
},
mouseover: {
firstElemHandler: elem => elem.textContent = "Now ... click me!",
outerHandling: elem => {
console.clear();
console.log(`Hi from outerHandling, handle time ${
new Date().toLocaleTimeString()}`);
},
}
};
Object.keys(actions).forEach(key => document.addEventListener(key, handle));
function handle(evt) {
const origin = evt.target.closest("[data-action]");
return origin &&
actions[evt.type] &&
actions[evt.type][origin.dataset.action] &&
actions[evt.type][origin.dataset.action](origin, evt) ||
true;
}
[data-action]:hover {
cursor: pointer;
}
<div data-action="outerHandling">
<div id="first" data-action="firstElemHandler">
<b>Hover, click or tap</b>
</div>
this is handled too (on mouse over)
</div>
For large numbers of events this might help:
var element = document.getElementById("myId");
var myEvents = "click touchstart touchend".split(" ");
var handler = function (e) {
do something
};
for (var i=0, len = myEvents.length; i < len; i++) {
element.addEventListener(myEvents[i], handler, false);
}
Update 06/2017:
Now that new language features are more widely available you could simplify adding a limited list of events that share one listener.
const element = document.querySelector("#myId");
function handleEvent(e) {
// do something
}
// I prefer string.split because it makes editing the event list slightly easier
"click touchstart touchend touchmove".split(" ")
.map(name => element.addEventListener(name, handleEvent, false));
If you want to handle lots of events and have different requirements per listener you can also pass an object which most people tend to forget.
const el = document.querySelector("#myId");
const eventHandler = {
// called for each event on this element
handleEvent(evt) {
switch (evt.type) {
case "click":
case "touchstart":
// click and touchstart share click handler
this.handleClick(e);
break;
case "touchend":
this.handleTouchend(e);
break;
default:
this.handleDefault(e);
}
},
handleClick(e) {
// do something
},
handleTouchend(e) {
// do something different
},
handleDefault(e) {
console.log("unhandled event: %s", e.type);
}
}
el.addEventListener(eventHandler);
Update 05/2019:
const el = document.querySelector("#myId");
const eventHandler = {
handlers: {
click(e) {
// do something
},
touchend(e) {
// do something different
},
default(e) {
console.log("unhandled event: %s", e.type);
}
},
// called for each event on this element
handleEvent(evt) {
switch (evt.type) {
case "click":
case "touchstart":
// click and touchstart share click handler
this.handlers.click(e);
break;
case "touchend":
this.handlers.touchend(e);
break;
default:
this.handlers.default(e);
}
}
}
Object.keys(eventHandler.handlers)
.map(eventName => el.addEventListener(eventName, eventHandler))
Unless your do_something function actually does something with any given arguments, you can just pass it as the event handler.
var first = document.getElementById('first');
first.addEventListener('touchstart', do_something, false);
first.addEventListener('click', do_something, false);
Simplest solution for me was passing the code into a separate function and then calling that function in an event listener, works like a charm.
function somefunction() { ..code goes here ..}
variable.addEventListener('keyup', function() {
somefunction(); // calling function on keyup event
})
variable.addEventListener('keydown', function() {
somefunction(); //calling function on keydown event
})
I have a small solution that attaches to the prototype
EventTarget.prototype.addEventListeners = function(type, listener, options,extra) {
let arr = type;
if(typeof type == 'string'){
let sp = type.split(/[\s,;]+/);
arr = sp;
}
for(let a of arr){
this.addEventListener(a,listener,options,extra);
}
};
Allows you to give it a string or Array. The string can be separated with a space(' '), a comma(',') OR a Semicolon(';')
I just made this function (intentionally minified):
((i,e,f)=>e.forEach(o=>i.addEventListener(o,f)))(element, events, handler)
Usage:
((i,e,f)=>e.forEach(o=>i.addEventListener(o,f)))(element, ['click', 'touchstart'], (event) => {
// function body
});
The difference compared to other approaches is that the handling function is defined only once and then passed to every addEventListener.
EDIT:
Adding a non-minified version to make it more comprehensible. The minified version was meant just to be copy-pasted and used.
((element, event_names, handler) => {
event_names.forEach( (event_name) => {
element.addEventListener(event_name, handler)
})
})(element, ['click', 'touchstart'], (event) => {
// function body
});
I'm new at JavaScript coding, so forgive me if I'm wrong.
I think you can create an object and the event handlers like this:
const myEvents = {
click: clickOnce,
dblclick: clickTwice,
};
function clickOnce() {
console.log("Once");
}
function clickTwice() {
console.log("Twice");
}
Object.keys(myEvents).forEach((key) => {
const myButton = document.querySelector(".myButton")
myButton.addEventListener(key, myEvents[key]);
});
<h1 class="myButton">Button</h1>
And then click on the element.
document.getElementById('first').addEventListener('touchstart',myFunction);
document.getElementById('first').addEventListener('click',myFunction);
function myFunction(e){
e.preventDefault();e.stopPropagation()
do_something();
}
You should be using e.stopPropagation() because if not, your function will fired twice on mobile
This is my solution in which I deal with multiple events in my workflow.
let h2 = document.querySelector("h2");
function addMultipleEvents(eventsArray, targetElem, handler) {
eventsArray.map(function(event) {
targetElem.addEventListener(event, handler, false);
}
);
}
let counter = 0;
function countP() {
counter++;
h2.innerHTML = counter;
}
// magic starts over here...
addMultipleEvents(['click', 'mouseleave', 'mouseenter'], h2, countP);
<h1>MULTI EVENTS DEMO - If you click, move away or enter the mouse on the number, it counts...</h1>
<h2 style="text-align:center; font: bold 3em comic; cursor: pointer">0</h2>
What about something like this:
['focusout','keydown'].forEach( function(evt) {
self.slave.addEventListener(evt, function(event) {
// Here `this` is for the slave, i.e. `self.slave`
if ((event.type === 'keydown' && event.which === 27) || event.type === 'focusout') {
this.style.display = 'none';
this.parentNode.querySelector('.master').style.display = '';
this.parentNode.querySelector('.master').value = this.value;
console.log('out');
}
}, false);
});
// The above is replacement of:
/* self.slave.addEventListener("focusout", function(event) { })
self.slave.addEventListener("keydown", function(event) {
if (event.which === 27) { // Esc
}
})
*/
You can simply do it iterating an Object. This can work with a single or multiple elements. This is an example:
const ELEMENTS = {'click': element1, ...};
for (const [key, value] of Object.entries(ELEMENTS)) {
value.addEventListener(key, () => {
do_something();
});
}
When key is the type of event and value is the element when you are adding the event, so you can edit ELEMENTS adding your elements and the type of event.
Semi-related, but this is for initializing one unique event listener specific per element.
You can use the slider to show the values in realtime, or check the console.
On the <input> element I have a attr tag called data-whatever, so you can customize that data if you want to.
sliders = document.querySelectorAll("input");
sliders.forEach(item=> {
item.addEventListener('input', (e) => {
console.log(`${item.getAttribute("data-whatever")} is this value: ${e.target.value}`);
item.nextElementSibling.textContent = e.target.value;
});
})
.wrapper {
display: flex;
}
span {
padding-right: 30px;
margin-left: 5px;
}
* {
font-size: 12px
}
<div class="wrapper">
<input type="range" min="1" data-whatever="size" max="800" value="50" id="sliderSize">
<em>50</em>
<span>Size</span>
<br>
<input type="range" min="1" data-whatever="OriginY" max="800" value="50" id="sliderOriginY">
<em>50</em>
<span>OriginY</span>
<br>
<input type="range" min="1" data-whatever="OriginX" max="800" value="50" id="sliderOriginX">
<em>50</em>
<span>OriginX</span>
</div>
//catch volume update
var volEvents = "change,input";
var volEventsArr = volEvents.split(",");
for(var i = 0;i<volknob.length;i++) {
for(var k=0;k<volEventsArr.length;k++) {
volknob[i].addEventListener(volEventsArr[k], function() {
var cfa = document.getElementsByClassName('watch_televised');
for (var j = 0; j<cfa.length; j++) {
cfa[j].volume = this.value / 100;
}
});
}
}
'onclick' in the html works for both touch and click event. Here's the example.
This mini javascript libary (1.3 KB) can do all these things
https://github.com/Norair1997/norjs/
nor.event(["#first"], ["touchstart", "click"], [doSomething, doSomething]);

Distinguish between single and doubleclick

I have the following snippet for distinguishing between clicks and doubleclicks:
observeSingleAndDoubleClick: function (element, singleClickHandler, doubleClickHandler, timeout) {
var clicks;
$(element).observe('click', function (event) {
++clicks;
if (clicks === 1) {
var timeoutCallback = function (event) {
if (clicks === 1) {
singleClickHandler.call(this, event);
} else {
doubleClickHandler.call(this, event);
}
clicks = 0;
};
timeoutCallback.bind(this).delay(timeout / 1000);
}
}.bind(this));
}
Problem: The event does not live anymore when the delay callback gets called. Though it works in Firefox but it does not in IE8. The event object passed to the click handlers is "dead" since the event itself is already passed.
Anyone has an advice how to solve this problem?
Don't only observe the click event but also the doubleclick event.
$(element).observe('click',singleClickHandler);
$(element).observe('dblclick',doubleClickHandler);
Here is a changed version after all the discussion:
var clicks;
observeSingleAndDoubleClick: function (element, singleClickHandler, doubleClickHandler, timeout) {
$(element).observe('click', function (event) {
++clicks;
if (clicks === 1) {
var timeoutCallback = function (event) {
if (clicks === 1) {
singleClickHandler.call(this, event);
} else {
doubleClickHandler.call(this, event);
}
clicks = 0;
};
timeoutCallback.bind(this, event).delay(timeout / 1000);
}
}.bind(this));
}
I know the OpenLayers project foes something similar. Look at line 210 in this file: OpenLayers.Handler.Click sourcecode.
I don't know how to use this with the Prototype framework, but I hope it can get you on the right way :)
Another thing: wouldn't it better to use the mouseUp event instead of the click?
There's a dblclick event id on Prototype. Why don't you use it?
observeSingleAndDoubleClick: function (element, singleClickHandler, doubleClickHandler) {
$(element).observe('click', function (event) {
singleClickHandler.call(this, event);
}
$(element).observe('dblclick', function (event) {
doubleClickHandler.call(this, event);
}
}

Categories

Resources