Simple range /value Slider in JavaScript - javascript

I am trying to do a simple Range/Value Slider by using javascript or jQuery, A button in a div.This slider should be done without bootstrapor any other pluginor with inbuild functions
My question is how to move the slider button within the div element and what mouse events are needed to do this?
Note:This is not a slideshow slider or image slider

Take a look at this simple slider implementation. Feel free to use and modify the way you prefer:
document.addEventListener('DOMContentLoaded', function() {
var sliders = document.querySelectorAll('.my-slider');
[].forEach.call(sliders, function(el, i) {
var btn = el.firstElementChild,
span = el.nextElementSibling.querySelector('span'),
isMoving = false;
var move = function(e) {
if (isMoving) {
var min = 0,
max = el.offsetWidth - btn.offsetWidth,
mousePos = (e.pageX - el.offsetLeft - (btn.offsetWidth / 2)),
position = (mousePos > max ? max : mousePos < min ? min : mousePos),
value = Math.floor((position / max) * 100);
btn.style.marginLeft = position + 'px';
btn.value = value;
span.textContent = value;
}
};
el.addEventListener('mousedown', function(e) {
isMoving = true;
move(e);
});
document.addEventListener('mouseup', function(e) {
isMoving = false;
});
document.addEventListener('mousemove', function(e) {
move(e);
});
});
});
.my-slider {
width: 250px;
border: 1px solid #999;
border-radius: 3px;
background-color: #ccc;
height: 10px;
line-height: 10px;
}
.my-slider__button {
border: 1px solid #333;
border-radius: 3px;
margin-top: -4px;
width: 18px;
height: 18px;
background-color: #eee;
display: block;
}
div {
margin-top: 6px;
}
<div class="my-slider">
<button class="my-slider__button"></button>
</div>
<div>
<strong>Current value: </strong><span></span>
</div>
<div class="my-slider">
<button class="my-slider__button"></button>
</div>
<div>
<strong>Current value: </strong><span></span>
</div>
<div class="my-slider">
<button class="my-slider__button"></button>
</div>
<div>
<strong>Current value: </strong><span></span>
</div>

You use drag and drop events, with a property setting that is restricted to the div it is within. Check out this link Drag Drop Reference Guide, and you will see everything you need. When you use draggable and dropable, you can restrict the movement to horizontal, and also set the element that it is bound to. This will allow you to only move left to right, and restrict vertical movement, and keep in the boundaries of the div. The same features bootstrap uses to get it done.
Here is a basic example showing some of the stuff mentioned:
$('. draggable').draggable({
axis: 'y',
handle: '.top'
drag: function( event, ui ) {
var distance = ui.originalPosition.top - ui.position.top;
// if dragged towards top
if (distance > 0) {
//then set it to its initial state
$('.draggable').css({top: ui.originalPosition.top + 'px'});
}
}
});

try this :
$('img').mouseenter(function(){ //or you can use hover()
// Set the effect type
var effect = 'slide';
// Set the options for the effect type chosen
var options = { direction: "right" };
// Set the duration (default: 400 milliseconds)
var duration = 1000;
$(this).toggle(effect, options, duration);
});

Related

Using two mouse events after each other

