Complex Jquery Selector With Variables - javascript

I am building a demo of a lotto site where a user is presented with one section full of the balls and a second section that will fill up with his/her selections.
What I am trying to do is create a jQuery function that will run when a user clicks on a ball, this function must retrieve the number of the ball that was clicked as well as the color of the ball (background-image) and then set the number and the background-image to the next available ball.
Here is a jsFiddle: http://jsfiddle.net/8kq5p6gb/1/
This is my jQuery function, it stores the number and background of the clicked ball and then tries to find the next available ball open and applies that text and background to it but it currently does not work. When I click on a ball I get this error :
Uncaught Error: Syntax error, unrecognized expression: [object Object] a:nth-child(1)
For Code :
$(document).ready(function () {
var line_counter = 1;
var number_counter = 1;
$('.draw-selection-wrapper.choice .draw-number').click(function (e) {
event.preventDefault(e);
var number = $(this).text(); ;
var background = $(this).css('background-image');
var row = $('.draw-selection-wrapper.selections div:nth-child(' + line_counter + ')');
var link = $(row + ' a:nth-child(' + number_counter + ')');
link.text(number);
link.css('background-image', background);
number_counter = number_counter + 1;
if (number_counter == 8) {
line_counter = line_counter + 1;
number_counter = 1;
}
});
});
Here is my HTML:
<div class="draw-numbers-outer-wrapper">
<div class="draw-selection-wrapper choice">
<div class="draw-number-row one">
1
2
3
4
5
6
7
</div>
<div class="draw-number-row two">
8
9
10
11
12
13
14
</div>
</div>
<div class="draw-selection-wrapper selections">
<div class="draw-number-row">
</div>
<div class="draw-number-row">
</div>
</div>
</div>
And my CSS:
.draw-selection-wrapper {
width: 50%;
float: left;
}
.draw-number-row {
height: 36px;
border: 1px solid #C6C4C5;
padding-left: 10px;
}
.line-number {
float: left;
height: 100%;
width: 12px;
}
.draw-number {
width: 9%;
float: left;
height: 100%;
line-height: 36px;
margin: 0px 2.5% 0px 2.5%;
color: #000;
text-align: center;
background-color: green;
}
.draw-selection-wrapper.selections .draw-number {
margin: 0px 2% 0px 2%;
}
.draw-number-row.one .draw-number {
background-color: red;
}
.draw-number-row.two .draw-number {
background-color: teal;
}

row is a jQuery object, not a string, and as such you end up with [Object, object] when you try to concantenate the object into a string.
You could use the context selector instead
var row = $('.draw-selection-wrapper.selections div:nth-child(' + line_counter + ')');
var link = $('a:nth-child(' + number_counter + ')', row);
FIDDLE

var link = row.find('a:nth-child(' + number_counter + ')');

Fiddle
replace this
var row = $('.draw-selection-wrapper.selections div:nth-child(' + line_counter + ')');
var link = $(row + ' a:nth-child(' + number_counter + ')');
by
var row = '.draw-selection-wrapper.selections div:nth-child(' + line_counter + ')';
var link = $(row + ' a:nth-child(' + number_counter + ')');

Related

What am I doing wrong in scoping my function?

