Animate a div down and up using Jquery on click - javascript

Need help in animating a div up on click and down via the same click link. Here is my Javascript below:
$(function() {
// global functions
var dash = $('#Dashboard');
var dashBtn = $('#dashClick');
var state = dash.css({
"top":600
});
var clicked = dashBtn.click(function(e) {
e.preventDefault();
if(clicked) {
dash.animate({"top":0});
}
if(state > 0 && clicked) {
dash.animate({"top":600});
}
});
//make it height of document
dash.height($(document).height());
});
and my HtML below showing the references to the javascript with the ID's:
<a id="dashClick" href="#">Dashboard</a>
<div id="Dashboard">
<h2 class="dashTitle">Project Information</h2>
<div class="dashInnerAdd">
<p>
Project name: CSS3 Effects N' Stuff
My github is: https://github.com/Amechi101/css3effects
</p>
</div>
</div>
</main> <!-- end grid main-->
</div>
<!--end wrap -->

Among other things (see the code for all changes):
If you want to use top, you probably are wanting it to behave like it does with absolute positioning. To do that, you need a container with relative positioning around the #Dashboard. Also, your javascript animate needs px values. "top":600 should really be top:"600px".
html:
<a id="dashClick" href="#">Dashboard</a>
<div class="container">
<div id="Dashboard">
<h2 class="dashTitle">Project Information</h2>
<div class="dashInnerAdd">
<p>
Project name: CSS3 Effects N' Stuff
My github is: https://github.com/Amechi101/css3effects
</p>
</div>
</div>
</div>
js:
$(function() {
// global functions
var dash = $('#Dashboard');
var dashBtn = $('#dashClick');
var clicked = false;
dashBtn.click(function(e) {
e.preventDefault();
if(clicked === true) {
clicked = false;
dash.animate({top:"0px"});
} else {
clicked = true;
dash.animate({top:"600px"});
}
});
//make it height of document
dash.height($(document).height());
});
and some css:
.container {
position: relative;
}
#Dashboard {
position: absolute;
top: 0;
}
fiddle: http://jsfiddle.net/SQK78/2/
If you don't need the absolute positioning, you can just change top to marginTop, and you can get rid of the container wrapper as well as all of the css in that fiddle.

Your main javascript only executes once. You need to track state from within the click handler. Try this:
$(function() {
// global functions
var dash = $('#Dashboard');
var dashBtn = $('#dashClick');
var state = true;
dashBtn.click(function(e) {
state = !state;
e.preventDefault();
if(state) {
dash.animate({"top":20});
}
if(!state) {
dash.animate({"top":600});
}
});
//make it height of document
dash.height($(document).height());
});

Related

jQuery animation with knockout beforeAdd and afterRemove

I wan't to animate tabs divs. When closing, the width is animated to 0px, and when opening, it is animated from 0px to the size of it's inner content.
https://jsfiddle.net/rrfogrku/5/
but the expected behaviour not work, closed div are not removed from DOM after the fadeOut function is called, and when I add a new tab, there is no animation.
Html:
<div class="main">
<div class="tab-list">
<!-- ko foreach: {data: editors, afterAdd: fadeIn, beforeRemove: fadeOut} -->
<div class="tab" data-bind="
css: { active: isSelected },
click: $parent.select" >
<span data-bind="text: title"></span>
<button data-bind="click: $parent.close">x</button>
</div>
<!-- /ko -->
<div class="plus">
<button data-bind="click: add">+</button>
</div>
</div>
</div>
Javascript
function MainViewModel() {
var self = this;
var storage = localStorage;
self.editors = ko.observableArray([new EditorViewModel("default.txt", "some content")]);
self.close = function(item){
self.editors.remove(item);
if(self.editors().length == 0){
self.add();
}
else if(!self.editors().some(val=>val.isSelected())){
self.select(self.editors()[0]);
}
}
self.select = function(item){
for(var i in self.editors()){
self.editors()[i].isSelected(false);
}
item.isSelected(true);
}
self.add = function(){
var editor = new EditorViewModel("sans-titre.js", "");
self.editors.push(editor);
self.select(editor);
}
self.fadeIn = function(el){
var $el = $(el);
var w = $el.width();
$el.css({ width: '0px' });
$el.animate({width : w });
}
self.fadeOut = function(el){
$(el).animate({ width: '0px'});
}
if(self.editors().length >0){
self.select(self.editors()[0]);
}
};
function EditorViewModel(title, initialContent){
var self = this;
self.title = ko.observable(title);
self.content = ko.observable(initialContent);
self.isSelected = ko.observable(false);
}
var viewModel = new MainViewModel();
ko.applyBindings(viewModel);
In the example in the knockout docs, you can see that you need to check for the nodeType of the added element, since knockout can include multiple elements from the template and we're only interested in the <div>:
if (el.nodeType === 1) { /* do work */ }
This page explains that, when using beforeRemove:
Knockout cannot know how soon it is allowed to physically remove the DOM nodes (who knows how long your animation will take?), so it is up to you to remove them
So for your fade out animation, you'll have to add the code that updates the DOM:
$(el).animate({
width: '0px'
}, 500, () => $(el).remove());
// ^^^^^^^^^^^^^^^^^^^^---- remove element after animation is done
Here's the two changes in an updated fiddle:
https://jsfiddle.net/1Lwfqpxk/
Free bonus tip: add white-space: nowrap; to your .tab css to prevent the reflow during the width animation.

