Only fire a function once on scroll - javascript

So, I'd like to fire a function only once on scroll.
The problem is that I don't get to fire the function only once. I've tried different solutions ( .on(), setting a counter, setting it outside/inside the window.scrollstop function) but nothing worked.
It does work... but it works whenever I scroll! :(
I don't think it's difficult, but.. I didn't get to make it work so far.
here's my code:
$(window).scroll(function(){
$('.sr-icons').toggleClass('scrolled', $(this).scrollTop() > 950);
});
CSS:
.sr-icons.scrolled {
opacity: 0.2;
}
and HTML:
<div class="container">
<div class="row">
<div class="col-lg-3 col-md-6 text-center">
<div class="mt-5 mx-auto">
<i class="fa fa-4x fa-superpowers text-primary mb-3 sr-icons"></i>
<h3 class="mb-3 text-dark">Sturdy Templates</h3>
<p class="text-muted mb-0">Our templates are updated regularly so they don't break.</p>
</div>
</div>
<div class="col-lg-3 col-md-6 text-center">
<div class="mt-5 mx-auto">
<i class="fa fa-4x fa-paper-plane text-primary mb-3 sr-icons"></i>
<h3 class="mb-3 text-dark">Ready to Ship</h3>
<p class="text-muted mb-0">You can use this theme as is, or you can make changes!</p>
</div>
</div>
<div class="col-lg-3 col-md-6 text-center">
<div class="mt-5 mx-auto">
<i class="fa fa-4x fa-newspaper-o text-primary mb-3 sr-icons"></i>
<h3 class="mb-3 text-dark">Up to Date</h3>
<p class="text-muted mb-0">We update dependencies to keep things fresh.</p>
</div>
</div>
<div class="col-lg-3 col-md-6 text-center">
<div class="mt-5 mx-auto">
<i class="fa fa-4x fa-cog fa-spin text-primary mb-3 sr-icons"></i>
<h3 class="mb-3 text-dark">I Work For You</h3>
<p class="text-muted mb-0">Just think about any website you want to have, I will make that a reality.</p>
</div>
</div>
</div>
</div>

If I understood you, you can do something like :
$(window).on('scroll', function(){
if($(this).scrollTop() > 950) {
$('.sr-icons').toggleClass('scrolled', true);
$(window).off('scroll');
}
});
As said in other comments, you should check wether you want $(this).scrollTop() > 950 or $(this).scrollTop() < 950
Edit : A more proper solution would be to remove only that specific handler, so you can attach other events on scroll if you ever want to :
var handler = function(){
if($(this).scrollTop() > 950) {
$('.sr-icons').toggleClass('scrolled', true);
$(window).off('scroll', handler);
}
}
$(window).on('scroll', handler);

You can use a flag variable, initially 0, then increment on scroll.
Then you can add check as
var flag=0;
$(window).scroll(function(){
if(flag==0){
$('.sr-icons').toggleClass('scrolled', $(this).scrollTop() > 950);
flag++;
}
});

Related

js is not working when i am putting the bootstrap card in the form

When I am putting the whole card into the form tag in HTML then the js is not working please give me a solution. I want to put form because the enter key of the keyboard is not working. and I want that to work, and in future, i want to save the conversation into the database model , the backend is made up of Django.
here is my html:
<section>
<div class="container py-5">
<div class="row d-flex justify-content-center">
<form>
<div class="card">
<div class="card-header d-flex justify-content-between align-items-center p-3"
style="border-top: 4px solid blue; background-color:#3792cd;" >
<h5 class="mb-0" style="text-align:center; color:white;">Your chatbot is here!
</h5>
<div class="d-flex flex-row align-items-center">
<i class="fa fa-minus me-3 text-muted fa-xs"></i>
<i class="fa fa-comments me-3 text-muted fa-xs"></i>
<i class="fa fa-times text-muted fa-xs"></i>
</div>
</div>
<div class="card-body" data-mdb-perfect-scrollbar="true" style="height: 440px;
overflow-y:auto">
<h5>Let's Chat<img style=""></h5>
<div id="chatbot">
</div>
</div>
<div class="card-footer text-muted d-flex justify-content-start align-items-
center p-3" style="text-align:center; background-color:#3792cd">
<div class="input-group mb-0">
<input type="text" class="form-control" id="textInput" name="userMessage"
placeholder="Type message"
aria-label="Recipient's username" aria-describedby="button-addon2" />
<button type="submit" id="buttonInput" style="padding-top: .55rem;">
Send<i class="fa fa-send" style="padding-left: 0.5em;"></i>
</button>
</div>
</div>
</div>
</form>
</div>
</div>
<section>
</form>
Here is my Java scripts:
function getUserResponse(){
var userText = $('#textInput').val();
var userHTML = "<div class='userhtml'><div class='img'><img style='width:36px'
src='https://cdn.pixabay.com/photo/2016/11/18/23/38/child-1837375__340.png'/></div><div
class='userText'><span>"+userText+"</span></div></div>";
$('#textInput').val("");
$('#chatbot').append(userHTML);
$.get('/getResponse',{userMessage:userText}).done(function(data){
var returnedMessage = "<br/><div class='bothtml'><img style='width:46px'src=''/><p
class='botText'><span>"+ data +"</span/></p></div>";
$('#chatbot').append(returnedMessage);
})
}
$('#buttonInput').click(function(){getUserResponse();})
if you tell me how to store the conversation into the django model it will be really appriciated too
Thankyou!

Changing the image output based on radio button output

Good day,
I am working on this project of mine but unfortunately I'm not skilled enough yet to fix the following problem I have been trying to solve for some time now. I have a webpage that shows the amount of calories that someone needs to consume to hit their training goals. Based on a 3 options radio input selection I want to show 3 different images on the output page based on the selection they made. This can be weight loss, maintenance or muscle gain.
The code is as following:
Code for the input of the goal:
<!-- Goal -->
<div class="row px-md-5 mrow" id="rowtwo">
<div class="col-12 py-5">
<div class="text-center">
<h2 class="text-primary">2. Wat is je doel?</h2>
</div>
</div>
<div class="col-12 col-md-12">
<ul class="row radio-group-goal d-flex flex-stretch p-0 m-0">
<li class="radio col-md-6 selected d-flex flex-stretch mb-2" data-goal="Afvallen / Lager vetpercentage" style="list-style: none;">
<div class="innerradio d-flex flex-column content shadow-sm rounded p-4 d-flex flex-row bg-white w-100 greenborder">
<h6 class="text-left"><i class="fas fa-check-circle hidebtn text-success mr-1"></i> <i class="fas fa-weight text-primary mr-2"></i> Afvallen / Lager vetpercentage</h6>
<!-- <p class="mb-0 text-left" style="font-size: 12px; line-height: 14px">minder kcal/koolhydraten</p> -->
</div>
</li>
<li class="radio col-md-6 d-flex flex-stretch mb-2" data-goal="Gezonde levensstijl" style="list-style: none;">
<div class="innerradio d-flex flex-column content shadow-sm rounded p-4 d-flex flex-row bg-white w-100">
<h6 class="text-left mb-0"><i class="fas fa-check-circle hidebtn text-success mr-1"></i> <i class="fas fa-carrot text-primary mr-2"></i> Gezonde levensstijl</h6>
<!-- <p class="mb-0 text-left" style="font-size: 12px; line-height: 14px">Gezond</p> -->
</div>
</li>
<li class="radio col-md-6 d-flex flex-stretch mb-2" data-goal="Aankomen / Meer spiermassa" style="list-style: none;">
<div class="innerradio d-flex flex-column content shadow-sm rounded p-4 d-flex flex-row bg-white w-100">
<h6 class="text-left mb-0"><i class="fas fa-check-circle hidebtn text-success mr-1"></i> <i class="fas fa-dumbbell text-primary mr-2"></i> Aankomen / Meer spiermassa</h6>
<!-- <p class="mb-0 text-left" style="font-size: 12px; line-height: 14px">muscle</p> -->
</div>
</li>
</ul>
</div>
Code for the output:
<div class="col-12 col-md-6">
<div class="row">
<div class="col-12 col-md-6 mb-4 d-flex flex-stretch">
<div class="youchoose-box px-4 py-5 d-flex align-items-center justify-content-center flex-column bg-white rounded shadow-sm w-100" style="border:1px solid white;">
<i class="fas fa-trophy text-center text-primary mb-2"></i>
<!-- <p class="mb-0 text-center">Doel</p> -->
<h5 class="text-primary text-center">
<?php echo $_POST['radio-value'];?>
</h5>
</div>
</div>
//The image I want to change based on the radio value:
<div class="container pb-5">
<div class="row">
<div class="col-12 d-flex align-items-center justify-content-center">
<div class="d-flex align-items-center justify-content-center rounded shadow-sm">
<img src="<?php echo home_url();?>/wp-content/uploads/2020/12/Macro-split.png">
</div>
</div>
</div>
</div>
<!-- save values and send to next pages -->
<input type="hidden" id="radio-value" name="radio-value" value="<?php echo $_POST['radio-value']?>" />
I hope you can guide me in the right direction as I am now on the basics of understanding Javascript.
Thank you in advance!
Assuming your value is coming through in $_POST['radio-value'] the basic way to do this would be with an if statement to check if one of the 3 values is set, and then set which image that value corrresponds to:
//The image I want to change based on the radio value:
<?php
$image = 'default.png';
if (isset($_POST['radio-value'])) {
if ($_POST['radio-value'] == 'value for image 1') {
$image = 'value1image.png';
} else if ($_POST['radio-value'] == 'value for image 2') {
$image = 'value2image.png';
} else if ($_POST['radio-value'] == 'value for image 3') {
$image = 'value3image.png';
}
}
?>
Then in your image src:
<img src="<?php echo home_url();?>/wp-content/uploads/2020/12/<?php echo $image;?>">

setTimeout function on a <div>

I am working on my own portfolio and I want to put a delay between 2 pages with a setTimeout function. I've tried some ways but haven't worked yet. I am already using a function to open my "href" with all my box but now I just want to put a delay to go from accueil.html to presentation.html.
"accueil.html":
document.addEventListener('DOMContentLoaded', function()
{
var items = document.querySelectorAll('.ouverture');
for (var i = 0; i < items.length; i++)
{
var item = items[i];
item.addEventListener('click', function()
{
var url = this.getElementsByTagName('a');
url = url[0];
window.location = url;
});
}
});
<div class="box">
<div class="container">
<div class="row">
<div class="col-lg-4 col-md-4 col-sm-4 col-xs-12">
<div class="box-part text-center ouverture">
<i class="fa fa-address-book fa-3x" aria-hidden="true"></i>
<div class="title">
<h4>Présentation</h4>
</div>
</div>
</div>
</div>
</div>
</div>
Just add a timeout add the part where you redirect to another page:
item.addEventListener('click', function() {
var url = this.getElementsByTagName('a');
if(url.length > 0)
url = url[0];
setTimeOut(() => {
window.location = url;
}, 2000); // 2000 = 2000ms === 2sec
});
More info is found here
A general-purpose snippet that "delays" clicks. Just add the script at the top of the page and use the delay-click[=numberOfMilliseconds] attribute.
document.body.addEventListener("click", function(event) {
var target = event.target;
var currentTarget = target.closest("[delay-click]:not(.delay-click-ignore)");
if (!currentTarget) return;
var delay = +currentTarget.getAttribute("delay") || 2000;
currentTarget.classList.add("delay-click-ignore");
setTimeout(function() {
target.click();
currentTarget.classList.remove("delay-click-ignore");
}, delay);
event.preventDefault();
});
.delay-click-ignore,
.delay-click-ignore a,
.delay-click-ignore input,
.delay-click-ignore button {
cursor: progress !important;
}
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<div class="box">
<div class="container">
<div class="row">
<div class="col-lg-4 col-md-4 col-sm-4 col-xs-12">
<div class="box-part text-center ouverture">
<i class="fa fa-address-book fa-3x" aria-hidden="true"></i>
<div class="title">
<!-- on the element itself -->
<h4><a href="presentation.html" delay-click>default delay</a></h4>
</div>
</div>
</div>
<div class="col-lg-4 col-md-4 col-sm-4 col-xs-12">
<!-- or somewhere up the ranks -->
<div class="box-part text-center ouverture" delay-click=5000>
<i class="fa fa-address-book fa-3x" aria-hidden="true"></i>
<div class="title">
<h4>delay 5s</h4>
</div>
</div>
</div>
<div class="col-lg-4 col-md-4 col-sm-4 col-xs-12">
<div class="box-part text-center ouverture">
<i class="fa fa-address-book fa-3x" aria-hidden="true"></i>
<div class="title">
<h4>immediate</h4>
</div>
</div>
</div>
</div>
<div class="form-group">
<!-- works here too -->
<input type="checkbox" class="form-control" delay-click />
</div>
</div>
</div>

Scroll top on multiple elements

I have an accordion from Bootstrap 4 where I want when I click any of the accordion's tabs the page scrolls to its section.
$('.toggling-tabs').on('click', function () {
if ($('.sections').hasClass('collapsing')) {
$('html, body').animate({
scrollTop: $('.sections').offset().top
},
'slow');
}
});
I got this jQuery snippet where it works with only one of the tabs of the accordion. .toggling-tabs is the class for the accordion tabs and .sections is the class for the sections where when pressing any tab the page should scroll to.
How can I make the code work for all the tabs when any is clicked either using JS or jQuery.
Update:
<div class="col-lg-3 col-md-6 col-sm-12 toggling-tabs">
<div class="port-item p-4 bg-primary" data-toggle="collapse" data-target="#home">
<i class="fa fa-home d-block pb-2"></i> Home
</div>
</div>
<!-- Some stuff in between -->
<section class="collapse show sections" id="home">
<div class="card card-body bg-primary text-white py-5 banner">
<h2>Welcome to my portfolio</h2>
</div>
</section>
<section class="collapse collapsing sections" id="resume">
<div class="card card-body bg-success text-white py-5">
<h2>My Resume</h2>
</div>
</section>
Assuming you use the data-target attribute on the .toggling-tabs items, you can obtain the target in the event handler via $(this).data('target'). Than you can scroll to the element by id.
Now, to make the toggling working as expected, do it via javascript and remove the data-toggle attributes from the tags. Below is a working example.
$('.toggling-tabs [data-target]').on('click', function(event) {
var target = $(this).data('target');
$('.collapse:not(' + target + ')').collapse('hide');
$(target).collapse('show');
$('html, body').animate({
scrollTop: $(target).offset().top
}, 'slow');
});
#placeholder {
height: 150vh;
background-color: light-grey;
}
<div class="container">
<div class="row">
<div class="col-lg-3 col-md-6 col-sm-12 toggling-tabs">
<div class="port-item p-4 bg-primary" data-target="#home">
<i class="fa fa-home d-block pb-2"></i> Home
</div>
</div>
<div class="col-lg-3 col-md-6 col-sm-12 toggling-tabs">
<div class="port-item p-4 bg-success" data-target="#resume">
<i class="fa fa-home d-block pb-2"></i> Resume
</div>
</div>
</div>
</div>
<div id="placeholder">
</div>
<section class="collapse sections" id="home">
<div class="card card-body bg-primary text-white py-5 banner">
<h2>Welcome to my portfolio</h2>
</div>
</section>
<section class="collapse sections" id="resume">
<div class="card card-body bg-success text-white py-5">
<h2>My Resume</h2>
</div>
</section>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.3/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.3/js/bootstrap.min.js"></script>
$('.toggling-tabs').on('click', function () {
$('html, body').animate({
scrollTop: $('.sections').offset().top
},
'slow');
});
in your code it checks whether it has class collapsing i removed that so now it will work for all class section

