I am trying to scrape http://www.snapdeal.com/offers/deal-of-the-day which loads JSON data using an AJAX call to below page:
json_url = http://www.snapdeal.com/json/getProductById?*
The code block I am using is below, I get the log message Waiting for AJAX request:, but not the Waiting for AJAX request:, instead waitForResource times out
casper.options.onResourceRequested = function (casper, requestData){
// loop through our AJAX urls
// create list of AJAX urls to track
var ajaxUrls = [json_url];
ajaxUrls.every(function(ajaxUrl){
// does this request match an AJAX url
if(requestData.url.indexOf(ajaxUrl) !== -1){
// it matches, so we'll wait for it to return (with 10s timeout)
//console.log("Waiting for AJAX request: " + requestData.url);
// print_object(requestData);
casper.waitForResource(requestData.url, function(){
console.log("AJAX request returned: " + requestData.url);
}, function(){
console.log("AJAX request didn't return after wait period: " + requestData.url)
}, 10000);
}
});
}
To further debug, I logged events and the resource at url json_url was successfully received, but not sure why waitForResource times out.
casper.on('resource.received', function(resource) {
if (resource.url.indexOf('http://www.snapdeal.com/json/getProductById') != -1){
casper.echo('resource.received: ' + resource.url);
}
});
Log after run:
Waiting for AJAX request: http://www.snapdeal.com/json/getProductById?pogIds=671556289429,649272180,60998,685755068805,677649317861,1239888775,661402031482,636966047361,1775140628,1822452791,439536 ,Range,2042952975,1472100667,899358889,643129681532,668235859588,&lang=en
resource.received: http://www.snapdeal.com/json/getProductById?pogIds=671556289429,649272180,60998,685755068805,677649317861,1239888775,661402031482,636966047361,1775140628,1822452791,439536,Range, 2042952975,1472100667,899358889,643129681532,668235859588,&lang=en
resource.received: http://www.snapdeal.com/json/getProductById?pogIds=671556289429,649272180,60998,685755068805,677649317861,1239888775,661402031482,636966047361,1775140628,1822452791,439536,Range, 2042952975,1472100667,899358889,643129681532,668235859588,&lang=en
AJAX request didn't return after wait period: http://www.snapdeal.com/json/getProductById?pogIds=671556289429,649272180,60998,685755068805,677649317861,1239888775,661402031482,636966047361,17751406 28,1822452791,439536,Range,2042952975,1472100667,899358889,643129681532,668235859588,&lang=en Got page No Offeres Found thestartin: ~/Appli
What you need is:
casper.waitForSelector()
or
casper.waitFor(function() {
// test here something that return true when the page is loaded
})
Related
Well Thank you in advance for taking the time to read through my question.
The situation is as follows:
I have a Wrodpress server with a singular site in the wp-admin/sites/contactform/index.php
From that site I want to make an Ajax call however I get a '/wp-admin/admin-ajax.php:1 Failed to load resource: the server responded with a status of 400 (Bad Request) ' error upon the initial loading of the site and a
' https://THECORRECTURL/wp-admin/admin-ajax.php 400 (Bad Request)' error when I execute the method.
My suspicion is that the errors are provoked by missing permissions to access the admin-ajax.php file.
I'd like to know what you think.
Here is the Code:
In a js file in the directory of 'contactform/dt/wb.js':
jQuery(document).ready(function($) {
$('#btn-x').click(function() {
$.ajax({
url: '../../admin-ajax.php', // The URL of the WordPress AJAX handler
type: 'POST', // The HTTP method of the request
data: { // The data to be sent with the request
action: 'usystorequest',
},
success: function(response) { // A function to be called if the request is successful
if (response) {$('#mail_sent').show(); //mail got sent
}
else { $('#mail_not_sent').show(); //mail didnt get sent
}
}
});
});
});
In the functions.php File in 'contactform':
add_action('wp_enqueue_scripts', function(){
wp_enqueue_script('wb', get_stylesheet_directory_uri() . '/dt/wb.js',['jquery'], '1.0', false);
wp_enqueue_script('jquery', get_stylesheet_directory_uri() . '/dt/jquery-3.4.1.min.js',[], '1.0', false);
});
//Function executed by ajax call
add_action("wp_ajax_usystorequest", "usystorequest");
add_action("wp_ajax_nopriv_usystorequest", "usystorequest");
function usystorequest(){
echo ':test:';
wp_die();
}
(I am not using a Contactform plugin because i am sending Information that gets calculated in js and the site is seperated from the usual structure with themes and plugins because of conflicts with the Plugins and Themes - its simply easier this way. A prior version of what I currently want to update already runs there just without ajax)
I added a nopriv ajax call so you dont need admin permissions (be logged in) to execute the ajax function.
The usystorequest function is kept as easy as possible to exclude the source of the error is the code.
I tried doing it over a custom ajax handler, here is the code. It got me the same error:
FUNCTIONS.PHP
// Step 1: Add a new endpoint in your functions.php file
add_action( 'init', 'add_my_endpoint' );
function add_my_endpoint() {
add_rewrite_endpoint( 'my-endpoint', EP_ROOT );
}
// Step 2: Add a function to handle the request
add_action( 'template_redirect', 'my_endpoint_handler' );
function my_endpoint_handler() {
global $wp_query;
if ( ! isset( $wp_query->query_vars['my-endpoint'] ) ) {
return;
}
// Handle the request
if ( $_SERVER['REQUEST_METHOD'] == 'GET' && isset( $_GET['action'] ) && $_GET['action'] == 'usystorequest' ) {
usystorequest();
exit;
}
}
JAVASCRIPT WB.JS FILE
// Step 3: Update your AJAX call to use the new endpoint
jQuery(document).ready(function($) {
$('#btn-x').click(function() {
$.ajax({
url: '/?my-endpoint=1', // The URL of the custom AJAX handler
type: 'GET', // The HTTP method of the request
data: { // The data to be sent with the request
action: 'usystorequest', // The name of the action to be triggered in the WordPress backend (functions.php)
},
success: function(response) { // A function to be called if the request is successful
if (response) {$('#mail_sent').show(); //mail got sent
}
else { $('#mail_not_sent').show(); //mail didnt get sent
}
}
});
});
});
I have an ajax request which invokes GetTierNamesServlet:
$('#application').change(function() {
$.ajax({
url : 'GetTierNamesServlet',
data : {
name : $('#application').find(":selected").text()
},
type : 'get',
cache : false,
success : function(data) {
},
error : function() {
alert('error');
}
}).done(function() {
var test = '<c:out value="${tiers}" />';
alert(test)
})
});
GetTierNamesServlet saves 'tiers' to a session attribute as follows and forwards back to the same page (index.html).
HttpSession session = request.getSession(false);
session.setAttribute("tiers", tiers);
getServletContext().getRequestDispatcher("/index.jsp").forward(request, response);
When alert(test) is called, it alerts the selected tiers from the previous time the ajax request was processed.
The session attribute 'tiers' always seems to "lag" one refresh behind.
What am I doing incorrectly here? I would expect that by placing the alert within the .done portion of the ajax request it would wait the asynchronous call to return before doing something.
This fragment of JavaScript:
var test = '<c:out value="${tiers}" />';
is rendered with the value of ${tiers} before your servlet is called. If you inspect the HTML on the page you will likely find something like:
...
}).done(function() {
var test = 'null'; // or some other "old" value
alert(test)
})
the JSP content is translated to HTML and sent to the browser (page 1)
some event on page 1 causes the JavaScript to be executed
the AJAX call results in the page being rendered again and returned to the browser (page 2)
the JavaScript in page 1 finishes executing via the .done(...) function.
You AJAX call is returning a page when it should probably return a JSON fragment containing your tiers content which will then be consumed by the .done function.
I can't seem to get the AJAX call correct. There have been other QA that deal with the $.ajax() function but I'm trying to solve this with $.post().
When the form button is clicked the javascript at the head is executed, which includes a $.post(). The url /login is routed through and passed to loginPost function. There a response is determined and sent back to the javascript (right?). Instead, webpage renders the response (pass || fail).
Why isn't the response from the AJAX call being sent back to get processed?
This is a simple example that I am working with to get me better acquainted to how AJAX in expressJS and jQuery work. Any Help is greatly appreciated!
--views/login.jade
script(src='/_js/jquery-1.8.2.min.js')
script
$(document).ready(function(req, res) {
$('#login').submit(function() {
var formData = $(this).serialize();
console.log(formData);
$.post('/login', formdata, processData).error('ouch');
function processData(data, status) {
console.log(status);
console.log(data);
if (data == 'pass') {
$('#content').html('<p>You have successfully loggin in!</p>');
} else {
if (! $('#fail').length) {
$('#formFrame').prepend('<p id="fail">Incorrect login information. Please try again)</p>');
}
}
} //end processData
}); //end submit
}); //end ready
div.main
h1= title
div#formFrame
form(id='login', action='/login', method='POST')
p
label(for='username') Username:
input(id='username', type='text', name='username')
p
label(for='password') Password:
input(id='password', type='password', name='password')
p
input(id='button', type='submit', name='button', value='Submit')
--routes/index.js
app.post('/login', loginPost);
--routes/loginPost
module.exports.loginPost = function(req, res) {
var password = 'admin'
, username = 'user'
, data = req.body;
if (data.username == username && data.password == password) {
res.send('pass');
} else {
res.send('fail');
}
};
You still have to stop the <form> from submitting via its default action, which can be done with event.preventDefault():
$('#login').submit(function(evt) {
evt.preventDefault();
// ...
});
Otherwise, the <form> will redirect the page to its action (or back to the current address if no action was given), interrupting the $.post request.
I'm using a customized example of plupload, where
one or more files are first uploaded to an Amazon S3 bucket, and
then file info + user-entered data (e.g. description) is POSTed
via ajax to my controller action in a loop.
This controller action then verifies that the file was upload to the S3 bucket and then saves the info into the database, returning a success or failure to the ajax call.
I use the 'UploadComplete' event to check for any upload errors, and if there are none, perform the actual POSTs in a loop.
What I'd like to do is wait until the entire loop has finished processing and then display the confirmation message (all success, all failed, mix of both) accordingly.
Current code:
uploader.bind('UploadComplete', function (up, files) {
var errorsPresent = false;
var errors = '';
// re-enable buttons
$('div.plupload_buttons a').removeClass('disabled');
$.each(uploader.files, function (i, file) {
if (errorDescArray.hasOwnProperty(file.id)) {
errorsPresent = true;
errors += errorDescArray[file.id] + '<br />';
}
else if (file.status = plupload.DONE) {
var jqXhr = $.post('/documents/add', {
'__RequestVerificationToken': $('#__AjaxAntiForgeryForm input[name=__RequestVerificationToken]').val(),
'filename': file.name,
'size': file.size,
'location': $('#' + file.id + '_location').val(),
'description': $('#filedesc_text_' + file.id).text()
}).error(function (response) {
errorsPresent = true;
errors += response.responseText + '<br />';
});
}
});
//
if (errorsPresent) {
$('#uploadErrors').html('<div data-alert="alert" class="alert-message block-message fade in error">×<p>' + errors + '</p></div>');
}
else {
// set confirmation message
var message = files.length + ' file(s) were successfully uploaded.';
// clear file list
$('ul.plupload_filelist').html('');
// remove files from list
uploader.splice();
// hide modal
$('#upload-modal').modal('hide');
// show confirmation
$('#flashMessage').html('<div data-alert="alert" class="alert-message block-message fade in success">×<p>' + message + '</p></div>');
}
});
The above is obviously flawed in that the second half of the snippet doesn't really wait for the POSTs to complete, with the result that the success confirmation is displayed even if POST has an error response.
So my question is this: How do I perform an ajax post in a loop (unless there's a better way) and process the confirmation message after the loop has finished processing?
I am wondering what is the best way to stop duplciate submissions when using jquery and ajax?
I come up with 2 possible ways but not sure if these are the only 2.
On Ajax start disable all buttons till request is done. 2 problems I see with this though is I use jquery model dialog so I don't know how easy it would be to disable those button as I not sure if they have id's. Second I if the the request hangs the user has really no way to try again since all the buttons are disabled.
I am looking into something called AjaxQueue at this time I have no clue if it is what I need or how it works since the site where the plugin is apparently down for maintenance.
http://docs.jquery.com/AjaxQueue
Edit
I think this is a spin off of what I was looking at.
http://www.protofunc.com/scripts/jquery/ajaxManager/
The only problem I see with this ajaxManager is that I think I have to change all my $.post, $.get and $.ajax ones to their type.
But what happens if I need a special parameter from $.ajax? Or that fact I like using .post and .get.
Edit 2
I think it can take in all $.ajax options. I am still looking into it. However what I am unsure about now is can I use the same constructor for all requests that will use the same options.
First you have to construct/configure a new Ajaxmanager
//create an ajaxmanager named someAjaxProfileName
var someManagedAjax = $.manageAjax.create('someAjaxProfileName', {
queue: true,
cacheResponse: true
});
Or do I have to make the above every single time?
How about setting a flag when the user clicks the button? You will only clear the flag when the AJAX request completes successfully (in complete, which is called after the success and error callbacks), and you will only send an AJAX request if the flag is not set.
Related to AJAX queuing there is a plugin called jQuery Message Queuing that is very good. I've used it myself.
var requestSent = false;
jQuery("#buttonID").click(function() {
if(!requestSent) {
requestSent = true;
jQuery.ajax({
url: "http://example.com",
....,
timeout: timeoutValue,
complete: function() {
...
requestSent = false;
},
});
}
});
You can set a timeout value for long-running requests (value is in milliseconds) if you think your request has a possibility of hanging. If an timeout occurs, the error callback is called, after which the complete callback gets called.
You could store an active request in a variable, then clear it when there's a response.
var request; // Stores the XMLHTTPRequest object
$('#myButton').click(function() {
if(!request) { // Only send the AJAX request if there's no current request
request = $.ajax({ // Assign the XMLHTTPRequest object to the variable
url:...,
...,
complete: function() { request = null } // Clear variable after response
});
}
});
EDIT:
One nice thing about this, is that you could cancel long running requests using abort().
var request; // Stores the XMLHTTPRequest object
var timeout; // Stores timeout reference for long running requests
$('#myButton').click(function() {
if(!request) { // Only send the AJAX request if there's no current request
request = $.ajax({ // Assign the XMLHTTPRequest object to the variable
url:...,
...,
complete: function() { timeout = request = null } // Clear variables after response
});
timeout = setTimeout( function() {
if(request) request.abort(); // abort request
}, 10000 ); // after 10 seconds
}
});
$.xhrPool = {};
$.xhrPool['hash'] = []
$.ajaxSetup({
beforeSend: function(jqXHR,settings) {
var hash = settings.url+settings.data
if ( $.xhrPool['hash'].indexOf(hash) === -1 ){
jqXHR.url = settings.url;
jqXHR.data = settings.data;
$.xhrPool['hash'].push(hash);
}else{
console.log('Duplicate request cancelled!');
jqXHR.abort();
}
},
complete: function(jqXHR,settings) {
var hash = jqXHR.url+jqXHR.data
if (index > -1) {
$.xhrPool['hash'].splice(index, 1);
}
}
});