I am trying to do a notification pop up, each pop up is dynamically generated after ajax fetched the data.
The pop up each will have a time limit of 10 seconds before it fade out. Something like you see on Facebook's notifications on the left bottom corner.
Each pop up will be hidden according to the time it is added and the timelimit.
Here's an example of my code:
function hidePop(obj){
$(obj).hide();
}
function newpopup(data){
$('#notifications').prepend('<li class="new" style="display:none;">'+data+'</li>');
$('.new').fadeIn(200, function(){
var $this = $(this);
$(this).removeClass('new');
setTimeout(function(){
hidePop($this)
}, 10000);
});
}
As you can see above, my AJAX call will call for newpopup with the data. Once it fades in completely the setTimeout function will run.
This works, however, after a few more li is appended, those new lis will keep hiding itself once its showed.
Note: I remove class new once everything is done since new will then be used for the latest incoming popups.
I think the setTimeOut is either not stopped or targeting all of the lis.
Is my method a problem or is there any better solutions?
Instead of simply prepending an <li> tag as a string that states a class, then selecting the class with jQuery, I would suggest using the DOM to create the <li> element and hold a reference to it like so:
function hidePop(obj){
obj.hide(); //obj parameter already wrapped by jquery, no need to do it again
}
function newpopup(data){
var newLi = $(document.createElement("li")); //createElement then wrap jQuery around it
newLi.html(data).css("display", "none"); //jQuery set innerHTML and CSS
$('#notifications').prepend(newLi); //Prepend to list
newLi.fadeIn(200, function() { //Select this and only this li element
setTimeout(function(){
hidePop(newLi); //Closure; reference to the same "this and only this li"
}, 10000); //10s
});
}
In the body of the anonymous function in setTimeout, $this is overwritten. Try this:
function newpopup(data){
$('#notifications').prepend('<li class="new" style="display:none;">'+data+'</li>');
$('.new').fadeIn(200, function(){
var $this = $(this);
$(this).removeClass('new');
var thatPopup = $this;
setTimeout(function(){
hidePop(thatPopup)
}, 5000);
});
}
Related
I'm trying to trigger a click on an element every x seconds. It's not the exact same element every time (depending on which tab a user has selected, it should click that tab), but they are all in the same container (with id #container. The selected element has the class .selected and gets that class when it has been clicked on by a user.
This is the code I have:
var feedContainer = $('#container');
window.setInterval(function () {
var selectedTab = feedContainer.find('.selected');
selectedTab.trigger('click');
}, 10000);
The problem is that between the timeouts, if a user clicks on another tab, this part doesn't pick up on that: var selectedTab = feedContainer.find('.selected');. It just gets the one that was selected before, not the new one that has the class. How do I avoid that?
It works fine if I do the entire selection in the timer each time (var selectedTab = $('#container .selected');). It seems to be somehow caching the results from the last run.
Why is this and how do I force it to fetch the correct element?
You are already caching the element yourself by doing this:
var feedContainer = $('#container');
If the contents change after you assign it to the variable then that variable won't get updated with the new contents automagically.
Just use it like this $('#container'); directly whenever you want to do operations on it.
What you're doing is that in the beginning, you gather some elements that match the selection (using $('#container')) but later on, you change the content of #container which is not reflected in the jQuery object in feedContainer. Simply get the container on each iteration.
window.setInterval(function () {
var feedContainer = $('#container');
var selectedTab = feedContainer.find('.selected');
selectedTab.trigger('click');
}, 10000);
window.setInterval(function () {
var selectedTab = $('#container').find('.selected');
selectedTab.trigger('click');
}, 10000);
As container is not changed above is proposed.
First of all, an ID should ideally be used to identify a "single" element, not multiple elements. Changing that would help you out by spreading the elements with the same name using a "class" identifier. Changing that might help you out a lot.
I'd do it like this. Short, to the point and no variable assigning thus no caching.
window.setInterval(function () {
$('#container .selected').trigger('click');
}, 10000);
I'm fairly new to Javascript, and am trying to get an 'on click enlarge' kind of effect, where clicking on the enlarged image reduces it again. The enlarging happens by replacing the thumbnail by the original image. I also want to get a slideshow using images from my database later on.
In order to do that, I made a test where I replace the id which indicates enlarging is possible by a class and I also use a global variable so that I can keep a track of the url I'm using. Not sure this is the best practice but I haven't found a better solution.
The first part works fine, my image gets changed no problem, values are also updated according to the 'alert' statement. However, the second part, the one with the class never triggers.
What am I doing wrong (apart from the very likely numerous bad practices) ?
If instead of changing the class I change the id directly (replacing .image_enlarged by #image_enlarged, etc.), it seems to call the first function, the one with the id, yet outputs the updated id, which is rather confusing.
var old_url = "";
$(function(){
$('#imageid').on('click', function ()
{
if($(this).attr('class')!='image_enlarged'){
old_url = $(this).attr('src');
var new_url = removeURLPart($(this).attr('src'));
$(this).attr('src',new_url); //image does enlarge
$(this).attr('class',"image_enlarged");
$(this).attr('id',"");
alert($(this).attr('class')); //returns updated class
}
});
$('.image_enlarged').on('click', function (){
alert(1); //never triggered
$(this).attr('src',old_url);
$(this).attr('class',"");
$(this).attr('id',"imageid");
});
});
function removeURLPart(e){
var tmp = e;
var tmp1 = tmp.replace('thumbnails/thumbnails_small/','');
var tmp2 = tmp1.replace('thumbnails/thumbnails_medium/','');
var tmp3 = tmp2.replace('thumbnails/thumbnails_large/','');
return tmp3;
}
As for the html, it's really simple :
<figure>
<img src = "http://localhost/Project/test/thumbnails/thumbnails_small/image.jpg" id="imageid" />
<figcaption>Test + Price thing</figcaption>
</figure>
<script>
document.write('<script src="js/jquery-1.11.1.min.js"><\/script>');
</script>
<script type="text/javascript" src="http://localhost/Project/js/onclickenlarge.js"></script>
From the API: http://api.jquery.com/on/
The .on() method attaches event handlers to the currently selected
set of elements in the jQuery object.
When you do $('.image_enlarged').on(...) there is no element with that class. Therefore, the function is not registered in any element.
If you want to do so, then you have to register the event after changing the class.
Here's an example based on your code: http://jsfiddle.net/8401mLf4/
But this registers the event multiple times (every time you click) and it would be wrong. So I would do something like:
$('#imageid').on('click', function () {
if (!$(this).hasClass('image_enlarged')) {
/* enlarge */
} else {
/* restore */
}
}
JSfiddle: http://jsfiddle.net/8401mLf4/2/
Try using:
addClass('image-enlarged')
instead of:
.attr('class',"image_enlarged");
the best way to do this would be to have a small-image class and a large image class that would contain the desired css for both and then use addClass() and removeClass depending on which you wanted to show.
I am attempting to append elements to a list using the .load() method to retrieve elements from another page.
But when I use this method it is removing the current DOM elements and replacing them, rather than appending them to the list.
Any help would be much appreciated.
Code below:
var $container = $('#container');
$('#insert a').click(function () {
var newEls;
$container.load('../pages/2.html .element', function () {
newEls = $(this);
});
$container.isotope('insert', $(newEls));
return false;
});
Surely you should be telling isotope to insert after they have been loaded.
e.g.
$container.load('../pages/2.html .element', function () {
newEls = $(this);
$container.isotope('insert', $(newEls));
});
otherwise you are inserting the current contents (or an empty div) before loading them.
Your $container.isotope('insert', $(newEls)); is executing before the load even starts (the load is asynchronous so you can only trust something to run against the loaded data if it is in the callback/function).
In addition to this, you are reloading the entire contents of the '#container' so it simply erases the previous children. You need to append the content, e.g. by loading into a dummy element then appending to your container.
maybe something like this (untested):
var $container = $('#container');
$('#insert a').click(function () {
var $newEls;
$container.append('<div id="#loadme"></div>');
var $loadme = $('#loadme');
$('#loadme').load('../pages/2.html .element', function () {
$newEls = $loadme.children();
$loadme.children().unwrap();
$container.isotope('insert', $newEls);
});
return false;
});
Normally I would not use load in this situation, but an AJAX get call and append the returned elements. Much simpler.
I'm trying to make some code which finds if a div exists, and if it does then have it fade away slowly. I have this to determine whether or not the div exists
if($('#error').length != 0)
{
$('#error').hide(500);
}
And that does work but only on a refresh, I've been attempting to put it in a timer like this:
var refreshId = setInterval(function()
{
if($('#error').length != 0)
{
$('#error').hide(500);
}
}, 500);
But its not getting rid of the innerHTML! I have some code which on hover alters the innerHTML of the error div so I can fill it up, but for some reason this isn't working, any advice would help!
Thank you!
$("#error").fadeOut(500);
Update:
If you are looking to check for existence:
var msg = $("#error");
if(msg.length) {
msg.fadeOut(500);
}
If you want to empty it:
$("#error").empty();
If you just want to delay 500ms then fade out, do this:
$("#error").delay(500).fadeOut();
To also empty the element, provide a callback to .fadeOut() like this:
$("#error").delay(500).fadeOut(function() {
$(this).html('');
});
There's no need to check .length, if an element that matches the selector isn't present, nothing happens :)
The div you're trying to hide likely hasn't loaded by the time your script runs. Try this; it will defer execution until the DOM is loaded:
$(document).ready(function() {
// put your code here
});
This is a good practice when using jQuery anyway.
Reference: http://docs.jquery.com/Tutorials:Introducing_$(document).ready()
I have my website getting a value as a result of an ajax call. After that, I would like to insert that result (a string) into a tag. However, I would like to insert that result in a way that (1) it must have opacity = 0, then (2) it will slideDown() so the whole content list being pushed down using animation, and finally (3) change opacity = 1. Imagine this is just like a Facebook message list insert process
The way I am planning to do this is to return the result string from ajax to opacity=0 first. However, I don't know how to use jQuery to select a tag from within a string. I know jQuery only select from the DOM. So how to do this? Any advice?
Thanks
I'd consider putting the return value inside a SPAN. Hide the container that will hold it. Set the opacity of the SPAN to 0, then add the result to it and put it in the container. Once that is done, slide the container down and animate showing the result in the callback to the slideDown method.
$.ajax({
...
success: function(data) {
var container = $('#container').hide();
$('<span />').css( 'opacity', 0 )
.html(data.result)
.appendTo(container);
container.slideDown('normal', function() {
$(this).( 'span:first' )
.animate( { 'opacity': 1.0 } );
});
}
...
});
Hide() is a jquery function, meaning that only works on a jquery object, so you have to first inject the html in the DOM, and then call hide() on the DOM element.
$('#msgList').load (url,data,function(html){
var $this = $(this); // cache $(this) for performance
$this.hide().html(html); // inject the html in the DOM
$('#aa', $this).hide(); // hide #aa
$this.show(); // reveal the messageList
});
The following will make the ajax call using the simple .get() wrapper.
Then the callback function will load the response into a jquery object and find the tag you want.
It then hides this tag and appends it to a div container.
Finally it will slide it down.
//do ajax call
$.get( url, function(html) {
//load html into a jQuery object, find the tag by id then hide it
var $el = $(html).filter('#someId').hide();
//append element to the dom and slide it down
$el.appendTo('#someDiv').slideDown('slow');
});