Moving between 4 buttons and have roll overs stay clicked between

I have seen a few things close to what I want but am not sure how to implement to what I'm doing.
The below code all works fine but have now been asked to make the hover stay in place when each button is clicked. How would I go about this? Or is it better to start again using buttons and not divs?
Here is a jsfiddle (not sure why all the divs are showing here, live only the first one does which is correct)
Example of button:
<div id="tab1" class="tab" style="height:50px; width:160px; background-color:#CCC; float:left;">
<img src=".../images/landing/terms-coach.jpg" onmouseover="this.src='.../images/landing/terms-coach-col-2.jpg'" onmouseout="this.src='.../images/landing/terms-coach.jpg'" />
</div>
https://jsfiddle.net/uqxdum1o/
I've modified the markup and JS a bit to get there but I think this code should fulfil the tab requirement and remove some of the inline JS.
Essentially, store the active image src in an attribute for each tab button:
<div id="tab1" class="tab" style="..."
data-image-active="./images/button1-active.jpg"
data-image="./images/button1.jpg">
<img src="./images/button1.jpg" />
</div>
Then use this to set active state in your javascript for each tab button. I've moved your current code for click handling into this each loop too.
$(document).ready(function(){
var $contents = $('.tab-content');
$contents.slice(1).hide();
$('.tab').each(function() {
$(this).hover(function() {
setButtonActive($(this));
}, function() {
if (!$(this).hasClass('active')) {
setButtonInactive($(this));
}
});
$(this).click(function() {
resetAllButtons();
setButtonActive($(this));
$(this).addClass('active');
var $target = $('#' + this.id + 'show').show();
$contents.not($target).hide();
})
});
});
function setButtonActive(button) {
var img = button.find('img'),
imgSrc = button.attr('data-image-active');
img.attr('src', imgSrc);
}
function setButtonInactive(button) {
var img = button.find('img'),
imgSrc = button.attr('data-image');
img.attr('src', imgSrc);
}
function resetAllButtons() {
$('.tab').removeClass('active').each(function() {
setButtonInactive($(this));
});
}

Change Div and Body Class on Refresh