I am creating a canvas alike without using canvas tag , by creating new div each time mouse is down, i can't figure out how to run a second event.
Like mousedown then mousemove event where the seconed event occur only after the first one is true?
also if you can help with the offset coordinates
var paintbox = document.getElementById("canvas");
var start = function() {
paintbox.addEventListener("mousedown", drawOnCanvas);
};
var newColor = document.getElementById("colorPick");
var drawOnCanvas = function() {
var newClick = document.createElement("div");
newClick.setAttribute("id", "smallDiv");
newClick.style.backgroundColor = newColor.value;
newClick.style.width = "10px";
newClick.style.height = "10px";
newClick.style.position = "absolute";
paintbox.appendChild(newClick);
}
Set the handler on the mousemove event instead of mousedown and in the handler check whether the mouse button is down.
It would be better to move the 10px/position style settings in a CSS class. Also, don't generate elements with the same id attribute value: that generates invalid HTML. Use a class instead.
For the positioning you can use the pageX and pageY properties of the event object.
Finally, as the events will be triggered on the small divs when you make small moves, an extra check might be necessary to verify the mouse is still in the paint box.
var paintbox = document.getElementById("canvas");
var start = function() {
paintbox.addEventListener("mousemove", drawOnCanvas);
};
var newColor = document.getElementById("colorPick");
var drawOnCanvas = function(e) {
if ((e.buttons & 1) === 0) return; // Mouse button is not down
// Extra check to see we are well within the box boundaries:
var box = paintbox.getBoundingClientRect();
if (e.clientX - 5 < box.left || e.clientX + 5 > box.right
|| e.clientY - 5 < box.top || e.clientY + 5 > box.bottom) return;
var newClick = document.createElement("div");
newClick.className = "smallDiv"; // Don't create duplicate ID; put CSS in class
newClick.style.backgroundColor = newColor.value;
paintbox.appendChild(newClick);
newClick.style.left = (e.pageX-5) + "px";
newClick.style.top = (e.pageY-5) + "px";
}
start();
#canvas {
height: 150px;
width: 300px;
border: 1px solid;
display: inline-block;
margin: 10px;
}
.smallDiv {
width: 10px;
height: 10px;
position: absolute;
}
Color: <input id="colorPick" type="color"><br>
<div id="canvas"></div>

Trying to get the element to appear once after clicking, but appears more than once

Im trying to get the shapes to appear once after clicking. After 1.2 seconds it appears, then when clicked it disappears, then the whole process repeats. The problem is after a few clicks two shapes appear.
This is the link to the program.
https://jsfiddle.net/EyedFox/w98naLjx/2/
function show() {
var randomColor = colors[Math.floor(colors.length * Math.random())]; // Random color chosen
var randomX = Math.floor(Math.random() * 60); // random x axis margin
var randomY = Math.floor(Math.random() * 80); // random y axis margin
square = document.getElementById("square");
circle = document.getElementById("circle");
var shapeArray = [square, circle];
var randShape = shapeArray[Math.floor(shapeArray.length * Math.random())];
randShape.style.margin = randomX + "% " + randomY + "%";
randShape.style.backgroundColor = randomColor;
randShape.style.display = "block";
randShape.addEventListener("click", click);
function click() {
randShape.style.display = "none";
setTimeout(show, 1200);
}
}
setTimeout(show, 1200);
Your code keep adding click event listener to randShape, but it never cleans them those event. As a result, they keep being added and click (and thus show) will get executed several times per click. Try to add console.log('clicked on', randShape); at the beginning of your click function to see it. If by chance all the show execution selects the same shape, you'll see only this one on screen, but otherwise you'll get both.
Your click function should look like this:
function click() {
console.log('clicked on', randShape);
randShape.style.display = "none";
setTimeout(show, 1200);
randShape.removeEventListener('click', click); // cleaning after myself ;-)
}
(btw (function() { ... })() is not executed on load, but as soon as it is encountered by the javascript vm)
Here is a fiddle that fixes the issue.
Edited my response based on #autra response
I would probably completely clean the canvas before redrawing:
https://jsfiddle.net/c0L54uk3/
Essentially made a reset function like so:
function reset(){
square = document.getElementById("square").style.display = "none";
circle = document.getElementById("circle").style.display = "none";
randShape.removeEventListener("click", click);
}
And called it at the beginning of the click() function to reset the canvas like so:
function click() {
reset();
setTimeout(show, 1200);
}
Hope that helps.
Delegate Events Instead of Registering Them Individually
addEventListener() should be outside the callback function (i.e. show()). There's an event listener being added to the clicked tag but none of them are being removed. So when the 4th to 7th click occurs, the browser starts slowing down and that setTimeout is never 1.2 seconds because it will be cued to fire off which means it'll wait however long then wait 1.2 seconds. As the cue accumulates, the clicks will out race the setTimeout.
Register the parent tag, .container to listen to the click event event for all of its children tags. This pattern is called Event Delegation. In doing so, you can add the click event to an unlimited number of tags within .container using only one event listener instead of one for each shape.
The #triangle was never styled so it's an extra invisible div that floats around. In the demo I have styled the #triangle and added a .blank <div> outlined in gold (you can remove the .blank).
Demo
Fiddle
Details commented in demo
// Reference parent tag
var box = document.querySelector('.container');
function show() {
// Collect all .shape into a NodeList and convert into an array
var shapes = Array.from(document.querySelectorAll('.shape'));
var colors = ["yellow", "red", "green", "purple", "aqua", "chartreuse", "coral", "dodgerBlue", "deepPink"];
var rColor = colors[Math.floor(colors.length * Math.random())];
var rX = Math.floor(Math.random() * 60);
var rY = Math.floor(Math.random() * 80);
var rShape = shapes[Math.floor(shapes.length * Math.random())];
rShape.style.margin = rX + "% " + rY + "%";
// if #triangle change the border-bottom-color
if (rShape.id === 'triangle') {
rShape.style.borderBottomColor = rColor;
// otherwise change background-color
} else {
rShape.style.backgroundColor = rColor;
}
rShape.style.display = "block";
}
/*
Run show()
A setTimeout nor an IIFE is needed to initially run show()
Simply call it.
*/
show();
// Register box to click event...
box.addEventListener('click', function(e) {
// ...reference the clicked tag (i.e. .shape)...
var tgt = e.target;
// ...reference the registered parent tag...
var cur = e.currentTarget;
/*
...if the clicked tag IS NOT the registered parent tag...
*/
if (tgt !== cur) {
// ...then hide clicked element...
tgt.style.display = "none";
// ...and run show() in about 1.2 seconds
setTimeout(show(), 1200);
}
});
.container {
overflow: hidden;
height: 800px;
width: 80%;
background-color: rgb(0, 34, 85);
margin: 0 auto;
margin-top: 5em;
}
#square {
width: 80px;
height: 80px;
background-color: red;
margin-left: 0%;
margin-top: 10%;
display: none
}
#circle {
width: 100px;
height: 100px;
background: red;
border-radius: 50px;
display: none
}
#triangle {
width: 0;
height: 0;
border-left: 45px solid transparent;
border-right: 45px solid transparent;
border-bottom: 90px solid cyan;
display: none
}
.shape {
cursor: pointer
}
.blank {
outline: 10px solid gold
}
<div class="container">
<div id="square" class='shape'></div>
<div id="triangle" class='shape'></div>
<!--
This .blank represents what #triangle was before it
had any style.
-->
<div class='blank'></div>
<div id="circle" class='shape'></div>
</div>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/css/bootstrap.min.css" />

