Displaying DOM elements on the web-page while looping over them - javascript

I am working on a landing page. I have 3 article elements, each of them has the property “display: none” and a class 'art'. I want to display each of them while looping over them. They should appear successively: the previous ones must disappear at each iteration, that is why I have used var j in the code below. But JS code displays them after the whole process of looping is completed. How to deal with it? Here: https://codepen.io/user_jacob/pen/oNjqWGg.
Currently, I am doing it like this (which is not working):
function makeAppear() {
var j = list.length-1;
for (var i = 0; i < list.length; i++) {
list[i].style.setProperty('display', 'block');
list[j-1].style.setProperty('display', 'none');
}
}

In set interval don put () just write function name . For looping create one global index then hide all first then show indexed one.
let j=0;
function makeAppear() {
for (var i = 0; i < list.length; i++) {
list[i].style.setProperty('display', 'none');
}
list[j].style.setProperty('display', 'block');
if(j<2){ j++;}
else {j=0}
}
setInterval(makeAppear, 2000);

Related

Javascript Performance improvement

I am Using Jquery plugin to show a dropdown which looks like this
Now in the edit page, this drop-down opens with checked checkboxes, I do this with the help of Javascript which is as below
var setValues = $("#SelectedFrameworks").val().split(",");
for (var i = 0; i < setValues.length; i++) {
var selectedElement = $("#frameworksDropDown").find('*[data-id="' + setValues[i] + '"]');
selectedElement.find("i").addClass("fa-check-square-o").removeClass("fa-square-o");
SelectParent(selectedElement);
}
function SelectParent(_element) {
var count = 0;
for (var i = 0; i < $(_element).parent().children().length; i++) {
if ($(_element).parent().children().eq(i).find("i").attr("class") == "fa select-box fa-check-square-o") {
count++;
}
}
if (count == $(_element).parent().children().length) {
$(_element).closest("ul").siblings("i").click();
}
}
I store this value first in the hidden field then use it to Check the checkboxes. (as shown in the code)
Now the problem is, it takes too much time when data is a lot. this causes the page to hang.
I found that operation
selectedElement.find("i").addClass("fa-check-square-o").removeClass("fa-square-o");
takes too much time. how can I optimize this code to have a better result
EDIT
Here is the HTML for this dropdown.
Note: this HTML is autogenarated.
Thanks.
So one of the big issues with this code is the amount of times you're calling the DOM. Everytime you do $(el) you're calling document.getElementByClassName or id etc. Which is gonna be slow and is unnecessary to make that many calls.
So you can change
function SelectParent(_element) {
var count = 0;
for (var i = 0; i < $(_element).parent().children().length; i++) {
if ($(_element).parent().children().eq(i).find("i").attr("class") == "fa select-box fa-check-square-o") {
count++;
}
}
if (count == $(_element).parent().children().length) {
$(_element).closest("ul").siblings("i").click();
}
}
To this, which accesses the DOM once, stores a reference to the element. This will cut down on the amount of DOM calls you make. The biggest advantage to this is of course, speed. I always make a point of naming jquery variables beginning with $ so that it's much easier and quicker to tell what that variable is in the future, or if someone else comes to work on your code.
function SelectParent(_element) {
var count = 0;
var $element = $(_element);
var $children = $element.parent().children();
for (var i = 0, length = $children.length; i < length; i++) {
if ($children.eq(i).find("i").attr("class") == "fa select-box fa-check-square-o") {
count++;
}
}
if (count == $children.length) {
$element.closest("ul").siblings("i").click();
}
}
Now of course you can refactor the rest to speed it up ;)

Using .push stops for loop from executing

I have a for loop that suddenly stops working when I try to push to an array. The best way to describe what's going on is just to show my code and try an explain what's going on.
for (var i = 0; i < childs.length; i++) {
if (childs[i].length > 0) {
for (var j = 0; j < amountsValue[i].options.custValues.length; j++) {
var label = amountsValue[i].options.custValues[j].label;
var value = amountsValue[i].options.custValues[j].value;
for (var k = childs[i].length - 1; k >= 0; k--) {
if (childs[i][k].attributes[label] != value) {
childBackup.push(childs[i][k]);
childs[i].splice(k, 1);
}
}
}
amountsValue[i].id = childs[i][0].attributes.internalid;
childs.push(childBackup);
}
}
What's happening is I am looping through an array of items which may or may not have custom options available such as different sizes or colours. The loop will check to see if there are any then get the value and label from the array.
After this, we then loop again to try and match up the values with option values stored within a separate model. The plan is to check if the value is the same as the one stored and if not then splice it from the array. The process of elimination should eventually leave only one option left and that will be used to get the internalid.
During this a back up of the spliced objects is kept so that they can be appended to the array again so that the user can change the option they want. The problem is using childs.push(childBackup) stops the browser form reading the options on amountsValue. This works if the code is removed or it is pushed into another index so I'm really not sure why it isn't working.
Does anyone have any suggestions on how to get this working? I'm sorry if this doesn't make much sense, I've tried to explain it as best I can but let me know if anything needs to be cleared up.
EDIT: I have fixed the issue. Thank you to everyone who suggested ways to solve the problem. As others said, I was trying to manipulate the array I was looping through and changing the length on it. So that part of the code was taken outside the loop and after the initial loop another loop was set up which contained the following code:
for (var i = 0; i < childBackup.length; i++) {
childs[0].push(childBackup[i]);
}
It now works as intended. Thank you.
You are manipulating the array you are looping through.
var count = childs.length;
for (var i = 0; i < count; i++) {
if (childs[i].length > 0) {
for (var j = 0; j < amountsValue[i].options.custValues.length; j++) {
var label = amountsValue[i].options.custValues[j].label;
var value = amountsValue[i].options.custValues[j].value;
for (var k = childs[i].length - 1; k >= 0; k--) {
if (childs[i][k].attributes[label] != value) {
childBackup.push(childs[i][k]);
childs[i].splice(k, 1);
}
}
}
amountsValue[i].id = childs[i][0].attributes.internalid;
childs.push(childBackup);
}
}

