Page does not change after I set an option button with HtmlUnit - htmlunit

I am using HtmlUnit to navigate through the Web of knowledge web page. I am using the code below to set an option button so that results on the page would be sorted appropriately. Unfortunately, nothing happens when I execute the code. Results on the page remains sorted in the same way as they ware before.
HtmlSelect ssort = (HtmlSelect) pageX.getFirstByXPath("//*[#id=\'topNavBar\']/tbody/tr/td[3]/form/select");
HtmlOption optionA = ssort.getOptionByValue("LC.D;PY.D;AU.A;SO.A;VL.D;PG.A");
ssort.setSelectedAttribute(optionA, true);
ssort.click();
I debuged the code and there is no errors. Do you have any idea what am I doing wrong?

As a general rule, functions like the .click() and .setSelectedAttribute(HTMLOption, boolean)(See JavaDoc) will return a HTMLPage that in most cases is the same as the current one, however in your case it will return a different HTMLPage. So to capture the new page you just need to assign the return value to a HTMLPage.
N.B: You could also use getCurrentWindow() on the WebClient instance.

Related

Loop through drop down with dynamic html table

I'm hard stuck with this one so any advice welcome!
Ive been trying to create a flow that goes to this website https://dlv.tnl-uk-uni-guide.gcpp.io/ and scrapes the data from each table in the Subject Areas drop down list. My knowledge of HTML is sketchy at best but from what I understand it's a dynamic html table that just refreshes with new data rather than going to a new url. I can extract the subject list as a variable and in my head i think i just need to add this to a UI selector action but despite numerous attempts i've got absolutely nowhere. Anyone got any ideas as to how i could fix this or work around?
Because it is not a conventional drop-down using the "Set drop-down list value on web page" doesn't work all that well.
You can use a bit of javascript and variables for this.
Hit F12 to show developer tools, you will see there is a list of hidden items with the class class="gug-select-items gug-select-hide" you will use this in the javascript.
Then add a 'Press button on web page' function and add the 'drop-down' element, which is a <div>
Then edit the element selector and change it to text editor.
then change the selector to make use of the nth-child(0) selector but use a variable for the index.
so it looks something like #gug-overall-ranking-select > div.gug-select-items > div:nth-child(%ddIdx%)
Use the "Run JavaScript function on web page" function to get the number of options available to the drop-down. (child elements)
The returned result is text, so convert it to a number that can be used in the loop.
function ExecuteScript() { /*your code here, return something (optionally); */
var firstDDlist = document.querySelector("#gug-overall-ranking-select > div.gug-select-items.gug-select-hide");
return firstDDlist.children.length;
}
In the loop each element will be pressed and cause the table to reload.
The table data extraction can then also be done in the loop, but that this code only shows the looping through the options.
The full flow 'code' (copy this and paste it in power automate).
WebAutomation.LaunchEdge.LaunchEdge Url: $'''https://dlv.tnl-uk-uni-guide.gcpp.io/?taxonomyId=36&/#gug-university-table''' WindowState: WebAutomation.BrowserWindowState.Normal ClearCache: False ClearCookies: False WaitForPageToLoadTimeout: 60 Timeout: 60 BrowserInstance=> Browser
WebAutomation.ExecuteJavascript BrowserInstance: Browser Javascript: $'''function ExecuteScript() { /*your code here, return something (optionally); */
var firstDDlist = document.querySelector(\"#gug-overall-ranking-select > div.gug-select-items.gug-select-hide\");
return firstDDlist.children.length;
}''' Result=> numberOfItems
Text.ToNumber Text: numberOfItems Number=> itemCount
LOOP ddIdx FROM 1 TO itemCount STEP 1
WebAutomation.PressButton.PressButton BrowserInstance: Browser Control: appmask['Web Page \'h ... sity-table\'']['Div \'gug-select-selected\''] WaitForPageToLoadTimeout: 60
END
It should end up looking like this:
Flow running:
With using Power Automate Desktop (PAD), the goal is to be a low-code solution. Of course knowing HTML is a bonus and will help you on tricky webpages or problems, but not knowing much is alright usually. I'm not really comfortable going to that web page you shared but you could try the below option.
PAD has a built in function in the action pane:
'Browser automation' > 'Web data extraction' > 'Extract data from web page'
Try using that and when asked to add UI Element select the table/dropdown list to see what information you get back. If that doesn't work you might need to try out JavaScript or another method.

Wicket (1.6) stateless form resets paging

