I'm creating several divs in Javascript by inserting something like this
'<div style="background-color:' + bgColor + '</div>'
Now I want to set the color of the text automatically based on the luminosity of the background to black or white.
I see 2 options - all driven from Javascript or in CSS only. I prefer the CSS option, however, don't know how to read the background color for a CSS function, e.g.
#function set-color($color) {
#if (lightness($color) > 40) {
#return #000;
}
#else {
#return #FFF;
}
}
How can I fetch the background color to do something like this
div { color: set-color(???); }
How about mix-blend-mode ?
There are several ideas put forward in the question about how to choose between black and white for text color depending on the background color.
Most have been answered one way or another in comments. Taking the ideas one by one:
Can we use CSS mix-blend-mode - no. There is no one setting for this that ensures text will appear readable on all possible backgrounds.
Can we use CSS (the preferred method) - unfortunately no as the div requiring the text color to depend on background color is created by JS at run time.
Can we use JS - yes and as the div is being created by JS and having its background-color set then it might as well have its color set then too.
The JS string is as given in the question with the addition of a setting for color:
'<div style="background-color:' + bgColor + '; color: ' + textBlackOrWhite(bgColor) + ';"'
Here is a snippet which defines the function. The snippet also lets you choose a background color and it then sets a color which (roughly) depends on the 'brightness' of the background. See the SO questions referenced here for further discussion as human color perception is a difficult topic.
//from https://stackoverflow.com/questions/5623838/rgb-to-hex-and-hex-to-rgb
function textBlackOrWhite(hex) {
// Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF")
var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
hex = hex.replace(shorthandRegex, function(m, r, g, b) {
return r + r + g + g + b + b;
});
let result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);//also checks we have a well-formed hex number
//from https://stackoverflow.com/questions/596216 the answer by #FranciPenov which gives an approximation: (R+R+G+G+G+B)/6
let itsbright = function () { return ((2*parseInt(result[1], 16) + 3*parseInt(result[2], 16) + parseInt(result[3], 16))/6)>127; }
return result ? (itsbright()) ? '#000000' : '#ffffff' : '#000000';//falls back onto black if bgColor was not a well-formed 3 or 6 digit hex color
}
<div id="div" style="font-family: monospace; box-sizing: border-box; margin: 0; padding: 40px 0; width: 100px; height: 100px; border-style: solid; border-radius: 50%; background-color: black; color: white;text-align:center;">#ffffff</div>
Click to choose background color: <input id="input" placeholder='#00000' type='color' value='#000000'/>
<button onclick="let d = document.getElementById('div'); let i = document.getElementById('input'); d.innerHTML = i.value; d.style.backgroundColor = i.value; d.style.color = textBlackOrWhite(i.value);">Submit</button>
I want to set the color of the text automatically based on the
luminosity of the background to black or white.
I recognise this is a different approach from what you're asking for, but one CSS-only approach to having universally-readable text, regardless of background-color is to have white text with a black outline (or vice versa).
You can use 4 text-shadows for the outline:
text-shadow: 1px 1px rgb(0, 0, 0), -1px 1px rgb(0, 0, 0), -1px -1px rgb(0, 0, 0), 1px -1px rgb(0, 0, 0);
Working Example
const divs = [...document.getElementsByTagName('div')];
for (div of divs) {
let redValue = Math.floor(Math.random() * 255);
let greenValue = Math.floor(Math.random() * 255);
let blueValue = Math.floor(Math.random() * 255);
div.style.backgroundColor = `rgb(${redValue}, ${greenValue}, ${blueValue})`;
}
div {
float: left;
width: 180px;
height: 40px;
margin: 0 6px 6px 0;
line-height: 40px;
color: rgb(255, 255, 255);
font-size: 32px;
text-align: center;
text-shadow: 1px 1px rgb(0, 0, 0), -1px 1px rgb(0, 0, 0), -1px -1px rgb(0, 0, 0), 1px -1px rgb(0, 0, 0);
background-color: yellow;
}
<div>Sample Text</div>
<div>Sample Text</div>
<div>Sample Text</div>
<div>Sample Text</div>
<div>Sample Text</div>
<div>Sample Text</div>
<div>Sample Text</div>
<div>Sample Text</div>
<div>Sample Text</div>
<div>Sample Text</div>
<div>Sample Text</div>
<div>Sample Text</div>
Related
<html>
<head>
<title>Random manga</title>
<script src="./js/my.js"></script>
<link type="text/css" rel="stylesheet" href="./css/style.css">
</head>
<body>
<div id="al">
<div id="pic">
<img src="" id="img" style="visibility: hidden;">
</div>
<button id="btng" onclick="my()">Suggest me manga</button>
</div>
</body>
</html>
Here is the html for button div and other things
Below is the css
body
{
background : white;
color : black;
}
#pic
{
border-radius : 25px;
background-color : #f2f2f2;
-webkit-border-radius : 35px;
-moz-border-radius : 75px;
box-shadow: rgba(0, 0, 0, 0.25) 0px 54px 55px, rgba(0, 0, 0, 0.12) 0px -12px 30px, rgba(0, 0, 0, 0.12) 0px 4px 6px, rgba(0, 0, 0, 0.17) 0px 12px 13px, rgba(0, 0, 0, 0.09) 0px -3px 5px;
background-size : cover;
text-align : center;
height: 400px;
width: 400px;
background-size : cover;
background-repeat: no-repeat;
background-position: center;
}
#btng
{
backface-visibility: hidden;
background-color: #405cf5;
border-radius: 6px;
border-width: 0;
box-shadow: rgba(50, 50, 93, .1) 0 0 0 1px inset,rgba(50, 50, 93, .1) 0 2px 5px 0,rgba(0, 0, 0, .07) 0 1px 1px 0;
color: #fff;
font-size: 100%;
height: 44px;
line-height: 1.15;
margin: 12px 0 0;
outline: none;
overflow: hidden;
padding: 0 25px;
position: relative;
text-align: center;
text-transform: none;
transform: translateZ(0);
transition: all .2s,box-shadow .08s ease-in;
width: 50%;
}
#btng:focus {
box-shadow: rgba(50, 50, 93, .1) 0 0 0 1px inset, rgba(50, 50, 93, .2) 0 6px 15px 0, rgba(0, 0, 0, .1) 0 2px 2px 0, rgba(50, 151, 211, .3) 0 0 0 4px;
}
#al
{
text-align : center;
position : absolute;
top : 50%;
left : 50%;
transform : translate(-50%, -50%);
}
#img{
height: 100%;
width: 100%;
}
And below the function for onclick on button
function my(){
var bt=document.getElementById("btng");
bt.textContent = "Suggest me another";
var my = new Array("im/R.jpg","im/S.jpg","im/E.jpg");
var randomNum = Math.floor(Math.random() * my.length);
var backgroundImage = my[randomNum];
document.getElementById("img").src = my[randomNum];
document.getElementById("pic").style.backgroundImage=`url(${backgroundImage})`;
}
The onclick event only runs after the button is clicked twice or thrice sometimes I tried doing something to slove it but I was unsuccessful, is there any way to do it? Here is the live preview:- https://mangasuggestions.000webhostapp.com/index.html
Please click on buttons 4/5 times to get the problem I am facing.
The onclick event and the function is working properly. The image didn't update is because the randomNum is the same as the previous one.
Our goal is to prevent using the same number that is generated previously.
One way to do this is to keep track of the last generated random number, and regenerate until it is different from the previous one.
Main logic
let randomNum;
do {
randomNum = Math.floor(Math.random() * images.length);
} while (randomNum === prevRandomNum);
prevRandomNum = randomNum
Full code (With some modification of your original code)
// Keep track of the last random number
let prevRandomNum = -1
function my(){
const btn = document.getElementById("btng");
btn.innerText = "Suggest me another";
const images = ["im/R.jpg","im/S.jpg","im/E.jpg"];
let randomNum;
do {
randomNum = Math.floor(Math.random() * images.length);
} while (randomNum === prevRandomNum);
prevRandomNum = randomNum
const backgroundImage = images[randomNum];
document.getElementById("pic").style.backgroundImage=`url(${backgroundImage})`;
}
Please make the button type="button". it seems working.
<button id="btng" type="button" onclick="my()">Suggest me another</button>
As #AndrewLi already answered, there is possibilty that generated random number is the same as the last one.
Instead of generating new number multiple times (with while loop).
You can filter out currently displayed image from array.
function my(){
var bt=document.getElementById("btng");
bt.textContent = "Suggest me another";
var img = document.getElementById("img");
var my = new Array("/im/R.jpg","/im/S.jpg","/im/E.jpg").filter((src) => src !== new URL(img.src).pathname);
var randomNum = Math.floor(Math.random() * my.length);
var backgroundImage = my[randomNum];
document.getElementById("img").src = my[randomNum];
document.getElementById("pic").style.backgroundImage=`url(${backgroundImage})`;
}
But to make it work, you need provide absolute path to your images in array.
So /im/R.jpg instead of im/R.jpg
Here is the probably most efficient way to do this without filtering the values causing a loop or re-generating values in case we get a duplicate using some index manipulation.
Explanation
For the first image we can select any image within the set of valid indices for the array i.e. 0 to array.length - 1 which we can do using Math.floor(Math.random() * array.length). Then we store the selected index in a variable currentImageIdx.
For any following image we generate a step value which determines the amount of steps we want to move on from the current index to the next value. We need to choose this in the range of 1 to array.length - 1 which we can do by using Math.floor(1 + Math.random() * (arrayLength - 1)) as this will make sure we will never move on so far that we are back at the same index as we currently are. We then just need to add that step value to the current index and take the remainder using modulo to make sure we're not getting out of bounds.
Examples for moving on to next index
For the following examples an array with 3 values is assumed:
We're currently at index 0 so we should either move on 1 or 2 steps. If we were to move on 3 steps we would be at 0 again because (start index + step) % array.length would translate to (0 + 3) % 3 = 0 and we'd be at the start index again.
If we're at index 1 we could again move on 1 or 2 steps but not 3 because (start index + step) % array.length would translate to (1 + 3) % 3 = 1 and we'd be at the start index again.
The same applies for index 2
This will work for an array of any size. Except that for the case of just having one element in the array that one element will of course be selected every time.
let currentImageIdx = undefined;
function my() {
var bt = document.getElementById("btng");
bt.textContent = "Suggest me another";
var my = new Array("https://dummyimage.com/20x20/000/fff", "https://dummyimage.com/20x20/00FF00/000", "https://dummyimage.com/20x20/FF0000/000");
let backgroundImageIdx;
// it is imporant to check for undefined here as currentImageIdx != 0 would also trigger this case if it just was if(!currentImageIdx) and may produce the same picture twice
if (currentImageIdx !== undefined) backgroundImageIdx = getNextImage(currentImageIdx, my.length)
else backgroundImageIdx = Math.floor(Math.random() * my.length);
document.getElementById("img").src = my[backgroundImageIdx];
currentImageIdx = backgroundImageIdx;
console.log(`selected image ${currentImageIdx}`);
document.getElementById(
"pic"
).style.backgroundImage = `url(${my[backgroundImageIdx]})`;
}
function getNextImage(currentIndex, arrayLength) {
// generate random step value between 1 and array.length - 1
// with three elements: either 1 and 2
var step = Math.floor(1 + Math.random() * (arrayLength - 1));
// add the step value to current index and make sure we're not out of bounds
console.log(`(${currentIndex} + ${step}) % ${arrayLength} = ${(currentIndex + step) % arrayLength}`)
return (currentIndex + step) % arrayLength;
}
<div id="al">
<div id="pic">
<img src="" id="img" style="visibility: hidden;">
</div>
<button id="btng" onclick="my()">Suggest me manga</button>
</div>
I have been working on code to tag images. I was able to insert the tags and for each inserted tag a small box is created and tagname will be displayed inside. What I would like to do is, to have different color for each of the box created.
var html = "<div class='inputtag'><i class='fa fa-eye' aria-hidden='true'></i><i class='fa fa-trash-alt' aria-hidden='true'></i><span>" + input + "</span><input type='hidden' name='tag_name[]' value='" + input + "'></div>";
$('.tags').append(html);
var theColors = []
document.querySelectorAll(".inputtag").forEach((el, idx) =>
theColors.push("#" + ((1 << 24) * Math.random() | 0).toString(16)); el.style.borderColor = theColors[idx]
)
.inputtag>i {
margin - right: 4 px;
}
.inputtag {
border - radius: 4 px;
border: 1 px solid skyblue;
color: #000;
padding: 2px 8px;
width: max-content;
text-align: center;
cursor: pointer;
margin: 4px 4px;
float: left;
}
In the above Javascript code i tried to get different border color for the elements inside div, but the color keeps changing after each new entry. I have attached the images below to explain it better.
Image 1:
In this image 1 , u can see the elements with two different colors. These colors change when i add a new element. i.e., for each element added inside the Div, the border color for each element keep changing.
Image 2 :
The image 2 shows the change in the border color for the elements. What i would like to have is to have different fixed colors for each of the elements inside the Div, so they don't change color on adding a new element.
Can someone help me with this problem.
Try this:
var render = document.querySelector('#tags');
var btnAdd = document.querySelector('#btn-add');
var tags = [];
btnAdd.addEventListener('click', () => {
var nameTag = document.querySelector('#name-tag');
var color = ((1 << 24) * Math.random() | 0).toString(16);
render.innerHTML += `
<div class="tag" style="border-color: #${color};">
${nameTag.value}
</div>
`;
});
.tag {
border-radius: 4px;
border: 2px solid skyblue;
color: #000;
padding: 2px 8px;
margin: 4px 4px;
float: left;
}
<input type="text" id="name-tag" placeholder="name tag...">
<button id="btn-add">Add</button>
<hr>
<div id="tags">
</div>
You can store a color code for each of your tags and retrieve them whenever you need to show those tags. Because if you refresh the page, this will reset all the colors too.
Or, you can use an array of color codes so that you can always assign those colors sequentially to the tags.
Though I would have followed the first approach.
There are random number of div's as show below, I am trying to clone these div on click. when cloning I want to change the content to actual content + no of clones it has (based on content of span , not the id or classes of "clone-this")
eg.
If I click the first "chrome" div, since the body already have "chrome (1) and chrome (2)" , div with content "chrome (3)" Should appear .
If I click the 2nd div ie. "Mozilla Firefox", since there is no cloned version, a div with content "Mozilla Firefox (1)" should appear.
and so on.
I tried to make this, but when i clone the count is based on class , not the content . so clicking on "chrome" div will clone "chrome (5)" not "chrome (3)" .
Also in my implementation when i click the "chrome (1)" div, it will clone as "chrome (1)(5)" . I want this to be like "chrome (3)"
how can i achieve this?
note that there will be any number of divs at first. 5 is just for and example.
jsfiddle here
$(document).on('click', '.clone-this', function(){
var CloneContainer = $(this).clone();
var no = $('.clone-this').size();
CloneContainer.html(CloneContainer.html() + " (" + no + ")");
CloneContainer.appendTo('body');
});
.clone-this{
padding: 15px;
width: 100px;
text-align: center;
border: 1px solid #ccc;
margin: 10px auto;
cursor: pointer;
color: #444;
border: 1px solid #ccc;
border-radius: 3px;
font-family: monospace;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="clone-this"><span>Chrome</span></div>
<div class="clone-this"><span>Mozilla Firefox</span></div>
<div class="clone-this"><span>Safari</span></div>
<div class="clone-this"><span>Chrome (1)</span></div>
<div class="clone-this"><span>Chrome (2)</span></div>
To accomplish that, you should check "content" of each item and count the number of elements which have same text. But, there is one problem here; each element (for example Chrome, Chrome (1), Chrome (2)) has different content. So, you may split the text using parenthesis or you may use RegEx (recommended).
$(document).on('click', '.clone-this', function(){
var CloneContainer = $(this).clone();
var content = CloneContainer.find('span').html().split(' (')[0];
var no = $(".clone-this:contains('"+content+"')").size();
CloneContainer.html( CloneContainer.html() .split(' (')[0] + " (" + no + ")" );
CloneContainer.appendTo('body');
});
.clone-this{
padding: 15px;
width: 100px;
text-align: center;
border: 1px solid #ccc;
margin: 10px auto;
cursor: pointer;
color: #444;
border: 1px solid #ccc;
border-radius: 3px;
font-family: monospace;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="clone-this"><span>Chrome</span></div>
<div class="clone-this"><span>Mozilla Firefox</span></div>
<div class="clone-this"><span>Safari</span></div>
<div class="clone-this"><span>Chrome (1)</span></div>
<div class="clone-this"><span>Chrome (2)</span></div>
On the snippet above, you may see basic version of it. But you MUST consider the "similar content" issue like following.
Chrome
Chrome Mobile
Firefox
Firefox Mobile
Here is another way to get you going. I "trim" the clicked div to its base name and then loop through the divs and get the length of all which contain the same base name.
After that I modify the cloned element to fill in the right count of the cloned element appropriately:
var regExp = /\([0-9]+\)/;
$('.clone-this').click(function(e){
var target = e.target.textContent;
var matches = regExp.exec(target);
var elements = $('.clone-this');
var count = elements.length;
var index = 0;
if (null != matches) {
target = matches.input.substr(0, matches.input.lastIndexOf(" "));
}
for(var i = 0; i < count; i++){
index += (elements[i].textContent.indexOf(target) > -1) ? 1: 0;
}
var CloneContainer = $(this).clone();
CloneContainer.html(CloneContainer.html().split('(')[0] + "(" + index + ")" );
CloneContainer.appendTo('body');
});
.clone-this{
padding: 15px;
width: 100px;
text-align: center;
border: 1px solid #ccc;
margin: 10px auto;
cursor: pointer;
color: #444;
border: 1px solid #ccc;
border-radius: 3px;
font-family: monospace;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="clone-this"><span>Chrome</span></div>
<div class="clone-this"><span>Mozilla Firefox</span></div>
<div class="clone-this"><span>Safari</span></div>
<div class="clone-this"><span>Chrome (1)</span></div>
<div class="clone-this"><span>Chrome (2)</span></div>
I am trying to change the background colour of a div based on it's current colour, via the click of a button.
For example, if the colour is cyan (#00ffff - it should change to yellow ('ffff00).
If the colour is yellow - it should change to magenta (#ff00ff).
If the colour is magenta - it should revert back to cyan.
I have managed to change the color to yellow from cyan, however I am not sure exactly how to write my if statement (assuming an if statement is the best way?) to change the colours based on the current colour.
function ColorFunction() {
if (light.getItem("backgroundColor") == '#00ffff') {
document.getElementById("light").style.backgroundColor = "#ffff00";
}
else
if (light.getItem("backgroundColor") == '#ffff00') {
document.getElementById("light").style.backgroundColor = "#ff00ff";
}
else
if (light.getItem("backgroundColor") == '#ff00ff') {
document.getElementById("light").style.backgroundColor = "00ffff";
}
}
.main {
width:250px;
color: #202020;
background-color: #d0d0d0;
}
.light {
width: 50px;
height: 50px;
background-color: #00ffff
}
#burn {
width: 150px;
font-style: italic;
}
#button {
font-style: bold;
width: 150px;
}
<h1>Disco Inferno</h1>
<div class="light" id="light">
div
</div>
<button onClick="ColorFunction()">Burn!</button>
Ok, lets start at the beginning here.
You have an element with the id light but that does not automatically become a variable you can use in javascript. Its easy enough to make it one:
var light = document.getElementById("light");
Then, i'm not even sure where you get getItem from - perhaps it was a guess - but its not a valid method on an HTMLElement
You could do this with light.style.backgroundColor - see the snippet below.
var colors = ["rgb(0, 255, 255)","rgb(255, 255, 0)","rgb(255, 0, 255)"];
function ColorFunction() {
var light = document.getElementById("light");
var curr = light.style.backgroundColor;
var next = colors.indexOf(curr)+1;
light.style.backgroundColor = colors[next%colors.length];
}
<h1>Disco Inferno</h1>
<div class="light" id="light" style="background-color:#00FFFF">
Burn, baby burn!
</div>
<button onClick="ColorFunction()">Burn!</button>
You could use an object for shifting the colors, after assigning directly a color to the div.
function ColorFunction() {
var colors = {
'rgb(0, 255, 255)': 'rgb(255, 255, 0)',
'rgb(255, 255, 0)': 'rgb(255, 0, 255)',
'rgb(255, 0, 255)': 'rgb(0, 255, 255)'
},
element = document.getElementById("light");
element.style.backgroundColor = colors[element.style.backgroundColor];
}
.main { width:250px; color: #202020; background-color: #d0d0d0; }
.light { width: 50px; height: 50px; background-color: #00ffff; }
#burn { width: 150px; font-style: italic; }
#button { font-style: bold; width: 150px; }
<div class="light" id="light" style="background-color: #00ffff;"></div>
<button onClick="ColorFunction()">Burn!</button>
There is no getItem() that is some made up method. Look at the console and you will see that it is an error. To read background color you should be using style.
var color = elementReference.style.backgroundColor
Now you are relying on a bad feature of JavaScript where you define a variable that matches an id of an element and it is magically a reference to that element.You should not do that. You should define the variable yourself.
var elementReference = document.getElementById("light");
Now the kicker, browsers returning different things when you read color values. SOme hex, some rgb. So checking for color is a bad thing to do. What to do? Use CSS classes.
function ColorFunction(){
var elem = document.getElementById("light");
if(elem.classList.contains("red")) {
elem.classList.remove("red");
elem.classList.add("blue");
} else if(elem.classList.contains("blue")) {
elem.classList.remove("blue");
elem.classList.add("green");
} else {
elem.classList.remove("green");
elem.classList.add("red");
}
}
.red { background-color: red;}
.blue {background-color: blue;}
.green {background-color: green;}
<h1>Disco Inferno</h1>
<div class="light red" id="light">
div
</div>
<button onClick="ColorFunction()">Burn!</button>
Now there are other ways to do the if check with add/remove, but that is the basic idea.
I've been messing about with an inventory-like system for a website I'm working on.
I don't usually use JavaScript, So this little problem has been driving me crazy.
I'm trying to add two floats together using two different functions.
One is addition, One is subtraction.
This is the code:
function addItem(item){
$("#item-" + item.toString()).insertAfter("#selected h1");
$("#item-" + item.toString() + " a").attr("onclick","remItem(" + item.toString() + ")");
updateTotal(item, 0);
}
function remItem(item){
$("#item-" + item.toString()).insertAfter("#my h1");
$("#item-" + item.toString() + " a").attr("onclick","addItem(" + item.toString() + ")");
updateTotal(item, 1);
}
function updateTotal(item, action){
if(action=0){
var value = $("#item-" + item.toString() + " a .value").text().replace("$ ", "");
var oldVal = $(".total").text().replace("$ ", "");
var newVal = parseFloat(value) + parseFloat(oldVal);
$(".total").text(newVal);
} else {
var value = $("#item-" + item.toString() + " a .value").text().replace("$ ", "");
var oldVal = $(".total").text().replace("$ ", "");
var newVal = parseFloat(value) - parseFloat(oldVal);
$(".total").text(newVal);
}
}
.wrapper{
text-align: center;
}
.item-holder{
width: 45%;
text-align: left;
padding: 5px;
overflow: auto;
display: inline-block;
background-color: #222;
min-height: 160px;
}
.item-holder h1{
color: white;
margin: 0;
padding: 0;
text-align: center;
}
.smallimg{
margin: 2px 2%;
width: 96%;
}
.item {
margin: 2px 2px 2px 2px !important;
cursor: pointer;
color: #333;
background: rgba(200,200,200,0.9);
text-align: center;
min-width: 60px;
max-width: 100px;
width: 18%;
border: solid medium gray;
display: inline-block;
}
.value{
font-size: 10pt;
font-weight: bold;
padding-top: 5px;
}
.rarity{
font-style: italic;
font-weight: bold;
}
.total{
font-weight: bold;
}
.Consumer{
border-color: rgb(176, 195, 217);
}
.Mil-Spec{
border-color: rgb(75, 105, 255);
}
.Industrial{
border-color: rgb(94, 152, 217);
}
.Restricted{
border-color: rgb(136, 71, 255);
}
.Classified{
border-color: rgb(211, 44, 230);
}
.Covert{
border-color: rgb(235, 75, 75);
}
#selected{
color: white !important;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrapper">
<span class="total">$ 0.00</span><br /><br />
<!-- START ITEM HOLDER-->
<div id="my" class="item-holder">
<h1>Your Items</h1>
<div class="item Industrial" id="item-22">
<a onClick="addItem(22);">
<div class="value">$ 0.05</div>
<img class="smallimg" src="http://cdn.steamcommunity.com/economy/image/7xs5DOPUQVgttOnINvLH41dX872npE8Y-Xo60tIUj0QmEA73usgHSo1t9TYQkpttT1Co-q67Txz_cT3A0wKYTilSGv2rzABDnRzxPBPYiHxLRuPi6u4BBfNwDMCbUs4XGA4Ox7nMBUq2J_ktDuKNfElG9JLx4gcd6DBlgc5SmRYmGE6o_s4QSYgi9G4Z2Jl8CEbm-Ky8VUKqJ2qCzFLOQyUZUOijyg==/99fx66f" title="SG 553 | Waves Perforated (Field-Tested)">
<div class="rarity">Field-Tested</div>
</a>
</div>
<div class="item Restricted" id="item-21">
<a onClick="addItem(21);">
<div class="value">$ 11.40</div>
<img class="smallimg" src="http://cdn.steamcommunity.com/economy/image/7xs5DOPUQVgttOnINvLH41dX872npE8Y-Xo60tIUj0QmEA73usgHSo1t9TYQkpttT1Co-q67Txz_cT3A0wKYTilSGv2rzABDnRzxPBPYiHxLRuPi6u4BBfNwDMCbUs4XGA4Ox7nMBUq2J_ktDuKNfElG9JLx4gcd6DBlgc5SmRYmGE6o_s4QSYgi9G4Z2Jl8CEbm-Ky8VUKqJ2qCzFLOQyUZUOijyg==/99fx66f" title="SG 553 | Waves Perforated (Field-Tested)">
<div class="rarity">Field-Tested</div>
</a>
</div>
<div class="item Covert" id="item-20">
<a onClick="addItem(20);">
<div class="value">$ 7.65</div>
<img class="smallimg" src="http://cdn.steamcommunity.com/economy/image/7xs5DOPUQVgttOnINvLH41dX872npE8Y-Xo60tIUj0QmEA73usgHSo1t9TYQkpttT1Co-q67Txz_cT3A0wKYTilSGv2rzABDnRzxPBPYiHxLRuPi6u4BBfNwDMCbUs4XGA4Ox7nMBUq2J_ktDuKNfElG9JLx4gcd6DBlgc5SmRYmGE6o_s4QSYgi9G4Z2Jl8CEbm-Ky8VUKqJ2qCzFLOQyUZUOijyg==/99fx66f" title="SG 553 | Waves Perforated (Field-Tested)">
<div class="rarity">Field-Tested</div>
</a>
</div>
</div>
<!-- END ITEM HOLDER -->
<div id="selected" class="item-holder">
<h1>Selected Items</h1>
</div>
</div>
The first item works fine, You add the item, It updates the total.
Add a second item, It subtracts the new item value from the old one.
Remove the first item and it adds the value to the total.
It's a little messed up, it randomly adds and subtracts.
I'm really not sure why it's causing this, so I came here.
Any ideas what I'm doing what?
Thanks in advance!
CodePen
Inu, in addition to fixing the if(action = 0) bug, you might also like to consider the following :
attach click handlers in javascript, not as HTML attributes.
things will simplify with more carefully chosen jQuery selectors and method chaining.
by delegating click handling to static wrappers (#selected and #my), you can avoid the need to dynamically swap out 'addItem' and 'remItem'. The click action of each item will be automatically determined by the current wrapper.
in the click handlers, this refers to the clicked a element, therefore no need to rediscover it with a jQuery selector, and .closest() will avoid the need to find items by id.
to maintain a reliable total, you should really recalculate from scratch by looping through all items, rather than applying deltas.
by putting values in spans with the '$' outisde, you can get the values directly, without stripping out the symbol.
Put everything together and you should end up with something like this :
HTML
....
<div class="value">$ <span>11.40</span></div>
....
Javascript
$('#my').on('click', '.item a', function(e) {
e.preventDefault();
$(this).closest('.item').insertAfter("#selected h1");
calcTotal();
});
$('#selected').on('click', '.item a', function(e) {
e.preventDefault();
$(this).closest('.item').insertAfter("#my h1");
calcTotal();
});
function calcTotal(item, sign) {
var total = 0;
$("#selected .value span").each(function() {
total += Number($(this).text());
});
$(".total").text(total);
}
untested
You are using the assignment operator = here: if(action=0){ when you should be using the comparisson operator == as if(action==0){