user clicks menu option:
current contents of div swirl, get small and disappear
those contents are replaced with other contents via replaceChild
the new contents start small, swirl and show
if the old and new contents are the same, it works fine; but if different, the swirl down works but the new contents simply appear full size after 500ms
when it works, the effect is quite nice
here's a complete working example:
<html>
<head>
<script>
var d1 = document.createElement('div');
d1.className = 't';
d1.innerHTML = 'testing1';
var d2 = document.createElement('div');
d2.className = 't';
d2.innerHTML = 'testing2';
function test(no) {
// current
var cur_dom = document.body.getElementsByTagName('div')[0];
cur_dom.style.webkitTransform = "rotate(180deg) scale(0.1)";
setTimeout( step2, 500 );
// new
function step2() {
// replace node with part
var new_dom = (no==1) ? d1 : d2;
cur_dom.parentNode.replaceChild(new_dom,cur_dom);
new_dom.style.webkitTransform = "rotate(0deg)";
}
return false;
};
</script>
<style>
div { border: 1px solid red; }
div.t { -webkit-transform: rotate(180deg) scale(0.1);
-webkit-transition: -webkit-transform ease-in-out 500ms; }
</style>
</head>
<body>
<a href='#' onclick='return test(1)'>test1</a>
<a href='#' onclick='return test(2)'>test2</a>
<div class='t'>this will be replaced</div>
</body>
</html>
took the coward's way out and, instead of dom assignment, copied the innerHTML of the new dom to the existent dom, and rotated it
cur_dom.innerHTML = new_dom.innerHTML;
cur_dom.style.style.webkitTransform = "rotate(0deg)";
works just fine. but still ugly.
The problem is that the new element you put in place isn't rotated. You basically solved the problem, and it's not ugly, but the correct thing to do. You can also leave out the generation of the "replacement" DIVs and just change the content of the original one:
cur_dom.innerHTML = (no==1) ? 'testing1' : 'testing2';
cur_dom.style.webkitTransform = "rotate(0deg)";
Working example: http://jsfiddle.net/CTxVu/
Related
The opacity fade works perfect in all browsers except IE11 and I can't figure out.
I don't even know how to describe it. It only happens after I fade in a child element and a parent element at the same time. But after that it screws up everything.
However when I try to replicate it as a simple test case it works fine in IE11 - https://jsfiddle.net/Noitidart/9q6Lxc46/2/
Here is screencast showing the bug (not seen in the fiddle) - https://youtu.be/knFQ4UvZP0I
Here is jsfiddle pasted here:
var FADE_ENTER_MS = 1000;
var FADE_LEAVE_MS = 1000;
var LOAD_MS = 5000;
function wait(ms, cb) {
setTimeout(cb, ms);
}
function doEnter(el, parent) {
parent.appendChild(el);
el.classList.add('fade-enter');
window.getComputedStyle(el, null).getPropertyValue('height'); // force paint as element was just added, so opacity:0 needs to register
wait(FADE_LEAVE_MS, function() { // wait for previous page to fade out
el.classList.add('fade-enter-active');
wait(FADE_ENTER_MS, function() {
el.classList.remove('fade-enter');
el.classList.remove('fade-enter-active');
});
});
}
function doLeave(el) {
el.classList.add('fade-leave');
window.getComputedStyle(el, null).getPropertyValue('height'); // force paint
el.classList.add('fade-leave-active');
wait(FADE_LEAVE_MS, function() {
// no need to mess with classList as i am removing element on line below
// el.classList.remove('fade-leave');
// el.classList.remove('fade-enter-active');
el.parentNode.removeChild(el);
});
}
window.showPage = function(pageNum) {
var leavingPageNum = pageNum === 1 ? 2 : 1;
var leavingPage = document.querySelector('.page-' + leavingPageNum);
var container = document.getElementById('page_fader');
var page = document.createElement('div');
page.setAttribute('class', 'page-' + pageNum + ' content-fader');
var loading = document.createElement('div');
loading.textContent = 'loading page ' + pageNum + '...';
var content = document.createElement('div');
content.innerHTML = 'CONTENT page ' + pageNum + ' <button onClick="showPage(' + leavingPageNum + ')">Show Page ' + leavingPageNum + '</button>';
doLeave(leavingPage);
doEnter(page, container);
doEnter(loading, page);
wait(LOAD_MS, function() {
doLeave(loading);
doEnter(content, page);
});
}
#page_fader > div { position:absolute; width:100%; height:100%; }
.content-fader > div { position:absolute; width:100%; height:100%; background-color:lightsteelblue; }
.fade-enter { opacity:0; }
.fade-enter.fade-enter-active { opacity:1; transition:opacity 1000ms; }
.fade-leave { opacity:1; }
.fade-leave.fade-leave-active { opacity:0; transition:opacity 1000ms; }
<div id="root">
<div id="page_fader">
<div class="content-fader page-1">
<div class="content-content">CONTENT page 1 <button onClick="showPage(2)">Show Page 2</button></div>
</div>
</div>
</div>
This is my worst question ever. I tried to formulate a question for months. I don't even know how to ask other then to show it. May you please see it in action: at https://mlink.info
Here is my best attempt at a description:
Please click on "login" then "signup" then the "MLINK" logo. You see the opacity fades perfectly in and out to 100%. However after hitting search, it fades in a inner loading thing, then out when the content loads. Then the content loads to 100% opacity but for some god forsaken reason, it goes down to like 50%'ish, I have no no idea why.
Right clicking and doing "inspect element" makes the opacity 100% again O_O so weird.
I held off on this question for months, I just cannot figure it out. :( Does anyone have any ideas?
I am new here and new to programming, so apologies in advance if this question is very basic and the answer is already here. I've done a lot of searching, but I've been unable to find the information I need.
What JavaScript code could I use to pull the current opacity value of a div, update that value, and reapply the updated value to that same div? In essence, I'm doing an exercise that involves gradually increasing the opacity of individual divs in a large grid on the mouseover event. Each individual div in the grid should have a 0.1 increase in opacity every time the mouse enters that div, up to the point of having an opacity of 1.
I already know how to do this in jQuery, I'm just trying to expand my knowledge of JavaScript at the moment.
So this is how you'd set opacities and events with jQuery:
// `elem` is the element you want to affect
// get opacity
var oldOpacity = $(elem).css('opacity');
// set opacity
$(elem).css('opacity', 0.5);
// add mouseover event
$(elem).on('mouseover', function onMouseOver(e) {
// do stuff with opacities
});
And here's how you'd do the above with vanilla DOM methods:
// `elem` is the element you want to affect
// get opacity
var oldOpacity = window.getComputedStyle(elem).getPropertyValue('opacity');
// set opacity
elem.style.setPropertyValue('opacity', 0.5);
// add mouseover event
elem.addEventListener('mouseover', function onMouseOver(e) {
// do stuff with opacities
}, false);
To get the element, you can use old DOM methods like document.getElementById or the new methods document.querySelectorAll and document.querySelector which are very much like jQuery in that they take a CSS selector and return a Node or list of Nodes.
To, say, retrieve all of the li elements with the class list-item, and iterate over them, you would do this:
var elems = document.querySelectorAll('li.list-item');
var i, l = elems.length, elem;
for (i = 0; i < l; i += 1) {
elem = elems[i];
// do stuff with elem
}
Here's the 'vanilla' JS way to check and update opacity, with the caveat that this only works in browsers; it won't work in NodeJS because there's no document in node. You can try it on this page by opening dev tools (right-click, inspect, console in Chrome).
var div = document.querySelector('.post-text')
console.log(div.style.opacity) // ""
div.style.opacity = 0.5
console.log(div.style.opacity) // "0.5"
So for your exercise, you'll want to assign the mouseover function like so:
function changeOpacity (element, delta) {
element.style.opacity = Number(element.style.opacity) + Number(delta)
}
var element = document.querySelector('.post-text')
var opacityDelta = -0.1
document.onmouseover = function () { changeOpacity(element, opacityDelta) }
I got it to work with these lines of code.
with vanilla Js.
I commented too.
// Vanilla Js.
//Getting elements.
var box = document.querySelector('.box');
var refresh = document.querySelector('.refresh');
// Assigning opacity
var defaultOpacity = 0.2;
box.style.opacity = defaultOpacity;
// Events.
// Opacity adding event on hover
box.addEventListener('mouseover', function(e){
var oldOp = e.target.style.opacity;
oldOp = Number.parseFloat(oldOp);
oldOp += defaultOpacity;
e.target.style.opacity = oldOp;
}, false);
//Refresh Evet.
refresh.addEventListener('click', function(e){
box.style.opacity = defaultOpacity;
});
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
<style>
.box {
background: #48A64C;
height: 100px;
width: 100px;
margin-bottom: 20px;
}
</head>
<body>
<div class="box"></div>
<p> Yeah you can refresh too </p>
<button class = "refresh">refresh</button>
</body>
</html>
I wan't to make show() and hide() method like jquery have, but with pure javascript because I want to modify how the element show and hide. But after my attempts, I've changed where the code placed, changed the code, etc, still it won't work. Only for a few times it was work but it was inconsistent (when I try to run it through firefox, it work for once but never again). The display (block and none) and the exact width and height is work, but not the 2s transition. How to fix this?
<!doctype html>
<html>
<head>
<style>
div {
width: 0px;
height: 0px;
background-color: yellow;
border: 1px solid black;
display: none;
}
</style>
</head>
<body>
<div>
</div>
<button>
click !
</button>
<script>
var x = document.getElementsByTagName("button");
var y = document.getElementsByTagName("div");
x[0].onclick = fungsi;
function fungsi() {
if (y[0].style.display != "block") {
y[0].style.display = "block";
y[0].style.transition = "width 2s";
y[0].style.transition = "height 2s";
y[0].style.width = "100px";
y[0].style.height = "100px";
} else {
y[0].style.display = "";
y[0].style.transition = "width 2s";
y[0].style.transition = "height 2s";
y[0].style.width = "";
y[0].style.height = "";
}
};
</script>
</body>
</html>
I've messed around with your code and found that the reason for your problem was the switching from display: none; to display: block; and back. I've made a simple solution for this if you would like to use it.
Here is the modified CSS code.
div {
width: 0px;
height: 0px;
background-color: yellow;
border: none;
}
Here is the modified JS code.
var x = document.getElementsByTagName("button");
var y = document.getElementsByTagName("div");
x[0].onclick = fungsi;
var expanded = false;
function fungsi() {
y[0].style.transition = "all 2s";
if (!expanded) {
y[0].style.border = "1px solid black";
y[0].style.width = "100px";
y[0].style.height = "100px";
expanded = true;
} else {
var applyBorder = function () {
y[0].style.border = "none";
};
y[0].style.width = "0";
y[0].style.height = "0";
expanded = false;
setTimeout(applyBorder, 2000);
}
};
And here is a JSFiddle of this code for an example.
It could be something to do with vendor prefixes
So as well as having the following:
y[0].style.transition
You will also need:
y[0].style.mozTransition
y[0].style.webkitTransition
Try that, hopefully should work.
What you are doing is not animating show and hide with "pure javascript", it really is animating show and hide with CSS3. You are just setting the CSS properties trough javascript!
That being said, CSS3 transitions are not supported by every browser. For example even IE9 does not support it. Some other browser only work with prefixed versions of this property.
Try setting -moz-transition, -webkit-transition and -o-transition too.
For more details see: Transition browser support
However if you expect your animation to work across all major platforms I suggest you to use jQuery and try adjusting the settings to your desired behavior..
When you run
y[0].style.transition = "width 2s";
y[0].style.transition = "height 2s";
The first line will be overwritten by the second. So the transition goes only for width or height at a time, and when one of them is 0, the transition will be invisible.
You should set transition like this:
y[0].style.transition = 'width 2s,height 2s';
Or just set it for all properties that support transition:
y[0].style.transition = 'all 2s';
BTW, since the transition property is not changing, you should set them outside the changing part.
Another problem is, the <div> must be visible before the animation starts, otherwise it will have the desired width and height once become visible, and no transition is needed any more. visibility is another choice since an element with visibility: hidden still takes the place.
Here is a working copy of code:
<!doctype html>
<html>
<head>
<style>
div {
width: 0px;
height: 0px;
background-color: yellow;
border: 1px solid black;
/* Use visibility instead of display */
visibility: hidden;
}
</style>
</head>
<body>
<div>
</div>
<button>
click !
</button>
<script>
var x = document.getElementsByTagName("button");
var y = document.getElementsByTagName("div");
x[0].onclick = fungsi;
// set transition
y[0].style.transition = "width 2s,height 2s";
function fungsi() {
if (y[0].style.visibility != "visible") {
y[0].style.visibility = "visible";
y[0].style.width = "100px";
y[0].style.height = "100px";
} else {
y[0].style.visibility = "";
y[0].style.width = "";
y[0].style.height = "";
}
};
</script>
</body>
</html>
And something more, if you want to hide the element after the animation ends, setTimeout will work.
I am using javascript to periodically replace a .png picture, which ist viewed fullscreen as the only content of a site. No matter how I try, in Firefox, after being loaded (as seen via firebug), the new image is always drawn from top to bottom. This takes some seconds. Is there any way to prevent this and show the picture all at once?
This is my current javascript code:
function preloadScreenshotPeriodically(){
var new_screenshot = new Image();
new_screenshot.src = "screenshot.png?defeat_firefox_caching=" + counter;
new_screenshot.id = "screenshot";
counter = counter + 1;
new_screenshot.onload = function(){
loadScreenshot(new_screenshot);
setTimeout("preloadScreenshotPeriodically();", 5000);
};
}
function loadScreenshot(new_screenshot){
document.getElementById("screenshot").parentNode.replaceChild(new_screenshot, document.screenshot);
}
I also tried to use two images, one of them hidden. Then loading the picture in the hidden one and swapping them. Same results :/
In an other version, I fetched the image with Ajax and after loading is complete, changed the url of the img-tag. My hope was, that the browser would recognize the picture had already been loaded and fetch it from the browsercache rather than loading it. But this didn't happen and I ended up with two requests to the server for one picture and the same slow drawing of it as in my other trys.
edit:
Now I tried it like suggested in answer 1. While it works just fine if I switch the picture when I load the next one (I don't want this), trying to switch it as soon as it is loaded (what I want) results in a blank window (very short) and visible loading of the picture as described above.
this works:
<body>
<style type="text/css">
#loaderWin { display:block; height:1px; width:1px; overflow:hidden; }
</style>
<div id="imagewin"></div>
<div id="loaderWin"></div>
<script type="text/javascript">
var screenshotCount=0;
function showFirstImage() {
loadNextImage();
}
function showNewImage() {
loadNextImage();
}
function nextImageLoaded() {
// swapImage();
}
function loadNextImage() {
swapImage();
screenshotCount = screenshotCount +1;
var nextImage = "<img id='loaderWinImg' src='screenshot.png?x="+screenshotCount+"' onload='nextImageLoaded()' />";
document.getElementById('loaderWin').innerHTML = nextImage;
}
function swapImage() {
document.getElementById("loaderWinImg").onload = '';
var newimage=document.getElementById('loaderWin').innerHTML;
document.getElementById('imagewin').innerHTML = newimage;
}
var showImages = setInterval("showNewImage()",15000);
showFirstImage();
</script>
</div>
</body>
</html>
this doesn't work:
<body>
<style type="text/css">
#loaderWin { display:block; height:1px; width:1px; overflow:hidden; }
</style>
<div id="imagewin"></div>
<div id="loaderWin"></div>
<script type="text/javascript">
var screenshotCount=0;
function showFirstImage() {
loadNextImage();
}
function showNewImage() {
loadNextImage();
}
function nextImageLoaded() {
swapImage();
}
function loadNextImage() {
screenshotCount = screenshotCount +1;
var nextImage = "<img id='loaderWinImg' src='screenshot.png?x="+screenshotCount+"' onload='nextImageLoaded()' />";
document.getElementById('loaderWin').innerHTML = nextImage;
}
function swapImage() {
// loadNextImage();
document.getElementById("loaderWinImg").onload = '';
var newimage=document.getElementById('loaderWin').innerHTML;
document.getElementById('imagewin').innerHTML = newimage;
}
var showImages = setInterval("showNewImage()",15000);
showFirstImage();
</script>
</div>
</body>
</html>
The problem can be seen here (in firefox problem like described above, in chrome there are no pauses between pictureloads and there is a blank window in between picture changes): http://sabine-schneider.silbe.org:1666/test.html
And here, what Rob suggested in answer 1 without any changes (displays the picture fine in firefox, but not in chrome - there I get a blank window in between picture changes): http://sabine-schneider.silbe.org:1666/test0.html
sounds like the image is "progressive" ( interlaced) and the preload needs more time for it to complete download.
You can set a width and height to the image also for a more stable presentation
( poss )
using
?defeat_firefox_caching=" + counter;
means you never cache the image ( which has confused me about your question ) - remove that line( unless you need it for something you haven't mentioned)
update: Can you try ...
<style type="text/css">
#loaderWin { display:block; height:1px; width:1px; overflow:hidden; }
</style>
<div id="imagewin"></div>
<div id="loaderWin"></div>
<script type="text/javascript">
var screenshotCount=0;
function showNewImage() {
screenshotCount = screenshotCount +1;
var newimage=document.getElementById('loaderWin').innerHTML;
document.getElementById('imagewin').innerHTML = newimage;
var nextImage = "<img src='screenshot.png?defeat_firefox_caching="+screenshotCoun+"'/>";
document.getElementById('loaderWin').innerHTML = nextImage;
}
var showImages = setInterval("showNewImage()",5000);
</script>
Could someone please check my code? Thank you
Here is the fiddle site if you want to test:
http://jsfiddle.net/66QYr/
I would like to have the first 3 text to appear on the left (vertically)
and then the next 3 text appear on the right (vertically)
then the next 2 text appear on the lower right bottom (vertically)
and the last 2 text appear on the lower left bottom (vertically)
http://i197.photobucket.com/albums/aa253/tintingerri/Test/pic001.png
<html>
<head>
<title>tintin</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<style type="text/css">
#tintin{
position: relative;
top: 211px;
left: 12px;
font-size:14pt;
font-weight:bold;
font-family: Calibri;
color:red;
filter:alpha(opacity=0);
opacity:0;}
.image{
height:350px;
width: 855px;}
</style>
<script type="text/javascript">
var txt=['text1','text2', 'text3', 'text4', 'text5', 'text6', 'text7', 'text8', 'text9', 'text10'], init=0,i=0,k=0,speed=20,el;
var loopCount=1000;
var j=0;
//var padd = 20; //set this to an approriate increment
function fade(){
init==0?i++:i--;
el.filters?el.style.filter='alpha(opacity='+i+')':el.style.opacity=i/100;
el.firstChild.nodeValue=txt[k];
if(i==100)init=1;
if(i==0) {init=0;k++;j++;
el.style.paddingLeft=20*k;
}
if(k==txt.length)k=0;
if (j<loopCount) setTimeout('fade()',speed);
}
window.onload=function(){
el=document.getElementById('tintin');
fade();
}
</script>
</head>
<body>
<div id="tintin"> </div>
<div class="image" style="background-image:url('pic007s.jpg')">;
</div>
</body>
</html>
There are two problems you're trying to solve here:
Positioning the text in the appropriate places
Getting them to fade in
Step One
The first problem can be solved with some simple CSS. Start out with a container:
#container {
position:relative;
width:150px;
height:150px;
}
<div id="container"></div>
The width and height can be anything, but you do have to tell it something. We're going to be putting our text in this container, but then use position:absolute. This will take them out of the normal document flow, and collapse the container if we have told it an explicit height.
The next step is the text. You're going to want four divs, with the text inside as paragraphs:
<div class="text" id="text1">
<p>text 1</p>
<p>text 2</p>
<p>text 3</p>
</div>
Do this for each of the four blocks of text that you want to have. Use the same class name on each one, but give each their own, unique ID (text2, text3, etc.).
Finally, just use (as I said earlier) absolute positioning to place them where you'd like:
.text { position:absolute; }
#text1 { top:0; left:0; }
#text2 { top:0; right:0; }
...and so on. When you're done, you should have something that looks like this:
Step Two
Fading elements in requires animation. You kind of have a basic animation function, but I suggest you read Robert Penner's article on tweening and animation. It was written for ActionScript, but the exact same principles apply.
For now, here's a good general-purpose JavaScript method that will take an element and fade it in:
function fadeIn(totalTime, elem, after) {
var cos = Math.cos,
PI = Math.PI,
startTime = +new Date(),
endTime = startTime + totalTime,
timer;
elem.style.opacity = 0;
elem.style.filter = 'alpha(opacity=0)';
timer = setInterval(function () {
var currentTime = +new Date();
currentTime = currentTime > endTime ? 1 : (currentTime - startTime) / totalTime;
var distance = (1 - cos(currentTime * PI)) / 2;
elem.style.opacity = distance;
elem.style.filter = 'alpha(opacity=' + distance * 100 + ')';
if (currentTime === 1) {
clearInterval(timer);
if (after) {
after();
}
}
}, 40);
}
You tell this function how long you want the animation to last (in milliseconds), and you can also give it a function to execute when the fading is done (if you want; it's not necessary).
If I understood your question correctly, you want all the texts to start invisible, and then fade in, one at a time, clockwise from the top. We can make them invisible with CSS, but then if the user has JS disabled, the page will appear blank. So you need to first "get" all of the elements (either with some kind of getByClass function or with four different calls to getElementById) and set their opacity to 0.
So you can make the first group of texts fade in by doing the following:
var text1 = document.getElementById('text1');
fadeIn(1000, text1);
The problem is, by doing this, there's no way to tell when to start the next animation. So we need to make a function, with the help of closures, to help keep track of things (this assumes that you've already gotten the elements in JS and made them invisible):
var tracker = (function () {
var texts = [text1, text2, text3, text4],
i = 0;
return function () {
var text = texts[i];
if (text) {
fadeIn(1000, text, tracker);
i += 1;
}
};
}());
This function cycles through each element and fades it in when the previous one is done. (It's okay if the code doesn't make a lot of sense; closures are tricky things.)
Here is the final result, in JSFiddle. Good luck.