Range Slider - Animate Output Number - javascript

I created a jsfiddle showing a simple range slider, with a max range of 4.
What I'm trying to achieve is to animate the number in the output, so for example if you're currently at 1 and you choose 4, 1 will go down and fade out, while 4 will come from the top and fade in. On the other hand, if you choose a lower number, the opposite will happen.
Thanks ahead for your help!
jsfiddle: https://jsfiddle.net/hm0gxs54/12/
HTML
<div class="container">
<div class="row">
<div class="col-md-12">
<div class="form-group">
<div class="range-slider-wrap range-slider-lg">
<input class="range-slider ng-valid ng-dirty ng-touched" step="1" type="range" id="range-slider" min="1" max="4" data-tooltip-top="true" aria-valuenow="3" aria-valuemin="1" aria-valuemax="4">
<output class="range-slider-output num" id="range-slider-output" for="range-slider"></output>
</div>
</div>
</div>
</div>
</div>
CSS
.range-slider-output {
position: relative;
display: inline-block;
padding: 0.2em 0.75em 0.25em;
color: #fff;
text-align: center;
background: #666;
border-radius: 3px;
width: 100%;
left: calc(50%);
flex: 0 0 5%;
align-self: center;
margin: 0;
font-size: 28px;
-webkit-transform: translateX(-50%);
transform: translateX(-50%);
top: -92px;
}
.range-slider-output::before {
position: absolute;
top: 50%;
left: 0;
content: "";
}
.range-slider-lg .range-slider-output::before {
top: 48px;
width: 0;
height: 0;
border-style: solid;
border-width: 12px 12px 0 12px;
border-color: #666 transparent transparent transparent;
transition: all 0.7s ease-out;
}
.range-slider-wrap {
min-width: 100px;
}
input[type='range'] {
width: 100%;
cursor: pointer;
padding-top: 90px;
}
input[type='range'] {
-webkit-appearance: none;
}
input[type='range']::-webkit-slider-runnable-track {
width: 100%;
height: 5px;
background: #e6e5e5;
border: 1px solid #999;
border-radius: 3px;
-webkit-appearance: none;
padding: 0 0.5rem;
}
input[type='range']::-moz-range-track {
width: 100%;
height: 5px;
background: #e6e5e5;
border: 1px solid #999;
border-radius: 3px;
}
input[type=range]::-webkit-slider-thumb {
width: 28px;
height: 28px;
margin-top: -11px;
background: #999;
border: 1px solid #666;
border-radius: 50%;
-webkit-appearance: none;
}
input[type='range']::-moz-range-thumb {
width: 28px;
height: 28px;
margin-top: -11px;
background: #999;
border: 1px solid #666;
border-radius: 50%;
}
JS
$(function() {
var slider = document.getElementById("range-slider");
var output = document.getElementById("range-slider-output");
output.innerHTML = slider.value;
slider.oninput = function() {
output.innerHTML = this.value;
}
});

Related

Onclick Function in Dropdown Menu not working