In this test case, I am using append.child with plain JavaScript to add 3 kinds of divs (blue, red, green) to a parent multiple times according to their corresponding button onclicks, then I am adding another child inside the added div with another button (innerButton).
My issue is that, the onclick function which is assigned to the innerbutton and is nested within the initial function, listens only to the very first appended div, and it adds the input (which is supposed to be added to the div I'm clicking on) to the last append element of its 'kind'.
I am doing something wrong with my scoping but I can't see it.
I just started studying JavaScript, so I am not familiar yet with libraries, jQuery etc.
var countBlue = 0;
var countRed = 0;
var countGreen = 0;
function addBlue() {
var addTo = document.getElementById('div1')
var blue = document.createElement("div");
blue.id = "blueDiv";
blue.innerHTML = "<input id=blueInput><button id=innerButtonBlue onclick=addInputs()>ADD INPUTS</button>";
addTo.appendChild(blue);
document.getElementById("innerButtonBlue").onclick = function() {
var newInput = document.createElement("div");
newInput.innerHTML = '<input id="newInput" placeholder="NEW">';
blue.appendChild(newInput);
}
countBlue++;
}
function addRed() {
var addTo = document.getElementById('div1')
var red = document.createElement("div");
red.id = "redDiv";
red.innerHTML = "<input id=redInput><button id=innerButtonRed>ADD INPUTS</button>";
addTo.appendChild(red);
document.getElementById("innerButtonRed").onclick = function() {
var newInput = document.createElement("div");
newInput.innerHTML = '<input id="newInput" placeholder="NEW">';
red.appendChild(newInput);
}
countRed++;
}
function addGreen() {
var addTo = document.getElementById('div1')
var green = document.createElement("div");
green.id = "greenDiv";
green.innerHTML = "<input id=greenInput><button id=innerButtonGreen>ADD INPUTS</button>";
addTo.appendChild(green)
document.getElementById("innerButtonGreen").onclick = function() {
var newInput = document.createElement("div");
newInput.innerHTML = '<input id="newInput" placeholder="NEW">';
green.appendChild(newInput);
}
countGreen++;
}
function displayCounters() {
alert("Blue divs amount : " + parseInt(countBlue) + "\n" + " Red divs amount : " + parseInt(countRed) + "\n" + " Green divs amount : " + parseInt(countGreen) + "\n" + "\n" + " All together is : " + (parseInt(countBlue) + parseInt(countRed) + parseInt(countGreen)))
}
button {
margin-bottom: 10px;
}
#blueDiv {
margin-top: 10px;
margin-bottom: 10px;
width: 300px;
}
#redDiv {
margin-top: 10px;
margin-bottom: 10px;
width: 300px;
}
#greenDiv {
margin-top: 10px;
margin-bottom: 10px;
width: 300px;
}
input {
text-align: center;
}
#innerButtonRed {
position: relative;
float: right;
}
#innerButtonBlue {
position: relative;
float: right;
}
#innerButtonGreen {
position: relative;
float: right;
}
#newInput {
margin-top: 2px;
width: 162px;
height: 23px;
}
#redInput {
background: red;
}
#blueInput {
background: blue;
}
#greenInput {
background: green;
}
<html>
<body>
<script src="test.js"></script>
<link rel="stylesheet" type="text/css" href="test.css">
<button onclick="addBlue()">BLUE</button>
<button onclick="addRed()">RED</button>
<button onclick="addGreen()">GREEN</button>
<button onclick="displayCounters()">COUNTERS</button>
<div id="div1"></div>
</body>
</html>
The first thing you need to know is that, although you can technically add the same id to multiple elements, it is bad practice to do so. The id of an element should be unique. If you need to apply the same style or target multiple elements with your code you should use class instead of id.
I think that's what is causing issues in your code.
Second, since you say you are learning, i think it would be good if you tried to make a single function to add the elements since the code is repeated in all of the three functions, except for the color.
Try making the function accept the color as a variable so you can reuse it for the three colors. Imagine if it was a hundred colors.
var countBlue = 0;
var countRed = 0;
var countGreen = 0;
function addBlue() {
var addTo = document.getElementById('div1')
var div = document.createElement("div");
countBlue++; //set the counter to one so ids don't start at zero
div.id = `blueDiv-${countBlue}`; //creates a unique id depending on the counter
div.classList = "blueDiv";
div.innerHTML = `<input id="blueInput-${countBlue}" class="blueInput"><button id="innerButtonBlue-${countBlue}" onclick="addInputs">ADD INPUTS</button>`;
addTo.appendChild(div);
document.getElementById(`innerButtonBlue-${countBlue}`).onclick = function() {
var newInput = document.createElement("div");
newInput.innerHTML = `<input id="newInput-blue-${countBlue}" class="newInput" placeholder="NEW">`;
div.appendChild(newInput);
}
}
function addRed() {
var addTo = document.getElementById('div1')
var div = document.createElement("div");
countRed++
div.id = `redDiv-${countRed}`;
div.classList = "redDiv";
div.innerHTML = `<input id="redInput-${countRed}" class="redInput"><button id="innerButtonRed-${countRed}" onclick="addInputs">ADD INPUTS</button>`;
addTo.appendChild(div);
document.getElementById(`innerButtonRed-${countRed}`).onclick = function() {
var newInput = document.createElement("div");
newInput.innerHTML = `<input id="newInput-red-${countRed}" class="newInput" placeholder="NEW">`;
div.appendChild(newInput);
}
}
function addGreen() {
var addTo = document.getElementById('div1')
var div = document.createElement("div");
countGreen++
div.id = `greenDiv-${countGreen}`;
div.classList = "greenDiv";
div.innerHTML = `<input id="greenInput-${countGreen}" class="greenInput"><button id="innerButtonGreen-${countGreen}" onclick="addInputs">ADD INPUTS</button>`;
addTo.appendChild(div);
document.getElementById(`innerButtonGreen-${countGreen}`).onclick = function() {
var newInput = document.createElement("div");
newInput.innerHTML = `<input id="newInput-green-${countGreen}" class="newInput" placeholder="NEW">`;
div.appendChild(newInput);
}
}
function displayCounters() {
alert("Blue divs amount : " + parseInt(countBlue) + "\n" + " Red divs amount : " + parseInt(countRed) + "\n" + " Green divs amount : " + parseInt(countGreen) + "\n" + "\n" + " All together is : " + (parseInt(countBlue) + parseInt(countRed) + parseInt(countGreen)))
}
button {
margin-bottom: 10px;
}
.blueDiv {
margin-top: 10px;
margin-bottom: 10px;
width: 300px;
}
.redDiv {
margin-top: 10px;
margin-bottom: 10px;
width: 300px;
}
.greenDiv {
margin-top: 10px;
margin-bottom: 10px;
width: 300px;
}
input {
text-align: center;
}
.innerButtonRed {
position: relative;
float: right;
}
.innerButtonBlue {
position: relative;
float: right;
}
.innerButtonGreen {
position: relative;
float: right;
}
.newInput {
margin-top: 2px;
width: 162px;
height: 23px;
}
.redInput {
background: red;
}
.blueInput {
background: blue;
}
.greenInput {
background: green;
}
<button onclick="addBlue()">BLUE</button>
<button onclick="addRed()">RED</button>
<button onclick="addGreen()">GREEN</button>
<button onclick="displayCounters()">COUNTERS</button>
<div id="div1"></div>
IDs need to be unique in the whole document. Don't use IDs for this, you can just use a class. But even with a class how is the code supposed to know which element it should look for since there will be more than one existing with the class? The solution is to search only inside the element that you just created (e.g. blue.querySelector('.someClass') to search for the first element with class someClass inside the blue element).
I changed your code to use classes everywhere:
var countBlue = 0;
var countRed = 0;
var countGreen = 0;
function addBlue() {
var addTo = document.getElementById('div1')
var blue = document.createElement("div");
blue.className = "blueDiv";
blue.innerHTML = "<input class='firstInput'><button class='innerButton'>ADD INPUTS</button>";
addTo.appendChild(blue);
blue.querySelector(".innerButton").onclick = function() {
var newInput = document.createElement("div");
newInput.innerHTML = '<input class="newInput" placeholder="NEW">';
blue.appendChild(newInput);
}
countBlue++;
}
function addRed() {
var addTo = document.getElementById('div1')
var red = document.createElement("div");
red.className = "redDiv";
red.innerHTML = "<input class='firstInput'><button class='innerButton'>ADD INPUTS</button>";
addTo.appendChild(red);
red.querySelector(".innerButton").onclick = function() {
var newInput = document.createElement("div");
newInput.innerHTML = '<input class="newInput" placeholder="NEW">';
red.appendChild(newInput);
}
countRed++;
}
function addGreen() {
var addTo = document.getElementById('div1')
var green = document.createElement("div");
green.className = "greenDiv";
green.innerHTML = "<input class='firstInput'><button class='innerButton'>ADD INPUTS</button>";
addTo.appendChild(green)
green.querySelector(".innerButton").onclick = function() {
var newInput = document.createElement("div");
newInput.innerHTML = '<input class="newInput" placeholder="NEW">';
green.appendChild(newInput);
}
countGreen++;
}
function displayCounters() {
alert("Blue divs amount : " + parseInt(countBlue) + "\n" + " Red divs amount : " + parseInt(countRed) + "\n" + " Green divs amount : " + parseInt(countGreen) + "\n" + "\n" + " All together is : " + (parseInt(countBlue) + parseInt(countRed) + parseInt(countGreen)))
}
button {
margin-bottom: 10px;
}
.blueDiv {
margin-top: 10px;
margin-bottom: 10px;
width: 300px;
}
.redDiv {
margin-top: 10px;
margin-bottom: 10px;
width: 300px;
}
.greenDiv {
margin-top: 10px;
margin-bottom: 10px;
width: 300px;
}
input {
text-align: center;
}
.redDiv .innerButton {
position: relative;
float: right;
}
.blueDiv .innerButton {
position: relative;
float: right;
}
.greenDiv .innerButton {
position: relative;
float: right;
}
.newInput {
margin-top: 2px;
width: 162px;
height: 23px;
}
.redDiv .firstInput {
background: red;
}
.blueDiv .firstInput {
background: blue;
}
.greenDiv .firstInput {
background: green;
}
body {
height: 800px; /* Just for visibility here in Stack Overflow */
}
<html>
<body>
<script src="test.js"></script>
<link rel="stylesheet" type="text/css" href="test.css">
<button onclick="addBlue()">BLUE</button>
<button onclick="addRed()">RED</button>
<button onclick="addGreen()">GREEN</button>
<button onclick="displayCounters()">COUNTERS</button>
<div id="div1"></div>
</body>
</html>
There is a lot more that could be improved of course - the code duplication could be removed, a generalized function for all three types (red/green/blue) can be created that is differentiated just by an attribute on the button for example - but that's beyond the scope of this answer.

