Ajax update post request on click jQuery - javascript

I would like to click on a previous or next button and update the ajax post request. The parameter I want to change is the variable called "page". The URL of the request takes this variable to show the right page. When I click on a previous or next button I want to change the "page" variable value. Thanks.
$(document).ready(()=>{
var pageSize = "pageSize=10";
//want to change the page number on click
var page = "page=1"
var requestIndex = $.ajax({
type: 'POST',
url: `url`,
beforeSend: function(){
$("#loading").show();
},
complete: function(){
$("#loading").hide();
}
});
// console.log(request)
requestIndex.done((data)=>{
var done = JSON.parse(data)
// console.log(done)
done.forEach((result, index)=>{
// res.push(result)
var firstName = result.FirstName;
var lastName = result.LastName;
var modelYear = result.ModelYear;
var make = result.Make;
var model = result.Model;
var dealership = result.Dealership;
$('#test>tbody').append(`
<tr>
<td>${firstName} ${lastName}</td>
<td>${modelYear}</td>
<td>${make}</td>
<td>${model}</td>
<td>${dealership}</td>
</tr>
`)
})
var tr = $('table').find("tr");
var resultQuant =[]
resultQuant.push(tr)
var pages = []
//loop over each result and create pagination
resultQuant.forEach(function(res, index){
console.log(res.length);
if(res.length > 9){
$('#prev_page').append(`
Prev Page
`)
$('#next_page').append(`
Next Page
`)
}
})
});
requestIndex.fail(function(jqXHR, textStatus) {
console.log('failed')
});
})

Here is a working snippet for what I think you're looking for. I had to make some changes, some for aesthetics, and some for functionality. Here's the functional changes/updates:
Your whole ajax/refresh table script needed to be outsourced to a function so it could be called multiple times.
The page and pageSize variables are better left as numbers rather than queryString strings
I created a delegated event listener on your buttons. It's one listener that will handle either button. The listener callback finds out if its the next or previous button that was clicked, then calls the goToPage() function with the incremented onPage variable
The table is now cleared before each new data batch is written to it, as you'd expect a paginated result to be
The buttons should disable/enable according to the pagination, so I put in a script to test if we're at the first page or the last page to disable/enable them
I changed all your vars to lets because that's the way we initialize block variables nowadays
let onPage, pageSize = 10;
$(document).ready(() => {
goToPage(1)
$('body').on('click', '#next_page, #prev_page', function() {
inc = 1;
if ($(this).attr('id') === 'prev_page') inc = -1;
goToPage(onPage + inc);
})
})
function goToPage(page) {
let requestIndex = $.ajax({
type: 'POST',
url: `url`,
beforeSend: function() {
$("#loading").show();
},
complete: function() {
$("#loading").hide();
}
});
requestIndex.done((data) => {
onPage = page;
$('#test>tbody').html('');
JSON.parse(data).forEach((result, index) => {
$('#test>tbody').append(`
<tr>
<td>${result.FirstName} ${result.LastName}</td>
<td>${result.ModelYear}</td>
<td>${result.Make}</td>
<td>${result.Model}</td>
<td>${result.Dealership}</td>
</tr>
`)
})
if (onPage > 1) $('#prev_page').removeAttr('disabled');
else $('#prev_page').attr('disabled', true)
if (JSON.parse(data).length === pageSize) $('#next_page').removeAttr('disabled');
else $('#next_page').attr('disabled', true)
});
requestIndex.fail(function(jqXHR, textStatus) {
console.log('failed')
});
}
#loading {
display: none'
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id='loading'>Loading...</div>
<table id='test'>
<tbody></tbody>
</table>
<button id='prev_page'>Prev Page</button>
<button id='next_page'>Next Page</button>

Related

Asp.net webform infinity scroll

