Destroying a function when exiting a matched breakpoint with enquire.js - javascript

This is probably basic to most reading, but I can't seem to figure it out.
I have a little test function that I want to execute if under a certain width. When the screen rotates or gets resized above that width, I want the function to cease to work. Here is some example code for simplicity sake.
enquire.register("screen and (max-width:500px)",{
match : function() {
$(".block .block-title").click(function(){
alert("Hello World!");
});
}
}).listen();
So if the page loads above 500px, it works as intended. Clicking won't execute. If the page loads at 500px or below, the click function executes. Only problem is that if you resize the viewport or change orientation to something above 500px, the function still executes. I'd like to be able to disable that.
The real world scenario I'm actually trying to do here is I have an un-ordered list of 4 items. Above a certain width they are displayed right away. If under a certain width, I just want to hide them and on click show them. I know there are a few ways to do it (.toggle(), .toggleClass("myclass"), etc).
I have done this a bunch of times but I always get caught with the entering / exiting break points and things not being reset, or working as intended. Usually it doesn't matter, but lately in some of my use cases it has mattered.
I know of the unmatch option but I'm not sure how to really kill the matched function above.
enquire.register("screen and (max-width:500px)",{
match : function() {
$(".block .block-title").click(function(){
alert("Hello World!");
});
},
{
unmatch : function() {
// what do I do here do kill above?
}
}
}).listen();
Any help would be appreciated. I am pretty sure it will help my current situation but will also help me expand my knowledge of enquire.js for other things.
Thanks.
edit: I forgot to mention... if you load the page under 500px, then resize or orientate wider then 500px, then go BACK under 500px, the click function won't work again.. which confuses me also. I basically was hoping it would work no matter what when under 500px, and not work at all when over 500px.

I'm the author of enquire.js, so hopefully I'll be able to help you ;-)
Basically, you want to add an event handler on match and remove event handler on unmatch. You seem to have the gist of how to do this above, but you've got the syntax a little wrong. Once the syntax is corrected it's just some jQuery knowledge to remove the click handler.
So let's look at how the syntax should be:
enquire.register("screen and (max-width:500px)", {
match: function() {
//match code here
},
unmatch: function() {
//unmatch code here
}
}).listen();
Notice that match and unmatch are part of a single object supplied to register.
Ideally you should be putting this in your document ready callback. To assign your click handler use jQuery's on method, as this allows you to use the off method to unassign:
$(".block .block-title").on("click", function() {
alert("hello");
});
$(".block .block-title").off("click");
This is great because you can even namespace your events, read up on the jQuery docs for more details on this. So to put it all together, we would have this:
$(document).ready(function() {
var $target = $(".block .block-title");
enquire.register("screen and (max-width:500px)", {
match: function() {
$target.on("click", function() {
alert("Hello World!");
});
},
unmatch: function() {
$target.off("click");
}
}).listen();
});​
You can find a working example here: http://jsfiddle.net/WickyNilliams/EHKQj/
That should then be all you need :) Hope that helps!

Related

Running function on window scroll once in jQuery

I'm creating my portfolio and I'm trying to make my skill bars load when I go to "My skills" section. I want them to do it only once, either when someone scroll to this section or goes to it straight away from the navigation. This is my code:
var skills = $('#mySkills');
var skillsPositionTop = skills.position().top;
$(window).on("resize scroll", function (){
if (pageYOffset<skillsPositionTop-20 && pageYOffset>skillsPositionTop-80){
console.log ("here is my loading script");
}
});
It doesn't work when I use one instead of on, doesn't work when I created one more function on window with one inside my if statement.
I was trying exit the function with return or return false as well and here, on stack overflow I found something about flag, which I didn't fully understand but I tried different combinations with it.
Can someone please help me with it? I've seen there is a library for this type of effects, but there is no point of installing any just for one thing...
Edit. Console.log represens my loading code.
You can set a namespace at .on() for resize, scroll events, use .off() within if statement to remove namespaced events.
var skills = $('#mySkills');
var skillsPositionTop = skills.position().top;
$(window).on("resize.once scroll.once", function (){
if (pageYOffset<skillsPositionTop-20 && pageYOffset>skillsPositionTop-80) {
$(this).off("resize.once").off("scroll.once");
console.log ("here is my loading script");
}
});

combine onLoad, onResize and onRefresh in jquery