I've already tried to find anything about that problem but I guess I either was not sure how to shortly describe the problem to find a solution or nobody else had that before which I can't think of. Maybe my thinking is wrong, too.
I have a stateless wicket 1.6 form with an ajax supporting panel (WebMarkupContainer with output id). The panel holds a dataview with paging navigator. The dataview itself is filled by a DataProvider.
The panel shows some entries from the database and below that is the navigator. by clicking any page on the navigator, the panel is refreshed (ajax) and shows content from that page. The page itself is not re-rendered by the browser.
When I now leave the page by navigating to another internal page (so basically when leaving the dataview-panel-page in any way) to open a detail page or so and then return to that dataview-page the navigator is resetted (because it's stateless I guess). The navigator can't remember which page to show and begins at the top of the first page again.
The question is: How can I solve this? I would like to i.ex. navigate to page 2 and then temporary leave the page for another internal page. When returning I want to be on page 2, focussed on the record where I clicked the link to "details" before. This also happens when I just open a new page in a new Browser tab.
Thank you!
Here's some code:
final WebMarkupContainer gamesPanel = new AjaxContainer("gamesPanel");
final DataView<Game> dataView =
new GameDataView("gameOverview", targetCurrencyModel, searchTextModel, gameFilterModel,
new GameDataProvider(searchTextModel, gameFilterModel, targetCurrencyModel));
dataView.setItemsPerPage(ITEMS_PER_PAGE);
gamesPanel.add(dataView);
final XNPagingNavigator navigator = new XNPagingNavigator("navigator", dataView);
navigator.setOutputMarkupId(true);
add(navigator);
You guys can try what I mean: The page I'm talking about is http://www.xbox-now.de. Just navigate to page 2, then click on details and return to main page.
I think you might use History API to push a new state when you click on navigation bar. In the new URL for the state you can include a parameter that indicates the index of the current navigator page.
You can customize your AJAX link in order to perform this operations when user click on it.
For more details on History API see Updating address bar with new URL without hash or reloading the page
I solved this in the NoWicket framework by introducing a model aware page cache which reuses page instances when hashcode/equals matches in the page model. You can see the implementation in the GitHub repo, try this implementation of the IPageFactory wrapper as a starting point, but it is more code involved there, just check out the code, debug the example and navigate the code to understand it better in order to apply it to your application. See your use case in action by trying this data table example in the documentation website (which you can also debug locally): http://invesdwin.de/nowicket/ajaxdatatable
Try changing the paging index, navigate to a different page and navigate back to the data table example page. You will still see the paging index that you left there.
Thank you guys for your replies. I've done it now another way. Used the base code from here and modified it in some ways. Added some nice css AttributeModifiers to indicate the actual page:
item.add(new AttributeModifier("class", new PageLinkCssModel(pageable, pageIndex, "active")));
Then I modified some code to add or reset the page parameter, that it's 1) used only once and 2) keeps all the actual page parameters which were there before adding own ones. So I am just appending the page number now. This way I can keep my initially mount path like www.foo.bar/path/path/path. Complete URL would now look like: www.foo.bar/path/path?page=123.
To pass my entered page (i.e. page=5) to the data provider I just had to override the providers iterator. It should start with the page I entered. Due to the ugly generated navigator URLs (which are extremly bad for SEO) I now have nice looking urls which are working independently what wasn't possible before. And that's also the reason why I could not get back to the correct page. The navigator URL was not lookup-able by wicket.
new DataView<GamePrice>("gamePriceOverview", new GameDetailDataProvider(gameId, targetRegion) {
#Override
public Iterator<GamePrice> iterator(final long first, final long count) {
return super.iterator(ITEMS_PER_PAGE * getCurrentPage(), count);
}
getCurrentPage() comes from the base template and gets the actual page number entered (if one is entered):
public long getCurrentPage() {
// -1 weil zero based
return getRequest().getQueryParameters().getParameterValue("page").toString() != null
? (getRequest().getQueryParameters().getParameterValue("page").toLong() - 1)
: 0;
}
So instead of having ugly SEO-unfriendly URLs which are also not compatible to work independant (directly enter the generated url) I now have the same URL I expect with an added page-parameter.
URL now would looks like:
http://localhost:8080/game/4249/de/doom-preorder?page=2
URL before was:
localhost:8080/game/4249/DE/doom-preorder?0-1.ILinkListener-gamePrices-navigator-navigation-2-pageLink
If I now go back from the detail page to the main index with active "Bookmarkable-Navigator", I correctly come back to the page and position where I left it (because of bookmarkable page links).
That's how I achieved this problem with a nice bonus: User- and SEO-friendly URLs.

How do I debug JQuery-BootGrid data api to NancyFX

Question edited:
I wrote a page with jquery-bootgrid data API.
Its should be calling with AJAX to my NancyFX REST API, but it isn't.
Client side:
I'm serving the bootgrid from a local repo:
<script src="~/scripts/jquery.bootgrid.min.js"></script>
Maybe I shouldn't be using the .min.js file but rather the open one for debugging? If so, could you walk me through what to do, or point me in the direction?
The page code is
...
data-toggle="bootgrid" data-ajax="true"
data-url="/cars/0" data-method="GET"
Server side:
I have the html page served by NancyFx and is seen ok, except for the grid which is empty. There's an API module with a breakpoint in Visual Studio (running on localhost), with the following:
Get["/cars/{status:int}?current={current}&rowCount={rowCount}"] = parameters => ...
This code is never called. How can I force the debugger to catch ANY call before the routing is checked, and show me what's coming into the server?
I'm using the chrome debugger.
The current URL is not valid by Nancy standards. We don't add query string params to the route.
You would want to write something along the lines of:
Get["/cars/{status:int}"] = parameters =>
{
var status = (int)parameters.status;
var current = (string)parameters.current.TryParse("");
var rowCount = (int)parameters.current.TryParse(10);
...
}
Along those lines. (written off the top of my head)
An alternative approach is to bind the request like so:
Get["/cars/{status:int}"] = parameters =>
{
var request = this.Bind<MyRequest>();
...
}
public class MyRequest
{
public MyRequest()
{
RowCount = 10;
}
public int Status {get;set;}
public string Current {get;set;}
public int RowCount {get;set;}
}
Changing the nancy to Get["/cars/{status:int}"] = parameters => did the trick of catching the request.
The ajax wasn't being called because I lost the JQuery first line...
$(document).ready(function() {
To get the current and rowCount you need to use
var current = (int)Request.Form["current"];
var rowCount = (int)Request.Form["rowCount];
By the way, the Get wasn't working (I think its a Bootgrid bug) so I changed it to POST.
The simplest way to debug any jQuery library is by using the in-built debugger, it's kinda difficult for me to use chrome for that , so I use Firefox but if you are habitual of chrome then use it, the functionality is almost the same, but with Firefox you can directly switch to the events associated with any element in the html (in the inspect section)
Once you get into the debugger, set the breakpoint and refresh the page either by F5 or Ctrl+F5 if you selected the valid breakpoint you can see all the values associated with every variable also with every function.
Secondly, use the step-in option in the debugger to see where the exact line is pointing, if it's refering to any other file it will pop open automatically in the debugger menu. Firefox's spider monkey is much good at debugging and relating codes (that's totally my opinion).
3- for the api calls, the reason for data not being processed or not displayed, very much lies within the structure of the library,(on what parameters the data is called/fetched/retrieved), for this try to use the "watch expressions" option in debugger and try implementing the code on loaded dom in console section with trigger on the node which you think is bugged or which should display the value.

iTextSharp multiple actions for pushbuttonfield

In a PDF, I can set up a button to
Submit the FDF data to my RestAPI
Redirect to a webpage (to tell user 'Thanks') and that works perfectly.
But I need to do this using code... I am using iTextSharp in the following way:
pb is my pushbutton...
sURL is the URL I need the data to go to...
This is my code:
PdfFormField pff = pb.Field;
pff.SetAdditionalActions(PdfName.A, PdfAction.CreateSubmitForm(sURL, null, PdfAction.SUBMIT_XFDF));
af.ReplacePushbuttonField("submit", pff);
This does replace the button with the submit action. How do I keep the page redirect or how do I set it in code?
I have also tried PdfName.AA and PdfName.U based on examples and I am not certain what the different names are for. But nothing works. :-/
Apparently, the SetAdditionalActions() replaces the existing actions.
I have also tried using annotations and just adding a button that doesn't exist.
You are looking for a concept called chained actions as demonstrated in the PrintTimeTable example:
Chunk chunk = new Chunk("print this page");
PdfAction action = PdfAction.javaScript(
"app.alert('Think before you print!');", stamper.getWriter());
action.next(PdfAction.javaScript(
"printCurrentPage(this.pageNum);", stamper.getWriter()));
action.next(new PdfAction("http://www.panda.org/savepaper/"));
chunk.setAction(action);
In this case, we have an action that shows an alert, prints a page and redirects to an URL. These actions are chained to each other using the next() method.
In C#, this would be:
Chunk chunk = new Chunk("print this page");
PdfAction action = PdfAction.JavaScript("app.alert('Think before you print!');", stamper.Writer);
action.Next(PdfAction.JavaScript("printCurrentPage(this.pageNum);", stamper.Writer));
action.Next(new PdfAction("http://www.panda.org/savepaper/"));
chunk.SetAction(action);
See also the C# port of the book examples.

Firefox and IE image cache

I'm having some trouble with the firefox and ie cache, on my website the user can make a query with a form, and this query returns a picture, but depending on which radio button is selected, it'll return a different picture, and it works just like that on chrome, but in IE and firefox, the same image is always returned, it only changes when i reopen the browser, can you guys give me some light on how to make this work?
Thanks to everyone, i solved my problem by putting and unique url each time i made the ajax call.
<?php $date = date("H:i:s");
echo ''; echo '<img src="web/WEB-INF/classes/lineChart.php?id='.$date.'" alt="">' ?>
Not sure the language you are using to code with, but regardless I am sure the strategy will work across the board. I pass an arbitrary value in the query string, something like a GUID or the datetime stamp. This will force a fresh load as the URL will be unique.
I use ASP.NET MVC which I then set a optional parameter in my route, which the controller method ignores. I then set my URL via JavaScript:
d = new Date();
$('.thumbnail').attr('src', $('.thumbnail').attr('src') + d.getTime());
The solution I needed was unique, so this is probably not similar to what you are trying to resolve. However, it should get the point across.
do private browsing in Firefox and see if image is changes successfully and problem is with cache memory or with the code
Given a unique can be the solution, but you have to watch the length in the string can keep growing, now, you can use this option at the begining of your code
$.ajaxSetup({ cache: false });
this will disable caching.

Resources