I have a page shows product catalog populated by a webmethod.
When user click on image he is redirect to details page.
When user come back to catalog id like page scroll bottom at the product visited
How can i accomplish this
my html
<div class="articoli">
</div>
my javascript
<script>
$(document).ready(function () {
var Skip = 9;
var Take = 9;
function Load(Skip, Take) {
$('#divPostsLoader').html('<img src="Images/loading.gif" height="100" />');
$.ajax({
type: "POST",
url: "page.aspx/LoadProduct",
data: "{ Skip:" + Skip + ", Take:" + Take + " }",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (data) {
if (data != "") {
//accodo dati a div
$('.articoli').append(data.d);
}
$('#divPostsLoader').empty();
},
error: function () {
alert('error');
}
})
};
$(window).scroll(function () {
if ($(window).scrollTop() == ($(document).height() - $(window).height())) {
Load(Skip, Take);
Skip = Skip + 9;
}
});
});
my c# webmethod
[System.Web.Services.WebMethod]
public static string LoadProduct(int Skip, int Take)
{
StringBuilder GetProduct = new StringBuilder();
MyDataBaseEntities db = new MyDataBaseEntities();
var prod = (from a in db.TAB
select a).Skip(Skip).Take(Take);
foreach (var a in prod)
{
var Codart = a.Codart;
var Prezz = a.Prezz;
var pathimg = a.pathimg;
GetProduct.Append("<div class=\"col-md-4\">");
GetProduct.Append("<div class=\"col-md-6 text-left\">");
GetProduct.AppendFormat(string.Format("<a href='Details.aspx?Articolo={0}' class=\"codart\" >", Codart));
GetProduct.AppendFormat("<span class=\"codart\">{0}</span>", Codart);
GetProduct.Append("</a>");
GetProduct.Append("</div> ");
GetProduct.Append("<div class=\"col-md-6 text-right\" style=\"color:gray;font-size:large;\">");
GetProduct.AppendFormat(string.Format("{0:c}", Prezz));
GetProduct.Append("</div> ");
GetProduct.AppendFormat(string.Format("<a href='Details.aspx?Articolo={0}' class=\"codart\" >", Codart));
GetProduct.AppendFormat(string.Format("<img src='{0}' class='img-responsive MyImage' alt='{1}'/>", pathimg, Codart));
GetProduct.Append("</a>");
GetProduct.Append("</div> ");
}
return GetProduct.ToString();
}
how can i scroll bottom at page load?
Try adding an Id to the item(s) you want to scroll to. You can then, depending on how you want to tackle it, either href or assign said Id through a script to initiate a scroll. Here you can see more details on how to scroll to a specific part of your page by using the component's Id.
I would add a unique Id to each item in your list.
Then I would write a script to read/set a variable to which item to scroll to.
Mind you, I'm writing this on a whim so you might need to correct or alter it to fit your needs.
You can use this to save and read cookies with jquery.
The script could be something like this:
var scrollToId;
$(document).ready(function () {
var cookie = $.cookie('last_clicked_id');
if (cookie != '') {
scrollToId = cookie;
} else {
scrollToId = '#';
}
$("html, body").animate({ scrollTop: $(scrollToId).offset().top }, 1000);
});
$('.productItemClass')
.on('click',
function() {
$.cookie('last_clicked_id', $(this).attr('id'));
});
use this and set the variable sc
var sc;
var scroll;
var loop = setInterval(function() {
sc = window.scrollTop;
if (scroll === null) {
localstorage.setItem("bgc", sc);
}
}, 10);
window.onload = function() {
scroll = localstorage.getItem("bgc");
if (scroll !== null) {
window.scollTop = scroll + "px";
}
}

Preventing multiple requests from ajax

I have "load more" button, and if I click it fast enough it load the same content twice, and I want to prevent it.
This is how I call to the load more with ajax:
<script type="text/javascript">
function loadmore() {
var val = document.getElementById("result_no").value;
var userval = document.getElementById("user_id").value;
$.ajax({
type: 'post',
url: 'fetch.php',
data: {
getresult: val,
getuserid: userval
},
context: this,
success: function(response) {
var content = document.getElementById("result_para");
content.innerHTML = content.innerHTML + response;
document.getElementById("result_no").value = Number(val) + 10;
}
});
}
</script>
<div id="content">
<div id="result_para">
</div>
</div>
<input type="hidden" id="user_id" value="<?php echo $userid;?>">
<input type="hidden" id="result_no" value="15">
<input type="button" id="load" onclick="loadmore()" value="Load More Results">
You could set a loading variable to true at the start of loadmore, and set it back to false in the ajax callback. loading should be declared outside of loadmore though (see what a closure is).
var loading = false;
function loadmore()
{
if (loading) {
return ;
}
loading = true;
var val = document.getElementById("result_no").value;
var userval = document.getElementById("user_id").value;
$.ajax({
type: 'post',
url: 'fetch.php',
data: {
getresult:val,
getuserid:userval
},
context: this,
success: function (response) {
loading = false;
var content = document.getElementById("result_para");
content.innerHTML = content.innerHTML+response;
document.getElementById("result_no").value = Number(val)+10;
},
error: function () {
loading = false;
}
});
}
Instead of using that variable, you could also programmatically disable/enable the button, but that means that your button will flicker if the request is fast.
You can prevent from this by disable the button after first click, so change this lines:
success: function (response) {
var content = document.getElementById("result_para");
content.innerHTML = content.innerHTML+response;
document.getElementById("result_no").value = Number(val)+10;
}
With this lines:
success: function (response) {
document.getElementById("load").disabled = true;
var content = document.getElementById("result_para");
content.innerHTML = content.innerHTML+response;
document.getElementById("result_no").value = Number(val)+10;
document.getElementById("load").disabled = false;
}
you could disable the button when the "load more" button is clicked then then use the javascript function setTimeout to remove the disabled attribute from the button after a period of time. This would mean that the button would not be able to be clicked after the first click and even if the ajax request returned an error the button would still be able to be clicked.
$('#load').click(function {
// disable the button
$(this).prop('disabled', true);
// after three seconds enable the button again
var timeout = setTimeout(function() { $(this).prop('disabled', false); }, 3000);
});