I'm using this Backstretch plugin to apply a stretched background image to my body element.
$("body.apples").backstretch("/apples.jpg");
$("body.oranges").backstretch("/oranges.jpg");
$("body.pears").backstretch("/pears.jpg");
I want my body class to change on refresh, so it shows the different background images on refresh. I'm also trying to work out how to only show the related .wrapper div below when the page is refreshed.
<body class="apples">
<div class="wrapper apples">
<h1>Something about Apples</h1>
<p>Some content</p>
</div>
<div class="wrapper oranges">
<h1>Something about Oranges</h1>
<p>Some content</p>
</div>
<div class="wrapper pears">
<h1>Something about Pears</h1>
<p>Some content</p>
</div>
</body>
I've managed to get the .wrapper div to change on refresh with this bit of JS:
function randomFromTo(from, to) {
return Math.floor(Math.random() * (to - from + 1) + from);
}
function RandomFruit() {
var r = randomFromTo(1, $('.wrapper').length);
$('.wrapper').hide().eq(r - 1).show();
}
$(document).ready(function() {
RandomFruit();
});
I've got a working demo here: http://codepen.io/realph/pen/KCEtB
For some reason, I can't work out how to make the background and .wrapper div change.
Any help with this is appreciated. Thanks in advance.
Maybe you can do it with an if else statement? And you would only need 1 wrapper
if ( $("body").hasClass("yourfruithere") ) {
$(".wrapper").html("<h1>Something about this fruit</h1><p>some content</p>");
You can detect the class of the body after the page loads, store that class as a variable, and show only the related content that also has that class:
fiddle
HTML:
<div class="oranges">
<p class="oranges">Oranges</p>
<p class="apples">Apples</p>
<p class="pears">Pears</p>
</div>
jQuery:
$(function() {
var activeClass = $('div').attr('class');
$('p').hide(),
$('p.' + activeClass).show();
});
This function runs on document load just as a demo, but you would want to make sure you store the body's class as a variable after it loads on the page and is dynamically set by your other JS. Otherwise you may end up with a class of null.
I don't know how comfortable you are working with objects in javascript, but here is one solution to your problem:
Create a Fruit object that contains the class name for the body, its own element, and its own image. Each fruit object would have a Show() method that would change the class of the body element, the background image, and show itself. It would also have a Hide() method for hiding itself.
Create an array of Fruit objects, and randomize an index. Call Hide() on all of them, and then Show() on the chosen one.
Here is one implementation:
var run = function () {
var apples = new Fruit(
'apples',
$('.apples'),
'apple.jpg');
var oranges = new Fruit(
'oranges',
$('.oranges'),
'orange.jpg');
var pears = new Fruit(
'pears',
$('.pears'),
'pear.jpg');
var fruitBasket = new FruitBasket([apples, oranges, pears]);
fruitBasket.displayRandomFruit();
}
var Fruit = function (className, element, image) {
this.show = function () {
$(element).show();
$('body').backstretch(image);
$('body').removeClass().addClass(className);
}
this.hide = function () {
$(element).hide();
}
}
var FruitBasket = function (fruitList) {
this.displayRandomFruit = function () {
var randomFruitIndex = Math.floor(Math.random() * fruitList.length);
for (var i = 0; i < fruitList.length; i++) {
fruitList[i].hide();
}
fruitList[randomFruitIndex].show();
}
}
$(document).ready(function () {
run();
});
Here it is on jsfiddle.

jquery animations happen randomly

I have a kind of splash screen, where you press one of the logo's and it animates the logo to the center, then loads the content for it. Then when you press the main top logo, it hides the content and goes back to the splash screen. However I am having problems with this.
Such as, the container hides, then comes back.
Look for yourself: http://dan.roguedraco.net/SpyroDev/
If happens if you click the top logo before the content has fully appeared, but I want to allow for all these occurences. Because it is possible a user may do the same.
Javascript:
$(document).ready(function() {
var inPage = false;
$('.ajax-loader').click(function() {
if(inPage == false) {
inPage = true;
var Obj = this;
$(Obj).siblings("a").fadeOut(500,function() {
if($(Obj).hasClass('left') || $(Obj).hasClass('right')) {
$(Obj).animate({left:'300px'},'slow','easeOutBack',function() {
$('#pageContent').fadeIn(500,function() {
$("#tabs").tab();
});
});
}
else {
$('#pageContent').fadeIn(500,function() {
$("#tabs").tab();
});
}
$(Obj).addClass('current-project');
});
}
});
$('#rootLogo').click(function() {
var Obj = $('.current-project');
if(inPage == true) {
inPage = false;
$('#pageContent').fadeOut(500,function() {
$(this).hide();
if($(Obj).hasClass('left')) {
$(Obj).animate({left:'0px'},'slow','easeOutBack',function() {
$(Obj).siblings("a").fadeIn(500);
});
}
else if($(Obj).hasClass('right')) {
$(Obj).animate({left: '600px'},'slow','easeOutBack',function() {
$(Obj).siblings("a").fadeIn(500);
});
}
else {
$(Obj).siblings("a").fadeIn(500);
}
$(Obj).removeClass('current-project');
});
}
});
});
Html:
<div id="thumbnails">
<div class="row-fluid">
<div class="span12" style="text-align: center;color:#fafafa;">
Click a plugin title for more information and downloads.
</div>
</div>
<div class="row-fluid">
<div class="span12" id='thumbnails'>
<img src="projects/JumpPorts/thumb.png" alt="JumpPorts" />
<img src="projects/RankUpOnKills/thumb.png" alt="RankUpOnKills" />
<img src="projects/InfoButton/thumb.png" alt="InfoButton" />
</div>
</div>
</div>
<div id="pageContent" style="display:none;">
<div class="row-fluid">
...
.stop()
have you tried to use .stop() before your .animate() and .fadeIn() and other animate methods? like: $(Obj).stop().animate({left:
Have you consider to not make the "" of the logo itself clickable? I mean, you're making your event ready whenever it's clicked.
Try this:
In the event of .ajaxloader add on the logo image a sorrounding it at the end of the code of the event.
Then you switch:
$('#rootLogo').click(function() {
var Obj = $('.current-project');
....
}
for this:
$('#click-event').click(function() {
// Assuming #click-event is the name of the span you placed
var Obj = $('.current-project');
.....
}
and in the end you delete the span created on the .ajaxloader.click event
It's an idea, you can use it, tell me if it worked

How to detect mouseleave() on two elements at once?

Answer can be in vanilla js or jQuery. I want to hide a div with the id "myDiv" if the user is no longer hovering over a link with the id "myLink" or a span with the id "mySpan". If the user has his mouse over either element "myDiv" will still show, but the second the user is not hover over either of the two (doesn't matter which element the user's mouse leaves first) "myDiv" will disappear from the face of existence.
In other words this is how I detect mouse leave on one element:
$('#someElement').mouseleave(function() {
// do something
});
but how to say (in a way that will actually work):
$('#someElement').mouseleave() || $('#someOtherElement').mouseleave()) {
// do something
});
How to detect this?
Something like this should work:
var count = 0;
$('#myLink, #mySpan').mouseenter(function(){
count++;
$('#myDiv').show();
}).mouseleave(function(){
count--;
if (!count) {
$('#myDiv').hide();
}
});
jsfiddle
You could use a multiple selector:
$("#someElement, #someOtherElement").mouseleave(function() {
// Do something.
});
You can beautifully use setTimeout() to give the mouseleave() function some "tolerance", that means if you leave the divs but re-enter one of them within a given period of time, it does not trigger the hide() function.
Here is the code (added to lonesomeday's answer):
var count = 0;
var tolerance = 500;
$('#d1, #d2').mouseenter(function(){
count++;
$('#d3').show();
}).mouseleave(function(){
count--;
setTimeout(function () {
if (!count) {
$('#d3').hide();
}
}, tolerance);
});
http://jsfiddle.net/pFTfm/195/
I think, it's your solution!!!
$(document).ready(function() {
var someOtherElement = "";
$("#someElement").hover(function(){
var someOtherElement = $(this).attr("href");
$(someOtherElement).show();
});
$("#someElement").mouseleave(function(){
var someOtherElement= $(this).attr("href");
$(someOtherElement).mouseenter(function(){
$(someOtherElement).show();
});
$(someOtherElement).mouseleave(function(){
$(someOtherElement).hide();
});
});
});
----
html
----
<div id="someElement">
<ul>
<li>element1</li>
<li>element2</li>
</ul>
</div>
<div id="tab1" style="display: none"> TAB1 </div>
<div id="tab2" style="display: none"> TAB1 </div>
While the answer from lonesomeday is perfectly valid I changed my html to have both elements in one container. I originally wanted to avoid this hence I had to do more refactoring for my clients in other html templates, but I think it will pay out on the long term.
<div id="my-container">
<div class="elem1">Foo</div>
<div class="elem2">Bar</div>
</div>
$('#my-container').mouseleave(function() { console.log("left"); });

Categories

Resources