问题
I am trying to set up the following page where:
- If you click the button, you can see a div.
- If you click the div, you can see the next div.
- If you move the button, there is no »click« (desired behaviour)
The problem I am having is that if you move the div, the next div appears - this is not what I want. The "next div" should not be displayed after a drag event finishes on it.
Here is my code:
$(function() {
$("#button").draggable({
stack: 'div',
containment: "body"
});
});
$('#button').on('mouseup', function() {
if (!$(this).hasClass('ui-draggable-dragging')) {
// click function
$("#content").toggle();
}
});
$(function() {
$("#content").draggable({
stack: 'div',
containment: "body"
});
});
let containers = $('.trip').hide();
let firstContainer = containers.first().show();
containers.on('click', function() {
//Get current element and next sibling
let elem = $(this);
let next = elem.next('.trip');
//Does sibling exist?
if (next.length) {
next.show();
} else {
firstContainer.show();
}
elem.hide();
});
body {
width: 100vw;
height: 100vh;
padding: 0;
margin: 0;
left: 0;
top: 0;
background-color: grey;
}
#button {
width: 100px;
height: 100px;
background-color: cyan;
}
#content {
display: none;
cursor: all-scroll;
top: 10%;
left: 10%;
position: absolute;
}
.trip {
width: 200px;
height: 200px;
background-color: blue;
color: white;
}
<div id="button">Button</div>
<div id="content">
<div class="trip">div 1</div>
<div class="trip">div 2</div>
<div class="trip">div 3</div>
</div>
<script src="https://code.jquery.com/jquery-1.7.2.min.js"></script>
<script src="https://code.jquery.com/ui/1.8.21/jquery-ui.min.js"></script>
<script src="https://raw.githubusercontent.com/furf/jquery-ui-touch-punch/master/jquery.ui.touch-punch.min.js"></script>
Is there a way to solve this? :)
(a possible problem is also that pure JavaScript is mixed with jQuery)
Thanks
回答1:
The main problem to solve here is in distinguishing a regular click
event on #content
, from other "click like events" that are also triggered during completion of the element being dragged.
You're code currently has a method of doing that which you could re purpose for the desired behaviour:
if (! $(this).hasClass('ui-draggable-dragging')) {
/* This was a "regular click event"
}
So in the case of your code, you could revise it as follows:
$(function() {
/* Combine on ready logic into one place */
$("#button").draggable({
stack: 'div',
containment: "body"
});
$("#content").draggable({
stack: 'div',
containment: "body"
});
/* Hide all trip elements except for first */
$('.trip', '#content').not(':first').hide();
});
$('#button').on('mouseup', function() {
if (!$(this).hasClass('ui-draggable-dragging')) {
$("#content").toggle();
}
});
$('#content').on('mouseup', function() {
/* Reuse same logic in #button mouseup handler */
if (!$(this).hasClass('ui-draggable-dragging')) {
/*
If content element if not dragging, treat mouse up as conclusion
of click event and rotate visibility of trip elements like this
*/
let trip = $('.trip:visible', '#content');
let next = trip.next().length === 0 ?
$('.trip:first', '#content') : trip.next();
trip.hide();
next.show();
}
});
body {
width: 100vw;
height: 100vh;
padding: 0;
margin: 0;
left: 0;
top: 0;
background-color: grey;
}
#button {
width: 100px;
height: 100px;
background-color: cyan;
}
#content {
display: none;
cursor: all-scroll;
top: 10%;
left: 10%;
position: absolute;
}
.trip {
width: 200px;
height: 200px;
background-color: blue;
color: white;
}
<div id="button">Button</div>
<div id="content">
<div class="trip">div 1</div>
<div class="trip">div 2</div>
<div class="trip">div 3</div>
</div>
<script src="https://code.jquery.com/jquery-1.7.2.min.js"></script>
<script src="https://code.jquery.com/ui/1.8.21/jquery-ui.min.js"></script>
<script src="https://raw.githubusercontent.com/furf/jquery-ui-touch-punch/master/jquery.ui.touch-punch.min.js"></script>
回答2:
Actually, all you need is this bit of readable code,
- Assign a class
.draggable
to all your draggable elements - Use the new class as
stack: '.draggable'
- Register click to your
'#container'
, not on your.trip
elements - Use only one Event, the
"click"
one: - Hide all
.trip
but first using CSS.trip~.trip {display:none;}
jQuery( $ => {
const $cont = $('#content');
const $bttn = $('#button');
const $trip = $('.trip');
const tripL = $trip.length;
let i = 0;
$('.draggable').draggable({stack:'div', containment:'body'});
$bttn.on('click', function() {
if (!$(this).hasClass('ui-draggable-dragging')) $cont.toggle();
});
$cont.on('click', function() {
$trip.eq(++i % tripL).show().siblings($trip).hide();
});
});
html, body { height:100%; margin:0;}
body {
background-color: grey;
}
#button {
width: 100px;
height: 100px;
background-color: cyan;
}
#content {
display: none;
cursor: all-scroll;
top: 10%;
left: 10%;
position: absolute;
}
.trip {
width: 200px;
height: 200px;
background-color: blue;
color: white;
}
.trip ~ .trip {display: none;}
<!-- PS: Add class="draggable" to draggable elements -->
<div id="button" class="draggable">Button</div>
<div id="content" class="draggable">
<div class="trip" id="a">div 1</div>
<div class="trip" id="b">div 2</div>
<div class="trip" id="c">div 3</div>
</div>
<script src="https://code.jquery.com/jquery-1.7.2.min.js"></script>
<script src="https://code.jquery.com/ui/1.8.21/jquery-ui.min.js"></script>
<script src="https://raw.githubusercontent.com/furf/jquery-ui-touch-punch/master/jquery.ui.touch-punch.min.js"></script>
EDIT
For more contents see this answer: https://stackoverflow.com/a/57351517/383904
来源:https://stackoverflow.com/questions/57350862/jquery-finish-dragging-without-triggering-click-event