Assistance with a table to add values in rows and delete them with a button. Using JQuery

I would like to create a table that will prompt you to add your name and occupation and add them in a row in the table. The values are supposed to go into an array. The delete button will delete them from the array and remove the row. There is supposed to be a counter as well.
At the moment I tried to do it only for the array peopleArray[]. I encounter the issue that the remove button will not work outside the function for "add" and executes many times, deleting everything in the array with just one click. I am misplacing something.
* {
font-family: verdana;
}
.table-container {
border-radius: 10px;
overflow: hidden;
display: inline-block;
}
.table {
border-collapse: collapse;
border-spacing: 0;
}
.table tr {
text-align: center;
}
.table tr:nth-child(2n) {
background-color: #eeeeee;
}
.table tr:nth-child(2n-1) {
background-color: #fcfafa;
}
.table th {
padding: 0 10px;
font-size: 12px;
width: 150px;
background-color: #A9BABA;
color: #000;
}
.table th:first-child,
.table th:nth-child(4) {
width: 15px;
}
.counter {
font-size: 12px;
font-weight: bold;
padding: 5px;
}
.btn_img {
width: 20px;
}
.button_style {
border: none;
background: none;
transition: all 0.5s;
padding: 5px;
}
.button_style:hover {
transform: scale(1.2);
}
.button_style:focus {
transform: rotateY(180deg);
outline: none;
}
table td {
padding: 0 10px;
border: 1px solid white;
font-size: 15px;
}
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.0/jquery.min.js"></script>
</head>
<body>
<div class="table-container">
<table class="table">
<tr>
<th class="">No.</th>
<th class="">Name</th>
<th class="">Occupation</th>
<th class="">
<button id="btn_add_people" class="button_style"><img class="btn_img" src="https://i.imgur.com/6FXVi7B.png" alt="options">
</button></th>
</tr>
<tr>
<td id="counter" class="counter" colspan="4"></td>
</tr>
</table>
</div>
<script>
$(document).ready(function() {
var peopleArray = [];
var occupArray = [];
var countP = 0;
$("#btn_add_people").click(function() {
var personName = prompt("Enter a name please!");
var personOccup = prompt("Enter an occupation please!");
peopleArray.push(personName);
occupArray.push(personOccup);
countP = peopleArray.length
var addedRow = '<tr id=""><td colspan="1" >' + peopleArray.length + '</td><td id="name' + peopleArray.length + '" colspan="1">' + peopleArray[peopleArray.length - 1] + '</td><td colspan="1">' + occupArray[occupArray.length - 1] + '</td><td colspan="1"><button id="' + peopleArray.length + '" class="button_style btn_remove_person"><img src="https://i.imgur.com/eiyNHjs.png" alt="close" class="btn_img" /></button></td></tr>';
$(".table").append(addedRow);
$("#counter").text("People added: " + countP);
$("tr").on('click', '.btn_remove_person', (function() {
$(this).parents("tr").remove()
var exitN = $(this).attr("id");
peopleArray.splice(exitN - 1, 1);
// get ID from button and connect with ID to splice name and occupation !!!
$("#counter").text("People added: " + countP);
}));
});
});
</script>
</body>
</html>
You could remove the $(document).ready(function() { }); as you are not really making great use of it. If you wanted to keep it to prevent users from entering information, then hide the add button first, then in the .ready display the button to indicate it is ready to use.
Keep the JQuery for adding entries but when creating the delete button add a onclick function to delete the entry.
I leave your counter calculations up to you as I do not know how you want to make the counters..people added being a total number to include deleted entries? People added being a count of entries in the table? Number next to entry being row number or could be 23 and 22 before it were deleted, etc...
var peopleArray = [];
var occupArray = [];
var countP = 0;
$("#btn_add_people").click(function() {
var personName = prompt("Enter a name please!");
var personOccup = prompt("Enter an occupation please!");
peopleArray.push(personName);
occupArray.push(personOccup);
countP = peopleArray.length
var addedRow = '<tr id=""><td colspan="1" >' + peopleArray.length + '</td><td id="name' + peopleArray.length + '" colspan="1">' + peopleArray[peopleArray.length - 1] + '</td><td colspan="1">' + occupArray[occupArray.length - 1] + '</td><td colspan="1"><button id="' + peopleArray.length + '" class="button_style btn_remove_person" onclick="_removeEntry(this)">Delete</button></td></tr>';
$(".table").append(addedRow);
$("#counter").text("People added: " + countP);
});
function _removeEntry(e) {
$(e).parents("tr").remove()
var exitN = $(e).attr("id");
peopleArray.splice(exitN - 1, 1);
$("#counter").text("People added: " + countP);
};