I want a website to execute a certain jquery script (which allows me to stretch the height of a vertical menu to the height of my browser window) when the page loads and when it is resized.
So I have written a jquery of this kind:
jQuery(document).ready(function ($) {
$(window).on('resize', function() {
<code to execute>
}).trigger('resize');
});
My problem is that this code works well when somebody loads the page or when he resizes it, but it doesn't work when one hits the refresh button. How could I make the code work also in that case?
Thank you in advance for your help.
Try this:
var myFn = function() { console.log('hello world') };
jQuery(document).ready(function ($) {
myFn();
$(window).on('resize', function() {
myFn();
});
});
jQuery(document).ready(function ($) {
function Resize(){
$(window).on('resize', function() {
<code to execute>
}).trigger('resize');
}
});
call this Resize() whenever you need. Either on load or on click.
It turned out that the way I described in my own question was more than right. It worked perfectly well that way, even onRefresh. What was not making my script work properly was the fact that one of the variables I was using would change after the page had finished loading, so when I was hitting "refresh", it would give a different value than in the beginning.
So for every user of stackoverflow.com, please note that whenever you want to set an event onLoad, onResize AND onRefresh, the easiest and best possible way is:
jQuery(document).ready(function ($) {
$(window).on('resize', function() {
<code to execute>
}).trigger('resize');
});
In fact, what glortho was suggesting could work, but that was using another variable, and in my humble opinion, that would make the whole thing a little more redundant.
Thank you everybody for your help and for reading.

fadeIn as callback function after fadeOut doenst work as expected

In my HTML a#navInnerMapR and a#navInnerMapL are contained within div#navTwo.
The following code is within a function. When called, I need the function to fadeOut any visible links in div#navTwo, pause for a moment, and then fadeIn a#navInnerMapR.
$('div#navTwo a').fadeOut(200, function() {
$('a#navInnerMapR').delay(100).fadeIn(200);
});
The code fades out the links but doesn't fade anything in. I thought that they delay would only start once the fadeOut finishes, however changing the delay value to 1000 makes it sometimes work but its very buggy. Thanks
UPDATE Here is a fiddle showing that the hidden link starts to be shown before the visible is hidden: http://jsfiddle.net/jamesbrighton/d9QKr/5/
UPDATE Apologies, my question doesnt include the full details of what I need to achieve. I simplified it as I thought I just had some sort of sytax issus that could be easily fixed.
div#navTwo actually contains 3 links. At any point (other than the delay before animations run) only 1 link is visible. I need to be able to call a function that will hide either of the other 2 links that are being shown, and then show a#navInnerMapR.
Different events will call this function, so either of the 2 links that arn't a#navInnerMapR may be visible. Thanks
UPDATE I think this fiddle illustrates the issue. Ive created 2 div.nav's to illustrate different states. Ive hidden different links with inline CSS in each one. JavaScript will be showing and hiding the links in my div repeatedly, so the same div will look like each example at different times.
Ive created 2 triggers to illustrate that different events will need to call the function. When you click on a trigger you can see the issue with both examples. The visible divs are not hidden before the a.one is shown. Thanks for your patience!
http://jsfiddle.net/jamesbrighton/dYvMS/24/
Interesting point, if I change $('.nav a.one').fadeIn(1000); to an alert, the alert fires multiple times! No idea why this would be the case!
Edit: Updated answer based on your below comment,
Yes this works as I need, but im not sure it will work for my actual
page. Sorry for my question not being detailed enough. The code
example I gave is simplified. In the actual page their are 3 links
within div#navTwo, at any time only one of them will be visible. I
need to be able to call a function that hides any links and shows a
specific one, but either one of the other 2 links in div#navTwo may be
visible. Thanks
DEMO
HTML: Added class to all links inside navTwo
<div id="navTwo">
Right
Left
Middle
Upper
Lower
</div>
JS:
$('.links').click(function() {
showHide($(this));
});
function showHide($this) {
$this.fadeOut(1000, function() {
$('#navTwo a').not($this).delay(1000).fadeIn(1000);
});
}
I think I understood what you need. Try below DEMO and let me know if that is what you want,
DEMO
$('#navInnerMapR').click(function() {
runMeR($(this));
});
$('#navInnerMapL').click(function() {
runMeL($(this));
});
function runMeR($this) {
$this.fadeOut(1000, function() {
$('a#navInnerMapL').delay(1000).fadeIn(1000);
});
}
function runMeL($this) {
$this.fadeOut(1000, function() {
$('a#navInnerMapR').delay(1000).fadeIn(1000);
});
}
As you said, You need the function to fadeOut any visible links in div#navTwo, pause for a moment, and then fadeIn a#navInnerMapR (not other links, only a#navInnerMapR).
$('#navTwo a').click(function(e) {
$(this).parent().children().each(function(i){
$(this).fadeOut('slow', function(){
$('a#navInnerMapR').delay(1000).fadeIn(1000);
});
});
});​
A fiddle is here.

