Ladda UI not set correct progress - javascript

I'm using this code to create a ladda button:
CSS:
<link href="./assets/global/plugins/ladda/ladda-themeless.min.css" rel="stylesheet" type="text/css">
CODE:
<button type="button" id="test" class="btn green mt-ladda-btn ladda-button" data-style="expand-left"> <span class="ladda-label"> <i class="fa fa-key"></i> Nuova Password</span> </button>
JS:
<script src="./assets/global/plugins/ladda/spin.min.js" type="text/javascript"></script>
<script src="./assets/global/plugins/ladda/ladda.min.js" type="text/javascript"></script>
<script>
Ladda.bind( 'input[type=button]' );
$(function() {
$('#test').click(function(e){
var l = Ladda.create( document.querySelector( '#test' ) );
// Start loading
l.start();
// Will display a progress bar for 50% of the button width
l.setProgress( 0.5 );
});
});
</script>
This way the code work but progress is not correct:
but when use this code js:
Ladda.bind( '#test', {
callback: function( instance ) {
var progress = 0;
var interval = setInterval( function() {
progress = Math.min( progress + Math.random() * 0.1, 1 );
instance.setProgress( 0.5 );
if( progress === 1 ) {
instance.stop();
clearInterval( interval );
}
}, 200 );
}
});
the result is correct:
Why this? I need to use the first code because on click i have some function and i set the progress manualy based on function position.
It is possible to fix? I have metronic license and Material Theme, but u think the problem is plugin not theme.

To understand what's going on in the first example you have to look in the Ladda button code source and at line 154 there is the setProgress function:
/**
* Sets the width of the visual progress bar inside of
* this Ladda button
*
* #param {Number} progress in the range of 0-1
*/
setProgress: function( progress ) {
// Cap it
progress = Math.max( Math.min( progress, 1 ), 0 );
var progressElement = button.querySelector( '.ladda-progress' );
// Remove the progress bar if we're at 0 progress
if( progress === 0 && progressElement && progressElement.parentNode ) {
progressElement.parentNode.removeChild( progressElement );
}
else {
if( !progressElement ) {
progressElement = document.createElement( 'div' );
progressElement.className = 'ladda-progress';
button.appendChild( progressElement );
}
progressElement.style.width = ( ( progress || 0 ) * button.offsetWidth ) + 'px';
}
}
The ladda button in you example has data-style="expand-left" setted.
When setProgress in the else section it calculate the .ladda-progress' width doing:
progressElement.style.width = ( ( progress || 0 ) * button.offsetWidth ) + 'px';
Now, when it gets button.offsetWidth there isn't inside the expand-left rules yet.
When expand-left is applied at .ladda-button element, it change width dimension because expand-left is adding padding-left to it.
.ladda-button[data-style="expand-left"][data-loading] {
padding-left: 56px;
}
E.g. .ladda-button has an offsetWidth of 100px.
When you click it the offsetwidth will change from 100px to 156px because of the expand-left css rule above.
But when setProgress is called button.offsetwidth it will get the 100px offsetWidth because the animation transitions is not happened yet. So when you call l.setProgress(0.5) you will see .ladda-progress width setted to 50px instead of the correct 78px.
A quick fix can be this (jsBin). Please note that is an ugly hard-coded solution. A better solution it could be the following.
When Ladda instantiate the button it could check the data-style attribute and get (for example from an associative array where the keys are only the width-oriented effect name and the value will be the measure) the offeset that will be applied to the .ladda-button element.
EDIT
Thanks, but if change progress to 1 the problem not is solved
jsbin.com/jonupadono/1/edit?html,output – user3477026
I see. The problem start from this css rule:
.ladda-button, .ladda-button .ladda-spinner, .ladda-button .ladda-label {
transition: all 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275) 0s !important;
}
So, when button.offsetWidth is called inside setProgress it gets a lesser offsetWidth because the css animation has not finished yet, it takes 300ms to finish.
Solution
Using percentage instead of pixels to calculate the .ladda-progress' width jsBin

