jQuery script fires twice? Perhaps live event is firing twice? - javascript

I am building an application using the latest version of PhoneGap, jQM and jQuery 1.8.0. So far so good except for this tiny and annoying problem I came across.
I have my show.html linked from the index.html that contains the following code:
<div id="search"> contains search bar and submit button </div>
<div id="list" style="display:none;">
<ul data-role="listview" data-filter="true"> </ul>
</div>
The ul tag is empty because the list will be dynamically appended to it using ajax when the submit button is clicked. I didn't want to display the #list div at first so I set the display to none.
So this works fine, when the submit button is clicked, it will send an ajax request to the server and append the items to the list. It will also hide the search div. This works alright as well!
Now the problem comes in, I added a window.scroll function to detect when the bottom of the page is reached.
Here's my jQuery code:
$(document).on("pageshow", "#pageID", function() {
$("#submit").click(function() {
$.ajax({
success: function(data, status){
$('#search').hide();
$('#list').show();
//append to list div and refresh list here
}
});
});
//detects bottom of page
$(window).scroll(function () {
if ($(window).scrollTop()+200 >= ($(document).height() - ($(window).height()))) {
console.log('end of the page');
lastPostFunc(); //infinite scroll function
}
});
});
This prints 'end of the page' two times to the firebug console! This script exists in between the head tag.
Is there anyway to just make it print once? I need this because I implemented my own endless scroll function and the problem is causing my ajax request to post twice to the server. The function works great but is not the cause of the problem because even when I commented lastPostFunc() out, it still prints to the console twice!!
Edit: Personally, I don't think the answers given so far are wrong, they are correct but they do not help me solve the problem. Maybe I need to rephrase things better. I copied my code and pasted it on a standalone page, it prints only once, so my code actually has nothing wrong with it and it's working like it should be.
Therefore, I was wondering whether there's something else that's causing it to print twice after submitting the form. My form and my results page is ON the same page. Does this means it caused the live event to work twice? Thus, causing it to print to the console twice on pageshow? If I am correct, is there anyway to work around this and making it only print ONCE?
Any help is appreciated. Thank you!

Okay I finally solved it.
Apparently all I have to do is to add this line of code to it:
$(window).scroll(function (e) {
if (reach bottom) {
e.stopImmediatePropagation();
console.log('End of the Page');
}
});
And it works! Stopped printing twice for me.

Your function will actually write output to the console more than two times. The problem lies within your condition:
if ($(window).scrollTop()+200 >= ($(document).height() - ($(window).height())))
Because for every scroll within this area the condition will evaluate to true. You could change it to:
if ($(window).scrollTop() == ($(document).height() - ($(window).height())))

May this will solve your problem
jQuery(window).scroll(function() {
if( (jQuery(document).height() < (jQuery(window).scrollTop() + jQuery(window).height() + 200))&&(jQuery(document).height() > (jQuery(window).scrollTop() + jQuery(window).height() + 99))) {
console.log('test')
}
});
//Update
var lastlogtime= null;
jQuery(window).scroll(function() {
if( (jQuery(document).height() < (jQuery(window).scrollTop() + jQuery(window).height() + 200))&&(jQuery(document).height() > (jQuery(window).scrollTop() + jQuery(window).height() + 99))) {
if(((lastlogtime+600)<(+new Date())) || (lastlogtime== null)){
//your scroll logic
console.log('test') ;
lastlogtime= +new Date();
}
}
});

Related

Using jQuery's .each feature when page is constantly updating