Hide divs on click - multiple boxes

I have a bit long info submission form. I have an option that someone click "add another", there is a notification box display with text like "Success!" like that with close button. Please check this image.
Therefore I have three "add another" buttons and three success alerts. When someone click close, that alert message needs to be disappear.
The problem
I used javascript for that success box. It does these things.
Click "Add another" button, appears success box. Click close button on
success box, box disappears.
Here is my code.
document.querySelector(".add-box").addEventListener("click", function() {
document.querySelector(".add-box-wrap").style.display = "inline-block";
});
document.querySelector(".add-box1").addEventListener("click", function() {
document.querySelector(".add-box-wrap1").style.display = "inline-block";
});
document.querySelector(".add-box2").addEventListener("click", function() {
document.querySelector(".add-box-wrap2").style.display = "inline-block";
});
$(".claim-btn-close").click(function() {
$(".add-box-wrap").hide();
});
$(".claim-btn-close1").click(function() {
$(".add-box-wrap1").hide();
});
$(".claim-btn-close2").click(function() {
$(".add-box-wrap2").hide();
});
<!-- This goes end of html page -->
function hide(target) {
document.getElementsByClassName(target).style.display = 'none';
};
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!--Success form-->
<div class="add-box-wrap">
<div class="claim-btn-close" onclick="hide('.claim-btn-close')">
<i class="fa fa-times" aria-hidden="true"></i>
</div>
Success!
</div>
<!--Add another button -->
<div class="col-lg-10 col-md-10 col-sm-12 no-padding">
<a class="add-box">Add another<i class="fa fa-plus"></i></a>
</div>
See.. there is a major problem with code repeating. (I didn't repeat html codes, just post here one example) I would like to know the best practice to achieve things like this.
For displaying the notification box without repeating the code, one of the way is you could make use of data attributes. Change the data attribute for all the buttons and let the class .add-box be the same. like so:
<div class="add-box-wrap1" style="display: none;">
<div class="claim-btn-close">
<i class="fa fa-times" aria-hidden="true"></i>
</div>
Success!
</div>
<div class="add-box-wrap2" style="display: none;">
<div class="claim-btn-close">
<i class="fa fa-times" aria-hidden="true"></i>
</div>
Success!
</div>
<!--Add another button -->
<div class="col-lg-10 col-md-10 col-sm-12 no-padding">
<a class="add-box" data-target="1">Add another<i class="fa fa-plus"></i></a>
</div>
<!--Add another button -->
<div class="col-lg-10 col-md-10 col-sm-12 no-padding">
<a class="add-box" data-target="2">Add another<i class="fa fa-plus"></i></a>
</div>
And change your Jquery to just one function.
$(".add-box").click(function() {
$(".add-box-wrap" + $(this).data('target')).show(); //.add-box-wrap1 or .add-box-wrap2
});
Explanation of the above line: It just means we are getting the value of the "clicked" button's data-target value(which is 1 or 2) AND appending that value to the "add-box-wrap"(which will be add-box-wrap1 or add-box-wrap2) to search for that element to display it using .show().
Using show() or .css jquery functions is upto you. But I suggest not to mix both vanilla JS and JQuery codes(like in your question).
Closing
You can simply use closest or parent, like so:
$(".claim-btn-close").click(function(){
$(this).parent().hide();
});
$(".add-box").click(function() {
$(".add-box-wrap" + $(this).data('target')).show();
});
$(".claim-btn-close").click(function(){
$(this).parent().hide();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="add-box-wrap1" style="display: none;">
<div class="claim-btn-close">
<i class="fa fa-times" aria-hidden="true"></i>
</div>
Success!
</div>
<div class="add-box-wrap2" style="display: none;">
<div class="claim-btn-close">
<i class="fa fa-times" aria-hidden="true"></i>
</div>
Success!
</div>
<!--Add another button -->
<div class="col-lg-10 col-md-10 col-sm-12 no-padding">
<a class="add-box" data-target="1">Add another<i class="fa fa-plus"></i></a>
</div>
<!--Add another button -->
<div class="col-lg-10 col-md-10 col-sm-12 no-padding">
<a class="add-box" data-target="2">Add another<i class="fa fa-plus"></i></a>
</div>
Update on another question(3 column):
Using bootstrap, you can wrap the add-box-wrap divs within a .row and give each of it a class like col-*-4(class="col-xs-4 col-md-4 col-lg-4") assuming you have 3 success buttons(12/3 = 4). So the first part of your html would become
<div class="row">
<div class="add-box-wrap1 col-md-4 col-lg-4" style="display: none;">
<div class="claim-btn-close">
<i class="fa fa-times" aria-hidden="true"></i>
</div>
Success!
</div>
<div class="add-box-wrap2 col-md-4 col-lg-4" style="display: none;">
<div class="claim-btn-close">
<i class="fa fa-times" aria-hidden="true"></i>
</div>
Success!
</div>
<div class="add-box-wrap3 col-md-4 col-lg-4" style="display: none;">
<div class="claim-btn-close">
<i class="fa fa-times" aria-hidden="true"></i>
</div>
Success!
</div>
</div>
You can use DOM relationship to target the desired element. Bind event handlers using a common class then use .closest() to traverse up desired element.
$(".claim-btn-close").click(function(){
$(this).closest(".add-box-wrap").hide();
});
If element are dynamically generate use Event Delegation approach.
$(staticParentElemet).on('click',".claim-btn-close",function(){
$(this).closest(".add-box-wrap").hide();
});

Categories

Resources