I'm trying to do something which I thought was quite extremely simple, but not having much luck. I have two long lists of scores to compare, each pair sits in its own div. I'm on the lookout for a function which I could specify the div IDs, and have the different reflected in the third div. If the figure is positive, apply one class, and if negative, apply another.
<style>
.positive {
color: green;
}
.negative {
color: red;
}
</style>
<div id = "score">50</div>
<div id = "benchmark">30</div>
<div id = "diff"></div>
and in my javascript:
$(window).ready(function() {
$('#diff').html(diff);
});
var diff = calc("score", "benchmark");
function calc(divID1, divID2) {
div1 = document.getElementById(divID1);
metric = div1.innerHTML;
div2 = document.getElementById(divID2);
benchmark = div2.innerHTML;
c = Math.abs(a) - Math.abs(b);
// this is the difference here
return String(c);
};
I have D3 and JQuery loaded up. The numbers within the columns of divs are dynamically generated through other functions, so I can't hard code the styling.
You have some errors in your code. You can call calc function when the document is ready and handle the result there. I sum it up to this:
$(document).ready(function() {
//get the result of your calc function
var diff = calc("score", "benchmark");
//display the result and add class depend of the returning value
$('#diff').html(diff).attr("class", diff > 0 ? "positive" : "negative");
});
function calc(divID1, divID2) {
//get first number
var div1Num = parseInt($("#" + divID1).text(), 10);
//get second number
var div2Num = parseInt($("#" + divID2).text(), 10);
//make the calculation
var result = div1Num - div2Num;
//return the result
return result;
};
.positive {
color: green;
}
.negative {
color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="score">50</div>
<div id="benchmark">30</div>
<div id="diff"></div>
Another example with negative result:
$(document).ready(function() {
//get the result of your calc function
var diff = calc("score", "benchmark");
//display the result and add class depend of the returning value
$('#diff').html(diff).attr("class", diff > 0 ? "positive" : "negative");
});
function calc(divID1, divID2) {
//get first number
var div1Num = parseInt($("#" + divID1).text(), 10);
//get second number
var div2Num = parseInt($("#" + divID2).text(), 10);
//make the calculation
var result = div1Num - div2Num;
//return the result
return result;
};
.positive {
color: green;
}
.negative {
color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="score">10</div>
<div id="benchmark">30</div>
<div id="diff"></div>
Edit: You can replace parseInt with parseFloat according to your needs.
References
.attr()
You cannot calc() the diff between values of 2 elements when the DOM is not ready yet.
(Your current ready handler isn't performing the actual calculation but only appending the already miscalculated value to some element).
Try this instead:
$(document).ready(function() {
var diff = Math.abs($("#score").text()) - Math.abs($("#benchmark").text());
$('#diff').html(diff).addClass(diff > 0 ? 'positive' : 'negative');
});
Also, I changed your $(window).ready() to $(document).ready() instead.
You can use following statement in js to get expected output.
score = jQuery('#score').text();
benchmark = jQuery('#benchmark').text();
if(Math.abs(score) > Math.abs(benchmark))
{
jQuery('#diff').text('Positive');
jQuery('#diff').addClass('positive');
}
else
{
jQuery('#diff').text('Negative');
jQuery('#diff').addClass('negative');
}
You can check example on this link- http://jsfiddle.net/o3k6u99p/1/
Related
JavaScript question:
Say, I have an array of links (images):
var images = [["https://samplelink.com/2014/01.jpg"], ["https://samplelink.com/2014/02.jpg"],
["https://samplelink.com/2014/03.jpg"]]
and I want to randomly select a new background-image from the links in the array when I click a button:
function random() {number = Math.floor(Math.random()*3);
return number;}
function photoSelect() { return images[random()]; }
I tried to do it this way:
var urlStr = '"url()"';
var toArr = urlStr.split(""); //so that I could insert the url inside the "url(+here+)"
var toStr, clean;
$('.new').click(function() {
$('.background').css("background-image", function() {
toArr.splice(5,0,[photoSelect()]); // ig. [",u,r,l,(,"https://samplelink.com/2014/01.jpg",),"]
toStr= toArr.toString(); // ig. ",u,r,l,(,"https://samplelink.com/2014/01.jpg",),"
clean = change.replace(/[,]/g,""); // ig. "url("https://samplelink.com/2014/01.jpg")"
return clean;
});
});
I'm new, admittedly, and self-taught and I would appreciate any help or correction.
I imagine there are other, better ways to do this (but I thought i'd try anyway just to see) and I have checked related questions prior to posting but so far I haven't found anything that matches mine so I am wondering if it's even possible.
Your implementation is close, but as stated in the comments, you are slight overthinking this. You do not need any array of arrays to store the images, and there's no need to splice string together when the appended value is static. Additionally when randomly selecting numbers, its best to use the length of the imageList rather than a hard coded value, in case you change this later. Take a look at this shortened example
var imageList = ['http://lorempixel.com/400/200/?1', 'http://lorempixel.com/400/200/?2', 'http://lorempixel.com/400/200/?3'];
function randomPhotoSelect() {
var ranNumber = Math.floor(Math.random()*imageList.length);
return imageList[ranNumber];
}
$('.newBtn').click(function(){
$('.randomImg').css("background-image", "url('" + randomPhotoSelect() + "')");
});
.randomImg{
height:200px;
width:400px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="randomImg"></div>
<button class="newBtn">New Image</button>
First:
var images = [
["https://samplelink.com/2014/01.jpg"],
["https://samplelink.com/2014/02.jpg"],
["https://samplelink.com/2014/03.jpg"]
];
is an array, made up of arrays, which is not needed for your data. You'd want:
var images = [
"https://samplelink.com/2014/01.jpg",
"https://samplelink.com/2014/02.jpg",
"https://samplelink.com/2014/03.jpg"
];
which is an array of strings.
Next, your code to get the random number, pick an element from the array and use that to set the image can be combined into a simple function.
So, to get a random image and use it as a background on an element, all you'd need is:
var el = document.getElementById("theElement");
var btn = document.querySelector("button");
btn.addEventListener("click", photoSelect);
var images = [
"http://www.underconsideration.com/brandnew/archives/abc_2013_logo.png",
"http://logok.org/wp-content/uploads/2014/03/CBS-Eye-logo-880x660.png",
"https://www.famouslogos.net/images/nbc-logo.jpg"
];
function photoSelect() {
el.style.backgroundImage = "url(" + images[Math.floor(Math.random()*3)] + ")";
console.clear();
console.log(el.style.backgroundImage);
}
#theElement {
height:100px;
width:100px;
background:gray;
background-size:contain;
}
<button>Click for random image</button>
<div id="theElement"></div>
JS:
var images = [["https://samplelink.com/2014/01.jpg"], ["https://samplelink.com/2014/02.jpg"], ["https://samplelink.com/2014/03.jpg"]]
var photoSelect = function() {
var _imagesLength = images.length;
var selectedImage = parseInt(Math.random() * (_imagesLength - 0)) + 0;
return images[selectedImage];
}
$(document).ready(function() {
$('.background').css("background-image", "url("+photoSelect()+")");
$('.new').on("click",function() {
$('.background').css("background-image", "url("+photoSelect()+")");
});
})
Working fiddle: https://jsfiddle.net/L8xgyh75/1/
I'm using a function on my website to randomly addClass to a div.
works fine, but I can't find a way to not repeat the same class twice one after the other (cause sometimes the same class is added and we can think the code is not working)...
here is my jquery code :
$("#switch").click(function(){
var classes = ["vert", "escalier","reverse","demi_escalier","demi_escalier_2","ligne" ];
$("#logo").removeClass().addClass(classes[~~(Math.random()*classes.length)]);
});
can anybody help me with this ?
thanks
if you want classes not repeat you can use following:
var classes = ["vert", "escalier", "reverse", "demi_escalier", "demi_escalier_2", "ligne"];
var classesCopy = classes.slice();
$('#switch').click(function() {
if (!classesCopy.length) {
classesCopy = classes.slice();
} // once alls classes used up it starts from beginning
var classToAdd = classesCopy.splice(Math.floor(Math.random() * classesCopy.length), 1);
$('.current-class').text('current class: ' + classToAdd);
$('#logo').removeClass().addClass(classToAdd+'');
});
#logo {
width: 100px;
height: 100px;
background: green;
}
<div class='current-class'></div>
<div id='logo'></div>
<button id='switch'>switch</button>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
//put it in an IIFE so the variables are scoped down
(function(){
//constants, don't need to declare them in the click function over and over
var classes = ["vert", "escalier","reverse","demi_escalier"
,"demi_escalier_2","ligne" ];
//keep track of the last class used, -1 initial so no chance of mismatch
var lastNumber = -1;
var $logo = $("#logo");
$("#switch").on('click', function() {
//get a new index
var nextClass = Date.now() * 100 % classes.length;;
//while they match, keep getting a new one
while (nextClass === lastNumber) {
nextClass = Date.now() * 100 % classes.length;
}
$logo.removeClass().addClass(classes[nextClass]);
//save it off so we can do the double check again on the next execution
lastNumber = nextClass;
});
})();
I am trying to make an object that will determine the highest height of a set of elements and make each element match the height of the largest.
In this object, I am trying to pass a selector to a JQuery method which resides inside of my object method. Unfortunately I am not able to get each item this way and my Each statement does not fire but the object returns 0 items.
Below is an example of my object:
var heightBalance = {
containerName: '',
childElements: '',
alert: function() {
var divs = $(this.childElements);
console.log(divs);
$.each(divs, function(index, value) {
console.log('working');
});
}
}
heightBalance.containerName = '#containers';
heightBalance.childElements = 'div';
heightBalance.alert();
#one {
background-color: green;
width: 50px;
height: 200px;
}
div {
width: 50px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="containers">
<div id="one">d</div>
<div id="two"></div>
<div id="three"></div>
<div id="four"></div>
<div id="five"></div>
</div>
You're script is initialized in the head, before the divs are rendered. Move the script to the end of the body, or use jQuery ready function (fiddle):
$(function () {
var heightBalance = {
containerName: '',
childElements: '',
alert: function () {
var divs = $(this.childElements);
console.log(divs);
$.each(divs, function (index, value) {
console.log('working');
});
}
}
heightBalance.containerName = '#containers';
heightBalance.childElements = 'div';
heightBalance.alert();
});
The code in this answer will give you the equal heights you want:
$(function() {
// Get an array of all element heights
var elementHeights = $('.features').map(function() {
return $(this).height();
}).get();
// Math.max takes a variable number of arguments
// `apply` is equivalent to passing each height as an argument
var maxHeight = Math.max.apply(null, elementHeights);
// Set each height to the max height
$('.features').height(maxHeight);
});
As the poster above states, your code is initializing in the head before your elements have loaded. If you looked at the object in the console, you can see that the object was referencing the root of your entire document. For future reference, in fiddle, under "Frameworks and Extensions" switching the second dropdown from "nowrap - in head" to "onload" can achieve the same result as the previous answer.
You're defining 2 variables. I assume the intention is to define a context - heightBalance.containerName
and then search that context for the highest child and modify all children to match that height. heightBalance.childElements.
Your function doesn't make use of heightBalance.containerName. so $(this.childElements) just looks for any div on the page. in the console, you can see that the container is being listed along with the child elements.
You probably want to change it to something more like var divs = $('#containers').find('div') or shortform $('div', '#containers')
alert: function(){
var divs = $('#containers').find('div')
console.log(divs);
$.each(divs, function(index, value){
console.log('working');
});
}
I modified my code a little and got this to work. Thank you for everyone showing me when I need to initialize JQuery to get this functioning.
var heightBalance = {
containerName: '',
childElements: '',
heightArray: [],
calc: function(){
var divs = $(this.containerName + " " + this.childElements);
$.each(divs, function(index, value){
var innHeight = $(value).height(); ;
heightBalance.heightArray.push(innHeight);
});
this.largestHeight(this.heightArray);
},
largestHeight: function(data)
{
var i = data.indexOf(Math.max.apply(Math, data));
$(heightBalance.childElements).height(this.heightArray[i] );
}
}
I'm trying to simulate a game through JS and HTML. My problem is that when I try and make it add the values it won't process it and change the value.
http://jsfiddle.net/rwybp41e/1/
I am trying to add all the Points and place them in the div with a class TotalPoints.
I have also tried using:
var div = document.getElementsByClassName('TotalPoints');
div.innerHTML = sum;
Thanks in advance
You can use each to loop over all the .Points and set the value inside .TotalPoints using text.
var total = 0;
$('.Points').each(function() {
total += parseInt($(this).text(), 10);
});
$('.TotalPoints').text(total);
Demo: https://jsfiddle.net/tusharj/rwybp41e/2/
Your targetting the wrong ID's and classes in your fiddle and you didn't include the jQuery library.
HTML:
<div id="TotalPoints"></div>
<div class="total-points">0</div>
CSS:
.total-points {
padding: 8px;
//background: blue;
width: 20px;
float:right;
margin-top: 4px;
}
Javascript:
// Add all "Points" class together
var sum = 0;
$('.Points').each(function () {
sum += parseFloat($(this).text());
});
$('.total-points').text(sum);
Here is a working demo:
http://jsfiddle.net/rwybp41e/3/
Since the data you're interested in is a reduction of a collection of points to a single total, you can calculate the total more functionally using Array.reduce:
$('.TotalPoints').text($('.Points')
.toArray()
.reduce(function (agg, point) {
return agg + parseInt($(point).text(), 10);
}, 0));
Working example: https://jsfiddle.net/rwybp41e/4/
I am dynamically loading some of the content within my page and would like to get a total of all the data-attributes.
First the elements are cloned and appended
$('.chip').on('click', function () {
$(this).clone().appendTo('.chipPlacement');
});
Then I have written a function that should get the totals
function chipsBet() {
var redchip = $('.chipPlacement .chipValue.r').data() || 0;
var bluechip = $('.chipPlacement .chipValue.b').data() || 0;
var orangechip = $('.chipPlacement .chipValue.o').data() || 0;
var total = redchip.chipValue + bluechip.chipValue + orangechip.chipValue;
return total;
}
Before I append the elements the HTML looks like
<div class="chipPlacement"></div>
and once appended the HTML structure is
<div class="chipPlacement">
<div class="chip red">
<div class="chipValue r" data-chip-value="1">1</div>
</div>
</div>
I need to listen for the DOM structure the change and then fire the chipsBet() function, but I'm not sure how to get this to work. I can't use .on('change') as that only applies to input, textarea and select.
I have tried firing the chipsBet function within the .chip.on('click') but I get NaN returned.
How can I get the data-attribute-values for the new elements in the DOM?
If you don't have a blue or orange chip, you're effectively trying to get .chipValue from 0 which is undefined and adding it to another number gives you NaN.
You can simply iterate over all .chipValue elements within the placement element like so:
function chipsBet()
{
var total = 0;
$('.chipPlacement .chipValue').each(function() {
total += $(this).data('chipValue');
});
return total;
}
Nevermind, you altered your initial question.. carrying on.
<div class='chipPlacement'>
<div class='chip red'>
<div class='chipValue' data-chip-value='1'></div>
</div>
</div>
Then to read your data attributes, you could do something like this.
$('.chip').on('click', function () {
$(this).clone().appendTo('.chipPlacement');
chipsBet();
});
function chipsBet() {
var redchipVal = parseInt($('.chipValue .r').data('chip-value')) || 0;
var bluechipVal = parseInt($('.chipValue .b').data('chip-value')) || 0;
var orangechipVal = parseInt($('.chipValue .o').data('chip-value')) || 0;
var total = redchipVal + bluechipVal + orangechipVal;
return total;
}
I think you want something like bellow. It will call the function every time any change will in div .chipPlacement.
$('.chipPlacement').bind("DOMSubtreeModified",function(){
console.log('Div modified');
});
You can say for your problem
$('.chipPlacement').bind("DOMSubtreeModified",function(){
chipsBet();
});
DEMO