I've been trying to get to find a solution for this all day but can't think of a good one that I can get working.
Basically, I made some jQuery/javascript code that runs an each() loop for certain items on a web page. This works well, but the page it runs on updates when you scroll to the bottom, adding more results. At the moment, my script can only go through as many items as there are loaded on the page. I would love for it to be able to go through all of them that are loaded, then scroll to the bottom and go through all the new results and continually repeat this process.
I've tried a lot of different solutions but can't seem to make one that works well.
Any help would definitely be appreciated.
Thanks :)
Edit:
Here are some of the concepts I've tried so far:
Place the code in a while loop and add an offset so it skips all of the items its already gone over
var a = 0;
var offset = 0;
while (a == 0) {
jQuery('.Grid-cell .js-stream-item .ProfileCard').each(function (i, ele) {
if (i >= offset) {
//Run script
}
});
offset = offset + 18; //18 is how many new items are added each time
setTimeout(function () {
jQuery('html, body').animate({scrollTop:$(document).height()}, 'fast'); //To scroll to the bottom
}, 5000);
}
Place code in while loop but no offset
(Similar to previous but offset removed since I figured it could just runover the ones already done)
This one was a bit more experimental since I was getting desperate after the previous attempts failed. Basically, I added a hidden checkbox, then I put my script and the each loop inside of a function. Then whenever the checkbox was clicked it would run the function which ran my script and once the each loop was complete it would scroll to the bottom of the page and click the checkbox to make the function go again
$( ".Footer-copyright" ).append( "<input type='checkbox' class='functionclass' style='display:none' value='no' />" );
jQuery(".functionclass").on("click", function() {
myfunction();
})
function myfunction() {
jQuery('.Grid-cell .js-stream-item .ProfileCard').each(function (i, ele) {
//Run script
});
jQuery('html, body').animate({scrollTop:$(document).height()}, 'fast');
jQuery(".functionclass").click();
}
jQuery(".functionclass").click();
So I believe I've found a solution to my issue. It's not exactly the cleanest solution ever, but it seems to get the job done. Basically, I've put the task inside of a setInterval() function and so it will now complete the task every 5 seconds and will scroll to the bottom after 15 tasks. This allows it to get an updated list of all of the elements every time it runs. Here is the code for anyone curious:
var i = 0;
task = setInterval(function(){
var elements = jQuery(".Grid-cell .js-stream-item .ProfileCard"); //Gets all of the elemnts
var element = jQuery(elements[i]); //Gets the element for the attempt number
//Completes task
if (i % 15 === 0){
jQuery('html, body').animate({scrollTop:$(document).height()}, 'fast'); //Scrolls to bottom when attempt number is divisible by 15
}
i++;
}, 5000);

Load more data - ScrollTop function not working

I am trying to load data on page scroll and for this I am trying to run the following function
$(window).scroll(function ()
{
if($(document).height() <= $(window).scrollTop() + $(window).height())
{
alert("done")
}
});
The problem is, as per my page setting I have done body overflow:hidden and made a container scrollable, the above code is not working in this case, however when I enable the body scroll then its working fine, can anybody please suggest how to handle this?
Here is the JSFiddle demo
You need to check the element with class scroller instead of window for scroll position.
$('.scroller').scroll(function ()
{
if($('.scroller').scrollTop() >= ($('.scroller')[0].scrollHeight - $(window).height()) )
{
alert("load more data")
}
});
JS Fiddle: https://jsfiddle.net/n0rramke/5/
This should work (if I correctly understand your question):
if ($(".scroller").height() <= $(".scroller").scrollTop()) {
alert("load more data")
}
Fiddle: https://jsfiddle.net/rhbmxssv/ ...

silentScroll will be undone after page is loaded

After my jQuery mobile site is loaded, I like to scroll to the position of a div. Works using this code
function changeViewport(){
var errorMsg = $('.dataerror').first();
if(errorMsg != null) {
var newPosition = errorMsg.offset();
$.mobile.silentScroll(newPosition.top);
}
}
I call the function on $(document).ready, but after calling the function and silentScroll to the position it seems the framework autoscroll back to the top of the page... Anyone know how to prevent this behaviour? (I also tried events pageinit, pageshow...)
Do I have to overwrite a function or trigger another event? Any help or suggestion is welcome :)
cheers.
After struggling with this myself, I seem to have found the cause as well as a workaround. It appears that the animation used in changePage is taking precidence over the silent scroll. You can read more about this here. On the same page, the comments also begin to discuss different events, such as pagebeforeshow or pageaftershow - unfortunately these yielded no results for me.
The workaround I have found was to wrap the .silentScroll in a timeout of a half a second. It looks a bit choppy, but it seems to be working for me. Hope this helps.
Try This:
function changeViewport(){
var errorMsg = $('.dataerror').first();
if(errorMsg != null) {
var newPosition = errorMsg.offset();
setTimeout(function(){$.mobile.silentScroll(newPosition.top)}, 500);
}
}

jQuery page fadeIn() only working on index page

Thanks everyone, for the quick help! Script now works. I've updated the site and code below. Maybe someone can find this code useful. :)
I've gotten the page (http://www.katmcgo.com) to fade in as desired using jQuery. However, it only fades in on the index page -- all subsequent pages load as normal.
I have the following script in the header of each page (including the sub-pages that are not fading in); it is included in each page using PHP:
$(document).ready(function() {
function fadePage() {
// Target the tags you want to effect with the fade
var fadingTag = "section";
var fadingTag2 = "hr";
var delay = 0; // Initialize delay - Should start at 0
var delayStagger = 600; // Delay stagger - Time between elements fading in
var fadingNum = document.getElementsByTagName(fadingTag).length; // Find out how many elements you need to hide
// Get and fix the overall document height before it disappears (which will happen when elements are hidden)
var pageHeight = $(document).height() + "px";
$("#wrapper").css("height", pageHeight);
// Hide all targeted tags
$(fadingTag).css("display", "none");
$(fadingTag2).css("display", "none");
// Fade each targeted tag in, one by one
for (var i = 0; i < fadingNum; i++){
$($(fadingTag).get(i)).delay(delay).fadeIn(delayStagger);
$($(fadingTag2).get(i)).delay(delay).fadeIn(delayStagger);
delay += 350;
}
}
fadePage();
});
I've been racking my brain as to why this is happening, and doing searches to the find the answer, but coming up with nothing...
This page is in the early stages, so I'm just doing dev in Firefox and Safari... fade works in both, but only on the first page. Any help would be greatly appreciated.
install firebug in firefox. your getting an undefined element[0] on all pages except index.php.
Edit:
wrap your s3Slider call inside an if statement checking if the element exists.
if( $('#slider').length ) {
$('#slider').s3Slider({
timeOut: 3500
});
}
Alternatively you could not output that code from the server if your not on the index page.
You have an error coming from s3Slider.js on all of your subsequent pages. Probably because the slider element does not exist on those pages, but the plugin is still being called.
The fade script probably works fine.

