I can add an overlay, but I can't remove it (jQuery) - javascript

This function adds an overlay with the following properties to the entire browser screen,
$('a.cell').click(function() {
$('<div id = "overlay" />').appendTo('body').fadeIn("slow");
});
#overlay
{
background-color: black;
width: 100%;
height: 100%;
position: fixed;
top: 0;
left: 0;
display: none;
z-index: 100;
opacity: 0.5;
}
And this function is supposed to remove it.
$('#overlay').click(function() {
$(this).fadeOut("slow").remove();
});
But it seems to do absolutely nothing and now my page is stuck with a black overly over it. What's wrong with the removal?

The problem is that when you're adding the click handler, there isn't any overlay, so you're adding the handler to an empty set of elements.
To fix this, use the live method to bind your handler to all elements that match #overlay, whenever they are created.
Also, fadeOut is not a blocking call, so it returns before the element finishes fading out. Therefore, you're calling remove right after the element starts fading out.
To fix this, use fadeOut's callback parameter to call remove after the animation finishes.
For example:
$('#overlay').live(function() {
$(this).fadeOut("slow", function() { $(this).remove(); });
});

Here you go. This should fix the problem and let the overlay fade out before removing it.
$('#overlay').live("click", function() {
$(this).fadeOut("slow", function() { $(this).remove() });
});

Remove should be in the callback to fadeout, like so:
$('#overlay').live('click', function() {
$(this).fadeOut("slow", function() {
$(this).remove();
});
});

Try:
$('#overlay').live('click', function() {
$(this).fadeOut("slow").remove();
});

My recommendation is to use the jquery.tools overlay plugin. Your overlay will have a trigger (usually a button or link), but you can load or clear it with a javascript command, e.g.:
js:
var config = { closeOnClick:true, mask:{opacity:0.7, color:'#333', loadSpeed:1} }
$("#myTrigger").overlay(config); // add overlay functionality
$("#myTrigger").data("overlay").load(); // make overlay appear
$("#myTrigger").data("overlay").close(); // make overlay disappear
html:
<div id="myOverlay" style="display:none;">Be sure to set width and height css.</div>
<button id="myTrigger" rel="#myOverlay">show overlay</button>

Related

slideToggle() Function does not work after scaling down

I got a confusing bug inside my code and do not know how to fix it. I got to main functions, calling scripts depending on the current window size.
For mobile devices I got a slideToggle() function, which does work when viewing on a mobile device. But when opening above 600px, and scaling down the function is fired, but the slideToggle(); does not work anymore.
Its set to display: block; and immediately set to display: none; again. My slideToggle(); is embedded like this:
$('.box-header').on('click', function() {
$(this).parent().toggleClass('folded').toggleClass('unfolded');
$(this).next('div').stop().slideToggle();
console.log('clicked');
});
JSFIDDLE DEMO
When viewing the demo its important to load the page while the window size is above 600px and than scale down to recreate the problem. If it works please try again, as it does work sometimes.
What am I missing? And is there a better approach to kill and call scripts depending on the viewers viewport after resize events?
Put the if in the click event:
$('.box-header').on('click', function() {
if ($(window).width() < 600) {
$(this).parent().toggleClass('folded unfolded');
$(this).next('div').stop().slideToggle();
} else {
//for other code here for medium+large screens
}
});
https://jsfiddle.net/5puqn9ts/1/
even use a class to toggle between the mobile and large screen, bind a click event to each
$(document).ready(function() {
$('body').on('click', '.mobile', function() {
$(this).parent().toggleClass('folded').toggleClass('unfolded');
$(this).next('div').stop().slideToggle();
console.log('clicked');
});
// init scripts for smartphone or desktops
var initScripts = function() {
if ($(window).width() < 600) {
$('.box-header').addClass('mobile');
}
if ($(window).width() >= 600) {
$('.box-header').removeClass('mobile');
/add class for medium screen then bind event to ti
}
}
initScripts();
var id;
$(window).resize(function() {
initScripts()
});
});
https://jsfiddle.net/75186j96/5/
Your function set an event in every call. Try this correct alternative:
var smartphoneFunctions = $('.box-header').on('click', function() {
$(this).parent().toggleClass('folded').toggleClass('unfolded');
$(this).next('div').stop().slideToggle();
console.log('clicked');
});
https://jsfiddle.net/75186j96/8/
To answer your question, you need to adjust your slideToggle() target to be .box-content rather than the abstract div as this will instead apply the toggle on the .box-header. Also your class toggling could be bundled.
The resulting code would be the following:
$('.box-header').on('click', function() {
$(this).parent().toggleClass('folded unfolded');
$(this).next('.box-content').stop().slideToggle();
console.log('clicked');
});
That being said, there are better ways of doing this.
You could tie your classes to the appearance of .box-content, like this:
.box-content {
transition: height 300ms;
overflow: hidden;
}
.box.folded .box-content {
max-height: 0;
}
.box.unfolded .box-content {
max-height: 300px;
}

