I do what something like:
$('div > img').onAll('load', function() { alert('Loaded!') })
Which would alert "Loaded!" only once
I don't want this:
$('div > img').on('load', function() { alert('Loaded!'); });
because this would call the event after every single image has been loaded
Is there any ready function in jQuery that calls an event on a set of matches? Or do I have to write a custom function for it?
Create your own method
$.fn.onAll = function(ev, callback) {
var xhr = [];
this.each(function() {
var def = new $.Deferred();
var ele = document.createElement(this.tagName.toLowerCase());
ele['on'+ev] = function() {
def.resolve();
}
ele.src = this.src;
xhr.push(def);
});
$.when.apply($, xhr).then(callback);
return this;
}
to be used as
$('div > img').onAll('load', function() { alert('Loaded!'); });
FIDDLE
Try this
var $images = $("div > img")
, imageCount = $images.length
, counter = 0;
// one instead of on, because it need only fire once per image
$images.one("load",function(){
// increment counter everytime an image finishes loading
counter++;
if (counter == imageCount) {
// do stuff when all have loaded
alert('Loaded!');
}
}).each(function () {
if (this.complete) {
// manually trigger load event in
// event of a cache pull
$(this).trigger("load");
}
});
try something like this
$('body').on('load','div > img',function() { alert('Loaded!') });
Happy Coding :)
Related
i have writen script which loads content from external php file. i'm using jquery1-9-1. my script works normal, except that moment when i'm clicking on button second time. there is delay for 0.5s before the animation starts. i think i know what is the problem and where is it. $("#header").animate({marginTop: "10px"... must execute just on the first click. after this clicked once, it must be deactivated. who knows how to solve it? don judge me so harsh and sorry my english
$(document).ready(function () {
var content = $("#content");
$("#main_menu a").click(function () {
var id = this.id;
$("#header").animate({
marginTop: "10px"
}, 500, function () {
$("#content").fadeOut(500, function () {
$("#content").load(id + ".php")
$("#content").fadeIn(500)
})
})
})
})
I have to ask, what is the point of caching content = $("#content") if you then refuse to use it and just call $("#content") repeatedly later?
Anyway, you need a variable to tell if it's the first run or not:
$(function () {
var content = $("#content"), isfirst = true;
$("#main_menu a").click(function () {
var id = this.id,
reveal = function() {
content.fadeOut(500, function () {
content.load(id + ".php")
content.fadeIn(500)
});
};
if( isfirst) $("#header").animate({marginTop: "10px"}, 500, reveal);
else reveal();
isfirst = false;
});
});
You need to track whether or not it has loaded, in that case. A simple variable and some closure should do it:
var isLoaded = false;
$("#main_menu a").click(function () {
var id = this.id;
if (!isLoaded) {
$("#header").animate({
marginTop: "10px"
}, 500);
isLoaded = true;
}
$("#content").fadeOut(500, function () {
$("#content").load(id + ".php")
$("#content").fadeIn(500)
})
});
I created a function and then called this function when the page loads, also I need call same the function, but without it existing twice. I want it to just stop from $(function(){}) and call again when an element is clicked on.
function myfunction(){
console.log('message');
}
$(function(){
myFunction();
$('#id').click(function(){
...some code here ...
myFunction();
});
})
When page is loaded the console gives me: "message" - it's ok, but when click on #id then I get this message twice, if again then 3 times;
Here my code
function select_cta(){
$('.cta-id').click(function(){
console.log('-');
$('.cta-id').removeClass('active');
$(this).addClass('active');
var cta_arr = parseInt($(this).attr('id').replace('cta-button-', ''))-1;
$('.cta-image').fadeOut(300).removeClass('active');
$('#'+$(this).attr('id').replace('cta-button', 'cta-image')).fadeIn(300).addClass('active');
if(cta_data[cta_arr]){
$('.cta-actions #cta_id').val(cta_data[cta_arr].id);
}
else{
$('.cta-actions #cta_id').val('');
};
if(cta_data[cta_arr]){
$('.cta-actions #cta_link').val(cta_data[cta_arr].link);
}
else{
$('.cta-actions #cta_link').val('');
};
});
}
$(function(){
select_cta();
$('.add-new-cta').click(function(){
var new_tab = parseInt($(this).prev().attr('id').replace('cta-button-',''))+1;
$(this).before('<div id="cta-button-'+new_tab+'" class="cta-btn cta-id empty" style="display:none;"><span>'+new_tab+'</span><span class="onair">ON</span></div>');
$('#cta-button-'+new_tab).fadeIn(300);
$('.cta-images').append('<div id="cta-image-'+new_tab+'" class="cta-image " style="display:none"><img src="/assets/images/page/placeholder_cta.gif"></div>');
select_cta();
})
});
Your problem that every call to select_cta adds another handler to each of the elements. They all would be executed when the click event fires. Two solutions:
Unbind the event handlers from all elements before you re-add them. To do so, begin the function select_cta with $('.cta-id').off("click").on("click", function(){…
Better: use event delegation:
jQuery(function($){
function getIdNumber($el) {
return parseInt($el.prop('id').replace(/\D/g, ''), 10);
}
var $active = $('.cta-id.active'),
$activeImg = $('.cta-image.active')
$(document).on("click", '.cta-id', function(e) {
$active.removeClass('active');
$active = $(this).addClass('active');
var num = getIdNumber($active);
$activeImg.fadeOut(300).removeClass('active');
$activeImg = $('#cta-image'+num).fadeIn(300).addClass('active');
var cta_arr = num - 1;
if(cta_arr in cta_data) {
$('#cta_id').val(cta_data[cta_arr].id);
$('#cta_link').val(cta_data[cta_arr].link);
} else {
$('#cta_id').val('');
$('#cta_link').val('');
}
});
$('.add-new-cta').click(function(e) {
var $this = $(this),
new_tab = getIdNumber($this.prev())+1,
new_button = $('<div id="cta-button-'+new_tab+'" class="cta-btn cta-id empty" style="display:none;"><span>'+new_tab+'</span><span class="onair">ON</span></div>');
$this.before(new_button);
new_button.fadeIn(300);
$('.cta-images').append('<div id="cta-image-'+new_tab+'" class="cta-image " style="display:none"><img src="/assets/images/page/placeholder_cta.gif"></div>');
})
});
I use the function below to show a list of items. I want to change the function so that I can display the navigation when the pseudo recussion is finished. Is there a way to dtect when it is finished?
function fadeItem() {
$('ul li:hidden:first').fadeIn(fadeItem);
}
(update: added this first part) Loads all embed images then recursively fades everything in every half second, then does an alert (replace with the concept you commented back on)
var selector = "ul li:hidden:first";
function fadeIn($item) {
$item.fadeIn(500,function() {
var n = $(selector);
if(n.length > 0) {
fadeIn($(selector));
} else {
// add a div
alert("added a div");
}
})
}
$(document).ready(function() {
// load images first
var imgs = []; // cached
$("ul li img").each(function() {
// create a separate img tag because img is not active due do [assumed css] display:none;
var cacheImage = document.createElement('img');
cacheImage.src = $(this).attr("src");
imgs.push(cacheImage);
});
// this is a quick method, you can change window to the image nodes to optimize better
$(window).load(function() {
fadeIn($(selector));
});
});
Source: http://jsfiddle.net/MattLo/ukLaG/1/ (using a very large image to test)
See the documentation. You can pass a callback function:
function fadeItem() {
$('ul li:hidden:first').fadeIn(fadeItem, function() {
// do something
});
}
I have two actions I need to apply to a set of DIV's, but I need one cycle to happen before the other is finished.
Here is my code:
$("div").each(function(){
//do stuff first
}).each(function(){
//do stuff next
});
but at present, do stuff next happens before do stuff first finishes. Anything I can do to stop this?
Full Script
$("div").each(function(){
if($(this).html() === "yes"){
$(this).fadeOut(time,function(){
$(this).parent().height(0);
});
}
}).each(function(){
if($(this).html() !== "yes"){
$(this).parent().height(25);
$(this).fadeIn(time);
}
});
Knowing that you want to fadeIn and then set height, will this do what you require?
var divs = $('div');
divs.fadeIn(function () {
divs.height('200');
});
Using each to allow different settings for different divs:
$('div').each(function () {
var div = $(this), toggle = true;
div.fadeIn(function () {
if (toggle = !toggle) {
div.height('200');
} else {
div.width('200');
}
});
});
Seeing your code snippet I believe I got it now:
var yesDivs = $('div').filter(function () {
return $(this).html() === 'yes';
});
yesDivs.fadeOut(time, function () {
yesDivs.parent().height(0);
$('div').filter(function () {
return $(this).html() !== 'yes';
}).fadeIn(time).parent().height(25);
});
I want to be able to fire an event when a user clicks on a button, then holds that click down for 1000 to 1500 ms.
Is there jQuery core functionality or a plugin that already enables this?
Should I roll my own? Where should I start?
var timeoutId = 0;
$('#myElement').on('mousedown', function() {
timeoutId = setTimeout(myFunction, 1000);
}).on('mouseup mouseleave', function() {
clearTimeout(timeoutId);
});
Edit: correction per AndyE...thanks!
Edit 2: using bind now for two events with same handler per gnarf
Aircoded (but tested on this fiddle)
(function($) {
function startTrigger(e) {
var $elem = $(this);
$elem.data('mouseheld_timeout', setTimeout(function() {
$elem.trigger('mouseheld');
}, e.data));
}
function stopTrigger() {
var $elem = $(this);
clearTimeout($elem.data('mouseheld_timeout'));
}
var mouseheld = $.event.special.mouseheld = {
setup: function(data) {
// the first binding of a mouseheld event on an element will trigger this
// lets bind our event handlers
var $this = $(this);
$this.bind('mousedown', +data || mouseheld.time, startTrigger);
$this.bind('mouseleave mouseup', stopTrigger);
},
teardown: function() {
var $this = $(this);
$this.unbind('mousedown', startTrigger);
$this.unbind('mouseleave mouseup', stopTrigger);
},
time: 750 // default to 750ms
};
})(jQuery);
// usage
$("div").bind('mouseheld', function(e) {
console.log('Held', e);
})
I made a simple JQuery plugin for this if anyone is interested.
http://plugins.jquery.com/pressAndHold/
Presumably you could kick off a setTimeout call in mousedown, and then cancel it in mouseup (if mouseup happens before your timeout completes).
However, looks like there is a plugin: longclick.
var _timeoutId = 0;
var _startHoldEvent = function(e) {
_timeoutId = setInterval(function() {
myFunction.call(e.target);
}, 1000);
};
var _stopHoldEvent = function() {
clearInterval(_timeoutId );
};
$('#myElement').on('mousedown', _startHoldEvent).on('mouseup mouseleave', _stopHoldEvent);
Here's my current implementation:
$.liveClickHold = function(selector, fn) {
$(selector).live("mousedown", function(evt) {
var $this = $(this).data("mousedown", true);
setTimeout(function() {
if ($this.data("mousedown") === true) {
fn(evt);
}
}, 500);
});
$(selector).live("mouseup", function(evt) {
$(this).data("mousedown", false);
});
}
I wrote some code to make it easy
//Add custom event listener
$(':root').on('mousedown', '*', function() {
var el = $(this),
events = $._data(this, 'events');
if (events && events.clickHold) {
el.data(
'clickHoldTimer',
setTimeout(
function() {
el.trigger('clickHold')
},
el.data('clickHoldTimeout')
)
);
}
}).on('mouseup mouseleave mousemove', '*', function() {
clearTimeout($(this).data('clickHoldTimer'));
});
//Attach it to the element
$('#HoldListener').data('clickHoldTimeout', 2000); //Time to hold
$('#HoldListener').on('clickHold', function() {
console.log('Worked!');
});
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<img src="http://lorempixel.com/400/200/" id="HoldListener">
See on JSFiddle
Now you need just to set the time of holding and add clickHold event on your element
Try this:
var thumbnailHold;
$(".image_thumb").mousedown(function() {
thumbnailHold = setTimeout(function(){
checkboxOn(); // Your action Here
} , 1000);
return false;
});
$(".image_thumb").mouseup(function() {
clearTimeout(thumbnailHold);
});