jQuery selector :not(:animated)

We're trying to make sure our JavaScript menu, which loads content, doesn't get overrun with commands before the content in question loads and is unfurled via .show('blind', 500), because then the animations run many times over, and it doesn't look so great. So I've got about six selectors that look like this:
("#center_content:not(:animated)")
And it doesn't seem to be having any effect. Trying only :animated has the expected effect (it never works, because it doesn't start animated), and trying :not(div) also has this effect (because #center_content is a div). For some reason, :not(:animated) seems not to be changing the results, because even when I trigger the selector while the div in question is visibly animated, the code runs. I know I've had success with this sort of thing before, but the difference here eludes me.
$("#center_content:not(:animated)").hide("blind", 500, function () {
var selector_str = 'button[value="' + url + '"]';
//alert(selector_str);
var button = $(selector_str);
//inspectProperties(button);
$("#center_content:not(:animated)").load(url, CenterContentCallback);
if (button) {
$("#navigation .active").removeClass("active");
button.addClass("active");
LoadSubNav(button);
}
});
I hope this provides sufficient context. I feel like the second selector is overkill (since it would only be run if the first selector succeeded), but I don't see how that would cause it to behave in this way.
Here's the snippet that seemed to be working in the other context:
function clearMenus(callback) {
$('[id$="_wrapper"]:visible:not(:animated)').hide("blind", 500, function() {
$('[id^="edit_"]:visible:not(:animated)').hide("slide", 200, function() {
callback();
});
});
}
Here, the animations queue instead of interrupt each other, but it occurs to me that the selector still doesn't seem to be working - the animations and associated loading events shouldn't be running at all, because the selectors should fail. While the queueing is nice behavior for animations to display, it made me realize that I seem to have never gotten this selector to work. Am I missing something?
Sometimes it's helpful to use .stop() and stop the current animation before you start the new animation.
$("#center_content").stop().hide("blind", 500, function () {});
Really depends on how it behaves within your environment. Remember that .stop() will stop the animation as it was (eg. halfway through hiding or fading)
I don't know if I understand it correctly, but if you want to make sure the user doesn't trigger the menu animation again while it's currently animating(causing it to queue animations and look retarded, this works and should help. I use an if-statement. And before any mouseover/off animation I add .stop(false, true).
$('whatever').click(function(){
//if center_content is not currently animated, do this:
if ($("#center_content").not(":animated")) {
$(this).hide(etc. etc. etc.)
}
//else if center_content IS currently animated, do nothing.
else {
return false;}
});
another example i found elsewhere:
if($("#someElement").is(":animated")) {
...
}
if($("#someElement:animated").length) {
...
}
// etc
then you can do:
$("#showBtn").attr("disabled", $("#someElement").is(":animated"));

Resizing images on mouse over (Javascript/MooTools)

I've built a webpage that's supposed to increase the size of images onmouseover.
I'm not replacing the images with bigger ones but rather "stretch" the existing ones because of system limitations.
Here's the webpage:
http://www.catmoviez.com/IMDBQueries.aspx
You can see that the movie images get bigger when you're on them.
Problem is when I move my mouse too quick that sometimes an image gets stuck open or it causes inifinite flickering.
attached is also the code I'm using for the resize:
function resizeImage(elem,width,height){
var myEffect = new Fx.Morph(elem, {duration: 350});
myEffect.start({'height': height,'width': width});
}
First thing, set this variable outside your functions
var imagegrow
And then mouseover this
function () {
imagegrow = setTimeout(function(){ resizeImage(elem,width,height); },1000);
}
And the mouseout this:
function () {
clearTimeout(imagegrow);
}
Adjust the 1000 number to suit your preferred delay (it's in milliseconds). I'd write the whole code for you, but I haven't used MooTools for a while.
Comment if you have any questions
Faruz, Gaussie is right you need to use a timeout. However, consider using mootools' addEvent function as described in the mootools docs as well as the $$ function which will allow you to achieve something much more elegant, along the lines of:
window.addEvent('domready', function() {
$$("tr td input").addEvent("mouseover", function() {
//anonymous function like Gaussie's here
});
});
Note that this isn't the exact code, it will take some modification but it is cleaner and should be more efficient then setting the onmouseover property of every image. Also, remember this goes in the head of your HTML document.

Categories

Resources