Live colour changing - javascript

I have made a color changer. but now I want to add a form to it.
if you change the dropdown it must show the color change directly.
what is the best way to do this?
Below I have added my code for the color changer
$im = b.gif;
$index = imagecolorclosest ( $im, 128,128,128); // old color
imagecolorset($im,$index,$color[0],$color[1],$color[2]); // new color
$imgname = "result.gif";
imagegif($im, $imgname ); // save image as gif
imagedestroy($im);

If you do not want to use <input type="color" />, you could use 3 <input type="range"> add change listeners to them and update the style of element you wish whenever one of them is changed. (The event change will trigger after you release the input, the event input will trigger whenever the value is changed, even if you are still holding the input). I made the coloring gets and sets using Object.defineProperty to make it easier to test.
["red", "green", "blue", "opacity"].forEach(function(colorType) {
Object.defineProperty(this, colorType, {
get: function() {
return +document.querySelector("#" + colorType).value;
}
});
document.querySelector("#" + colorType).addEventListener("input", onChange);
});
Object.defineProperty(this, "result", {
set: function(newColor) {
document.querySelector("#result").setAttribute("style", "background-color: rgba(" + newColor + ");");
}
});
onChange();
function onChange() {
result = [red, green, blue, opacity].join(", ");
}
#result {
display: block;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
<form id="result">
<input type="range" id="red" name="red" min="0" max="255" />
<input type="range" id="green" name="green" min="0" max="255" />
<input type="range" id="blue" name="blue" min="0" max="255" />
<input type="range" id="opacity" name="opacity" min="0" max="1" step="0.01" />
</form>
Object.defineProperty(this, "color", {
get: function() {
return document.querySelector("#color").value;
}
});
document.querySelector("#color").addEventListener("input", onChange);
Object.defineProperty(this, "result", {
set: function(newColor) {
document.querySelector("#result").setAttribute("style", "background-color: " + newColor + ";");
}
});
onChange();
function onChange() {
result = color;
}
#result {
display: block;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
<form id="result">
<input type="color" id="color" name="color" />
</form>

Related

how to transfer the value of range in to span?

I want to use the "update" function that queries the current value of the slider, transfers it to
Meter. Span "Value: [current value]". If the current
value is at least 85, the indicator color should be set to #ffff00, otherwise the color is
#808080.
<form onchange="update();" oninput="update();">
<input type="range" name="power" min="0" max="100" value="0">
<br>
<span>value:0</span>
</form>
<meter id="output" value="88" low="85" max="100" optimum="85"> </meter>
<div class="indicator"></div>
<script>
function update() {
let indicatorColors = ['#808080', 'ffff00'];
// here I would have to access the indicator
let indicator =
// here I would have to access indicatorColors
indicator.style.backgroundColor =
}
</script>
<!-- css part -->
<style>
#output{
height: 20px;
width: 200px;
}
.indicator{
height: 50px;
width: 50px;
border-radius: 50%;
background-color: #808080;
position: absolute;
top: 40px;
left: 210px;
}
</style>
How to get the value?
In your html, add update to <input /> instead of <form /> as input is what actually changes.
pass this into update() function (update(this)). this here refers to the element itself that onchange() is called on, which is the <input />
Now, in your js code, you can access the input's value in update() function.
const valueCounter = document.querySelector(".value-counter");
const indicator = document.querySelector(".indicator");
function update(input) { // here the input parameter gets whatever u pass to update function in your html
const value = input.value;
valueCounter.textContent = `value:${value}`;
indicator.style.backgroundColor = value >= 85 ? "#ffff00" : "#808080";
}
.indicator { /* just to view the changes */
width: 50px;
height: 50px;
}
<input type="range" name="power" min="0" max="100" value="0" onchange="update(this)">
<br>
<span class="value-counter">value:0</span>
<div class="indicator"></div>

why does two object with same property not work the same way

