I would like to run some jQuery code once another jQuery function named loadItems has completed. The loadItems function is from the IAS jQuery plugin https://github.com/webcreate/infinite-ajax-scroll
How can I do this using jQuery
The loadItems function is:
/**
* Loads items from certain url, triggers
* onComplete handler when finished
*
* #param string the url to load
* #param function the callback function
* #param int minimal time the loading should take, defaults to $.ias.default.loaderDelay
* #return void
*/
function loadItems(url, onCompleteHandler, delay)
{
var items = [],
container,
startTime = Date.now(),
diffTime,
self;
delay = delay || opts.loaderDelay;
$.get(url, null, function (data) {
// walk through the items on the next page
// and add them to the items array
container = $(opts.container, data).eq(0);
if (0 === container.length) {
// incase the element is a root element (body > element),
// try to filter it
container = $(data).filter(opts.container).eq(0);
}
if (container) {
container.find(opts.item).each(function () {
items.push(this);
});
}
if (onCompleteHandler) {
self = this;
diffTime = Date.now() - startTime;
if (diffTime < delay) {
setTimeout(function () {
onCompleteHandler.call(self, data, items);
}, delay - diffTime);
} else {
onCompleteHandler.call(self, data, items);
}
}
}, 'html');
}
And it is being called in the HTML with:
<script type="text/javascript">
jQuery.ias({
container : '.category-products',
item: '.products-grid',
pagination: '.toolbar-bottom',
next: '.next',
loader: '<img src="http://example.com/skin/frontend/bootstrapped/default/images/ajax-loader.gif" /> Loading more products, please be patient...',
onPageChange: function(pageNum, pageUrl, scrollOffset) {
// This will track a pageview every time the user scrolls up or down the screen to a different page.
path = jQuery('<a/>').attr('href',pageUrl)[0].pathname.replace(/^[^\/]/,'/');
_gaq.push(['_trackPageview', path]);
},
triggerPageTreshold: 100,
thresholdMargin: 700,
trigger: 'Load more items',
history: true,
onLoadItems: function(items) {
jQuery.each(items, function(i, ul){
jQuery(ul).find('select.qtychange').customSelect()
});
}
});
jQuery(document).ready(function() {
jQuery().UItoTop({ easingType: 'easeOutQuart' });
});
</script>
The function already provides callback functionality; simply provide an anonymous function in the onCompleteHandler parameter when you call the loadItems function. Something like this:
loadItems('/foo.php', function(data, items) {
console.log('loading complete');
console.log(data);
console.log(items);
});
Got it working in the end by adding an onRenderComplete to the plugins options as below.
<script type="text/javascript">
jQuery.ias({
container : '.category-products',
item: '.products-grid',
pagination: '.toolbar-bottom',
next: '.next',
loader: '<img src="http://example.com/skin/frontend/default/default/images/ajax-loader.gif" /> Loading more products, please be patient...',
onPageChange: function(pageNum, pageUrl, scrollOffset) {
// This will track a pageview every time the user scrolls up or down the screen to a different page.
path = jQuery('<a/>').attr('href',pageUrl)[0].pathname.replace(/^[^\/]/,'/');
_gaq.push(['_trackPageview', path]);
},
triggerPageTreshold: 100,
thresholdMargin: 700,
trigger: 'Load more items',
history: true,
onLoadItems: function(items) {
jQuery.each(items, function(i, ul){
jQuery(ul).find('select.qtychange').customSelect()
});
},
onRenderComplete: function () {
console.log('it worked');
// added my code here
}
});
</script>
Strangely it is not mentioned in the plugins docs but I saw in the code and just gave it a shot.
Related
Im using django-el-pagination to do lazy loading of entries.
When I click on an entry and then use the browser back button, all of the lazy loading is gone, I tried to add window.history.pushState() but then I only get the current page i.e.?page=4 when I use the browser back button, and all of the entries on top is not loaded.
Is there any way to implement a correct history so that the user is back at the same place when they use the browser back button?
$.endlessPaginate({
paginateOnScroll: true,
paginateOnScrollMargin: 400,
paginateOnScrollChunkSize: 2,
onCompleted: function(context, fragment) {
window.history.pushState(null, null, context.url);
}
});
Edit 1
Here is the JavaScript for the .endlessPaginate function:
'use strict';
(function ($) {
// Fix JS String.trim() function is unavailable in IE<9 #45
if (typeof(String.prototype.trim) === "undefined") {
String.prototype.trim = function() {
return String(this).replace(/^\s+|\s+$/g, '');
};
}
$.fn.endlessPaginate = function(options) {
var defaults = {
// Twitter-style pagination container selector.
containerSelector: '.endless_container',
// Twitter-style pagination loading selector.
loadingSelector: '.endless_loading',
// Twitter-style pagination link selector.
moreSelector: 'a.endless_more',
// Digg-style pagination page template selector.
pageSelector: '.endless_page_template',
// Digg-style pagination link selector.
pagesSelector: 'a.endless_page_link',
// Callback called when the user clicks to get another page.
onClick: function() {},
// Callback called when the new page is correctly displayed.
onCompleted: function() {},
// Set this to true to use the paginate-on-scroll feature.
paginateOnScroll: false,
// If paginate-on-scroll is on, this margin will be used.
paginateOnScrollMargin : 1,
// If paginate-on-scroll is on, it is possible to define chunks.
paginateOnScrollChunkSize: 0
},
settings = $.extend(defaults, options);
var getContext = function(link) {
return {
key: link.attr('rel').split(' ')[0],
url: link.attr('href')
};
};
return this.each(function() {
var element = $(this),
loadedPages = 1;
// Twitter-style pagination.
element.on('click', settings.moreSelector, function() {
var link = $(this),
html_link = link.get(0),
container = link.closest(settings.containerSelector),
loading = container.find(settings.loadingSelector);
// Avoid multiple Ajax calls.
if (loading.is(':visible')) {
return false;
}
link.hide();
loading.show();
var context = getContext(link);
// Fire onClick callback.
if (settings.onClick.apply(html_link, [context]) !== false) {
var data = 'querystring_key=' + context.key;
// Send the Ajax request.
$.get(context.url, data, function(fragment) {
container.before(fragment);
container.remove();
// Increase the number of loaded pages.
loadedPages += 1;
// Fire onCompleted callback.
settings.onCompleted.apply(
html_link, [context, fragment.trim()]);
});
}
return false;
});
// On scroll pagination.
if (settings.paginateOnScroll) {
var win = $(window),
doc = $(document);
doc.scroll(function(){
if (doc.height() - win.height() -
win.scrollTop() <= settings.paginateOnScrollMargin) {
// Do not paginate on scroll if chunks are used and
// the current chunk is complete.
var chunckSize = settings.paginateOnScrollChunkSize;
if (!chunckSize || loadedPages % chunckSize) {
element.find(settings.moreSelector).click();
} else {
element.find(settings.moreSelector).addClass('endless_chunk_complete');
}
}
});
}
// Digg-style pagination.
element.on('click', settings.pagesSelector, function() {
var link = $(this),
html_link = link.get(0),
context = getContext(link);
// Fire onClick callback.
if (settings.onClick.apply(html_link, [context]) !== false) {
var page_template = link.closest(settings.pageSelector),
data = 'querystring_key=' + context.key;
// Send the Ajax request.
page_template.load(context.url, data, function(fragment) {
// Fire onCompleted callback.
settings.onCompleted.apply(
html_link, [context, fragment.trim()]);
});
}
return false;
});
});
};
$.endlessPaginate = function(options) {
return $('body').endlessPaginate(options);
};
})(jQuery);
short answer: no. The whole point of 'endless pagination' is to not reload a (new) page, therefore there is no history.
I have a custom plugin that was originally loading html content via ajax into the page by appending a hash marker and page ID to the URL.
I am very new to this level of complexity and would like to 'undo' this functionality, so the plugin can initialize without the Router function. I've been looking at this for a couple days and am pretty lost...
The entire plugin seems to be initialized by this function. Any tips or suggestions on how to turn 'off' this feature, so the code still initializes without appending the # to the URL would be greatly appreciated.
$(function() {
var connections = [],
IEversion = detectIE(),
killConnections = null,
node = null,
randomBehaviour,
rootIndex = 1,
silentRoute = null;
// Splash.
var splash = {
init: function() {
$('#splash').addClass('active');
$('.node.splash').draggable({
containment: 'parent',
drag: function() {
if(!splash.destroyed) {
$('.node.splash').addClass('dragging');
splash.destroy('drag');
splash.destroyed = true;
}
},
scroll: false,
disabled: false
});
setTimeout(function() {
if($('.arrow').is(':visible')) {
splash.destroy();
}
}, 4000);
},
destroy: function(event) {
if(event === 'drag') {
$('.arrow').hide();
} else {
$('.arrow').fadeOut(500);
}
$('#splash-wrapper p, .node.splash').fadeOut(500);
setTimeout(function() {
$('#splash').remove();
nody.init();
}, 500);
},
destroyed: false
};
// Router.
var routes = {
'/': function() {
if(!splash.destroyed) {
splash.init();
}else {
nody.unloadMenu();
}
}
};
var router = Router(routes);
router.configure({
strict: false,
before: function() {
if(silentRoute) {
silentRoute = false;
return false;
}
}
}).init('/');
});
An easy answer-
$.mobile.ajaxEnabled = false;
Using jQuery Mobile.
Detail is here.
If u want to use jQuery, then there is not a direct way of doing it.
So u should use a global variable for doing it like this way-
var is_ajax_enabled = true;
$(document).ready(function()
{
...................
...................
$("selector").click(function()
{
...................
//before AJAX call, just do a checking like it-
if(is_ajax_enabled())
{
//make your AJAX call here
$.ajax({url: "demo_test.txt", success: function(result)
{
$("#div1").html(result);
}});
}
...................
});
...................
...................
});
function disable_ajax()
{
is_ajax_enabled=false;
}
function enable_ajax()
{
is_ajax_enabled=true;
}
function is_ajax_enabled()
{
return is_ajax_enabled;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
Update-
If u want to have only one request available at a time and make a queue for the request, u can try this jQuery-Ajax-Singleton like this way-
$.ajax(options || {})
I have this notification system that works with the following jQuery / javascript and displays a notification when called.
What I am having some trouble doing and what I am trying to do is once a new notification is create to hide and remove / destroy any existing notifications.
I've tried something like this: $('.notification').not(this).hide().remove();, but that didn't work.
Here is the jQuery behind the notifications:
;(function($) {
$.notificationOptions = {
className: '',
click: function() {},
content: '',
duration: 5000,
fadeIn: 400,
fadeOut: 600,
limit: false,
queue: false,
slideUp: 200,
horizontal: 'right',
vertical: 'top',
afterShow: function(){},
afterClose: function(){}
};
var Notification = function(board, options) {
var that = this;
// build notification template
var htmlElement = $([
'<div class="notification ' + options.className + '" style="display:none">',
'<div class="close"></div>',
options.content,
'</div>'
].join(''));
// getter for template
this.getHtmlElement = function() {
return htmlElement;
};
// custom hide
this.hide = function() {
htmlElement.addClass('hiding');
htmlElement.animate({ opacity: .01 }, options.fadeOut, function() {
var queued = queue.shift();
if (queued) {
$.createNotification(queued);
}
});
htmlElement.slideUp(options.slideUp, function() {
$(this).remove();
options.afterClose();
});
};
// show in board
this.show = function() {
// append to board and show
htmlElement[options.vertical == 'top' ? 'appendTo' : 'prependTo'](board);
htmlElement.fadeIn(options.fadeIn, options.afterShow());
//$('.notification').css('marginLeft', -$('.notification').outerWidth()/2);
$('.notification-board.center').css('marginLeft', -($('.notification-board.center').width()/2));
$(window).on('resize', function(){
$('.notification-board.center').css('marginLeft', -($('.notification-board.center').width()/2));
});
};
// set custom click callback
htmlElement.on('click', function() {
options.click.apply(that);
});
// helper classes to avoid hide when hover
htmlElement.on('mouseenter', function() {
htmlElement.addClass('hover');
if (htmlElement.hasClass('hiding')) {
// recover
htmlElement.stop(true);
// reset slideUp, could not find a better way to achieve this
htmlElement.attr('style', 'opacity: ' + htmlElement.css('opacity'));
htmlElement.animate({ opacity: 1 }, options.fadeIn);
htmlElement.removeClass('hiding');
htmlElement.addClass('pending');
}
});
htmlElement.on('mouseleave', function() {
if (htmlElement.hasClass('pending')) {
// hide was pending
that.hide();
}
htmlElement.removeClass('hover');
});
// close button bind
htmlElement.children('.close').on('click', function() {
that.hide();
});
if (options.duration) {
// hide timer
setTimeout(function() {
if (htmlElement.hasClass('hover')) {
// hovering, do not hide now
htmlElement.addClass('pending');
} else {
that.hide();
}
}, options.duration);
}
return this;
};
var queue = [];
$.createNotification = function(options) {
options = $.extend({}, $.notificationOptions, options || {});
// get notification container (aka board)
var board = $('.notification-board.' + options.horizontal + '.' + options.vertical);
if (!board.length) {
board = $('<div class="notification-board ' + options.horizontal + ' ' + options.vertical + '" />');
board.appendTo('body');
}
if (options.limit && board.children('.notification:not(.hiding)').length >= options.limit) {
// limit reached
if (options.queue) {
queue.push(options);
}
return;
}
// create new notification and show
var notification = new Notification(board, options)
notification.show(board);
return notification;
};
})(jQuery);
and here is how the notifications are called / created:
$.createNotification({
horizontal:'center',
vertical:'top',
content:'No more cards at this time.',
duration:6000,
click:function(){
this.hide();
}
});
The code:
$('.notification').not(this).hide().remove();
will work just fine to remove all .notification DOM elements currently in the DOM except the current one IF this is the current notification DOM element. If that code isn't working, then it's likely because this isn't the desired notification DOM element that you want to keep. If this is an instance of your Notification class, then that's the wrong type of object. For that above code to work, this has to be the notification DOM object.
If you want to just remove all old notification DOM elements BEFORE you insert your new one, then you can just do this before your new one is in the DOM:
$('.notification').remove();
That will clear out the old ones before you insert your new one.
Since you don't have this line of code in your currently posted code, I can't tell where you were trying to use it so can't advise further on what might be wrong. Please describe further where in your code you were trying to use this.
With alot of help from #kalley we have found out that If I comment the following two lines out the LAG is gone!
var $tableContents = $table.find('tbody')
var $html = $('<tbody/>').html(data);
But how do I keep the above but cancel out the LAG ?
MORE INFO:
The code below works but the problem is that the $.GET is causing the browser to hang until the ajax request completes. I need (flow control?) or something that will solve this problem without locking/hanging up the browser until ajax completes the GET request.
The biggest LAG/Lockup/Hang is at $.get("updatetable.php", since the others only return 7 or less (number) values and this one ('updatetable.php') returns alot more (200-300kb). I would like to implement some sort of flow control here or make the script wait like 5 secs before firing the update command for tablesort and before showing the toast message so that ajax has time to GET the $.get("updatetable.php"data I just don't understand why does it lockup the browser as it is getting the data? is it trying to fire the other commands and that's whats causing the LAG?
Here are the STEPS
1.
$.get("getlastupdate.php" Will fire every 10 secs or so to check if the date and time are the same the return data looks like this: 20130812092636 the format is: YYYmmddHHmmss.
2.
if the date and time are not the same as the last GET then $.get("getlastupdate2.php" will trigger and this data will be send back and placed into a toast message and dispalyed to the user $().toastmessage('showNoticeToast', Vinfoo);
3.
before or after the above ($.get("getlastupdate2.php") another GET will fire: $.get('updatetable.php' this will GET the updated table info. and replace the old one with the new info. and then update/resort the table
4.
at the end of it all I want to $.get("ajaxcontrol.php" and this will return a 1 or 2 if the user is logged in then it will be a 2 else it's a 1 and it will destroy the session and log the user out.
<script type="text/javascript" src="tablesorter/jquery-1.10.2.min.js"></script>
<script type="text/javascript" src="tablesorter/final/jquery.tablesorter.js"></script>
<script type="text/javascript" src="tablesorter/final/jquery.tablesorter.widgets.js"></script>
<script type="text/javascript" src="tablesorter/final/toastmessage/jquery.toastmessage-min.js"></script>
<script type="text/javascript" src="tablesorter/qtip/jquery.qtip.min.js"></script>
<script type="text/javascript">
var comper;
function checkSession() {
return $.get("ajaxcontrol.php", function (DblIn) {
console.log('checking for session');
if (DblIn == 1) {
window.location = 'loggedout.php';
}
}).then(updateTable);
}
function checkComper() {
var SvInfo;
var onResponse = function (comperNow) {
if (comper === undefined) {
comper = comperNow;
} else if (comper !== comperNow) {
var Vinfoo;
comper = comperNow;
// returning this $.get will make delay done until this is done.
return $.get("getlastupdate2.php", function (primaryAddType) {
Vinfoo = primaryAddType;
$().toastmessage('showNoticeToast', Vinfoo);
}).then(checkSession);
}
};
$.get('getlastupdate.php').then(onResponse).done(function () {
tid = setTimeout(checkComper, 2000);
});
}
function updateTable() {
return $.get('updatetable.php', function (data) {
console.log('update table');
var $table = $("table.tablesorter");
var $tableContents = $table.find('tbody')
var $html = $('<tbody/>').html(data);
$tableContents.replaceWith('<tbody>' + data + '</tbody>')
//$tableContents.replaceWith($html)
$table.trigger("update", [true]);
var currentUrl = document.getElementById("frmcontent").contentWindow.location.href;
var urls = ['indexTOM.php', 'index1.php'],
frame = document.getElementById('frmcontent').contentDocument;
for (var i = 0; i < urls.length; i++) {
var url = urls[i];
if (frame.location.href.indexOf(url) !== -1) {
frame.location.reload()
}
}
$('[title!=""]').qtip({});
});
};
$(function () {
var tid = setTimeout(checkComper, 2000);
$("#append").click(function (e) {
// We will assume this is a user action
e.preventDefault();
updateTable();
});
// call the tablesorter plugin
$("table.tablesorter").tablesorter({
theme: 'blue',
// hidden filter input/selects will resize the columns, so try to minimize the change
widthFixed: true,
// initialize zebra striping and filter widgets
widgets: ["saveSort", "zebra", "filter"],
headers: {
8: {
sorter: false,
filter: false
}
},
widgetOptions: {
filter_childRows: false,
filter_columnFilters: true,
filter_cssFilter: 'tablesorter-filter',
filter_filteredRow: 'filtered',
filter_formatter: null,
filter_functions: null,
filter_hideFilters: false, // true, (see note in the options section above)
filter_ignoreCase: true,
filter_liveSearch: true,
filter_reset: 'button.reset',
filter_searchDelay: 300,
filter_serversideFiltering: false,
filter_startsWith: false,
filter_useParsedData: false
}
});
// External search
$('button.search').click(function () {
var filters = [],
col = $(this).data('filter-column'), // zero-based index
txt = $(this).data('filter-text'); // text to add to filter
filters[col] = txt;
$.tablesorter.setFilters($('table.hasFilters'), filters, true); // new v2.9
return false;
});
});
</script>
Maybe instead of using setInterval, you should consider switching to setTimeout. It will give you more control over when the time repeats:
function checkComper() {
var SvInfo;
var onResponse = function (comperNow) {
if (comper === undefined) {
comper = comperNow;
} else if (comper !== comperNow) {
var Vinfoo;
comper = comperNow;
// returning this $.get will make delay done until this is done.
return $.get("getlastupdate2.php", function (primaryAddType) {
Vinfoo = primaryAddType;
$().toastmessage('showNoticeToast', Vinfoo);
}).then(checkSession);
}
};
$.get('getlastupdate.php').then(onResponse).done(function () {
tid = setTimeout(checkComper, 10000);
});
}
var tid = setTimeout(checkComper, 10000);
Then you can keep it async: true
Here's a fiddle showing it working using echo.jsontest.com and some fudging numbers.
Since the click event callback seems to be where the issue is, try doing this and see if it removes the lag (I removed other comments to make it more brief):
function checkSession() {
return $.get("ajaxcontrol.php", function (DblIn) {
console.log('checking for session');
if (DblIn == 1) {
window.location = 'loggedout.php';
}
}).then(updateTable);
}
function updateTable() {
return $.get('updatetable.php', function (data) {
console.log('update table');
var $tableContents = $table.find('tbody')
//var $html = $('<tbody/>').html(data);
//$tableContents.replaceWith($html);
// replaceWith text seems to be much faster:
// http://jsperf.com/jquery-html-vs-replacewith/4
$tableContents.replaceWith('<tbody'> + data + '</tbody>');
//$table.trigger("update", [true]);
var currentUrl = document.getElementById("frmcontent").contentWindow.location.href;
var urls = ['indexTOM.php', 'index1.php'],
frame = document.getElementById('frmcontent').contentDocument;
for (var i = 0; i < urls.length; i++) {
var url = urls[i];
if (frame.location.href.indexOf(url) !== -1) {
frame.location.reload()
}
}
$('[title!=""]').qtip({});
});
};
$("#append").click(function (e) {
// We will assume this is a user action
e.preventDefault();
updateTable();
});
I commented out $table.trigger("update", [true]) since if you sort the table on the server before you return it, you shouldn't need to run that, which I'm almost certain is where the bottleneck is.
It is really hard untangle the mess you have but if what you want is ajax requests every 10 seconds it make sense to separate this logic from business logic over data from server.
Your code would also really benefit from using promises. Consider this example
$(document).ready(function() {
var myData = { }
, ajaxPromise = null
setInterval(callServer, 1000)
function callServer() {
ajaxPromise = updateCall()
.then(controlCall)
.done(handler)
.error(errorHandler)
}
function updateCall() {
return $.get('updateTable.php', function(data) {
myData.update = data
})
}
function controlCall( ) {
return $.get('ajaxControl.php', function(data) {
myData.control = data
})
}
function handler() {
console.dir(myData)
}
function errorHandler(err) {
console.log(err)
console.dir(myData)
}
})
when I click on the log in button the pop up open correctly. But when I close it and again click on the log in button without refreshing the page, it doesn't appear.
my code is:
<script type="text/javascript">
load_login_page = function() {
$.get(HOST_NAME + "e_commerce/ECommerces/ecommerce_login", {}, function(data) {
$("#temp_login_box").html(data);
$.blockUI({
message:$('#temp_login_box'),
css:{
top:($(window).height() - 300) / 2 + 'px',
left:($(window).width() - 800) / 2 + 'px',
width:'620px',
border:'none',
background:'none',
cursor:'default'
},
overlayCSS:{ backgroundColor:'#333' }
});
load_login_ajax_form();
});
};
load_login_ajax_form = function () {
var options = {
beforeSubmit:show_login_request, // pre-submit callback
success:show_login_response // post-submit callback
};
$('#product_info_form').ajaxForm(options);
};
show_login_request = function (formData, jqForm, options) {
return true;
};
show_login_response = function (responseText, statusText, xhr, $form) {
if (responseText == 'ok') {
// $("#temp_login_box").html(responseText);
window.location.href = HOST_NAME + "e_commerce/ECommerces/user_desboard";
//load_login_ajax_form();
} else {
$("#temp_login_box").html(responseText);
load_login_ajax_form();
}
};
hide_login_info = function() {
$.unblockUI();
};
hide_login_info is form closing function. temp_login_box is id to targeted div. please help me out with this code.
Please trace your function load_login_page to check whether $.get called every time.
because you are creating $.blockUI in success of $.get
To check more i need $.unblockUI Code.
But what i suggest is, in unblockUI function either you do empty the div or hide it.
If you hide it then to show on click you have to write $().show(); in $.blockUI function
if it is not the reason
provide $.unblockUI code then might be i can help you.
Note is jquery selector for the div you hide