Creating variables in Javascript to manipulate the CSS box-shadow

I am creating a CSS editor using Javascript. I would like the User to be able to change the attributes of the CSS box-shadow. I imagine the function would look something like this:
var box = document.getElementById("boxDiv");
var h-offset; //= getUserInput (= document.getElementById("textareaID").value;)
var v-offset; //= getUserInput
var blur; //= getUserInput
var spread; //= getUserInput
var color; //= getUserInput
box.style.boxShadow =; //(h-offset,v-offset,blur,spread,color)
I am not sure how to format the String in a way the CSS box-shadow can understand it.
Thanks!
You can just concatenate the strings together. Keep in mind, that you need to validate the user input first. Otherwise, the box-shadow is not properly shown, if the user inserts a wrong value.
box.style.boxShadow = offsetX + ' ' + offsetY + ' ' + blurRadius + ' ' + spreadRadius + ' ' + color;
With ES6, you can also use template strings:
box.style.boxShadow = `${offsetX} ${offsetY} ${blurRadius} ${spreadRadius} ${color}`;
Here is a live example:
function apply() {
var box = document.getElementById('box');
var offsetX = document.getElementById('offsetX').value;
var offsetY = document.getElementById('offsetY').value;
var blurRadius = document.getElementById('blurRadius').value;
var spreadRadius = document.getElementById('spreadRadius').value;
var color = document.getElementById('color').value;
box.style.boxShadow = offsetX + ' ' + offsetY + ' ' + blurRadius + ' ' + spreadRadius + ' ' + color;
}
#box {
width: 100px;
height: 100px;
background: #f2f2f2;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
input {
display: block;
}
<div id="box"></div>
<input id="offsetX" placeholder="offsetX" />
<input id="offsetY" placeholder="offsetY" />
<input id="blurRadius" placeholder="blurRadius" />
<input id="spreadRadius" placeholder="spreadRadius" />
<input id="color" placeholder="color" />
<button onclick="apply()">Apply</button>
Thanks. I realized that I was not formatting the String correctly.
What I was coding:
box.style.boxShadow = String(h-offset + v-offset + blur + spread + color);
What I needed to code:
box.style.boxShadow = String(h-offset + " " + v-offset + " " + blur + " " + spread + " " + color);
Almost a 'Well Duh' moment XD
var first = "10px";
var second = "20px";
var third = "red";
$("#bshadow_jquery").css('box-shadow', first + " " + second + " " + third);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<html>
<head>
<style>
#bshadow_css {
border: 1px solid;
padding: 10px;
box-shadow: 5px 10px;
}
#bshadow_jquery {
border: 1px solid;
padding: 10px;
}
</style>
</head>
<body>
<h2>box-shadow css: 5px 5px #990000:</h2>
<div id="bshadow_css">
<p>this is a block-shadow by css</p>
</div>
<hr style="margin: 50px 0px">
<h2>box-shadow jquery: 5px 5px #990000:</h2>
<div id="bshadow_jquery">
<p>this is a block-shadow by JQuery</p>
</div>
</body>
</html>

