JQuery scroll action repeated the result - javascript

I have to load more products with an ajax call when the page reaches the end.
<script>
$(window).scroll(function() {
if ($(document).height() <= ($(window).height() + $(window).scrollTop())) {
var _token = '{{ csrf_token() }}';
var theurl = 'homePaginate';
console.log(skip_arr);
$.ajax({
type: 'post',
url: theurl,
data:{_token:_token,page:page,avoid:skip_arr},
dataType: 'json',
success: function (data) {
page+=1;
printProducts(data,false,true,true)
}
});
}
});
I use a function to loop over my product to print it, in ajax call I send the page number and some times i need to avoid some products to show
function printProducts(data,is_ad,get_void,is_animate) {
console.log(page);
for (i=0;i< data.length;i++){
var id = '#col'+columnIndex;
columnIndex++;
if (columnIndex == 6){
columnIndex = 1;
}
var stars = '';
for(star = 0 ;star < Math.floor(data[i]['rate']);star++){
stars += '<i class="fas fa-star"></i>';
}
var fraction = data[i]['rate']%1;
if (fraction > 0 ){
stars += '<i class="fas fa-star-half-alt"></i>';
for(star = 0 ;star < 4-data[i]['rate'];star++){
stars += '<i class="far fa-star"></i>';
}
}else{
for(star = 0 ;star < 5-data[i]['rate'];star++){
stars += '<i class="far fa-star"></i>';
}
}
var discount ='';
if (data[i]['runningDiscount']){
discount = '<span class="discount-tag">'+data[i]['discount']['valuePercentage']+'% Off</span>';
}
if(get_void){
skip_arr.push(data[i]['id']);
}
var isFavorite = data[i]['isFavourite']?'fas':'far';
var image = '{{ url('') }}'+'/'+data[i]["image"];
var url = '{{ url('product') }}'+'/'+data[i]["id"];
var quick_cart = '';
if (data[i]["quickCart"] === true){
quick_cart = 'class="quick-add" data-item-id="'+data[i]['item']["id"]+'"';
}else{
quick_cart = 'href="'+url+'"';
}
var ad = '';
if (is_ad) ad = ' <span class="ad">Ad</span>';
var animate = '';
if(is_animate){
animate = ' animated fadeInDown ';
}
var product = '<div class="col-xs-12 product'+animate+'" data-id="'+id+'">\n' +
' <div class="row product-body">\n' +ad+ // print ad tag
' <span class="actions">\n' +
' <a '+quick_cart+'>\n' +
' <img src="{{ asset("site_assets/img/cart.png") }}" class="product-cart">\n' +
' </a>\n' +
' <a>\n' +
' <i class="'+isFavorite+' fa-heart shoptizer-color" data-id="'+data[i]["id"]+'"></i>\n' +
' </a>\n' +
' </span>\n' +
' <span class="view-icon" data-id='+ data[i]["id"]+'>\n' +
' <img src="{{ asset("site_assets/img/eye.png") }}">\n' +
' </span>\n' +discount+
' <img class="img-fluid" src="'+image+'">\n' +
' '+
' </div>\n' +
' <div class="col-sm-12">\n' +
' <span>'+data[i]['name']+' </span>\n' +
' <h6 class="shoptizer-color price">'+data[i]['price']+' EGP</h6>\n' +
' </div>\n' +
' <div class="col-xs-12 p-rate">\n' +stars+'</div>\n' +
' </div>';
$(id).append(product);
}
}
So when I reach the end it works fine but while testing the client scrolled up and down, so I got a repeated product in two rows. Why is that and how can I prevent it?
I think the problem in $(window).scroll()!!

the problem was in my ajax call I update the page on the success function so if the user reached the bottom twice before the request respond it duplicate the printed data because it send the same page so same response.
so the solution for me was to update the page
$(window).scroll(function() {
if ($(document).height() <= ($(window).height() + $(window).scrollTop())) {
var _token = '{{ csrf_token() }}';
var theurl = 'homePaginate';
$.ajax({
type: 'post',
url: theurl,
data:{_token:_token,page:page,avoid:skip_arr},
dataType: 'json',
success: function (data) {
printProducts(data,false,true,true)
}
});
page+=1;
}
});

Related

How to use search box to filter posts from WordPress API?

