Set position of jquery draggable element while dragging - javascript

In my web app, there is a draggable element.
I need to set the left position of this element when the element reaches a certain limit while dragging.
Using jQuery draggable widget, I have access to the position of the element:
function drag(e, ui) {
console.log(ui.position.left);
}
Let say my left attribute is setted to 1100px, I need to set it to 500px and this, without stopping the dragging.
I have three functions: dragStart, drag, and gradEnd.
Currently, I managed to get only one result: when setting ui.position.left = 500; on the drag function (using a condition), the left position is set to 500 but of course, the element is then stuck at 500px. The reason is that every time the drag function is triggered, the left position is setted to 500.
If the code runs only once the line ui.position.left = 500; the position left attribute is set to 500, but directly reset to 1100.
How can I set the left attribute once and for all?
$("#divId").draggable({
drag: drag,
})
function drag(e, ui) {
if (ui.position.top > 50) {
ui.position.left = 100;
}
}
#divId {
height: 70px;
background-color: white;
border: 4px solid #000000;
text-align: center;
color: black;
cursor: grab;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<div id="divId">
Bubble
</div>

I am not sure how jQuery Draggable handles things under the hood, but even after setting ui.position.left = 100, it does not register in the event until after dragging has stopped - that is why I opted to check the actual CSS property of the element that is being targeted.
I have also provided an example (closure/functional based) which demonstrates how to handle this without having to check CSS..
First example:
$("#divId").draggable({
drag: drag
});
function drag(e, ui) {
if (ui.position.top > 50) {
$("#container").css('padding-left', '100px');
$(this).css('left', '0px');
}
if (ui.position.left < 0) {
ui.position.left = 0
}
}
#divId {
height: 70px;
background-color: white;
border: 4px solid #000000;
text-align: center;
color: black;
width: 300px;
cursor: grab;
}
#container {
height: 100vh;
width: 1000px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<div id="container">
<div id="divId">
Bubble
</div>
</div>
Second example, more of a 'closure based functional approach': does not require you to check CSS..
$("#divId").draggable({
drag: drag()
});
function drag(e, ui) {
let TRIGGER = false, TOP_THRESHOLD = 50, LEFT_POSITION = 100;
return function(e, ui) {
if (TRIGGER) {
ui.position.left = LEFT_POSITION;
} else if (ui.position.top > TOP_THRESHOLD) {
TRIGGER = true;
ui.position.left = LEFT_POSITION;
}
}
}
#divId {
height: 70px;
background-color: white;
border: 4px solid #000000;
text-align: center;
color: black;
cursor: grab;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<div id="divId">
Bubble
</div>

Related

I have a problem with understanding the event system