Related

Scrolling animation from on specific spot to another

Let's say i have a box and it's offset from the correct spot by tranform:translateX(-200px)
Example below pic has two <section>'s, one is the large grey box and other white containing the .box in red. The illustration shows where/how the animation should move only as the viewer scrolls and contentiously move .box back and forth from -200px to 0px.
$( document ).ready(function(){
$(window).scroll(function(){
var wScroll = $(this).scrollTop();
var greySection = $('.grey').height(); // Which is 800px high
// (what other variables, and functions could I add? )
if( wScroll > greySection /1.3 ) // 1.3 of section.grey is where i want the animation to start
$('.box').css('transform','translateX(' + /* (what do i put here?) */ + 'px)');
});
});
.grey{ /* for visual purposes */
background-color: grey;
}
section {
width:100%;
height:800px;
}
p{
width:100%;
text-align:center;
}
.box{
width:200px;
height:200px;
background-color:red;
margin:0 auto; /* Here is where the box position should end up */
transform:translateX(-200px); /* Control this property to move box */
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.2/jquery.min.js"></script>
<section class="grey">
<p>Some contents here. Ignore this section</p>
</section>
<section id="box-holder">
<div class="box"></div>
</section>
How could i let the user control the transform property of the box position to the finished spot -200px to 0px only back and forth with the scrollbar.
I will look into now but first a few hints.
Use document ready so your variable gets stored ones and not after each scroll.
$( document ).ready(function() {
var greySection = $('.grey').height();
});
Should the box slide to the complete right, directly in the middle or just 200px to the right? I got a little confused by the -200px.
Here you go
https://jsfiddle.net/DenizTemizer/j6m73qnf/1/
var greySection;
$( document ).ready(function() {
greySection = $('.grey').height();
console.log(greySection);
});
$(window).scroll(function() {
var wScroll = $(this).scrollTop();
if( !$('.grey').hasClass('animated') && wScroll > (greySection / 1.3) ) {
console.log("animate");
$('.grey').addClass('animated');
$('.box').css({
"-webkit-transform":"translateX(0)",
"-ms-transform":"translateX(0)",
"transform":"translateX(0)"
});
}
});
Added as new answer so it is easier to find if this thread gets bigger.
Ripped this from stuff I'm working on, then chunked it together, Dig in.
The formula you want is something like:
(scrollTop-topOffset)/(pageHeight-windowHeight-topOffset)*translateDistance
This is where it is in the JavaScript:
mem[7] = -(~~(((mem[0]-BoxOffset)/mem[6])*BoxDistance));
This needs some work, I used a right shift by zero to round the result but it was acting weird when I ran the snippet so I used the double '~~' and then had to set it to negative '-' to make it positive, don't copy/paste, fix/tidy up my chicken scratch!! XD
INP=0xFFFF; // INPut flags
BoxDistance=200; // box travel distance
mem=[]; // mem array
JC = function(intv, event){
L_BOOT:{
L_TRIPEVENT:{
if (!event) break L_TRIPEVENT; // if there is an event
event = event || window.event; // for IE
if (event.stopPropagation) { event.stopPropagation(); } else { event.cancelBubble = true; } // stop bubble up
FP= event.target ? event.target : event.srcElement; // get it
if ((INP&=intv)&0x002) break L_TRIPEVENT; // if boot is complete
INP_Resize:{
// Save the old browser width/height dimentions? if needed ...
if(INP&0x020) break INP_Resize; INP |= 0x020; // INP_Resize = OFF
//
// Get the window dimentions
//
mem[2] = (document.body.innerWidth)? document.body.innerWidth : document.body.clientWidth; // window width
mem[3] = (document.body.innerHeight)? document.body.innerHeight : document.body.clientHeight; // window height
//
// Get the page dimentions
//
mem[4]=document.getElementById('box-holder').offsetWidth; // section width:
mem[5]=document.getElementById('box-holder').offsetHeight*2; // section width: (box-holder x 2) both sections are of the same height
BoxOffset=document.getElementById('ThisTrigger').offsetHeight; // section width:
mem[6]=mem[5]-mem[3]-BoxOffset; // page height - window height = (scroll bottom)
}// INP_Resize:
INP_Scroll:{
mem[1] = mem[0]; // Save last scroll location, not really needed ...
if(INP&0x010) break INP_Scroll; INP |= 0x010; // INP_Scroll = OFF
mem[0] = ((document.body.scrollTop)? (document.body.scrollTop) : ((document.documentElement.scrollTop)? (document.documentElement.scrollTop):(window.pageYOffset) ));// get current scroll location
if ( BoxOffset<mem[0] ) { // get current scroll location
if (BoxOffset<mem[0]) {
mem[7] = -(~~(((mem[0]-BoxOffset)/mem[6])*BoxDistance)); // right shift 0 times, un-round to a whole number
/*
mem[0] = scroll top -> DistanceThusFar
BoxOffset = with the top offfset
mem[6] = (scroll bottom) -> DistanceCanGo
BoxDistance = distance
(DistanceThusFar / DistanceCanGo) = (0.???)%
the ratio between how far, and whats left to go
(0.???) * (BoxDistance) = (???px)
the ratio multiplied by BoxDistance is the distance
*/
mem[7] = BoxDistance<mem[7] ? BoxDistance : mem[7]; // if the number rounded, exceeds BoxDistance, set it to BoxDistance
}//if (mem[0]>=BoxOffse...
} else {
mem[7]^=mem[7]; // if the number rounded, is greater than 0, when scrollTop is less then trigger height, set it to zero
}
AX=mem[7];
document.getElementById("meee").setAttribute('style', 'margin-left: '+AX+'px;'); // update box distance
}// INP_Scroll:
}//L_TRIPEVENT:
if (INP&0x001) break L_BOOT; INP|=0x001; INP&=0xFFD; // L_BOOT = OFF
INP &= 0xFEF; // 1110:1111 <- set this bit off, to trip SCROLL interupt
INP &= 0xFDF; // 1110:1111 <- set this bit off, to trip SCROLL interupt
}//L_BOOT:
//
// Print out memory
//
PrintText='';
i=0;
do{
PrintText += "<br> " + i + " " + mem[i];
i++;
}while (i^0x08)
document.getElementById("JC_TEST_TEXT").innerHTML = PrintText;
PrintText^=PrintText;
TIC=setTimeout(JC,100);
}; JC();
function JCinterupts(i0,i1,i2,i3){
if ('addEventListener' in window){
window.addEventListener(i0, ( function (intv) {return function (event) {JC(intv, event);};} )( 0xFBF ), false);
window.addEventListener(i1, ( function (intv) {return function (event) {JC(intv, event);};} )( 0xFEF ), false);
window.addEventListener(i2, ( function (intv) {return function (event) {JC(intv, event);};} )( 0xFDF ), false);
window.addEventListener(i3, ( function (intv) {return function (event) {JC(intv, event);};} )( 0xFFE ), false);
} else if ('attachEvent' in window){//IE
window.attachEvent('on'+i0, ( function (intv) {return function (event) {JC(intv, event);};} )( 0xFBF ) );
window.attachEvent('on'+i1, ( function (intv) {return function (event) {JC(intv, event);};} )( 0xFEF ) );
window.attachEvent('on'+i2, ( function (intv) {return function (event) {JC(intv, event);};} )( 0xFDF ) );
window.attachEvent('on'+i2, ( function (intv) {return function (event) {JC(intv, event);};} )( 0xFFE ) );
}
} JCinterupts('click','scroll','resize','load');
<!--
░░█████░░░░░░░░░░░░███░░░░░░░░░░░░
░░░░█░░░░░░░░░░░░░░█░░░░░░░░░█░░░░
░░░░█░░███░███░███░█░░░███░░░█░███
░░░░█░░█░█░█░█░█░░░█░░░█░█░███░█░█ JonathanClingan
░░░░█░░█░█░█░█░░░█░█░░░█░█░█░█░█░░ ©JonsCode
░░███░░███░█░█░███░███░███░███░███ 5.24.16
■ JonWasHere :P
-->
<HTML /><!-- HTML markup -->
<HEAD /><!-- self closing tags -->
<style>
HTML,BODY {
margin:0;
padding:0;
border:0;
}
.grey{ /* for visual purposes */
background-color: grey;
}
.darkgrey{ /* for visual purposes */
background-color: darkgrey;
height:34px;
}
section {
width:100%;
height:134px;
}
p{
width:100%;
text-align:center;
}
.box{
left:200px;
width:200px;
height:200px;
background-color:red;
margin:0 auto;
}
#JC_TEST_HOLD{
position:absolute;
position:fixed;
overflow:visible;
padding:0 10px 0 0;
color:white;
z-index:900;
text-align:left;
}
#JC_TEST_BOX{
height:100%;
overflow:auto;
position:relative;
margin:0;
padding:0 15px 0 0;
color:white;
background:rgba(0,0,0,0.8);
text-align:left;
}
#JC_TEST_TEXT{
text-align:left;
}
</style>
<BODY /><!-- Mhmmm, I like yo' body. ;) -->
<DIV ID="JC_TEST_HOLD" >
<DIV ID="JC_TEST_BOX" >
<p id="JC_TEST_TEXT"></p>
</DIV>
</DIV>
<section id="ThisBox" class="grey">
<div id="ThisTrigger" class="darkgrey">
<p>Some contents here. Ignore this section, or pay attention.</p>
</div>
</section>
<section id="box-holder">
<div id="meee" class="box"></div>
</section>

