Javascript transition duration won't work - javascript

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.

Related

Why div DOM object does not have height and width properties [duplicate]

This question already has answers here:
How do I retrieve an HTML element's actual width and height?
(16 answers)
How to get actual CSS property value of an HTML element node? [duplicate]
(5 answers)
Closed 4 years ago.
I am a beginner coder. It is probably very simple, but I tried to find the answer and have not succeeded. My question is why do width and height properties of div object return undefined while they are apparently 100px both?
In this topic is explained how to get .offsetWidth property. But as I understand it is not 100% the same as .width.
window.onload = function() {
var test = document.getElementById("test");
test.addEventListener("click", select);
function select(e) {
var elementID = e.target.id;
var element = document.getElementById(elementID);
var width = element.width;
console.log(element);
console.log(width);
}
}
div#test {
position: absolute;
height: 100px;
width: 100px;
background-color: black;
}
<div id="test"></div>
My answer
Thank you all guys for your answers. They pushed me to find my own simple solution which I hope will be helpful for such beginners as me. The answer is: div DOM object does not have .width and .height property even if you assign them in CSS and they work well. For this purpose it has .style.width and .style.height respectively. But even if you assign them through CSS they will not appear in element.style until you do it purposefully using Java Script. So to get width or height of the div element through JS first of all remove these properties from CSS. You will not need them anymore. Then assign width through element.style.width command and then you can easily get it whenever you want using element.style.width.
CSS
div {
position: absolute;
background-color: black;
}
JavaScript
window.onload = function() {
var test = document.getElementById("test");
test.addEventListener("click", select);
test.style.width = "100px";
test.style.height = "100px";
function select(e) {
var elementID = e.target.id;
var element = document.getElementById(elementID);
var width = element.style.width;
console.log(element);
console.log(width);
}
}
Use offsetWidth and offsetHeight
var test = document.getElementById("test");
test.addEventListener("click", select);
function select(e) {
var elementID = e.target.id;
var element = document.getElementById(elementID);
var offsetWidth = element.offsetWidth;
var positionInfo = element.getBoundingClientRect();
var height = positionInfo.height;
var width = positionInfo.width;
console.log('element', element);
console.log('offsetWidth', offsetWidth);
console.log('width', width);
console.log('height', height);
}
div#test {
position: absolute;
height: 100px;
width: 100px;
background-color: black;
}
<!doctype html>
<html lang="en">
<head>
<title>test</title>
<meta charset="utf-8">
</head>
<body>
<div id="test"></div>
</body>
</html>
I think you need clientWidth and clientHeight.

SVG object display toggle stops EventListener

I managed to load an external svg and to grab the path's name and insert it into a tooltip.
But when i now toggle the display of the div, containing the svg object, off and on again the EventListener somehow doesn't work anymore (it only works in FireFox) and the name of the path will not show again.
Any idea Why Safari and Chrome won't listen anymore?
window.onload = function() {
var a = document.getElementById("Map1");
var svgDoc = a.contentDocument;
var myImage = svgDoc.getElementsByTagName("path");
for (var i = 0; i < myImage.length; i++) {
myImage[i].addEventListener('mouseover', show);
myImage[i].addEventListener('mouseout', hide);
}
var text = document.getElementById("show");
function show() {
var myID = this.id;
text.innerHTML = myID;
document.getElementById("show").style.display = "block";
}
function hide() {
var myID = this.id;
text.innerHTML = '';
document.getElementById("show").style.display = "none";
}
}
function myFunction() {
var toggle = document.getElementById("Map");
toggle.style.display = toggle.style.display === 'none' ? 'block' : 'none';
}
#show {
display: none;
}
<button onclick="myFunction()">Show Map!</button>
<div id="show" style="position: absolute; left: 100px; background-color:aqua; padding: 5px;"></div>
<div id="Map" style="display: block;"><object id='Map1' data="Test-01.svg" type="image/svg+xml">Your browser doesn't support SVG</object></div>
That's a weird bug, which I did reproduce here.
The core of this bug is that webkit browsers will unload an <object> or <embed> content when its CSS display is set to none. Doing so, it will remove all of its content, your event listeners included.
Thus, you've got two possible workarounds (at least) :
1 - Use an <iframe>. This tag is not concerned by this bug...
Live example
2 - Use some other CSS rules to hide your <object>.
Something like the following should provide the same functionality as display: none
object.hidden {
position: absolute;
z-index: -99;
width: 0px;
height: 0px;
visibility: hidden;
pointer-events: none;
}
Live example
And to add more weirdness, this bug doesn't affect BlobURIs in chrome (couldn't test in Safari, the blob gets downloaded, one other bug...).

