I am making a simple game of mine mobile-friendly.
The goal is to:
Make character walk if a touchstart event is sensed on right half of screen.
Stop character if a touchend event is sensed on the right half.
Jump the character if a touchend event happens on the left half of the screen.
I have the logic working perfectly for mouse up and down events so I'm pretty sure it's something to do inside the touchstart and end functions.
If two fingers are used as one press it seems to work fine.
If only one finger is used it doesn't work properly: touching anywhere starts the movement but nothing will stop it.
Here is the code for the touch inputs and associated function:
CheckWhichScreenHalf = function(e) {
loc = WindowToCanvas(e.pageX, e.pageY);
onScreenY = loc.y >= 0 && loc.y <= gameCanvas.height;
leftSideX = loc.x >= 0 && loc.x < gameCanvas.width/2;
rightSideX = loc.x > gameCanvas.width/2 && loc.x <= gameCanvas.width;
if (onScreenY && leftSideX){
return 'left';
}
else if (onScreenY && rightSideX){
return 'right';
}
else return 'neither';
};
TouchMove = false;
TouchJump = false;
gameCanvas.ontouchstart = function(e){
if (imagesHaveBeenLoaded) {
e.preventDefault();
for (var i = 0; i < e.touches.length; i++){
var side = CheckWhichScreenHalf(e.touches.item(i));
if (side === 'right'){
TouchMove = true;
}
}
}
}
gameCanvas.ontouchend = function(e){
if (imagesHaveBeenLoaded) {
e.preventDefault();
for (var i = 0; i < e.touches.length; i++){
var side = CheckWhichScreenHalf(e.touches.item(i));
if (side === 'right'){
TouchMove = false;
}
else if (side === 'left'){
playerJumping = true;
}
}
}
}
The game can be played here: http://webstudentwork.com/jgossling/MMWD/mp2/mp2.html
Hi I am trying to make drag drop feature in JS, It works fine in Firefox, but it doesn't work on chrome. I Think it is something to do with Event Deligation, I am attaching the link of my code base. Following are the steps to reproduce the problem:
Create a new Task
Drag it to another column
Now click on Edit or Delete Icon(E and D in circle).
Following are the Code highlights(Code is a bit bigger You can check it on Codepen):
JS:
$(function(){
function init(){
var mouseX = 0, // Mouse Position
mouseY = 0,
elmX = 0, // Element Position
elmY = 0,
pillers = $('.pillers'), // Task Container
pillerWidth = $('.pillers:nth-child(1)').width(), // Taks Container width
currentElm; // Current Element
/* When Left Mouse Button is Pressed */
$('.dragable').on('mousedown', function(e){
var temp;
$(this).addClass('rel');
mouseX = e.clientX; // Current Mouse Position and Store it to global variables
mouseY = e.clientY;
temp = +($(this).css('left').slice(0, -2)); // Get Element Position and if it not a number then change it to 0
elmX = null || isNaN(temp) ? 0 : temp;
temp = +($(this).css('top').slice(0, -2));
elmY = null || isNaN(temp) ? 0 : temp;
$(this).css({'z-index':'9999'}); // Increase the Z-Index of the Element so that it wont be overlapped by other element.
currentElm = $(this); // set the current value so that it could be use by mouse move
/* Some Hack for not let heighlight the data(Copied from net) */
document.body.focus();
document.onselectstart = function () { return false; };
$(this).ondragstart = function() { return false; };
return false;
}).on('mouseup',function(e){ // This will be fired when Mouse Button release back
if(currentElm !== null){
currentElm.removeClass('rel').prependTo('.arrived .tasks').css({ // Resetting the Position Object
left: 0,
top: 0
});
currentElm.css({'z-index' : '1'}); // Set Z-Index back to normal value.
currentElm = null; // Finally Set the Current Element to null so that it won't get dragged any more
}
}).on("mousemove", function(e){ // Mouse Move Event .. This is the main part, It will reposition the element with mouse pointer
if(currentElm !== undefined && currentElm !== null){
currentElm.addClass('draged').css({ // This sets the position of div element
left : (elmX + e.clientX - mouseX)+'px',
top : (elmY + e.clientY - mouseY)+'px'
});
/* Set Appropriate Class to Piller to Which The Element is going to be added */
if( e.clientX >= $('.pillers:nth-child(1)').offset().left && e.clientX < ($('.pillers:nth-child(1)').offset().left+pillerWidth) && e.clientY < $('.pillers:nth-child(1)').outerHeight()){
$('.pillers:nth-child(1)').addClass('arrived').siblings('.pillers').removeClass('arrived');
}else if(e.clientX >= $('.pillers:nth-child(2)').offset().left && e.clientX < ($('.pillers:nth-child(2)').offset().left+pillerWidth) && e.clientY < $('.pillers:nth-child(2)').outerHeight()){
$('.pillers:nth-child(2)').addClass('arrived').siblings('.pillers').removeClass('arrived');
}else if(e.clientX >= $('.pillers:nth-child(3)').offset().left && e.clientX < ($('.pillers:nth-child(3)').offset().left+pillerWidth) && e.clientY < $('.pillers:nth-child(3)').outerHeight()){
$('.pillers:nth-child(3)').addClass('arrived').siblings('.pillers').removeClass('arrived');
}else if(e.clientX >= $('.pillers:nth-child(4)').offset().left && e.clientX < ($('.pillers:nth-child(4)').offset().left+pillerWidth) && e.clientY < $('.pillers:nth-child(4)').outerHeight()){
$('.pillers:nth-child(4)').addClass('arrived').siblings('.pillers').removeClass('arrived');
}
}
});
$('a.remove').on('click',function(){
console.log('hey')
$(this).parents('.dragable').remove();
});
$('.add_task_button').on('click',function () {
var place= $(this).closest('.create_task_box'),
titl=place.find('input#title').val(),
disc=place.find('textarea#discription').val(),
time = new Date(),
format = time.toLocaleDateString();
if(titl || disc){
var val = $('.temp').clone(true).removeClass('temp hide').insertBefore(place);
val.find('#TaskHeading').val(titl).end().find('#task-discription').text(disc).end().find('.time').text(format).css({
left: 0,
top: 0
});
}
$('input#title, textarea#discription').val('');
});
$(document).on("click", ".edit", function(){
e.stopPropagation();
if($(this).is('.done')){
$(this).removeClass('done');
$(this).closest('.task-unit').addClass('dragable').find('input, textarea').attr('readonly', 'readonly').addClass('readonly');
}else{
$(this).addClass('done');
var task = $(this).closest('.dragable');
task.removeClass('dragable').find('input, textarea').removeAttr('readonly').removeClass('readonly');
}
});
}
init();
});
I am not mentioning the HTML and CSS part here because it will take a lot of space.. You can see full code Here on Codepen.
Let me know if anything else required.
The problem is, you have an object (parent) with a mousedown event and inside it, another object (children) with a click event. It seems that in Chrome, the first event (mousedown) is capturing the click over the buttons.
As a workaround, you can do this:
have a function for the mousedown event on the parent element.
unbind the mousedown event when the user does a mouseover event on the children.
bind again the function to the parent when the user does a mouseout off the parent.
As an example:
$(".theparent").on("mousedown",function(){
doThings();
});
$(".thechildren").on("click",function(){
alert("Child");
});
$(".thechildren").on("mouseover",function(){
$(this).closest(".theparent").off("mousedown");
console.log("Off");
});
$(".thechildren").on("mouseout",function(){
$(this).closest(".theparent").on("mousedown",doThings);
console.log("on");
});
function doThings(){
alert("Parent");
}
.theparent{
width:200px;
height:100px;
background-color:#3a3a3a;
position:absolute;
}
.thechildren{
position:relative;
background-color:#FF0000;
width:50px;
height:50px;
cursor:pointer;
left:50px;
top:25px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="theparent">
<div class="thechildren">Child</div>
</div>
See it working on fiddle.
I'm fairly new to JavaScript, so any help would be awesome!
I created this small block of code that let's me grab a div and drag it around. I assign the "dragme" id to the div and all is fine and dandy. The problem is that if I replace that div from my html and put an img element instead (obviously assigning the "dragme" id to the img), things don't work as expected.
When I click to drag the img, it actually moves for about 3 or 4 pixels then it freezes until I lift the mouse button (mouseup).
Is there some property or characteristic that would prevent the img element from acting the same way as the div does?
var isClicked = false;
var startClientX = 0;
var startClientY = 0;
var startLeft = 0;
var startTop = 0;
window.addEventListener("load", addListeners, true);
function addListeners()
{
document.getElementById("dragme").addEventListener("mousedown", mouseIsDown, false);
document.getElementById("dragme").addEventListener("mouseup", mouseIsUp, false);
window.addEventListener("mousemove", moveImage, false);
function mouseIsDown(e)
{
if (isClicked == false)
{
isClicked = true;
startClientX = e.clientX;
startClientY = e.clientY;
startLeft = document.getElementById("dragme").offsetLeft;
startTop = document.getElementById("dragme").offsetTop;
}
}
function mouseIsUp()
{
if (isClicked == true)
{
isClicked = false;
}
}
function moveImage(e)
{
if (isClicked == true)
{
imageLeftDif = e.clientX - startClientX;
imageTopDif = e.clientY - startClientY;
var newLeftPos = (startLeft + imageLeftDif) + "px";
var newTopPos = (startTop + imageTopDif) + "px";
document.getElementById("dragme").style.left = newLeftPos;
document.getElementById("dragme").style.top = newTopPos;
}
}
}
This fixed the problem (answer provided as a comment by syazdani):
I'd venture to say that the built in browser drag and drop for images
is kicking in. Try e.preventDefault and return false in the mousedown
handler. – syazdani Dec 2 '12 at 17:26
I have a div, with a scroll bar, When it reaches the end, my page starts scrolling. Is there anyway I can stop this behavior ?
You can inactivate the scrolling of the whole page by doing something like this:
<div onmouseover="document.body.style.overflow='hidden';" onmouseout="document.body.style.overflow='auto';"></div>
Found the solution.
http://jsbin.com/itajok
This is what I needed.
And this is the code.
http://jsbin.com/itajok/edit#javascript,html
Uses a jQuery Plug-in.
Update due to deprecation notice
From jquery-mousewheel:
The old behavior of adding three arguments (delta, deltaX, and deltaY)
to the event handler is now deprecated and will be removed in later
releases.
Then, event.deltaY must now be used:
var toolbox = $('#toolbox'),
height = toolbox.height(),
scrollHeight = toolbox.get(0).scrollHeight;
toolbox.off("mousewheel").on("mousewheel", function (event) {
var blockScrolling = this.scrollTop === scrollHeight - height && event.deltaY < 0 || this.scrollTop === 0 && event.deltaY > 0;
return !blockScrolling;
});
Demo
The selected solution is a work of art. Thought it was worthy of a plugin....
$.fn.scrollGuard = function() {
return this
.on( 'wheel', function ( e ) {
var event = e.originalEvent;
var d = event.wheelDelta || -event.detail;
this.scrollTop += ( d < 0 ? 1 : -1 ) * 30;
e.preventDefault();
});
};
This has been an ongoing inconvenience for me and this solution is so clean compared to other hacks I've seen. Curious to know how more about how it works and how widely supported it would be, but cheers to Jeevan and whoever originally came up with this. BTW - stackoverflow answer editor needs this!
UPDATE
I believe this is better in that it doesn't try to manipulate the DOM at all, only prevents bubbling conditionally...
$.fn.scrollGuard2 = function() {
return this
.on( 'wheel', function ( e ) {
var $this = $(this);
if (e.originalEvent.deltaY < 0) {
/* scrolling up */
return ($this.scrollTop() > 0);
} else {
/* scrolling down */
return ($this.scrollTop() + $this.innerHeight() < $this[0].scrollHeight);
}
})
;
};
Works great in chrome and much simpler than other solutions... let me know how it fares elsewhere...
FIDDLE
You could use a mouseover event on the div to disable the body scrollbar and then a mouseout event to activate it again?
E.g. The HTML
<div onmouseover="disableBodyScroll();" onmouseout="enableBodyScroll();">
content
</div>
And then the javascript like so:
var body = document.getElementsByTagName('body')[0];
function disableBodyScroll() {
body.style.overflowY = 'hidden';
}
function enableBodyScroll() {
body.style.overflowY = 'auto';
}
As answered here, most modern browsers now support the overscroll-behavior: none; CSS property, that prevents scroll chaining. And that's it, just one line!
Here's a cross-browser way to do this on the Y axis, it works on desktop and mobile. Tested on OSX and iOS.
var scrollArea = this.querySelector(".scroll-area");
scrollArea.addEventListener("wheel", function() {
var scrollTop = this.scrollTop;
var maxScroll = this.scrollHeight - this.offsetHeight;
var deltaY = event.deltaY;
if ( (scrollTop >= maxScroll && deltaY > 0) || (scrollTop === 0 && deltaY < 0) ) {
event.preventDefault();
}
}, {passive:false});
scrollArea.addEventListener("touchstart", function(event) {
this.previousClientY = event.touches[0].clientY;
}, {passive:false});
scrollArea.addEventListener("touchmove", function(event) {
var scrollTop = this.scrollTop;
var maxScroll = this.scrollHeight - this.offsetHeight;
var currentClientY = event.touches[0].clientY;
var deltaY = this.previousClientY - currentClientY;
if ( (scrollTop >= maxScroll && deltaY > 0) || (scrollTop === 0 && deltaY < 0) ) {
event.preventDefault();
}
this.previousClientY = currentClientY;
}, {passive:false});
I wrote resolving for this issue
var div;
div = document.getElementsByClassName('selector')[0];
div.addEventListener('mousewheel', function(e) {
if (div.clientHeight + div.scrollTop + e.deltaY >= div.scrollHeight) {
e.preventDefault();
div.scrollTop = div.scrollHeight;
} else if (div.scrollTop + e.deltaY <= 0) {
e.preventDefault();
div.scrollTop = 0;
}
}, false);
If I understand your question correctly, then you want to prevent scrolling of the main content when the mouse is over a div (let's say a sidebar). For that, the sidebar may not be a child of the scrolling container of the main content (which was the browser window), to prevent the scroll event from bubbling up to its parent.
This possibly requires some markup changes in the following manner:
<div id="wrapper">
<div id="content">
</div>
</div>
<div id="sidebar">
</div>
See it's working in this sample fiddle and compare that with this sample fiddle which has a slightly different mouse leave behavior of the sidebar.
See also scroll only one particular div with browser's main scrollbar.
this disables the scrolling on the window if you enter the selector element.
works like charms.
elements = $(".selector");
elements.on('mouseenter', function() {
window.currentScrollTop = $(window).scrollTop();
window.currentScrollLeft = $(window).scrollTop();
$(window).on("scroll.prevent", function() {
$(window).scrollTop(window.currentScrollTop);
$(window).scrollLeft(window.currentScrollLeft);
});
});
elements.on('mouseleave', function() {
$(window).off("scroll.prevent");
});
You can inactivate the scrolling of the whole page by doing something like this but display the scrollbar!
<div onmouseover="document.body.style.overflow='hidden'; document.body.style.position='fixed';" onmouseout="document.body.style.overflow='auto'; document.body.style.position='relative';"></div>
$this.find('.scrollingDiv').on('mousewheel DOMMouseScroll', function (e) {
var delta = -e.originalEvent.wheelDelta || e.originalEvent.detail;
var scrollTop = this.scrollTop;
if((delta < 0 && scrollTop === 0) || (delta > 0 && this.scrollHeight - this.clientHeight - scrollTop === 0)) {
e.preventDefault();
}
});
Based on ceed's answer, here is a version that allows nesting scroll guarded elements. Only the element the mouse is over will scroll, and it scrolls quite smoothly. This version is also re-entrant. It can be used multiple times on the same element and will correctly remove and reinstall the handlers.
jQuery.fn.scrollGuard = function() {
this
.addClass('scroll-guarding')
.off('.scrollGuard').on('mouseenter.scrollGuard', function() {
var $g = $(this).parent().closest('.scroll-guarding');
$g = $g.length ? $g : $(window);
$g[0].myCst = $g.scrollTop();
$g[0].myCsl = $g.scrollLeft();
$g.off("scroll.prevent").on("scroll.prevent", function() {
$g.scrollTop($g[0].myCst);
$g.scrollLeft($g[0].myCsl);
});
})
.on('mouseleave.scrollGuard', function() {
var $g = $(this).parent().closest('.scroll-guarding');
$g = $g.length ? $g : $(window);
$g.off("scroll.prevent");
});
};
One easy way to use is to add a class, such as scroll-guard, to all the elements in the page that you allow scrolling on. Then use $('.scroll-guard').scrollGuard() to guard them.
If you apply an overflow: hidden style it should go away
edit: actually I read your question wrong, that will only hide the scroll bar but I don't think that's what you are looking for.
I couldn't get any of the answers to work in Chrome and Firefox, so I came up with this amalgamation:
$someElement.on('mousewheel DOMMouseScroll', scrollProtection);
function scrollProtection(event) {
var $this = $(this);
event = event.originalEvent;
var direction = (event.wheelDelta * -1) || (event.detail);
if (direction < 0) {
if ($this.scrollTop() <= 0) {
return false;
}
} else {
if ($this.scrollTop() + $this.innerHeight() >= $this[0].scrollHeight) {
return false;
}
}
}
i use this code,
to scroll overflow div (hidden) in ipad , and works expect its not smooth , is there any way i can make it smooth scroll ?
function initMobileScroll(ele) {
var mobileScrollArea = document.getElementById(ele);
mobileScrollArea.addEventListener('touchstart', function(event){
touchstart (event);
});
mobileScrollArea.addEventListener('touchmove', function(event){
touchmove (event);
});
// let’s set the starting point when someone first touches
function touchstart (e) {
startY = e.touches[0].pageY;
startX = e.touches[0].pageX;
}
// calls repeatedly while the user’s finger is moving
function touchmove(e) {
var touches = e.touches[0];
// override the touch event’s normal functionality
e.preventDefault();
// y-axis
var touchMovedY = startY - touches.pageY;
startY = touches.pageY; // reset startY for the next call
mobileScrollArea.scrollTop = mobileScrollArea.scrollTop + touchMovedY;
// x-axis
var touchMovedX = startX - touches.pageX;
startX = touches.pageX; // reset startX for the next call
mobileScrollArea.scrollLeft = mobileScrollArea.scrollLeft + touchMovedX;
}
}
code source : http://www.flexmls.com/developers/2011/04/13/ipad-and-single-finger-scrolling-in-flexmls/
add this to your css:
-webkit-overflow-scrolling: touch;
Compatibility
Safari: iOS 5
Android Browser: 3.0
Blackberry Browser: 6
Chrome for Mobile
Firefox Mobile
IE Mobile: 9
Opera Mobile
example: JSfiddle
reference: barrow.io - Overflow scrolling
Take a look at this: http://cubiq.org/iscroll-4
Looks similar to what I was trying to do.. Good luck
if (evt.type == "touchstart")
{
tsStartY = evt.originalEvent.changedTouches[0].clientY;
}
if (evt.type == "touchend")
{
var te = evt.originalEvent.changedTouches[0].clientY;
var delta = tsStartY - te;
if (tsStartY > te) {
// going down
this.transY += delta;
if (this.transY > this.minY)
{
this.transY = this.minY;
}
}
if (tsStartY < te)
{
// going up
this.transY -= -delta;
if (this.transY < this.maxY) {
this.transY = this.maxY;
}
}
}