On entering section (#stake-section) on scroll, I want each letter of the word "STAKE"
to animate like this (See Pic). basically here, I want to change individual letter colors.
<section id="stake-section" class="stake bgColor2">
<div class="container h-100 p-0">
<div class="row h-100">
<div class="col-lg-12 text-center">
<p id="stake">
<span class="active_s">S</span>
<span class="active_t">T</span>
<span class="active_a">A</span>
<span class="active_k">K</span>
<span class="active_e">E</span>
</p>
</div>
</div>
</div>
</section>
You have to use Javascript for this requirement. I would use the wheel as event trigger. Then you can work with the classList function. It is important that you define partial areas here when the next letter is to be manipulated. Now you can add your style and work on the IF conditions.
use this example in the full page view
const el = document.querySelector('.w');
const spans = document.querySelectorAll('#stake span');
let counter = 0;
el.addEventListener("wheel", ev => {
/* code here */
const direction_1 = ev.deltaY;
spans.forEach(i => {
if (direction_1 < 0) {
console.log('scrolling up');
counter = counter - 1;
if (counter < 40) {
document.querySelector('#stake span:nth-child(5)').classList.remove('boom')
}
if (counter < 30) {
document.querySelector('#stake span:nth-child(4)').classList.remove('boom')
}
if (counter < 20) {
document.querySelector('#stake span:nth-child(3)').classList.remove('boom')
}
if (counter < 10) {
document.querySelector('#stake span:nth-child(2)').classList.remove('boom')
}
if (counter < 1) {
document.querySelector('#stake span:nth-child(1)').classList.remove('boom')
}
} else {
counter = counter + 1;
if (! i.classList.contains('boom')) {
if (counter > 1) {
document.querySelector('#stake span:nth-child(1)').classList.add('boom')
}
if (counter > 10) {
document.querySelector('#stake span:nth-child(2)').classList.add('boom')
}
if (counter > 20) {
document.querySelector('#stake span:nth-child(3)').classList.add('boom')
}
if (counter > 30) {
document.querySelector('#stake span:nth-child(4)').classList.add('boom')
}
if (counter > 40) {
document.querySelector('#stake span:nth-child(5)').classList.add('boom')
}
}
}
console.log(counter);
//i.classList.toggle('boom');
})
})
.w {
background: gray;
height:120px;
overflow:scroll;
overflow-x:hidden;
text-align:center;
}
.w span {
font-size:40px;
font-weight: bold;
}
.boom {
color: red
}
<div class="w">
<section id="stake-section" class="stake bgColor2">
<div class="container h-100 p-0">
<div class="row h-100">
<div class="col-lg-12 text-center">
<p id="stake">
<span class="active_s">S</span>
<span class="active_t">T</span>
<span class="active_a">A</span>
<span class="active_k">K</span>
<span class="active_e">E</span>
</p>
</div>
</div>
</div>
</section>
</div>
You could have a common class to apply standard styling to the letters, and unique classes for each of the letters for individually customized styles.
<span class="active s">S</span>
<span class="active t">T</span>
The class .active would allow you to apply common styling to all the letters.
While .s would allow you to apply some styling to the letter S only and so on.
Related
I want to append a <br> after a <div>.
My code
function generatescene() {
for (i = 1; i < 101; i++) {
$('#fightarea').append('<div class=\'block block' + i + '\'><img src=block.png></div>');
if (i % 5) { } else {
if (i % 5 == 0) {
console.log('.block' + i + ' img');
$('.block' + i).after('<br>');
}
}
}
$('.block').wrapAll('<div class=\'scene\'></div>');
}
I have this result
<div>
<div class="scene">
<div class="block block1"><img src="block.png"></div>
<div class="block block2"><img src="block.png"></div>
<div class="block block3"><img src="block.png"></div>
<div class="block block4"><img src="block.png"></div>
<div class="block block5"><img src="block.png"></div>
<div class="block block6"><img src="block.png"></div>
<div class="block block7"><img src="block.png"></div>
<div class="block block8"><img src="block.png"></div>
<div class="block block9"><img src="block.png"></div>
<div class="block block10"><img src="block.png"></div>
<!-- ... -->
</div><br><br><br><br><br><br><br><br><br><br><br><br><br>
<br><br><br><br><br><br><br>
</div>
The <br> append after the div.scene but I want the <br> append after the "div.block" + i.
The issue is this line:
$('.block').wrapAll('<div class=\'scene\'></div>');
which, as stated in the jquery wrapAll doc does:
The structure will be wrapped around all of the elements in the set of matched elements, as a single group.
so it takes all the .block elements that are siblings and creates a single group, thus moving your <br/>s to outside the .scene div.
function generatescene() {
for (i = 1; i < 100; i++) {
$('#fightarea').append('<div class=\'block block' + i + '\'><img src=block.png></div>');
if (i % 5) { } else {
if (i % 5 == 0) {
console.log('.block' + i + ' img');
$('.block' + i).after('<br>');
}
}
}
//$('.block').wrapAll('<div class=\'scene\'></div>');
}
generatescene();
$("#btn").click(function() {
$('.block').wrapAll('<div class=\'scene\'></div>');
});
.block { float:left; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id="btn">wrap all </button>
<hr/>
<div id='fightarea'>
</div>
It's not clear exactly what you're trying to achieve, perhaps adding the .scene div first and then inserting the blocks inside that?
function generatescene() {
var scene = $('<div class=\'scene\'></div>').appendTo("#fightarea");
for (i = 1; i < 100; i++) {
scene.append('<div class=\'block block' + i + '\'><img src=block.png></div>');
if (i % 5) { } else {
if (i % 5 == 0) {
console.log('.block' + i + ' img');
$('.block' + i).after('<br>');
}
}
}
}
generatescene();
.block { float:left; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id='fightarea'>
</div>
You could use
$('.block' + i).append('<br>');
instead of
$('.block' + i).after('<br>');
Explanation:
When you are using .after() you put the element after the element
Ex.
$('.a').after($('.c'));
will result in
<div class='a'>
<div class='b'>b</div>
</div>
<div class='c'>c</div>
but on the other hand when using .append()
$('.a').append($('.c'));
to
<div class='a'>
<div class='b'>b</div>
<div class='c'>c</div>
</div>
Hope that helped!
Try the following code:
function generatescene() {
for (i = 1; i < 101; i++) {
var sthtm ='<div class=\'block block' + i + '\'><img src=block.png></div>';
if(i==0) shtm ='<div class=\'scene\'>'+shtm;
if ((i % 5) == 0) {
sthtm +='<br>';
console.log('.block' + i + ' img');
}
if(i==100) shtm +='</div>';
$('#fightarea').append(sthtm);
}
}
I have a piece of code that adds an event listener to a number of buttons, when the user clicks a button a class is applied to the button container. How can I restrict this so the user can only select a maximum of three buttons. The code below is working to a point, when you get to three you cannot deselect. Can anyone help me achieve
var blocks = document.querySelectorAll(".block");
var btn = document.querySelectorAll("button");
var total = 0;
for (let i = 0; i < btn.length; i++) {
btn[i].addEventListener("click", function() {
if (total < 3 && blocks[i].classList.contains("active")) {
blocks[i].classList.remove("active");
total--;
} else if (total < 3 && !blocks[i].classList.contains("active")) {
blocks[i].classList.add("active");
total++;
}
});
}
.container{
display:flex;
}
.block{
padding: 50px;
border:1px solid;
max-width:
}
.block.active{
background:grey;
}
<div class="container">
<div class="block">
<button>click</button>
</div>
<div class="block">
<button>click</button>
</div>
<div class="block">
<button>click</button>
</div>
<div class="block">
<button>click</button>
</div>
</div>
this.
You simply need to remove this condition total < 3 && from your first if. The number of selected items is irrelevant if the element is already selected. You just want to de-select it.
var blocks = document.querySelectorAll(".block");
var btn = document.querySelectorAll("button");
var total = 0;
for (let i = 0; i < btn.length; i++) {
btn[i].addEventListener("click", function() {
if (blocks[i].classList.contains("active")) {
blocks[i].classList.remove("active");
total--;
} else if (total < 3 && !blocks[i].classList.contains("active")) {
blocks[i].classList.add("active");
total++;
}
});
}
.container{
display:flex;
}
.block{
padding: 50px;
border:1px solid;
max-width:
}
.block.active{
background:grey;
}
<div class="container">
<div class="block">
<button>click</button>
</div>
<div class="block">
<button>click</button>
</div>
<div class="block">
<button>click</button>
</div>
<div class="block">
<button>click</button>
</div>
</div>
I have a JavaScript .each() function which check the value of my div tag and toggle a css class. I am just checking the value fetched from my db and giving the a particular color.
$(".c").each(function() {
if ($(this).text() < 4) {
$(".col").toggleClass("yellow");
} else if ($(this).text() >= 4 && $(this).text() <=6) {
$(".col").toggleClass("orange");
} else if ($(this).text() >= 6 && $(this).text() <=10) {
$(".col").toggleClass("red");
}
});
The problem is when I ran the code only the last else if which is the toggleClass("red') runs. And I am only getting one color which in this case is red displayed,don't know why.
My HTML is looped in a php foreach loop:
<div class="col">
<h4 class="c">'.$marks.'</h4>
<h6>Marks</h6>
</div>
<div class="col">
<h4 class="c">'.$highest.'</h4>
<h6>Highest</h6>
</div>
Like thhe above image I was looking to put my text and number in a same color
Your code sets the class on all the .col elements. to isolate just the one you are matching, you need to use .closest() to look for the closest ancestor that matches your criteria.
$(".c").each(function() {
if($(this).text() < 4){
$(this).closest($(".col")).toggleClass("yellow");
} else if ($(this).text() >= 4 && $(this).text() <=6){
$(this).closest($(".col")).toggleClass("orange");
} else if ($(this).text() >= 6 && $(this).text() <=10){
$(this).closest($(".col")).toggleClass("red");
}
});
.col { width: 5em; text-align:center; padding:1em; margin:5px; float:left; }
.yellow { background-color:yellow; }
.orange { background-color:orange; }
.red { background-color:red; }
h4, h6 { margin:0; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="col">
<h4 class="c">4</h4>
<h6>Marks</h6>
</div>
<div class="col">
<h4 class="c">7</h4>
<h6>Highest</h6>
</div>
<div class="col">
<h4 class="c">2</h4>
<h6>Highest</h6>
</div>
You are setting all .col elements. Change to this:
$(".c").each(function() {
if($(this).text() < 4){
$(this).parent().toggleClass("blue");
} else if ($(this).text() >= 4 && $(this).text() <=6) {
$(this).parent().toggleClass("orange");
} else if ($(this).text() >= 6 && $(this).text() <=10) {
$(this).parent().toggleClass("red");
}
});
.red {
color: red;
}
.blue {
color: blue;
}
.orange {
color: orange;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="col">
<h4 class="c">2</h4>
<h6>Marks</h6>
</div>
<div class="col">
<h4 class="c">5</h4>
<h6>Highest</h6>
</div>
I used blue color so to make the difference more visible.
Try the below script:
$("div.col h4.c").each(function() {
if($(this).text() < 4){
$("div.col").toggleClass("yellow");
}
else if ($(this).text() >= 4 && $(this).text() <=6){
$("div.col").toggleClass("orange");
}
else if ($(this).text() >= 6 && $(this).text() <=10){
$("div.col").toggleClass("red");
}
});
I want to write a dynamic function for an element with several pages. At time just one page is visible and with a click on the forward or backward button the next or previous page is shown.
I have several of these elements with different amount of pages.
function pageTurn(forwardID, backwardID, pageClass, counter, numbers) {
var forward = document.getElementById(forwardID);
var backward = document.getElementById(backwardID);
var page = document.getElementsByClassName(pageClass);
var count = document.getElementById(counter);
var pageCount = 1;
forward.addEventListener('click', function() {
pageCount ++;
count.innerHTML = pageCount + ' / ' + numbers;
page[pageCount - 2].classList.add('invisible')
page[pageCount - 2].addEventListener("transitionend", OnTransitionEnd());
buttonCheck();
})
backward.addEventListener('click', function() {
pageCount --;
count.innerHTML = pageCount + ' / ' + numbers;
page[pageCount].classList.add('invisible')
page[pageCount].addEventListener("transitionend", OnTransitionEnd());
buttonCheck();
})
function buttonCheck() {
//SHOW AND HIDE PAGETURN BUTTONS
if(pageCount == 1) {
backward.classList.add('invisible');
} else if (pageCount > 1) {
backward.classList.remove('invisible');
} else if (pageCount == numbers) {
forward.classList.add('invisible');
} else if (pageCount < numbers) {
forward.classList.remove('invisible');
}
}
function OnTransitionEnd() {
page[pageCount - 1].classList.remove('invisible');
}
}
Same logic for the backwards button, just reversed.
I want the function to add value of 1 to the pageCount on a click on the forward button. To dynamicly add and remove the .invisible class from the page element i want to use the pageCount variable to choose the right page out of the class array. But it doesn't work.
What am i doing wrong here?
https://jsfiddle.net/1qt8p9of/12/
There are quite a few things to consider here: I think you'd be better of posting on codereview.stackexchange.com.
However, here's a snippet where I slightly modified the code you provided to make it work. Don't hesitate to take a look!
function initialize(forwardID, backwardID, pageClass) {
const forward = document.getElementById(forwardID);
const backward = document.getElementById(backwardID);
const pages = document.getElementsByClassName(pageClass);
let counter = 0;
function buttonCheck() {
if (counter <= 0) {
backward.setAttribute('disabled', true);
} else {
backward.removeAttribute('disabled');
}
if (counter >= pages.length - 1) {
forward.setAttribute('disabled', true);
} else {
forward.removeAttribute('disabled');
}
}
forward.addEventListener('click', function() {
pages[counter].classList.add('invisible');
counter++;
pages[counter].classList.remove('invisible');
buttonCheck();
});
backward.addEventListener('click', function() {
pages[counter].classList.add('invisible');
counter--;
pages[counter].classList.remove('invisible');
buttonCheck();
});
}
initialize('forwards', 'backwards', 'page');
initialize('forwards2', 'backwards2', 'page2');
.pages .invisible {
display: none;
}
<fieldset>
<legend>First set of page</legend>
<div class="controls">
<button id="backwards" disabled>←</button>
<button id="forwards">→</button>
</div>
<div class="pages">
<div class="page">Page One</div>
<div class="page invisible">Page Two</div>
<div class="page invisible">Page Three</div>
<div class="page invisible">Last Page</div>
</div>
</fieldset>
<hr />
<fieldset>
<legend>Second set of pages</legend>
<div class="controls">
<button id="backwards2" disabled>←</button>
<button id="forwards2">→</button>
</div>
<div class="pages">
<div class="page2">Page One</div>
<div class="page2 invisible">Page Two</div>
<div class="page2 invisible">Page Three</div>
<div class="page2 invisible">Page Four</div>
<div class="page2 invisible">Last Page</div>
</div>
</fieldset>
I hope this will help you.
what i am trying to do is make the first 12 elements hidden and show the next 12 elements.
//this is dynamic loaded content
<div class="inner-content">
<div class="front-pro">1</div>
<div class="front-pro">2</div>
<div class="front-pro">3</div>
<div class="front-pro">4</div>
<div class="front-pro">5</div>
<div class="front-pro">6</div>
<div class="front-pro">7</div>
<div class="front-pro">8</div>
<div class="front-pro">9</div>
<div class="front-pro">10</div>
<div class="front-pro">11</div>
<div class="front-pro">12</div>
<div class="front-pro hidden">13</div>
<div class="front-pro hidden">14</div>
..... etc (200 divs more)
</div>
<div onclick="SearchNext();">next</div>
This is my javascript/jquery:
function SearchNext(){
var first = $('.inner-content').children('.front-pro:hidden:first');
first.prevAll(':lt(12)').hide();
first.nextAll(':lt(12)').show();
}
It works one time, after it stops working. (and it skips number 13)
i want to have 12 new elements visible with each Next click and hide the previous.
UPDATE - this is my end result that works perfectly
JSFIDDLE DEMO
Thanks to Alex Char
PHP for creating page numbers, you could do this also with javascript
//$counter is search results
$x = 1;
$Pnumbers = '';
while($x <= ceil($counter/12)) {
if($x == 1){ $ecl = 'bold'; } else{ $ecl = ''; }
$Pnumbers .= ' <span class="number '.$ecl.' numbering" onClick="GoTo('.$x.');">'.$x.'</span> ';
$x++;
}
if($counter > 12){ echo'<div class="page-numbers">
<span class="prev number" onclick="GoTo(\'prev\')">Prev</span>
'.$Pnumbers.'
<span class="next number" onclick="GoTo(\'next\');">Next</span>
</div>'; }
Javascript:
function GoTo(nn) {
var nng = parseInt($('.page-numbers .numbering.bold').text());
if(nn == 'next'){
nn = nng+1;
}if(nn == 'prev'){
nn = nng-1;
}
//get all child elements with class front-pro
//of element with class .inner-content
var childElems = $(".inner-content .front-pro");
var totalpages = Math.ceil(childElems.length/12);
//iterate through the elements
var first = (nn-1)*12;
var last = first+11;
childElems.each(function(i, el) {
//show the elements that match the criteria removing css class
if (i >= first && i <= last) {
$(el).removeClass('hidden');
} else {
//hide rest
$(el).addClass('hidden');
}
});
if(nn > 1){ $('.page-numbers .prev').show(); }else{ $('.page-numbers .prev').hide(); }
if(nn < totalpages){ $('.page-numbers .next').show(); }else{ $('.page-numbers .next').hide(); }
$('.page-numbers .numbering').removeClass('bold');
$('.page-numbers .numbering:eq('+(nn-1)+')').addClass('bold');
}
CSS:
.front-pro.hidden{ display:none !important; }
.prev { display: none; }
.page-numbers .number{
background: #ff0000; }
.page-numbers{ text-align:center; }
.page-numbers .number.bold{ font-weight:bold; background:#000; }
.page-numbers .number:hover{ background:#000; cursor: pointer; }
Make sure that the first 12 divs do not contain the "hidden" class, all the divs that come after should have "hidden" in there class
I change a bit the implementation to support and previous. I use a css class to hide content.
function searchNext() {
$('.inner-content').children('.front-pro:lt(12)').addClass('hidden');
$('.inner-content').children('.front-pro:gt(11)').removeClass('hidden');
$(".next").hide();
$(".prev").show();
}
function searchPrev() {
$('.inner-content').children('.front-pro:lt(12)').removeClass('hidden');
$('.inner-content').children('.front-pro:gt(11)').addClass('hidden');
$(".next").show();
$(".prev").hide();
}
.front-pro.hidden {
display: none;
}
.prev {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="inner-content">
<div class="front-pro">1</div>
<div class="front-pro">2</div>
<div class="front-pro">3</div>
<div class="front-pro">4</div>
<div class="front-pro">5</div>
<div class="front-pro">6</div>
<div class="front-pro">7</div>
<div class="front-pro">8</div>
<div class="front-pro">9</div>
<div class="front-pro">10</div>
<div class="front-pro">11</div>
<div class="front-pro">12</div>
<div class="front-pro hidden">13</div>
<div class="front-pro hidden">14</div>
</div>
<div class="next" onclick="searchNext();">next</div>
<div class="prev" onclick="searchPrev();">prev</div>
I create a general solution after your comment with next and previous(I use step 3 for demo purposes but you can use what ever you want):
var pager = (function() {
/*declare private variables*/
var first = 0,
last = 2,
step = 3;
function searchNext() {
//next function
//increasing first and last variables
first += step;
last += step;
pagerHelper();
}
function searchPrev() {
//previous function
//decrease first and last variables
first -= step;
last -= step;
pagerHelper();
}
function pagerHelper() {
//get all child elements with class front-pro
//of element with class .inner-content
var childElems = $(".inner-content .front-pro");
//iterate through the elements
childElems.each(function(i, el) {
//show the elements that match the criteria removing css class
if (i >= first && i <= last) {
$(el).removeClass('hidden');
} else {
//hide rest
$(el).addClass('hidden');
}
});
nextPreviousToggle(childElems.length);
}
function nextPreviousToggle(maxEle) {
//here the code is to show/hide next/previous buttons
if (last >= maxEle) {
$(".next").hide();
} else {
$(".next").show();
}
if (first === 0) {
$(".prev").hide();
} else {
$(".prev").show();
}
}
return {
searchNext: searchNext,
searchPrev: searchPrev
}
})();
.front-pro.hidden {
display: none;
}
.prev {
display: none;
}
.prev:hover,
.next:hover {
text-decoration: underline;
cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="inner-content">
<div class="front-pro">1</div>
<div class="front-pro">2</div>
<div class="front-pro">3</div>
<div class="front-pro hidden">4</div>
<div class="front-pro hidden">5</div>
<div class="front-pro hidden">6</div>
<div class="front-pro hidden">7</div>
<div class="front-pro hidden">8</div>
<div class="front-pro hidden">9</div>
<div class="front-pro hidden">10</div>
<div class="front-pro hidden">11</div>
<div class="front-pro hidden">12</div>
<div class="front-pro hidden">13</div>
<div class="front-pro hidden">14</div>
</div>
<span class="next" onclick="pager.searchNext();">next</span>
<span class="prev" onclick="pager.searchPrev();">prev</span>
References
:gt()
:lt()
You use the following code to handle any number of divs,
var x = $(".inner-content div").hide();
$("div:contains(next)").click(function() {
var cnt = $(this).data("cnt") || 0;
if((cnt * 12) > x.length){ cnt = 0; }
x.hide().filter(":eq("+ (cnt * 12) + "), :lt(" + ((cnt * 12) + 12) + "):gt(" + (cnt * 12) + ")").show();
$(this).data("cnt", ++cnt);
});
DEMO
Try this instead
$('.inner-content').children().each(function (i, x) {
if (i < 12) // Hide First 12 i.e 0-11
$(x).addClass('hidden');
else if (i < 24) // Show Next 12 i.e 12-23
$(x).removeClass('hidden');
})
Also make sure you have css rule defined as
.hidden {
display: none;
}