While doing a task in Javascript30 I noticed that
document.querySelectorAll('input')[0].style.setProperty and document.documentElement.style.setProperty output thesame object but the former does not work when I try to set a property.
I want to know why the former does not work but the later does.
I did a console.log to view the output of both lines of code.
let controller = document.querySelectorAll(".controller input");
//console.log(document.querySelectorAll('input')[0].style.setProperty);
//console.log(document.documentElement.style.setProperty);
function handleChange() {
const suffix = this.dataset.sizing || "";
document.documentElement.style.setProperty(`--${this.name}`, this.value + suffix);
/*document.querySelectorAll('input').forEach((input) => {
input.style.setProperty(`--${this.name}`, this.value + suffix);
});*/
}
controller.forEach(input => input.addEventListener('change', handleChange));
controller.forEach(input => input.addEventListener('mousemove', handleChange));
body {
text-align: center;
color: white;
background-color: rgb(150, 200, 140);
}
:root {
--blur: 10px;
--spacing: 10px;
--color: red;
}
img {
padding: var(--spacing);
filter: blur(var(--blur));
background: var(--color);
}
<header>Playing with CSS variables and JS</header>
<div class="controller">
<label for="spacing">Spacing: </label>
<input type="range" min="10" max="200" id="spacing" name="spacing" value="10" data-sizing="px">
<label for="blur">Blur: </label>
<input type="range" min="0" max="30" id="blur" name="blur" value="10" data-sizing="px">
<label for="color">Base Color</label>
<input type="color" id="color" name="color">
</div>
<img src="https://res.cloudinary.com/dzwmmrwr2/image/upload/v1542708495/6_kmfxtt.png" alt="image" width="300" height="350">
Plunker
The Problem is that you are selecting the 'input-elements' using the querySelector, instead of the 'html-element' as you do with document.documentElement
using document.querySelectorAll('html') instead of document.querySelectorAll('input') sould solve your issue:
// Code goes here
let controller = document.querySelectorAll(".controller input");
function handleChange() {
const suffix = this.dataset.sizing || "";
document.querySelectorAll('html').forEach((input) => {
input.style.setProperty(`--${this.name}`, this.value + suffix);
});
}
controller.forEach(input => input.addEventListener('change', handleChange));
controller.forEach(input => input.addEventListener('mousemove', handleChange));
body {
text-align: center;
color: white;
background-color: rgb(150, 200, 140);
}
:root {
--blur: 10px;
--spacing: 10px;
--color: red;
}
img {
padding: var(--spacing);
filter: blur(var(--blur));
background: var(--color);
}
<header>Playing with CSS variables and JS</header>
<div class="controller">
<label for="spacing">Spacing: </label>
<input type="range" min="10" max="200" id="spacing" name="spacing" value="10" data-sizing="px">
<label for="blur">Blur: </label>
<input type="range" min="0" max="30" id="blur" name="blur" value="10" data-sizing="px">
<label for="color">Base Color</label>
<input type="color" id="color" name="color">
</div>
<img src="https://res.cloudinary.com/dzwmmrwr2/image/upload/v1542708495/6_kmfxtt.png" alt="image" width="300" height="350">

Prevent slider from jumping when value is changed

I have a slider that live-updates the value on a label tag to the right of it. What should I do to prevent it from "jumping" when the value goes from 1-digit value to 2-digits value? How can I give the label a fixed position so that it won't change the layout:
var range = document.getElementById('range');
range.addEventListener('input', rangeChange);
function rangeChange() {
label.innerHTML = this.value;
}
<label id="label">0</label>
<input id="range" type="range" value=0 min=0 max=100>
Either add width: 20px;display: inline-block; to the label.
Or
Add a wrapper around both the elements and give them display: flex; align-items: center; style and width to the label.
var range = document.getElementById('range');
range.addEventListener('input', rangeChange);
function rangeChange() {
label.innerHTML = this.value;
}
<div style="display: flex; align-items: center;">
<label id="label" style="width: 20px;">0</label>
<input id="range" type="range" value=0 min=0 max=100>
</div>
Option 1: Put label to right side of slider
var range = document.getElementById('range');
range.addEventListener('input', rangeChange);
function rangeChange() {
label.innerHTML = this.value;
}
<input id="range" type="range" value=0 min=0 max=100>
<label id="label">0</label>
Option 2: Zero padding:
var range = document.getElementById('range');
range.addEventListener('input', rangeChange);
function rangeChange() {
var val = +(this.value);
if (10 > val) {
val = '00' + val;
} else if (100 > val) {
val = '0' + val;
}
label.innerHTML = val;
}
<label id="label">000</label>
<input id="range" type="range" value=0 min=0 max=100>

Multiple object events for one function?