jQuery click event stop working in plugin

I've been trying to add event listeners as a part of a plugin. The idea is really simple, the goal is to do a slider plugin that handles 2 dimensions (horizontally and vertically)
So I have something like this
<div class="tab-container bg-dark-blue" start-tab="Home">
<div class="tab-page" x-index="1" y-index="1" id="Home">
<h1>x=1, y=1</h1>
</div>
<div class="tab-page" x-index="1" y-index="2">
<h1>x=1, y=2</h1>
</div>
<div class="tab-page" x-index="2" y-index="1">
<h1>x=2, y=1</h1>
</div>
<div class="tab-page" x-index="2" y-index="2">
<h1>x=2, y=2</h1>
</div>
</div>
Where tab-page divs are absolutely positioned with 100% width and height, and tab-container is relatively positioned with 100% width and height of the browser.
var __MyMethods = {
width : 0
height : 0,
container : null,
// other stuff
setup : function(tab_container) {
// setup __MyPlugin.container = tab_container
// setup width, height of the container
},
/*
* Movement functions
*
*/
move : function(direction)
{
if( direction == 'left' )
{
__MyMethods.x--;
__MyMethods.translate( 'left', __MyMethods.width );
//
}
if( direction == 'right' )
{
__MyMethods.x++;
__MyMethods.translate( 'left', (-1)*__MyMethods.width );
//
}
if( direction == 'up' )
{
__MyMethods.y--;
__MyMethods.translate( 'top', __MyMethods.height );
}
if( direction == 'down' )
{
//
__MyMethods.y++;
__MyMethods.translate( 'top', (-1)*__MyMethods.height );
//
}
},
translate : function(property, offset)
{
// For each .tab-page in we animate the CSS property
$(__MyMethods.container).children(".tab-page").each( function() {
var animation = {};
var x = parseInt( $(this).css(property).replace('px','') ) + offset;
animation[property] = x.toString() + 'px';
$(this).animate(
animation,
{
'duration' : 0,
'queue' : false,
}
);
});
},
};
$.fn.MyPlugin = function()
{
__MyMethods.setup(this);
$(".btn").click( function(event)
{
__MyMethods.move( $(this).attr("move") );
console.log(this);
});
return this;
};
So I put
<button class="btn" move="up"></button>
<button class="btn" move="down"></button>
<button class="btn" move="left"></button>
<button class="btn" move="right"></button>
Somewhere in the HTML and it works fine for up, left, right... but if you click the move="down" button it works only the first time.
I don't know why is that hapening, the event never fires again if you click that button, I tried doing console.log(this) inside the click event function, but it doesn't show anything after the down button is clicked...
Any idea of what can be happening?
Thank you very much for any help you can give me
Edit: Here is a demo
Regards
In you jsfiddle the down button seems to stay behind the tab-page s. Giving z-index to menu and tab-page elements solves the problem.
In your css file:
Add
z-index: 10;
to .menu
Add
z-index: 1;
to .tab-page
css