Changing Javascript Focus in onClick event?

Note: A possible solution needs only work in Firefox 3.0, my app doesn't allow access from IE! =)
I have a link that, when clicked, will display a lightbox to the user:
show lightbox
My problem is that when the lightbox is displayed, the focus remains on the link. So if the user presses the up or down keys, they end up scrolling the main document, not the lightbox that is displayed!
I've tried to set the focus to the lightbox element using code like this
function focus_on_lightbox() {
document.getElementById('lightbox_content').focus();
}
This works fine if I type it in the firebug console, but will not work if I include it at the end of the onclick snippet. It appears as though I can't change the focus away from the link from code executed inside the onclick event?
-- Update 1
I've tried something like this before
show lightbox
and I've modified function to add some debugging output, as follows
function focus_on_lightbox() {
console.log('hihi');
console.log(document.activeElement);
document.getElementById('lightbox_content').focus();
console.log(document.activeElement);
}
The output is as follows
hihi
<a onclick="closePopup();lightbox('apartment_detail','11619');focus_on_lightbox();return false;" href="#">
<a onclick="closePopup();lightbox('apartment_detail','11619');focus_on_lightbox();return false;" href="#">
So the focus before I did anything was on the link and after I tried to change the focus it still remained on the link?
Not sure if it matters, but I use ajax to load the lightbox, as follows
new Ajax.Updater(lightbox_content_id, url, {asynchronous:true, evalScripts:true, onLoading:show_lightbox_loading(), onComplete:focus_on_lightbox() });
I tried to set the focus after the ajax complete, but also, no luck.
What am I missing?
I've been trying to make a solution work that was suggested below by trying to set the focus, seeing if I succeeded by checking document.activeElement, if not, wait 100 milliseconds and try again. If I use the following function, it will work
function focus_on_lightbox() {
var seconds_waited = 0
pause(100);
var current_focus = document.activeElement
while (document.getElementById(lightbox_content_id) != current_focus && seconds_waited < 2000)
{
document.getElementById(lightbox_content_id).focus();
console.log(document.activeElement);
pause(100);
current_focus = document.activeElement
seconds_waited += 100;
}
}
However, if I remove the firebug debugging statment console.log, the function stops working!! I have no idea why this would be the case?? Why would outputting a variable to the firebug console affect weather focus is moved to the element or not? Does the console.log statement affect focus? perhaps by bringing the focus to the console debugging window?
I think your problem is calling your focus method after return false. your code should be like that :
<a href="#"
onclick="show_lightbox();focus_on_lightbox();return false;">
show lightbox
</a>
Here is the function that finally worked
function focus_on_lightbox(seconds) {
var seconds_waited
seconds_waited = seconds
document.getElementById(lightbox_content_id).focus();
seconds_waited += 100;
if (document.getElementById(lightbox_content_id) != document.activeElement && seconds_waited < 2000)
setTimeout("focus_on_lightbox(" + seconds_waited + ");", 100);
{
}
}
So why did console.log seem to affect setting the focus? Before I was using this function to pause between attempts of changing the focus.
function pause(milliseconds) {
var dt = new Date();
while ((new Date()) - dt <= milliseconds) { /* Do nothing */ }
}
This causes javascript to constantly be doing something and I think it wasn't giving the document time to render or update or something. The console.log seemed to break this lock and give the page a chance to change its focus.
When I changed approaches to using the timeout to pause between attempts, console.log was no longer needed!
Thanks bmoeskau for pointing me in the right direction.
In my experience, focus issues can sometimes be timing-related (e.g., focus() executes before the element is fully ready to be focused). I'm assuming that the lightbox markup is created dynamically when the show_lightbox function is called? If that's the case you could try adding a slight delay before attempting to focus to see if that's the issue, something like:
setTimeout("focus_on_lightbox();", 10);
Make the element focus itself. On the element's load event, set a timeout of a few ms and then call this.focus();
Else try jQuery.

Categories