What does this for-loop do? - javascript

for (o.$slider.addClass("slick-dotted"), t = i("<ul />").addClass(o.options.dotsClass), e = 0; e <= o.getDotCount(); e += 1)
t.append(i("<li />").append(o.options.customPaging.call(this, o, e)));
(o.$dots = t.appendTo(o.options.appendDots)), o.$dots.find("li").first().addClass("slick-active");
I have to modify a JS-Script from a template I downloaded. In order to do this, I first wanted to understand the script, so I know where and what I have to change. But I don't understand what these lines of code do, can anyone help?(I understand the principle of for-loops, but this one seems different and I'm a bit confused.
And yes I'm aware that you can't tell me what exactly will appear on the website, since you only have two lines of code, but I just need to know what happens with a specific class or element and I hope you can read this information from these two lines).
Thanks in advance

Strip back the object/plugin calls, add a couple of console logs:
for (console.log('do this'), console.log('then this'), e = 0; e <= 10; e += 1)
console.log.call(this, 'slider', e);
result is:
do this
then this
slider 0
slider 1
slider 2
slider 3
slider 4
slider 5
slider 6
slider 7
slider 8
slider 9
slider 10
It's building out <li>'s for the slick slider DOM

It seems like minified code, it will therefore always be hard to read and understand. You should get the unminified version and work on that instead.
Here is the same code unminified plus the rest of surrounding function (from GitHub), I hope now it makes a lot more sense:
Slick.prototype.buildDots = function() {
var _ = this,
i, dot;
if (_.options.dots === true && _.slideCount > _.options.slidesToShow) {
_.$slider.addClass('slick-dotted');
dot = $('<ul />').addClass(_.options.dotsClass);
for (i = 0; i <= _.getDotCount(); i += 1) {
dot.append($('<li />').append(_.options.customPaging.call(this, _, i)));
}
_.$dots = dot.appendTo(_.options.appendDots);
_.$dots.find('li').first().addClass('slick-active');
}
};
It checks if the option dots is set and there are more slides than visible, and in this case it adds the class slick-dotted to the slider and creates an <ul> with the dotsClass and fills it with <li>s that contain the return value of the customPaging function. At the end, the first <li> gets the slick-active class. - I.e., it creates the dot navigation for the slides.

Related

How do I stop the 6th Star from appearing in this code?