Leap.JS: How can I select items on a webpage using the LeapMotion?

I am looking to select items in a web page using the LeapMotion and I am struggling with programming this interaction.
Using this code as a base (but updating the link so it connects to the current SDK) I can get my cursor to move around the window based on where my hand is in space. However, I do not know how to make the equivalent of the event listener "click" using the LeapMotion. I am using Leap.js and have built a crude GUI using svg.js.
How do I program an event listener that selects using the LeapMotion in Javascript?
I have working code with Leap motion. I did quize software. Here cursor is a div element which styled as:
#cursor {
width: 60px;
height: 60px;
position: fixed;
margin-left: 20px;
margin-top: 20px;
z-index: 99999;
opacity: 0.9;
background: black;
border-radius: 100%;
background: -webkit-radial-gradient(100px 100px, circle, #f00, #ff6a00);
background: -moz-radial-gradient(100px 100px, circle, #f00, #ff6a00);
background: radial-gradient(100px 100px, circle, #f00, #ff6a00);
}
and Java script at bottom. What I did, I get HTML element by position and triggering click event on it by tap gestures.
var w = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
var h = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
// Setting cursor and output position
window.cursor = $('#cursor');
var controller= Leap.loop(function(frame) {
if (frame.pointables.length > 0) {
try
{
var position = frame.pointables[0].stabilizedTipPosition;
var normalized = frame.interactionBox.normalizePoint(position);
var cx = w * normalized[0];
var cy = h * (1 - normalized[1]);
$('#cursor').css('left', cx);
$('#cursor').css('top', cy);
}catch(e){
console.error(e);
}
}
});
controller.use('screenPosition', {
scale: 1
});
controller.on('gesture', onGesture);
function onGesture(gesture,frame)
{
try
{
// If gesture type is keyTap
switch(gesture.type)
{
case 'keyTap':
case 'screenTap':
var position = frame.pointables[0].stabilizedTipPosition;
var normalized = frame.interactionBox.normalizePoint(position);
//Hiding cursor for getting background element
cursor.hide();
// Trying find element by position
var cx = w * normalized[0];
var cy = h * (1 - normalized[1]);
var el = document.elementFromPoint(cx, cy);
cursor.show();
console.log(el);
if (el) {
$(el).trigger("click");
}
break;
}
}
catch (e) {
console.info(e);
}
}

Draggable Columns With Pure JavaScript

I'm trying to build a draggable column based layout in JavaScript and having a bit of hard time with it.
The layout comprises of 3 columns (divs), with two dragable divs splitting each. The idea is that they are positioned absolutely and as you drag the draggers, the columns' respective widths, and left values are updated.
The three columns should always span the full width of the browser (the right most column is 100% width), but the other two should remain static by default when the browser is resized (which is why i'm using px, not %).
My code isn't working as of yet, I'm relatively new to JavaScript (which is why I don't want to use jQuery).
Having said that, there must be a more efficient (and cleaner) way of achieving this with less code that works (without reaching for the $ key).
If anyone with some awesome JS skills can help me out on this I'd be super-appreciative.
Here's the fiddle I'm working on http://jsfiddle.net/ZFwz5/3/
And here's the code:
HTML
<!-- colums -->
<div class="col colA"></div>
<div class="col colB"></div>
<div class="col colC"></div>
<!-- draggers -->
<div class="drag dragA" style="position: absolute; width: 0px; height: 100%; cursor: col-resize; left:100px;"><div></div></div>
<div class="drag dragB" style="position: absolute; width: 0px; height: 100%; cursor: col-resize; left: 300px;"><div></div></div>
CSS:
body {
overflow:hidden;
}
.col {
position: absolute;
height:100%;
left: 0;
top: 0;
overflow: hidden;
}
.colA {background:red;width:100px;}
.colB {background:green; width:200px; left:100px;}
.colC {background:blue; width:100%; left:300px;}
.drag > div {
background: 0 0;
position: absolute;
width: 10px;
height: 100%;
cursor: col-resize;
left: -5px;
}
and my terrible JavaScript:
//variabe columns
var colA = document.querySelector('.colA');
var colB = document.querySelector('.colB');
var colC = document.querySelector('.colC');
//variable draggers
var draggers = document.querySelectorAll('.drag');
var dragA = document.querySelector(".dragA");
var dragB = document.querySelector(".dragB");
var dragging = false;
function drag() {
var dragLoop;
var t = this;
var max;
var min;
if (dragging = true) {
if (this == dragA) {
min = 0;
max = dragB.style.left;
} else {
min = dragA.style.left;
max = window.innerWidth;
}
dragLoop = setInterval(function () {
var mouseX = event.clientX;
var mouseY = event.clientY;
if (mouseX >= max) {
mouseX = max;
}
if (mouseY <= min) {
mouseY = min;
}
t.style.left = mouseX;
updateLayout();
}, 200);
}
}
function updateLayout() {
var posA = dragA.style.left;
var posB = dragB.style.left;
colB.style.paddingRight = 0;
colA.style.width = posA;
colB.style.left = posA;
colB.style.width = posB - posA;
colC.style.left = posB;
colC.style.width = window.innerWidth - posB;
}
for (var i = 0; i < draggers.length; i++) {
draggers[i].addEventListener('mousedown', function () {
dragging = true;
});
draggers[i].addEventListener('mouseup', function () {
clearInterval(dragLoop);
dragging = false;
});
draggers[i].addEventListener('mouseMove', function () {
updateLayout();
drag();
});
}
I see a couple of things wrong here. First of all, the mousemove event only fires on an element when the mouse is over that element. You might have better luck registering a mousemove listener on the parent of your div.drag elements, then calculating the mouse's position inside that parent whenever a mouse event happens, then using that position to resize your columns and your draggers.
Second, I'm not quite sure what you're trying to do by registering a function with setInterval. You're doing pretty well with registering event listeners; why not continue to use them to change the state of your DOM? Why switch to a polling-based mechanism? (and the function you pass to setInterval won't work anyway - it refers to a variable named event, which in that context is undefined.)
This is just a little example... I hope it can help you :)
window.onload = function() {
var myDiv = document.getElementById('myDiv');
function show_coords(){
var monitor = document.getElementById('monitor');
var x = event.clientX - myDiv.clientWidth / 2;
var y = event.clientY - myDiv.clientWidth / 2;
monitor.innerText = "X: " + x + "\n" + "Y: " + y;
myDiv.style.left = x + "px";
myDiv.style.top = y + "px";
}
document.onmousemove = function(){
if(myDiv.innerText == "YES"){show_coords();}
}
myDiv.onmousedown = function(){
myDiv.innerText = "YES";
}
myDiv.onmouseup = function(){
myDiv.innerText = "NO";
}
}

Javascript Vertical Slider

I am trying to create a vertical slider widget in javascript. I am not looking for any plugins or libraries, I am trying to see how it can done using plain javascript . I think I got the general idea.
See here for what has been developed so far and do view source to see the code and please open the link in chrome.
http://eco-system2031.appspot.com/pages/ex5slider/verticalslider.html
Issues:
1) Sometimes the border ranges(eg: 0, 500) does not get calculated properly when I move the slider to the very top or the very bottom.
2) Sometimes the slider does not get released when I release the mouse(mouseup), the slider moves along with the mouse even after mouseup.
3) Any other things I need to make the code more robust and smooth using only javascript.
And it is done. Thank you very one for your help.
Here is the HTML
Minimum Value: <input id="minimum-value" type="text" value="0" /> <br/>
Maximum Value: <input id="maximum-value" type="text" value="500" /> <br/>
<input id="submit-value" type="submit" value="Submit" /> <br/>
Slider Value: <span id="sliderValue"></span> <br/>
<div id="slider-container">
<div id="slider-bar"></div>
<div id="slider-handle"></div>
</div>
and here is the css
#slider-container {
width: 20px;
height: 325px;
margin: 100px;
margin-top: 30px;
background: #26AFE3;
/* Safari 3-4, iOS 1-3.2, Android 1.6 */
-webkit-border-radius: 20px 20px 20px 20px;
/* Firefox 1-3.6 */
-moz-border-radius: 20px 20px 20px 20px;
/* Opera 10.5, IE 9, Safari 5, Chrome, Firefox 4, iOS 4, Android 2.1+ */
border-radius: 20px 20px 20px 20px;
}
#slider-bar {
width: 100%;
height: 100%;
background: #E6E6E6;
/* Safari 3-4. iOS 1-3.2, Android 1.6 */
-webkit-border-radius: 20px 20px 20px 20px;
/* Firefox 1-3.6 */
-moz-border-radius: 20px 20px 20px 20px;
/* Opera 10.5, IE9, Safari 5, Chromer, Firefox 4, iOS 4, Android 2.1+ */
border-radius: 20px 20px 20px 20px;
}
#slider-handle {
width: 25px;
height: 25px;
background: #7C7D82;
position: relative;
left: -2.5px;
top: -10px;
/* Safari 3-4, iOS 1-3.2, Android 1.6 */
-webkit-border-radius: 2px 20px 20px 20px;
/* Firefox 1-3.6 */
-moz-border-radius: 20px 20px 20px 20px;
/* Opera 10.5, IE 9, Safari 5, Chrome, Firefox 4, iOS 4, Android 2.1+ */
border-radius: 20px 20px 20px 20px;
}
here is the js
(function () {
// html elements
var container = document.getElementById("slider-container");
var slider = document.getElementById("slider-bar");
var handle = document.getElementById("slider-handle");
var submitVal = document.getElementById("submit-value");
// initial values
var minVal = Number( document.getElementById("minimum-value").value );
var maxVal = Number( document.getElementById("maximum-value").value );
var range = maxVal - minVal;
var isSliding = false;
// recalculate range
submitVal.onclick = function() {
minVal = Number( document.getElementById("minimum-value").value );
maxVal = Number( document.getElementById("maximum-value").value );
range = maxVal - minVal;
};
// the sliding function
var move = function(e) {
var mouseY = 0;
var containerTop = 0;
var newHeight = 0;
var containerHeight = 0;
var percentHght = 0;
var x = 0;
var y = 0;
var sliderValue = 0;
if (!e) var e = window.event;
if( e.pageY ){ // all browsers except IE before version 9
mouseY = e.pageY;
} else if ( e.clientY ) { // IE before version 9
mouseY = e.clientY;
}
containerTop = container.offsetTop;
newHeight = mouseY - containerTop;
containerHeight = container.offsetHeight;
percentHght = newHeight * 100 / containerHeight;
if( (percentHght <= 100) && (percentHght >= 0) ) {
slider.style.height = (percentHght) + '%';
y = 100 - percentHght;
x = y * range / 100;
} else if( percentHght < 0 ) {
percentHght = 0;
slider.style.height = (percentHght) + '%';
y = 100 - percentHght;
x = y * range / 100;
} else if( percentHght > 100 ) {
percentHght = 100;
slider.style.height = (percentHght) + '%';
y = 100 - percentHght;
x = y * range / 100;
}
sliderValue = Math.round(x);
document.getElementById('sliderValue').innerHTML = sliderValue + minVal;
};
// adding the slide functionality
var addSlide = function() {
isSliding = true;
if ( !window.addEventListener ){
document.attachEvent('onmousemove',move);
} else {
document.addEventListener('mousemove', move, false);
}
};
// removing the slide functionality
var cancelSlide = function() {
if( isSliding ) {
if ( window.removeEventListener ) {
document.removeEventListener('mousemove', move, false);
} else if ( window.detachEvent ) {
document.detachEvent('onmousemove', move );
}
}
};
// cancelling event bubbling
// cancelling default event action
var cancelBubble = function(e) {
var evt = e ? e:window.event;
if( evt.stopPropogation ){
evt.stopPropogation();
}
if( evt.cancelBubble != null ){
evt.cancelBubble = true;
}
if( evt.preventDefault ){
evt.preventDefault();
} else {
evt.returnValue = false;
}
};
// capture events
//capturing the mousedown on the handle
handle.onmousedown = function(e) {
addSlide();
cancelBubble(e);
}
//capture the mouseup on the handle
handle.onmouseup = function(e) {
cancelSlide();
cancelBubble(e);
}
// capture the mouse up on the slider
slider.onmouseup = function(e) {
cancelSlide();
cancelBubble(e);
}
// capture the mouse down on the slider
slider.onmousedown = function(e) {
move(e);
cancelBubble(e);
}
// capture the mouse up on the container
container.onmouseup = function(e) {
cancelSlide();
cancelBubble(e);
}
// capture the mouse down on the container
container.onmousedown = function(e) {
move(e);
cancelBubble(e);
}
// capture the mouse up on the window
document.onmouseup = function(e) {
cancelSlide();
cancelBubble(e);
}
})();
here is the jsfiddle link
http://jsfiddle.net/nPaKp/
and here is a link out side jsfiddle
http://eco-system2031.appspot.com/pages/ex5slider/verticalslider.html
By the way, add this:
slider.onmouseuout = slider.onmouseup;
sort of thing to the end of each onmouseup declaration and the problem of the slider still following the pointer if it slips off the slider handle goes away.
Great addition!
Also change this:
stopPropogation() --> stopPropagation() // spelling mistake
A better way is to avoid stopPropagation altogether as it's bad practice. Interesting article: Dangers of stopping event propagation
If you want a larger handle click area e.g. when adding touch support:
#slider-handle {
position: relative;
width: 75px;
height: 48px;
left: -32.5px;
top: -24px;
border-radius: 50% / 50%;
border: 1px solid red; /* remove after test */
cursor: grab;
}
#slider-handle:after {
content: '';
position: absolute;
width: 100%;
height: 20%;
top: 40%;
left: 0;
background: #fff;
border-radius: 50%/50%;
}

Categories