I have this code:
<template>
<div class="chart"
v-bind:style="chartStyleObject"
v-on:mousedown.left="initHandleMousedown($event)"
v-on:mouseup.left="initHandleMouseup()"
v-on:mouseout="initHandleMouseup()">
<div class="chartContent">
</div>
<!-- <div class="chartContent"> end -->
</div>
<!-- <div class="chart"> end -->
</template>
<script>
import axios from 'axios';
export default{
created () {
},
data () {
return {
ticket: null,
chartStyleObject: {
width: '500px',
widthWrapper: '1600px',
heightWrapper: '500px',
height: '247px',
marginTop: '15px',
marginRight: '0px',
marginBottom: '0px',
marginLeft: '15px',
},
XCoord: null,
YCoord: null,
}
},
methods: {
initHandleMousedown(event) {
this.startMousedownXCoord = event.clientX;
this.startMousedownYCoord = event.clientY;
this.XCoord = event.clientX;
this.YCoord = event.clientY;
console.log('XCoord', this.XCoord);
console.log('YCoord', this.YCoord);
window.addEventListener('mousemove', this.initHandleMouseMove);
},
initHandleMouseMove(event) {
this.XCoord = event.clientX;
this.YCoord = event.clientY;
console.log('XCoord', this.XCoord);
console.log('YCoord', this.YCoord);
},
initHandleMouseup() {
window.removeEventListener('mousemove', this.initHandleMouseMove);
},
},
}
</script>
<style scoped>
.chart{
position: relative;
border-radius: 10px;
padding: 27px 10px 10px 10px;
background-color: #45788b;
box-sizing: border-box;
cursor: move;
}
.chart .chartContent{
position: relative;
top: 0;
left: 0;
height: 100%;
width: 100%;
margin: 0 0 0 0;
background-color: #2f2c8b;
}
</style>
HTML design consists of 2 blocks:
(parent and child)
The event is tied to the parent tag `<div class =" chart ">`
Also, the parent block has padding on all 4 sides:
If you click on the parent block and drive with the mouse (holding the button pressed) without affecting the padding space, the mousemove event will fire without problems.
But as soon as the mouse cursor touches the padding territory, the event ceases to function.
If you click on the padding, the event also works correctly - but it stops working if I move the mouse cursor over the block space outside the paddings (internal space)
Question:
Why is this happening - and is this behavior normal for js + nuxt.js?
I can't exactly follow your descriptions of the various regions of the page but I can have a go at explaining what I think you're seeing.
The key to this is that you have a mouseout listener that removes your mousemove listener. The mouseout event propagates, which means it will fire even if the mouseout occurred on a child element. Contrast with mouseleave which will only fire if the event occurs on the element itself.
The example below illustrates how a mouseout listener will fire even if the mouse cursor doesn't leave the root element. Just moving the cursor outside a child is sufficient.
document.getElementById('outer').addEventListener('mouseout', () => {
document.getElementById('out').innerHTML += 'mouseout\n'
})
div {
border: 1px solid;
display: inline-block;
padding: 20px;
}
<div id="outer">
<div></div>
</div>
<pre id="out"></pre>
I suspect that when you observe the event ceasing to function what is actually happening is that a mouseout event is occurring and that is removing the mousemove listener.
skirtle answer is correct. I am only providing this answer to illustrate how to do it using your own code. The only line I changed was this v-on:mouseleave="initHandleMouseup(). Notice I changed it to mouseout to mouseleave.
To summarize:
mouseleave is fired once per element regardless of its children
hover.
mouseout is fired every time the element abandoned (whether
moving the mouse away or hovering over its children).
new Vue({
el: "#app",
template: `
<div class="chart"
v-bind:style="chartStyleObject"
v-on:mousedown.left="initHandleMousedown($event)"
v-on:mouseup.left="initHandleMouseup()"
v-on:mouseleave="initHandleMouseup()">
<div class="chartContent">
</div>
<!-- <div class="chartContent"> end -->
</div>
<!-- <div class="chart"> end -->
`,
created: function() {},
data() {
return {
ticket: null,
chartStyleObject: {
width: '500px',
widthWrapper: '1600px',
heightWrapper: '500px',
height: '247px',
marginTop: '15px',
marginRight: '0px',
marginBottom: '0px',
marginLeft: '15px',
},
XCoord: null,
YCoord: null,
}
},
methods: {
initHandleMousedown: function(event) {
this.startMousedownXCoord = event.clientX;
this.startMousedownYCoord = event.clientY;
this.XCoord = event.clientX;
this.YCoord = event.clientY;
console.log('XCoord', this.XCoord);
console.log('YCoord', this.YCoord);
window.addEventListener('mousemove', this.initHandleMouseMove);
},
initHandleMouseMove: function(event) {
this.XCoord = event.clientX;
this.YCoord = event.clientY;
console.log('XCoord', this.XCoord);
console.log('YCoord', this.YCoord);
},
initHandleMouseup: function() {
window.removeEventListener('mousemove', this.initHandleMouseMove);
}
}
});
.chart {
position: relative;
border-radius: 10px;
padding: 27px 10px 10px 10px;
background-color: #45788b;
box-sizing: border-box;
cursor: move;
}
.chart .chartContent {
position: relative;
top: 0;
left: 0;
height: 100%;
width: 100%;
margin: 0 0 0 0;
background-color: #2f2c8b;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id='app'></div>
To see the different between mouseout/mouseover vs mouseenter/mouseleave events see this demo (taken from jQuery documentation) :
var i = 0;
$("div.overout")
.mouseout(function() {
$("p", this).first().text("mouse out");
$("p", this).last().text(++i);
})
.mouseover(function() {
$("p", this).first().text("mouse over");
});
var n = 0;
$("div.enterleave")
.on("mouseenter", function() {
$("p", this).first().text("mouse enter");
})
.on("mouseleave", function() {
$("p", this).first().text("mouse leave");
$("p", this).last().text(++n);
});
div.out {
width: 40%;
height: 120px;
margin: 0 15px;
background-color: #d6edfc;
float: left;
}
div.in {
width: 60%;
height: 60%;
background-color: #fc0;
margin: 10px auto;
}
p {
line-height: 1em;
margin: 0;
padding: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="out overout">
<p>move your mouse</p>
<div class="in overout">
<p>move your mouse</p>
<p>0</p>
</div>
<p>0</p>
</div>
<div class="out enterleave">
<p>move your mouse</p>
<div class="in enterleave">
<p>move your mouse</p>
<p>0</p>
</div>
<p>0</p>
</div>

html5 drag and drop, getting dragged item position

is there any way to get the dragged item position in the dragover/dragenter/dragleave events in terms of X and Y related to the page? i know i can get the mouse position by calling event.clientX or event.clientY, but i would like to know the position of the floating element that created by the drag (the one that can be set by event.dataTransfer.setDragImage() function)
for example this code will print the mouse location when dragging, and not the real offset of the floating element:
function dragOver(event) {
console.log(event.clientX
});
With help of jQuery library you can achieve it,You can use console to print values, just to show you I'm printing positions on screen.
$('#dragMe').draggable(
{
containment: $('body'),
drag: function(){
var position = $(this).position();
var xPos = position.left;
var yPos = position.top;
$('#positionX').text('positionX: ' + xPos);
$('#positionY').text('positionY: ' + yPos);
},
accept: '#dragMe',
over : function(){
$(this).animate({'border-width' : '5px',
'border-color' : '#0f0'
}, 500);
$('#dragThis').draggable('option','containment',$(this));
}
});
#dragMe {
width: 10em;
height: 6em;
padding: 0.5em;
border: 4px solid #ccc;
border-radius: 0 2em 2em 2em;
background-color: #fff;
background-color: rgba(255,255,255,0.5);
}
#dropMe {
width: 12em;
height: 12em;
padding: 0.5em;
margin: 0 auto;
}
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<div id="dragMe">
<p>DRAG ME</p>
<ul>
<li id="positionX"></li>
<li id="positionY"></li>
</ul>
</div>
<div id="dropMe"></div>