I'm a newbie and practicing dropdown menu using the following Youtube video https://www.youtube.com/watch?v=uFIl4BvYne0. Everything is working except the onclick function.
Can anyone point out where I'm going wrong?
function show(anything) {
document.querySelector('.textBox').value =
anything;
}
let dropdown = document.querySelector('.dropdown');
dropdown.onclick = function() {
dropdown.classList.toggle('active');
}
#import url('https://fonts.googleapis.com/css?family=Poppins:100,200,300,400,500,600,700,800,900');
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Poppins', sans-serif;
}
body {
display: flex;
justify-content: center;
min-height: 100vh;
background: #fafafa;
}
.dropdown {
position: relative;
margin-top: 100px;
width: 300px;
height: 50px;
}
.dropdown::before {
content: "";
position: absolute;
right: 20px;
top: 15px;
z-index: 10000;
width: 8px;
height: 8px;
border: 2px solid #333;
border-top: 2px solid #fff;
border-right: 2px solid #fff;
transform: rotate(-45deg);
transition: 0.5s;
pointer-events: none;
}
.dropdown.active::before {
top: 22px;
transform: rotate(-225deg);
}
.dropdown input {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100;
cursor: pointer;
background: #fff;
border: none;
outline: none;
box-shadow: 0px 5px 20px rgba(0, 0, 0, 0.05);
padding: 12px 20px;
border-radius: 10px;
}
.dropdown .option {
position: absolute;
top: 70px;
width: 100%;
background: #fff;
box-shadow: 0px 30px 30px rgba(0, 0, 0, 0.05);
border-radius: 10px;
overflow: hidden;
/*display: none*/
;
}
.dropdown.active .option {
display: block;
}
.dropdown .option div {
padding: 10px 20px;
cursor: pointer;
}
.dropdown .option div:hover {
background: #62baea;
color: #fff;
}
<body>
<h2>Converter</h2>
<label>Litres</label>
<div class="dropdown">
<input type="text" class="textBox" placeholder="HTML" readonly>
<div class="option">
<div onlcick="show('HTML')">HTML</div>
<div onclick="show('HTML')">HTML</div>
<div onclick="show('HTML')">HTML</div>
<div onclick="show('HTML')">HTML</div>
</div>
</div>
</body>
I have tried some fixes but couldn't find out the problem.
Note: I'm pretty new in this field.
You need to add addEventListener in order to append an action:
function show(anything) {
document.querySelector('.textBox').value =
anything;
}
let dropdown = document.querySelector('.dropdown');
dropdown.addEventListener('click', function(event) { // add click function
dropdown.classList.toggle('active'); // i don't know what class you want to change so i changed the background to a class to demonstrate the click
});
#import url('https://fonts.googleapis.com/css?family=Poppins:100,200,300,400,500,600,700,800,900');
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Poppins', sans-serif;
}
body {
display: flex;
justify-content: center;
min-height: 100vh;
background: #fafafa;
}
.dropdown {
position: relative;
margin-top: 100px;
width: 300px;
height: 50px;
}
.dropdown::before {
content: "";
position: absolute;
right: 20px;
top: 15px;
z-index: 10000;
width: 8px;
height: 8px;
border: 2px solid #333;
border-top: 2px solid #fff;
border-right: 2px solid #fff;
transform: rotate(-45deg);
transition: 0.5s;
pointer-events: none;
}
.dropdown.active::before {
top: 22px;
transform: rotate(-225deg);
}
.dropdown input {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100;
cursor: pointer;
background: #fff;
border: none;
outline: none;
box-shadow: 0px 5px 20px rgba(0, 0, 0, 0.05);
padding: 12px 20px;
border-radius: 10px;
}
.dropdown .option {
position: absolute;
top: 70px;
width: 100%;
background: #fff;
box-shadow: 0px 30px 30px rgba(0, 0, 0, 0.05);
border-radius: 10px;
overflow: hidden;
/*display: none*/
;
}
.dropdown.active .option {
display: block;
background-color: grey;
}
.dropdown .option div {
padding: 10px 20px;
cursor: pointer;
}
.dropdown .option div:hover {
background: #62baea;
color: #fff;
}
<body>
<h2>Converter</h2>
<label>Litres</label>
<div class="dropdown">
<input type="text" class="textBox" placeholder="HTML" readonly>
<div class="option">
<div onlcick="show('HTML')">HTML</div>
<div onclick="show('HTML')">HTML</div>
<div onclick="show('HTML')">HTML</div>
<div onclick="show('HTML')">HTML</div>
</div>
</div>
</body>

how to get a pointer pointing at centre of slider thumb? CSS and Jquery

