Jtable pagination is not working if I am pressing back button.
I have some 4 option in menu. First option is home and last is report. When I am clicking on report, getting a list which I am displaying by using jtable. After clicking page 1,2,3,4,10,20 new page come. But after pressing back button previous should display. For that I modified some code of jtable api.
/* Performs an AJAX call to reload data of the table.
*************************************************************************/
_reloadTable: function (completeCallback) {
var self = this;
//Disable table since it's busy
self._showBusy(self.options.messages.loadingMessage, self.options.loadingAnimationDelay);
//Generate URL (with query string parameters) to load records
var loadUrl = self._createRecordLoadUrl();
//Load data from server
self._onLoadingRecords();
self._ajax({
type:'GET',
url: loadUrl,
cache : false,
data: self._lastPostData,
success: function (data) {
var historyData = self._lastPostData;
historyData.url=loadUrl;
history.pushState(stringifyObject(self),'List',window.location.href);
location.hash = loadUrl;
self._hideBusy();
//Show the error message if server returns error
if (data.Result != 'OK') {
self._showError(data.Message);
return;
}
//Re-generate table rows
self._removeAllRows('reloading');
self._addRecordsToTable(data.Records);
self._onRecordsLoaded(data);
//Call complete callback
if (completeCallback) {
completeCallback();
}
},
error: function () {
self._hideBusy();
self._showError(self.options.messages.serverCommunicationError);
}
});
},
And added one more method
window.onhashchange = function() {
//console.log(JSON.stringify(eval("(" + history.state + ")"));
if(history.state!=null){
var self = JSON.parse(history.state);
alert(self._createRecordLoadUrl());
alert(self.state._lastPostData);
self._reloadTable(completeCallback);
}
}
I am not able to call these method because self is not jtable object.
Please provide better solution.
Related
I`m using the following function to get a search result. The search that is the '$form" part works and returns the result but the part that uses the '$anchor' does not get the url and does not move to the next page. Can anybody help how it is right to take url. Or more precisely the broken part at least up to here is "url: $anchor.attr ("href")," After debuging I can see that url remains unidentified.
$(function () {
var MovieFormSubmit = function () {
//Grab the refernce of the form
var $form = $(this);
//Build the options object
var options =
{
url: $form.attr("action"),
type: $form.attr("method"),
data: $form.serialize()
};
$.ajax(options).done(function (data) {
var target = $($form.attr("data-movie-target"));
target.replaceWith(data);
});
//To prevent the browser from doing it's defualt action means navigating
//away and redrawing the complete page
return false;
};
var fetchPage = function () {
//Get the anchor tag that user clicked on
var $anchor = $(this);
//Extract values like Href attributes which is in the anchor tag http://localhost:1430/
var options = {
url: $anchor.attr("href"),
data: $("form").serialize(),
type: "get"
}
//make the ajax request with options object, when the data retrieved successfully,
//go and find out the target and then replace the target with the fetched one
$.ajax(options).done(function (data) {
var target = $anchor.parents("div.pagedList").attr("data-movie-target");
$(target).replaceWith(data);
});
return false;
};
//Look for Form with the name "data-movie-ajax", then wire up the submit event.
$("form[data-movie-ajax='true']").submit(MovieFormSubmit);
//Find the main-content and wire up the click event then filter these events based on ".pagedList a"
//then call the method fetchPage
$('#body').on("click", 'li', fetchPage);
});
I'm still trying to master jQuery, AJAX, and JSON.
On my application, I have the following dropdown select menu:
<select id="serviceload" name="serviceload"></select>
I auto populate the OPTIONS with another function which I don't think is necessary to display here. Just know that the above SELECT has 1 or more OPTION values.
This is followed by the content section:
<div class="row" id="completeProfile">
// series of DIVS and TABLES
</div>
Initially, the content section is hidden, so the user will only see the dropdown menu:
$('#completeProfile').hide();
And now, the jQuery: this next piece of code is what I use when the user chooses a selection from the dropdown menu. Every time they pick a new selection, queries rerun, and new content is displayed to the screen, unless they select a blank OPTION.
$('#serviceload').change(function () {
var page = $('#serviceload').val();
if (page == "") {
$('#completeProfile').hide();
} else {
$.post('api/profileSearch.php', {
page: page
}, function (data) {
var obj = JSON.parse(data);
$('#portBody').empty();
var htmlToInsert = obj.map(function (item) {
return '<tr><td>' + item.PORT + '</td><td>' + item.NAME + '</tr>';
});
$('#portBody').html(htmlToInsert);
});
// I do several more $.post to return data into specific tables
// Take note of this next $.post
$.post('api/vesselSearch.php', {
page: page
}, function (data) {
var obj = JSON.parse(data);
$('#vesselinfo').empty();
var htmlToInsert = obj.map(function (item) {
return '<tr><td>Edit</td><td>' + item.VESSEL_NAME + '</td></tr>';
});
});
// after all the queries are ran, and the data is returned, now we show the content
$('#completeProfile').show();
}
});
In the vesselInfo portion above, there is section that prints a hyperlink with which you can click, and it opens a modal window. This is for editing purpose. This functions properly.
Here is where the issue lies.
Back in the content section, there is another hyperlink that opens a modal window to add a new vessel.
<h3>Vessels</h3> / Add New
This opens an Add New Vessel modal. In that modal there is a FORM with a button that reads like this:
<button type="button" id="addVesselSubmit">Add</button>
When this button is clicked, it sends the values entered by the user to a PHP script which updates a table.
$('#addVesselSubmit').click(function () {
var addservice = $('#addservice').val();
var addvessel = $('#addvessel').val();
$.post('api/addInfo.php', {
addservice: addservice,
addvessel: addvessel
}, function (data) {
// here is where my problem lies
if (data == 0) {
alert("Vessel was not saved");
} else {
alert("Vessel was saved");
// At this point, I need to rerun the main function above so that it shows the vessel that was added immediately to the content section without a page refresh
}
});
});
So in the code directly above, if the new record was successfully saved to the table, the whole content section should rerun without a page refresh, with the new record automatically showing in the vesselInfo section.
I think the code that is used to display the content needs to be turned into a main function that can be called when the addVesselSubmit is successful, but I am not sure how to proceed with that.
To reiterate my question: I need to be able to save a new record, and print the new record to the page without a page refresh.
$.post('api/addInfo.php', {
addservice: addservice,
addvessel: addvessel
}, function (data) {
// here is where my problem lies
if (data == 0) {
alert("Vessel was not saved");
} else {
alert("Vessel was saved");
// At this point, I need to rerun the main function above so that it shows the vessel that was added immediately to the content section without a page refresh
//Trigger a change on element
$('#serviceload').trigger('change');
/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
}
});
This topic is covered in a few other questions, but I had some difficulty applying the suggested approaches into this use case. I have a checkbox list, where a user can select n sub-sites to publish their post to. since this list could grow to be 100+, I need an efficient way to perform an expensive task on each one. It's okay if it takes awhile, as long as Im providing visual feedback, so I planned to apply an "in progress" style to each checkbox item as its working, then move to the next item int he list once it is successfully published. Also note: I'm working in the WordPress wp_ajax_ hook but the PHP side of things is working well, this is focused on the JS solution.
This code is working right now (console.logs left in for debug), but I've seen multiple warnings against using async: true. How can I achieve a waterfall AJAX loop in a more efficient way?
//Starts when user clicks a button
$("a#as_network_syndicate").click( function(e) {
e.preventDefault(); //stop the button from loading the page
//Get the checklist values that are checked (option value = site_id)
$('.as-network-list').first().find('input[type="checkbox"]').each(function(){
if($(this).is(':checked')){
blog_id = $(this).val();
console.log(blog_id+' started');
$(this).parent().addClass('synd-in-progress'); //add visual feedback of 'in-progress'
var process = as_process_syndication_to_blog(blog_id);
console.log('finished'+blog_id);
$(this).parent().removeClass('synd-in-progress');
}
});
});
function as_process_syndication_to_blog(blog_id){
var data = {
"post_id": $('#as-syndicate_data-attr').attr("data-post_id"), //these values are stored in hidden html elements
"nonce": $('#as-syndicate_data-attr').attr("data-nonce"),
"blog_id": blog_id
};
var result = as_syndicate_to_blog(data);
console.log('end 2nd func');
return true;
}
function as_syndicate_to_blog(data){
$.ajax({
type : "post",
dataType : "json",
async: false,
url : ASpub.ajaxurl, //reference localized script to trigger wp_ajax PHP function
data : {action: "as_syndicate_post", post_id : data.post_id, nonce: data.nonce, blog_id: data.blog_id},
success: function(response) {
if(response.type == "success") {
console.log(response);
return response;
} else {
}
},
error: {
}
});
}
Indeed, doing synchronous AJAX request is bad because it will block the browser during the whole AJAX call. This means that the user cannot interact with your page during this time. In your case, if you're doing like 30 AJAX calls which take say 0.5 seconds, the browser will be blocked during 15 whole seconds, that's a lot.
In any case, you could do something following this pattern:
// some huge list
var allOptions = [];
function doIntensiveWork (option, callback) {
// do what ever you want
// then call 'callback' when work is done
callback();
}
function processNextOption () {
if (allOptions.length === 0)
{
// list is empty, so you're done
return;
}
// get the next item
var option = allOptions.shift();
// process this item, and call "processNextOption" when done
doIntensiveWork(option, processNextOption);
// if "doIntensiveWork" is asynchronous (using AJAX for example)
// the code above might be OK.
// but if "doIntensiveWork" is synchronous,
// you should let the browser breath a bit, like this:
doIntensiveWork(option, function () {
setTimeout(processNextOption, 0);
});
}
processNextOption();
Notice: as said by Karl-André Gagnon, you should avoid doing many AJAX requests using this technique. Try combining them if you can, it will be better and faster.
If you can't pass the whole block to the server to be processed in bulk, you could use a jQuery queue. This is using your sample code as a base:
var $container = $('.as-network-list').first();
$container.find('input[type="checkbox"]:checked').each(function(){
var $input = $(this);
$container.queue('publish', function(next) {
var blog_id = $input.val(),
$parent = $input.parent();
console.log(blog_id+' started');
$parent.addClass('synd-in-progress'); //add visual feedback of 'in-progress'
as_process_syndication_to_blog(blog_id).done(function(response) {
console.log(response);
console.log('finished'+blog_id);
$parent.removeClass('synd-in-progress');
next();
});
});
});
$container.dequeue('publish');
function as_process_syndication_to_blog(blog_id){
var data = {
"post_id": $('#as-syndicate_data-attr').attr("data-post_id"), //these values are stored in hidden html elements
"nonce": $('#as-syndicate_data-attr').attr("data-nonce"),
"blog_id": blog_id
};
return as_syndicate_to_blog(data).done(function(){ console.log('end 2nd func'); });
}
function as_syndicate_to_blog(data){
return $.ajax({
type : "post",
dataType : "json",
url : ASpub.ajaxurl, //reference localized script to trigger wp_ajax PHP function
data : {action: "as_syndicate_post", post_id : data.post_id, nonce: data.nonce, blog_id: data.blog_id}
});
}
I don't have a test environment for this so you may need to tweak it for your use case.
I have got a form with two tabs, on both tabs you can edit data and submit your changes which is working already.
Now I want the tab where you made changes to get reloaded after you changed something (e.g. a picture URL and the thumbnail should get refreshed) to see the changes.
I have this code for the second tab
<script>
$(document).ready(function(){
$('.btn').click(function(){
var clickBtnValue = $(this).val();
if(clickBtnValue == 'Save') {
var ajaxurl = 'ajax.php',
data = $('form').serialize();
$.post(ajaxurl, data, function (response) {
if(response == '')
{
alert("Successfully saved");
location.href="catalog.php";
}
else alert(response);
});
}
else if(clickBtnValue == 'Save & Continue Edit')
{
var ajaxurl = 'ajax.php',
data = $('form').serialize();
$.post(ajaxurl, data, function (response) {
if(response == '') alert("Successfully saved");
else alert(response);
});
}
else if(clickBtnValue == 'Add new Item')
{
var ajaxurl = 'ajax.php',
data = $('#itemform').serialize();
$.post(ajaxurl, data, function (response) {
if(response == '')
{
alert("Successfully added new Item");
location.href="catalog.php";
}
else alert(response);
});
}
else if(clickBtnValue == 'Save Images')
{
var ajaxurl = 'saveimages.php',
data = $('#imageform').serialize();
$.post(ajaxurl, data, function (response) {
if(response == '')
{
alert("Successfully saved");
$("#tab_images").load(location.href+" #tab_images>*","");
}
else alert(response);
});
}
});
});
Everything is working until now, the data get saved and the DIV reloads, but now whenever I try to press a button nothing happens, even on the first tab.
What am I doing wrong?
EDIT:
My Tab Code: http://i.epvpimg.com/9SaKb.png
Can't post it here since it is too long so I had to make a screenshot.
It looks like the buttons you try to click are inside the div what you are reloading. When the content of that div is replaces, all the elements you fetched with ajax are considered as new - that also means that the click handlers you had previously on those buttons are also lost - hence they don't react the same way :D
try binding the event not on the button itself but an element outside the div that is being replaced
$("parent_selector_outside_ajax_div").on("click", ".btn", function() {
//your button function
});
read move about event delegation with jQuery at http://api.jquery.com/on/
As your external js library binds it's own buttons I suggest moving those buttons outside the div you are trying to update (which shouln't be a big problem as you are trying to update only for the sake of them image previews? :D).
The other alternative (which I wouln't do) would be to rebind those buttons again after the ajax has reloaded by calling whatever function the library offers to initialize itself. If your application is long lived, you also should, before replacing the old content with a new one, remove all the event handlers from the current content, to avoid possible memory leaks in some browsers (not sure what is your target audience).
I am using Magnific Popup version 0.8.9.
I am loading content into it via Ajax, and I use a callback for ajaxContentAdded. This callback sets up an event handler for submitting a form that was loaded into the popup, like so:
$('.add-item-btn').magnificPopup({
type: 'ajax',
closeOnContentClick: false,
callbacks: {
ajaxContentAdded: HandleItemFormSubmit
}
});
This works fine, the form submit is handled correctly. The event handler function posts it to the server, which (in case of errors) returns the entire form including error messages.
For this purpose I let it replace the popup's content with the returned form, and setup the submit handler again.
function HandleItemFormSubmit()
{
var popup = this;
// Submit form using ajax
$('form.item-form').submit(function()
{
var data = $(this).serialize();
var url = $(this).attr('action');
$.post(url, data, function(resp)
{
if (resp == 'OK')
{
// All good, close up
popup.close();
}
else
{
// Show HTML from response (with errors)
popup.closeOnContentClick = false;
popup.content.replaceWith(resp);
popup.updateItemHTML();
HandleItemFormSubmit();
}
});
return false;
});
}
However, despite setting closeOnContentClick to false at two different points, the popup immediately closes when content is clicked after the content was replaced (it does work the first time).
The content in the popup has a single root element by the way.
I hope the author or someone else can help out here, I have no idea what is wrong here.
Thank you very much!
I've found another solution:
$('html').on('submit', '#UR_FORM', function(e) {
e.preventDefault();
$.ajax({
data: $(this).serialize(),
type: $(this).attr('method'),
url: $(this).attr('action'),
success: function(response) {
var magnificPopup = $.magnificPopup.instance;
magnificPopup.items[0].type = "inline";
magnificPopup.items[0].src = response;
magnificPopup.updateItemHTML();
}
});
});
You need to call the HandleItemFormSubmit for the popup object:
HandleItemFormSubmit.call(popup);
Otherwise when you call it the way you do, HandleItemFormSubmit();, the this will be set to window and this will not work as expected.
Update
Use this in the else clause:
if (resp == 'OK')
{
popup.close();
}
else
{
// Show HTML from response (with errors)
popup.closeOnContentClick = false;
popup.content.replaceWith(resp);
popup.updateItemHTML();
HandleItemFormSubmit.call(popup);
}