I'm learning Javascript and as an exercise I want to take a list of text ratings and convert it into star ratings.
There are probably some easier ways and libraries to do this but I wanted to try it with my own code just so I can understand how the code works.
I've mostly stumbled my way to a nearly working solution. However, I keep getting an extra star after going through the loops.
Here is a link to fiddle with the full code...
Fiddle
This is my HTML
<div class="container" id="container">
<div class="rating" id="rating">1.2</div>
<div class="rating" id="rating">3.2</div>
<div class="rating" id="rating">4.8</div>
<div class="rating" id="rating">5</div>
<div class="rating" id="rating">2.6</div>
</div>
this is my javascript
I'm basically getting all the ".ratings" elements from the parent "container"
const ratingsContainer = document.getElementById('container');
const ratings = ratingsContainer.getElementsByClassName('rating');
Iterating through them;
In the for loop Im fetching the innerHTML of each ratings div.
const ratingScore = parseFloat(ratings[i].innerHTML).toFixed(1);
Im converting them to decimal numbers because I have to split the rating in order to get the number of full stars needed and the number of fractional stars needed.
Im also calculating the number of empty stars needed.
let emptyStars;
emptyStars = fullStars < 5 ? 5 - fullStars - 1 : 0;
I then create the required elements for the fullstars, the fractional stars and the empty stars through a loop for each that looks something like this...
for (let i = 0; i < fullStars; i++) {
const newstarContainer = document.createElement('div');
newstarContainer.className = 'starContainer';
const starFill = document.createElement('div');
starFill.className = 'starFill';
const starFillImage = document.createElement('img');
starFillImage.src = 'images/star.svg';
const starOutline = document.createElement('div');
starOutline.className = 'starOutline';
const starOutlineImage = document.createElement('img');
starOutlineImage.src = 'images/outline.svg';
const newstarContainerFill = newstarContainer
.appendChild(starFill)
.appendChild(starFillImage);
const newstarContainerOutline = newstarContainer
.appendChild(starOutline)
.appendChild(starOutlineImage);
document
.getElementById('container')
.appendChild(newRatingsContainer)
.appendChild(newstarContainer);
}
I do this for the empty and fractional stars as well.
The fractional stars get a custom width style added to the star image container this cuts off the star.svg image based on the percentage width.
const starFill = document.createElement('div');
starFill.className = 'starFill';
starFill.style.width = `${fractionalStars}%`;
Finally I append everything to the container and remove the original text ratings.
My problem is when the text ratings number is 0 or not existing, I get an extra star. I've tried to play around with the code but I cant seem to figure out why its happening.
Can someone please help me to explain what Im doing wrong.
Got a few pointers and finally came up with something that works.
The first issue was getting an extra star.
That turned out to be a problem with the part of the code that fractional and empty stars.
I was running the loop like this...
for (let i = 0; i < 1; i++) {
That meant it always run at least once. This meant that when there was no fractional star to be added like in the case of an integer without a float, the loop still run and generated a star with a width of 0%. Which looked like extra empty star. I solved that by changing the loop to an if statement since it was only supposed to run once. So the code became
if (fractionalStarsFill > 0) {
The second problem was the way I was getting the number of empty stars required. I was doing it like this...
emptyStars = fullStars < 5 ? 5 - fullStars - 1 : 0;
Which is obviously wrong. I think I was tired.
I changed that to
emptyStars = fractionalStarsFill > 0 ? 4 - fullStars : 5 - fullStars;
This takes into account whether there are fractional stars or not and generates the number of empty stars accordingly.
Finally, I refactored the code and moved the repeated statements into a function, and changed a few variables to more meaningful names.
Here is a Fiddle to the final solution.

subtraction in p5.js if statement only occurs once instead of repeating

I have a p5.js animation here that is meant to animate the artwork then reverse the animation, however while it works for my other artworks, the logic doesn't work here as the if statement doesn't get triggered due to the subtraction for my mask only occurs once. Right now only have of the animation works, you can view it here: https://editor.p5js.org/theruantan/sketches/8g583LF8j
The main issue begins at line 116 and it is at line 124 where the code is unable to reach this if statement.
//Start of reversal for masks
for (let i = beachSwitches.length - 1; i >= 0; i--) {
if (beachSwitches[i] == 0) {
if (beachMasks[i] > 0) {
beachMasks[i] -= 20;
animating = true;
//console.log("beachMasks");
console.log(beachMasks[i])
}
if (beachMasks[i] <= 300) {
// Begin reversing the next bar
beachSwitches[i - 1] = 0;
// To see if the code is able to reach here.
console.log(beachSwitches[i - 1] + "This is triggered");
}
}
}
beachMarks[i] should be able to be <= 300 but it's stuck at 780.
I have recently started working with p5.js but just based on reading the code and understanding what you are trying to do what I can see is in the line you mentioned i.e 116 , if you log inside and outside you will understand why its only running once.
Inside the 116 lines for loop, you are checking for beachSwitches[i]==0, which only happens once(at the last index of that array) because the beachSwitches gets modified above, also you haven't defined anything in the else part for this condition. Which is what is beachSwtiches[i] == 0 is NOT TRUE.
In my screenshot below, you might get a rough idea. Hope this helps in some manner! Cheers!
Screenshot of logs I took from line 116 to 124

Data-percent works only sometimes javascript

(Sorry for bad english) Hi, I'm trying to make a JavaScript app which is basically a music player and I can't figure out why one thing is not working. There's a chart that displays the music percentage (here's a screenshot) made with jQuery CDN and a GitHub source. The percentage resets at the beginning of the song (and this works) because of songTime.dataset.percent = 0;.
Then, there's the songTime.dataset.percent = sliderPosition; in a function that calculate at what point are you in the song
function chartUpdate() {
let sliderPosition = 0;
if (currentSong.duration != NaN) {
sliderPosition = Math.round(currentSong.currentTime * (100 / currentSong.duration));
songTime.dataset.percent = sliderPosition;
}}
It is in an if statement which is in a function, but this doesn't work (it's not because of the variable, I've checked it).
I've tested it several times, and the only difference between the two lines is that the one that doesn't work is in an if statement (as I already said, which is in a function).
I know it can be difficult to understand me because there isn't any code (I tried to add it, but in stackoverflow it doesn't work, I don't know why), but if you need (I don't know if it can be helpful) I hosted the non-working website here. Summing up, my problem is that the data-percent works only sometimes.
Your if statement contains invalid syntax. Replace
if (currentSong.duration != NaN)
with
if ( ! isNaN(currentSong.duration) )

Modifying style in JS bypassing current styleSheets.cssRules lmitations with loops on get ID

Firstly, apologies if an answer is somewhere around the internet, but I've searched far and wide and found nothing relevant.
So, as most of you are aware, there are limitations from injecting rules in CSS sheets in certain conditions. Mine is that I cannot use a variable inside a .div:nth-child(thejsvariable) {transform: whatever-transform-option;}. But that extends to any style modifications on using JS variable in the CSS string.
I've tried vaaaarious options and ideas. The most recent one is the one with this problem.
I'm trying to modify any style with a simple getElementById, in which the ID consists of the string "hexpod" and the loop variable.
Now, for the loop variable I need it to select specific items that are on each second row of a grid.
So Tried to nest multiple loops with "multiple of" conditionals.
var wholeRowItems = rowIterations.toFixed(0);
for (var r = 1; r <= hexIterations; r++) {
if (r % 15 == 1 ) {
console.log(r);
for (var t = 1; t <= wholeRowItems; t++) {
console.log(t);
}
}
}
For a bit of Context my grid is fully responsive related to the size of the body.
So the var rowIterations returns how many items with fixed size fit in the body on a row. In my case it's 15 with the toFixed(0) method.
The var hexIterations returns how many items fit in the body. In my case it's 134 items.
Console log returns (not an array, but separate numbers) the range between 1 and 15 followed each time by 16, 31, 46 and so on.
At this point I'm just very frustrated and crying for help on solutions or at least ideas.
You can find the entire code here, if you want to see what's up around the problem, just in case it's relevant.
https://jsitor.com/AXU_pOzBD
Edit: I forgot to mention that once I've placed a getElementById('hexpod' + r + t) it selected only 2 rows, starting in the middle of the rows, one at the beginning and one at about the end aand my brain just faded away.
After more neurons grinding I've managed to find the solution, and I'm post it for the record in case anyone else stumbles over this problem.
I've managed to better understand the conditional logic of multiple of number identification. There should've been "0" instead of "1" in r % 30 statement.
Got the getElementById method to identify the string "hexpod" with r (that is set to target each second row) -15 (in order to start from the second row) + t (to use every grid element of the targeted row).
var wholeRowItems = rowIterations.toFixed(0);
for (var r = 1; r <= hexIterations; r++) {
if (r % 30 === 0 ) {
for (var t = 1; t <= 15; t++) {
var rt = document.getElementById("hexpod" + Number(r - 16 + t));
rt.style.transform = "translateX(-100%) translateY(-75%) rotate(-60deg) skewY(30deg) scale(0.95)";
}
}
}

