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);
//.......
});
Related
I am trying to dynamically load data into the body of my modal but cannot seem to get it to work.
function legend(mb) {
var url = mb;
var location = document.getElementById("choice2");
var gwc = location.options[location.selectedIndex].value;
if (gwc == 15)
{
title = ['<strong>Geomorphology</strong>'];
var url = 'http://localhost/geoserver/apib/wms?REQUEST=GetLegendGraphic&VERSION=1.1.0&FORMAT=image/png&WIDTH=20&HEIGHT=25&LAYER=apib:chamapwathi_block_gm&legend_options=fontSize:14';
}
}
Considering you have only the javascript tag there, I am adding a basic javascript solution. In my example, content changes on button click, which you would have to do when you get the data from your API call.
I have also added an id attribute to the modal body.
document.getElementById('left-modal-body').innerHTML = 'Hello';
Updated Example
I've a servlet that prints html pages. I would like that those pages auto cicling using a js script. So I load an html page, after 3 second it refresh and I load another html page (printed by the same servlet).
In the servlet:
- read the session where I store the index of the page i'm printing;
- basing on this index, I print the page and I update the index (it increase or it return to 0 if I'm printing last page)
- store the index in a div element, so I can find it by javascript function and refresh the html page with a js function
out.println("<div id=\"storedDiv\">");
int indexRefresh= (int) request.getSession().getAttribute("indexRefresh");
out.println(Integer.toString(indexRefresh) );
indexRefresh=indexRefresh+1;
if (indexRefresh==Tot) {
indexRefresh=0;
}
request.getSession().setAttribute("indexRefresh", indexRefresh);
out.println("</div>");
The js function find the div element in the html page and update the page
function refresh(){
var element = document.getElementById("storeDiv");
if (element==0){
setTimeout(function() {
window.location.href = "http://localhost:9080/HydroGui/Query?anno=2018&id=1";
}, 3000);
}
if (element==1){
setTimeout(function() {
window.location.href = "http://localhost:9080/HydroGui/Query?anno=2018&id=2";
}, 3000);
}
}
But where have I call the function? if I use the
window.onload = refresh();
page load before I stored the index in the div.
So what is the best method to do this?
Use innerHTML
var element = document.getElementById("storeDiv").innerHTML;
if (element == '0') {
//...
}
I am using infinity scroll in my project. First it will fetch few records from MySQL database and show on page. Once page scroll down it make ajax query to server and load more data.
Is it possible to fetch all data at once from mysql database in json format and then perform load more on client side. So, basically I want no ajax request to database.
Here is the code which is working fine if I make ajax request on page scroll.
flag = true;
$(window).scroll(function() {
if($(window).scrollTop() + $(window).height() == $(document).height()){
first = $('#first').val();
limit = $('#limit').val();
no_data = true;
if(flag && no_data){
flag = false;
$('#loader').show();
$.ajax({
url : 'ajax_html.php',
method: 'post',
data: {
start : first,
limit : limit
},
success: function( data ) {
flag = true;
$('#loader').hide();
if(data !=''){
first = parseInt($('#first').val());
limit = parseInt($('#limit').val());
$('#first').val( first+limit );
$('#timeline-conatiner').append( '<li class="year">'+year+'</li>');
$('#timeline-conatiner').append( data );
year--;
}else{
alert('No more data to show');
no_data = false;
}
},
error: function( data ){
flag = true;
$('#loader').hide();
no_data = false;
alert('Something went wrong, Please contact admin');
}
});
}
}
});
This is untested and just an example of the method, Sorry I don't have time for a full example but this should give you the idea.
//data cache
var cache = ['one','two', 'three' .....];
//current location in cache
var current = 0;
//ajax request object
var request;
if($(window).scrollTop() + $(window).height() == $(document).height()){
var cache_total = cache.length;
//add next item to page & increase the current pointer
$('#timeline-conatiner').append( cache[current] );
++current;
if( current - cache.length < 50 ){
//if we only have 50 items not shown in cache pull next results with ajax and add to cache
if( !request ){
//also youll want to keep track if you have a pending request that hasn't returned yet, to prevent race conditions.
request = $.ajax( .... ).success( function( data ){
$.extend( cache, data ); //or push each if you like
}).always( function(){
request = false; //should be false on finish but just because.
});
} //end if request
//make sure to properly offset the data using the total in the cache to prevent pulling duplicates. eg SELECT ... LIMIT {cache.length}, 50
} // end if cached
} //end scroll
See the issue with what you have above is the user needs to wait for the ajax call to finish, which essentially turns it into a synchronous request ( like reloading the page ). You want to keep it asynchronous as ajax is intended to be. So instead of displaying the results of the ajax, you buffer them and keep some data you are not showing. Then on scroll show some buffered data and after that fill the cache back up.
Obviously this makes it much more complex to code, but the advantage is you don't need to pull a massive amount of data at one time and the user wont get the delay from halting on the ajax request. You'll have to balance the time the request takes with the amount of data in the cache so you always have some data in there. This depends on how much space data takes to render and how long the ajax query takes.
I would say you don't need infinity scroller (or whatever) at all to do what u want... but since u have it all nicely working and I suspect u might decide u want that 'lazy load' type functionality back at some point u could do the lazy thing...
Simply try playing around with the first and limit param values in your example...
Say...
first = 0 and
limit = some really big number...
I think u can set some values and force a single ajax call on page load very easily.
If all data has been retrieved and added to DOM, then following script may be helpful. First add hidden class to extra elements. Run this script after DOM is created.
$(".elements").each(function(index, el) { // `elements` is the common class for all elements on which this functionality is to be done
if (index >= maxLimitToShow) { // maxLimitToShow - number of elements to show in the beginning
$(el).addClass("hidden"); // for extra elements
}
});
Add css for class hidden
.hidden {
display: none;
}
And check when scroll has reached the bottom of page to show more items.
$(window).scroll(function() {
if($(window).scrollTop() + $(window).height() == $(document).height()) { // checks if scroll reached at bottom
var elements = $(".elements.hidden"); // fetch all hidden elements
elements.each(function (index, el) {
if (index < singleRowLimit) { // singleRowLimit - number of elements to show in one scroll
$(el).removeClass('hidden');
}
});
}
});
EDIT - without using CSS - hide/show
If all data has been retrieved and added to DOM, then following script may be helpful. First add hidden class to extra elements. Run this script after DOM is created.
$(".elements").each(function(index, el) { // `elements` is the common class for all elements on which this functionality is to be done
if (index >= maxLimitToShow) { // maxLimitToShow - number of elements to show in the beginning
$(el).addClass("hidden").hide(); // for extra elements
}
});
And check when scroll has reached the bottom of page to show more items.
$(window).scroll(function() {
if($(window).scrollTop() + $(window).height() == $(document).height()) { // checks if scroll reached at bottom
var elements = $(".elements.hidden"); // fetch all hidden elements
elements.each(function (index, el) {
if (index < singleRowLimit) { // singleRowLimit - number of elements to show in one scroll
$(el).removeClass('hidden').show();
}
});
}
});
I am new at AJAX and JQuery and trying to use them in the part of my website. Basically the website that I have, has this kind of design and currently it is functional (Sorry for my poor paint work :)
The items in the website are created by user. This means item number is not constant but can be fetched by db query.
Each item has a unique URL and currently when you click an item, all page is refreshing. I want to change the system to let the user have a chance to navigate quickly between these items by only chaning middle content area as shown above. However I also want to have a unique URL to each item. I mean if the item has a name like "stack overflow", I want the item to have a URL kind of dev.com/#stack-overflow or similar.
I don't mind about the "#" that may come from AJAX.
In similar topics I have seen people hold constant names for items. For instance
<a href="#ajax"> but my items are not constant.
WHAT I HAVE TRIED
Whats my idea is; while fetching all item's links, I'm holding links in $link variable and using it in <a href="#<?php echo $link; ?>">.
Inside $link it is not actual URL. it is for instance a name like "stack-overflow" as I ve given example above. Until this part there is no problem.
PROBLEM
In this topic a friend suggested this kind of code as an idea and I ve changed it for my purpose.
<script>
$(document).ready(function() {
var router = {
"<?php echo $link ?> ": "http://localhost/ajax_tut/link_process.php"
};
$(window).on("hashchange", function() {
var route = router[location.hash];
if (route === undefined) {
return;
} else {
$(".content-right").load("" + route + " #ortadaki_baslik");
}
});
});
</script>
I'm trying to post the value of $link to the link_process.php and at link_process.php I will get the value of $link and arrange neccessary page content to show.
The questions are;
- How should I change this code to do that?
- I couldnt see someone doing similar to take as an example solve this
issue. Is this the right way to solve this situation?
- Do you guys have a better solution or suggestion for my case?
Thanks in advance.
WHEN your server side AJAX call handler [PHP script - handling AJAX requests at server side] is constant and you are passing item_id/link as GET parameter...
For example:
localhost/ajax_tut/link_process.php?item_id=stack-overflow OR
localhost/ajax_tut/link_process.php?item_id=stack-exchange
Then you can use following code.
<script>
$(document).ready(function() {
var ajax_handler = "localhost/ajax_tut/link_process.php?item_id=";
$(window).on("hashchange", function() {
var route = location.hash;
if (route === undefined) {
return;
} else {
route = route.slice(1); //Removing hash character
$(".content-right").load( ajax_handler + route );
}
});
});
</script>
WHEN you are passing item_id/link as URL part and not parameter...
For example:
localhost/ajax_tut/stack-overflow.php OR
localhost/ajax_tut/stack-exchange.php
Then you can use following code.
<script>
$(document).ready(function() {
var ajax_handler = "localhost/ajax_tut/";
$(window).on("hashchange", function() {
var route = location.hash;
if (route === undefined) {
return;
} else {
route = route.slice(1); //Removing hash character
$(".content-right").load( ajax_handler + route + ".php");
}
});
});
</script>
WHEN Your server side AJAX handler script url is not constant and varies for different items...
For example: localhost/ajax_tut/link_process.php?item_id=stack-overflow OR localhost/ajax_tut/fetch_item.php?item_id=stack-exchange OR localhost/ajax_tut/stack-exchange.php
Then I suggest to change PHP script which is generating item's links placed on left hand side.
<?php
foreach($links as $link){
// Make sure that you are populating route parameter correctly
echo '<a href="'.$link['item_id'].'" route="'.$link['full_ajax_handler_route_url_path'].'" >'.$link['title'].'</a>';
}
?>
Here is Javascript
<script>
$(document).ready(function() {
var ajax_handler = "localhost/ajax_tut/"; //Base url or path
$(window).on("hashchange", function() {
var route = location.hash;
if (route === undefined) {
return;
} else {
route = route.slice(1); //Removing hash character
route = $('a [href="'+.slice(1)+'"]').attr('route'); //Fetching ajax URL
$(".content-right").load( ajax_handler + route ); //Here you need to design your url based on need
}
});
});
</script>
I have a list of products say:
laptops/prod1.html
laptops/prod2.html
laptops/prod3.html
monitors/prod1.html
monitors/prod2.html
monitors/prod3.html
I would like a button on my page that 'cycles' through the available items.
No idea how to do this. Is this possible with javascript?
function nextProduct(incr) {
var href = window.location.href
, offset = (typeof(incr)==='undefined' ? 1 : incr);
window.location = href.replace(/(\d+)\.html/, function(m, g1) {
return (Number(g1) + offset) + '.html'
});
}
Then you can do something like:
var button;
button = document.getElementByID('next-button');
button.addEventListener('click', function() { nextProduct(1); });
button = document.getElementByID('prev-button');
button.addEventListener('click', function() { nextProduct(-1); });
Setup a main page, this should not be a static html page but in your server side language of choice.
Include jquery to a main page using a script tag (you can get jquery from http://jquery.com/).
Your html could look like this:
<div id='content'></div>
<div>
<a href='javascript:void(0)' id='prev' class='btn'>Previous</a>
<a href='javascript:void(0)' id='next' class='btn'>Next</a>
</div>
In your js file you would have something like this:
var currPage = 0;
var pageList = ["laptops/prod1.html","laptops/prod2.html", "laptops/prod3.html"];
var totalPages = pageList.length;
$(".btn").on("click",function(){
//if we are at the last page set currpage = 0 else increment currPage.
currPage = currPage < (totalPages - 1) ? ++currPage : 0;
var page = pageList[currPage];
$('#content').load(currPage);
});
Some points to consider:
You will want to decide if the first page gets loaded on the main page load or on click
You will need to set a js variable to keep track of the currently loaded page
You will need to add some method of storing all the possible pages (think an array). This can get printed out to a script tag on the page on page load.
You need to decide what happens when you hit the end of the line. You can either cycle around or grey out the appropriate link.
jquery on
jquery load