Asp.net webform infinity scroll - javascript

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";
}
}

Related

Ajax update post request on click jQuery

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>

yii2 hide model name from url in GET Method

I have a script that switches images in a certain amount of time. But on my page, the images are not displayed because they get method gets the wrong URL: GET http://schedule/monitor/img/math/22.03/22.03.JPG 404 (Not Found). The correct URL should be like this:
http://schedule/img/math/22.03/22.03.JPG. How to hide the model name from image src when I get this from js script?
slider.js
$(document).ready(function () {
$.ajax({
type: 'GET',
dataType: 'json',
url: '/monitor/insert_math',
data: 'json',
success: function (data) {
var i = 0; //START POINT
var unfiltered_images = data; //UNFILTERED IMAGES ARRAY
var time = 30000; //TIME BETWEEN SWITCH
var images = unfiltered_images.filter(file => file.endsWith('.JPG')); //FILE FILTER BY EXTENSION
console.log(images);
if (images.length != 0) {
function changeImg() {
document.getElementById('slide').src = images[i];
if (i < images.length - 1) { //CHECK IF INDEX IS UNDER MAX
i++; //ADD 1 TO INDEX
} else {
i = 0; //RESET BACK TO 0
}
setTimeout(changeImg, time); //RUN FUNCTION EVERY X SECONDS
}
window.onload = changeImg(); //RUN FUNCTION WHEN PAGE LOADS
}
}
});
});
1311.php
<div class="info_block">
<img id="slide" height="626px">
</div>
Path to PHP file:
document.getElementById('slide').src = "/"+images[i];
answer by Shringiraj Dewangan

Append footer only once within a callback

My code is a bit complex as I'm appending dynamic content to a cart following a successful AJAX call. I need to add the footer ($(.mini-cart__footer)) to the cart only once at the end of the li items. How do I achieve that? The problem I'm currently facing that every time a li is added, a footer section is attached to it - so if 3 products are added to the cart, I'll end up with 3 footer sections.
Here is my code:
var __isp_options = {
isp_add_to_cart_callback: function(product_id) {
var image = ISP_PRODUCTS[product_id].image.replace('?c=2', '');
var title = ISP_PRODUCTS[product_id].l;
var description = ISP_PRODUCTS[product_id].d;
var price = ISP_PRODUCTS[product_id].p;
isp_add_to_cart(event, product_id);
var miniCart_html = '<div class="mini-cart__full is-mini-cart"><ul class="mini-cart__items is-cart__items"><li class="mini-cart__item"><div class="mini-cart__image-container"><svg class="icon icon-close"><use xlink:href="#icon-close"></use></svg><img class="mini-cart__image" src="'+image+'"></div><div class="product-meta"><span class="cart-item__brand">'+title+'</span><h2 class="product-meta__title">'+'1 X '+'<span class="product-meta__title cart-item__title product-tag">'+description+'<span class="dot"></span><span class="dot"></span></span></h2><span class="product-meta__price" data-money-convertible="">'+Shopify.formatMoney(price)+'</span></div></li></ul></div>';
$('.mini-cart__content').append(miniCart_html);
$('.is-cart__items').append('<footer class="mini-cart__footer"><div class="mini-cart__total"><span class="mini-cart__total-label">'+'Total'+'</span><span class="mini-cart__total-price" data-money-convertible="">'+Shopify.formatMoney(price)+'</span></div><form action="/cart" method="POST">'+'Continue to checkout'+'</form></footer>')
}
}
function isp_add_to_cart(event, product_id) {
$.ajax({
url: '/cart?view=mini-cart-content/add?id='+ product_id + "&quantity=1",
type: 'POST',
success: function(result) {
console.log('success');
$.getJSON('/cart.js').then(function(results) {
if (results['item_count'] > 0) {
$('.cart-icon-wrapper__count').text(results['item_count']);
$('.cart-icon-wrapper--has-items').show();
$('.cart-icon-wrapper--empty').hide();
}
});
},
error: function(result) { console.log('error'); }
});
event.preventDefault();
event.stopPropagation();
event.stopImmediatePropagation();
return false;
}

MVC 5 - Registering JavaScript events from partial view which uses BeginCollectionItem