Change amount from px to percent based

I am trying to create a carousel with a sliding effect. The basic setup is I have 2 div's wrapping around the sliding content. The first div's width (the outerWrapper) is the size of all slides width together. The next div's width (the innerWrapper) is the size of 1 div.
When it's supposed to change slides, the innerWrapper get's a translation of x amount and it animates from the css transition.
I have everything working, but there's one thing I want to change. I want to change from pixel to percent.
Line 29:
innerWrapper.style.transform = 'translateX(-' + imgWidth * targetIndex + 'px)';
I tried a lot of things, but nothing worked. The only thing that worked was targetIndex * 20 + %, but that only works for 5 divs. It's not a concrete solution. How can I make the translateX percentage based?
JSFiddle
var trigger = document.getElementsByClassName('trigger'),
outerWrapper = document.createElement('div'),
innerWrapper = document.createElement('div'),
slide = document.getElementsByClassName('slide'),
parentElm = slide[0].parentNode,
imgWidth = slide[0].offsetWidth,
lastElm = trigger.length - 1,
previousSelectedIndex = 0;
innerWrapper.id = 'innerWrapper';
outerWrapper.id = 'outerWrapper';
trigger[0].className += ' selected';
innerWrapper.style.width = imgWidth * (lastElm + 1) + 'px';
while (slide.length) {
innerWrapper.appendChild(slide[0]);
}
for (var i = 0; i < trigger.length; i++) {
trigger[i].addEventListener('click', function(e) {
clickEvent(e);
})
}
function clickEvent(e) {
if (!hasClass(e.target, 'selected')) {
var targetIndex = [].slice.call(trigger).indexOf(e.target);
innerWrapper.style.transform = 'translateX(-' + imgWidth * targetIndex + 'px)';
e.target.className += ' selected';
removeClass(trigger[previousSelectedIndex], 'selected');
previousSelectedIndex = targetIndex;
}
}
outerWrapper.appendChild(innerWrapper);
parentElm.appendChild(outerWrapper);
function hasClass(element, cls) {
return (' ' + element.className + ' ').indexOf(' ' + cls + ' ') > -1;
}
function removeClass(ele, cls) {
if (hasClass(ele, cls)) {
var reg = new RegExp('(\\s|^)' + cls + '(\\s|$)');
ele.className = ele.className.replace(reg, ' ');
}
}
#outerWrapper {
float: left;
width: 270px;
height: 266px;
overflow: hidden;
}
#innerWrapper {
position: relative;
display: flex;
transition: transform 0.7s cubic-bezier(0.45, 0.05, 0.55, 0.95);
}
ul.triggers li {
float: left;
margin: 0 5px;
font: bold 16px arial;
cursor: pointer;
background-color: #ccc;
padding: 10px;
}
ul.triggers li.selected {
background-color: orange;
}
<img class="slide" width="270" src="http://i.imgur.com/XyWadkY.jpg" />
<img class="slide" width="270" src="http://i.imgur.com/OpP86hg.jpg" />
<img class="slide" width="270" src="http://i.imgur.com/oWbhwWT.jpg" />
<img class="slide" width="270" src="http://i.imgur.com/IXcqVB1.jpg" />
<img class="slide" width="270" src="http://i.imgur.com/OpP86hg.jpg" />
<ul class="triggers">
<li class="trigger">1</li>
<li class="trigger">2</li>
<li class="trigger">3</li>
<li class="trigger">4</li>
<li class="trigger">5</li>
</ul>
Try this,
innerWrapper.style.transform = 'translateX(-' + (targetIndex*(100/document.getElementsByClassName("slide").length)) + '%)';

