Can't add together two variables which store an offsetHeight - javascript

I'm trying to add two numbers together so I can use a CSS calc function to reduce the top margin of an element so it shows just the title and its top line text.
var roomInfoPanel = document.querySelector(".room-info");
var panelCapacityInfo = parseInt(document.querySelector(".room-info__capacity").offsetHeight);
var panelTitleRoom = parseInt(document.querySelector(".room-info__title").offsetHeight);
var panelCombinedHeights = panelCapacityInfo + panelTitleRoom;
if (panelTitleRoom && panelCapacityInfo) {
document.querySelector(".room-info").style.marginTop = "calc( -" + panelCombinedHeights + "-7vw + -20px)";
}
However, panelCombinedHeights always returns undefined :(
I don't think this is a scope issue.
The parseInt was added after looking at this article, but without this no good either.
What am I doing wrong?

Try to convert variables to numbers
var roomInfoPanel = document.querySelector(".room-info");
var panelCapacityInfo = parseInt(document.querySelector(".room-info__capacity").offsetHeight);
var panelTitleRoom = parseInt(document.querySelector(".room-info__title").offsetHeight);
// Convert variables to numbers
// Print what to summ
console.log(panelCapacityInfo, panelTitleRoom)
var panelCombinedHeights = Number(panelCapacityInfo) + Number(panelTitleRoom);
// Print summ
console.log(panelCombinedHeights)
if (panelTitleRoom && panelCapacityInfo) {
console.log("Style to be applied:", "calc( -" + panelCombinedHeights + "-7vw + -20px)");
document.querySelector(".room-info").style.marginTop = "calc( -" + panelCombinedHeights + "-7vw + -20px)";
}
.room-info {
height: 200px;
}
.room-info__capacity {
height: 100px;
}
.room-info__title {
height: 70px;
}
<div class="room-info">
<div class="room-info__capacity">
1
</div>
<div class="room-info__title">
2
</div>
</div>

The function offsetHeigth already returns a number, so you don't need the parseInt() here.
Are the values panelCapacityInfo and panelTitleRoom defined or not?
If they are undefined then the error is probably in the querySelector.

var roomInfoPanel = document.querySelector(".room-info");
var panelCapacityInfo = parseInt(document.querySelector(".room-info__capacity").offsetHeight);
var panelTitleRoom = parseInt(document.querySelector(".room-info__title").offsetHeight);
var panelCombinedHeights = parseInt(panelCapacityInfo) + parseInt(panelCapacityInfo)
if (panelTitleRoom && panelCapacityInfo) {
document.querySelector(".room-info").style.marginTop = "calc( -" + panelCombinedHeights + "-7vw + -20px)";
}

Related

javascript get natural width/height of all images in table

I am trying to get the actual image sizes from the images listed in column Image and display it in column Image Size.
The problem I have is that I am only able to get the size of the first image, which is added in each cell for column Image Size.
jsFiddle: https://jsfiddle.net/a92ck0em/
var xmlFile = 'https://raw.githubusercontent.com/joenbergen/files/master/XMLParse2.xml';
function loadDoc() {
var xhttp = new XMLHttpRequest();
xhttp.open("GET", xmlFile, true);
xhttp.send();
xhttp.onreadystatechange = function() {
if (this.readyState === 4 && this.status === 200) {
xmlFunction(this.response);
}
};
}
function xmlFunction(xml) {
var parser = new DOMParser();
var xmlDoc = parser.parseFromString(xml, "text/xml");
var table = "<tr><th>Category</th><th>Title</th><th>Image</th><th>Image Size</th></tr>";
var x = xmlDoc.getElementsByTagName("ITEM");
for (var elem of x) {
var titles = elem.getElementsByTagName(
"TITLE")[0].childNodes[0].nodeValue;
var cats = elem.getElementsByTagName("CATEGORY")[0].childNodes[0].nodeValue;
var imageURL = elem.getElementsByTagName("IMAGE").length === 0 ? "..." : elem.getElementsByTagName("IMAGE")[0].getAttribute('url');
var imageSize = elem.getElementsByTagName("IMAGE").length === 0 ? "..." : elem.getElementsByTagName("IMAGE")[0].width + 'x' + [0].height;
table += "<tr><td>" + cats + "</td><td>" + titles + "</td><td>" + "<img src=" + imageURL + ' height="150" width="100">' + '</td><td id="cellId"><textTag>' + "" + "</textTag></td></tr>";
}
document.getElementById("myTable").innerHTML = table;
document.querySelector("img").addEventListener('load', function() {
var imgTags = document.querySelectorAll('img'), i;
for (i = 0; i < imgTags.length; ++i) {
var image_width = document.querySelector("img").naturalWidth;
var image_height = document.querySelector("img").naturalHeight;
}
$('#myTable textTag').each(function() {
$(this).append(image_width + 'x' + image_height);
//console.log(image_width + 'x' + image_height);
});
});
}
table,
th,
td {
border: 1px solid black;
border-collapse: collapse;
}
th,
td {
padding: 5px;
}
<head>
<script src="https://code.jquery.com/jquery-1.10.2.js"></script>
</head>
<button type="button" onclick="loadDoc()">Load</button>
<br><br>
<table id="myTable"></table>
Expected:
Ok there are many parts to your question, I started doing the simplest thing, logging that parsed xml document, looks like this:
...
<IMAGE url="...."></IMAGE>
<IMAGESIZE></IMAGESIZE>
...
So in your script you are getting an attribute that does not exist. So you can safely remove this line:
var imageSize = elem.getElementsByTagName("IMAGE").length === 0 ? "..." : elem.getElementsByTagName("IMAGE")[0].width + 'x' + [0].height;
Next you need to check if the images are loaded, simplest thing to do:
"<img src=" + imageURL + ' height="150" width="100" onload="this._loaded = true;">' +
this will add a proprietary _loaded property to it.
Next you need to check when the images are loaded and once loaded fire a function, you need a recursive function to do that which does not blow the stack:
var imgTags = document.getElementsByTagName('img');
function isLoaded(){
if(Array.prototype.slice.call(imgTags).some(function(d,i){return !d._loaded})){
setTimeout(isLoaded,4);
} else {
$('#myTable textTag').each(function(i,node) {
node.textContent = imgTags[i].naturalWidth + 'x' + imgTags[i].naturalHeight;
//console.log(image_width + 'x' + image_height);
});
}
};
isLoaded();
I removed the querySelectorAll(img) bit, it is slower compared to getElementsByTagName and does not return a LIVE HTML Collection, returns a NodeList. The loaded function will fire your Jquery thing once it detects all the _loaded properties. The Array.prototype.slice.call is an old school way to convert HTML Collection or NodeList to a regular array, the cool kids you Array.from nowadays, it is up to you. You might also optimize the above function a bit by storing the result of Array.prototype.slice.call... once, I leave that to you. All in all it looks like this:
https://jsfiddle.net/ibowankenobi/h9evc81a/
The problem is that you need to wait for the images to load before querying properties like width or height.
Normally this is done by setting an onload event handler that updates the display of these properties.
Moreover you're making a loop setting two variables and then, outside of the loop, you're assigning all the images the value of the very same variables.
You need to do the querying inside the second loop instead.

Removing commas from arrays in HTML [element.innerHTML]

So I'm having an issue with this. I'm trying to get rid of those commas. Used varArray.join(" ") too, but with no success. I went as far as creating a for loop, but it didn't work(well it might've worked, but I'm a beginner, though I doubt that).
Here's the code:
let varArray = [];
let rufus1 = document.getElementById('rufus1');
let rufus2 = document.getElementById('rufus2'); // variables for easing syntax
function arrayGiver() {
varArray.push('<div>' + document.getElementById('rufus1').value + '</div>');
// I've used `<div>` instead of `<br>` for line breaking the elements, but when I'll be making bigger more complex projects I should probably use `<br>` shouldn't I?
rufus2.innerHTML = ("You have just added to your collection:" + "<br/>" +
varArray);
//this cleans the input after executing the function
rufus1.value = '';
}
//this makes the function execute on an enter key press
document.addEventListener('keydown', function(enterKey) {
if (enterKey.keyCode === 13) {
arrayGiver();
}
})
<input id="rufus1">
<br>
<br>
<button onclick="arrayGiver();">Bleh</button>
<p id="rufus2"></p>
Because array auto add commas as separator when converted to string. You can get rid of this by simply use join(' ') on varArray as below
let varArray = [];
let rufus1 = document.getElementById('rufus1');
let rufus2 = document.getElementById('rufus2');
// variables for easing syntax
function arrayGiver() {
varArray.push('<div>' + document.getElementById('rufus1').value + '</div>') // I've used `<div>` instead of `<br>` for line breaking the elements, but when I'll be making bigger more complex projects I should probably use `<br>` shouldn't I?
rufus2.innerHTML = ("You have just added to your collection:" + "<br/>" +
varArray.join(' '));
//this cleans the input after executing the function
rufus1.value = '';
}
//this makes the function execute on an enter key press
document.addEventListener('keydown', function (enterKey) {
if (enterKey.keyCode === 13) {
arrayGiver();
}
})
<input id="rufus1" type="text">
<br>
<br>
<button onclick="arrayGiver();">Bleh</button>
<p id="rufus2"></p>
You can use forEach() or another loop to add the array elements to innerHTML
For this answer I used:
varArray.forEach(e => rufus2.innerHTML += e);
which iterates over the array adding each element (e) to rufus2.innerHTML.
let varArray = [];
let rufus1 = document.getElementById('rufus1');
let rufus2 = document.getElementById('rufus2'); // variables for easing syntax
function arrayGiver() {
varArray.push('<div>' + document.getElementById('rufus1').value + '</div>');
// I've used `<div>` instead of `<br>` for line breaking the elements, but when I'll be making bigger more complex projects I should probably use `<br>` shouldn't I?
rufus2.innerHTML = ("You have just added to your collection:" + "<br/>");
varArray.forEach(e => rufus2.innerHTML += e);
//this cleans the input after executing the function
rufus1.value = '';
}
//this makes the function execute on an enter key press
document.addEventListener('keydown', function(enterKey) {
if (enterKey.keyCode === 13) {
arrayGiver();
}
})
<input id="rufus1">
<br>
<br>
<button onclick="arrayGiver();">Bleh</button>
<p id="rufus2"></p>
To achieve expected result, use string variable instead of array as below
let varArray = [];
var list ='';
let rufus1 = document.getElementById('rufus1');
let rufus2 = document.getElementById('rufus2');
// variables for easing syntax
function arrayGiver(){
list = list + '<div>' + document.getElementById('rufus1').value + '</div>'
rufus2.innerHTML = ("You have just added to your collection:" + "<br/>" + list);
list.value = '';
}
https://codepen.io/nagasai/pen/bvQKbX
let varArray = [];
var list ='';
let rufus1 = document.getElementById('rufus1');
let rufus2 = document.getElementById('rufus2');
// variables for easing syntax
function arrayGiver(){
list = list + '<div>' + document.getElementById('rufus1').value + '</div>'
rufus2.innerHTML = ("You have just added to your collection:" + "<br/>" + list);
list.value = '';
}
document.addEventListener('keydown', function(enterKey) {
if(enterKey.keyCode === 13){
arrayGiver();
}
})
body {
font-family: Arial;
font-size: 24px;
}
button {
width: 100px;
height: 25px;
}
<input id="rufus1">
<br>
<br>
<button onclick="arrayGiver();">Bleh</button>
<p id="rufus2"></p>

Javascript - changing widths of images

I'm creating a tug of war website as a small project. My problem is that my javascript doesn't seem to want to work.
<script>
function randomTeam(){
var TeamV = Math.floor((Math.random() *2 ) + 1)
document.getElementById("TeamHeader").innerHTML = "Team: " + TeamV;
return TeamV;
}
function changeWidth(TeamV){
var MetreLeftV = document.getElementById('MetreLeft');
var MetreRightV = document.getElementById('MetreRight');
if(TeamV == 1){
MetreLeftV.style.width += '10px';
MetreRightV.style.width -= '10px';
}
else if(TeamV == 2){
MetreRightV.style.width += '10px';
MetreLeftV.style.width -= '10px';
}
}
</script>
Basically, when the page is loaded the randomTeam function is called, and when the button is pressed, it increments the size of your teams side, and decrements the side of the enemy's team. The problem is, it doesn't work at all. Could anyone help me see where this is going wrong? Thank you in advance :')
You can not just add 10px to the width. Convert the width to a number, add 10, than add px to it.
MetreLeftV.style.width = (parseFloat(MetreLeftV.style.width) + 10) + "px"
Do the same for the others and you will need a check for negative numbers.
function randomTeam() {
var TeamV = Math.floor((Math.random() * 2) + 1)
document.getElementById("TeamHeader").innerHTML = "Team: " + TeamV;
return TeamV;
}
function changeWidth(TeamV) {
var MetreLeftV = document.getElementById('MetreLeft');
var MetreRightV = document.getElementById('MetreRight');
console.log(parseFloat(MetreLeftV.style.width) + 10 + 'px')
if (TeamV == 1) {
MetreLeftV.style.width = parseFloat(MetreLeftV.style.width) + 10 + 'px';
MetreRightV.style.width = parseFloat(MetreRightV.style.width) - 10 + 'px';
} else if (TeamV == 2) {
MetreLeftV.style.width = parseFloat(MetreLeftV.style.width) - 10 + 'px';
MetreRightV.style.width = parseFloat(MetreRightV.style.width) + 10 + 'px'
}
}
window.setInterval( function () {
var move = randomTeam();
changeWidth(move);
}, 1000);
#MetreLeft {
background-color: red
}
#MetreRight {
background-color: yellow
}
<div id="TeamHeader"></div>
<div id="MetreLeft" style="width:200px">Left</div>
<div id="MetreRight" style="width:200px">Right</div>

