Input Range - Highlight Selected Part [duplicate] - javascript

I want the left side to be green and the right side to be gray. As pictured above would be PERFECT. Preferably a pure CSS solution (only need to worry about WebKit).
Is such a thing possible?

Pure CSS solution:
Chrome: Hide the overflow from input[range], and fill all the space left to
thumb with shadow color.
IE: no need to reinvent the wheel: ::-ms-fill-lower
Firefox no need to reinvent the wheel: ::-moz-range-progress
/*Chrome*/
#media screen and (-webkit-min-device-pixel-ratio:0) {
input[type='range'] {
overflow: hidden;
width: 80px;
-webkit-appearance: none;
background-color: #9a905d;
}
input[type='range']::-webkit-slider-runnable-track {
height: 10px;
-webkit-appearance: none;
color: #13bba4;
margin-top: -1px;
}
input[type='range']::-webkit-slider-thumb {
width: 10px;
-webkit-appearance: none;
height: 10px;
cursor: ew-resize;
background: #434343;
box-shadow: -80px 0 0 80px #43e5f7;
}
}
/** FF*/
input[type="range"]::-moz-range-progress {
background-color: #43e5f7;
}
input[type="range"]::-moz-range-track {
background-color: #9a905d;
}
/* IE*/
input[type="range"]::-ms-fill-lower {
background-color: #43e5f7;
}
input[type="range"]::-ms-fill-upper {
background-color: #9a905d;
}
<input type="range"/>

While the accepted answer is good in theory, it ignores the fact that the thumb then cannot be bigger than size of the track without being chopped off by the overflow: hidden. See this example of how to handle this with just a tiny bit of JS.
// .chrome styling Vanilla JS
document.getElementById("myinput").oninput = function() {
var value = (this.value-this.min)/(this.max-this.min)*100
this.style.background = 'linear-gradient(to right, #82CFD0 0%, #82CFD0 ' + value + '%, #fff ' + value + '%, white 100%)'
};
#myinput {
background: linear-gradient(to right, #82CFD0 0%, #82CFD0 50%, #fff 50%, #fff 100%);
border: solid 1px #82CFD0;
border-radius: 8px;
height: 7px;
width: 356px;
outline: none;
transition: background 450ms ease-in;
-webkit-appearance: none;
}
<div class="chrome">
<input id="myinput" min="0" max="60" type="range" value="30" />
</div>

Use this simple css property to change color of checkbox, radio button and range
accent-color: #F55050;
Current browser support

Yes, it is possible. Though I wouldn't recommend it because input range is not really supported properly by all browsers because is an new element added in HTML5 and HTML5 is only a draft (and will be for long) so going as far as to styling it is perhaps not the best choice.
Also, you'll need a bit of JavaScript too. I took the liberty of using jQuery library for this, for simplicity purposes.
Here you go: http://jsfiddle.net/JnrvG/1/.

If you use first answer, there is a problem with thumb. In chrome if you want the thumb to be larger than the track, then the box shadow overlaps the track with the height of the thumb.
Just sumup all these answers and wrote normally working slider with larger slider thumb: jsfiddle
const slider = document.getElementById("myinput")
const min = slider.min
const max = slider.max
const value = slider.value
slider.style.background = `linear-gradient(to right, red 0%, red ${(value-min)/(max-min)*100}%, #DEE2E6 ${(value-min)/(max-min)*100}%, #DEE2E6 100%)`
slider.oninput = function() {
this.style.background = `linear-gradient(to right, red 0%, red ${(this.value-this.min)/(this.max-this.min)*100}%, #DEE2E6 ${(this.value-this.min)/(this.max-this.min)*100}%, #DEE2E6 100%)`
};
#myinput {
border-radius: 8px;
height: 4px;
width: 150px;
outline: none;
-webkit-appearance: none;
}
input[type='range']::-webkit-slider-thumb {
width: 6px;
-webkit-appearance: none;
height: 12px;
background: black;
border-radius: 2px;
}
<div class="chrome">
<input id="myinput" type="range" min="0" value="25" max="200" />
</div>