I have been able to get a list of posts on a php web page (outside of WordPress). How can I use the search box to filter the existing results by blog title(search term).
Here is my search box
<div class="sbox">
<h4>Search blog by title</h4>
<div class="form-group ">
<input type="text" name="search_box" id="search_box" class="form-control" placeholder="Search by title, author or category" >
</div>
</div>
Here is my ajax attempt
$('#search_box').keyup(function(){
var text = $('#search_box').val();
var api_url_search = `http://example.com/wordpress/wp-json/wp/v2/posts?filter[s]=${text}`;
$.ajax({
url:api_url_search,
dataType: 'json',
success: function(response){
var len = response.length;
for(var i=0; i<len; i++){
var title = response[i].title.rendered;
var search_str =
'<li>'+
'<p>' + title + '</p>' +
'</li>'
;
$('#results').append(search_str);
}
}
});
});
It seems to be looping through every letter that is typed and returning all posts for each letter.
I found the answer. The WordPress api won't enable you to filter by title but you can filter by slug. So the user has to type the title with hyphens (e.g my-title)
//setup before functions
var typingTimer; //timer identifier
var doneTypingInterval = 5000; //time in ms (5 seconds)
//on keyup, start the countdown
$('#search_box').keyup(function(){
clearTimeout(typingTimer);
if ($('#search_box').val()) {
var text = $('#search_box').val();
typingTimer = setTimeout(doneTyping(text), doneTypingInterval)
}
});
//user is "finished typing," do something
function doneTyping (text) {
// var text = text;
var api_url_search = `http://examle.com/wordpress/wp-json/wp/v2/posts?slug=${text}`;
$.ajax({
url:api_url_search,
dataType: 'json',
success: function(response){
var len = response.length;
for(var i=0; i<len; i++){
var id = response[i].id;
var date = response[i].date_gmt;
var slug = response[i].slug;
var excerpt = response[i].excerpt.rendered;
var categories = response[i].categories;
var search_str =
'<td>'+
'<div class="card" style="width: 300px;">' +
'<div class="card-divider">' + (i+1) + ' ' + slug + '</div>' +
' <div class="card-section">' +
'<p>' + excerpt + '</p>' +
'<h4>' + date + '</h4>' +
'<h4>' + 'Category:' + categories + '</h4>' +
'<a href="http://example.com/api-posts.php?">'+
'<input type="button" value="read more">' + '</input>' +
' </a>' +
' </div>' +
'</div>'+
'</td>'
;
$('#results').empty().append(search_str); // empty previous results and append new results
}
}
});
};

Ajax function is not display xml data on some mobile browsers

I tried to view XML data in html. This project works fine on desktop browsers but does not work on some mobile browsers. I feel like the issue is obviously but I don't know what to do. Please help.
<div class="row" id="xmldata"></div>
$(document).ready(function() {
$.ajax({
type: "GET",
url: "data.xml",
dataType: "xml",
success: xmlParser2
});
});
function xmlParser2(xml) {
xml = $(xml).children();
let total = $(xml).children().length;
$(xml).children().each(function(idx, index, item) {
let tag = $(this).prop("tagName");
let nextIdx = idx + 1;
let prevIdx = idx - 1;
//to make cyclic
nextIdx = nextIdx == total ? 0 : nextIdx;
prevIdx = prevIdx == -1 ? (total - 1) : prevIdx;
let image = '<img style="background-image:url(' + $(this).find("image").text() + ')"' + '" />';
let image2 = '<div><img src="' + $(this).find("image").text() + '" width="100%" alt="' + '" />' + '</div>';
let head = '<div>' + $(this).find("head").text() + '</div>';
let html = `<div class="col-sm-4 random reveal" id="random">
<div class="thumbnail randomdiv3">
<a href="#${tag + idx}" id="openModalBtn">
<div>${image}</div>
<h5>${head}</h5>
</a>
</div>
</div>`;
$("#xmldata").append(html);
});
}

What can I do to avoid Syncronous AJAX Request