Force browser to immediately repaint a dom element

I need to insert a huge html markup to some dom element which will take awhile. It is a reason why I want to display some preloader indicator. I have two blocks: #preloader and #container. Some code displays the preloader firstly and then starts to paste a big html markup.
The problem - preloader hasn't really displayed until browser will not finish render html markup. I've tried a lot of solutions (a lot of them are described here) but still haven't success.
An example is avalable below:
https://jsfiddle.net/f9f5atzu/
<div id='preloader'>Preloader...</div>
<div id='container'>Container...</div>
#preloader {
display: none;
background-color: #f00;
color: #fff;
hight: 100px;
text-align: center;
padding: 10px 20px;
}
#container {
background-color: #ccc;
}
setTimeout(function() {
// Define variables
let domPreloader = document.getElementById('preloader');
let domContainer = document.getElementById('container');
const html = Array(100000).fill("<div>1</div>");
// Display preloader
domPreloader.style.display = 'hide';
domPreloader.offsetHeight;
domPreloader.style.webkitTransform = 'scale(1)';
domPreloader.style.display = 'block';
// Render a big html
domContainer.innerHTML = html;
}, 1000);
Is there any solutions for the problem?
The way you did it, you're not releasing control to the browser between the display of the preloader and the display of the 'big html'.
Rather than encapsulating this whole block inside a setTimeout(), you should just differ the rendering part.
Please try something along those lines:
// Define variables
let domPreloader = document.getElementById('preloader');
let domContainer = document.getElementById('container');
// Display preloader
domPreloader.style.webkitTransform = 'scale(1)';
domPreloader.style.display = 'block';
// Render a big html
setTimeout(render, 100);
function render() {
const html = Array(100000).fill("<div>1</div>");
domContainer.innerHTML = html;
// Hide preloader
domPreloader.style.display = 'none';
}
JSFiddle

Cannot update div style attributes

I'm trying to change a couple of style attributes. Here is the style I first assigned to clickedMenuHexagonDiv:
clickedMenuHexagonDiv.style.MozTransform = "scale(.9999)";
clickedMenuHexagonDiv.style.width = num2px(this.width);
clickedMenuHexagonDiv.style.marginRight = "3px";
clickedMenuHexagonDiv.style.position = "relative";
clickedMenuHexagonDiv.style.zIndex = "5";
clickedMenuHexagonDiv.style.styleFloat = "right";
clickedMenuHexagonDiv.style.cssFloat = "right";
Here is the code later on, for the attributes I want to change:
clickedMenuHexagonDiv.className = "centerHexagonDiv";
clickedMenuHexagonDiv.style.bottom = "auto";
clickedMenuHexagonDiv.style.right = "auto";
clickedMenuHexagonDiv.style.float = "none";
alert("clickedMenuHexagonDiv: " + clickedMenuHexagonDiv.style.cssText);
And here is the output of the alert:
clickedMenuHexagonDiv: transform: scale(0.9999); width: 80px; margin-right: 3px; position: relative; z-index: 5; float: right; right: auto; bottom: auto;
As you can see, it only updates attributes that weren't declared earlier. There were no console errors. Also, somewhat oddly, bottom and right were changed by the jquery animate function (I put an alert in before clickedMenuHexagonDiv.className = "centerHexagonDiv";, and it showed values other than "auto" for bottom and right.
I figured out that I can sort of fix this if I insert clickedMenuHexagonDiv.style.cssText = "" before changing the style attributes, but then I have to declare all of the attributes again. I'd rather try to understand why I can't update specific attributes.
If figured it out: I needed to use "styleFloat" and/or "cssFloat". "float" isn't a css property.
Here's the updated code (only the second section needed updating):
clickedMenuHexagonDiv.className = "centerHexagonDiv";
clickedMenuHexagonDiv.style.bottom = "auto";
clickedMenuHexagonDiv.style.right = "auto";
clickedMenuHexagonDiv.style.styleFloat = "none";
clickedMenuHexagonDiv.style.cssFloat = "none";

problems with CSS3 transform and transition

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/

Categories