Highcharts Bar Chart not printing correctly

I have a bar chart using Highcharts. On the screen it looks like this:
But when I go to print it looks like this:
So basically nothing is showing up when I go to print. Here is the javascript I am using.
function qm_load_barcharts(qmsr_data) {
var bar_width = 200;
$('#profile-barchart tbody tr').each(function() {
$(this).children('td').eq(4).each(function() {
// Get the div id.
var $div_id = $(this).children('div').eq(0).attr('id');
// From the div id reconstitute the pfx in proper form.
var pfx = $div_id.replace(/^x/, '');
pfx = pfx.replace(/_/g, '.');
pfx = pfx.replace(/-/, '/');
// Look up our indicator values for the prefix.
var active_cnt = qmsr_data[pfx]['active'];
var latent_cnt = qmsr_data[pfx]['latent'];
var indicators_cnt = qmsr_data[pfx]['indicators'];
// Set our bar segment sizes.
var total = active_cnt + latent_cnt + indicators_cnt;
var active_size;
var latent_size;
var indicators_size;
if (active_cnt == 0) {
active_size = 0;
}
else {
active_size = Math.round((active_cnt/total) * bar_width);
}
if (latent_cnt == 0) {
latent_size = 0;
}
else {
latent_size = Math.round((latent_cnt/total) * bar_width);
}
if (indicators_cnt == 0) {
indicators_size = 0;
}
else {
indicators_size = Math.round((indicators_cnt/total) * bar_width);
}
if ((active_cnt + latent_cnt + indicators_cnt) == 0) {
// Perfect score, so make one full-width gray bar.
$('#' + $div_id).children('div.active-bar').eq(0).css("background-color", "#ababab");
$('#' + $div_id).children('div').eq(0).width(bar_width + 'px');
$('#' + $div_id).children('div').eq(1).width('0px');
$('#' + $div_id).children('div').eq(2).width('0px');
}
else {
// Set div sizes proportionately.
$('#' + $div_id).children('div').eq(0).width(active_size + 'px');
$('#' + $div_id).children('div').eq(1).width(latent_size + 'px');
$('#' + $div_id).children('div').eq(2).width(indicators_size + 'px');
// Set values inside dives.
$('#' + $div_id).children('div.active-bar').children('div').eq(0).html(active_cnt);
$('#' + $div_id).children('div.latent-bar').children('div').eq(0).html(latent_cnt);
$('#' + $div_id).children('div.indicators-bar').children('div').eq(0).html(indicators_cnt);
}
});
});
}
Here's the HTML:
<div id="<%= $pfx_id %>" class='qmsr-barchart'>
<div class='active-bar'>
<div class='hidden-nugget'></div>
</div>
<div class='latent-bar'>
<div class='hidden-nugget'></div>
</div>
<div class='indicators-bar'>
<div class='hidden-nugget'></div>
</div>
</div>
And here's the print view CSS:
#media print {
.active-bar {
background-color: #A74A44;
}
.latent-bar {
background-color: #EB8104;
}
.indicators-bar {
background-color: #E6E714;
}
}
I am trying to print it in Chrome, if that matters at all.

