Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 12 months ago.
Improve this question
I am working on a project where I need to find the position of a "div" element, relative to the other divs (index position). for example if I have a div of class "item" and below it a div of class "list", the "item" would have an index value of 0, and the "list" would have an index value of 1.
I need help in finding the divs index.
I also need to use vanilla javascript without any library and no jQuery
I would share the code but unfortunatly, I write the program on an air gapped system. so I cannot post the code here.
You can fetch all divs and iterate the List. Check if contains the classes item or list and push to an array the index.
for example like that:
const d = document.querySelectorAll('div');
let r = [];
for(let i = 0; i < d.length; i++) {
if (d[i].classList.contains('item')) {
r.push({'itemIndex': i});
}
if (d[i].classList.contains('list')) {
r.push({'listIndex': i});
}
};
console.log(r)
<div class="a">A</div>
<div class="x">X</div>
<div class="item">ITEM</div>
<div class="list">LIST</div>
<div class="y">Y</div>
After much digging I found this post: JavaScript DOM: Find Element Index In Container
which my answer is based of (note the objects are inside a div called wit a class of "side-bar" and the amount of divs is saved in a global variable called sidebar_len)
var element1 = el_in; //the function gets "this" for the event
var sidebar = document.getElementsByClassName("side-bar")[0];
var sidebar_divs = sidebar.getElementsByTagName("div");
var div_index = 0;
var is_same = false;
while(div_index < sidebar_len && is_same == false) {
is_same = sidebar_divs[div_index].isSameNode(element1);
div_index++
}
div_index--;
const index = (start, find) => {
const sEl = document.getElementsByClassName(start)[0];
const el = document.getElementsByClassName(find)[0];
const childrens = [...el.parentElement.children];
const sIndex = childrens.indexOf(sEl);
for (let i = sIndex - 1; i >= 0; i--) {
childrens.splice(i, 1);
}
return childrens.indexOf(el);
};
const startClsName = 'item';
console.log('item index', index(startClsName, 'item'));
console.log('list index', index(startClsName, 'list'));
<div class='first'></div>
<div class='second'></div>
<div class='item'></div>
<div class='list'></div>
Related
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 5 years ago.
Improve this question
I want to make an element 50 times within a for loop. My code is below:
function pGenerate() {
for (i, i <= 50; i++;) {
var newP = document.createElement("p");
var pText = document.createTextNode("sample paragraph");
newP.appendChild(pText);
var contentSection = document.getElementById("content");
document.body.insertBefore(newP, contentSection);
}
}
The expected result is that it generates 50 <p> tags with "sample content inside of them. The actual result is well...nothing. https://jsfiddle.net/2L8reked/1/
My thought process behind the code I wrote this code is as follows: I basically have a loop set to cycle 50 times. for each cycle, I want to create a p tag, along with create a text node with the content "sample paragraph." In the next step, I grab the div by it's id, #content, and I then attempt to populate the area using insertBefore.
My error here seems to be how I use insertBefore. Looking this up on MDN, it's definition is "inserts the specified node before the reference node as a child of the current node." https://developer.mozilla.org/en-US/docs/Web/API/Node/insertBefore
With that definition in mind - I'm using this with the understanding as of now that I'm inserting (or attempting to) the p tags as a child of #content. Should I be using a different method? Am I misunderstanding how this works?
I also tried an innerHTML approach, seen here: https://jsfiddle.net/0e1ej9sk/1/
which method is best suited for what I'm trying to do?
In the first example what is the flaw behind my logic of the use of insertBefore?
You have 3 syntax errors.
Change i, in for loop to 1=1; then remove the last ; where i++; to i++
function pGenerate() {
for (i=1; i <= 50; i++) {
var newP = document.createElement("p");
var pText = document.createTextNode("sample paragraph");
newP.appendChild(pText);
var contentSection = document.getElementById("content");
document.body.insertBefore(newP, contentSection);
}
}
window.onload = function() {
pGenerate();
}
<div id="content"></div>
You need to initialize i at 1, and properly separate all parts of the for statement with semi-colons, like this:
function pGenerate() {
for (var i = 1; i <= 50; i++) {
var newP = document.createElement("p");
var pText = document.createTextNode("sample paragraph (i=" + i + ")");
newP.appendChild(pText);
var contentSection = document.getElementById("content");
document.body.insertBefore(newP, contentSection);
}
}
pGenerate();
<div id="content"></div>
you can do this
function pGenerate() {
for (i=1; i <= 50; i++) {
var newP = document.createElement("p");
var pText = document.createTextNode("sample paragraph");
newP.appendChild(pText);
var contentSection = document.getElementById("content");
document.body.insertBefore(newP, contentSection);
}
}
document.ready(pGenerate);
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
I'm afraid it might be a silly question, but I have no idea what occurs my problem.
I dynamically create buttons (each button has unique id), and I store each btn reference (document.getElementById()) in simple two-dimensional array. All these because i need to hold btns in well organized structure.
The problem is: when i try to modify element by reference previously stored in my array, there appears to be no connection between ref and html element.
var Table = {
size: 10,
table: [],
generateTable: function() {
var i = 0,
j = 0,
id = null,
tablePlaceholder = document.getElementById("tableHTML");
//Generate table
for (i = 0; i < this.size; i++) {
this.table.push([]);
for (j = 0; j < this.size; j++) {
id = i.toString() + "-" + j.toString();
tablePlaceholder.innerHTML += element(id);
this.table[i].push(document.getElementById(id));
}
tablePlaceholder.innerHTML += "</br>";
}
console.log(this.table[0][0].className);
document.getElementById("0-0").className += " btn-success";
console.log(this.table[0][0].className);
}, ...
Results of last two console.logs is the same, but element has changed in DOM.
table[0][0] returns same content as document.getElementById("0-0").
(element() function returns simple html code (it works well))
innerHTML += '<div>...</div>';
This could break references to already constructed DOM elements and cause other chaos. In reality, all you want to do is append a single new element to the end.
var elem = document.createElement('div');
elem.id = id;
tablePlaceholder.appendChild(elem);
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
How would I get the index of the chosen element or of 'elems[i]' within the javascript? I know this is a very simple question so any suggestions on a book to buy or course to take would be greatly appreciated. Thanks!
code:
<html>
<body>
<table>
<tr id="subject"><?php
$subjects = array("IT","Programming","Networks");
foreach($subjects as $key => $value) {
echo "<td>"."<a href='index.php' class='column'>".$value."</a>"."</td>";
}
?></tr>
</table>
</body>
<script type="text/javascript">
var elems = document.getElementsByClassName('column');
for (var i = 0; i < elems.length; i++) {
elems[i].onclick = function () {
console.log(this.innerHTML);
};
}
</script>
var elems = document.getElementsByClassName('column');
for (var i = 0; i < elems.length; i++) {
let a=i;//the magic happens
elems[i].onclick = function () {
console.log(a);
};
}
See Closures, let, ES6.
Option two (for older browsers):
var elems = document.getElementsByClassName('column');
for (var i = 0; i < elems.length; i++) {
(function(){
var a=i;
elems[i].onclick = function () {
console.log(a);
};
})();
}
You need to put the index into the handlers scope, either trough using block scoping (let, first answer) or by creating a new scope trough an IIFE...
(You need to create an own scope for each handler)
solution 3:
set the dom objects id:
elems[i].id=i;
elems[i].onclick=function(){
alert(this.id);
};
Solution 4:
Get the index dynamically:
alert(elems.indexOf(this));
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
I am trying to achieve is a simple remove Class function that receives the target ID and the classname wanting to remove. However I am not sure how can I get the specific classname from the var x using document.getElementById.
See below:
removeClass: function (selector, string) {
var x = document.getElementById(selector);
for ( i = 0; i < x.length; i++ ) {
x[i].classList.remove(string);
}
},
var removeClass = function (strElementId, strClassToRemove) {
var x = document.getElementById(strElementId);
x.classList.remove(strClassToRemove);
}
removeClass('a', 'b');
<div id="a" class="a b c">
test
</div>
Just get element by its id (should be unique in the html page) and use remove with class name key.
To know more about class manipulation using core JavaScript, please visit below link.
http://www.w3schools.com/jsref/prop_element_classlist.asp
First check whether the element have that class or not. Based on that remove it. Try something like this:
removeClass: function (selector, str) {
var x = document.querySelectorAll(selector);
for (i = 0; i < x.length; i++ ) {
if ( $(x[i]).hasClass(str)) {
$(x[i]).removeClass(str);
}
}
}
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
I have a piece of code which will invert all the checkboxes on my form. I have multiple elements (not just checkboxes but also <input type='text'>'s) in it. The reason I need it to be optimised is because it takes about two to three seconds to select all the checkboxes (275 right now).
Here's my code:
function FormInverse() {
var iCheckbox = 1; // Because there are multiple input elements, we need to distinquish the input element ID and the row id
var FormLength = document.FormFacturen.elements.length;
for (i=0; i < FormLength; i++) {
var FormElementType = document.FormFacturen.elements[i].type;
if (FormElementType == "checkbox") {
var Elements = document.getElementsByClassName('row' + iCheckbox); // Alle elementen in de array zetten
var iNumElements = Elements.length;
for (iElement=0; iElement < iNumElements; iElement++) {
if (document.FormFacturen[i].checked == true) {
Elements[iElement].className = "invoice-tr-standard row" + iCheckbox;
} else {
Elements[iElement].className = "invoice-tr-clicked row" + iCheckbox;
}
}
iCheckbox++;
document.FormFacturen[i].checked = !document.FormFacturen[i].checked;
}
}
}
And here is the document.getElementsByClassName function:
document.getElementsByClassName = function(cl) {
var retnode = [];
var myclass = new RegExp('\\b'+cl+'\\b');
var elem = document.getElementsByTagName('*');
for (var i = 0; i < elem.length; i++) {
var classes = elem[i].className;
if (myclass.test(classes)) retnode.push(elem[i]);
}
return retnode;
};
I would suggest using jQuery as well.
Try this:
Add a reference to jQuery:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js" type="text/javascript" language="JavaScript"></script>
Use this code:
$(':checkbox').each( function() {
$(this).attr('checked', !$(this).attr('checked'));
});
Edited:
Or use this to change the classes as well:
$(':checkbox').each(function() {
var checked = $(this).attr('checked');
if (checked) {
$(this).attr('checked', false);
$(this).addClass('invoice-tr-clicked');
$(this).removeClass('invoice-tr-standard');
}
else {
$(this).attr('checked', true);
$(this).addClass('invoice-tr-standard');
$(this).removeClass('invoice-tr-clicked');
}
});
Final version:
$('#FormFacturen :checkbox').each(function() {
var checked = $(this).attr('checked');
if (checked) {
$(this).attr('checked', false);
$(this).parents('tr').addClass('invoice-tr-clicked');
$(this).parents('tr').removeClass('invoice-tr-standard');
}
else {
$(this).attr('checked', true);
$(this).parents('tr').addClass('invoice-tr-standard');
$(this).parents('tr').removeClass('invoice-tr-clicked');
}
});
Each call to getElementsByClassName is expensive, and it is being called on each pass of your for loop.
In addition to #Geoff's suggestion, you could call document.getElementsByTagName('input'); just once, instead of each time getElementsByClassName is called and cache the result for use within your loop.
That would require making a small modification to your getElementsByClassName function whereby it accepts an array of elements to search through.
document.getElementsByClassName = function(cl, eles) {
var retnode = [];
var myclass = new RegExp('\\b'+cl+'\\b');
var len = eles.length;
for (var i = 0; i < len; i++) {
var classes = eles[i].className;
if (myclass.test(classes)) retnode.push(eles[i]);
}
return retnode;
};
function FormInverse() {
// cache all inputs
var inputs = document.getElementsByTagName("input");
...
// later
var Elements = document.getElementsByClassName('row' + iCheckbox, inputs);
You should look into a library like JQuery. It will handle this kind of thing well.
There are a lot of little things you can do to improve your code though. First thing I notice is that your getElementsByClassName function is looping through ALL elements on your page every time you call it. You could change this line:
var elem = document.getElementsByTagName('*');
to just get the input elements:
var elem = document.getElementsByTagName('input');
I am pretty much sure the bottleneck here is the getElementsByClassName function, the browser needs to re-scan the whole html each time to find your element. I suggest you give your elements a unique id id="row1", id="row2", ... instead of a unique class name and use getElementById which is much faster.
var Elements = document.getElementsById('row' + iCheckbox);