I am using Laravel 6. I have a button which gets triggered when it has been clicked. The click event does two things. It adds a css class to the button which shows an animated svg spinner to indicate that something is loading and it sends information to my controller which sends an e-mail.
The spinner class is set as soon as the button is clicked, but the problem is that the spinner is only shown when the mail has been sent. But I want the spinner to be shown while the gets sent so the user knows that he has to wait.
This is my .spinner class
.spinner {
background-image: url(storage/app/public/img/spinner.svg);
background-size: 100% 100%;
height: 40px;
width: 40px;
}
This is the button from my child component which can be clicked:
<button class="btn btn-success teamplayerButton" #click="addSpinner($event.target); $emit('del-match', match.id);">Add
</button>
The addSpinner method on the child component:
addSpinner(match) {
match.classList.toggle('spinner');
match.innerText = "";
}
The parent component gets the emitted match.id and makes a get request to a route which sends a mail like this:
Mail::to($email)->send(new ReceivedInvitation(Auth::user()->name, $receiverName));
Here is a short video to show you what I mean.
click here
Why does the css depends on what php(laravel) on the backend does?
The css gets set instant but the animation is shown after a few seconds.
When I remove the call of the mail function in my controller, and try it again, the spinner is shown instantly.
It would appear that the CSS changes instantly, but the actual image isn't being loaded until after the AJAX call finishes.
I would check your network tab to understand how the spinner file is being loaded, and see if its being blocked for some reason by the AJAX call. If it isn't just a static file, something else might be going on.
Related
I have been searching for hours about how to do this, trying different things and not succeeding.
All I want to do is make a one-page site that shows/hides divs and does one simple animation. I have already made it do everything I want and look the way I want it to look: When you click a link in my navbar, there is a script that runs that hides one div, shows another, and also changes the size of the header image. This is all done with simple JS and CSS, but the back button doesn't work and the URL does not change even when I make the link a hash anchor. Maybe having all the divs on the index and showing/hiding them isn't even the best way to do this.
The implementation of the HTML5 History API (If I should even be using that) has got me stumpped, and I can't seem to find a simple straightforward working example of this.
Can anyone point me to a fiddle or codepen of something like this working properly?
This is the basics of what I'm doing:
Link:
Work
Function:
function work() {
document.getElementById("work").style.cssText = 'display: block; opacity: 1;'
document.getElementById("about").style.cssText = 'display: none; opacity: 0;'
document.getElementById("hero").style.cssText = 'height: 85px; transition: 200ms ease-in-out;'
document.getElementById("introcontainer").style.cssText = 'visibility: hidden; opacity: 0; transition: visibility 200ms, opacity 200ms linear;';
}
When my "Work" link is clicked, "about" is hidden, "introcontainer" is hidden, height of "hero" is changed, and "work" is displayed. I have two other "pages" and they function the same way.
History API is made just for such scenarios , instead of scanning url hashes and running complex if else you can use pushState to keep track of application state and decide what happens at each state.
The gist of this API is when you push something using pushState it gets returned to you on popState (on hitting back button).
history.pushState(objState,title,Url);
The first argument is where we pass stuff that will help identify application state you can put anything but it has to be enclosed in an object
I will ignore the 2nd one(pass any string). 3rd one is what URL bar would show relative to current path on executing PushState()
Assuming you have nav something like this
<ul id="nav">
<li>About</li>
<li>Contact</li>
<li>Team</li>
</ul>
assign click handlers for pushing state
$('a').click(function(e){
e.preventDefault();
var targetUrl = $(this).attr('href');
history.pushState({url:targetUrl}, targetUrl, targetUrl);
applyState(targetUrl); //will show div associated with this anchor
});
Now when user clicks a link you need to push something related to this say its href or title to identify it later (I've used its href but you are free to use anything) after it gets pushed you may animate and show div associated with this link eg. If I click <a href="work"> then push “work” and show the div that holds your work details(while minimizing/hiding other divs) .Your url reads xyz/work atm
Next if I click <a href="contact"> state for contact gets pushed and same way it's associated div gets highlighted.Your url reads xyz/contact atm
Now when I hit back history will pop and url will change from xyz/contact to xyz/work popping the latest inactive state (wiz. work and not contact!)
If you have assigned handler for onpopstate you can catch the popped content
window.onpopstate = function(e) {
var popie = e.state ? e.state.url : null;
applyState(popie);
}
so popie would be “work” , applyState will do its fancy animation and show work div
applyState might look like
function applyState(url) {
$('#status').text('Current active page ' + url);
switch(url){
case "work": //show work details div hide others
break;
case "about": //show aboutdetails div hide others
break;
}
I have two buttons ("Approve","Unapprove") and an image of a loading spinner. By default the Approve button is showing and the Unapprove button and loading spinner image are hidden.
When the "Approve" button is clicked I want it to disappear, show the loading spinner, and then perform an ajax request. On completion of the request, I want the loading spinner image to get hidden again. If the ajax request was successful, I want the "Unapprove" button to show. If the ajax request failed, I want the "Approve" button to show again.
The problem I have is that upon completion of the ajax request, my .always() method runs but the spinner image does not get hidden. Here is an example:
https://jsfiddle.net/ebme6fjs/7/
If I change the url of my ajax request to give me a 404 not found error, this process works like it's supposed to:
https://jsfiddle.net/ebme6fjs/8/
Does anyone know why in my first case the spinner.toggleClass("hide"); command isn't running in the always() function? Thanks.
UPDATE:
One interesting thing I found is that if I redefine my spinner variable in the .always() function, it works correctly on a succesful ajax request:
https://jsfiddle.net/ebme6fjs/9/
If you modify the ajax url to receive a 404 though, the same problem of the spinner not disappearing happens again.
In a context where you always want to add the class, use addClass, not toggleClass. In your code, the class is toggled twice: Once in "always" and then again in "fail". So it ends up in the same state as before.
The reason you are targeting the image twice, is because you are defining otherButton like this:
var otherButton = currentButton.siblings();
When what you want to do is this:
var otherButton = currentButton.siblings('button');
toggleClass is most useful when you might want to add or remove the class depending on some condition.
In your code, you were toggling hide class on image twice, in always() callback and done()/fail() ones.
This is because you were targeting image in both variables, spinner & otherbutton.
You should define otherbutton as following:
var otherButton = currentButton.siblings("button");
Not including image in matched set.
As a side note, for code readability, you should use addClass()/removeClass() instead as noted in KWeiss answer and btw, set all your logic for displaying/undisplaying elements only in always() callback.
I am trying to show a simple confirmation message of successfully logging out following this but I am not sure how to proceed.
This message is going to appear for 5 seconds, after the user clicks the logout button (which simply does the log out and redirects to the home page).
This confirmation message, along with the logout button is located at the header.
I have the text wrapped in a div, with id="confirmation".
The onClick event on a link calls the informUser function which does this:
$("#confirmation").show();
setTimeout(function() { $("#myElem").hide(); }, 5000);
The css of the div wrapper is this:
#confirmation {
position: absolute;
top: 0;
left: 45%;
text-align: center;
font-size: 1.25em;
}
Now, I needed to hide this element, I tried with visibility: hidden; but the element never showed up.
I tried hiding it using
$(document).ready(function() {
$("#confirmation").hide("slow"); });
and the element showed up for less than a second and then disappeared (due to document.ready being loaded again).
Because you are changing pages (when you redirect to the home page), the javascript that handles an event on the logout button won't do anything to show and hide the message on the home page. Instead, I would try setting a cookie with a somewhat short life span, and letting a separate script on the home page handle the displaying of the message if that cookie is set.
You can see a basic overview of cookies here: http://www.quirksmode.org/js/cookies.html
It's probably just a typo in the post, but I can't leave comments yet, so here's my answer (just in case).
$("#confirmation").show();
setTimeout(function() { $("#myElem").hide(); }, 5000);
should be
$("#confirmation").show();
setTimeout(function() { $("#confirmation").hide(); }, 5000);
My need is very simple. When a user try to log in and submit the login form, i would to display an ajax loader icon (like ones generated at www.ajaxload.info) in foreground with the background transparent and unclickable (like in this site). when the server has finished, it can display the next page or redisplay the old one with the errors.
How can i do that?
Thank you very much in advance.
Using jQuery (which is a great javascript library and has hundreds of uses besides this one)
you can detect the submit event on the form and take some action, like this:
$(function(){
$('#yourFormId').on('submit', function(e){
//stop the form refreshing the page
e.preventDefault();
//serialize the form for submission to the server
var data = $(this).serialize();
//get the url for the form
var url = $(this).attr('action');
//make an ajax request to submit the form, showing the loader and unclickable div
$('#yourAjaxLoader,#unclickableDiv').fadeIn();
$.post(url, data, function(response){
//the request has completed, so fade out the loader and div
$('#yourAjaxLoader,#unclickableDiv').fadeOut();
});
});
});
To acheive the unclickable div, try some css like this:
/*css*/
#unclickableDiv
{
z-index:99999;
width: 100%;
height: 100%;
opacity: 0.5;
background-color: black;
display:none;
}
and put the div just inside the body tag. when it is faded in, it will be 'above' the rest of the page, making it unclickable. just put your ajax loading icon inside this div so it will show up, too.
You can get jQuery from http://jquery.com and I highly recommend using it anyway, even if not for this. Hope this helps
Update:
The new jQuery on() method has effectively replaced .submit and .click etc since version 1.7, so I've updated this example to reflect that. More info here: http://api.jquery.com/on/
You could use JQuery and take a look at Throbber plugin (http://plugins.jquery.com/plugin-tags/throbber):
Provides trivially easy way to notify users that a request is being loaded and processed in the background, so that they know their action was received and the page has not frozen. Just toggle the message (or image or any element) on or off with $.loading() or $('#foo').loading(). The plugin handles creation and positioning and "pulsing" of the message for you. It also provides a 'mask' option to block the UI (at the call level) while the loading message (or image or any element) is running.
I have a button to download an excel file. When the user clicks the button, the onClick function calls
window.location= url
and when the downloading is done, the save as dialog popups with the file.
Now, I want to show a spinner until the file dialog appears. How do I do this?
I tried to create a spinner before "window.location" and hide it after that, but the spinner goes away immediately because window.location does not block until the file downloads.
Any ideas?
Thanks.
This would be a solution which only works for Firefox browsers:
<script type="text/javascript">
//<![CDATA[
function download(url){
document.getElementById('spinner').style.display='';
frame = document.createElement("iframe");
frame.onload=function(){document.getElementById('spinner').style.display='none';}
frame.src=url;
document.body.appendChild(frame);
}
//]]>
</script>
In your HTML, have a spinner set up and ready to go:
<div id="spinner" style="background:url('/images/ico-loading.gif') #000 center no-repeat;opacity:.5;width:100%;height:100%;display:none;position:absolute" />
Then call it using this:
<button type="button" onclick="download('/spreadsheet.xls');">DOWNLOAD SPREADSHEET</button>
The button will call our javascript function with the URL we want to download. At this time we make the hidden spinner DIV visible and allow it take over the screen (note position absolute in style). An IFRAME is created to suck down the file. After the file downloads, it is given to the user and the .ONLOAD event is fired which hides the spinner DIV. All done with client side javascript!
You can't do that using just client script, because there is no event for when the download completes.
You would have to download the file through a proxy page on the server, with a unique identity in the URL so that each download could be identified. Then you could send AJAX requests from the script to the server to determine the status of the download.
This code works for jQuery, but with simple modification also for javascript. With this you won't need to change your requests-codes at all.
Create a div element which contains the animation (either another div element with css-animation or an animated gif in an img element) and give it the id = "loadingicondiv". For example like this
<div id="loadingicondiv">
<div id="loadingicon" style="background:url('imgs/logo.png') center no-repeat;opacity:1.0;display:none;position:absolute;z-index: 9999;"></div></div>
Set the style of that div in your css file as follows
#loadingicondiv{
width: 100vw;
height: 100vh;
background: rgba(0,0,0, 0.3);
position: fixed;
z-index: 9999;
}
In the embeded js file enter this
function showAnimation(){
$('#loadingicondiv').css({display : ''});
};
function hideAnimation(){
$('#loadingicondiv').css({display : 'none'});
};
$(document).ajaxStart(showAnimation).ajaxStop(hideAnimation);
This last line makes, that every request sent by your web application, executes the function "showAnimation" at the beginning and executes the function "hideAnimation", when the request is done.
If you don't use jQuery and need pure javascript, simply replace $('#loadingicondiv') with the following code
document.getElementById('loadingicondiv').style.display = 'none'
Note: In case you have some frequent updating on your website, which you don't want to show that animation for, just make the displaying of the animation dependent from a global variable, which you set to false before sending those special requests, which you don't want the animation to be shown for. And don't forget to set it to true, when the request is done by them.