Trigger jQuery events one after another

Hi I am trying to create an animation where one class is added only after the one before it is finished triggered.
$('.flipper').click(function(){
$('#first').addClass('first-flip');
$('#second').addClass('second-flip');
$('#fourth').addClass('fourth-flip');
});
so
$('#second').addClass('second-flip');
would only trigger when
$('#first').addClass('first-flip');
has finished its process.
so another way of explaining this would be.
Block A has a rotate effect added to it, after Block A is rotated, only then will Block B move 20 px right.
I basically just want to know how to create Jquery effects that trigger in sequential order.
You want to tie into transitionend or animationend. Here is an example using transitionend. After the box has finished moving, a new class is added which begins the next transition to turn the box blue.
var mydiv = document.querySelector("#mydiv");
document.querySelector("button").addEventListener("click", buttonHandler);
mydiv.addEventListener("transitionend", onEndHandler)
function buttonHandler() {
mydiv.classList.add("move-left");
}
function onEndHandler() {
mydiv.classList.add("turn-blue");
}
#mydiv {
background: red;
width: 10em;
height: 10em;
transition: 1s;
}
#mydiv.move-left {
transform: translateX(100px);
}
#mydiv.turn-blue {
background: blue;
}
<div id="mydiv"></div>
<button>Move div</button>
If you need the jQuery version, it's here:
var mydiv = $("#mydiv");
$("button").on("click", buttonHandler);
mydiv.on("transitionend", onEndHandler)
function buttonHandler() {
mydiv.addClass("move-left");
}
function onEndHandler() {
mydiv.addClass("turn-blue");
}
Nice resource: https://davidwalsh.name/css-animation-callback

while having elements slide, make wrapper div width decrease

I have a simple div wrapper called .falling within this div I have 10 small images. I created a simple function that allows them to 'slide down' when I desire. That code is below.
JS:
function slide(){
$(".falling").delay(100).fadeIn().animate({opacity: 1, top:"300px"},'slow');}
slide();
CSS:
.falling {
width: 500px;
left: 600px;
top: 60px;
position: absolute;
display:none;
}
The problem is; 2 things. One, at the end of the 'slide down' I would like to have the .falling wrapper width to DECREASE so down to maybe 250px; because I want the illusion the images are grouping together at the end. Each img has a shared class called .imgfall I would like to use this to make the images smaller in width at the bottom as well. So, maybe max-width: 25px;
function slide(){
$(".falling").delay(100).fadeIn().animate({opacity: 1, top:"300px"},'slow');
$(".falling").css("width", "250px"); // tried this before and after slide but doesn't resize after slide but instead before, so not working!
}
slide();
By calling a function as the last parameter in jquery's animate function, you basically call an 'on complete'. See: http://api.jquery.com/animate/
var $fallingShell = $(".falling");
var animateSlides = function(){
function slide(){
$fallingShell.delay(100).fadeIn().animate({opacity: 1, top:"300px"},'slow', function(){
$fallingShell.animate({"width":"250px"}, 500);
});
}
}
And the replay needs the inline css create by the js reset. See: http://api.jquery.com/css/
I think this is everything you need to reset, but this is a best guess having not seen the code.
var resetSlides = function(){
$(".falling").css(
"width":"auto",
"opacity":"0",
"top":"0px"
);
}
So then you can tie it all together with a click or timer or something, or even call the reset at the start of animateSlides();
$('button').on('click', function(){
resetSlides();
animateSlides();
});

Partially showing/hiding an element with jQuery

I have this basic script that makes an element show onmouseenter, and hide onmouseleave.
In HTML version works fine, but i need to display it in wordpress; but in WP didn't work.
Firebug shows the following error:
sidebar_animate is not defined
How can I fix this?
The script
<script language="javascript">
function sidebar_animate(px) {
$('#sidebar').animate({
'marginLeft' : px
});
}
</script>
Body
<div id="sidebar" onmouseenter="sidebar_animate('+180px');"
onmouseleave="sidebar_animate('-20px');"
style="background-color: red; width: 240px; height: 100px; position: absolute; left: -180px;" >
This is going to move
</div>
How about binding the event handlers with jQuery so your code is all in one spot:
<script language="javascript">
//wait for document.ready to fire so elements are available to manipulate
$(function () {
//setup object to convert the type of event fired to the pixel offset to apply for the event
var eventToPx = {
mouseenter : 180,
mouseleave : -20
};
//bind an event handler to the `#sidebar` element for `mouseleave` and `mouseenter`
$('#sidebar').on('mouseenter mouseleave', function (event) {
//animate this element's `margin-left` property to the specified number of pixels
//note that jQuery assumes pixels if you omit units
$(this).stop().animate({
marginLeft : eventToPx[event.type]
}, 500);
});
});
</script>
Here is a demo: http://jsfiddle.net/jasper/mYwqE/
Notice that I added .stop() to your code just before the .animate() call. It will stop the current animation if a new one is queued, so the animations won't queue-up if the user mouse-over's and mouse-out's the element many times rapidly.
Note that .on() is new as of jQuery 1.7 and in this case is the same as using .bind(): http://api.jquery.com/on