I have this Array
var testFlows = ["test1","test2","test3","test4","test5"];
I'm trying to get the inputs one by one and generating some html (the html generated doesn't really matter).
What matters is that I want to see this html panels by the order of the testFlows array. My code is completely random. If I refresh the page they are on different positions.
One solution would be to make a synchronous ajax but it's deprecated and bad, so what else can I do?
Code:
var testFlows = ["test1","test2","test3","test4","test5"];
$.each(testFlows, function (index, testFlow) {
//get the inputs
$.ajax({
url: '/flow/getInputs',
type: 'post',
data: {testCaseName: testFlow.testCase.name},
success: function (inputNames) {
testCaseAccordion = '<div class="panel panel-default"><div class="panel-heading"><h4 class="panel-title"><a class="collapseTitle" data-toggle="collapse" data-parent="#accordion" href="#collapse-' + testFlow.testCase.name + index + '">' + testFlow.testCase.name + '(' + testFlow.testCase.type.name + ') <span id="eyeIcon" class="fas fa-eye float-right"></span></a></h4></div>';
testCaseAccordion += '<div id="collapse-' + testFlow.testCase.name + index + '" class="panel-collapse collapse"><div id="panel-body-' + testFlow.testCase.name + index + '" class="panel-body"></div></div>';
$('#accordion').append(testCaseAccordion);
if (testFlow.params !== null) {
var inputs = testFlow.params.split(',');
for (var i = 0; i < inputs.length; i++) {
$('#panel-body-' + testFlow.testCase.name + index).append('<strong class="color-red">' + inputNames[i] + ': </strong>' + inputs[i] + '<br>');
}
}
else {
$('#panel-body-' + testFlow.testCase.name + index).append("This test case doesn't have any inputs");
}
}
});
});
You can use promises, for example, in your case:
var testFlows = ["test1","test2","test3","test4","test5"];
function success(testFlowAndInputNames, index) {
var testFlow = testFlowAndInputNames[0];
var inputNames = testFlowAndInputNames[1];
var testCaseAccordion = '<div class="panel panel-default"><div class="panel-heading"><h4 class="panel-title"><a class="collapseTitle" data-toggle="collapse" data-parent="#accordion" href="#collapse-' + testFlow.testCase.name + index + '">' + testFlow.testCase.name + '(' + testFlow.testCase.type.name + ') <span id="eyeIcon" class="fas fa-eye float-right"></span></a></h4></div>';
testCaseAccordion += '<div id="collapse-' + testFlow.testCase.name + index + '" class="panel-collapse collapse"><div id="panel-body-' + testFlow.testCase.name + index + '" class="panel-body"></div></div>';
$('#accordion').append(testCaseAccordion);
if (testFlow.params !== null) {
var inputs = testFlow.params.split(',');
for (var i = 0; i < inputs.length; i++) {
$('#panel-body-' + testFlow.testCase.name + index).append('<strong class="color-red">' + inputNames[i] + ': </strong>' + inputs[i] + '<br>');
}
}
else {
$('#panel-body-' + testFlow.testCase.name + index).append("This test case doesn't have any inputs");
}
}
var arrayOfPromises = testFlows.map(function (testFlow) {
return new Promise(function (resolve, reject) {
$.ajax({
url: '/flow/getInputs',
type: 'post',
data: {testCaseName: testFlow.testCase.name},
success: resolve
});
})
.then(function(inputNames) {
return [testFlow, inputNames];
})
});
Promise.all(arrayOfPromises)
.then(function(results) {
results.forEach(success)
});
jQuery ajax returns a promise, so you could save all the promises into an array, eg:
var testFlows = ["test1", "test2", "test3", "test4", "test5"];
var testFlowsPromises = $.map(testFlows, function(testFlow, index) {
//get the inputs
return $.ajax({
url: '/flow/getInputs',
type: 'post',
data: {testCaseName: testFlow.testCase.name}
}).then(function(inputNames) {
return {
inputNames: inputNames,
testFlow: testFlow
};
});
});
Then, wait until all of them are done:
$.when.apply($, testFlowsPromises).done(function() {
$.each(arguments, function(index, data) {
// do stuff with index, data.inputNames, data.testFlow
});
});
Now you'd have an array of ajax data in the same order.
DEMO:
https://jsbin.com/fixuxezale/edit?js,console

Only able to display first item of database

