clearTimeout/setTimeout on mobile devices - javascript

I have to make a button that has the following functions:
If you click on it, it should show some lines and hide them after 3 seconds, but if you click on the button before the 3 seconds are over the lines should hide as well.
I have written some code that is working perfectly on desktop browsers, but on mobile browsers it is not. Android devices seem to ignore my clearTimeout and on iphones it seems more like a "buttonPressed" event.
I have created a jsfiddle so that you can see what i have written.
var timeout = null;
var buttonCallback = function() {
if( timeout === null ) {
log('show lines');
timeout = setTimeout(buttonCallback, 3000);
}
else {
clearTimeout(timeout);
timeout = null;
log('hide lines');
}
}
var hammerElement = Hammer(document.getElementById('showLines'));
hammerElement.on("touch", function(e) {
e.preventDefault()
buttonCallback();
});
Any idea how i can make this behaviour work for mobile browsers?

As #wumm mentioned, it works in my iPhone5 iOS7 as well.
Another way you could try is this fiddle I setup for you: http://jsfiddle.net/thePav/jC32X/5
HTML
<button id="showLines">Show Lines</button>
JS
var timeout;
var flag = false;
function buttonCallback() {
$('#showLines').click(function(){
if(flag == false){
flag = true;
//show lines here
timeout = setTimeout(function(){
flag = false;
//hide lines here
}, 3000);
}else{
flag = false;
clearTimeout(timeout);
//hide lines here
}
});
}
$(document).ready(function(){
buttonCallback();
});
Not sure what the issue with your code was but this is just another way to implement it.

The error was that on some mobile devices that I was testing (not all!) has sometimes send 2 tab events (double tab).
To fix that I have been added a delayTime and checked when the function got called last time.
var buttonCallback = function() {
if( timeout === null ) {
//for old slow andoid devices
if ((new Date().getTime() - delayTime) < 2200)
return;
delayTime = new Date().getTime();
log('show lines');
timeout = setTimeout(buttonCallback, 3000);
}
// for fast devices to prevent the double tab error
else if ( (new Date().getTime() - delayTime) > 1200 ) {
clearTimeout(timeout);
timeout = null;
log('hide lines');
}
}

Related

JS - Window Focus and Bring to front in Firefox

