Using HtmlUnit how to click (form) a button that isnt a button - htmlunit

I often encounter buttons, particularly on login forms, that seem to be a series of nested divs with a span as the final element.
These are rarely part of a form, and I assume controlled by Jvascript.
Is there away to click on these buttons such that the effect of the button's action is achieved, e.g logging into the site and the new page returned?
I have tried waiting for the javascript to load after the page has loaded thus:
HtmlPage page = webClient.getPage(someUrl);
webClient.waitForBackgroundJavaScript(6000);
then clicking on the divs and the span and nothing happens.
I am using HtmlUnit 2.36 and I am aware there are some Javascript evalutations issues.

Usually you can do something similar to this
webClient.getOptions().setThrowExceptionOnScriptError(false);
HtmlPage page = webClient.getPage(someUrl);
webClient.waitForBackgroundJavaScript(6000);
// locate your clickable element
....
buttonLike.click();
// wait until the js has done the job
webClient.waitForBackgroundJavaScript(20000);
// now get the current page content based on the current window; using
// HtmlPage myPage = (HtmlPage) buttonLike.click();
// does not work in all cases because the page content might be
// async replaced by javascript
HtmlPage myPage = (HtmlPage) webClient.getCurrentWindow().getEnclosedPage();

Related

Xamarin Shell: Redirect to different page and remove current page from nav stack

I imagine this is pretty straightforward, but I'm struggling to make sense of how to do it via the documentation...
I've got a tab page, that is opened from a flyout item.
The tabs for this page are dynamically loaded from saved data in the code behind, and all works exactly as expected.
However, in the scenario when there is no saved data (and thus, no tabs) I want to redirect the user to a different page, and crucially, not be able to navigate back to this tab page (but allow going back to the page they were initially on BEFORE they navigated to the tabbed page)
I've got a method in initalize for the tabbed page that, if it doesn't have any saved data, attempts to do this. I started with:
Shell.Current.Navigation.PopAsync();
Shell.Current.GoToAsync(nameof(AddNewDataPage));
which navigated to the add page, but pressing the back button just resulted in the add page being shown again, over and over.
I then tried:
Shell.Current.Navigation.PopToRootAsync();
Shell.Current.GoToAsync(nameof(AddNewDataPage));
which did the same.
So next I went with trying to navigate backwards:
Shell.Current.GoToAsync("../" + nameof(AddNewDataPage));
which showed the right page again, but now the back button doesn't work
Next, I went with trying an absolute route:
Shell.Current.GoToAsync("//HomePage/" + nameof(AddNewDataPage));
which worked... sort of.
The first time the user clicks the flyout for the tabbed page, it all works great. back button takes you to the home page etc... but the second and subsequent times the user clicked the flyout, they navigate to the tabbed page and my LoadData method isn't called.
I assumed this is because the tabbed page is still loaded, so I added:
protected override void OnAppearing()
{
LoadData();
}
Now, when the user clicks the flyout for the second and subsequent times, they navigate to the HomePage page instead of the AddNewDataPage page (an improvement, I guess?)
So, now I'm at a loss.. it seems like this should be really simple, but I can't figure it out.
You can try this.
//route The route hierarchy will be searched for the specified route, upwards from the current position. The matching page will replace the navigation stack.
https://learn.microsoft.com/nl-nl/xamarin/xamarin-forms/app-fundamentals/shell/navigation?WT.mc_id=friends-0000-jamont#relative-routes
await Shell.Current.GoToAsync($"//{nameof(AddNewDataPage)}");
https://www.youtube.com/watch?v=ylbgWHB_gMI&t=703s&ab_channel=JamesMontemagno
An explanation about relative routes.
May I don't understand your problem clearly. But I created a simple with the flyout shell app.
At first, it seems that the construction method of the content page will jut call once which the page shows first time. So I put the following code into it. Such as:
public ItemsPage()
{
InitializeComponent();
BindingContext = _viewModel = new ItemsViewModel();
Shell.Current.Navigation.PopAsync();
Shell.Current.GoToAsync(nameof(NewItemPage));
}
And then when the app got into the ItemsPage first time, it will get into the NewItemPage. User can add new item here. After that, when I clicked the back button, I will get into the ItemsPage back without it's construction method called. So you can't add the LoadData(); in it.
You can put it into the OnAppearing method. Such as:
protected override void OnAppearing()
{
//LoadData();
if (_viewModel.Items.Count < 8)
{
Shell.Current.Navigation.PopAsync();
Shell.Current.GoToAsync(nameof(NewItemPage));
// then add two item in the NewItemPage
}
else {
base.OnAppearing();
_viewModel.OnAppearing();
}
}
This will get the same effect as above. I also try to move the Shell.Current.Navigation.PopAsync();. The result is same. It will get back to the ItemsPage when you clicked the back button in the NewItemPage after you add two item.
which navigated to the add page, but pressing the back button just resulted in the add page being shown again, over and over.
You may just need a if() to judge the condition the app need to go to the AddNewDataPage with skipping the tab page.