MVC DropDownListFor how to add RouteLink

Hi sorry for asking such an easy question but I'm scratching my head all day today and cannot figure this out. I found lots of similar questions but non of them resolve my problem.
I had a page with list of products and few buttons to filter products by category. Because number of products has increased I decided to change them to drop down box.
So I have drop down box which populates categories:
#Html.DropDownListFor(m => m.SelectedCategoryId, Model.CategoryItems, new { id = "changeCategory" })
and javascript which fires on change event:
<script type="text/javascript">
$(document).ready(function () {
$("#changeCategory").change(function () {
var selectedCategory = $(this).text();
$.ajax({
url: '#Url.Action("List", "Deal")',
type: 'GET',
data: { category: selectedCategory },
cache: false,
});
});
});
</script>
This doesn't work. My previous routing works with the code below:
#foreach (var link in Model) {
#Html.RouteLink(link, new {
controller = "Deal",
action = "List",
category = link,
page = 1
}, new {
#class = "btn btn-block btn-default btn-lg"
})
}
UPDATE:
I have changed the jQuery code to:
<script type="text/javascript">
$(document).ready(function () {
$("#changeCategory").change(function () {
var selectedCategory = $("#changeCategory option:selected").text();
$.ajax({
url: selectedCategory,
type: 'POST',
cache: true,
});
});
});
</script>
and the link looks correct now but the website doesn't reload. When I watch this in the Chrome Developer Tool in Network section the link appear there and when I click it it does open correct page.
Why it doesn't do that on website?
UPDATE 2
My Controller
public ViewResult List(string category, int page = 1)
{
DealsListViewModel model = new DealsListViewModel
{
Deals = repository.Deals
.Where(p => category == null || p.Category == category)
.OrderBy(p => p.DealID)
.Skip((page - 1) * PageSize)
.Take(PageSize),
PagingInfo = new PagingInfo
{
CurrentPage = page,
ItemsPerPage = PageSize,
TotalItems = repository.Deals.Count()
},
CurrentCategory = category
};
return View(model);
}
Any help is appriciated
It appears you want to redirect to the List method of DealController and pass the text of the selected option. If so then
$("#changeCategory").change(function () {
window.location.href = '#Url.Action("List", "Deal")' + '/' + $(this).find('option:selected').text();
});
assuming your action method is something like
public ActionResult(string someValue)
AJAX calls stay on the same page and do not redirect to another page.
And out of curiosity, why override the default id (and not just use $("#SelectedCategoryId").change(...)?
Edit
If you want to return some html to include on the page, return a partial view and update the page html in the AJAX success function
Controller
public PartialViewResult List(string category, int page = 1)
{
DealsListViewModel model = new DealsListViewModel ....
....
return PartialView(model)
}
Script (assumes you have an element with `id="results" where you want to render the returned html)
$("#changeCategory").change(function () {
var url = '#Url.Action("List", "Deal")';
var category = $(this).find('option:selected').text();
var page = ? // if you want to pass this as well
$.get(url, { category: category, page: page }, function(data) {
$('#results').html(data);
});
});
Try the following in your ajax call:
type: 'POST'

Loading more posts not working

I am adding a LoadMore function to append more posts based on the length of current displayed posts and total posts in DOM. The issue I am having is when I console log the listofposts and I inspect the element in Google Chrome, I see the length is showing zero (0). I am not sure exactly where I have gone wrong or if the aproach I have taken is right or should I separate the two functions by first loading the first 4 posts, then create a new function separate to handle the appending?
$(document).on('pagebeforeshow', '#blogposts', function() {
//$.mobile.showPageLoadingMsg();
$.ajax({
url: "http://howtodeployit.com/category/daily-devotion/?json=recentstories&callback=",
dataType: "json",
jsonpCallback: 'successCallback',
async: true,
beforeSend: function() { $.mobile.showPageLoadingMsg(true); },
complete: function() { $.mobile.hidePageLoadingMsg(); },
success:function(data){
var $listofposts = $('data');
console.log($listofposts);
var $loadMore = $listofposts.parent().find('.load-more');
// console.log($loadMore);
currentPage = 0;
postsPerPage = 4;
var showMorePosts = function () {
$offset = currentPage * postsPerPage, //initial value is 0
posts = data.posts.slice($offset, $offset + postsPerPage);
console.log(posts);
$.each(posts, function(i, val) {
//console.log(val);
$("#postlist").html();
var result = $('<li/>').append([$("<h3>", {html: val.title}),$("<p>", {html: val.excerpt})]).wrapInner('');
$('#postlist').append(result);
console.log(result);
});
if(posts.length !== postsPerPage){
alert ('True');
$loadMore.hide();
}
currentPage++;
$("#postlist").listview();
$("#postlist").listview('refresh');
}
showMorePosts();
$loadMore.on('click', showMorePosts);
}});
var $listofposts = $('data');
is asking jQuery for a list of all <data> tags in the document.
You might want to use $(data) instead.

How to update database with jQuery without refreshing the page?

How do I send this display_false() function to the server with jQuery so that the database is updated without refreshing the page?
def display_false():
if display == "false":
main_id = self.request.get("main_id")
k = Main.get_by_id(int(main_id))
k.display = False
k.put()
display_false()
First I hide a table row with this jQuery (see my previous question):
$(document).ready(function() {
$("a.false").click(function(e) {
$(this).closest("tr.hide").hide("slow");
e.preventDefault();
});
and then I want to update the "display" property in the database to "false" with display_false()so that the item is not displayed.
And this is the html where the hide link is:
for item in e:
main_id = item.key().id()
...
<tr class="hide">
...
<a class="false" href="/useradminpage?main_id=%s&display=false"><span class="small">(hide)</span></a>
...
</td>
</tr>
...
Thanks!
Update
This is what I tried according to Paul's answer, but this is not working.
$(document).ready(function() {
//hide the row
$("a.false").click(function(e) {
$(this).closest("tr.hide").hide("slow");
e.preventDefault();
});
$("a.false").click(function() {
//ajax server call
$.ajax({
url: "/useradminpage?main_id=%s&display=false",
success: function(data) {
//do some stuff.
display_false()
alert('returned');
}
});
});
});
Update
I put alerts to see what is running as suggested by Paul. Alerts 1, 2 and 3 are running but 4 is not running:
$(document).ready(function() {
alert("1 - document ready is called")
$("a.false").click(function(e) {
$(this).closest("tr.hide").hide("slow");
e.preventDefault();
alert("2 - row is hidden")
});
$("a.false").click(function() {
//ajax server call
alert("3 - ajax server call")
$.ajax({
url: "/useradminpage?main_id=%s&display=false",
success: function(data) {
//do some stuff.
display_false()
alert(4 - "returned");
}
});
});
});
Update
This is the part of the code for that section of the table; I am trying to get the main_id and pass it to ajax call:
#-----------main table------------#
main_id = self.request.get("main_id")
self.response.out.write("""<table class="mytable">
<tr class="head">
<th width="80%">links</th><th>edit tags</th>
</tr>
""")
query = Main.all()
query.filter("owner", user)
query.filter("display", True)
query.order("-date")
cursor = self.request.get("cursor")
if cursor: query.with_cursor(cursor)
e = query.fetch(100)
cursor = query.cursor()
for item in e:
main_id = item.key().id()
self.response.out.write("""
<tr class="hide">
<td>%s<span class=small> (%s) </span><br />
<span class=small>%s</span>
<span class="small">(edit)</span>
<a class="false" href="/useradminpage?main_id=%s&display=false"><span class="small">(hide)</span></a>
<span class="small">(comments)</span></td>
<td>%s
</td>
</tr>
""" % tuple([item.url, item.title, urlparse(item.url).netloc,
f1.truncate_at_space(item.pitch), main_id, main_id, main_id,
item.url, main_id, (", ".join(item.tag_list)),
(", ".join(item.tag_list)),]))
self.response.out.write("""</tbody></table>""")
display = self.request.get("display")
def display_false():
if display == "false":
main_id = self.request.get("main_id")
k = Main.get_by_id(int(main_id))
k.display = False
k.put()
display_false()
Update after discussion with Paul to get the id number of the hidden row:
<script>
$(document).ready(function() {
alert("1 - document ready is called")
$("a.false").click(function(e) {
$(this).closest("tr.hide").hide("slow");
e.preventDefault();
alert("2 - row is hidden")
});
$("a.false").click(function() {
alert(this.attr("title"));
$.ajax({
url: "/useradminpage?main_id=%s&display=false",
success: function(data) {
display_false()
alert(4 - "returned");
}
});
});
});
</script>
You cannot update a server database with JQuery. All you can do is send a request that is handled by the server.
Use JQuery.Ajax or any spin-offs of that function to send the request. To your server it will look as a regular request.
You'll need an AJAX call, something like this after including your jQuery libraries.
$(document).ready(function() {
//false click action
$("a.false").click(function () {
//ajax server call
$.ajax({
url: '/useradminpage?main_id=%s&display=false',
success: function(data) {
//do some stuff.
alert('returned');
}
});
});
});

Categories

Resources