I have a feature to show the price range and the most repeated price (Mode). What i did is i used the range input type and deactivated it (so it can't be moved by user as it's only for illustration).
Below is my HTML, CSS and JS which i guess will explain better my issue
<div class="range">
<div class="sliderValue">
<span class="show" style="left: ${pinPostion}%;">${mostCommonMaxPrice}</span>
</div>
<div class="field">
<div class="value left">${lowestMinPrice}</div>
<input type="range" min="${lowestMinPrice}" max="${highestMaxPrice}" value="${mostCommonMaxPrice}" disabled>
<div class="value right">${highestMaxPrice}</div>
</div>
</div>
.range{
height: 40px;
width: 130px;
background: #fff;
border-radius: 10px;
padding: 0 32.5px 0 22.5px;
}
.field{
display: flex;
align-items: center;
justify-content: center;
height: 100%;
position: relative;
}
.field .value{
position: absolute;
font-size: 12px;
color: #4638D2;
font-weight: 600;
}
.field .value.left{
left: -15px;
}
.field .value.right{
right: -21.5px;
}
.range input{
-webkit-appearance: none;
width: 100%;
height: 3px;
background: #ddd;
border-radius: 5px;
outline: none;
border: none;
z-index: 2222;
}
.range input::-webkit-slider-thumb{
-webkit-appearance: none;
width: 10px;
height: 10px;
background: #4638D2 !important;
border-radius: 50%;
background: #4638D2;
border: 1px solid #4638D2;
}
.range input::-moz-range-progress{
background: #4638D2;
}
.sliderValue{
position: relative;
width: 100%;
align-items: center;
}
.sliderValue span{
font-size: 8px;
position: absolute;
height: 22.5px;
width: 22.5px;
/*transform: translateX(-70%) scale(0);*/
font-weight: 600;
top: -15px;
line-height: 27.5px;
z-index: 2;
color: #fff;
text-align: center;
}
.sliderValue span.show{
transform: translateX(-70%) scale(1.3);
}
.sliderValue span:after{
position: absolute;
content: '';
height: 100%;
width: 100%;
background: #4638D2;
border: 3px solid #fff;
z-index: -1;
left: 50%;
transform: translateX(-50%) rotate(45deg);
border-bottom-left-radius: 50%;
box-shadow: 0px 0px 8px rgba(0,0,0,0.1);
border-top-left-radius: 50%;
border-top-right-radius: 50%;
}
const pinPostion = (((mostCommonMaxPrice - lowestMinPrice)/(highestMaxPrice - lowestMinPrice)) * 100) + lowestMinPrice;
As you see in the picture am not able to get the bubble that shows the mode number to point at the slider thumb position, it is only showing well when it's 100 but if it's more or less then it goes off position, I tried to calculate the percentage and pass it as a variable but it's still coming off, am not sure if my CSS is wrong or is it the equation am using or am I doing all this altogether wrong and there is an easier way to do it. I really appreciate your help. And would be grateful if you up the question, please :)
I found some code example here, it uses similar to yours approach with manual position calculation for Value Bubble, try it:
const allRanges = document.querySelectorAll(".range-wrap");
allRanges.forEach(wrap => {
const range = wrap.querySelector(".range");
const bubble = wrap.querySelector(".bubble");
range.addEventListener("input", () => {
setBubble(range, bubble);
});
setBubble(range, bubble);
});
function setBubble(range, bubble) {
const val = range.value;
const min = range.min ? range.min : 0;
const max = range.max ? range.max : 100;
const newVal = Number(((val - min) * 100) / (max - min));
bubble.innerHTML = val;
// Sorta magic numbers based on size of the native UI thumb
bubble.style.left = `calc(${newVal}% + (${8 - newVal * 0.15}px))`;
}
.range-wrap {
position: relative;
margin: 0 auto 3rem;
}
.range {
width: 100%;
}
.bubble {
background: red;
color: white;
padding: 4px 12px;
position: absolute;
border-radius: 4px;
left: 50%;
transform: translateX(-50%);
}
.bubble::after {
content: "";
position: absolute;
width: 2px;
height: 2px;
background: red;
top: -1px;
left: 50%;
}
body {
margin: 2rem;
}
<div class="range-wrap">
<input type="range" class="range">
<output class="bubble"></output>
</div>
<div class="range-wrap">
<input type="range" class="range" min="20" max="940">
<output class="bubble"></output>
</div>
<div class="range-wrap" style="width: 75%;">
<input type="range" class="range" min="50" max="60" step="2">
<output class="bubble"></output>
</div>
<div class="range-wrap" style="width: 55%;">
<input type="range" class="range" min="-20" max="20">
<output class="bubble"></output>
</div>
I found it here https://css-tricks.com/value-bubbles-for-range-inputs/
I think the pinpoint position does not consider the border width of the pinpoint itself, therefore it is not aligned to its center of the tip.
Consider this example, the pinpoint should be right at the middle:
variable
value
lowestMinPrice
0
highestMaxPrice
100
mostCommonMaxPrice
50
const pinPostion = (((mostCommonMaxPrice - lowestMinPrice)/(highestMaxPrice - lowestMinPrice)) * 100) + lowestMinPrice;
pinPostion = (((50 - 0)/(100 - 0)) * 100) + 0;
pinPostion = 50
The pinpoint is made from a rotated element with border radius. If I take the radius off, this is how it looks
If I further take the transform off, this is how it looks
Even I port the number to your example, the pinpoint is off a little bit.
.range {
height: 40px;
width: 130px;
background: #fff;
border-radius: 10px;
padding: 0 32.5px 0 22.5px;
}
.field {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
position: relative;
}
.field .value {
position: absolute;
font-size: 12px;
color: #4638D2;
font-weight: 600;
}
.field .value.left {
left: -15px;
}
.field .value.right {
right: -21.5px;
}
.range input {
-webkit-appearance: none;
width: 100%;
height: 3px;
background: #ddd;
border-radius: 5px;
outline: none;
border: none;
z-index: 2222;
}
.range input::-webkit-slider-thumb {
-webkit-appearance: none;
width: 10px;
height: 10px;
background: #4638D2 !important;
border-radius: 50%;
background: #4638D2;
border: 1px solid #4638D2;
}
.range input::-moz-range-progress {
background: #4638D2;
}
.sliderValue {
position: relative;
width: 100%;
align-items: center;
}
.sliderValue span {
font-size: 8px;
position: absolute;
height: 22.5px;
width: 22.5px;
/*transform: translateX(-70%) scale(0);*/
font-weight: 600;
top: -15px;
line-height: 27.5px;
z-index: 2;
color: #fff;
text-align: center;
}
.sliderValue span.show {
transform: translateX(-70%) scale(1.3);
}
.sliderValue span:after {
position: absolute;
content: '';
height: 100%;
width: 100%;
background: #4638D2;
border: 3px solid #fff;
z-index: -1;
left: 50%;
transform: translateX(-50%) rotate(45deg);
border-bottom-left-radius: 50%;
box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.1);
border-top-left-radius: 50%;
border-top-right-radius: 50%;
}
<div class="range">
<div class="sliderValue">
<span class="show" style="left: 50%;">50</span>
</div>
<div class="field">
<div class="value left">0</div>
<input type="range" min="0" max="100" value="50" disabled>
<div class="value right">100</div>
</div>
</div>