Javascript width of span element

I create via a String some DOM-Elements and assign it via innerHTML to a div.
Now I need a flexible width of the span element (span_homebase). What I experience is that sometimes (for me it looks randomly) it returns other width than expected. I need the width of this span element because after this in the same line there is an Information Button but the width of the span could be different. So I use the width of span element as margin for the information button. Code is as follows. I searched for a async handler of innerHTML but in another post somebody said that it is not required because it is assigned instantly.
Are there any thoughts what to try? Because the information is now sometimes on the right place and sometimes not.
string = string + "<span id ='span_homebase'>" + homebaseCity + "</span>";
string = string + "<div class='section-end'></div>";
element.innerHTML = string;
var marginInfoHomebase = document.getElementById('span_homebase').offsetWidth + 20;
document.getElementById("information_button_homebase").style.margin = "5px 0 0 " + marginInfoHomebase + "px";
Now if I open the respective site for me sometimes the marginInfoHomebase sometimes returns 108 and sometimes 183 even if the same value is assigned to span element. Very strange. Any thoughts?
EDIT:
Working Example:
function createHomeSettingsView(settingsA){
var element = document.getElementById("table-settings");
var string = "";
for(var i = 0; i < settingsA.length; i++){
for(var z = 0; z < settingsA[i].length; z++){
if(i == 1){
//Notification buttons
if(z == 1){
//homebase setting
if(window.localStorage.getItem("switch_homebase") == 1){
//homebase on
var homebaseCity = settingsA[i][z] + ": " + window.localStorage.getItem("homebase_loc");
string = string + " \
<div class='row' style='height:100px;' id='settings-sec-"+ i +"-row-" + z +"'> \
<div class='text'> \
<span id='span_homebase'>" + homebaseCity + "</span> \
</div> \
<div onClick='homebaseInfoClick();' class='information_button' id='information_button_homebase'></div>\
<div id='handleAutoSwitcherHomebase'></div>\
<div id='showRadiusRangeHomebase'>Radius: 30km</div>\
<input class='sliders' id='changeRadiusRangeHomebase' type='range' min='5' max='100' step='5' oninput='handleChangeHomebase(this.value)' onchange='handleInputHomebase(this.value)' >\
</div>";
}
else{
//homebase off
string = string + " \
<div class='row' id='settings-sec-"+ i +"-row-" + z +"'> \
<div class='text'>\
<span id='span_homebase'>" + settingsA[i][z] + "</span> \
</div> \
<div onClick='homebaseInfoClick();' class='information_button' id='information_button_homebase'></div>\
<div id='handleAutoSwitcherHomebase'></div>\
</div>";
}
}
}
}
}
element.innerHTML = string;
var marginInfoHomebase = document.getElementById("span_homebase").offsetWidth + 25;
var marginText = "5px 0 0 " + marginInfoHomebase + "px";
console.log("Span: " + marginInfoHomebase);
document.getElementById("information_button_homebase").style.margin = marginText;
}
CSS:
.container .table-settings{
top: 64px;
position: absolute;
padding:0;
left: 0;
right: 0;
bottom:0;
overflow-y: scroll;
-webkit-overflow-scrolling: touch;
background-color: #ECEBF3;
}
.container .table-settings .row{
background-color: white;
padding-top: 14px;
height:50px;
border-bottom: 1px solid LightGray;
}
.container .table-settings .row .text{
margin-left: 15px;
color: black;
float: left;
}
#span_homebase{
display: inline-block;
}
To get an inline element's width use getBoundingClientRect method:
var mySpan = document.getElementById("mySpan");
var spanWidth = mySpan.getBoundingClientRect().width;
var spanHeight = mySpan.getBoundingClientRect().height;
By default a span element has no dimension because its CSS display property is inline.
If you want to give it a width, you should change that property to inline-block.
<style>
span {
display: inline-block ;
}
</style>
Now you can play with its dimensions.

Categories