How to execute code after 3rd party slide down animation? - javascript

Background:
I am using the materialize JS to create collapsible divs. When a div that has a class of collapsible-header is clicked, a slide down animation occurs on the sibling div that has a class of collapsible-body, showing the contents of the collapsible-body.
What I am trying to accomplish is when a collapsible header is clicked, the browser should scroll to the top of that div so that the contents are in full view of the user. I have used an on click event, which works fine on the first collapsible. But then, if you have an open collapsible and you click on another to open it, it doesn't scroll to the top of the clicked div properly (it will scroll to the middle of the body, or way above the top of the div).
JS Fiddle of on click functionality: https://jsfiddle.net/f83dct8f/4/
I am able to accomplish what I am looking to do by editing the Materialize JS itself. Here is how the line looks before my edit:
object.siblings('.collapsible-body').stop(true, false).slideDown({
duration: 350,
easing: "easeOutQuart",
queue: false,
complete: function() {
$(this).css('height', '');
}
});
I add the following to the complete portion of the above statement to accomplish what I'm looking for:
$('body').animate({scrollTop: $('.collapsible-header.active').offset().top },'slow');
Question: I do not want to edit the Materialize 3rd party code to accomplish what I need, so I need to find a way to implement the body animate code after the slide down is finished, without editing the Materialize animation. I know there has to be a way to do it?
I have tried event queues on the collapsible body, which seemed promising, but my test console print executed during the animation. See below. If someone could point me in the right direction of what else I could try, I would greatly appreciate it.
$('.collapsible-header.active')
.siblings('.collapsible-body').slideDown().queue(function(){
console.log('DONE');
});

You should be able to use the onOpen option when initialising your .collapsible. Pass in a function to execute when the accordion is opened. The function receives the element as a argument.
$(document).ready(function() {
$('.collapsible').collapsible({
onOpen: function(el) {
$('body').animate({scrollTop: el.offset().top },'slow');
}
});
});

Related

How to make Intro.js select the element that dynamically generated after page load

JsFiddle: JsFiddle
I have a bootstrap popover window and a button to call the popover out.
My goal is: I want to have Intro.js feature to introduce:
step 1: click the button;
step 2:Here is the popover window.
Intro.js provides an option that can pre-define the steps programmically. So here's my code of introjs:
var intro2 = introJs();
intro2.setOptions({
exitOnOverlayClick: true,
showBullets: false,
//showStepNumbers: false,
steps: [
{
element: document.querySelector('#saveSelection'),
intro: "Click this button to call popover window.",
position: 'top'
},
{
element: document.querySelector('.popover.fade.top.in'),
intro: "popover windown",
position: 'top'
},
],
}).setOption('doneLabel', 'Close').start();
});
But my problem is that while I was in the introJs layout(step1), it located the button but this time popover window wasn't called out. Then I went ahead to click the button, popover called out, then I click next on Introjs, it couldn't locate my popover window.
The reason probably is because when introJs was initialized at the first time. it has already scanned those elements in the steps I defined in intro2.setOptions, but since the popover is a dynamic element so introJs couldn't find a popover named class="popover fade top in" at the initial stage.
Same issue happened for bootstrap Modal.
Any solutions?
If anyone is still looking for a solution on google, I figured out a working solution that can be applied to other cases of attaching a step's element to dynamic objects.
On the intro object init, add the following to enable step-specific function calls before loading the step. (function creds)
intro2.onbeforechange(function(){
if (this._introItems[this._currentStep].preChange) {
this._introItems[this._currentStep].preChange();
}
});
Within the popover step, use the preChange attribute to call a function and dynamically set the element and position of that step.
{
intro: "popover windown",
preChange: function(){
this.element = document.querySelector('.popover.fade.top.in');
this.position = "top";
}
},
Note that the code in general will break if the popover is not active when moving onto to the popover step, so you would want to enforce/check if the popover is open before moving onto that step. Otherwise, assuming that the popover is visible in this example, it functions as expected
JSFiddle
If I'm not mistaken, you have the same problem as asked Event binding on dynamically created elements?
On that case you have to bind a function to the dinamic created element.

jQuery Isotope doesn't rearrange properly after items have been dynamically adjusted

I have an isotope layout and everything - sorting and filtering and general display - works great. But I have to make the isotope items expandable on click. I did this via a span class which is hidden via JavaScript on initial page load but can be toggled via click on a different span class <span class='Point'>.
This works to a certain degree: the text is toggable - but the layout doesn't resize on click, despite me including .isotope('layout'). The specific jQuery code looks as follows:
$(".risknotes").hide(); $grid.on( 'click', '.Point', function() {
$(this).parent().find(".risknotes").toggle(2000);
$(this).parent().toggleClass('bigger');
$grid.isotope('layout')
});
Funny thing is: if I click a filter, or a sort button, everything resizes perfectly. Just not on initial load or click. I made a jsfiddle reproducing the problem: http://jsfiddle.net/3t2fk5aq/
Your problem is jquery take a time to finish toggle .ricknotes but isotope relayout instantly.
You can use complete option of .toggle() to handle it like this:
$grid.on('click', '.Point', function() {
$(this)
.parent()
.find(".risknotes")
.toggle({ duration: 200,complete: function(){ $grid.isotope('layout') } });
$(this)
.parent()
.toggleClass('bigger');
});

