Check if a dynamically url exists within an ajax function - javascript

I am using a script that auto loads blog posts on scroll by parsing the posts from the "blogurl.com/page/#" urls that the pages are set to.
I am working with a test blog and currently I have 2 pages of test posts.
When I scroll down to a point the posts from page 2 load and parse to the container. I don't have any posts on page 3, so page 3 doesn't exist (i.e. blogurl.com/page/3 is not a real url). This script however only checks if there are posts on a url, not if the url itself actually exists.
(function($) {
$.fn.swoosh = function(loadingImgUrl, callback) {
if (!loadingImgUrl) {
loadingImgUrl = "Loading...";
}
if (callback == null) {
callback = -1;
}
var postList = this;
var turnOff = false;
var pageNumber = 2;
var urlArray = window.location.href.toString().split("/");
var blogUrl = urlArray[0] + "//" + urlArray[2] + "/" + urlArray[3] + "/";
var baseUrl = blogUrl + "page/";
var postUrl = "";
var processing = false;
//insert the loading bar at the end of the posts-list
if (loadingImgUrl != "Loading...") {
postList.parent().append('<div class="loading"><img src="' + loadingImgUrl + '"></div>');
} else {
postList.parent().append('<div class="loading">' + loadingImgUrl + '</div>');
}
$(".loading").hide(); //make sure loading bar is hidden
$(document).scroll(function() {
//kick out of function if it's already running, if it has been shut off, or if there is no 2nd page
if (processing || turnOff || pageNumber == 0) {
return false;
}
//when scrolling gets to the footer, start chugging!
if ($(window).scrollTop() >= $(document).height() - $(window).height() - $(".blog_footer").height() - 150) {
processing = true;
//currently processessing, so don't call function again until done
$(".loading").fadeIn(200); //fade in loading bar
postUrl = baseUrl + pageNumber; //calculate the page to load
//AJAX CALL
$.get(postUrl, function(data) {
//grab only post items from the loaded page
var posts = $(data).find(".col-item");
//check that the loaded page has content
if (posts.length > 0) {
console.log(loadingImgUrl);
//fade out the loading bar, then attach the new items to the end of the list
$(".loading").fadeOut(200, function() {
posts.appendTo(".blog-listing .container-wrap");
});
pageNumber++; //increment the page to load.
$(".next-posts-link").attr("href", baseUrl + pageNumber);
}
//if the loaded page doesn't have content, it means we have reached the end.
else {
turnOff = true;
$(".next-posts-link").after('<div class="next-posts-link unactive">Next</div>');
$(".next-posts-link:not(.unactive)").remove();
$(".loading").fadeOut(200);
}
processing = false; //we are done processing, so set up for the next time
setTimeout(function() {
twttr.widgets.load();
IN.parse();
FB.XFBML.parse();
gapi.plusone.go();
}, 350);
});
}
});
};
})(jQuery);
This is a pretty clunky script as is. At the moment when it attempts to load in a page that doesn't exist the console receives a 404 on the url, and the "loading..." text stays at the bottom of the page. The couple of things I have tried don't work. any suggestions?
Edit** I think that the obvious place to check if the url exists would be at:
pageNumber++; //increment the page to load.
$(".next-posts-link").attr("href", baseUrl + pageNumber);
because this is where pageNumber is increased and then passed back to postUrl:
postUrl = baseUrl + pageNumber; //calculate the page to load
//AJAX CALL
$.get(postUrl, function(data) {
Not sure if I am on track on this or not though.
Edit*** figured the live link may be helpful:
http://blog.bbjlinen.com/test-blog

Have you tried adding the fail handler:
https://api.jquery.com/jquery.get/
$.get(postUrl, function(data){
...
...
}).fail(function(){
//whatever you need to do here
});
This should trigger if the request returns a 404
You could also use this to check the status of the request:
.fail(function(response){
if(response.status == 404){
...
}
}

Related

infinite scroll on squarespace get category filter

I am using this code to infinite load a page on squarespace. My problem is the reloading doesn't capture the filtering that I have set up in my url. It cannot seem to 'see' the variables or even the url or categoryFilter in my collection. I've tried to use a .var directive but the lazy loaded items cannot see the scope of things defined before it. I'm running out of ideas here please help!
edit: I've since found the answer but gained another question.
I was able to use window.location.href instead of window.location.pathname to eventually get the parameters that way. Except this doesn't work in IE11 so now I have to search for this.
<script>
function infiniteScroll(parent, post) {
// Set some variables. We'll use all these later.
var postIndex = 1,
execute = true,
stuffBottom = Y.one(parent).get('clientHeight') + Y.one(parent).getY(),
urlQuery = window.location.pathname,
postNumber = Static.SQUARESPACE_CONTEXT.collection.itemCount,
presentNumber = Y.all(post).size();
Y.on('scroll', function() {
if (presentNumber >= postNumber && execute === true) {
Y.one(parent).append('<h1>There are no more posts.</h1>')
execute = false;
} else {
// A few more variables.
var spaceHeight = document.documentElement.clientHeight + window.scrollY,
next = false;
/*
This if statement measures if the distance from
the top of the page to the bottom of the content
is less than the scrollY position. If it is,
it's sets next to true.
*/
if (stuffBottom < spaceHeight && execute === true) {
next = true;
}
if (next === true) {
/*
Immediately set execute back to false.
This prevents the scroll listener from
firing too often.
*/
execute = false;
// Increment the post index.
postIndex++;
// Make the Ajax request.
Y.io(urlQuery + '?page=' + postIndex, {
on: {
success: function (x, o) {
try {
d = Y.DOM.create(o.responseText);
} catch (e) {
console.log("JSON Parse failed!");
return;
}
// Append the contents of the next page to this page.
Y.one(parent).append(Y.Selector.query(parent, d, true).innerHTML);
// Reset some variables.
stuffBottom = Y.one(parent).get('clientHeight') + Y.one(parent).getY();
presentNumber = Y.all(post).size();
execute = true;
}
}
});
}
}
});
}
// Call the function on domready.
Y.use('node', function() {
Y.on('domready', function() {
infiniteScroll('#content','.lazy-post');
});
});
</script>
I was able to get this script working the way I wanted.
I thought I could use:
Static.SQUARESPACE_CONTEXT.collection.itemCount
to get {collection.categoryFilter} like with jsont, like this:
Static.SQUARESPACE_CONTEXT.collection.categoryFilter
or this:
Static.SQUARESPACE_CONTEXT.categoryFilter
It didn't work so I instead changed
urlQuery = window.location.pathname
to
urlQuery = window.location.href
which gave me the parameters I needed.
The IE11 problem I encountered was this script uses
window.scrollY
I changed it to the ie11 compatible
Window.pageYOffset
and we were good to go!

How to Change the Domain URL of website and sub-links of the website using single code?

I want to add a string to the main domain, and also to the sub links of the website.
I tried the below code but main domain is not getting changed, I want to change main domain first and after reload of the website all the sub links should change.
if (typeof this.href != "undefined") {
web = this.href.toString().toLowerCase();
}
else{
web = document.location.toString().toLowerCase();
}
function urlAddress() {
confirm('Would you like to clear the cache.......... of '+ web + '- Ninja :)');
//window.location.replace(web + "/?NoCDN=123");
var stateObj = web;
if (window.history.state) {
history.pushState(stateObj, "page 1", "/?NoCDN=123");
}
}
/*Second Function
This code is changing all URL of the website...*/
function linkAddress() {
$('a[href]').each(function(){
var link = this.href;
$(this).attr('href',link + '?NoCDN=123');
});
$('script[src]').each(function(){
var link = this.href;
$(this).attr('src',link + '?NoCDN=123');
});
$('link[href]').each(function(){
var link = this.href;
$(this).attr('href',link + '?NoCDN=123');
});
$('img[src]').each(function(){
var link = this.src;
$(this).attr('src',link + '?NoCDN=123');
});
}
//I am calling both functions here ...
$( document ).ready(function() {
urlAddress();
setTimeout(function(){
alert("It's Almost clear. Just click Ok for more result.");
linkAddress();
}, 3000);
});

jQuery infinite scroll firing multiple ajax requests

I added some infinite scrolling from this tutorial and i've been stuck on ajax request. it's always requesting multiple times.
and this is my code :
$(document).ready(function() {
var win = $(window);
var page = 1;
var req = null;
win.scroll(function() {
if ($(document).height() - win.height() == win.scrollTop()) {
if (req != null) {
req.abort();
}
req = $.ajax({
url: "/member/member_c/generate_data",
type: "POST",
data: {
"page": page
},
dataType: "text",
success: function(msg) {
var obj = jQuery.parseJSON(msg);
if (obj.result) {
$('#contentz').append(obj.data);
console.log(JSON.stringify('page ' + obj.page + ' : ' + jQuery.inArray(page,done)));
page = page + 1;
req = null;
}
},
});
}
});
});
i've been wondering, what is 'VM' at my console and why is what always firing a 'wrong' request?
Thanks
It appears that you're including two copies of your code somehow, since one call comes from your member_c.js file and the copies come from VM22* sources. You should show us your entire source code for the page with this problem, not just this single snippet.

Load download in browser background, tell when finished

I'm trying to get a file which takes a good few seconds to load in the background, so I can display a spinner at the same time.
I'm currently trying with an iframe in the background, and this works but I'm not sure how I can be notified when it's finished loading (so I can remove the spinner).
Any good ways of doing this? Any better solution than an iframe?
Here's my code so far:
<script>
$(document).ready(function() {
var link = $('.generate-pdf');
link.click(function(e) {
e.preventDefault();
var spinner = $("<img src='/assets/images/ajax-loader.gif' />");
var iframe = $('<iframe src="' + link.attr('href') + '" style="height:0;width:0;visibility;hidden;display:none;"></iframe>');
link.before(spinner);
link.before(iframe);
});
})
</script>
According to this site, given that my Content-disposition is attachment I can't guarantee to receive any events. Can I poll any properties on the iframe to find out?
Have you tried
iframe.load(function(){
log("done");
})
In the end, I had to do this by contacting the server, and seeing if the file had been sent to the browser. I'd still like to see a pure client-based implementation.
Thankfully the download was generated with PHP so this was ok.
<script>
$(document).ready(function() {
var link = $('.generate-pdf');
link.click(function(e) {
e.preventDefault();
var spinner = $("<div class='spinner'><img src='/assets/images/ajax-loader.gif' /><span>Your PDF is being generated...</span></div>");
var downloadKey = new Date().getTime();
var iframe = $('<iframe src="' + link.attr('href') + '&downloadKey='+downloadKey+'" style="height:0;width:0;visibility;hidden;display:none;" onload="alert(\'hello\')"></iframe>');
link.before(spinner);
link.before(iframe);
var hasFinished = function(downloadKey, callback) {
var that = this;
$.ajax({
url: "index.php?controller=is-download-finished&downloadKey=" + downloadKey,
success: function(data) {
if (data) {
callback();
} else {
setTimeout(function() {
that(downloadKey, callback);
}, 1000);
}
}
})
};
hasFinished(downloadKey, function() {
spinner.remove();
iframe.remove();
});
});
})
</script>
The extra request just returns JSON true or false.

Override "Error Loading Page" for network failure in js file

I have JQuery Mobile-1.0.js file.
// Load a page into the DOM.
$.mobile.loadPage = function (url, options) {
// This function uses deferred notifications to let callers
// know when the page is done loading, or if an error has occurred.
var deferred = $.Deferred(),
// The default loadPage options with overrides specified by
// the caller.
settings = $.extend({}, $.mobile.loadPage.defaults, options),
// The DOM element for the page after it has been loaded.
page = null,
// If the reloadPage option is true, and the page is already
// in the DOM, dupCachedPage will be set to the page element
// so that it can be removed after the new version of the
// page is loaded off the network.
dupCachedPage = null,
// determine the current base url
findBaseWithDefault = function () {
var closestBase = ($.mobile.activePage && getClosestBaseUrl($.mobile.activePage));
return closestBase || documentBase.hrefNoHash;
},
// The absolute version of the URL passed into the function. This
// version of the URL may contain dialog/subpage params in it.
absUrl = path.makeUrlAbsolute(url, findBaseWithDefault());
// If the caller provided data, and we're using "get" request,
// append the data to the URL.
if (settings.data && settings.type === "get") {
absUrl = path.addSearchParams(absUrl, settings.data);
settings.data = undefined;
}
// If the caller is using a "post" request, reloadPage must be true
if (settings.data && settings.type === "post") {
settings.reloadPage = true;
}
// The absolute version of the URL minus any dialog/subpage params.
// In otherwords the real URL of the page to be loaded.
var fileUrl = path.getFilePath(absUrl),
// The version of the Url actually stored in the data-url attribute of
// the page. For embedded pages, it is just the id of the page. For pages
// within the same domain as the document base, it is the site relative
// path. For cross-domain pages (Phone Gap only) the entire absolute Url
// used to load the page.
dataUrl = path.convertUrlToDataUrl(absUrl);
// Make sure we have a pageContainer to work with.
settings.pageContainer = settings.pageContainer || $.mobile.pageContainer;
// Check to see if the page already exists in the DOM.
page = settings.pageContainer.children(":jqmData(url='" + dataUrl + "')");
// If we failed to find the page, check to see if the url is a
// reference to an embedded page. If so, it may have been dynamically
// injected by a developer, in which case it would be lacking a data-url
// attribute and in need of enhancement.
if (page.length === 0 && dataUrl && !path.isPath(dataUrl)) {
page = settings.pageContainer.children("#" + dataUrl)
.attr("data-" + $.mobile.ns + "url", dataUrl);
}
// If we failed to find a page in the DOM, check the URL to see if it
// refers to the first page in the application. If it isn't a reference
// to the first page and refers to non-existent embedded page, error out.
if (page.length === 0) {
if ($.mobile.firstPage && path.isFirstPageUrl(fileUrl)) {
// Check to make sure our cached-first-page is actually
// in the DOM. Some user deployed apps are pruning the first
// page from the DOM for various reasons, we check for this
// case here because we don't want a first-page with an id
// falling through to the non-existent embedded page error
// case. If the first-page is not in the DOM, then we let
// things fall through to the ajax loading code below so
// that it gets reloaded.
if ($.mobile.firstPage.parent().length) {
page = $($.mobile.firstPage);
}
} else if (path.isEmbeddedPage(fileUrl)) {
deferred.reject(absUrl, options);
return deferred.promise();
}
}
// Reset base to the default document base.
if (base) {
base.reset();
}
// If the page we are interested in is already in the DOM,
// and the caller did not indicate that we should force a
// reload of the file, we are done. Otherwise, track the
// existing page as a duplicated.
if (page.length) {
if (!settings.reloadPage) {
enhancePage(page, settings.role);
deferred.resolve(absUrl, options, page);
return deferred.promise();
}
dupCachedPage = page;
}
var mpc = settings.pageContainer,
pblEvent = new $.Event("pagebeforeload"),
triggerData = { url: url, absUrl: absUrl, dataUrl: dataUrl, deferred: deferred, options: settings };
// Let listeners know we're about to load a page.
mpc.trigger(pblEvent, triggerData);
// If the default behavior is prevented, stop here!
if (pblEvent.isDefaultPrevented()) {
return deferred.promise();
}
if (settings.showLoadMsg) {
// This configurable timeout allows cached pages a brief delay to load without showing a message
var loadMsgDelay = setTimeout(function () {
$.mobile.showPageLoadingMsg();
}, settings.loadMsgDelay),
// Shared logic for clearing timeout and removing message.
hideMsg = function () {
// Stop message show timer
clearTimeout(loadMsgDelay);
// Hide loading message
$.mobile.hidePageLoadingMsg();
};
}
if (!($.mobile.allowCrossDomainPages || path.isSameDomain(documentUrl, absUrl))) {
deferred.reject(absUrl, options);
} else {
// Load the new page.
$.ajax({
url: fileUrl,
type: settings.type,
data: settings.data,
dataType: "html",
success: function (html, textStatus, xhr) {
//pre-parse html to check for a data-url,
//use it as the new fileUrl, base path, etc
var all = $("<div></div>"),
//page title regexp
newPageTitle = html.match(/<title[^>]*>([^<]*)/) && RegExp.$1,
// TODO handle dialogs again
pageElemRegex = new RegExp("(<[^>]+\\bdata-" + $.mobile.ns + "role=[\"']?page[\"']?[^>]*>)"),
dataUrlRegex = new RegExp("\\bdata-" + $.mobile.ns + "url=[\"']?([^\"'>]*)[\"']?");
// data-url must be provided for the base tag so resource requests can be directed to the
// correct url. loading into a temprorary element makes these requests immediately
if (pageElemRegex.test(html)
&& RegExp.$1
&& dataUrlRegex.test(RegExp.$1)
&& RegExp.$1) {
url = fileUrl = path.getFilePath(RegExp.$1);
}
if (base) {
base.set(fileUrl);
}
//workaround to allow scripts to execute when included in page divs
all.get(0).innerHTML = html;
page = all.find(":jqmData(role='page'), :jqmData(role='dialog')").first();
//if page elem couldn't be found, create one and insert the body element's contents
if (!page.length) {
page = $("<div data-" + $.mobile.ns + "role='page'>" + html.split(/<\/?body[^>]*>/gmi)[1] + "</div>");
}
if (newPageTitle && !page.jqmData("title")) {
if (~newPageTitle.indexOf("&")) {
newPageTitle = $("<div>" + newPageTitle + "</div>").text();
}
page.jqmData("title", newPageTitle);
}
//rewrite src and href attrs to use a base url
if (!$.support.dynamicBaseTag) {
var newPath = path.get(fileUrl);
page.find("[src], link[href], a[rel='external'], :jqmData(ajax='false'), a[target]").each(function () {
var thisAttr = $(this).is('[href]') ? 'href' :
$(this).is('[src]') ? 'src' : 'action',
thisUrl = $(this).attr(thisAttr);
// XXX_jblas: We need to fix this so that it removes the document
// base URL, and then prepends with the new page URL.
//if full path exists and is same, chop it - helps IE out
thisUrl = thisUrl.replace(location.protocol + '//' + location.host + location.pathname, '');
if (!/^(\w+:|#|\/)/.test(thisUrl)) {
$(this).attr(thisAttr, newPath + thisUrl);
}
});
}
//append to page and enhance
// TODO taging a page with external to make sure that embedded pages aren't removed
// by the various page handling code is bad. Having page handling code in many
// places is bad. Solutions post 1.0
page
.attr("data-" + $.mobile.ns + "url", path.convertUrlToDataUrl(fileUrl))
.attr("data-" + $.mobile.ns + "external-page", true)
.appendTo(settings.pageContainer);
// wait for page creation to leverage options defined on widget
page.one('pagecreate', $.mobile._bindPageRemove);
enhancePage(page, settings.role);
// Enhancing the page may result in new dialogs/sub pages being inserted
// into the DOM. If the original absUrl refers to a sub-page, that is the
// real page we are interested in.
if (absUrl.indexOf("&" + $.mobile.subPageUrlKey) > -1) {
page = settings.pageContainer.children(":jqmData(url='" + dataUrl + "')");
}
//bind pageHide to removePage after it's hidden, if the page options specify to do so
// Remove loading message.
if (settings.showLoadMsg) {
hideMsg();
}
// Add the page reference and xhr to our triggerData.
triggerData.xhr = xhr;
triggerData.textStatus = textStatus;
triggerData.page = page;
// Let listeners know the page loaded successfully.
settings.pageContainer.trigger("pageload", triggerData);
deferred.resolve(absUrl, options, page, dupCachedPage);
},
error: function (xhr, textStatus, errorThrown) {
//set base back to current path
if (base) {
base.set(path.get());
}
// Add error info to our triggerData.
triggerData.xhr = xhr;
triggerData.textStatus = textStatus;
triggerData.errorThrown = errorThrown;
var plfEvent = new $.Event("pageloadfailed");
// Let listeners know the page load failed.
settings.pageContainer.trigger(plfEvent, triggerData);
// If the default behavior is prevented, stop here!
// Note that it is the responsibility of the listener/handler
// that called preventDefault(), to resolve/reject the
// deferred object within the triggerData.
if (plfEvent.isDefaultPrevented()) {
return;
}
// Remove loading message.
if (settings.showLoadMsg) {
// Remove loading message.
hideMsg();
//show error message
$("<div class='ui-loader ui-overlay-shadow ui-body-e ui-corner-all'><h1>" + $.mobile.pageLoadErrorMessage + "</h1></div>")
.css({ "display": "block", "opacity": 0.96, "top": $window.scrollTop() + 100 })
.appendTo(settings.pageContainer)
.delay(800)
.fadeOut(400, function () {
$(this).remove();
});
}
deferred.reject(absUrl, options);
}
});
}
return deferred.promise();
};
This is the code for showing an error message "Error Loading Page" for error in page. Here i want to show alert message for net connection failure as "Please check your net connection" instead of the below image.
Note: I dont want to change the pageloaderrormessage. want to stop to get the page error messages, instead of that i will enable my network error condition as in Show Network Error in android. If the user pressed "Ok" in alert dialog i'll navigate them into Reload.html.
Please tell me where i can check that condition and where i have to change the error message?
As both #shkschneider and #codemonkey have suggested you need to set this option on mobileinit
Example:
$(document).bind("mobileinit", function(){
$.mobile.pageLoadErrorMessage = "Please check your net connection";
});
Linking the jQM 1.0.1 docs:
http://jquerymobile.com/demos/1.0.1/docs/api/globalconfig.html
Here is a example:
http://jquerymobile.com/demos/1.0.1/docs/config/pageLoadErrorMessage.html ( click the "or Try this broken link" button )
Now if you have the ability to upgrade jQM to 1.1.1 you might try something like this:
//use theme swatch "b", a custom message, and no spinner
$.mobile.showPageLoadingMsg("b", "Please check your net connection", true);
// hide after delay
setTimeout( $.mobile.hidePageLoadingMsg, 1500 );
Docs:
http://jquerymobile.com/demos/1.1.1/docs/api/methods.html
UPDATE:
Another thought is to use a plugin to achieve something like you want, Does something like this work?
http://dev.jtsage.com/jQM-SimpleDialog/demos/bool.html
Simply use:
$(document).bind("mobileinit", function(){
$.mobile.pageLoadErrorMessage("Please check your netconnection");
});
http://jquerymobile.com/test/docs/api/globalconfig.html
Set the pageLoadErrorMessage as described here http://jquerymobile.com/demos/1.1.1/docs/api/globalconfig.html
EDIT
If you want to handle the behaviour in a custom way, set loadingMessage to false. This prevents the loading message from being displayed. You can bind to the pageloadfailed (described here http://jquerymobile.com/demos/1.1.1/docs/api/events.html) and add add your custom handling logic in the event handler.

Categories

Resources