How do you listen for a HTML element moving in JavaScript?

I have an HTML element that I need to track another element. Specifically, I need to have the top left and top right corners of both elements be positioned the same. When a window gets resized, the resize event gets triggered and I can adjust the position of the dependent element. However, if the element being tracked is repositioned (but not resized), I do not see any DOM event.
How can we find out if a DOM element has been moved? We are using the latest jQuery.
Here is a code sample.
Note that elementOne and mouseTracking divs are there to show elements that get moved for "some" reason that is outside the control of my code.
This code works for the elementOne case.
MouseTrackingTracker does not track a moving element.
ResizerTracker does not put the border around the complete text in the overflow case.
I would like the trackingDivs to move and resize no matter the reason for the tracked element's reasons for changing.
This code relies on the window resize being the hooked event. Hooking some event that fires when the element changes its dimensions is closer to what I need.
<!DOCTYPE html>
<html>
<head>
<link href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/themes/base/jquery-ui.css" rel="stylesheet" type="text/css"/>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6/jquery.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/jquery-ui.js"></script>
<style type="text/css">
#elementOne { float : right;width : 200px; display:inline-block}
#resizer { float : left; display:inline-block}
.trackedDiv { width:50px; height:50px; background-color: blue }
.trackingDiv { position:absolute; z-index: 1; border:3px green; border-style: solid;}
</style>
<script>
$(function() {
$( window ).bind("resize",function(){
$("#elementOne").trigger("reposition");
$("#mouseTracking").trigger("reposition");
$("#resizer").trigger("reposition");
});
var repositionFunction = function(selfish, element){
var self = $(selfish);
var offset = self.offset();
var selfTop = offset.top;
var selfLeft = offset.left;
var selfWidth = self.width();
var selfHeight = self.height();
$(element).css({
top: selfTop,
left: selfLeft,
width : selfWidth,
height : selfHeight
});
}
$(document).mousemove(function(ev){
$("#mouseTracking").position({
my: "left bottom",
of: ev,
offset: "3 -3",
collision: "fit"
});
});
var timedShort = function() {
$('#resizer').html("Really short").resize();
setTimeout(timedLong, 10000);
}
var timedLong = function() {
$('#resizer').html("Really longggggggggggggggggggggggggggggggggggggggggggggggggggg text").resize();
setTimeout(timedShort, 10000);
}
setTimeout(timedLong, 10000);
$("#elementOne").bind("reposition",
function() { repositionFunction(this, "#elementOneTracker"); });
$("#mouseTracking").bind("reposition",
function() { repositionFunction(this, "#mouseTrackingTracker"); });
$("#resizer").bind("reposition",
function() { repositionFunction(this, "#resizerTracker"); });
});
</script>
</head>
<body>
<div class="trackedDiv" id="mouseTracking">tracks mouse</div>
<div class="trackingDiv" id="mouseTrackingTracker"></div>
<div style="clear:both;"></div>
<div class="trackedDiv" id="resizer">resizer: resizes</div>
<div class="trackingDiv" id="resizerTracker"></div>
<div class="trackedDiv" id="elementOne">elementOne: floats to the right</div>
<div class="trackingDiv" id="elementOneTracker"></div>
</body>
</html>
You can fire custom events with jquery whenever you reposition the element.
$( window ).bind("resize",function(){
$("#elementOne").css({
top: 200,
left: 200
}).trigger("reposition");
});
// and now you can listen to a "reposition event"
$("#elementOne").bind("reposition",function(){
var self = $(this);
$("#elementTwo").css({
top: self.css("top"),
left: self.css("left")
});
});
So you can provide event hooks yourself with some manual coding, which is useful since cool events like DOMAttrModified and so on, are not fully supported in all browsers. The downside, you have to do it all yourself.
Unfortunately, there are no reliable events to tell you when an element moves or is resized. You could resort to polling the element, though that won't necessarily be the most performant solution:
setInterval(repositionElement, 10);
Another option is to make your element "track" the other element purely through CSS. For this to work, you'll need a "wrapper" around the element you're tracking, and the other element:
#wrapper-around-element-to-track
{
position: relative;
}
#tracked-element
{
position: absolute;
/* set top and left to position, if necessary */
}
#tracking-element
{
position: absolute;
/* set top and left to position, if necessary */
}
Since you're already using jQuery, you can also use the resize event plugin to simulate the resize event on any element, but if I recall the last time I looked at it, it simply does the polling like I mentioned.
There is the DOMAttrModified event, but its only impleneted in Firefox and Chrome. But as you need a JavaScript function to start the element moving, you can firing a custom event with Jquery in this place.

Categories