I am trying to set up a tiny script for Firefox that runs in a javascript add-on (Greasemonkey). We have a queue that we monitor for arriving tickets, I coded something that is supposed to refresh the page every 2 minutes and do the following:
if tickets are found by this condition
if (isEmpty($('#incident_table > tbody'))&isEmpty($('#task_table > tbody')))
then I want the following to happen:
- task-bar blinks with a message so it is visible
- if the window is focused it will display "Tickets in the queue!" alert right away
- if the window is not focused, it will wait for 10 seconds, if still not focused - display "Tickets in the queue!" alert and bring the window to front.
I've got the refresh and blinking part, but I cannot get the focus part to work... I've been looking around and I see that Firefox is having some "issues" with window.focus() and all the "bring to front", most of the code below is inspired by stuff I've found on this site.
Any input is appreciated! I am also opened to alternatives - in the end, what this needs to do is refresh, check the condition and notify if I am already looking at it or if it is not focused wait 10 seconds with a "soft notify" (blink) then bring it to the front if I don't notice it.
Regards,
Dan
{
newExcitingAlerts = (function () {
var oldTitle = document.title;
var msg = "***NEW***";
var timeoutId;
var blink = function() { document.title = document.title == msg ? 'Tickets in queue!' : msg; };
var clear = function() {
clearInterval(timeoutId);
document.title = oldTitle;
window.onmousemove = null;
timeoutId = null;
};
return function () {
if (!timeoutId) {
timeoutId = setInterval(blink, 1000);
window.onmousemove = clear;
}
};
}());
$(document).ready(function(){
function isEmpty( el ){
return !$.trim(el.html());
}
if (isEmpty($('#incident_table > tbody'))&isEmpty($('#task_table > tbody'))) {
}
else{
newExcitingAlerts();
}
setTimeout(function() {
location.reload();
}, 120000);
});
}
Here is the alternative I've used, works like a charm. Web API notifications.
document.addEventListener('DOMContentLoaded', function () {
if (Notification.permission !== "granted")
Notification.requestPermission();
});
function notifyMe() {
if (!Notification) {
alert('Desktop notifications not available in your browser. Try Chromium.');
return;
}
if (Notification.permission !== "granted")
Notification.requestPermission();
else {
var notification = new Notification('Tickets in queue!', {
icon: 'http://siliconangle.com/files/2014/05/servicenow-icon.png',
body: "There are new tickets in queue, please acknowledge!",
});
notification.onclick = function () {
window.open("https://cchprod.service-now.com/task_list.do?sysparm_query=assignment_group%3D3139519437b7f1009654261953990e1f^ORassignment_group%3D31de85e337818a00ef8898a543990e99^ORassignment_group%3Da40029e937ec420065aa261953990eb5^ORassignment_group%3De903ad2d37ec420065aa261953990ecb^ORassignment_group%3Dd25fe5323779c24065aa261953990e54^ORassignment_group%3D508639363779c24065aa261953990e29^ORassignment_group%3D51fe5a37379e0a00ef8898a543990ea2^ORassignment_group%3D3d8171b23779c24065aa261953990e21^ORassignment_group%3Decfe5a37379e0a00ef8898a543990e6c^ORassignment_group%3D48c0b9723779c24065aa261953990e5d^ORassignment_group%3De5fde9fe3739c24065aa261953990e75^ORassignment_group%3D15fe5a37379e0a00ef8898a543990e99^ORassignment_group%3D15fe5a37379e0a00ef8898a543990ea7^ORassignment_group%3D1ed3f1f23779c24065aa261953990e47^active%3Dtrue^sys_class_name%3Dincident^ORsys_class_name%3Dsc_req_item^assigned_toISEMPTY&sysparm_first_row=1&sysparm_view=");
};
}
}
{
newExcitingAlerts = (function () {
var oldTitle = document.title;
var msg = "***NEW***";
var timeoutId;
var blink = function() {
document.title = document.title == msg ? 'Tickets in queue!' : msg;
};
var clear = function() {
clearInterval(timeoutId);
document.title = oldTitle;
window.onmousemove = null;
timeoutId = null;
};
return function () {
if (!timeoutId) {
timeoutId = setInterval(blink, 1000);
window.onmousemove = clear;
}
};
}
());
$(document).ready(function () {
function isEmpty(el) {
return !$.trim(el.html());
}
var x = document.getElementById("task_table").getAttribute("grand_total_rows");
if( x != "0" ) {
newExcitingAlerts();
notifyMe();
}
else
{
}
setTimeout(function() {
location.reload();
}
, 120000);
});
}
In Windows operating system you cannot focus the window while the window of another process is focused. You have to use js-ctypes to get around this.
On Mac OS X and Linux, I'm not sure if you can make your process steal focus from another with the normal functions. But if you can't you can for sure use js-ctypes to get the job done.
Here is how to do it in Windows - https://stackoverflow.com/a/32038880/1828637
It is harder on Windows then on OS X and Linux. I have focused windows on all systems using js-ctypes. So if you can't find out how to do with the functions available to you, let me know.

Only run JavaScript in Chrome