Position fixed, but scroll on <body>

I have this situation:
my website, which I am creating, has a left sidebar, which must be set to height 100%, while scrolling the webpage, and the content inside it is definitely over 1000px height.
because of the height of the content, I get vertical scroll on this sidebar element, and when my content has enough content, I get another scroll for this section.
What I have to do is to, somehow, transfer, scroll from the "fixed" element to the main page scroll...
I hope that you can understand me...
I hope that this screenshot, can also help you to understand what I ask:
link
Thank you in advance for you answers.
Your question got me interested, so I gave it a try.
You could have your sidebar set up like so:
#sidebar{
position:fixed;
min-height:100%;
top:0;
left:0;
/* ... */
}
Now, to make it scroll, we can play with its margin-top css property:
If we scroll down, we decrement it unless we scrolled past its
height.
If we scroll up, we increment it unless it's above zero.
I created a ScrollingSidebar class with 2 functions in order to deal with that:
// ScrollingSidebar class
// Define some variables and bind events
function ScrollingSidebar(el){
this.sidebar = el;
var that = this;
that.updateVariables();
document.addEventListener('scroll',function(){that.scrollSidebar();});
window.addEventListener('resize',function(){that.updateVariables();});
}
// Updates variables used for calculation
ScrollingSidebar.prototype.updateVariables = function(){
this.height = parseInt( getComputedStyle(this.sidebar).height );
document.body.style.minHeight = this.height + 'px';
this.winHeight = parseInt( window.innerHeight );
this.previousScrollPos = Math.floor( document.body.scrollTop ||
document.documentElement.scrollTop ||
document.body.parentNode.scrollTop
);
this.scrollSidebar();
};
// Updates the sidebar's margin-top
ScrollingSidebar.prototype.scrollSidebar = function(){
var curScrollPos = Math.floor( document.body.scrollTop ||
document.documentElement.scrollTop ||
document.body.parentNode.scrollTop
);
if(this.previousScrollPos < curScrollPos){
this.sidebar.style.marginTop = - Math.min(-parseInt( getComputedStyle(this.sidebar).marginTop ) + (curScrollPos - this.previousScrollPos),
this.height-this.winHeight) + 'px';
} else {
this.sidebar.style.marginTop = Math.min(0,parseInt( getComputedStyle(this.sidebar).marginTop ) + this.previousScrollPos-curScrollPos) + 'px';
}
this.previousScrollPos = curScrollPos;
};
You can use it like so:
// Create an instance of ScrollingSidebar
var sidebar = document.getElementById('sidebar');
var x = new ScrollingSidebar(sidebar);
JS Fiddle Demo (with a small amount of content)
JS Fiddle Demo (with a lot of content)
Note: I did not take the time to comment my code very well, but if you have any question about it or any problem with it, feel free to ask.
If your website is responsive and you don't want this method to be used on small screens, you might want to consider using a condition to disable it.

