I have created a function who tracks on which slide I am currently on and display the result
e.g. If I am on slide 2 of 3 it will display 2/3
my problem is that right now it is set to do that every time I click the forward arrow but it displays nothing on page load.
$('.forward').click(function() {
var current = $('#slider').data('AnythingSlider').currentPage; // returns page #
var count = $("#slider").children().length - 2;
$("#bottom-image").html(current + "/" + count) ;
});
I am trying to find out how to execute this function on page load and where to put it in my code. I am currently learning Javascript through Codecadamedy so I have a basic knowledge of Javascript but I am not enough fluent right now to figure this one out.
Here is a link to the current non working code : http://www.soleilcom.com/metacor_dev/our-plants.php
It looks like you are using jQuery. To execute a function on DOM load in query, do this:
$(document).ready(function() {
/* your code */
});
In your case, that would be:
$(document).ready(function() {
$('.forward').click(function() {
var current = $('#slider').data('AnythingSlider').currentPage; // returns page #
var count = $("#slider").children().length - 2;
$("#bottom-image").html(current + "/" + count) ;
});
});
For things like most event handlers, and most other things, initializing at DOM load is good enough. If your code needs to take account for rendered elements or rendered heights, use $(window).load() instead. (In your case DOM load is fine).
Note that this will just establish the click handler at load time. To also run it once, you can do it automatically by either calling the function yourself or triggering a click. To call it yourself, first define another function. The use the function in both the click handler and in one immediate call:
$(document).ready(function() {
var forward = function() {
var current = $('#slider').data('AnythingSlider').currentPage; // returns page #
var count = $("#slider").children().length - 2;
$("#bottom-image").html(current + "/" + count) ;
}
$('.forward').click(forward);
forward();
});
Or to trigger it yourself, just define the click handler and trigger a click programatically:
$(document).ready(function() {
$('.forward').click(function() {
var current = $('#slider').data('AnythingSlider').currentPage; // returns page #
var count = $("#slider").children().length - 2;
$("#bottom-image").html(current + "/" + count) ;
}).click();
});
It looks like you are using jQuery, so you would use this:
$(document).ready(function(){
// Code here
});
Or, you can use the shortcut:
$(function(){
// Code here
});
Read more about this on the jQuery website
If you give the function a name, then you can use it multiple times:
$(document).ready(function() {
// Bind to click event
$('.forward').click(forwardSlide)
// Execute function on page load
forwardSlide();
});
function forwardSlide() {
var current = $('#slider').data('AnythingSlider').currentPage; // returns page #
var count = $("#slider").children().length - 2;
};
Is this what you're looking for?
Related
What I'm trying to do exactly
I'm creating a custom WordPress site, it displays a "load more posts" button in the pages blog (main), category and search results. When the user clicks this button, the script retrieves the posts in the next page and appends them inside a container. Here's the code:
<script>
document.addEventListener("DOMContentLoaded", function() {
// display or not the btn when page is loaded
var morePosts = $("#dom-target").text();
if (morePosts != "true") {
$('.load-more').css('display','none');
}
// button functionality
var pageIndex = 1;
var numOfPages = Number($('#numOfPages').text()); // parsed from php
var nextLink = $('#nextLink').text(); // parsed from php
$('.load-more').click(function(){
if (pageIndex < numOfPages) {
var nextPosts;
$.get(nextLink+' .post-card', function(data){
// get articles in next page
nextPosts = data;
// append articles
$('#content').append(nextPosts);
// change value of index and redefine nextLink
pageIndex++;
nextLink = nextLink.replace(pageIndex+'/',pageIndex+1+'/');
// check if button display is still needed
if (pageIndex == numOfPages) {
$('.load-more').css('transition','all 0s');
$('.load-more').fadeOut();
}
});
}
});
});
</script>
The problem: It loads the entire page
I wonder if $.get() has a equivalent for .load('main url .specific-class'), because when I try to apply the analogous syntax
$.get(nextLink+' .post-card')
the console threw me
GET http://localhost/blog/page/2/%20.post-card 404 (Not Found)
Or if there is a way to parse the data (a string) as an HTML document (so I can apply jQuery to the variable that stores the data and get just the post cards instead of the entire page).
Thanks in advance! :)
You have to parse the response yourself which you can do simply by wrapping in $() and using any jQuery method on
$.get(nextLink, function(data){
var nextPosts = $(data).find('.post-card');
$('#content').append(nextPosts);
//.......
});
Ok I will try to make it simple.
1) I have 3 links that execute an Ajax Request and update a div with some content.
The DIV
<div id="content-to-update"></div>
The 3 links that update #content-to-update
example 1
example 2
example 3
Each link update the div #content-to-update with the content just below with one parameter named CODE
The the div #content-to-update is updated with the code below.
var loading = false;
$(window).scroll(function () {
var winTop = $(window).scrollTop();
var docHeight = $(document).height();
var winHeight = $(window).height();
//if user reach bottom of the page
if (!loading && (winTop / (docHeight - winHeight)) > 0.95) {
loading = true;
//the CODE parameter is different on each call from the links that I
//talked earlier.
$.get("/items/next/?list_name=" + CODE, function(data){
//executing some javascript to display next items
}).done(function() {
loading = false;
})
}
});
});
The problem is that it seams the browser keep all different version of the updated div.
Its like the old content is not erased before the new content is added.
If I click on the first link and scroll I get the right items OK!.
Then if I click on the second link, when I scroll I get the Item twice (duplicated- it calls the code from the previous ajax call)
Then if I click on the third link, when I scroll I get the Item 3 times. (it calls the code from the 2 previous ajax call )
When I use the Chrome debugger I see that it goes first in the code that have received the parameter EXAMPLE_1 then it goes in the code that has received the parameter EXAMPLE_2 etc
But this code should has been overridden by the call of the EXAMPLE_2 link.
It is difficult to explain I don't know if someone understand what Im trying to explain but I give it a try :) and again sorry for my english.
Thanks
I'm a bit picky about POST and GET, so even though Wayne is technically correct, the fact that you are retrieving data makes your use of GET the right way of doing it.
The way around caching is either by using jQuery's ajax method and setting cache to false, like so:
$.ajax({
url: "/items/next/?list_name=" + CODE,
type: 'GET',
success: function(data) {
$('#content-to-update').html(data);
},
cache:false,
error: function(e) {
alert("Server failure! Is the server turned off?");
}
});
You can also trick the browser by adding a random string to the end of the URL, which is what I usually do. Something like this:
$.get("/items/next/?list_name=" + CODE + '&cache_buster=' + (new Date()).getTime().toString(), function(data){
//executing some javascript to display next items
}).done(function() {
loading = false;
})
If you are using .html() to set the content, the error is definitely somewhere else. Ensure that you are not appending the new content to the div, which seems like what you are doing.
Also, your functions should act independently of one another. Your current process seems to support that, but your problem seem to suggest otherwise.
Try the suggestions first and if they don't work, post more code.
Update
Try this:
var loading = false;
function executeSomeAjax(CODE){
$(window).scroll(function () {
var winTop = $(window).scrollTop();
var docHeight = $(document).height();
var winHeight = $(window).height();
//if user reach bottom of the page
if (!loading && (winTop / (docHeight - winHeight)) > 0.95) {
loading = true;
//the CODE parameter is different on each call from the links that I
//talked earlier.
$.get("/items/next/?list_name=" + CODE, function(data){
//executing some javascript to display next items
}).done(function() {
loading = false;
})
}
});
});
}
As you can see, the variable loading is now a global variable. I suspect that it was a local variable in your original function and as a result was set to false anytime the function ran.
Making it a global variable should resolve your issue.
Hope this helps.
UPDATE
Ok this is the final working code thanks to everybody for helping me out !
I think the problem was coming from low memory on my computer. The code you see below was used yesterday and was not working.
Since I rebooted the computer this morning everything works like a charm. I have 4GO of memory and working with Grails 2.2.2 and Intellij IDEA Im often with 100Mo of memory left I guess this should have a side effect. I cant see other explanations.
If That can help anyone to read this post
var loading = false;
function nextProject(){
$('.logo').html('<img src="/images/ajax-loader-transparent.gif">');
$.ajax({
type:'GET',
url: "/project/next/",
data:"list_name=" + CODE,
beforeSend:function(){
console.log("loading : " + loading)
}
}).done(function(data) {
if(data != ""){
var arrayOfObjects = eval(data);
for(var i=0; i < arrayOfObjects.length; i++){
TrackManager.newTrack(btoa(arrayOfObjects[i].base64Params));
var projectMgr = new ProjectManager(arrayOfObjects[i].id);
projectMgr.socialShare();
<sec:ifNotLoggedIn >
projectMgr.runDeny();
</sec:ifNotLoggedIn>
<sec:ifLoggedIn >
projectMgr.runGranted(arrayOfObjects[i].likeUp, arrayOfObjects[i].inPlayList );
</sec:ifLoggedIn>
INC++;
}
loading = false;
$('.logo').html('<img src="/images/soundshare_logo_32.png">');
console.log(INC + "/" + PROJECT_COUNT );
}
}).fail(function(){
console.error("Ajax error!")
});
}
$(window).scroll(function(){
var winTop = $(window).scrollTop();
var docHeight = $(document).height();
var winHeight = $(window).height();
if ((winTop / (docHeight - winHeight)) > 0.95) {
if(INC < PROJECT_COUNT){
if(!loading){
loading = true;
nextProject()
}
}
}
});
I'm writing a Greasemonkey script to automatically delete my notifications from a site, based on words I enter into a search box.
The delete "button" is basically a link, so I'm trying to open the first link in a new tab. Then, after it loads enough, open the rest of the links, one by one, in that same tab.
I figured out how to get the links I needed and how to loop and manipulate them. I was able to grab the first delete-link and open it in a new tab. I added an event listener to make sure the page was loaded before going to the next link.
I finally made that work so added my search box and button. Then I had to figure out how to wrap the whole thing in the event listener again.
So, I now have the whole thing working, except only the last link loads.
All links are going to my waitFor function so they should open, so it seems the event listener isn't working so it goes through the loop too fast and only the last link loads.
How do I make this script not continue the loop until the previous loaded page is fully loaded?
Complete code except for box and button creation:
var mytable = document.getElementById ('content').getElementsByTagName ('table')[0]
var myrows = mytable.rows
//function openLinkInTab () {
//mywin2.close ();
//}
var mywin2;
mywin2 = window.open ("http://www.aywas.com/message/notices/test/", "my_win2");
var links;
var waitFor = function (i) {
links = myrows[i].cells[1].getElementsByTagName ("a");
mywin2 = window.open (links[0].href, "my_win2");
}
var delnotifs = function () {
var matching;
var toRemove;
toRemove = document.getElementById ('find').value;
alert (toRemove)
for (i = 0; i < 10; i++) {
matching = myrows[i].cells[0].innerHTML;
if (matching.indexOf (toRemove) > 0) {
mywin2.addEventListener ('load', waitFor (i), false);
}
}
}
searchButton.addEventListener ('click', delnotifs, true);
So, why isn't it waiting for `mywin2.addEventListener('load', waitFor(i), false);`? I have a feeling it's something extremely simple that I'm missing here, but I just can't see it.
I also tried mywin2.addEventListener('load', function(){waitFor(i)}, false); and it still does the same thing, so it's not a problem of being a call instead of a pointer.
Swapping mywin2.addEventListener('load', waitFor(i), false); for
if (mywin2.document.readyState === "complete") { waitFor(i)} doesn't work either.
And while I'm at it... every time I see code looping through a list like this it uses
for(i=1;i < myrows.length;i++)
Which was skipping the first link in the list since arrays start at zero. So my question is, if I switch 'i' to zero, and the loop only goes while 'i' is < length, doesn't that mean it won't go through the whole list? Shouldn't it be
for(i=0;i != myrows.length;i++)
When you open a popup (or tab) with window.open, the load event only fires once -- even if you "open" a new URL with the same window handle.
To get the load listener to fire every time, you must close the window after each URL, and open a new one for the next URL.
Because popups are asynchronous and you want to load these links sequentially, don't use a for() loop for that. Use the popup load status to "chain" the links.
Here is the code to do that. It pushes the links onto an array, and then uses the load event to grab and open the next link. You can see the code in action at jsFiddle. :
var searchButton = document.getElementById ('gmPopUpBtn');
var mytable = document.getElementById ('content').getElementsByTagName ('table')[0];
var myrows = mytable.rows;
var linksToOpen = [];
var mywin2 = null;
function delnotifs () {
var toRemove = document.getElementById ('find').value;
for (var J = 0, L = myrows.length; J < L; J++) {
var matching = myrows[J].cells[0].innerHTML;
if (matching.indexOf (toRemove) > 0) {
var links = myrows[J].cells[1].getElementsByTagName ("a");
linksToOpen.push (links[0].href); //-- Add URL to list
}
}
openLinksInSequence ();
};
function openLinksInSequence () {
if (mywin2) {
mywin2.close ();
mywin2 = null;
}
if (linksToOpen.length) {
var link = linksToOpen.shift ();
mywin2 = window.open (link, "my_win2");
mywin2.addEventListener ('load', openLinksInSequence, false);
}
}
searchButton.addEventListener ('click', delnotifs, true);
See https://developer.mozilla.org/en-US/docs/Web/API/EventTarget.addEventListener.
The second argument of the addEventLister function must be a pointer to a function and not a call.
All,
I have a 'credit module' (similar to credit system in games), which when a user performs an action, creates an inner div with the cost to be added or substracted so user can see what the cost of the last action was.
Problem: Everything works fine as long as the function is called once, if the user performs multiple actions quickly, the setTimeout functions (which are suppose to animate & then delete the cost div) donot get executed. It seems the second instance of the function resets the setTimeout function of the first.
(function()
{
$("#press").on("click", function(){creditCost(50)});
function creditCost(x)
{
var eParent = document.getElementById("creditModule");
// following code creates the div with the cost
eParent.innerHTML += '<div class="cCCost"><p class="cCostNo"></p></div>';
var aCostNo = document.getElementsByClassName("cCostNo");
var eLatestCost = aCostNo[aCostNo.length - 1];
// following line assigns variable to above created div '.cCCost'
var eCCost = eLatestCost.parentNode;
// cost being assigned
eLatestCost.innerHTML = x;
$(eCCost).animate ({"left":"-=50px", "opacity":"1"}, 250, "swing");
// following code needs review... not executing if action is performed multiple times quickly
setTimeout(function()
{
$(eCCost).animate ({"left":"+=50px", "opacity":"0"}, 250, "swing", function ()
{
$(eCCost).remove();
})
}, 1000);
}
})();
jsfiddle, excuse the CSS
eParent.innerHTML += '<div class="cCCost"><p class="cCostNo"></p></div>';
is the bad line. This resets the innerHTML of your element, recreating the whole DOM and destroying the elements which were referenced in the previous invocations - letting their timeouts fail. See "innerHTML += ..." vs "appendChild(txtNode)" for details. Why don't you use jQuery when you have it available?
function creditCost(x) {
var eParent = $("#creditModule");
// Create a DOM node on the fly - without any innerHTML
var eCCost = $('<div class="cCCost"><p class="cCostNo"></p></div>');
eCCost.find("p").text(x); // don't set the HTML if you only want text
eParent.append(eCCost); // don't throw over all the other children
eCCost.animate ({"left":"-=50px", "opacity":"1"}, 250, "swing")
.delay(1000) // of course the setTimeout would have worked as well
.animate ({"left":"+=50px", "opacity":"0"}, 250, "swing", function() {
eCCost.remove();
});
}
You are starting an animation and scheduling a timeout to work on DOM elements that will get modified in the middle of that operation if the user clicks quickly. You have two options for fixing this:
Make the adding of new items upon a second click to be safe so that it doesn't mess up the previous animations.
Stop the previous animations and clean them up before starting a new one.
You can implement either behavior with the following rewrite and simplification of your code. You control whether you get behavior #1 or #2 by whether you include the first line of code or not.
function creditCost(x) {
// This first line of code is optional depending upon what you want to happen when the
// user clicks rapid fire. With this line in place, any previous animations will
// be stopped and their objects will be removed immediately
// Without this line of code, previous objects will continue to animate and will then
// clean remove themselves when the animation is done
$("#creditModule .cCCost").stop(true, false).remove();
// create HTML objects for cCCost
var cCCost = $('<div class="cCCost"><p class="cCostNo">' + x + '</p></div>');
// add these objects onto end of creditModule
$("#creditModule").append(cCCost);
cCCost
.animate ({"left":"-=50px", "opacity":"1"}, 250, "swing")
.delay(750)
.animate({"left":"+=50px", "opacity":"0"}, 250, "swing", function () {
cCCost.remove();
});
}
})();
Note, I changed from setTimeout() to .delay() to make it easier to stop all future actions. If you stayed with setTimeout(), then you would need to save the timerID returned from that so that you could call clearTimeout(). Using .delay(), jQuery does this for us.
Updated code for anyone who might want to do with mostly javascript. Jsfiddle, excuse the CSS.
function creditCost(x)
{
var eParent = document.getElementById("creditModule");
var eCCost = document.createElement("div");
var eCostNo = document.createElement("p");
var sCostNoTxt = document.createTextNode(x);
eCCost.setAttribute("class","cCCost");
eCostNo.setAttribute("class","cCostNo");
eCostNo.appendChild(sCostNoTxt);
eCCost.appendChild(eCostNo);
eParent.insertBefore(eCCost, document.getElementById("creditSystem").nextSibling);
$(eCCost).animate ({"left":"-=50px", "opacity":"1"}, 250, "swing");
setTimeout(function()
{
$(eCCost).animate ({"left":"+=50px", "opacity":"0"}, 250, "swing", function ()
{
$(eCCost).remove();
})
}, 1000);
}
I have the following code which is not working
jQuery
jQuery(window).bind("load", function() {
function effects(content_name,active_name)
{
// switch all tabs off
$(active_name).removeClass("active");
// switch this tab on
$(this).addClass("active");
// slide all content up
$(content_name).slideUp();
// slide this content up
var content_show = $(this).attr("title");
$("#"+content_show).slideDown();
}
$("a.tab_1").click(function () {
var content_name = '.content_a';
var active_name = 'a.tab_1.active';
effects(content_name,active_name);
});
$("a.tab_2").click(function () {
var content_name = '.content_b';
var active_name = 'a.tab_2.active';
effects(content_name,active_name);
});
$("a.tab_3").click(function () {
var content_name = '.content_c';
var active_name = 'a.tab_3.active';
effects(content_name,active_name);//create effects with the content
});
});
Its a set of tab groups upto 8 in number. Writing individual functions will have an adverse effect on loading time.
Answer 2 hours later:
Thank you all for pointing out the "effetcs" mistake in the code.
The other mistake was I was doing was not passing "$(this)" as a parameter into the called function "effects".
I Have adjoined the link where the necessary changes are done and the code works.
[jsfiddle] http://jsfiddle.net/phyGS/2/
Replace effetcs with effects at the first block, and replace every occurrence of
effects(content_name,active_name);
with
effects.call(this, content_name, active_name);
This call method assigns a new value to the this property of function effects.