Generating a random color not working

I was working on a simple project, to have the background of a webpage change every time you click on it. I succeeded in such, tested it a few times, save, tested again, and then left.
I go home and load it.. And it no longer works. I am using the same browser, I have no idea how anything could have changed.. I must have messed up a few ways almost impossible it feels like.. But alas, I'm sitting here dumb-founded..
Could anyone take a look at my simple program and tell me what is wrong? (Again, the program purpose is to change the webpage's background color to a random color whenever you click on the page.)
Here is the code:
<!DOCTYPE HTML PUBLIC>
<html>
<head>
<title>Random Colors</title>
<script language="javascript">
function randomColor() {
var h0 = Math.floor(Math.random()*99);
var h1 = Math.floor(Math.random()*99);
var h2 = Math.floor(Math.random()*99);
var h3 = Math.floor(Math.random()*99);
var h4 = Math.floor(Math.random()*99);
var h5 = Math.floor(Math.random()*99);
return '#'.toString(16)+h0.toString(16)+h1.toString(16)+h2.toString(16);+h3.toString(16)+h4.toString(16)+h5.toString(16);
}
</script>
</head>
<body onclick="document.bgColor=randomColor();">
</body>
</html>
Thanks in advance if anyone can help.
Having '#'.toString(16) makes no sense, the string '#' can't be converted to a string in hexadecimal form...
You have an extra semicolon after h2.toString(16).
return '#'+h0.toString(16)+h1.toString(16)+h2.toString(16)+h3.toString(16)+h4.toString(16)+h5.toString(16);
I think that you want to keep each digit in the range 0-15 instead of 0-98:
var h0 = Math.floor(Math.random()*16);
Try this out. Built off of what #Guffa did
function randomColor() {
var h0 = Math.floor(Math.random()*16);
var h1 = Math.floor(Math.random()*16);
var h2 = Math.floor(Math.random()*16);
var h3 = Math.floor(Math.random()*16);
var h4 = Math.floor(Math.random()*16);
var h5 = Math.floor(Math.random()*16);
return '#' + h0.toString(16) + h1.toString(16) + h2.toString(16) + h3.toString(16) + h4.toString(16) + h5.toString(16);
}
Here's the fiddle --> http://jsfiddle.net/Jh5ms/1/
Is there a reason you're using Math.random so many times?
function pad6(s) {
s = '' + s;
return '000000'.slice(s.length) + s;
}
function randomColor() {
var rand = Math.floor(Math.random() * 0x1000000);
return '#' + pad6(rand.toString(16)).toUpperCase();
}
randomColor(); // "#7EE83D"
randomColor(); // "#19E771"
As pointed out by Guffa, your first error was attempting to convert '#' to a hexadecimal representation.
This should do the trick:
function randomColor() {
var ret = Math.floor(Math.random() * (0xFFFFFF + 1)).toString(16);
return ('#' + new Array((6 - ret.length) + 1).join('0') + ret);
}
window.onload = function() {
document.querySelector('button').onclick = function() {
document.querySelector('body').style.backgroundColor = randomColor();
};
};
Here is a demonstration.
Here is another demonstration showing how you could implement it into your current page. I also took the liberty of changing your event handler to be unobtrusive.
Adding to Guffa fixing the Math.random()*99 problem, I would put all this in a loop like this:
var theColor = "#";
for (var i = 0; i < 6; i++) {
theColor += Math.floor(Math.random() * 16).toString(16);
}
return theColor;
Here's a jsFiddle
another answer in your format - pass this to whatever you want to change backgroundcolor
http://jsfiddle.net/FpLKW/2/
<div onclick="test(this);">
</div>
function test (ele) {
var h0 = Math.floor(Math.random()*10);
var h1 = Math.floor(Math.random()*10);
var h2 = Math.floor(Math.random()*10);
var h3 = Math.floor(Math.random()*10);
var h4 = Math.floor(Math.random()*10);
var h5 = Math.floor(Math.random()*10);
var x = '#' + h0.toString(16) + h1.toString(16) + h2.toString(16) + h3.toString(16) + h4.toString(16) + h5.toString(16);
ele.style.backgroundColor=x;
}

Categories