jQuery hover is too slow

Please run the snippet and drag you mouse over the bar to make it red.
If you drag the mouse very slowly, you will fill it red, but if you move it fast, there will be white holes in it.
How to fix it? (the white holes)
I want to make a bar divided into 500 parts and if you hover it, it becomes red and being able to drag fast and fill it without holes.
Any help appreciated :)
$(function() {
var line = $("#line");
for ( var i = 0; i < 500; i++) {
line.append('<div class="tile" id="t'+(i+1)+'"></div>');
}
var tile = $(".tile");
tile.hover (
function() { //hover-in
$(this).css("background-color","red");
},
function() { //hover-out
}
);
});
#line{
height: 50px;
background-color: #000;
width: 500px;
}
.tile {
height: 50px;
float: left;
background-color: #ddd;
width: 1px;
}
<script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.2.1.min.js"></script>
<div id="line"></div>
With your design one way would be to iterate over the first to your current hovered element and fill it, which would lead no spaces. That said you may want to consider using the HTML5 Canvas and drawing a rectangle from 0 to your mouse position, which will perform significantly faster.
$(function() {
var line = $("#line");
for ( var i = 0; i < 500; i++) {
line.append('<div class="tile" id="t'+(i+1)+'"></div>');
}
var tile = $(".tile");
tile.hover (
function() { //hover-in
var self = this;
$("#line").children().each(function(){
$(this).css("background-color","red");
if(this == self) return false;
});
},
function() { //hover-out
}
);
});
#line{
height: 50px;
background-color: #000;
width: 500px;
}
.tile {
height: 50px;
float: left;
background-color: #ddd;
width: 1px;
}
<script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.2.1.min.js"></script>
<div id="line"></div>
Edit
Below is an example doing the same task but using the HTML 5 Canvas:
$("#line").mousemove(function(e){
var canvas = $(this)[0];
var ctx = canvas.getContext("2d");
var rect = canvas.getBoundingClientRect()
var x = e.clientX - rect.left;
ctx.fillStyle="red";
ctx.fillRect(0, 0, x, canvas.height);
});
#line{ background-color: #ddd; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<canvas id="line" width=500 height=50 ></canvas>
This is another approach with nextUntil to select siblings..
$(function() {
var line = $("#line");
for ( var i = 0; i < 500; i++) {
line.append('<div class="tile" id="t'+(i+1)+'"></div>');
}
var tile = $(".tile");
line.on( 'mouseover', function(ev){
$('.tile').first().nextUntil( $('.tile').eq(ev.pageX) ).css("background-color","red");
});
line.on( 'mouseleave', function(ev){
$('.tile').css("background-color","#ddd");
});
});
#line{
height: 50px;
background-color: #000;
width: 500px;
}
.tile {
height: 50px;
float: left;
background-color: #ddd;
width: 1px;
}
<script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.2.1.min.js"></script>
<div id="line"></div>
Another solution makes use of jQuery's mousemove method. This allows the bar to go both forward and backwards, simply following the cursors position.
This detects movement inside of the div, then I calculate the position of the cursor within the div as a percentage and apply it as the width of the red bar.
$( ".bar" ).mousemove(function( event ) {
var xCord = event.pageX;
xPercent = (xCord + $('.pct').width()) / $( document ).width() * 100;
$('.pct').width(xPercent+'%');
});
.bar{
background:'#999999';
width:50%;
height:50px;
}
.pct{
height:100%;
background:red;
width:0%;
}
<script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.2.1.min.js">
</script>
<div class="bar" style="background:#999999">
<div class="pct"></div>
</div>