So I have a little script that only seems to work correctly in Chrome. It's not a big problem, however the negative effects it has in other browsers is annoying, so I'd like to only run it in Chrome.
This is my current working script that runs in all browsers:
function psn() {
var myElement = document.getElementById('noti');
if(window.addEventListener) {
// Normal browsers
myElement.addEventListener('DOMSubtreeModified', contentChanged, false);
} else
if(window.attachEvent) {
// IE
myElement.attachEvent('DOMSubtreeModified', contentChanged);
}
function contentChanged() {
// this function will run each time the content of the DIV changes
document.getElementById('audiotag1').play();
var vid = document.getElementById("audiotag1");
vid.volume = 1;
}}
setTimeout(function () {psn()}, 2000);
And this is what I've tried already to make it run only in Chrome, which made the script stop working all together:
function psn() {
var myElement = document.getElementById('noti');
if(window.addEventListener) {
// Normal browsers
myElement.addEventListener('DOMSubtreeModified', contentChanged, false);
} else
if(window.attachEvent) {
// IE
myElement.attachEvent('DOMSubtreeModified', contentChanged);
}
function contentChanged() {
// this function will run each time the content of the DIV changes
document.getElementById('audiotag1').play();
var vid = document.getElementById("audiotag1");
vid.volume = 1;
}}
var isChrome = !!window.chrome;
if (isChrome) {
setTimeout(function () {psn()}, 2000);
}
Anyone know why this is just stopping everything completely?
It is best to not have to do specific browser detection, but an easy way to see if you are using Chrome or not is the following:
var isChrome = navigator.userAgent.toLowerCase().indexOf("chrome") >= 0 ? true : false;
This will populate isChrome with either true of false.

mousewheel event is too fast. How to disable it

I am trying to bring in an effect like hugeinc.com in my website udowalzfinal.umatechcorner.com
I did the following
$(window).on({
'DOMMouseScroll mousewheel': ScrollBegin
});
var delta = 0;
var scrollThreshold = 10;
function ScrollBegin(e) {
// --- Scrolling up ---
if (e.originalEvent.detail < 0 || e.originalEvent.wheelDelta > 0) {
delta--;
console.log(delta);
if ( Math.abs(delta) >= scrollThreshold) {
timer = setTimeout(function () {
MoveScreen('up');
}, 800);
clearTimeout(timer);
}
}
// --- Scrolling down ---
else {
delta++;
console.log(delta);
if (delta >= scrollThreshold) {
timer = setTimeout(function () {
MoveScreen('down');
clearTimeout(timer);
}, 800);
}
}
// Prevent page from scrolling
return false;
}
I don't know what value to set for scrollThreshold.
mousewheel event is raised & ScrollBegin is executed. But this is too slow in IE & too fast in Safari with Apple Mouse.
Mousewheel event is raised for each mouse wheel move. In my case, it raises the event 10 times when I scroll the mouse wheel once. How can I disable those 9 events and only handle it once.
How to get a MouseWheel Event to fire only once in jQuery? article does not fix my problem. This only gives support for moving up once & then down once. But I have 5 slides in my page.
Can someone please help?
You should probably use a debouncer.
//Debouncer functions add a delay between an event and a reaction, so scaling and scrolling don't evoke a function dozens of times.
function debouncer(func, timeout) {
var timeoutID , timeout = timeout || 200;
return function () {
var scope = this , args = arguments;
clearTimeout( timeoutID );
timeoutID = setTimeout( function () {
func.apply( scope , Array.prototype.slice.call( args ) );
} , timeout );
};
}
This is a general purpose function. Use it like this:
jQuery(window).scroll(debouncer(function(){
//Call your scroll handler here.
}));
To really fine tune the delay, add a cecond parameter, like:
jQuery(window).scroll(debouncer(function(){
//Call your scroll handler here.
}), 600);
You want to look at something like Underscore.js's Debounce function. You can either use debounce directly by bringing underscore onto your page (not a bad idea), or implement it yourself. There's also throttle, which works slightly differently; here's an example with both:
http://goo.gl/jEl9lA

HTML5 Progress Bar Pause when in another tab