JSF Command button F param goes missing on AJAX re-render of button - Workaround ActionListener

I am facing - and not for the first time i believe - JSF composite component re-render pain.
The issue I am facing sounds like it is pretty much the same as:
https://forum.primefaces.org/viewtopic.php?t=27870
Essentially I am reconverting an application from full page navigation to ajax navigation, to avoid reloading javascripts etc...
So this application has a bottom navigation menu, where each button is essentially composite component
composite:implementation
Based on the primefaces
p:commandButton
These buttons used to be non ajax, define the attribute action and return as output of the action the new XHTML page to navigate into.
You would get the full page and that would be it.
Now if we enable ajax based navigation, we instead get a nice little ajax p:commandd button.
<myTagLib:commandButton id="btn_#{pl.newPageLinkKey}" title="#{i18n.static[pl.newPageLinkKey]}"
action="#{box001.navigateToPageAjax}"
disabled="#{box001.selectedBoxPageLink eq pl.pageLink ? true : false}"
icon="#{box001.getIconByKey(pl.newPageLinkKey)}" value="#{i18n.static[pl.newPageLinkKey]}"
update=":pageForm:pageTitle :pageForm:footer-main :popupDialogRegion :pageForm:MainPageContent"
rendered="#{useAjaxPageNavigation}"
>
<f:param name="pageLink" value="#{pl.pageLink}" />
</mytaglib:commandButton>
Something along these lines.
So the first tive we navigate to this SINGLE page application and see our menu being rendered, if we go debug what the command button looks all nice and dandy.
The onclick action is all setup do a super nice ajax request with parameters...
PrimeFaces.ab({
s:"pageForm:mainMenuButtonsTouchBoxFramework:btn_controls:confirmSubmit",
u:"pageForm:pageTitle pageForm:footer-main popupDialogRegion pageForm:MainPageContent",
onco:function(xhr,status,args){boxFrameworkHelperJavascript.updateHeadPageTitle('Control / Events'); ;},
pa:[{name:"pageLink",value:"/blalallaba/WHATEVENEPAGE.xhtml"},{name:"pageLinkDummyValue1",value:"dummtValue001"}]
});
return false;
And these command buttons exist in hundreds of pages and they work perfectly 99 percent of the time.
But we see on complex pages with several layers of templates that the JSF composite components sometimes sart showing off arifacts on re-rendering...
So what comes next is the, pain.
We do our click on the button.
On the server side
FacesContext fc = FacesContext.getCurrentInstance();
Map<String, String> params = fc.getExternalContext().getRequestParameterMap();
String pageLink = params.get("pageLink");
Is looking good.
But then... Re-render disaster.
The menu area, being updated :pageForm:footer-main, comes back with button looking selected. All the mnu buttons are there.
But voila, the problem is that our onclick event this time around is poor poor...
PrimeFaces.ab({
s:"pageForm:mainMenuButtonsTouchBoxFramework:btn_controls:confirmSubmit",
u:"pageForm:pageTitle pageForm:footer-main popupDialogRegion pageForm:MainPageContent",
onco:function(xhr,status,args){boxFrameworkHelperJavascript.updateHeadPageTitle('Control / Events'); ;}});return false;
See the difference between the two on clicks?
The PArguments are gone.
The composite:insert children our composite component is ignored on the re-rendering of the area.
<p:commandButton id="confirmSubmit"
style="display:none;"
ajax="#{cc.attrs.ajax}"
async="#{cc.attrs.async}"
global="#{cc.attrs.global}"
immediate="#{cc.attrs.immediate}"
oncomplete="#{func:object(cc.attrs.oncomplete)}"
onerror="#{func:object(cc.attrs.onerror)}"
onstart="#{func:object(cc.attrs.onstart)}"
onsuccess="#{func:object(cc.attrs.onsuccess)}"
partialSubmit="#{cc.attrs.partialSubmit}"
process="#{func:object(cc.attrs.process)}"
update="#{func:object(cc.attrs.update)}"
type="#{func:object(cc.attrs.type)}">
<composite:insertChildren/>
</p:commandButton>
Work around?
Yes... there is one.
A decent one luckily.
We can instead of make use of the attribute actionListener instead of action.
And we get away with this...
Why because instead of being dependent on having a proper ajax request to the server with all request parameter specified we get the parameter from the Server side view structure.
That is :
public void navigateToPageAjaxActionListener(ActionEvent actionListenerEvent) {
// (a) We use an action lister because we have problems with the composite component if we render it when we
// navigate from page to page
UIComponent component = actionListenerEvent.getComponent();
UIParameter param = (UIParameter) component.getChildren().get(0);
String pageLink = (String) param.getValue();
Not pretty and also not easily reproducible.
There are many pages where the re-rendering of such buttons do not corrupt the parameters.
Is this a known issue?
Is it a primefaces issue or a a JSF version issue.
JSF 2.2.8-35.jar.

jQuery Mobile: javascript breaks when after loading a page from ajax

So I've decided to use the jQuery Mobile framework to build my new mobile website. It has this feature of loading any local href link by ajax, which is great. But the new page that loads doesn't respond to any of the javascript. I've got a home page and page 2, both of which have the same html layout which a few changes in the content, I'll give an example.
I have made a navigation menu that slides in from the left and pushes the main content to the right. When I click on a page link, it loads the new page through ajax, but then on the new page, if I click the menu button, jQuery doesn't pick this up and so nothing happens (the menu doesnt slide out).
$(document).ready(function() {
$( ".menu-trigger" ).click(function() {
console.log("1")
if ($( 'nav' ).hasClass('navTransform')) {
console.log("2")
$( 'nav' ).removeClass('navTransform');
$( 'article' ).removeClass('articleTransform');
}
else {
console.log("3")
$( 'nav' ).addClass('navTransform');
$( 'article' ).addClass('articleTransform');
}
});
});
This jQuery script is in a seperate .js file thats included in the header of both the pages. I know the script works normally because when i refresh the page, the menu trigger works. Is there a known work around for this?
The workaround for this is to use appropriate jQM handler pageinit() instead of jQuery ready handler.
pageinit = DOM ready
One of the first things people learn in jQuery is to use the
$(document).ready() function for executing DOM-specific code as soon
as the DOM is ready (which often occurs long before the onload event).
However, in jQuery Mobile site and apps, pages are requested and
injected into the same DOM as the user navigates, so the DOM ready
event is not as useful, as it only executes for the first page. To
execute code whenever a new page is loaded and created in jQuery
Mobile, you can bind to the pageinit event.
So, your code might look like this:
$(document).on("pageinit", "#page1", function(){
//Your init code for page 1 goes here
});
$(document).on("pageinit", "#page2", function(){
//Your init code for page 2 goes here
});

Is there a way to print html source without having it displayed in a window or tab?

So I have this situation:
I perform an ajax post to a controller action that returns me some complete html source (i.e. if the result was viewed in a browser and you right-clicked and selected view source, all of that is what gets returned).
Now I want to be able to print that html source as if was being displayed in a browser (i.e. not the markup but what a user would actually see if it was being displayed in a browser).
This must be done without opening a new tab or window or popup window. Is it possible? And if so how?
Thanks
How about with a temporary, invisible iframe?
var iframe = document.createElement('iframe');
iframe.style.display = 'none';
document.body.appendChild(iframe);
iframe.contentDocument.open();
iframe.contentDocument.write(html_source_here);
iframe.contentDocument.close();
iframe.contentWindow.print();
document.body.removeChild(iframe);
Yes, You can do it by creating a DIV and add the HTML by calling the innerHTML function.
document.getElementById('yourNewDIV').innerHTML = htmlReceived;

Modifying main Activities grid view in CRM 4.0 using JavaScript

I have a task to change envelope icons on the main Activities view page (Work Place, My Work -> Activities) for every row in the grid, depending on the custom status of the row in crm 4.0. I need to do it using JavaScript. Does anybody know if there is a way to do that and where should the JavaScript code be placed? I am assuming that I need to intercept grid onLoad event, go through the grid, check the condition and flip the url of the icon. But I cannot figure out how to hook into that event...
Thanks very much!
I got several very useful advices and here is what I got so far.
1. I added SiteMap to load a custom page, instead of default one (/workplace/home_activities.aspx)
2. Here is the code of the custom page, placing onreadystatechange in the html was the only way I could get this function to run. Do not know why.
HTML>
HEAD>
TITLE>
script language="javascript" type="text/javascript">
function Run()
{
var objIframe = getIframe();
if(objIframe.readyState == "complete")
{
var docFrame = objIframe.contentWindow.document;
var grid = docFrame.getElementById("crmGrid");
var allRecords = grid.InnerGrid.AllRecords;
for(var i=0; i
function getIframe()
{
return document.getElementById("wraperActivitiesFrame");
}
/script>
/HEAD>
body >
iframe id="wraperActivitiesFrame" src="/workplace/home_activities.aspx" WIDTH="100%" HEIGHT="100%" onreadystatechange="Run()">
/HTML>
The issue I am having now is that the function does not run again when I try to page the grid. I have 2 pages of Activities; when the page loads for the first time - I have my alert boxes, but when I click on "page 2" arrow - nothing happens. Why??? What I am doing wrong?
You kinda can hook into that event. You create a "wrapper" HTML page that you load in CRM instead of the default activities grid via Sitemap. This wrapper contains a full-size IFrame in which you load the actual grid, and in the IFrame's onreadystatechange handler (for readyState == 4), you traverse the grid's DOM (jQuery might make this a little easier, but I haven't used jQuery much myself) and do whatever changes you need to do (that means the JavaScript goes within the wrapper HTML page). If you call this via setInterval and put a try-catch around it, this will even be safe against grid refreshes and browsing through the pages.

Resources