different CSS behavior in Firefox vs Chrome - slider example

My first question on Stackoverflow :) I have this situation. I build a slider trying to get with js the value and displaying in a box. Additionally I want to hide the slider thumb and replace it with my icon.. in Chrome is all nice and good but the in Firefox the original thumb of the slider is still rendered and displayed.
Any I dean what I'm doing wrong in CSS? Thanks in advance!
let slider = document.getElementById("slider_qt");
let selector = document.getElementById("selector");
let SelectValue = document.getElementById("SelectValue");
SelectValue.innerHTML = slider.value;
slider_qt.oninput = function () {
SelectValue.innerHTML = this.value;
selector.style.left = this.value + "%";
};
.container_quality_tools {
width: 100%;
margin-top: 20%;
}
.slider_text {
font-size: 10px;
margin-bottom: 1%;
margin-left: 20px;
}
#slider_qt {
-webkit-appearance: none;
width: 100%;
margin-left: 3%;
margin-right: 0%;
height: 7px;
outline: none;
border-radius: 3px;
}
#slider_qt::-webkit-slider-thumb {
-webkit-appearance: none;
width: 30px;
height: 30px;
cursor: pointer;
z-index: 3;
position: relative;
}
#selector {
position: absolute;
left: 85%;
margin-top: -10%;
}
.SelectorBtn {
height: 14px;
width: 14px;
background-image: url("../media/slider-icon-14.jpg");
background-size: cover;
background-position: center;
border-radius: 50%;
bottom: 0;
}
#SelectValue {
width: 20px;
height: 20px;
position: absolute;
top: -25px;
left: -2px;
background: #feb360;
border-radius: 4px;
text-align: center;
line-height: 20px;
font-size: 8px;
font-weight: bold;
}
#SelectValue::after {
content: "";
border-top: 12px solid #feb360;
border-left: 10px solid #f1f0f0;
border-right: 10px solid #f1f1f1;
position: absolute;
bottom: -4px;
left: 0;
z-index: -1;
}
<div class="row no-gutters">
<div class="col-6">
<div class="container_quality_tools">
<p class="slider_text">Quality Tools</p>
<input type="range" min="1" max="100" value="90" id="slider_qt">
<div id="selector">
<div class="SelectorBtn"></div>
<div id="SelectValue"></div>
</div>
</div>
</div>
</div>
Chrome:
Firefox:
Make background and border disappear with -moz-range-thumb pseudo selector.
#slider_qt::-moz-range-thumb {
background-color: #fff;
border: 0;
width: 30px;
height: 30px;
cursor: pointer;
z-index: 3;
position: relative;
}
It looks broken in the snippet, but I think it would work in your code.
let slider = document.getElementById("slider_qt");
let selector = document.getElementById("selector");
let SelectValue = document.getElementById("SelectValue");
SelectValue.innerHTML = slider.value;
slider_qt.oninput = function() {
SelectValue.innerHTML = this.value;
selector.style.left = this.value + "%";
};
.container_quality_tools {
width: 100%;
margin-top: 20%;
}
.slider_text {
font-size: 10px;
margin-bottom: 1%;
margin-left: 20px;
}
#slider_qt {
-webkit-appearance: none;
width: 100%;
margin-left: 3%;
margin-right: 0%;
height: 7px;
outline: none;
border-radius: 3px;
}
#slider_qt::-webkit-slider-thumb {
-webkit-appearance: none;
width: 30px;
height: 30px;
cursor: pointer;
z-index: 3;
position: relative;
}
#slider_qt::-moz-range-thumb {
background-color: #fff;
border: 0;
width: 30px;
height: 30px;
cursor: pointer;
z-index: 3;
position: relative;
}
#selector {
position: absolute;
left: 85%;
margin-top: -10%;
}
.SelectorBtn {
height: 14px;
width: 14px;
background-image: url("../media/slider-icon-14.jpg");
background-size: cover;
background-position: center;
border-radius: 50%;
bottom: 0;
}
#SelectValue {
width: 20px;
height: 20px;
position: absolute;
top: -25px;
left: -2px;
background: #feb360;
border-radius: 4px;
text-align: center;
line-height: 20px;
font-size: 8px;
font-weight: bold;
}
#SelectValue::after {
content: "";
border-top: 12px solid #feb360;
border-left: 10px solid #f1f0f0;
border-right: 10px solid #f1f1f1;
position: absolute;
bottom: -4px;
left: 0;
z-index: -1;
}
<div class="row no-gutters">
<div class="col-6">
<div class="container_quality_tools">
<p class="slider_text">Quality Tools</p>
<input type="range" min="1" max="100" value="90" id="slider_qt">
<div id="selector">
<div class="SelectorBtn"></div>
<div id="SelectValue"></div>
</div>
</div>
</div>
</div>
``` in the end I was able to solve it like this! Thx all for support! ``
#slider_qt::-moz-range-thumb {
-webkit-appearance: none;
background: transparent;
border-color: transparent;
color: transparent;
width: 20px;
height: 20px;
cursor: pointer;
}

How do I cancel my button:hover in css when a button is clicked?

I have a .button:hover thing in my css code, but I want that code to be canceled for five seconds when my button is pressed? My code is below.
function myFunction(){
var text = document.getElementById('input').value;
var textArray = text.split(" ").sort();
var output= document.getElementById('output');
output.value = textArray.toString().replace(/,/g," ");
}
function maFunction() {
var copyText = document.getElementById("output");
copyText.select();
copyText.setSelectionRange(0, 99999)
document.execCommand("copy");
}
/*function ok() {
document.getElementById("copied").innerHTML = "Hello World";
}
*/
/*function fadeOut(){
location.href='index.html#open-modal';
setTimeout(function () {
location.href='index.html#modal-close';
}, 1000);
}*/
body {
margin-top: 10px;
margin-left: 20px;
display: flex;
}
.form {
margin-right: 20px;
background: #ffffff;
position: relative;
}
.input {
height: 700px;
width: 600px;
margin-top: 15px;
outline: none;
font-size: 26px;
resize: none;
border-style: solid;
border-color: #4CAF50;
border-width: 2px;
outline: none;
border-radius: 10px;
margin-top: 0px;
padding-top: 5px;
padding-left: 10px;
}
.otput {
height: 695px;
width: 620px;
outline: none;
resize: none;
border-style: solid;
border-color: #4CAF50;
border-width: 2px;
border-radius: 10px;
outline: none;
margin-left: 10px;
}
.output {
height: 650px;
width: 512px;
outline: none;
font-size: 26px;
resize: none;
outline: none;
border: none;
padding: 0px;
margin-top: 5px;
margin-left: 10px;
}
.button {
background: #4CAF50;
border: none;
outline: none;
color: #ffffff;
padding: 14px;
width: 100px;
border-radius: 0 10px;
/*margin-left: 1134px;*/
font-size: 22px;
cursor: pointer;
position: absolute;
}
.speech-bubble {
height: 20px;
width: 150px;
color: white;
font-size: 20px;
text-align: left;
position: relative;
background: #4CAF50;
border-radius: 1px;
padding: 10px 10px 10px 5px;
box-shadow: 0 4px 8px 0 rgba(141, 105, 105, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
display: none;
margin-top: 35px;
margin-left: 630px;
}
.speech-bubble:after {
content: '';
position: absolute;
left: 0;
top: 50%;
width: 0;
height: 0;
border: 9px solid transparent;
border-right-color: #4CAF50;
border-left: 0;
margin-top: -9px;
margin-left: -9px;
}
.button:hover + .speech-bubble {
transform: translateY(-690px);
display: block;
}
.button:hover + .speech-bubble:after {
display: block;
}
::selection {
color: black;
background: lightblue;
}
::-webkit-scrollbar {
width: 10px;
}
::-webkit-scrollbar:hover {
width: 20px;
}
::-webkit-scrollbar-thumb {
background: #888;
}
/*.modal-window {
position: fixed;
background-color: rgba(200, 200, 200, 0.75);
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 999;
opacity: 0;
pointer-events: none;
-webkit-transition: all 0.3s;
-moz-transition: all 0.3s;
transition: all 0.3s;
}
.modal-window:target {
opacity: 1;
pointer-events: auto;
}
.modal-window > div {
width: 170px;
height: 50px;
padding: 10px;
position: relative;
margin: 10% auto;
/*padding: 2rem;*/
/*background: #fff;
color: #333;
}
.modal-window .copy{
font-size: 20px;
}*/
<html>
<head>
<title>alphabetical order machine</title>
<link rel="stylesheet" href="index.css">
</head>
<body>
<textarea class="input" id="input" type="text" placeholder="type your text here" onchange="myFunction()" onkeyup="myFunction()"></textarea>
<form class="otput">
<textarea class="output" id="output" type="output" placeholder="your alphabetized text will appear here"></textarea>
<input class="button" type='button' value="copy" onclick="maFunction()">
<p class="speech-bubble">click to copy text</p>
<!--p id="copied" class="copied"></p-->
</form>
<script src="index.js"></script>
</body>
</html>
You can add a class on click and use it to set display:none for the speech buble .
possible example
function myFunction(){
var text = document.getElementById('input').value;
var textArray = text.split(" ").sort();
var output= document.getElementById('output');
output.value = textArray.toString().replace(/,/g," ");
}
function maFunction(el) { //update : el
el.classList.add('clicked');// update
var copyText = document.getElementById("output");
copyText.select();
copyText.setSelectionRange(0, 99999)
document.execCommand("copy");
setTimeout( () => el.classList.remove('clicked'),5000);//Oups, needed : update to recover hover behavior after 5s
}
/*function ok() {
document.getElementById("copied").innerHTML = "Hello World";
}
*/
/*function fadeOut(){
location.href='index.html#open-modal';
setTimeout(function () {
location.href='index.html#modal-close';
}, 1000);
}*/
body {
margin-top: 10px;
margin-left: 20px;
display: flex;
}
.form {
margin-right: 20px;
background: #ffffff;
position: relative;
}
.input {
height: 700px;
width: 600px;
margin-top: 15px;
outline: none;
font-size: 26px;
resize: none;
border-style: solid;
border-color: #4CAF50;
border-width: 2px;
outline: none;
border-radius: 10px;
margin-top: 0px;
padding-top: 5px;
padding-left: 10px;
}
.otput {
height: 695px;
width: 620px;
outline: none;
resize: none;
border-style: solid;
border-color: #4CAF50;
border-width: 2px;
border-radius: 10px;
outline: none;
margin-left: 10px;
}
.output {
height: 650px;
width: 512px;
outline: none;
font-size: 26px;
resize: none;
outline: none;
border: none;
padding: 0px;
margin-top: 5px;
margin-left: 10px;
}
.button {
background: #4CAF50;
border: none;
outline: none;
color: #ffffff;
padding: 14px;
width: 100px;
border-radius: 0 10px;
/*margin-left: 1134px;*/
font-size: 22px;
cursor: pointer;
position: absolute;
}
.speech-bubble {
height: 20px;
width: 150px;
color: white;
font-size: 20px;
text-align: left;
position: relative;
background: #4CAF50;
border-radius: 1px;
padding: 10px 10px 10px 5px;
box-shadow: 0 4px 8px 0 rgba(141, 105, 105, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
display: none;
margin-top: 35px;
margin-left: 630px;
}
.speech-bubble:after {
content: '';
position: absolute;
left: 0;
top: 50%;
width: 0;
height: 0;
border: 9px solid transparent;
border-right-color: #4CAF50;
border-left: 0;
margin-top: -9px;
margin-left: -9px;
}
.button:hover + .speech-bubble {
transform: translateY(-690px);
display: block;
}
.button:hover + .speech-bubble:after {
display: block;
}
.button.clicked + .speech-bubble {display:none}/* UPDATE HERE */
::selection {
color: black;
background: lightblue;
}
::-webkit-scrollbar {
width: 10px;
}
::-webkit-scrollbar:hover {
width: 20px;
}
::-webkit-scrollbar-thumb {
background: #888;
}
/*.modal-window {
position: fixed;
background-color: rgba(200, 200, 200, 0.75);
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 999;
opacity: 0;
pointer-events: none;
-webkit-transition: all 0.3s;
-moz-transition: all 0.3s;
transition: all 0.3s;
}
.modal-window:target {
opacity: 1;
pointer-events: auto;
}
.modal-window > div {
width: 170px;
height: 50px;
padding: 10px;
position: relative;
margin: 10% auto;
/*padding: 2rem;*/
/*background: #fff;
color: #333;
}
.modal-window .copy{
font-size: 20px;
}*/
<textarea class="input" id="input" type="text" placeholder="type your text here" onchange="myFunction()" onkeyup="myFunction()"></textarea>
<form class="otput">
<textarea class="output" id="output" type="output" placeholder="your alphabetized text will appear here"></textarea>
<input class="button" type='button' value="copy" onclick="maFunction(this)"><!-- update on onclick -->
<p class="speech-bubble">click to copy text</p>
<!--p id="copied" class="copied"></p-->
</form>
Create a new class called .clicked, which contains the styling you want to see when the button is clicked. Then add the class to the button for 5 seconds.
function clicked (button) {
button.classList.add('clicked');
setTimeout(
() => button.classList.remove('clicked'),
5000);
}
button:hover.clicked {
background-color: red;
}
button:hover.clicked + .speech-bubble {
color: blue;
background-color: #aaa;
}
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" rel="stylesheet" />
<div class="m-4">
<button class="btn btn-primary" onclick="clicked(this);">Sample Button</button>
<p class="speech-bubble">click to copy text</p>
</div>

Range Slider - Down Arrow to Follow Thumb

I have a range slider with an output element above it. Below the output element is a down arrow that follows wherever the thumb is on the slider.
I'm using CSS to place the arrow and to animate it as well.
Unfortunately, the arrow is not consistently above the thumb, considering that the slider is responsive.
Thanks for your help!
$(function() {
var slider = document.getElementById("range-slider");
var output = document.getElementById("range-slider-output");
output.innerHTML = slider.value;
slider.oninput = function() {
output.innerHTML = this.value;
// resets state of user icon
$('.fa-user').removeClass("disabled");
if (output.innerHTML == 1) {
document.getElementById("range-slider").setAttribute("aria-valuenow", "1");
$('.range-slider-icons li:nth-of-type(2) span, .range-slider-icons li:nth-of-type(3) span, .range-slider-icons li:nth-of-type(4) span').addClass('disabled');
} else if (output.innerHTML == 2) {
document.getElementById("range-slider").setAttribute("aria-valuenow", "2");
$('.range-slider-icons li:nth-of-type(3) span, .range-slider-icons li:nth-of-type(4) span').addClass('disabled');
} else if (output.innerHTML == 3) {
document.getElementById("range-slider").setAttribute("aria-valuenow", "3");
$('.range-slider-icons li:nth-of-type(4) span').addClass('disabled');
} else {
document.getElementById("range-slider").setAttribute("aria-valuenow", "4");
}
}
});
.range-slider-output {
position: relative;
display: inline-block;
padding: 0.2em 0.75em 0.25em;
color: #fff;
text-align: center;
background: #666;
border-radius: 3px;
width: 100%;
left: calc(50%);
flex: 0 0 5%;
align-self: center;
margin: 0;
font-size: 28px;
-webkit-transform: translateX(-50%);
transform: translateX(-50%);
top: -92px;
}
.range-slider-output::before {
position: absolute;
top: 50%;
left: 0;
content: "";
}
.range-slider-lg .range-slider-output::before {
top: 48px;
width: 0;
height: 0;
border-style: solid;
border-width: 12px 12px 0 12px;
border-color: #666 transparent transparent transparent;
transition: all 0.7s ease-out;
}
.range-slider-wrap {
min-width: 250px;
}
input[aria-valuenow='1']+.range-slider-output::before {
left: 1rem;
}
input[aria-valuenow='2']+.range-slider-output::before {
left: 32.5%;
}
input[aria-valuenow='3']+.range-slider-output::before {
left: 64%;
}
input[aria-valuenow='4']+.range-slider-output::before {
left: 94%;
}
input[type='range'] {
width: 100%;
cursor: pointer;
padding-top: 90px;
}
input[type='range'] {
-webkit-appearance: none;
}
input[type='range']::-webkit-slider-runnable-track {
width: 100%;
height: 5px;
background: #e6e5e5;
border: 1px solid #999;
border-radius: 3px;
-webkit-appearance: none;
padding: 0 0.5rem;
}
input[type='range']::-moz-range-track {
width: 100%;
height: 5px;
background: #e6e5e5;
border: 1px solid #999;
border-radius: 3px;
}
input[type=range]::-webkit-slider-thumb {
width: 28px;
height: 28px;
margin-top: -11px;
background: #999;
border: 1px solid #666;
border-radius: 50%;
-webkit-appearance: none;
}
input[type='range']::-moz-range-thumb {
width: 28px;
height: 28px;
margin-top: -11px;
background: #999;
border: 1px solid #666;
border-radius: 50%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container">
<div class="row">
<div class="col-md-12">
<div class="form-group">
<div class="range-slider-wrap range-slider-lg">
<input class="range-slider ng-valid ng-dirty ng-touched" step="1" type="range" id="range-slider" min="1" max="4" data-tooltip-top="true" aria-valuenow="3" aria-valuemin="1" aria-valuemax="4">
<output class="range-slider-output num" id="range-slider-output" for="range-slider"></output>
</div>
</div>
</div>
</div>
</div>
The thing is that notches are not simply positionned by percentage like:
first = 0%
second = 33.3%
third = 66.6%
fourth = 100%
The slider-thumb has a dimension... 28px in your case.
And there are spacings before the first notch and the last...
The arrow also has a width!
So the alignment calculation can become twisty...
I didn't find anything close to a all cases formula. But using calc() with a "logical percentage" and an offset in px, it does the job right and is responsive. It just a matter of a couple try and fail to find the right offset.
Here is the only lines I changed from your snippet:
input[aria-valuenow='1'] + .range-slider-output::before {
left: 11px;
}
input[aria-valuenow='2'] + .range-slider-output::before {
left: calc(33.3% - 4px);
}
input[aria-valuenow='3'] + .range-slider-output::before {
left: calc(66.6% - 20px);
}
input[aria-valuenow='4'] + .range-slider-output::before {
left: calc(100% - 36px);
}
I also added bootstrap files (that were in your fiddle).
Updated Fiddle
Working snippet
$(function() {
var slider = document.getElementById("range-slider");
var output = document.getElementById("range-slider-output");
output.innerHTML = slider.value;
slider.oninput = function() {
output.innerHTML = this.value;
// resets state of user icon
$('.fa-user').removeClass("disabled");
if (output.innerHTML == 1) {
document.getElementById("range-slider").setAttribute("aria-valuenow", "1");
$('.range-slider-icons li:nth-of-type(2) span, .range-slider-icons li:nth-of-type(3) span, .range-slider-icons li:nth-of-type(4) span').addClass('disabled');
} else if (output.innerHTML == 2) {
document.getElementById("range-slider").setAttribute("aria-valuenow", "2");
$('.range-slider-icons li:nth-of-type(3) span, .range-slider-icons li:nth-of-type(4) span').addClass('disabled');
} else if (output.innerHTML == 3) {
document.getElementById("range-slider").setAttribute("aria-valuenow", "3");
$('.range-slider-icons li:nth-of-type(4) span').addClass('disabled');
} else {
document.getElementById("range-slider").setAttribute("aria-valuenow", "4");
}
}
});
.range-slider-output {
position: relative;
display: inline-block;
padding: 0.2em 0.75em 0.25em;
color: #fff;
text-align: center;
background: #666;
border-radius: 3px;
width: 100%;
left: calc(50%);
flex: 0 0 5%;
align-self: center;
margin: 0;
font-size: 28px;
-webkit-transform: translateX(-50%);
transform: translateX(-50%);
top: -92px;
}
.range-slider-output::before {
position: absolute;
top: 50%;
left: 0;
content: "";
}
.range-slider-lg .range-slider-output::before {
top: 48px;
width: 0;
height: 0;
border-style: solid;
border-width: 12px 12px 0 12px;
border-color: #666 transparent transparent transparent;
transition: all 0.7s ease-out;
}
.range-slider-wrap {
min-width: 250px;
}
input[aria-valuenow='1'] + .range-slider-output::before {
left: 11px;
}
input[aria-valuenow='2'] + .range-slider-output::before {
left: calc(33.3% - 4px);
}
input[aria-valuenow='3'] + .range-slider-output::before {
left: calc(66.6% - 20px);
}
input[aria-valuenow='4'] + .range-slider-output::before {
left: calc(100% - 36px);
}
input[type='range'] {
width: 100%;
cursor: pointer;
padding-top: 90px;
}
input[type='range'] {
-webkit-appearance: none;
}
input[type='range']::-webkit-slider-runnable-track {
width: 100%;
height: 5px;
background: #e6e5e5;
border: 1px solid #999;
border-radius: 3px;
-webkit-appearance: none;
padding: 0 0.5rem;
}
input[type='range']::-moz-range-track {
width: 100%;
height: 5px;
background: #e6e5e5;
border: 1px solid #999;
border-radius: 3px;
}
input[type=range]::-webkit-slider-thumb {
width: 28px;
height: 28px;
margin-top: -11px;
background: #999;
border: 1px solid #666;
border-radius: 50%;
-webkit-appearance: none;
}
input[type='range']::-moz-range-thumb {
width: 28px;
height: 28px;
margin-top: -11px;
background: #999;
border: 1px solid #666;
border-radius: 50%;
}
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"></script>
<div class="container">
<div class="row">
<div class="col-md-12">
<div class="form-group">
<div class="range-slider-wrap range-slider-lg">
<input class="range-slider ng-valid ng-dirty ng-touched" step="1" type="range" id="range-slider" min="1" max="4" data-tooltip-top="true" aria-valuenow="3" aria-valuemin="1" aria-valuemax="4">
<output class="range-slider-output num" id="range-slider-output" for="range-slider"></output>
</div>
</div>
</div>
</div>
</div>

Categories

Resources