My progress bar loader which i'm using to display a sorten amount of seconds while my page is loading in Javascript is having some trouble.
If i click another tab while its counting it will pause, and will only resume when you go back.
How would i go by allowing it to count even though you're in another tab
$(document).ready(function() {
if(!Modernizr.meter){
alert('Sorry your brower does not support HTML5 progress bar');
} else {
var progressbar = $('#progressbar'),
max = progressbar.attr('max'),
time = (800/max)*10,
value = progressbar.val();
var loading = function() {
value += 1;
addValue = progressbar.val(value);
$('.progress-value').html(value + '%');
if (value == max) {
clearInterval(animate); $(".demo-wrapper").remove(); $("#details").fadeIn("slow"); $("#motion1").html("Report for Registration."); $("#motion").remove();
}
if (value == 1) {
$("#motion").html("Loading Page..");
}
if (value == 86) {
$("#motion").html("Connecting..");
}
};
var animate = setInterval(function() {
loading();
}, time);
};
});
Here's an example http://jsfiddle.net/w977Q/
Maybe have a look at the accepted answer here: How can I make setInterval also work when a tab is inactive in Chrome?
It appears this is basically a function of the browser not wanting to use processing power on tabs that aren't in focus.
Hope this helps you
setInterval('yourFunction();', 1000); // this will work even on other tab
and
setInterval(yourFunction, 1000); // this will run only if on current tab

This action will actually increase or decrease a webpage performance?

I created this piece of code to increase my webpage performance.
If autoplay.v.mystart is true, the sliding and animations of 2 slideshows will not be played,I made condition on it. My aim is to stop the animations while user is scrolling and reactivate it while user stopped scrolling, I think it will reduce a webpage load, to make a webpage scroll smoother, as I listened to people say stop unused animations or hide things that's unused. However, I see it didn't go smoother, but a bit more laggy. Is it using scroll event listener and timer/cleartimeout will take up a lot of resources too? What is the best way to accomplish my aim , to reduce my webpage load? I am thinking should I remove this code?That will be a waste,I can't decide
var saviour = {
'$mywrapper' : $('#wrapper'),
'mychecked':false,
run : function(){
var wrapper_timer;
saviour.$mywrapper.scroll(function(){
if(saviour.mychecked==false){
saviour.mychecked = true;
autoplay.v.mystart = false;
clearTimeout(wrapper_timer);
setTimeout(function(){saviour.mychecked=false},1000);
wrapper_timer = setTimeout(function(){
autoplay.v.mystart = true;
console.log('autoplay restart')
},4000);
console.log('check');
}
});
}
}
saviour.run();
First, here's a jQuery addon that provides 'scrollstart' and 'scrollstop' events, based on this, which was written for an early version of jQuery and needed to be modernized.
(function($, latency) {
var special = $.event.special;
special.scrollstart = {
setup: function() {
var timer;
function handler(evt) {
if (timer) {
clearTimeout(timer);
} else {
evt.type = 'scrollstart';
$.event.handle.apply(this, arguments);
}
timer = setTimeout(function() {
timer = null;
}, latency);
};
$(this).on('scroll.start', handler);
},
teardown: function() {
$(this).off('scroll.start');
}
};
special.scrollstop = {
setup: function() {
var timer;
function handler(evt) {
var _self = this,
_args = arguments;
if (timer) {
clearTimeout(timer);
}
timer = setTimeout(function() {
timer = null;
evt.type = 'scrollstop';
$.event.handle.apply(_self, _args);
}, latency);
};
$(this).on('scroll.stop', handler);
},
teardown: function() {
$(this).off('scroll.stop');
}
};
})(jQuery, 300);
This version :
Replaces .bind() and .unbind() with .on() and .off(), plus associated simplification.
Allows the latency to be specified as a parameter to the self-executing function wrapper.
With 'scrollstart' and 'scrollstop' event detection in place, the application snippet for starting and stopping the animation can be as simple as this :
$(window).on ('scrollstart', function(e) {
allowAnim = false;
stopAnim();
}).on ('scrollstop', function(e) {
allowAnim = true;
anim();
}).trigger('scrollstop');
where anim() and stopAnim() are your functions for starting and stopping animation(s) and allowAnim is a boolean var in an outer scope.
You may want to adjust the latency. I found 300 to be about the minimum acceptable value, and very responsive. Larger A higher value will be less responsive but will better prevent the animation from restarting in mid-scroll.
DEMO

Categories