Jquery animate problem with potential variable scope issue?

I've written an example of my problem, for some reason (which I don't seem to fully understand I guess), my variables are losing scope. I'm trying to animate several things on the screen, once they've reached their destination the 'complete' function within animate() kicks in, this is meant to basically delete the dom element as well as a couple other functions that are meant to be delayed within it. A good way to think of it is a gun firing, do the damage when the bullet hits and not before, and the damage the bullet does is tied into the animation itself.
As I mentioned in my first sentence, I've written an example to demonstrate exactly what I mean. I'll also paste in the console.log output that came with it and give a summary of what it shows.
I've placed the example in jsbin, as it should be easier for you guys to see (I hope -- I've never used that stuff before). For my example I just did an animation of a square block filling, and some squares flying near it. When those squares reach its destination, it empties some out of the 'Jar' and resets its animation, then it removes itself from the dom.
http://jsbin.com/ihozil/2
Here's the console.log text from chrome:
Set Height to: 30px
Testing.Start( [Object] )
Setup #I63326848.animate()
Setup #I22596539.animate()
Setup #I14561405.animate()
Setup #I57372916.animate()
Setup #I31994195.animate()
OnComplete for :I63326848
Set Height to: 30.6px
OnComplete for :I14561405
Set Height to: 33px
OnComplete for :I57372916
Set Height to: 34.2px
OnComplete for :I31994195
Set Height to: 36px
OnComplete for :I63326848
Set Height to: 36.6px
Finished filling
As you can see from the log above, #I22596539 (2nd one) was set up, however when it came to the OnComplete methods, it did not fire, all the others did and #I63326848 fired twice (1st method setup). I've also noticed that when I remove the .stop() part of the chain on the squared box (#Jar), that these problems do not happen. However that is needed so I don't end up with several animations trying to fill the jar at the same time. I've also noticed that it's ALWAYS the second animation to be set up that does this.
So I'm not entirely sure if it's variables losing scope, else surely this would happen to the others, I've sent the last couple of days trying to suss this one out and I've hit my road block. I've ran out of things to try to fix it. You guys are my last hope!
function Jar() {
this._iAmount = 50;
this._iMaxAmount = 100;
this._iRefillRate = 5;
return this;
}
Jar.prototype = {
ReduceAmount: function( m_iAmount ) {
this._iAmount -= m_iAmount;
if( this._iAmount < 0 ) {
this._iAmount = 0;
}
return;
},
StartFill: function() {
var iHeight = ( 60 - ( 60 * this._iAmount / this._iMaxAmount ) );
console.log( "Set Height to: "+iHeight+"px" );
jQuery( '#Jar' ).css( 'height', iHeight+'px' );
if( iHeight < 60 ) {
var iMillisecondsTilMax = ( ( this._iMaxAmount - this._iAmount ) / this._iRefillRate ) * 1000;
jQuery('#Jar').stop().animate({height: '0px'}, iMillisecondsTilMax, function() { console.log( "Finished filling" ); } );
}
return;
}
};
var Testing = {
Start: function( m_oJar ) {
console.log( "Testing.Start( [Object] )" );
for( var iLoop = 0; iLoop < 5; iLoop++ ) {
var elNewDiv = document.createElement('div');
var iRandomValue = Math.round( 1 + ( Math.random() * ( 99999999 - 1 ) ) );
var iAmount = Math.round( 1 + ( Math.random() * ( 5 - 1 ) ) );
var strID = "I"+iRandomValue;
elNewDiv.setAttribute( 'id', strID );
elNewDiv.style.border = 'solid 1px red';
elNewDiv.style.position = "absolute";
elNewDiv.style.height = '200px';
elNewDiv.style.width = '200px';
elNewDiv.style.left = '0px';
elNewDiv.style.top = '0px';
document.body.appendChild( elNewDiv );
this.Animate( m_oJar, strID, iAmount );
}
return;
},
Animate: function( m_oJar, m_strID, m_iAmount ) {
console.log( "Setup #"+m_strID+".animate()" );
jQuery( '#'+m_strID ).animate({ width: '30px', height: '30px', top: '100px', left: '200px' }, {
duration: 1000,
queue: false,
easing: 'linear',
complete: function() {
console.log( "OnComplete for :"+m_strID );
m_oJar.ReduceAmount( m_iAmount );
m_oJar.StartFill();
jQuery( '#'+m_strID ).remove();
}
});
}
};
jQuery(document).ready( function() {
var oJar = new Jar();
oJar.StartFill();
Testing.Start( oJar );
});
I don't have a great answer, but I think this might be a jQuery bug. I have been able to work around the issue by modifying the StartFill method, or just not calling it the first time in the ready() function. I've also seen it go away when I use the debugger which leans towards some sort of timing issue...possibly in jQuery, possibly in the browser. I've not tested this on anything other than Chrome so it's hard to be sure. However I don't think there is anything wrong with the logic in your code provided.