for loop in protractor js

I have a scenario where there are repeating elements with classname .product-tile and I am trying to get the elements by that class name and loop through each of them and finding the element whose title is Products.
If so, I'm trying clicking on apt-add-to-cart-button, but here the code isn't going in for loop.
var products = element.all(by.css('.product-tile'));
for (var i = 0; i < products.length; i++) {
console.log(i);
var product = products.get(0);
if (product.element(by.css('.productName .title')).getText() === 'Products') {
product.element(by.css('apt-add-to-cart-button')).click();
}
}
html :
Any help would be appreciated.
actually the repeating selector should be resolved as a promise like below
element.all(by.css('.product-tile.ng-scope')).then(function(items){
console.log(items.length); //will get the length here
// do the stuff here
});
Please read this through, as getText() returns a promise which needs to be resolved.
You may need something like this
var products = element.all(by.css('.product-tile.ng-scope'));
for (var i = 0; i <= products.length; i++) {
console.log(i);
var product = products.get(0);
if (product.element(by.css('.productName .title')).getText().then(function(returnText){
if(returnText==='Products'){
product.element(by.css('apt-add-to-cart-button')).click();
}else{
console.log('Something happened');
}
});
}
Edit - Your class contains compound class, so you cannot use a single class inside your CSS selector. Please see updated code

Check if the elements in array have been connected into a pair in Javascript

I have a problem that I can't seem to solve, maybe you can help.
There is an array I have. E.g. ['#dog','#cat','#mouse']
I want to reiterate through each value in that array and connect it to all the other values in that same array (through building a DB query).
However, because I'll be writing that in a database I need to avoid duplicates.
So if the #cat has been already connected to #mouse then by the time my for statement reaches the #mouse i want it to skip adding connection to #cat (and also to #dog because it was already connected on the first iteration to #mouse.
I've been trying with for loops, such as
for (var i=0; i<animals.length; i++) {
for (var j = 0; j<animals.length; j++) {
if (animals[i] !== animals[j]) {
// adds connection between animals[i] and animals[j]
}
}
}
But what's the best way to implement a check of the already existing pairs? (where it doesn't matter which element is the first, which is the second - e.g. my graph is not unidirectional).
This especially becomes a problem if I'm going to have more than 4 elements in the array...
Thank you for your help!
for (var i=0; i<animals.length; i++) {
for (var j = 0; j<i; j++) {
if (animals[i] !== animals[j]) {
// adds connection between animals[i] and animals[j]
}
}
}
This way, each element of the array is only compared against those before it in the array. I think this is much closer to what you want.
In the inner loop, you only want to make connections to elements not yet visited by the outer loop:
for (var i=0; i<animals.length; i++) {
for (var j = i+1; j<animals.length; j++) {
// ^^^
// adds connection between animals[i] and animals[j]
}
}
That way you won't get duplicate edges (assuming that animals itself is duplicate-free)

Javascript Wait for Ajax Content Load

I am newbie to javascript and am writing to traverse a DOM . The page uses Checkboxes to filter results. Results are displayed using Ajax. There are 4 level of checkboxes.
Grand Parent
Parent
Child
Grand Child .
For each level, I want the javascript to click the checkbox and WAIT for the content to load.
Right now it checks and traverses the whole DOM , but does not wait .
What I want is , that when the element is CLICKED , next function decideread() should be called only when Ajax results have been refreshed.
I have tried using setTimeOut and other delay methods, but they say it's single threaded so that won't work. Any ideas ?
for (i = 0; i < mgtNode.length; i++) {
mgtNode[i].click();
for (j = 1; j < stateNode.length; j++)
{
stateNode[j].click();
var read = decideRead();
if (read)
{
alert('we have read the data, now skip further reading below');
stateNode[j].click(); // we have read the data, now skip further reading below.
continue;
}
for (k = 0; k < inTypeNode.length; k++) {
inTypeNode[k].click();
var read = decideRead();
if (read)
{
alert('we have read the data, now skip further reading below');
inTypeNode[k].click();
continue;
}
for (l = 0; l < jobNode.length; l++)
{
jobNode[l].click();
while (true) {
if (new Date() - startTime >= 5000) {
break;
}
}
saveData();
jobNode[l].click();
}
inTypeNode[k].click();
}
stateNode[j].click();
}
mgtNode[i].click();
}
You should use the onreadystatechange for this. Check this http://www.w3schools.com/ajax/ajax_xmlhttprequest_onreadystatechange.asp

Categories

Resources