Add class to element based on its index - javascript

Currently i am building a storytelling website, where the client can iterate through several videos. However, there is also a page with chapters on the website. So when the client clicks on the next or previous button, the chapters should be lighten up on the chapter he currently is on.
At the moment i build a click counter, so the counter is counting up, when he clicked on next and counting down, when clicked on previous. I have 11 chapters, so 11 video's. I am checking the chapters by index. They are going from 0 to 11. When the client hits the next button, he's going to the next video and the click counter goes up with one.
At the moment i have trouble to connect this click counter to the current index of the chapter. So if the click counter goes to two for instance, the background of only chapter 2 (index 2) should be lighten up.
At the moment i have this:
<a href="#" class="vorige prev-rew button-sound">
<svg>icon</svg>
</a>
<a href="#" class="next prev-rew button-sound">
<svg> icon</svg>
</a>
<div class="marketing-chapter job-chapter">
<a href="#">
<div class="anchor-point chapter-1">
<p>1</p>
</div>
</a>
<a href="#">
<div class="anchor-point chapter-2">
<p>2</p>
</div>
</a>
<a href="#">
<div class="anchor-point chapter-3">
<p>3</p>
</div>
</a>
<a href="#">
<div class="anchor-point chapter-4">
<p>4</p>
</div>
</a>
<a href="#">
<div class="anchor-point chapter-5">
<p>5</p>
</div>
</a>
<a href="#">
<div class="anchor-point chapter-6">
<p>6</p>
</div>
</a>
<a href="#">
<div class="anchor-point chapter-7">
<p>7</p>
</div>
</a>
<a href="#">
<div class="anchor-point chapter-8">
<p>8</p>
</div>
</a>
<a href="#">
<div class="anchor-point chapter-9">
<p>9</p>
</div>
</a>
<a href="#">
<div class="anchor-point chapter-10">
<p>10</p>
</div>
</a>
<a href="#">
<div class="anchor-point chapter-11">
<p>11</p>
</div>
</a>
</div>
// Anchorpoint loop
var set = $(".anchor-point");
var length = set.length;
var ViewportCount = 1;
$('.prev-rew').on("click", function() {
if ($(this).hasClass('next')) {
console.log('klikkert next');
ViewportCount = ViewportCount + 1;
} else if ($(this).hasClass('vorige')) {
console.log('klikkert vorige');
ViewportCount = ViewportCount - 1;
}
set.each(function(index) {
index = ViewportCount;
console.log(index);
console.log(ViewportCount);
if(index == ViewportCount){
// Change the background-color of the number, connected to the index. So
current chapter will light up
}
});
});