Button that displays and hides a sliding menu

I'm trying to build a header with a menu button that triggers a sliding menu. I can make the menu appear when I press the button, but I also want it to dissappear when I click the button again.
This is the event that triggers when the button is clicked.
$('#nav-button').click(function () {
$("#slidermenu").animate({right: "0px"}, 200);
$("body").animate({right: "300px"}, 200);
});
I looked up the animate method and saw that it has a function called done, which takes two parameters. A promise and a boolean. So I figured I can use a if-statement to check if the animation is done, and if the animation is done, the button would send the slidermenu back.
But how can I test if animate().done() is true? Or is there a more simple way of achiveing this?
Here is my fiddle.
.is(':animated') will return true if it's currently being animated.
In the context of what you're trying to do:
if(!$('#slidermenu').is(':animated'))
{
// Animation has finished
}
As an aside:
I try and do this with CSS only now where possible. If you use jQuery toggleClass and predefine the right attributes in your CSS for the toggled classes, you can add a CSS transition to deal with the animation. Just thought it was worth mentioning (this does come with it's own compatibility issues).
Like DeeMac said, it may be better to do this with css transition instead of jQuery animate. But just to add an option, I'll try to show you how to get this to work with jQuery animation also.
First of all, instead of inspecting if the animation is still running or not, you can just stop the ongoing animation before starting another. It will make the button to respond immediately to the users clicks.
For finding out if the menu is open or not, you can use toggleClass. This way you can just use hasClass to determine in which direction you need to animate the menu.
So, this what I came up with:
$('#nav-button').click(function () {
$("#slidermenu").stop();
animateToPosition = "0px";
if ($("#slidermenu").hasClass("open")) {
animateToPosition = "-300px";
}
$("#slidermenu").toggleClass("open");
$("#slidermenu").animate({
right: animateToPosition
}, 200);
});
I made a Demo. If you are going with the css solution, it's fine. Maybe this will help someone else in the future.

How to slideDown a fixed div once you press another button

What I am trying to do
Close a div with a secondary button and mimicking the slideDown script from the first button.
The problem
Once the footer button is pressed it displays my hidden div (#footerPanel) by pushing the header up. Once you click footer again it closes the panel and slides the header back into place.
The menu button will work as follow, once you hover over the button the site navigation will display (not included in JSFiddle). By having this I would like to have the ability to close the #footerPanel and have the header slide down, mimicking the close ability from the footer button.
What is happening now is, when I click menu the #footerPanel slides down but leaving the header stuck at the position where the div pushed it. Also when you move the mouse the div slides back up.
How can I go about fixing this issue? I tried a few solution but they all seem to have the same outcome.
The js
$('#more').toggle(function(){
//show its submenu
$('#footerPanel').slideDown(500);
$(this).parent().parent().animate({'bottom': "+=400"}, 500);
},
function () {
//hide its submenu
$('#footerPanel').slideUp(500);
$(this).parent().parent().animate({'bottom': "-=400"}, 500);
});
$(document).ready(function(){
$('#menu').hover(function(){
$("#footerPanel").slideToggle();
});
});
JSFiddle
Updated Fiddle: http://jsfiddle.net/9s33F/5/
I think I have what you are looking for. I added the following as a callback for when the animate function completes when opening the menu.
function () {
$(this).addClass('open');
}
Then in the click handler for menu add the following if statement:
if ($(this).closest('header').is('.open')) {
$('header').animate({'bottom': "-=400"});
}
Also, you're code will look cleaner and be less if you used .closest() rather than .parent().parent() and so on.
jQuery.closest: http://api.jquery.com/closest/

jquery show/hide content based on button

I have a product page and i would like to add a tech spec button to the page which will open and close a show hide that is to be situated below the product description. I need the user to be taken down to the tech spec when the show hide opens.
I think i need to use jquery but when the show/hide is hidden, i.e nobody has pressed the button the footer should come up, so there shouldnt be any white space.
any examples links that i could refer too?
could anyone be kind to make me a little jsfiddle?
Thanks
Really simple with jQuery slideToggle:
http://jsfiddle.net/r7Qf7/12/ (example with new scrolling on button click).
Scrolling to the tech specs section once the button is clicked can be accomplished with the animate function in jQuery, like so.
$('html,body').animate({
scrollTop: $("#techspecs").offset().top
}, 'slow');
First, you've got to add the click event to the button, after the document is ready:
$(document).ready(function(){
$("#Button_ID").click(function(){
$('#Tech_Spec').toggle();
});
});
jsfiddle: http://jsfiddle.net/YEtBy/

Categories

Resources