I have a partial view which looks like this:
#model Whatever.Models.Jobs
#using (Html.BeginCollectionItem("JobRecords"))
{
<tr id="jobRow">
#Html.HiddenFor(m => m.Id)
<th width="40%">
#Html.EditorFor(m => m.Project, new { htmlAttributes = new { #class = "form-control", id = "project", list = "projectResults" } })
<datalist id="projectResults"></datalist>
#Html.ValidationMessageFor(m => m.Project, "", new { #class = "text-danger" })
</th>
</tr>
}
This is embedded in the parent view like:
#if (Model.JobRecords != null)
{
foreach (var item in Model.JobRecords)
{
Html.RenderPartial("_JobEditorRow", item);
}
}
It all works, but as you can see from the partial view I want to add a searchable box using data-list, so I add a method in my controller:
[HttpGet]
public JsonResult GetProjects(string query)
{
var list = unitOfWork.ProjectRepository.Get(c => c.Name.contains(query));
var serialized = list.Select(p => new { p.ProjectCode, p.Name});
return Json(serialized, JsonRequestBehavior.AllowGet);
}
And then add some javascript which uses AJAX to populate this data-list:
$(document).ready(function () {
var delay = 1000;
var globalTimeout = null;
function contractsCall() {
console.log("called");
$("#projectResults").empty();
$.ajax({
cache: false,
type: "GET",
contentType: "application/json;charset=utf-8",
url: "/MyController/GetProjects?query=" + $("#project").val()
})
.done(function (data) {
if (data[0] !== undefined) {
for (var i = 0; i < data.length; i++) {
$("#projectResults").append(
"<option value=" + data[i]["ProjectCode"] + ">" + data[i]["Name"] + " - " + data[i]["ProjectCode"] + "</option>"
);
}
} else {
$("#projectResults").empty();
}
});
}
$("#project").keyup(function (event) {
console.log("keyup");
if (globalTimeout !== null) {
clearTimeout(globalTimeout);
}
globalTimeout = setTimeout(function () {
globalTimeout = null;
contractsCall();
}, delay);
});
});
This javascript is included in the parent view which is also embedding the partial view. But I add a job record and type something in the input box, it doesn't do anything despite it having the id of project.
My question is, how can I register events that occur in partial views from a parent view; or if I could embed by javascript file in the partialview to fix this? And the more difficult question is, how can I prevent the duplication of ids when adding a job with BeginCollectionItem? Because adding multiple rows would add multiple project id input boxes.
Update
#Stephen helped me greatly to fix this issue, I removed the <datalist> tag from the partial view and placed it in the main view, and used class instead of id. Then I changed my JS to something like this:
$("body").on("keyup", ".projectField", function () {
var self = $(this);
if (globalTimeout !== null) {
clearTimeout(globalTimeout);
}
globalTimeout = setTimeout(function () {
globalTimeout = null;
contractsCall(self.val());
}, delay);
});
This way I can search using my AJAX call for $(this) input box. The other issue I had was seeing which input box was clicked so I can update some other things, for this I used:
document.querySelectorAll('input[list="projectResults"]').forEach(function (element) {
element.addEventListener('input', onInput);
});
Which calls:
function onInput(e) {
var input = e.target,
val = input.value;
list = input.getAttribute('list'),
options = document.getElementById(list).childNodes;
var row = $(this).closest("tr");
var p = row.find(".projDescription");
for (var i = 0; i < options.length; i++) {
if (options[i].value === val) {
$.ajax({
cache: false,
type: "GET",
contentType: "application/json;charset=utf-8",
url: "/ContractProject/GetProjects?query=" + val;
})
.done(function (data) {
if (data[0] !== undefined) {
console.log(data[0]["WorksDescription"]);
p.text(data[0]["WorksDescription"]);
}
});
break;
}
}
}
It's a little bit counter intuitive because I am making 2 AJAX calls but the second one isn't going to be heavy as it's asking for a specific element.

Seeing span tag when I want to be rendering the text within the span tag

I have some words on a page that display "present" or "absent" that a user can click to toggle between being present or absent.
When the word is set to "absent" I want that text to be red.
The word represents a bool and is updated on screen using the following code:
<script type="text/javascript">
absentText = $.trim('#MyApp.Resources.MyAppResource.Absent_Text').toLowerCase();
presentText = $.trim('#MyApp.Resources.MyAppResource.Present_Text').toLowerCase();
updateAttendanceUrl = '#Url.Action("UpdateAttendance", "Attendance")';
</script>
Where MyAppResource.Absent_Text = absent the page displays fine with the word, "absent" on the page.
When I change MyAppResource.Absent_Text to read "absent" my page literally displays <span style="color:red">absent</span>
Here is a sample of my view source:
<td><span style="color:red">absent</span></td>
So somehow my < and > symbols are getting taken away.
How can I change my code so that when the word on my screen is written as "absent" it is colored red?
Is there a simpler way to just color any text on the screen that matches "absent" red?
For reference, here is the rest of the javascript from my page:
var userId;
var attendanceDay;
var isPresent;
var updateAttendanceUrl;
var absentText;
var presentText;
var courseId;
$(document).ready(function (event) {
$('.attendance').live('click', function () {
userId = $(this).parents('tr').attr('id');
if (userId != '') {
attendanceDay = $(this).attr('id');
isPresent = $.trim($(this).find('span').text().toLowerCase());
courseId = $(this).parents('tbody').attr('id');
$(this).find('span').addClass('currentClass');
if (isPresent == absentText) {
UpdateAttendance(1);
} else {
UpdateAttendance(0);
}
} else {
event.preventDefault();
}
});
});
function UpdateAttendance(present) {
url = updateAttendanceUrl;
$.ajax({
type: "POST",
url: url,
data: "userId=" + userId + "&attendanceDay=" + attendanceDay + "&courseId=" + courseId + "&present=" + present,
success: function (data) {
if (isPresent == absentText) {
$('#' + userId).find('.currentClass').text(presentText).removeAttr('class');
} else {
$('#' + userId).find('.currentClass').text(absentText).removeAttr('class');
}
return true;
}
});
}
What your looking for is called unescape or htmldecode. There are various topics available on SO already. Here is one.

Categories

Resources