如何触发Ajax请求填写表格并等到DOM更改?(How to trigger Ajax Request for filling a Form out and wait until DOM change

编程入门 行业动态 更新时间:2024-10-24 06:28:33
如何触发Ajax请求填写表格并等到DOM更改?(How to trigger Ajax Request for filling a Form out and wait until DOM changes?)

我将通过PhantomJS使用JQuery填写表单 。

我有以下脚本:

var page = require('webpage').create(); page.open('http://demo.opencart.com/index.php?route=account/register', function() { fillTheForm(); phantom.exit(); }); function fillTheForm () { page.evaluate(function() { var selectTags = new Array(); selectTags = document.getElementsByTagName('select'); $(selectTags[0]).val("38"); $(selectTags[0]).trigger('change'); $(selectTags[1]).val('610'); }); page.render('form.png'); };

运行此脚本后,我在控制台内得到以下消息!

警报,JavaScript错误

此外,我尝试填写表格后的图片告诉我,第二个选择框的现有值尚未更改,然后PhantomJS无法将值分配给第二个字段。

有人可以帮我解决这个问题吗? 如何使用JQuery和PhantomJS填写这两个字段?

I am going to fill out a Form using JQuery through PhantomJS.

I have following script for doing that:

var page = require('webpage').create(); page.open('http://demo.opencart.com/index.php?route=account/register', function() { fillTheForm(); phantom.exit(); }); function fillTheForm () { page.evaluate(function() { var selectTags = new Array(); selectTags = document.getElementsByTagName('select'); $(selectTags[0]).val("38"); $(selectTags[0]).trigger('change'); $(selectTags[1]).val('610'); }); page.render('form.png'); };

after running this script, I got following message inside the console!

Alert, JavaScript error

Also, the picture that I have, after trying to fill the Form out, tells me that the existing values for the second Select box have not changed yet and then PhantomJS could not assign the value to the second field.

Can someone please help me to solve this problem? How can I fill out this two fields using JQuery and PhantomJS?

最满意答案

这是链式选择问题。 第二个依赖于第一个,并通过AJAX填充。 这意味着它是异步的。 您必须等待才能设置第二个值。 在PhantomJS中,这也是有问题的,因为你有两个已经“同步”的上下文(页面上下文和幻像上下文)。

例如,您可以使用

function fillTheForm () { page.evaluate(function() { var selectTags = document.getElementsByTagName('select'); $(selectTags[0]).val("38"); $(selectTags[0]).trigger('change'); }); setTimeout(function(){ page.evaluate(function() { var selectTags = document.getElementsByTagName('select'); $(selectTags[1]).val('610'); }); page.render('form.png'); phantom.exit(); // this has to be inside, because everything is asynchronous now }, 3000); // assuming 3 seconds are enough time for the request };

更好,更健壮的方法是从示例中使用waitFor ,因为只要数据可用就会完成。 重新加载第二个选择时,我有一些指标:

var page = require('webpage').create(); page.open('http://demo.opencart.com/index.php?route=account/register', function() { fillTheForm(function(){ page.render('form.png'); phantom.exit(); }); }); function fillTheForm(done) { page.evaluate(function() { var selectTags = document.getElementsByTagName('select'); // custom indicators, perhaps something more elaborate is needed for general selects // in this case it is ok window._chainedSelectChildrenLength = selectTags[1].children.length; window._chainedSelectFirstChildText = selectTags[1].children[0].innerText; $(selectTags[0]).val("38"); $(selectTags[0]).trigger('change'); }); waitFor(function testFx(){ return page.evaluate(function() { var selectTags = document.getElementsByTagName('select'); // use indicators return window._chainedSelectChildrenLength !== selectTags[1].children.length || window._chainedSelectFirstChildText !== selectTags[1].children[0].innerText; }); }, function onReady(){ page.evaluate(function(){ // continue var selectTags = document.getElementsByTagName('select'); $(selectTags[1]).val('610'); }); done(); }, 5000); // 3 seconds is the default }; function waitFor(testFx, onReady, timeOutMillis) { var maxtimeOutMillis = timeOutMillis ? timeOutMillis : 3000, //< Default Max Timout is 3s start = new Date().getTime(), condition = false, interval = setInterval(function() { if ( (new Date().getTime() - start < maxtimeOutMillis) && !condition ) { // If not time-out yet and condition not yet fulfilled condition = (typeof(testFx) === "string" ? eval(testFx) : testFx()); //< defensive code } else { if(!condition) { // If condition still not fulfilled (timeout but condition is 'false') console.log("'waitFor()' timeout"); phantom.exit(1); } else { // Condition fulfilled (timeout and/or condition is 'true') console.log("'waitFor()' finished in " + (new Date().getTime() - start) + "ms."); typeof(onReady) === "string" ? eval(onReady) : onReady(); //< Do what it's supposed to do once the condition is fulfilled clearInterval(interval); //< Stop this interval } } }, 250); //< repeat check every 250ms };

This is the chained selects problem. The second one is dependent on the first one and is populated via AJAX. This means that it is asynchronous. You have to wait before you can set the second value. In PhantomJS this is also problematic, because you have two contexts (page context and phantom context) that have do be "synchronized".

For example you can use

function fillTheForm () { page.evaluate(function() { var selectTags = document.getElementsByTagName('select'); $(selectTags[0]).val("38"); $(selectTags[0]).trigger('change'); }); setTimeout(function(){ page.evaluate(function() { var selectTags = document.getElementsByTagName('select'); $(selectTags[1]).val('610'); }); page.render('form.png'); phantom.exit(); // this has to be inside, because everything is asynchronous now }, 3000); // assuming 3 seconds are enough time for the request };

A better and more robust way would be to use waitFor from the examples, because it is finished as soon as the data is available. Here I have some indicators when the second select is reloaded:

var page = require('webpage').create(); page.open('http://demo.opencart.com/index.php?route=account/register', function() { fillTheForm(function(){ page.render('form.png'); phantom.exit(); }); }); function fillTheForm(done) { page.evaluate(function() { var selectTags = document.getElementsByTagName('select'); // custom indicators, perhaps something more elaborate is needed for general selects // in this case it is ok window._chainedSelectChildrenLength = selectTags[1].children.length; window._chainedSelectFirstChildText = selectTags[1].children[0].innerText; $(selectTags[0]).val("38"); $(selectTags[0]).trigger('change'); }); waitFor(function testFx(){ return page.evaluate(function() { var selectTags = document.getElementsByTagName('select'); // use indicators return window._chainedSelectChildrenLength !== selectTags[1].children.length || window._chainedSelectFirstChildText !== selectTags[1].children[0].innerText; }); }, function onReady(){ page.evaluate(function(){ // continue var selectTags = document.getElementsByTagName('select'); $(selectTags[1]).val('610'); }); done(); }, 5000); // 3 seconds is the default }; function waitFor(testFx, onReady, timeOutMillis) { var maxtimeOutMillis = timeOutMillis ? timeOutMillis : 3000, //< Default Max Timout is 3s start = new Date().getTime(), condition = false, interval = setInterval(function() { if ( (new Date().getTime() - start < maxtimeOutMillis) && !condition ) { // If not time-out yet and condition not yet fulfilled condition = (typeof(testFx) === "string" ? eval(testFx) : testFx()); //< defensive code } else { if(!condition) { // If condition still not fulfilled (timeout but condition is 'false') console.log("'waitFor()' timeout"); phantom.exit(1); } else { // Condition fulfilled (timeout and/or condition is 'true') console.log("'waitFor()' finished in " + (new Date().getTime() - start) + "ms."); typeof(onReady) === "string" ? eval(onReady) : onReady(); //< Do what it's supposed to do once the condition is fulfilled clearInterval(interval); //< Stop this interval } } }, 250); //< repeat check every 250ms };

更多推荐

本文发布于:2023-08-07 13:28:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1464262.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:表格   trigger   DOM   Ajax   Form

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!