To do what you require you can use the eq() method to directly select the element in the collection without a loop:
var set = $(".anchor-point");
var ViewportCount = 0;
$('.prev-rew').on("click", function() {
if ($(this).hasClass('next')) {
ViewportCount = ViewportCount + 1;
} else if ($(this).hasClass('vorige')) {
ViewportCount = ViewportCount - 1;
}
set.removeClass('active').eq(ViewportCount % set.length).addClass('active');
});
.active { background-color: #C00; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Previous
Next
<div class="marketing-chapter job-chapter">
<a href="#">
<div class="anchor-point chapter-1 active"><p>1</p></div>
</a>
<a href="#">
<div class="anchor-point chapter-2"><p>2</p></div>
</a>
<a href="#">
<div class="anchor-point chapter-3"><p>3</p></div>
</a>
<a href="#">
<div class="anchor-point chapter-4"><p>4</p></div>
</a>
<a href="#">
<div class="anchor-point chapter-5"><p>5</p></div>
</a>
<a href="#">
<div class="anchor-point chapter-6"><p>6</p></div>
</a>
<a href="#">
<div class="anchor-point chapter-7"><p>7</p></div>
</a>
<a href="#">
<div class="anchor-point chapter-8"><p>8</p></div>
</a>
<a href="#">
<div class="anchor-point chapter-9"><p>9</p></div>
</a>
<a href="#">
<div class="anchor-point chapter-10"><p>10</p></div>
</a>
<a href="#">
<div class="anchor-point chapter-11"><p>11</p></div>
</a>
</div>
However, you can avoid the need for the counter variable and instead move the active class based on its current position in the DOM. The <a> elements wrapping the div can also be removed as it's invalid HTML, it makes the JS more straightforward and it's also not necessary in this case
$('.prev-rew').on("click", function() {
let $current = $('.active');
let $target = $current[$(this).data('action')]();
if ($target.length) {
$current.removeClass('active');
$target.addClass('active');
}
});
.active {
background-color: #C00;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Previous
Next
<div class="marketing-chapter job-chapter">
<div class="anchor-point chapter-1 active"><p>1</p></div>
<div class="anchor-point chapter-2"><p>2</p></div>
<div class="anchor-point chapter-3"><p>3</p></div>
<div class="anchor-point chapter-4"><p>4</p></div>
<div class="anchor-point chapter-5"><p>5</p></div>
<div class="anchor-point chapter-6"><p>6</p></div>
<div class="anchor-point chapter-7"><p>7</p></div>
<div class="anchor-point chapter-8"><p>8</p></div>
<div class="anchor-point chapter-9"><p>9</p></div>
<div class="anchor-point chapter-10"><p>10</p></div>
<div class="anchor-point chapter-11"><p>11</p></div>
</div>

Related

Cannot read properties of undefined (reading 'scrollTo')

This below code giving me runtime error. I just want the browser to go to top while the page is routed from footer link. It just stick to the bottom and need to scroll.
document.getElementsByClassName('homemenu').scrollTo(0, 0);
header.component.html
<header class="top-head homemenu" *ngIf="showMenu == 'home'">
<div class="container-fluid">
<div class="row" [ngClass]="{'justify-content-center': onlyLogo}">
<div class="col-3 lm-logo"><img src="/assets/images/lm-logo.svg"></div>
<div class="col-9" *ngIf="!onlyLogo">
<div class="d-flex justify-content-end">
<ul class="menu_wrap d-flex">
<ng-container *ngIf="homemenu; else individual_page">
<li>Home</li>
<li>Individuals</li>
<li>Corporate</li>
<li>Hiring Managers</li>
<li class="dropdown_menu"><a class="dropdown-toggle nav-link" [routerLink]="['/partners']" routerLinkActive="active" aria-expanded="true" data-toggle="dropdown">Partners</a>
<div class="dropdown-menu">
<div class="menu_item">
<img class="img-fluid" src="{{bitBucketUrl}}library/images/corporate/home/p-ico5.png">
<a href="javascript:void(0)" [routerLink]="['/partners/content-owners']" routerLinkActive="active" >Content Owner</a>
</div>
<div class="menu_item">
<img class="img-fluid" src="{{bitBucketUrl}}library/images/corporate/home/p-ico3.png">
<a href="javascript:void(0)" [routerLink]="['/partners/influencers']" routerLinkActive="active" >Influencers</a>
</div>
<div class="menu_item">
<img class="img-fluid" src="{{bitBucketUrl}}library/images/corporate/home/p-ico2.png">
<a href="javascript:void(0)" [routerLink]="['/partners/localmasters-for-startup']" routerLinkActive="active" >Localmasters for Startup</a>
</div>
<div class="menu_item">
<img class="img-fluid" src="{{bitBucketUrl}}library/images/corporate/home/p-ico4.png">
<a href="javascript:void(0)" [routerLink]="['/partners/customer-training-solutions']" routerLinkActive="active" >Customer Training Solutions</a>
</div>
<div class="menu_item">
<img class="img-fluid" src="{{bitBucketUrl}}library/images/corporate/home/p-ico1.png">
<a href="javascript:void(0)" [routerLink]="['/partners/solution-partner-program']" routerLinkActive="active" >Solution Partner Program</a>
</div>
</div>
</li>
</ng-container>
<ng-template #individual_page>
<li>Home</li>
<li>How It Works</li>
<li>Be a Mentor</li>
</ng-template>
</ul>
<button class="btn top-btn" [routerLink]="['/login']" type="button">Sign In</button>
<!-- (click)="showSiteMap = !showSiteMap" -->
</div>
</div>
</div>
</div>
</header>
The above code works as expeceted but leave a error as shown in screenshot.
getElementsByClassName returns HTMLCollection.
You have to specify the exact item within the HTMLCollection, that you want to use scrollTo on. Ex.:
document.getElementsByClassName('homemenu')[0].scrollTo(0, 0);
Or use more modern function to query html, like querySelector. Ex.:
document.querySelector('.homemenu').scrollTo(0, 0);
To updated question
As I can see, you have that class assigned to element, that is rendered by angular. Make sure to call this function only when angular has rendered this tag.
Also, if code works as expected, then you can just check for null value the element, to get rid of the error:
document.querySelector('.homemenu')?.scrollTo(0, 0);
document.querySelector('.homemenu').scrollTo({top : 0});

Javascript (jquery) variable adding values instead of replacing, why?

dear friends.
I've found some case i cant understand.
Here is an example - whenether you choose 1,2,3,4 or 5 button, betPrice takes normally 1 value.
But if you press PUT button it will tell, betPrice variable has as many values inside, as you had pressed before! Why?
If you press 1,2,3,4 or 5 button again, it will be one value again.
Heading
$('.single-place-to-bet').find('a').on('click', function() {
var betPrice;
betPrice = $(this).find("span[class^='bet-price']").attr('class');
console.log(betPrice);
$("#sendnumber").click(
function() {
console.log(betPrice);
}
);
});
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!-- bet modal begin -->
</head>
<body>
<button id="sendnumber" name="sendnumber">Put</button>
<!-- bet modal end -->
<hr>
<div class="single-place-to-bet col-xl-2 col-lg-2">
<a href="#">
<span class="result-for-final" data-numberid="choice1">
1
</span>
<span class="bet-price-1">???</span>
</a>
</div>
<div class="single-place-to-bet col-xl-2 col-lg-2">
<a href="#">
<span class="result-for-final" data-numberid="choice2">
2
</span>
<span class="bet-price-2">???</span>
</a>
</div>
<div class="single-place-to-bet col-xl-2 col-lg-2">
<a href="#">
<span class="result-for-final" data-numberid="choice3">
3
</span>
<span class="bet-price-3">???</span>
</a>
</div>
<div class="single-place-to-bet col-xl-2 col-lg-2">
<a href="#">
<span class="result-for-final" data-numberid="choice4">
4
</span>
<span class="bet-price-4">???</span>
</a>
</div>
<div class="single-place-to-bet col-xl-2 col-lg-2">
<a href="#">
<span class="result-for-final" data-numberid="choice5">
5
</span>
<span class="bet-price-5">???</span>
</a>
</div>
</body>
</html>
Each time the function runs, your set an additionnal event listener.
For your case you can't move the event listener out of the function, so you can une jQuery off() to remove any event listener on the button then set it again.
$('.single-place-to-bet').find('a').on('click', function() {
var betPrice;
betPrice = $(this).find("span[class^='bet-price']").attr('class');
console.log(betPrice);
$("#sendnumber").off().on('click',
function() {
console.log(betPrice);
}
);
});
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!-- bet modal begin -->
</head>
<body>
<button id="sendnumber" name="sendnumber">Put</button>
<!-- bet modal end -->
<hr>
<div class="single-place-to-bet col-xl-2 col-lg-2">
<a href="#">
<span class="result-for-final" data-numberid="choice1">
1
</span>
<span class="bet-price-1">???</span>
</a>
</div>
<div class="single-place-to-bet col-xl-2 col-lg-2">
<a href="#">
<span class="result-for-final" data-numberid="choice2">
2
</span>
<span class="bet-price-2">???</span>
</a>
</div>
<div class="single-place-to-bet col-xl-2 col-lg-2">
<a href="#">
<span class="result-for-final" data-numberid="choice3">
3
</span>
<span class="bet-price-3">???</span>
</a>
</div>
<div class="single-place-to-bet col-xl-2 col-lg-2">
<a href="#">
<span class="result-for-final" data-numberid="choice4">
4
</span>
<span class="bet-price-4">???</span>
</a>
</div>
<div class="single-place-to-bet col-xl-2 col-lg-2">
<a href="#">
<span class="result-for-final" data-numberid="choice5">
5
</span>
<span class="bet-price-5">???</span>
</a>
</div>
</body>
</html>
Everytime any number is pressed, it is registering a new click listener for sendnumber button element. Place the button click listener outside the callback function of .single-place-to-bet listener
var betPrice;
$('.single-place-to-bet').find('a').on('click', function() {
betPrice = $(this).find("span[class^='bet-price']").attr('class');
console.log(betPrice);
});
$("#sendnumber").click(
function() {
if (betPrice) {
console.log(betPrice);
}
}
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id="sendnumber" name="sendnumber">Put</button>
<!-- bet modal end -->
<hr>
<div class="single-place-to-bet col-xl-2 col-lg-2">
<a href="#">
<span class="result-for-final" data-numberid="choice1">
1
</span>
<span class="bet-price-1">???</span>
</a>
</div>
<div class="single-place-to-bet col-xl-2 col-lg-2">
<a href="#">
<span class="result-for-final" data-numberid="choice2">
2
</span>
<span class="bet-price-2">???</span>
</a>
</div>
<div class="single-place-to-bet col-xl-2 col-lg-2">
<a href="#">
<span class="result-for-final" data-numberid="choice3">
3
</span>
<span class="bet-price-3">???</span>
</a>
</div>
<div class="single-place-to-bet col-xl-2 col-lg-2">
<a href="#">
<span class="result-for-final" data-numberid="choice4">
4
</span>
<span class="bet-price-4">???</span>
</a>
</div>
<div class="single-place-to-bet col-xl-2 col-lg-2">
<a href="#">
<span class="result-for-final" data-numberid="choice5">
5
</span>
<span class="bet-price-5">???</span>
</a>
</div>
There are actually multiple betPrice variables printing themselves with console.log().
This happens because you put ("#sendnumber")... inside your .on event handler, creating a new event handler everytime you click the Put button.
Move the second event handler creator outside the first one, like below, and you should be fine:
$('.single-place-to-bet').find('a').on('click', function() {
var betPrice;
betPrice = $(this).find("span[class^='bet-price']").attr('class');
console.log(betPrice);
$("#sendnumber").click(
function() {
console.log(betPrice);
}
);
});

Google tag manager get closest a text

i want use custom js variable to get card-title a shop-item-title-link's text for the event label = "product x".
Clicking the click class fa-cart-plus to get the label product x;
Click the image to get the label product x
I've tried this js below, but it gets [object] [object] as the result.
function() {
var el = {{Click Element}};
return $(el).closest('card-title').text('a.shop-item-title-link');
}
HTML
<div class="card card-product">
<div class="card-image">
<a href="#" title="product x">
<img width="230" height="230" src="#" class="attachment-_thumbnail" alt="product x">
</a>
<div class="ripple-container"></div>
</div>
<div class="content">
<h6 class="category">Items</h6>
<h4 class="card-title">
<a class="shop-item-title-link" href="#" title="product x">product x</a>
</h4>
<div class="card-description">
<p><span>product descirption</span></p>
</div>
<div class="footer">
<div class="price">
<h4><span class="Price"><span class="Price-currencySymbol">£</span>45.00</span></h4>
</div>
<div class="stats">
<a rel="nofollow" href="#" title="Add to cart">
<i rel="tooltip" data-original-title="Add to cart" class="fa fa-cart-plus"></i>
</a>
</div>
</div>
</div>
</div>
That is a very specific target, what you want to do is use parent and sibling together.
Try something like this:
return $(el).parents().siblings('.card-title').text();

How do you move a div into another using javascript?

I have two divs of the same size, and when I click a button on one of the divs, it will get larger. I want to move the smaller div into the bottom-right corner of the larger div, and when I click the button again the divs will return to their original size and position.
Before:
--- ---
| 1 | | 2 |
--- ---
After:
---------
| 2 |
| ---|
| | 1 |
---------
Here's my javascript for resizing so far:
function resizeSubscriber() {
var subscriberPanel = document.getElementById('dvOtherPerson');
var publisherPanel = document.getElementById('dvYou');
var classSetting = subscriberPanel.getAttribute('class');
if (classSetting == 'col-xl-4') {
subscriberPanel.setAttribute('class', 'col-xl-12');
}
else {
subscriberPanel.setAttribute('class', 'col-xl-4');
}
}
here is my asp code
<div id="dvOtherPerson" class="col-xl-4">
<div>
<div class="m-portlet__head">
<div class="m-portlet__head-caption">
<div class="m-portlet__head-title">
<h3 class="m-portlet__head-text">
Rachel Hawkins
</h3>
</div>
</div>
<div class="m-portlet__head-tools">
<ul class="m-portlet__nav">
<li class="m-portlet__nav-item">
<a href="" class="m-portlet__nav-link m-portlet__nav-link--icon">
<a href="" class="m-portlet__nav-link m-portlet__nav-link--icon">
<i class="fa fa-volume-up text-success"></i>
</a>
<a href="" class="m-portlet__nav-link m-portlet__nav-link--icon">
<i class="fa fa-refresh"></i>
</a>
<a onclick="resizeSubscriber();" href="#" class="m-portlet__nav-link m-portlet__nav-link--icon">
<i class="fa fa-expand"></i>
</a>
</li>
</ul>
</div>
</div>
<div class="m-portlet__body">
<img src="./img/temp/users/video_rachel.jpg" class="img-fluid" />
</div>
</div>
<%-- <div id="videos">
<div id="subscriber"></div>
</div>--%>
</div>
<div id="dvYou" class="col-xl-4">
<div class="m-portlet m-portlet--fit">
<div class="m-portlet__head">
<div class="m-portlet__head-caption">
<div class="m-portlet__head-title">
<h3 class="m-portlet__head-text">
Me
</h3>
</div>
</div>
<div class="m-portlet__head-tools">
<ul class="m-portlet__nav">
<li class="m-portlet__nav-item">
<a href="" class="m-portlet__nav-link m-portlet__nav-link--icon">
<i class="fa fa-microphone-slash text-danger"></i>
</a>
<a href="" class="m-portlet__nav-link m-portlet__nav-link--icon">
<i class="fa fa-refresh"></i>
</a>
</li>
</ul>
</div>
</div>
<div class="m-portlet__body">
<div id="publisher"></div>
</div>
</div>
</div>
Use appendChild, and it will move the source element to a target element, e.g.
target_element.appendChild(source_element)
As commented, to apply different CSS style, do like this and the source_element will automatically change when inside the target_element
source_element {...}
target_element source_element {...}
If you can use jQuery, you can use the method append():
$(<OUTER_SELECTOR>).append($(<INNER_SELECTOR>));

'Show More' & 'Show Less' with jQuery for an article website

I am trying to show an extra row of articles when user clicks 'show more' and I want to remove that row with 'show less'.
I have 4 rows of articles, but I want to start with 2 rows and have the user add one row at a time.
My jQuery might be a little messed up because I took bits and pieces from different places.
I simplified the code by removing the content.
Any idea why it's not working?
<div class="writing-clips">
<div class="row">
<h2>Writing Clips</h2>
</div>
<div class="row clip-container li">
<div class="col span-1-of-4 box" id="story-1" href="#">
<a href="#">
content
</a>
</div>
<div class="col span-1-of-4 box" id="story-2">
<a href="#">
content
</a>
</div>
</div>
<div class="row clip-container clips-2 li">
<div class="col span-1-of-4 box" id="story-5" href="#">
<a href="#">
content
</a>
</div>
<div class="col span-1-of-4 box" id="story-6" href="#">
<a href="#">
content
</a>
</div>
</div>
<div class="row clip-container clips-3 li">
<div class="col span-1-of-4 box" id="story-9" href="#">
<a href="#">
content
</a>
</div>
<div class="col span-1-of-4 box" id="story-10" href="#">
<a href="#">
content
</a>
</div>
</div>
<div class="row clip-container clips-4 li">
<div class="col span-1-of-4 box" id="story-13" href="#">
<a href="#">
content
</a>
</div>
<div class="col span-1-of-4 box" id="story-14" href="#">
<a href="#">
content
</a>
</div>
</div>
</section>
<div class="showmore">showmore</div>
<div class="showless">showless</div>
jquery:
$(document).ready(function(){
size_li = $(".writing-clips .li").size();
x=2;
$('.writing-clips .li:lt('+x+')').show();
$('.showmore').click(function () {
x= (x+1 <= size_li) ? x+1 : size_li;
$('.writing-clips .li:lt('+x+')').show();
});
$('.showless').click(function () {
x=(x-1<2) ? 2 : x-1;
$('.writing-clips .li').not(':lt('+x+')').hide();
});
});
css:
.writing-clips .li { display: none; }
.showmore {
cursor: pointer;
color: green;
}
.showmore:hover { color: blue; }
.showless {
color: red;
cursor: pointer;
}
.showless:hover { color: blue; }
You need to hide all rows before show first two
Add this line
$('.writing-clips .li').hide();
before
$('.writing-clips .li:lt('+x+')').show();
I've re-written your script...
The this is to perform the correct comparison and increment a counter which represent how many are actually shown.
See console logs and comments in code.
$(document).ready(function(){
// Show first four.
var shownOnload = 4;
for(i=0;i<shownOnload;i++){
$(".col").eq(i).show();
}
// Total link we have
var size_li = $(".col").length;
console.log( " Total: " +size_li );
// More handler
$(".showmore").click(function () {
console.log("More clicked!");
if(shownOnload<size_li && shownOnload>=0){
shownOnload++;
console.log("Show #"+shownOnload);
$(".col").eq(shownOnload-1).show();
}
});
// Less handler
$(".showless").click(function () {
console.log("Less clicked!");
if(shownOnload<=size_li && shownOnload>0){
console.log("Hide #"+shownOnload);
$(".col").eq(shownOnload-1).hide();
shownOnload--;
}
});
}); // ready
.col{
display:none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="writing-clips">
<div class="row">
<h2>Writing Clips</h2>
</div>
<div class="row clip-container li">
<div class="col span-1-of-4 box" id="story-1" href="#">
<a href="#">
content 1
</a>
</div>
<div class="col span-1-of-4 box" id="story-2">
<a href="#">
content 2
</a>
</div>
</div>
<div class="row clip-container clips-2 li">
<div class="col span-1-of-4 box" id="story-5" href="#">
<a href="#">
content 3
</a>
</div>
<div class="col span-1-of-4 box" id="story-6" href="#">
<a href="#">
content 4
</a>
</div>
</div>
<div class="row clip-container clips-3 li">
<div class="col span-1-of-4 box" id="story-9" href="#">
<a href="#">
content 5
</a>
</div>
<div class="col span-1-of-4 box" id="story-10" href="#">
<a href="#">
content 6
</a>
</div>
</div>
<div class="row clip-container clips-4 li">
<div class="col span-1-of-4 box" id="story-13" href="#">
<a href="#">
content 7
</a>
</div>
<div class="col span-1-of-4 box" id="story-14" href="#">
<a href="#">
content 8
</a>
</div>
</div>
</section>
<div class="showmore">showmore</div>
<div class="showless">showless</div>

Categories

Resources