I am trying to display items from my database. There are 6 items in it. However, it was only able to display the first item. But they are able to display all the 6 buttons. I have also attached a picture at the end to show how my page looks like currently. Is there any way to solve this problem? I want my item image, description and price to appear and followed by the button next. But as of now, its showing the first item and the 6 buttons.
Javascript
$(document).ready(function () {
showlist();
});
function showlist(userid) {
var url = serverURL() + "/listitems.php";
categorynameID = decodeURIComponent(getUrlVars()["categoryID"]);
var JSONObject = {
"categoryID": decodeURIComponent(getUrlVars()["categoryID"])
};
$.ajax({
url: url,
type: 'GET',
data: JSONObject,
dataType: 'json',
contentType: "application/json; charset=utf-8",
success: function (arr) {
_showitemResult(arr);
},
error: function () {
validationMsg();
}
});
}
function _showitemResult(arr) {
for (var i = 0; i < arr.length; i++) {
$("#lblimagefile").attr("src", serverURL() + "/images/" + arr[i].imagefile); //display profile image
$("#lblitemName").html(arr[i].itemName); //display item name
$("#lblprice").html(arr[i].price); //display price
htmlstring = "<a href='#' class='ui-btn' id='btn" + arr[i].itemID + "'>View Item</a>"; //add a new [Category] button
$("#result").append(htmlstring);
$("#btn" + arr[i].itemID).bind("click", { id: arr[i].itemID }, function (event) {
var data = event.data;
showitem(data.id);
});
}
}
function showitem(itemID) {
//alert(categoryID);
window.location = "showitem.html?itemID=" + itemID;
}
HTML
<div role="main" class="ui-content" id="main-ui">
<img id="lblimagefile" height="100">
<div id="lblitemName"></div>
<div id="lblprice"></div>
<div id="result"></div>
</div>
Add to htmlstring price, image and name template. htmlstring is your template for every post.
HTML:
<div role="main" class="ui-content" id="main-ui">
<div id="result"></div>
</div>
jQuery:
htmlstring = "<img src='" + serverURL() + "/images/" + arr[i].imagefile + "' height='100'><div>" + arr[i].itemName + "</div><div>" + arr[i].price + "</div><a href='#' class='ui-btn' id='btn" + arr[i].itemID + "'>View Item</a>"; //add a new [Category] button
$("#result").append(htmlstring);

.empty() function won't work after loading contents with ajax

I did a multilevel ajax call .i.e. make an ajax call and use the id value from the call to make another call... I tried calling a jquery .empty() isn't working for the data generated in the inner ajax call... But when i place the .empty() function on the outer generated element, it worked just fine... How can i fix this issue? This is my code../
$(document).on('click', '.stories', function(e) {
e.preventDefault();
var request = $.ajax({ //first ajax call///
url: 'includes/functions.php?job=front_title',
cache: false,
dataType: 'json',
contentType: 'application/json; charset=utf-8',
type: 'get'
});
request.done(function(output) {
if (output.result === 'success') {
$('.blog').empty();
var jsonArray = $(jQuery.parseJSON(JSON.stringify(output.data))).each(function() {
var id = this.titleID;
var storyTitle = this.story_view;
var frontTitle = '<div class="blog-item"><h3>' + storyTitle + '</h3>' + '<img class="img-responsive img-story" src="images/blog/blog1.jpg" width="100%" alt="" />' + '<div class="blog-content"><div class="entry-meta"><h4>Episodes</h4></div>' + '<div class="well" style="padding-right: 10px; padding-left: 5px; width: 105%;">' + '<ul class="tag-cloud stories">';
var request2 = $.ajax({ ////inner ajax call//////
url: 'includes/functions.php?job=story_episodes',
cache: false,
data: 'id=' + id,
dataType: 'json',
contentType: 'application/json; charset=utf-8',
type: 'get'
});
request2.done(function(output2) {
var i = 1;
if (output2.result === 'success') {
var jsonArray2 = $(jQuery.parseJSON(JSON.stringify(output2.data))).each(function() {
var id2 = this.id;
var title = this.title;
var count = this.episode_count;
if (count == 0) {
frontTitle += id2;
} else if (i % 20 == 0) {
frontTitle += '<li data-id="' + id2 + '" id="singleEpisode"><a class="btn btn-sm btn-primary" href="#story/' + storyTitle + '/' + title + '">' + i + '</a></li></ul><ul class="tag-cloud">';
} else {
frontTitle += '<li style="margin: 1px" data-id="' + id2 + '" id="singleEpisode"><a class="btn btn-sm btn-primary" href="#story/' + storyTitle + '/' + title + '">' + i + '</a></li>';
}
i += 1;
})
}
$('.blog').append(frontTitle);
frontTitle += '</ul></div></div>';
})
})
} else {
console.log('failed');
}
});
});
I really need help for this, i av been on this for two days now... I would really appreciate the help.. or is there a better way i could do this?

Categories