So I'm trying to make an html page with 3 sliders for the background (R,G,B)
I want each slider to call a function that changes the background on input, but I can't get it to work unless I rewrite the function for each event. Please bear with me, I'm a new coder and most of this is spaghetti
var red = document.getElementById("red"); //slider values
var routput = document.getElementById("reddemo"); //display values
routput.innerHTML = red.value; //for function
var green = document.getElementById("green");
var goutput = document.getElementById("greendemo");
goutput.innerHTML = green.value;
var blue = document.getElementById("blue");
var boutput = document.getElementById("bluedemo");
boutput.innerHTML = blue.value;
red.oninput && blue.oninput && green.oninput = function() {
//this is what I want to do; string all of these oninputs together... obviously this way doesn't work
var x = Math.round([Number(red.value) + Number(blue.value) + Number(green.value)] / 3);
//this is for later, the text color in body changes to white when color values get too low
routput.innerHTML = Math.round(this.value);
boutput.innerHTML = Math.round(this.value);
goutput.innerHTML = Math.round(this.value);
document.body.style.backgroundColor = "rgb(" + routput.innerHTML + "," + routput.innerHTML + "," + routput.innerHTML + ")";
if (x < 127.5) {
document.body.style.color = "rgb(255,255,255)";
} else {
document.body.style.color = "rgb(0,0,0)";
}
}
<p>Red</p>
<div class="slidecontainer">
<input type="range" min="0" max="255" value="255" class="slider" id="red">
<p>Value: <span id="reddemo"></span></p>
</div>
<p>Green</p>
<div class="slidecontainer">
<input type="range" min="0" max="255" value="255" class="slider" id="green">
<p>Value: <span id="greendemo"></span></p>
</div>
<p>Blue</p>
<div class="slidecontainer">
<input type="range" min="0" max="255" value="255" class="slider" id="blue">
<p>Value: <span id="bluedemo"></span></p>
</div>
Functions in JavaScript are first-class citizens, meaning you can treat a function as a variable:
var changeBackground = function () {…};
red.oninput = changeBackground;
blue.oninput = changeBackground;
…
The other solution - Makhiel's is also correct is:
red.oninput = blue.oninput = green.oninput = function() {
&& is 'logical and' in JavaScript: it always turns into true or false. Though "Set red.oninput and blue.oninput to the same function" works in english, the and in English doesn't translate to the and in Javascript.
It's pretty straight forward using the HTMLFormControlsCollection API.
Changed the elements into more semantic as well as functional form control elements: <form>, <output>, <fieldset>,<legend>, and <label>. Used Template Literals to get all 3 values to mix in one value.
The key to reducing the number of functions and events is to use Event Delegation by having an element that is a common ancestor to the ranges, listen for the input event. Then by referencing the Event.target we can determine exactly which range is interacting with the user.
BTW in this case, there's no need to convert any values to a number because the value the CSS takes as a RGB color is actually a string that has chars that represent numbers.
Update
Added a second Demo that does the same thing as Demo 1, but with very minimal code by using On Event Attributes. Although the use of them is strongly discouraged I've seen a growing trend of it's use in current but minor code such as this.
Demo 1
Details commented in Demo
form {
display: flex;
flex-flow: column wrap;
height: 100vh;
}
.slidecontainer {
width: 40%;
height: 15vh
}
output {
transform: translate(5px, -7px);
display: inline-block;
}
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<form id='rgb'>
<fieldset class="slidecontainer">
<legend>Red</legend>
<input type="range" min="0" max="255" value="255" class="slider" id="red0">
<output id="redO"></output>
</fieldset>
<fieldset class="slidecontainer">
<legend>Green</legend>
<input type="range" min="0" max="255" value="255" class="slider" id="grn0">
<output id="grnO"></output>
</fieldset>
<fieldset class="slidecontainer">
<legend>Blue</legend>
<input type="range" min="0" max="255" value="255" class="slider" id="blu0">
<output id="bluO"></output>
</fieldset>
</form>
<script>
//Reference the form
var form = document.forms.rgb;
//Reference all of form's form controls
var rgb = form.elements;
//Register input event on form
form.addEventListener('input', composeColor);
// Callback function pass Event Object
function composeColor(e) {
//if the node interacting with user is type=range...
if (e.target.type === "range") {
// Reference active range
var rng = e.target;
// Get range's "little brother" output
var viewVal = rng.nextElementSibling;
// Sync their values
viewVal.value = rng.value;
// Collect the values of all ranges then interpolate them
// into a template literal.
// The TL is the color of body
document.body.style.background = `rgb(${red0.value}, ${grn0.value}, ${blu0.value})`;
} else return false;
}
</script>
</body>
</html>
Demo 2
On Event Attribute
form {
display: flex;
flex-flow: column wrap;
height: 100vh;
}
.slidecontainer {
width: 40%;
height: 15vh
}
output {
transform: translate(5px, -7px);
display: inline-block;
}
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<form id='rgb' oninput="document.body.style.background = `rgb(${red0.value},${grn0.value}, ${blu0.value})`">
<fieldset class="slidecontainer">
<legend>Red</legend>
<input type="range" min="0" max="255" value="255" class="slider" id="red0" oninput='redO.value = this.value'>
<output id="redO" for='red0'></output>
</fieldset>
<fieldset class="slidecontainer">
<legend>Green</legend>
<input type="range" min="0" max="255" value="255" class="slider" id="grn0" oninput='grnO.value = this.value'>
<output id="grnO" for='grn0'></output>
</fieldset>
<fieldset class="slidecontainer">
<legend>Blue</legend>
<input type="range" min="0" max="255" value="255" class="slider" id="blu0" oninput='bluO.value = this.value'>
<output id="bluO" for='blu0'></output>
</fieldset>
</form>
<script>
</script>
</body>
</html>

show checked checkbox values on textarea javascript

I am trying to get all the checkbox checked values on the input field provided. I am using javascript to get the values but it only shows one checked value. When I check another checkbox it displays the second one only.
Here is what i did so far:
<html>
<head>
<script type="text/javascript">
function checkbox(val){
document.getElementById("show").value = val;
}
</script>
</head>
<body>
<form>
<input type="checkbox" id="bk" name="vehicle" onClick="checkbox(this.value);" value="Bike">I have a bike<br></br>
<input type="checkbox" id="cr" name="vehicle" onClick="checkbox(this.value);" value="Car">I have a car<br></br>
<input type="text" id="show" name="vehicle"><br>
<input type="submit" value="Showe">
</form>
</body>
</html>
As I said, this one only shows a single checked value, but I want to show all the checked values on the input field specified!
Thanks!
Your code is only sending the currently clicked item to the method. You need to look at all the checkboxes in that method and find the checked ones, put them in an array, then insert the array value into your input. Also worth noting, when you do it this way and build out the array on each click, it also makes it appear as though items are being removed from the input when you uncheck them.
function checkbox(){
var checkboxes = document.getElementsByName('vehicle');
var checkboxesChecked = [];
// loop over them all
for (var i=0; i<checkboxes.length; i++) {
// And stick the checked ones onto an array...
if (checkboxes[i].checked) {
checkboxesChecked.push(checkboxes[i].value);
}
}
document.getElementById("show").value = checkboxesChecked;
}
<form>
<input type="checkbox" id="bk" name="vehicle" onClick="checkbox();" value="Bike">I have a bike<br></br>
<input type="checkbox" id="cr" name="vehicle" onClick="checkbox();" value="Car">I have a car<br></br>
<input type="text" id="show" name="vehicle"><br>
<input type="submit" value="Showe">
</form>
var txt = document.getElementById( 'droptxt' ),
content = document.getElementById( 'content' ),
list = document.querySelectorAll( '.content input[type="checkbox"]' ),
quantity = document.querySelectorAll( '.quantity' );
txt.addEventListener( 'click', function() {
content.classList.toggle( 'show' )
} )
window.onclick = function( e ) {
if ( !e.target.matches( '.list' ) ) {
if ( content.classList.contains( 'show' ) ) content.classList.remove( 'show' )
}
}
list.forEach( function( item, index ) {
item.addEventListener( 'click', function() {
calc()
} )
} )
function calc() {
for ( var i = 0, arr = []; i < list.length; i++ ) {
let spanArray = [];
document.querySelectorAll('span').forEach(element => {
spanArray.push(element.innerHTML);
});
if ( list[ i ].checked ) arr.push( list[ i ].value + " "+ spanArray)
}
txt.value = arr.join(', ')
}
h1 {
color: #0000ff;
}
#droptxt {
padding: 8px;
width: 300px;
cursor: pointer;
box-sizing: border-box
}
.dropdown {
position: relative;
display: inline-block
}
.content {
display: none;
position: absolute;
background-color: #f1f1f1;
min-width: 200px;
overflow: auto;
box-shadow: 0 8px 16px 0 rgba(0, 0, 0, .2);
z-index: 1
}
.content div {
padding: 10px 15px
}
.content div:hover {
background-color: #ddd
}
.show {
display: block
}
<h1>KIAAT</h1>
<b>Adding/Removing Checkbox Values into TextArea</b>
<br><br>
<input type="text" id="droptxt" class="list" placeholder="Select the values" readonly>
<div id="content" class="content">
<div id="market" class="list">
<label><input type="checkbox" id="market" class="list" value="Bike" /> I have a bike</label>
</div>
<div class="list">
<label><input type="checkbox" id="banana" class="list" value="Car" /> I have a car</label>
</div>
</div>

Categories

Resources