clearInterval() doesnt work on iPad - javascript

This is what i do:
var scrolling;
$('#nw_scroll_down').on('mousedown', function(){
scrolling = setInterval(function() {
$('.mod_article').scrollTop( $('.mod_article').scrollTop() + 5 );
},25);
});
$('#nw_scroll_down').on('mouseup', function(){
if (scrolling) {
window.clearInterval(scrolling);
scrolling = false;
}
});
inside a $(document).ready(function(){});
Everything works fine until the line
window.clearInterval(scrolling);
This works fine on PC but not on iPad. Can anyone imagine why it doesnt work on the ipad (chrome browser)?

Instead of mousedown, you should make use of touchstart and touchend events for iPad as detailed in Apple documentation or Mozilla documentation.
Try this:
$('#nw_scroll_down').bind( "touchstart", function(e){
scrolling = setInterval(function() {
$('.mod_article').scrollTop( $('.mod_article').scrollTop() + 5 );
},25);
});
$('#nw_scroll_down').bind('touchend', function(){
if (scrolling) {
window.clearInterval(scrolling);
scrolling = false;
}
});
In order to make it work in both, desktop and touch devices, you can try this:
$('#nw_scroll_down').on("mousedown touchstart", function(e){
.
Update
Another solution given by Apple documentation seems to be to add the inline event onclick="void(0)" to the element in which you have the mousedown event.
A clickable element is a link, form element, image map area, or any other element with mousemove, mousedown, mouseup, or onclick handlers. A scrollable element is any element with appropriate overflow style, text areas, and scrollable iframe elements. Because of these differences, you might need to change some of your elements to clickable elements, as described in “Making Elements Clickable,” to get the desired behavior in iPhone OS.

Related

Holdable button on JS. How need rewrite code for correctly work on mobile devices?

Holdable button works on desktop, but doesn't work on mobile
clicker.mousedown(function(){
timeout = setInterval(function(){
clicker.text(count++);
}, 500);
return false;
});
http://jsfiddle.net/8FmRd/
what's wrong?
To do it by actual hold, you'd do something like:
var timeoutContainer;
// this should work with mouse only
$el.on('mousedown', function(ev) {
if(ev.type=='click'){
timeoutContainer = setInterval(function(){
// your stuff.
}, timeToHold);
}
});
$el.on('mouseup', function(ev) {
clearInterval(timeoutContainer);
});
// or, if you only want to apply it to touch.
$el.on('touchstart', function(ev) {
timeoutContainer = setTimeout(function(){
// your stuff.
}, timeToHold);
});
$el.on('touchend', function(ev) {
clearTimeout(timeoutContainer);
});
After looking at your fiddle, it may not be working as expected because of touchcancel. I noticed you have document.mouseup. It might be treating moving finger as a mouse up or something. If you do it explicitly as touch start it may behave differently. You'd need to check for mobile before as above in the mouse down part.
You need to use touchstart and touchend events to detect a touch on a button on mobile devices. On some devices touchmove might also trigger so you can also check for that.
https://developer.mozilla.org/en-US/docs/Web/API/Touch_events

BlueImp Gallery - How to deactivate swipe event

I am using BlueImp Gallery (DEMO). I need to lock hide the buttons on certain situations, that worked great. But now I also need to hide the mouse and touch swipes as well.
Explanation: Users can swipe left or right, this will change the current picture.
I was not able to find the responsible event yet. How can I deactivate the swipe events and active it again? Is that possible?
They had no intend of publishing this feature, but it's in there.
var galleryContext
// initalize your gallery
blueimp.Gallery([{/* your images */}], {
// we need the context of the gallery
onopened: function () {
galleryContext = this
}
})
// now disable
galleryContext.destroyEventListeners()
// or enable
galleryContext.initEventListeners()
You can use on() like,
$(document).on('click touchmove',function(){
if(CERTAIN_SITUATIONS){ // only on certain situations
return false;// it will prevent to do anything in your document
}
});
If you want a div or container to be disable then use it like,
$(document).on('click touchmove','CONTAINER_ID_OR_CLASS',function(){
....
You can use stopPropagation() to prevent bubbling,
$(document).on('click touchmove',function(e){
if(CERTAIN_SITUATIONS){ // only on certain situations
e.stopPropagation();
return false;// it will prevent to do anything in your document
}
});
this worked for me: (tested on v3.2.0)
this.galleryInstance = blueimp(this.config.images, options);
this.galleryInstance.destroyEventListeners();
//this line makes sure no touch events are registered in the init function
//and preserving other events in tact
this.galleryInstance.support.touch = false;
this.galleryInstance.initEventListeners();

Scratch Effect Plugin: getting the scratch to go across multiple panels without lifting mouse

I'm using the HTML5 rabid scratch plugin to achieve a grid of little panels that can be scratched off to reveal images behind.
Demo:
http://jsfiddle.net/CeTR8/2/
Problem:
When you click and drag over a panel, it scratches that panel but you have to mouseup and mousedown for each panel. I'd like scratch from one to another without having to mouseup and mousedown.
I've tried making the following modifications to trigger on mousemove (if mouse button is also down) and it's somewhat working on safari/chrome in Mac but not in IE9 and probably others..
// Bind downHandler to mousemover instead
self.theCanvas.bind('mousemove', $.proxy(self.addDownHandler, self));
// self.theCanvas.bind('mousedown', $.proxy(self.addDownHandler, self));
// self.theCanvas.bind('mouseup', $.proxy(self.addUpHandler, self));
// $(window).bind('mouseup', $.proxy(self.addUpHandler, self));
....
addDownHandler: function (e) {
// only scratch if mouse down
if(e.which == 1){
var self = this;
self.theCanvas.bind('mousemove', $.proxy(self.mouseMoveHandler, self));
}
}
Current
http://jsfiddle.net/CeTR8/3/
Is there a better way to do this that will work across browsers?
http://jsfiddle.net/ericjbasti/CeTR8/5/
Changed
self.theCanvas.bind('mousedown', $.proxy(self.addDownHandler, self));
to
$(window).bind('mousedown', $.proxy(self.addDownHandler, self));

Firefox firing dragleave when dragging over text

I'm attempting to track a dragenter/leave for the entire screen, which is so far working fine in Chrome/Safari, courtesy of the draghover plugin from https://stackoverflow.com/a/10310815/698289 as in:
$.fn.draghover = function(options) {
return this.each(function() {
var collection = $(),
self = $(this);
self.on('dragenter', function(e) {
if (collection.size() === 0) {
self.trigger('draghoverstart');
}
collection = collection.add(e.target);
});
self.on('dragleave drop', function(e) {
// timeout is needed because Firefox 3.6 fires the dragleave event on
// the previous element before firing dragenter on the next one
setTimeout( function() {
collection = collection.not(e.target);
if (collection.size() === 0) {
self.trigger('draghoverend');
}
}, 1);
});
});
};
function setText(text) {
$('p.target').text(text);
}
$(document).ready(function() {
$(window).draghover().on({
'draghoverstart': function() {
setText('enter');
},
'draghoverend': function() {
setText('leave');
}
});
});
However Firefox is still giving me problems when I drag over text items, here's a fiddle to demonstrate: http://jsfiddle.net/tusRy/6/
Is this a Firefox bug or can this be tamed with JS? Or is there a more robust method for performing all of this?
Thanks!
UPDATE: Updated fiddle to http://jsfiddle.net/tusRy/6/ to reduce clutter a bit. To explain the expected behavior of the fiddle:
Drag a file into the window and p.target should be "ENTER" colored yellow.
Drag a file out of the window and p.target should be "LEAVE" colored red.
Drop a file in the window and p.target should be "LEAVE" colored red.
In firefox, the LEAVE event is triggered when you drag the file over text.
As of version 22.0 Firefox is still doing this. When you drag over a text node it fires two kinds of dragenter and dragleave events: one where the event target and relatedTarget are BOTH the parent element of the text node, and another where the target is the parent element and the relatedTarget is the actual text node (not even a proper DOM element).
The workaround is just to check for those two kinds of events in your dragenter and dragleave handlers and ignore them:
try {
if(event.relatedTarget.nodeType == 3) return;
} catch(err) {}
if(event.target === event.relatedTarget) return;
I use a try/catch block to check the nodeType because occasionally events fire (inexplicably) from outside the document (eg. in other iframes) and trying to access their nodeType throws a permissions error.
Here's the implementation:
http://jsfiddle.net/9A7te/
1) Your dropzone should have only one child element, which might have everything else you need. Something like
<div id="#dropzone">
<div><!--Your contents here--></div>
</div>
2) Use this CSS:
#dropzone * { pointer-events: none; }
You might need to include the :before and :after since the * don't apply to them.
This should be enough to let the drop work in Firefox and Chrome. In your example, it should be enough to add:
body * { pointer-events: none; }
At the end of the CSS. I've done it here:
http://jsfiddle.net/djsbellini/eKttq/
Other examples:
http://jsfiddle.net/djsbellini/6yZV6/1/
http://jsfiddle.net/djsbellini/yR8t8/
I came up with kind of a solution, yet to test on other browsers other than Chrome and FF but working so far. This is how the setTimeout looks now:
setTimeout( function() {
var isChild = false;
// in order to get permission errors, use the try-catch
// to check if the relatedTarget is a child of the body
try {
isChild = $('body').find(e.relatedTarget).length ? true : isChild;
}
catch(err){} // do nothing
collection = collection.not(e.target);
if (collection.size() === 0 && !isChild) {
self.trigger('draghoverend');
}
}, 1);
The entire code here - http://jsfiddle.net/tusRy/13/.
The idea is to check if the related tag is a child of the body, in which case we are still in the Browsers and the draghoverend event should be not triggered. As this can throw errors when moving out of the windows, I used a try method to avoid it.
Well, perhaps somebody with more skills on JS could improve this :)
I found the answer in a non-selected answer to this SO question asking about dragleave firing on child elements. I have a <div> that has many children elements. An semi-opaque overlay <span> becomes visible over the <div> whenever there's a dragenter on the page. As you found, 'dragover' isn't like mouseover. It triggers dragleave whenever you hover over a child element.
The solution? Dragout It makes dragover work more like mouseover. Very short.

What's the best way of constantly resizing elements with the mouse?

What's the best way of constantly resizing elements using clicking and holding a resize image in the bottom-right corner of the element? Is there a specific empty element that has resizing built in or a style to use that would be better than using a while loop in JavaScript?
Here you go man:
http://jsfiddle.net/d9hsG/
function c(a){console.log(a)}
function coords(el){
var curleft, curtop;
curleft=curtop=0;
do{
curleft+=el.offsetLeft;
curtop+=el.offsetTop;
} while(el=el.offsetParent);
return [curleft,curtop];
}
Resizer = {
attach: function(el,minh,minw){
var rs=el.resizer=el.getElementsByClassName('drag')[0];
rs.resizeParent=el;
if(minh==undefined){
el.minh=rs.offsetHeight*2;
}
if(minw==undefined){
el.minw=rs.offsetWidth*2;
}
rs.onmousedown = Resizer.begin;
},
begin: function(e){
var el=Resizer.el=this.resizeParent;
var e=e||window.event;
this.lastx=e.clientX;
this.lasty=e.clientY;
document.onmousemove=Resizer.resize;
document.onmouseup=Resizer.end;
return false;
},
resize: function(e){
var e = e || window.event;
var x,y,mx,my,el,rs,neww,newh;
el=Resizer.el;
rs=el.resizer;
mx=e.clientX;
my=e.clientY;
neww=(el.clientWidth-(rs.lastx-mx));
newh=(el.clientHeight-(rs.lasty-my));
if(neww>=el.minw){
el.style.width=neww+'px';
rs.lastx=mx;
}
else{
rs.lastx-=parseInt(el.style.width)-el.minw;
el.style.width=el.minw+'px';
}
if(newh>=el.minh){
el.style.height=newh+'px';
rs.lasty=my;
}
else{
rs.lasty-=parseInt(el.style.height)-el.minh;
el.style.height=el.minh+'px';
}
return false;
},
end: function(){
document.onmouseup=null;
document.onmousemove=null;
}
};
window.onload=function(){
Resizer.attach(document.getElementsByClassName('resize')[0]);
}
Your HTML needs to look like:
<div class="resize"><
div class="drag"></div>
</div>
Neither one needs to be a div, but the resizeable one's class needs to be "resize" and the draggable element's class needs to be "drag".
Attach it with:
Resizer.attach(element);
...where element is the one to be resized.
Works on multiple elements, as shown in the jsfiddle. You can also pass in a minimum height and minimum width. If you don't, it automatically makes them twice the height of the draggable element.
It currently does have a problem when you're scrolled all the way down. I'm not sure how to counter it, but I'll work on it more later.
The general approach goes something like this:
When onmousedown fires on the resize target, start tracking onmousemove
When onmousemove fires, resize the element
When onmouseup fires, clear the onmousemove handler
So basically you just respond to events, there are no while loops or anything involved.
It can be somewhat tricky to accomplish so that it works nicely, so I would suggest seeing if there's a JS library you could use. A pretty simple way to get this behavior would be to use jQuery UI's resizable component

Categories

Resources