Building on top of #dargue3's answer, if you want the thumb to be larger than the track, you want to fully take advantage of the <input type="range" /> element and go cross browser, you need a little extra lines of JS & CSS.
On Chrome/Mozilla you can use the linear-gradient technique, but you need to adjust the ratio based on the min, max, value attributes as mentioned here by #Attila O.. You need to make sure you are not applying this on Edge, otherwise the thumb is not displayed. #Geoffrey Lalloué explains this in more detail here.
Another thing worth mentioning, is that you need to adjust the rangeEl.style.height = "20px"; on IE/Older. Simply put this is because in this case "the height is not applied to the track but rather the whole input including the thumb". fiddle
/**
* Sniffs for Older Edge or IE,
* more info here:
* https://stackoverflow.com/q/31721250/3528132
*/
function isOlderEdgeOrIE() {
return (
window.navigator.userAgent.indexOf("MSIE ") > -1 ||
!!navigator.userAgent.match(/Trident.*rv\:11\./) ||
window.navigator.userAgent.indexOf("Edge") > -1
);
}
function valueTotalRatio(value, min, max) {
return ((value - min) / (max - min)).toFixed(2);
}
function getLinearGradientCSS(ratio, leftColor, rightColor) {
return [
'-webkit-gradient(',
'linear, ',
'left top, ',
'right top, ',
'color-stop(' + ratio + ', ' + leftColor + '), ',
'color-stop(' + ratio + ', ' + rightColor + ')',
')'
].join('');
}
function updateRangeEl(rangeEl) {
var ratio = valueTotalRatio(rangeEl.value, rangeEl.min, rangeEl.max);
rangeEl.style.backgroundImage = getLinearGradientCSS(ratio, '#919e4b', '#c5c5c5');
}
function initRangeEl() {
var rangeEl = document.querySelector('input[type=range]');
var textEl = document.querySelector('input[type=text]');
/**
* IE/Older Edge FIX
* On IE/Older Edge the height of the <input type="range" />
* is the whole element as oposed to Chrome/Moz
* where the height is applied to the track.
*
*/
if (isOlderEdgeOrIE()) {
rangeEl.style.height = "20px";
// IE 11/10 fires change instead of input
// https://stackoverflow.com/a/50887531/3528132
rangeEl.addEventListener("change", function(e) {
textEl.value = e.target.value;
});
rangeEl.addEventListener("input", function(e) {
textEl.value = e.target.value;
});
} else {
updateRangeEl(rangeEl);
rangeEl.addEventListener("input", function(e) {
updateRangeEl(e.target);
textEl.value = e.target.value;
});
}
}
initRangeEl();
input[type="range"] {
-webkit-appearance: none;
-moz-appearance: none;
width: 300px;
height: 5px;
padding: 0;
border-radius: 2px;
outline: none;
cursor: pointer;
}
/*Chrome thumb*/
input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
-moz-appearance: none;
-webkit-border-radius: 5px;
/*16x16px adjusted to be same as 14x14px on moz*/
height: 16px;
width: 16px;
border-radius: 5px;
background: #e7e7e7;
border: 1px solid #c5c5c5;
}
/*Mozilla thumb*/
input[type="range"]::-moz-range-thumb {
-webkit-appearance: none;
-moz-appearance: none;
-moz-border-radius: 5px;
height: 14px;
width: 14px;
border-radius: 5px;
background: #e7e7e7;
border: 1px solid #c5c5c5;
}
/*IE & Edge input*/
input[type=range]::-ms-track {
width: 300px;
height: 6px;
/*remove bg colour from the track, we'll use ms-fill-lower and ms-fill-upper instead */
background: transparent;
/*leave room for the larger thumb to overflow with a transparent border */
border-color: transparent;
border-width: 2px 0;
/*remove default tick marks*/
color: transparent;
}
/*IE & Edge thumb*/
input[type=range]::-ms-thumb {
height: 14px;
width: 14px;
border-radius: 5px;
background: #e7e7e7;
border: 1px solid #c5c5c5;
}
/*IE & Edge left side*/
input[type=range]::-ms-fill-lower {
background: #919e4b;
border-radius: 2px;
}
/*IE & Edge right side*/
input[type=range]::-ms-fill-upper {
background: #c5c5c5;
border-radius: 2px;
}
/*IE disable tooltip*/
input[type=range]::-ms-tooltip {
display: none;
}
input[type="text"] {
border: none;
}
<input type="range" value="80" min="10" max="100" step="1" />
<input type="text" value="80" size="3" />