Javascript slide element

I want to know what's the best technique to slide an element just like in these examples:
http://demos.flesler.com/jquery/localScroll/#section1c
But with Pure Javascript so NOT jQuery or any library.
Example structure
<div id="holder">
<div id="bridge" onclick="slide('content')">Click to slide</div>
<div id="content" style="display:block;">The content</div>
</div>
So if I click on id=bridge the id=content will slide up and sets it's display to none and If I click on it again then sets it's display to block and slides down;
The sliding animation itself, like all animation in javascript, is done using timer functions: setTimeout or setInterval. For simple effects like this I always prefer setTimeout since it's easier to end the animation sequence compared to setInterval. How it works is to change CSS attribute values using setTimeout:
// move the content div down 200 pixels:
var content = document.getElementById('content');
function moveDown () {
var top = parseInt(content.style.marginTop); // get the top margin
// we'll be using this to
// push the div down
if (!top) {
top = 0; // if the margin is undefined, default it to zero
}
top += 20; // add 20 pixels to the current margin
content.style.marginTop = top + 'px'; // push div down
if (top < 200) {
// If it's not yet 200 pixels then call this function
// again in another 100 milliseconds (100 ms gives us
// roughly 10 fps which should be good enough):
setTimeout(moveDown,100);
}
}
That's essentially the basics of animation in javascript. The idea is very simple. You can use any CSS style attribute for animation: top and left for absolutely or relatively positioned elements, margins like my example, width, height, transparency etc.
Now, as for what to use in your specific case depends on exactly what your intentions are. For example, the simplest thing to do what you describe would be to change the div height until it becomes zero. Something like:
function collapseContent () {
var height = parseInt(content.style.height);
if (!height) {
height = content.offsetHeight; // if height attribute is undefined then
// use the actual height of the div
}
height -= 10; // reduce height 10 pixels at a time
if (height < 0) height = 0;
content.style.height = height + 'px';
if (height > 0) {
// keep doing this until height is zero:
setTimeout(collapseContent,100);
}
}
But that's not how the example jQuery plugin does it. It looke like it moves the element by shifting its top and left style attribute and hides content off screen by using a container div with overflow:hidden.
My solution uses a css transition:
<style type="text/css">
#slider {
box-sizing: border-box;
transition: height 1s ease;
overflow: hidden;
}
</style>
<div id="slider" style="height: 0">
line 1<br>
line 2<br>
line 3
</div>
<script>
function slideDown(){
var ele = document.getElementById('slider');
ele.style.height = "3.3em";
// avoid scrollbar during slide down
setTimeout( function(){
ele.style.overflow = "auto";
}.bind(ele), 1000 ); // according to height animation
}
function slideUp(){
var ele = document.getElementById('slider');
ele.style.overflow = "hidden";
ele.style.height = "0";
}
</script>

Categories