Infinite loop when using generic solution to split up carousel contents

Basically, I'm getting an infinite loop and maybe I'm working too hard but I can't see why.
Context:
I'm using a carousel (Bootstrap's). The contents of the carousel is generated and pushed into one carousel slide, then the goal is to take the contents and split it up into multiple slides if the number of items inside surpass a certain pre-defined max-length property (5). I got this working fine for a specific use case of the carousel (a table being spread across the multiple slides if there are more than 5 table rows), but it's not generic enough. What happened is that the JS would take the overflown table rows (i.e. of index 5 and up), create a new slide from a harcoded HTML string in the function (a slide div containing all the markup for the table yet empty) and push those extra rows into it.
To make it more generic, I've decided to use classes like carousel_common_list and carousel_common_item which would be applied to the tbody and trs in the case I've explained. Then, I've to handle the template in a decoupled way. What I've tried to do is, take a clone of the original sole slide, empty the carousel_common_list and push any overflown carousel_common_items into it, and so on. But I get an infinite loop.
Code
What I've called a slide so far is called an item in the code (to match Bootstrap's carousel's item class for slides).
var carousels = $('div.carousel'),
carouselCommonListClass = 'carousel_common_list',
carouselCommonItemClass = 'carousel_common_item',
items_per_slide = 5;
$.each(carousels, function (index, element) {//for each carousel
var $carousel = carousels.eq(index),
$items = $carousel.find('.item');
var getItemTemplate = function ($item) {
$copy = $item.clone();//take the html, create a new element from it (not added to DOM)
$copy.find('.' + carouselCommonListClass).empty();
$copy.removeClass('active');
return $copy;
}
var splitUpItem = function ($item, $itemTemplate) {
var $bigList = $item.find('.' + carouselCommonListClass), group;
while ((group = $bigList.find('.' + carouselCommonItemClass + ':gt(' + (items_per_slide - 1 ) + ')').remove()).length) {
var $newItem = $itemTemplate;
$newItem.find('.' + carouselCommonListClass).prepend(group);
$newItem.insertAfter($item);
splitUpItem($newItem, $itemTemplate);//infintely called
}
}
//foreach item
$.each($items, function (item_index, item_element) {//for each slide, in each carousel
var $item = $items.eq(item_index);
splitUpItem($item, getItemTemplate($item));
});
});
FYI, this works like expected when the line marked with //infintely called is commented out; i.e. splits one oversized slide into one slide of items_per_slide length and another slide (which could be over items_per_slide in length if the original sole slide was over items_per_slide * 2 in length.
Also, I took this answer and modified it for the contents of splitUpItem().
Note:
I know it's not the most usable or accessible solution to split tables, lists, etc. over multiple slides like I am, but if you've a better idea answer my open question on that.
You're not getting an infinite loop per se, in that you're not infinitely stuck in the same while loop. As you mention, when you remove the //infinitely called line you're fine. The first pass through that while loop, the length you compute will equal the number of items (with gt:(4)) in all the lists in $item. You then remove all those items, so the next pass through will have that number equal to 0. This will always be the behaviour of that loop, so it really doesn't need to be a loop, but that's not the main problem.
The problem is that it's a recursive call. And the only guard you have against making the recursive call infinite is the condition in your while loop, but that condition will always be met the first pass through. In fact, if $item has 5 lists, each with 3 items with gt:(4), then $newItem will have 5 lists, each with 5 x 3 = 15 items. So when splitUpItem gets called on $newItem, the condition in your while loop will again first be non-zero. And then it'll get called again, and that number will be 5 x 15 = 75. And so on. In other words, you're recursively calling this function, and your guard against this call being made infinitely many times is to check that some number is 0, but the number there will actually grow exponentially with each recursive call of splitUpItem.
Hope that answers your question about why it's "infinitely looping." Gotta get to work, but I'll try to suggest a better way to split up the slides tomorrow if no one else has by then.

Categories