A small update to this one:
if you use the following it will update on the fly rather than on mouse release.
"change mousemove", function"
<script>
$('input[type="range"]').on("change mousemove", function () {
var val = ($(this).val() - $(this).attr('min')) / ($(this).attr('max') - $(this).attr('min'));
$(this).css('background-image',
'-webkit-gradient(linear, left top, right top, '
+ 'color-stop(' + val + ', #2f466b), '
+ 'color-stop(' + val + ', #d3d3db)'
+ ')'
);
});</script>

You can simply use the accent color (in Chrome 99)
<input style="accent-color: #2ecc71" type="range"/>

The previous accepted solution is not working any longer.
I ended up coding a simple function which wraps the range into a styled container adding the bar that is needed before the cursor.
I wrote this example where easy to see the two colors 'blue' and 'orange' set in the css, so they can be quickly modified.

-webkit-appearance: none; removes tick marks when using datalist. If the general appearance of the slider is fine, but the default blue color (in Chrome) needs to fit a theme color, apply a filter: hue-rotate(); to the input[type="range"] element. Other filters can be used. Some even change the background color of the slider.
input[type="range"] {
filter: hue-rotate(180deg); //rotate degrees to get desired color
}
<input type="range" min="0" max="5" step="1" list="data" value="1" />
<datalist id="data">
<option>0</option>
<option>1</option>
<option>2</option>
<option>3</option>
<option>4</option>
<option>5</option>
</datalist>

