I'm very new to JavaScript and I'm trying to figure out a way to trigger a keyframe animation if the page is accessed via a link on a menu page.
The code I have come up with so far using document.referrer does not work:
var ref = document.referrer;
if (ref.includes("menu")) {
document.getElementById('symbol').style.animation=' 2s ease-in-out 0s 1 slideLogo';
}
What am I doing wrong? The script is located at the end of <body> and runs nicely when ref is changed to a statement containing the search word.
I'm currently only testing locally, could that be why?
Hard to say what is going wrong without seeing the rest of the code, but the following should work.
Save as landing.html
<style type="text/css">
#symbol {
width: 100px;
height: 100px;
background-color: red;
}
#keyframes slideLogo { from { margin-left: -20%; } to { margin-left: 100%; } }
</style>
<h1>Landing page</h1>
<div id="symbol"></div>
<script>
var ref = document.referrer;
console.log('referrer is', ref);
if (ref.includes("menu")) {
console.log('set the style.animation property');
document.getElementById('symbol').style.animation=' 2s ease-in-out 0s 1 slideLogo';
}
else {
console.log('DO NOT set the style.animation property');
}
</script>
Put a link to landing.html in a file called menu.html. And make sure you're accessing it via something like http://localhost/menu.html
Similarly, put a link to landing.html in a file that will not have "menu" anywhere in the url, e.g.http://localhost/something-else.html. This will not trigger the animation.
So if these 3 files are accessed by their filenames, then the link from http://localhost/menu.html will trigger the animation on http://localhost/landing.html
It's worth noting that your referrer test will look anywhere in the referrer url, so even partial matches like http://localhost/not-a-menu.html will trigger the animation. So you may want to make your test a little more specific if you're worried about this.
Also, for browser compatibility, I think at this point it is still a little safer to use indexOf instead of includes.
if(document.referrer.indexOf('menu') !== -1) { ... }
Related
I am trying to make a kind of template, for a dashboard page, where when a dashboard button is clicked, something is added to the DOM.
I was trying to template this, so that when someone makes a new dashboard for example, he has the option, to specify in CSS an animation that should run on each button when clicked. If an animation is defined on the button, the actual loading of the element should be delayed until the animation completes.
Now, if I actually specify an animation in css, everything works fine, because I am delaying the logical code with a callback on the animations end. My problem is, that I can't achieve the same, when there is no animation set to the element.
What I would want is something simmilar:
function buttonClick($button) {
$button.addClass('activated');
$button.one('animationend', function() {
// ... run the logic here
});
if (...no animation specified in activated class) {
// ... run the logic here
}
}
NOTE: I am using jQuery here, if there is a method specific in jQuery for this, that would also be okay for me, but a plain javascript method would be fine as well. I heard about the jQuery(":animated") selector, but when I was testing it, it seems that it only works for animations started with jQuery itself, and not with CSS3.
As you seem to use animation CSS for your animations (given that you use the animationend event), you could use getComputedStyle to verify the content of the animation-name CSS property.
Here is a demo with two buttons: one triggers an animation on click, while the other doesn't:
$("button").click(function () {
buttonClick($(this));
});
function hasAnimation($button) {
return getComputedStyle($button[0], null)["animation-name"] != "none";
}
function onEndAnimation($button) {
$button.removeClass('activated');
console.log("animation complete on button " + $button.text());
}
function buttonClick($button) {
$button.addClass('activated');
$button.one('animationend', () => onEndAnimation($button));
if (!hasAnimation($button)) onEndAnimation($button);
}
#yes.activated {
animation-duration: 1s;
animation-name: grow;
}
#keyframes grow {
from { width: 50px; }
50% { width: 100px; }
to { width: 50px; }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id="yes" style="width: 50px">Yes</button><br>
<button id = "no" style="width: 50px">No</button>
I am working on an asp.net web form project which has a site.master page as well as other aspx pages that use the site master.
I have a div on the site master as such:
<div id="msg" class="dialog">loading, please wait...</div>
Full context of it (the site master) is as such (note im keeping it simple here):
<body id="pageContainer">
<div id="msg" class="dialog">loading, please wait...</div>
<div id="pageBody">
<form id="formMaster" runat="server">
</form>
</div>
</body>
The class=dialog is defined as such for the div:
.dialog {
display: none;
width: 300px;
height: 300px;
position: absolute;
left: 50%;
top: 50%;
margin-left: -150px;
margin-top: -150px;
}
Basically I use this when I want to display "loading please wait" across requests, and I turn it on / off via jquery:
// Simulate some time before everything's loaded
setTimeout(function () {
$("#msg").fadeOut(function () {
// Wait for #msg to fade out before fading in #pageBody
$("#pageBody").animate({
opacity: "1.0"
}, 1);
});
}, 1);
This is done inside of $(document).ready(). I need to simulate some time and then I make the pageBody div visible (using the opacity property)...This seems to work fine but upon initial say hyperlink clicks / submits that redirect a user to another page the loading doesn't show up right away...it takes quite some time to show up confusing the user.
For instance if I have a simple hyperlinked page (where that page has LOTS of database data)...The initial click of that hyperlink shows the spinning circle (in chromes tab) and then finally takes you to that page. At that point my loading div comes up and finally that fades out and the page is shown. I was hoping instantly my loading div can come up so that the user knows something is happening. Most of our users are not too savvy on the web so they dont even pay attention to the browser spinning wheel, they just think the page is not responding (I dont blame them, this can be tricky).
What can I do so that this loading, please wait... div comes up almost instantaneously? Or even can I ?
Yes you can, using Javascript/jQuery and a begin-end request.
<script type="text/javascript">
Sys.WebForms.PageRequestManager.getInstance().add_beginRequest(beginLoading);
Sys.WebForms.PageRequestManager.getInstance().add_endRequest(endLoading);
function beginLoading(sender, args) {
var LoadingDiv = $find(LoadingDiv);
if (LoadingDiv!= null) {
LoadingDiv.show();
}
}
function endLoading(sender, args) {
var LoadingDiv = $find(LoadingDiv);
if (LoadingDiv != null) {
LoadingDiv.hide();
}
}
I have an element with a transition applied to it. I want to control the transition by adding a class to the element which causes the transition to run. However, if I apply the class too quickly, the transition effect does not take place.
I'm assuming this is because the .shown is placed onto the div during the same event loop as when .foo is placed onto the DOM. This tricks the browser into thinking that it was created with opacity: 1 so no transition is put into place.
I'm wondering if there is an elegant solution to this rather than wrapping my class in a setTimeout.
Here's a snippet:
var foo = $('<div>', {
'class': 'foo'
});
foo.appendTo($('body'));
setTimeout(function(){
foo.addClass('shown');
});
.foo {
opacity: 0;
transition: opacity 5s ease;
width: 200px;
height: 200px;
background-color: red;
}
.foo.shown {
opacity: 1;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Actually, the point is not about the setTimeout, but about how the element is rendered.
The CSS transition will only appear if the element is rendered with a property value, and then this property is changed.
But once you append the element, it does not mean that it was rendered. Simply adding a setTimeout is not enough. Thought it may work for you, in some browser versions it won't work! (Mostly Firefox)
The point is about the element's render time. Instead of setTimeout, you can force a DOM render by requesting a visual style property, and then changing the class:
var foo = $('<div>', {
'class': 'foo'
});
foo.appendTo($('body'));
//Here I request a visual render.
var x = foo[0].clientHeight;
//And it works, without setTimeout
foo.addClass('shown');
.foo {
opacity: 0;
transition: opacity 5s ease;
width: 200px;
height: 200px;
background-color: red;
}
.foo.shown {
opacity: 1;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
When you do DOM manipulation that that javascript relies on immediately afterwards, you need to pause javascript execution briefly in order to allow rendering to catch up, since that will be done asynchronously. All a blank setTimeout does is move the code within to the end of the current execution pipeline. The browser must complete rendering the new layout before it will obey a trigger for your transition so the setTimeout is a good idea and in my opinion the most elegant solution.
I can produce
-webkit-animation-name:mymove;
dynamically with
object.style.animationName="mymove"
but is it possible to generate something like
#keyframes mymove
{
from {left:0px;}
to {left:200px;}
}
dynamically with JS?
Yes, i use Jquery library and then apply like so:
Say in this situation i want the left value to be dynamic from a div with attribute class value = "push"
<!--HTML-->
<div class="push">Wall</div>
//--JS--
var KeyFrame =
{
init: function(){
if(!KeyFrame.check)
{
//get the left position
var pushLeft = $('.push').position().left;
//set the style and append to head
var css = $('<style>#keyframes mymove{from {left:0px;}to {left:'+pushLeft+'px;}}</style>').appendTo('head'); //make sure you don't carriage return the css inline statement, or else it'll be error as ILLEGAL
//so u don't keep appending style to head
KeyFrame.check = true;
}
}
}
KeyFrame.init();
Consider the idea of how to access the styleSheet...
document.styleSheets[0].insertRule(animationRule)
It's certainly going to be complicated to do well, so briefly you'd want to retain a link and alter the rule associated with each object or something to avoid clutter. Or you could try to run a form of garbage collection with time stamps or something to figure out when the old ones can be removed.
From a quick look for other links I found...
http://davidwalsh.name/add-rules-stylesheets
deleteRule
http://developer.mozilla.org/en-US/docs/Web/API/CSSStyleSheet/deleteRule
insertRule (addRule precedes and is therefore more reliable)
http://developer.mozilla.org/en-US/docs/Web/API/CSSStyleSheet.insertRule
I'm also just now noting something else that might be useful...
http://developer.mozilla.org/en-US/docs/Web/API/CSSKeyframesRule
Actually this looks like a better cleaner understanding or at least another way.
http://blog.joelambert.co.uk/2011/09/07/accessing-modifying-css3-animations-with-javascript/
Okay so if I am understanding correctly this jsfiddle should do the trick.
It uses a pre-defined set of transition properties, and changes the values dynamically via jquery.
The syntax for defining these animations is as follows...
transition-property: prop1, prop2, prop3;
transition-duration: timing1, timing2, timing3;
transition-timing-function: ease1, ease2, ease3;
By doing this, you can achieve nearly everything you can with #keyframes (not quite everything, but certainly a fair amount), it just happens to be built into the element style. From here you can go on to change whatever you want via jquery. If its the amount to move you can doing something like...
$("#myElem").css("left", "50px");
and the css3 transition will take care of the rest. If it's something like changing the ease type you can do that too with...
$("#myElem").css("transition-timing-function", "linear");
I know this is not exactly what you were looking for, but chances are it will do the trick.
It looks as if you have an understanding of css3 keyframes. I recommend jQuery.Keyframes to generate keyframes, you can also attach events and callbacks to the animations.
Yes you can, when you write your javascript code, you use the setAttribute() function vs the style() so that you can include more than one type of style. Just insert the animation-name, animation-duration, animation-timing-function or any other types that you wish.
<!DOCTYPE html>
<html>
<head>
<title> Welcome </title>
<meta charset = "utf-8">
<style>
#keyframes appear-in {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
#landing-page {
width: 100%;
height: 1000px;
}
</style>
<script>
window.addEventListener('load', function(){setTimeout(renderService, 1000)});
function renderService(){
var server = document.getElementById('Services');
server.setAttribute("style", "animation-name: appear-in; animation-duration: 5s; animation-timing-function: ease-in; background-image: url('https://wallpaperaccess.com/full/949819.jpg'); background-size: 80% 100%; background-position: center");
}
</script>
</head>
<body>
<div id = "landing-page">
</div>
</body>
</html>
I have searched through StackOverflow posts and various forums, but cannot find an answer. I have found answers for similar questions, but nothing breaks it down quite enough for me to understand. I understand a good deal of PHP and HTML, but am having difficulty with scripts.
How can I click on a link, get the href (or what do I need?), have it fade out the current content, find the content I'm trying to load (href or whatever in the link) and load it, then fade it in?
My previous problems with random bits of code I've tried:
While going from page to page if another link was clicked while loading, it would only partially fade the second page in.
Each link had to have it's own script to direct it there. Could never figure out how to make it get the href of the link clicked.
Examples were so complicated I couldn't modify them to what I needed exactly. I need to understand the process of it.
Something like:
$('.link').on('click', function(){
$('.content').fadeOut().load('/path/to/script', function() {
$(this).fadeIn();
});
});
The key to this to use a HTML page or PHP script which can return the content you want. You might want to retrieve the URL from another element or hard-code it into your script - your call. For more information about how load() works, visit jQuery's documentation.
I actually developed something just like this some time ago.
The trick (or a trick) is to wrap your page an an iframe, and on the parent window, have a div element that fades into view when a page is requested, and fades out when the page loads.
The parent window looks like this:
<!DOCTYPE html>
<html>
<head>
<title>< Page1 ></title>
<style>
html, body{
font-family:helvetica;
}
#fade, iframe {
position:absolute;
left:0px;
top:0px;
width:100%;
height:100%;
border-width:0px;
z-index:-1;
opacity:0;
color:#AAA;
background-color:#FFF;
-webkit-transition: opacity 300ms;
-moz-transition: opacity 300ms;
-o-transition: opacity 300ms;
}
iframe {
opacity:1;
z-index:1;
background-color:#FFF;
}
</style>
</head>
<body>
<div id="fade">
<h1>Loadin..</h1>
</div>
<iframe src="p1.html"></iframe>
<script>
var fade = document.getElementById("fade");
var iframe = document.getElementsByTagName("iframe")[0];
var t = null;
addEventListener("message", function(e) {
if(t!=null)clearTimeout(t);
fade.style.zIndex = "2";
t=setTimeout(function(){
fade.style.opacity = "1";
},0);
}, true);
iframe.addEventListener("load", function() {
if(t!=null)clearTimeout(t);
t=setTimeout(function(){
fade.style.opacity = "0";
},0);
document.title = iframe.contentWindow.document.title;
t=setTimeout(function(){
fade.style.zIndex = "-1";
},300);
}, true);
</script>
</body>
</html>
And the subpages would each have the following code:
<script>
function go() {
window.parent.postMessage("showLoadScreen", "*");
}
</script>
somepage.html
This code is a little different in that the fader doesn't pop up unless the requested resource is taking awhile to load. But, you get the idea.
Since the iframe only exists for visual purposes, it shouldn't cause any major problems. However, note that this code uses HTML5's postMessage API, and you may want to tweak it a bit.