Custom cursor with drag and drop an HTML element without libraries

I have an HTML page which has some draggable elements. Our specs say that hovering mouse on such element the cursor must be grab , and during drag cursor must be grabbing .
I know it is possible to set dropEffect which changes cursor appearance above drop zone, but there are very little options: copy, move, link, and none -- no custom or alike.
I have tried to change cursor with Javascript and CSS, like setting cursor: grabbing; when ondragstart is fired. But browser default move cursor appears instead when dragging on drop zone.
So the question is: What am I missing to show grabbing cursor () during drag?
Unfortunately I cannot use JQuery or other helping libraries in the solution. Thanks in advance!
var onDragStart = function(event) {
event.dataTransfer.setData("Text", event.target.id);
event.currentTarget.classList.add("being-dragged");
};
var onDragEnd = function(event) {
event.currentTarget.classList.remove("being-dragged");
};
var onDragOver = function(event) {
event.preventDefault();
};
.dropzone {
width: 500px;
height: 200px;
background-color: silver;
}
.block {
position: absolute;
background-color: pink;
margin: 10px;
border: 20px solid pink;
}
.draggable {
cursor: -webkit-grab;
cursor: grab;
}
.being-dragged {
cursor: -webkit-grabbing;
cursor: grabbing;
background-color: red;
}
<div class = "dropzone"
ondragover = "onDragOver(event);"
>
Grab and drag block around
<div class = "draggable block"
draggable = "true"
ondragstart = "onDragStart(event);"
ondragend = "onDragEnd(event);"
>
I'm draggable
</div>
</div>
It seems that browsers don't allow changing the cursor at the beginning of a drag & drop operation. I don't know why but it's a known issue, I believe they will in the future.
If jQuery is not an option, a possible way around is to implement a drag & drop from scratch, using mouse events and cloning the source element:
var onDragStart = function (event) {
event.preventDefault();
var clone = event.target.cloneNode(true);
clone.classList.add("dragging");
event.target.parentNode.appendChild(clone);
var style = getComputedStyle(clone);
clone.drag = {
x: (event.pageX||(event.clientX+document.body.scrollLeft)) - clone.offsetLeft + parseInt(style.marginLeft),
y: (event.pageY||(event.clientY+document.body.scrollTop)) - clone.offsetTop + parseInt(style.marginTop),
source: event.target
};
};
var onDragMove = function (event) {
if (!event.target.drag) {return;}
event.target.style.left = ((event.pageX||(event.clientX+document.body.scrollLeft)) - event.target.drag.x) + "px";
event.target.style.top = ((event.pageY||(event.clientY+document.body.scrollTop)) - event.target.drag.y) + "px";
};
var onDragEnd = function (event) {
if (!event.target.drag) {return;}
// Define persist true to let the source persist and drop the target, otherwise persist the target.
var persist = true;
if (persist || event.out) {
event.target.parentNode.removeChild(event.target);
} else {
event.target.parentNode.removeChild(event.target.drag.source);
}
event.target.classList.remove("dragging");
event.target.drag = null;
};
var onDragOver = function (event) {
event.preventDefault();
};
.dropzone {
width: 500px;
height: 200px;
background-color: silver;
}
.block {
position: absolute;
background-color: pink;
margin: 10px;
border: 20px solid pink;
}
.draggable {
position: absolute;
cursor: pointer; /* IE */
cursor: -webkit-grab;
cursor: grab;
}
.dragging {
cursor: -webkit-grabbing;
cursor: grabbing;
background-color: red;
}
<div class="dropzone" onmouseover="onDragOver(event);">
Grab and drag block around
<div class = "draggable block"
onmousedown = "onDragStart(event);"
onmousemove = "onDragMove(event);"
onmouseup = "onDragEnd(event);"
onmouseout = "event.out = true; onDragEnd(event);"
>
I'm draggable
</div>
</div>
It is a known issue reported here
While dragging, the cursor will automatically changed to normal.
My tries gave me the following. Gave an active on the element with grabbing cursor. While it is active, the cursor will change but once you start the drag, it will change automatically.
I tried to set body cursor to grabbing on dragstart but no result. Even it is not working.
var onDragStart = function(event) {
event.dataTransfer.setData("Text", event.target.id);
event.currentTarget.classList.add("being-dragged");
};
var onDragEnd = function(event) {
event.currentTarget.classList.remove("being-dragged");
};
var onDragOver = function(event) {
event.preventDefault();
};
.dropzone {
width: 500px;
height: 200px;
background-color: silver;
}
.block {
position: absolute;
background-color: pink;
margin: 10px;
border: 20px solid pink;
}
.draggable {
cursor: -webkit-grab;
cursor: grab;
}
.draggable:active{
cursor : -moz-grabbing;
cursor: -webkit-grabbing;
cursor: grabbing;
}
.being-dragged{
background-color: red;
cursor : -moz-grabbing;
cursor: -webkit-grabbing;
cursor: grabbing;
}
<div class = "dropzone"
ondragover = "onDragOver(event);"
>
Grab and drag block around
<div class = "draggable block"
draggable = "true"
ondragstart = "onDragStart(event);"
ondragend = "onDragEnd(event);"
>
I'm draggable
</div>
</div>
I went through a lot of pain trying to figure this out. The accepted answer was the best answer on the web, but best practices now would be to use the element's .setPointerCapture event, which allows you to listen to and act upon drag like behaviors on an element without being boxed into the narrow behavior of the Drag API. One way to do it would be like so:
el.onpointerdown = ev => {
el.onpointermove = pointerMove
el.setPointerCapture(ev.pointerId)
}
pointerMove = ev => {
console.log('Dragged!')
}
el.onpointerup = ev => {
el.onpointermove = null
el.releasePointerCapture(ev.pointerId)
}
The obvious gift being the fact that there is no cursor hijacking to be found sneaking in the backdoor here.
I know just a little bit about draggable elements with pure JavaScript and I'm sorry that I can't explain the following.
The problem was that the onDragEnd never get fired so I've searched something and find this example with draggable elements.
Now, if you change the function of the onDragStart event it will work but I think you have to change the cursor in another way like to change the class of the body onDragStart
var onDragStart = function(event) {
event.dataTransfer.setData("Text", event.target.id);
event.currentTarget.classList.add("being-dragged");
};
All in one
var onDragStart = function(event) {
event.dataTransfer.setData("Text", event.target.id);
event.currentTarget.classList.add("being-dragged");
};
var onDragEnd = function(event) {
event.currentTarget.classList.remove("being-dragged");
};
var onDragOver = function(event) {
event.preventDefault();
};
.dropzone {
width: 500px;
height: 500px;
background-color: silver;
}
.block {
width: 200px;
height: 50px;
background-color: pink;
}
.draggable1 {
cursor: -webkit-grab;
cursor: grab;
}
.being-dragged {
cursor: -webkit-grabbing;
cursor: grabbing;
background-color: red;
}
<div class="dropzone" ondragover="onDragOver(event);">
<div class="draggable1 block" draggable="true" ondragstart="onDragStart(event);" ondragend="onDragEnd(event);">
I'm draggable
</div>
</div>
Try this ! It works for me !
.draggable {
cursor: -webkit-grab;
cursor: grab;
}
.draggable:active {
cursor: -webkit-grabbing;
cursor: grabbing;
}
I spent sometime to find solution for this, ended with this trick. I feel this is best way less code and apt work.
.drag{
cursor: url('../images/grab.png'), auto;
}
.drag:active {
cursor: url('../images/grabbing.png'), auto;
}