It's now supported with pseudo elements in each of WebKit, Firefox and IE. But, of course, it's different in each one. : (
See this question's answers and/or search for a CodePen titled prettify <input type=range> #101 for some solutions.

Here is another approach if you don't mind using JS. This #steveholgado Codepen overlays 3 divs for the track, progress, and thumb over the top of an input[type=range] with an opacity of zero (transparent). An oninput listener updates the styles for the divs to create pretty much any appearance you want.
The nice thing is that it is fairly browser agnostic, and deals with the inflexibility of styling sliders on Chrome. It offers a lot more styling flexibility in general.
If you want to use something other than 0 to 100 for the slider range, you'll have to scale appropriately in the listener. For example, value = value * 100 / parseInt(range.getAttribute("max")); (assuming min=0)
https://codepen.io/steveholgado/pen/OEpGXq
HTML:
<div class="wrap">
<input type="range" class="range" min="0" max="100" step="0.1" value="0">
<div class="track">
<div class="track-inner"></div>
</div>
<div class="thumb"></div>
</div>
CSS:
.wrap {
width: 300px;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.range {
width: 100%;
cursor: pointer;
opacity: 0;
}
.range::-ms-tooltip {
display: none;
}
.track {
width: 100%;
height: 4px;
background: #DDDDDD;
position: absolute;
top: 50%;
transform: translateY(-50%);
pointer-events: none;
}
.track-inner {
width: 0;
height: 100%;
background: #E24F4F;
}
.thumb {
width: 16px;
height: 16px;
background: #AAAAAA;
border-radius: 50%;
position: absolute;
top: 50%;
left: 0;
transform: translate(0%, -50%);
pointer-events: none;
}
JS:
const range = document.querySelector('.range')
const thumb = document.querySelector('.thumb')
const track = document.querySelector('.track-inner')
const updateSlider = (value) => {
thumb.style.left = `${value}%`
thumb.style.transform = `translate(-${value}%, -50%)`
track.style.width = `${value}%`
}
range.oninput = (e) =>
updateSlider(e.target.value)
updateSlider(50) // Init value

input type="range" min="0" max="50" value="0" style="margin-left: 6%;width: 88%;background-color: whitesmoke;"
above code changes range input style.....

Related

How make a textarea with tags in react that have clickable dropdown

Id like to make a component in react that allows me to have a textarea with tags that can be inserted when clicked from a dropdown. Id also like this textarea to be able to mix text aswell. I have currently been trying to use tagify with react but I cant seem to figure out a way to the tagify's function that adds the tag to be accessed by the onClick that is connected to the dropdown.
Any ideas?
I believe you can get your answer in this URL of other question asked on StackOverflow https://stackoverflow.com/a/38119725/15405352
var $container = $('.container');
var $backdrop = $('.backdrop');
var $highlights = $('.highlights');
var $textarea = $('textarea');
var $toggle = $('button');
// yeah, browser sniffing sucks, but there are browser-specific quirks to handle that are not a matter of feature detection
var ua = window.navigator.userAgent.toLowerCase();
var isIE = !!ua.match(/msie|trident\/7|edge/);
var isWinPhone = ua.indexOf('windows phone') !== -1;
var isIOS = !isWinPhone && !!ua.match(/ipad|iphone|ipod/);
function applyHighlights(text) {
text = text
.replace(/\n$/g, '\n\n')
.replace(/[A-Z].*?\b/g, '<mark>$&</mark>');
if (isIE) {
// IE wraps whitespace differently in a div vs textarea, this fixes it
text = text.replace(/ /g, ' <wbr>');
}
return text;
}
function handleInput() {
var text = $textarea.val();
var highlightedText = applyHighlights(text);
$highlights.html(highlightedText);
}
function handleScroll() {
var scrollTop = $textarea.scrollTop();
$backdrop.scrollTop(scrollTop);
var scrollLeft = $textarea.scrollLeft();
$backdrop.scrollLeft(scrollLeft);
}
function fixIOS() {
// iOS adds 3px of (unremovable) padding to the left and right of a textarea, so adjust highlights div to match
$highlights.css({
'padding-left': '+=3px',
'padding-right': '+=3px'
});
}
function bindEvents() {
$textarea.on({
'input': handleInput,
'scroll': handleScroll
});
$toggle.on('click', function() {
$container.toggleClass('perspective');
});
}
if (isIOS) {
fixIOS();
}
bindEvents();
handleInput();
#import url(https://fonts.googleapis.com/css?family=Open+Sans);
*, *::before, *::after {
box-sizing: border-box;
}
body {
margin: 30px;
background-color: #f0f0f0;
}
.container, .backdrop, textarea {
width: 460px;
height: 180px;
}
.highlights, textarea {
padding: 10px;
font: 20px/28px 'Open Sans', sans-serif;
letter-spacing: 1px;
}
.container {
display: block;
margin: 0 auto;
transform: translateZ(0);
-webkit-text-size-adjust: none;
}
.backdrop {
position: absolute;
z-index: 1;
border: 2px solid #685972;
background-color: #fff;
overflow: auto;
pointer-events: none;
transition: transform 1s;
}
.highlights {
white-space: pre-wrap;
word-wrap: break-word;
color: transparent;
}
textarea {
display: block;
position: absolute;
z-index: 2;
margin: 0;
border: 2px solid #74637f;
border-radius: 0;
color: #444;
background-color: transparent;
overflow: auto;
resize: none;
transition: transform 1s;
}
mark {
border-radius: 3px;
color: transparent;
background-color: #b1d5e5;
}
button {
display: block;
width: 300px;
margin: 30px auto 0;
padding: 10px;
border: none;
border-radius: 6px;
color: #fff;
background-color: #74637f;
font: 18px 'Opens Sans', sans-serif;
letter-spacing: 1px;
appearance: none;
cursor: pointer;
}
.perspective .backdrop {
transform:
perspective(1500px)
translateX(-125px)
rotateY(45deg)
scale(.9);
}
.perspective textarea {
transform:
perspective(1500px)
translateX(155px)
rotateY(45deg)
scale(1.1);
}
textarea:focus, button:focus {
outline: none;
box-shadow: 0 0 0 2px #c6aada;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container">
<div class="backdrop">
<div class="highlights"></div>
</div>
<textarea>This demo shows how to highlight bits of text within a textarea. Alright, that's a lie. You can't actually render markup inside a textarea. However, you can fake it by carefully positioning a div behind the textarea and adding your highlight markup there. JavaScript takes care of syncing the content and scroll position from the textarea to the div, so everything lines up nicely. Hit the toggle button to peek behind the curtain. And feel free to edit this text. All capitalized words will be highlighted.</textarea>
</div>
<button>Toggle Perspective</button>
Reference- https://codepen.io/lonekorean/pen/gaLEMR for example

How to apply custom styles to the HTML element of input type range for different browsers? [duplicate]

I want to style the bar before the thumb with a different color on a range input. I'v tried looking for a solution but I havent found a proper solution. This is what I need it to look like:
Chrome doesnt seem to support input[type='range']::-webkit-slider-thumb:before anymore and I am at a loss how to style it. Here's what I have so far:
input[type='range'] {
min-width: 100px;
max-width: 200px;
&::-webkit-slider-thumb {
-webkit-appearance: none !important;
background-color: #white;
border: 1px solid #gray-4;
height: 14px;
width: 14px;
&:hover,
&:focus,
&:active {
border-color: #blue;
background-color: #gray-2;
}
}
&::-webkit-slider-runnable-track {
background-color: #gray-2;
border: 1px solid #gray-4;
}
}
document.querySelectorAll(".__range").forEach(function(el) {
el.oninput =function(){
var valPercent = (el.valueAsNumber - parseInt(el.min)) /
(parseInt(el.max) - parseInt(el.min));
var style = 'background-image: -webkit-gradient(linear, 0% 0%, 100% 0%, color-stop('+ valPercent+', #29907f), color-stop('+ valPercent+', #f5f6f8));';
el.style = style;
};
el.oninput();
});
.__range{
margin:30px 0 20px 0;
-webkit-appearance: none;
background-color: #f5f6f8;
height: 3px;
width: 100%;
margin: 10px auto;
}
.__range:focus{
outline:none;
}
.__range::-webkit-slider-thumb{
-webkit-appearance: none;
width: 20px;
height: 20px;
background: #29907f;
border-radius: 50%;
cursor: -moz-grab;
cursor: -webkit-grab;
}
<input class="__range" id="rng" name="rng" value="30" type="range" max="100" min="1" value="100" step="1">
The trick in the post referenced by shambalambala is clever, but I don't think it will work in this case if you want to get something that looks exactly like the image you show. The approach there is to put a shadow on the thumb to create the different coloring to the left of the thumb. Since the shadow extends in the vertical, as well as the horizontal, direction, you also have to add overflow:hidden to the range or the track in order to clip the shadow. Unfortunately, this also clips the thumb. So if you want a thumb that extends beyond the track in the vertical dimension, such as in the image you show where the thumb is a circle with a diameter larger than the track width, this won't work.
I'm not sure there's a pure CSS solution to this problem. With JavaScript, one way around this is to make two range elements that overlap exactly. For one range element, you will see only the thumb and for one you will see only the track. You can use the shadow approach on the track element to get the different color before the thumb. You can style the thumb on the thumb range however you want, and since overflow is not set to hidden for this range element, it can extend beyond the width of the track. You can then use JavaScript to yoke the two range elements together, so that when you move the thumb on the thumb-visible element, the value of the track-visible element also changes.
For example (works in webkit browsers--will need some additional styling for other browsers):
<html>
<head>
<style>
.styled_range {
position: relative;
padding: 10px;
}
input[type=range] {
-webkit-appearance: none;
width: 600px;
background: transparent;
position: absolute;
top: 0;
left: 0;
}
input[type=range]::-webkit-slider-thumb {
-webkit-appearance: none;
}
input[type=range]:focus {
outline: none;
}
input[type=range]::-webkit-slider-runnable-track {
width: 100%;
height: 12px;
}
.track_range {
pointer-events: none;
}
.track_range::-webkit-slider-runnable-track {
background: #D0D0D0;
border-radius: 6px;
overflow: hidden;
}
.track_range::-webkit-slider-thumb {
-webkit-appearance: none;
background: transparent;
height: 1px;
width: 1px;
box-shadow: -600px 0 0 600px #666666;
}
.thumb_range::-webkit-slider-runnable-track {
background: transparent;
cursor: pointer;
}
.thumb_range::-webkit-slider-thumb {
-webkit-appearance: none;
border: 3px solid #ffffff;
border-radius: 20px;
height: 40px;
width: 40px;
background: #1180AD;
cursor: pointer;
margin: -12px 0px 0px 0px;
}
</style>
</head>
<body>
<form>
<div class="styled_range">
<input type="range" class="track_range"/>
<input type="range" class="thumb_range"/>
</div>
<br/>
<div class="styled_range">
<input type="range" class="track_range"/>
<input type="range" class="thumb_range"/>
</div>
</form>
</body>
<script>
window.onload = function() {
var styledRanges = document.getElementsByClassName('styled_range');
for (var i=0; i<styledRanges.length; i++) {
var thumbRange = null, trackRange = null;
for (var j=0; j<styledRanges[i].children.length; j++) {
var child = styledRanges[i].children[j];
if (child.className === 'thumb_range')
var thumbRange = child;
else if (child.className === 'track_range')
var trackRange = child;
}
thumbRange.oninput = function(thumbRange, trackRange) {
return function(e) {
trackRange.value = thumbRange.value;
};
}(thumbRange, trackRange);
}
}
</script>
</html>

Make input range not jump when I hit thumb not exactly in center

Below is HTML input of type range. I made it bigger so that it is more noticable. When I mouse down on red thumb and move to side, if I am not perfectly in the center of thumb it will jump so that mouse cursors is in the center of thumb and then it moves normally.
Is it possible to change it so that there is no first sudden jump on first move?
input[type=range] {
-webkit-appearance: none;
pointer-events: none;
background-color: green;
}
input[type=range]::-webkit-slider-thumb {
-webkit-appearance: none;
width: 1cm;
height: 1cm;
background-color: red;
cursor: pointer;
pointer-events: auto !important;
}
<input type="range">
I'm afraid the only way the achieve this, is to override the range behavior with Javascript.
I did it with jQuery, but it could be done with vanilla JS or any other JS framework.
Please note I have fixed the CSS to make it works in Firefox.
I also had to use px instead of cm for the thumb width, so that this value can be provided to JS.
function overrideSliderBehavior() {
var el = $(this);
var thumbWidth = parseFloat(el.data('thumb-width'));
if(!thumbWidth) {
return;
}
var dragOrigin = null;
el.on('mousedown', function(evt) {
evt.preventDefault();
dragOrigin = {
x:event.clientX,
val:parseFloat(el.val())
};
});
$(document).on('mouseup', function(){
dragOrigin = null;
});
$(document).on('mousemove', function(evt) {
if(dragOrigin !== null) {
evt.preventDefault();
var rect = el[0].getBoundingClientRect();
var offsetX = (event.clientX - dragOrigin.x);
var offsetVal = offsetX/(rect.width - thumbWidth);
var max = el[0].max || 100;
var min = el[0].min || 0;
el.val(dragOrigin.val + offsetVal*(max - min));
}
});
}
$(document).ready(function() {
$('input[type=range]').each(overrideSliderBehavior);
});
input[type=range] {
-webkit-appearance: none;
pointer-events: none;
background-color: green;
height: 38px;
}
input[type=range]::-webkit-slider-thumb {
-webkit-appearance: none;
width: 38px;
height: 38px;
background-color: red;
cursor: pointer;
pointer-events: auto !important;
}
input[type=range]::-moz-range-thumb {
width: 38px;
height: 38px;
background-color: red;
cursor: pointer;
pointer-events: auto !important;
border: none;
border-radius: 0;
}
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha256-4+XzXVhsDmqanXGHaHvgh1gMQKX40OUvDEBTu8JcmNs=" crossorigin="anonymous"></script>
<input type="range" data-thumb-width="38">

How to define the css :focus state in a jQuery selector?

Here is a resizable textarea:
var KeyDown;
$(".TxtArea > div").mousedown(function(){
$(this).parent().addClass("Resize");
$("body").addClass("UnSelectable");
KeyDown = 1;
$("textarea").css("opacity","0.3");
$("textarea").focus(function() { $(this).css("border-color","#ccc") });
});
$(document).mouseup(function(){
$(".TxtArea").removeClass("Resize");
$("body").removeClass("UnSelectable");
KeyDown = 0;
$("textarea").css("opacity","1");
$("textarea").focus(function() { $(this).css("border-color","#07c") });
});
$(document).mousemove(function(Event){
if (KeyDown == 1 && $(".TxtArea").hasClass("Resize")) {
var Height = Event.pageY - $(".TxtArea").children("textarea").offset().top;
$("textarea").height(Height);
}
});
textarea {
border: 1px solid #ccc;
outline:none;
}
textarea:focus{
border: 1px solid #07c;
}
.TxtArea {
width: 300px;
}
.TxtArea > textarea {
width: 100%;
display: block;
resize: none;
box-sizing: border-box;
}
.TxtArea > div {
height: 10px;
background: #eee;
border: 1px solid #ddd;
box-sizing: border-box;
text-align: center;
line-height: 0px;
}
.TxtArea > div:hover {
cursor: n-resize;
}
.UnSelectable {
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="TxtArea">
<textarea></textarea>
<div>.....</div>
</div>
Please follow these steps:
run the above fiddle
write something on that textarea
click on x-scroll bar on the bottom of textarea and keep it
move your mouse and resize that textarea (Now border color is #ccc and opacity is 0.3)
after resizing, leave your finger from click (Now opacity will be 1 but border doesn't change)
Why border doesn't change? and how can I return it to #07c after unclicking. How can I do that? (I want something exactly like SO)
Note: I want to set #07c just only focus state of that textarea after unclicking (Not a permanent border)
So I'm not sure exactly why your focus code wasn't working, but in general, this is just better practice. Typically you want the css to handle all of the styling and the javascript just toggles it. It just keeps things cleaner and more organized.
So you can do this: https://jsfiddle.net/psp12a0n/
The main thing that was changed was this part in the javascript:
$(".TxtArea > div").mousedown(function(){
$(this).parent().addClass("Resize");
$("body").addClass("UnSelectable");
KeyDown = 1;
$("textarea").addClass('inactive');
});
$(document).mouseup(function(){
$(".TxtArea").removeClass("Resize");
$("body").removeClass("UnSelectable");
KeyDown = 0;
$("textarea").removeClass('inactive');
});
And this in the css:
textarea:focus,
textarea:active {
border: 1px solid #07c;
}
textarea.inactive {
opacity: .3;
border-color: #ccc;
}
Hope this works for you!

Making range output responsive

Ok, so the problem I'm having is making the output for the range responsive.
It's currently working fine when you run the code because the value is being position in pixels, but when you resize the viewport is doesn't align with the slider thumb correctly. I thought maybe aligning the output using percentages instead of pixels might fix the problem but I'm not sure how to implement it correctly.
I have tried messing around with it but no luck, does anyone know how I can achieve this?
HTML:
<form>
<div class="range-control" data-thumbwidth="20">
<input id="inputRange" type="range" min="0" max="100" step="1" value="0">
<div><output name="rangeVal">0</output></div>
</div>
</form>
CSS:
*,
*:before,
*:after {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
html {
font-family: Arial, sans-serif;
}
form {
padding-top: 100px;
margin: 0 auto;
}
.range-control {
position: relative;
}
input[type=range] {
display: block;
width: 100%;
margin: 0;
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
outline: none;
}
input[type=range]::-webkit-slider-runnable-track {
position: relative;
height: 12px;
border: 1px solid #b2b2b2;
border-radius: 5px;
background-color: #e2e2e2;
box-shadow: inset 0 1px 2px 0 rgba(0,0,0,0.1);
}
input[type=range]::-webkit-slider-thumb {
position: relative;
top: -5px;
width: 20px;
height: 20px;
border: 1px solid #999;
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
background-color: #fff;
box-shadow: inset 0 -1px 2px 0 rgba(0,0,0,0.25);
border-radius: 100%;
cursor: pointer;
}
output {
position: absolute;
top: 20px;
width: 50px;
height: 24px;
border: 1px solid #e2e2e2;
margin-left: -15px;
background-color: #fff;
border-radius: 3px;
color: #777;
font-size: .8em;
line-height: 24px;
text-align: center;
}
input[type=range]:active + output {
display: block;
}
JQUERY:
$('.range-control').each(function(){
var container = $(this),
input = container.find('input'),
output = container.find('output'),
rangeWidth = input.width(),
thumbWidth = container.attr('data-thumbwidth'),
startValue = input.val(),
startOffset = ((rangeWidth - thumbWidth) / 100) * startValue + '%';
output
.css({
'left' : startOffset
});
$(input).on('input', function(){
var value = this.value,
offset = ((rangeWidth - thumbWidth) / 100) * value;
output
.val(value)
.css({
'left' : offset
});
});
});
JSFiddle
Any help would be appreciated greatly!!!
** EDIT ** Please Read
So below Mohamed-Yousef answered the question in the way he would do it which does work, so I have up voted it, however he has duplicated the variables twice in the code (see his answer for details about this). I think there is a more efficient way of doing this (using less code), so if anyone has a better way of doing this please share.
simply you need to update your variable on window resize to change its values .. and make your input event inside each function print it more than one time and that make it not available to read a new variable after resize .. so I take it out and run each event individual
AFTER EDIT
$(document).ready(function(){
var container,input,output,rangeWidth,thumbWidth,startValue,startOffset;
// make a function to update variable
var update_variable = function(){
$('.range-control').each(function(){
container = $(this);
input = container.find('input');
output = container.find('output');
rangeWidth = input.width();
thumbWidth = container.attr('data-thumbwidth');
startValue = input.val();
startOffset = ((rangeWidth - thumbWidth) / 100) * startValue;
output
.css({
'left' : startOffset
});
});
}
// update variable after document ready
update_variable();
// input input event
$('.range-control > input').on('input', function(){
var value = this.value,
offset = ((rangeWidth - thumbWidth) / 100) * value;
$(this).closest('.range-control').find('output')
.val(value +'%')
.css({
'left' : offset
});
});
// update variable in window resize
$(window).on('resize',update_variable);
});
DEMO HERE
Important Note: this code will work perfect if you have inputs with the same width .. if its not the same width you need to use an array of elements to get each element width

Categories