Applying background color based on scrolling content

Here is my JsFiddle
I want to apply background-color change property to circle when the window slides. Like in the beginning only first circle will have background-color. and when the images slides to second screen the second circle will have only color.
Can anybody guide me how to achieve that.
JQuery:
$(document).ready(function () {
setInterval(function () {
var A = $('.gallery').scrollLeft();
if (A < 993) {
$('.gallery').animate({
scrollLeft: '+=331px'
}, 300);
}
if (A >= 993) {
$('.gallery').delay(400).animate({
scrollLeft: 0
}, 300);
}
}, 3000);
});
Here's a simple solution of your problem: http://jsfiddle.net/pjvCw/44/ but....
The way you're doing galleries is quite wrong.
You have a really sensitive CSS full of margin bugs (see in CSS code),
you calculate all by hand, which will just complicate your life one day if you'll get to add images, change widths etc...
Your buttons are positioned really wrongly, and again you don't even need to manually add them in your HTML. Let jQuery do all the job for you:
Calculate margins, widths,
Get the number of slides
generate buttons,
Make your buttons clickable
Pause gallery on mouseenter (loop again on mouseleave)
LIVE DEMO
This is the way you should go with your slider:
HTML:
<div class="galleryContainer"> <!-- Note this main 'wrapper' -->
<div class="gallery">
<div class="row">
<!-- ..your images.. -->
</div>
<div class="row">
<!-- ..your images.. -->
</div>
</div>
<div class="content-nav-control"></div> <!-- Let jQ create the buttons -->
</div>
Note the general gallery wrapper, it allows you with this CSS to make your buttons parent not move with the gallery.
CSS:
In your code, using display:inline-block; adds 4px margin to your elements, ruining your math. So you just need to apply font-size:0; to remove that inconvenience.
As soon I did that the math was working and the right width was than 340px, having 5px border for your images and 20px margin.
.galleryContainer{
/* you need that one
// to prevent the navigation move */
position:relative; /* cause .content-nav-control is absolute */
background-color: #abcdef;
width:340px; /* (instead of 350) now the math will work */
height: 265px;
}
.gallery{
position:relative;
overflow: hidden; /* "overflow" is enough */
width:340px; /* (instead of 350) now the math will work */
height: 265px;
}
.gallery .row {
white-space: nowrap;
font-size:0; /* prevent inline-block 4px margin issue */
}
.gallery img {
display: inline-block;
margin-left: 20px;
margin-top: 20px;
}
.normalimage {
height: 80px;
width: 50px;
border: 5px solid black;
}
.wideimage {
height: 80px;
width: 130px;
border: 5px solid black;
}
img:last-of-type {
margin-right:20px;
}
.content-nav-control {
position: absolute;
width:100%; /* cause it's absolute */
bottom:10px;
text-align:center; /* cause of inline-block buttons inside*/
font-size:0; /* same trick as above */
}
.content-nav-control > span {
cursor:pointer;
width: 20px;
height: 20px;
display: inline-block;
border-radius: 50%;
border:1px solid #000;
box-shadow: inset 0 0 6px 2px rgba(0,0,0,.75);
margin: 0 2px; /* BOTH MARGINS LEFT AND RIGHT */
}
.content-nav-control > span.active{
background:blue;
}
And finally:
$(function () { // DOM ready shorty
var $gal = $('.gallery'),
$nav = $('.content-nav-control'),
galSW = $gal[0].scrollWidth, // scrollable width
imgM = parseInt($gal.find('img').css('marginLeft'), 10), // 20px
galW = $gal.width() - imgM, // - one Margin
n = Math.round(galSW/galW), // n of slides
c = 0, // counter
galIntv; // the interval
for(var i=0; i<n; i++){
$nav.append('<span />'); // Create circles
}
var $btn = $nav.find('span');
$btn.eq(c).addClass('active');
function anim(){
$btn.removeClass('active').eq(c).addClass('active');
$gal.stop().animate({scrollLeft: galW*c }, 400);
}
function loop(){
galIntv = setInterval(function(){
c = ++c%n;
anim();
}, 3000);
}
loop(); // first start kick
// MAKE BUTTONS CLICKABLE
$nav.on('click', 'span', function(){
c = $(this).index();
anim();
});
// PAUSE ON GALLERY MOUSEENTER
$gal.parent('.galleryContainer').hover(function( e ){
return e.type=='mouseenter' ? clearInterval(galIntv) : loop() ;
});
});
"- With this solution, What can I do now and in the future? -"
Nothing! just freely add images into your HTML and play, and never again have to take a look at your backyard :)
Try this: http://jsfiddle.net/yerdW/1/
I added a line that gets the scrollLeft and divides it by your width (331px) to get the position and use that to select the 'active' circle:
$(".circle").removeClass("coloured");
position = Math.ceil($(".gallery").scrollLeft()/331 + 2);
if(position > $(".circle").length){
position = 1; // yes...
}
$(".content-nav-control div:nth-child("+position+")").addClass("coloured");
Red background for active circle:
.coloured {
background : red;
}
Note that you should initialise with the first circle already having the .coloured class applied.
Here you go: http://jsfiddle.net/pjvCw/41/
i added new class
.selected
{
background-color: red;
}
and modified some js code
Here is your jsfiddle edited http://jsfiddle.net/pjvCw/45/
var scrolled = 0;
var circles = $(".circle");
var colorCircle = function(index) {
for(var i=0; i<circles.length; i++) {
if(i == index) {
circles.eq(i).css("background-color", "rgba(255, 0, 0, 1)");
} else {
circles.eq(i).css("background-color", "rgba(255, 0, 0, 0)");
}
}
}
$(document).ready(function () {
setInterval(function () {
var A = $('.gallery').scrollLeft();
if (A < 993) {
$('.gallery').animate({
scrollLeft: '+=331px'
}, 300);
colorCircle(++scrolled);
}
if (A >= 993) {
$('.gallery').delay(400).animate({
scrollLeft: 0
}, 300);
colorCircle(scrolled = 0);
}
}, 3000);
colorCircle(0);
});
I added a transition to the .circle class, so it looks a little bit better:
.circle {
width: 20px;
height: 20px;
display: inline-block;
border-radius: 50%;
border:1px solid #000;
box-shadow: inset 0 0 6px 2px rgba(0,0,0,.75);
margin-right: 5px;
transition: background-color 700ms;
-webkit-transition: background-color 700ms;
}

Categories