I am using HTMLAjaxCommandButton with methodexpression set for action. When this button is clicked, corresponding action gets invoked but what I'm trying now is to submit the form before the binded method gets invoked. For that purpose, I was using setOnClick method of HTMLAjaxCommandButton to provide Javascript for form submission. This is working fine in firefox but has issues in Chrome. Reason being action expression also gets converted to Ajax call present in onClick method on Button. So, effectively now we have two methods getting called up from onClick. Chrome do not like this!
Anyone has idea about it or a better way to deal with this scenario.
Issue is resolved. I removed setAjaxSingle and setImmediate for HtmlAjaxCommandButton. Now, everything works fine. We don't need to have javascript for form submission.
Related
I have this page where an angularjs modal-content popup, in there i fill up some fields and click save. After save is initiated, popup should dissapear an event should happen and so on.
My selenium test does all that perfectly except that when it clicks on the save button, popup dissapears but no event is triggered or saved so when i open up the window again everything is empty. I've tried stuff that i know with selenium and it still doesn't work. Can anyone help me out here?
This is the save button:
<button class="save-button" data-ng-click="onSettingsSave()" ng-hide="readOnlyMode || !canSave()">Save</button>
Stuff i've tried:
var saveButton = driver.FindElement(By.CssSelector("button.save-button"));
saveButton.Click();
var saveButton = driver.FindElement(By.XPath(saveXpath));
saveButton.SendKeys(Keys.Enter);
((IJavaScriptExecutor)driver).ExecuteScript("arguments[0].focus();",saveButton);
((IJavaScriptExecutor)driver).ExecuteScript("arguments[0].click();",saveButton );
Try force clicking the element using pure JS:
driver.execute_script("arguments[0].click();", yourElement)
You can't use $ as a shortcut for document.querySelector in a script like that.
driver.ExecuteScript("document.querySelector('#base_element_id div input').click()");
Also this probably won't trigger an onClick in react / angular
Like the OP I have tried everything I can think of to get Selenium to trigger client side javascript events. I've seen some posts across the web of people having partial success where it randomly works; in my case it never works.
Selenium does successfully trigger the browsers primary click action, be it checking a checkbox or pressing a button, but it does not trigger any attached client side javascript events.
Both the native element.Click() method in selenium, and the abstracted ExecuteScript with arguments method of clicking as suggested by #csaladenes have the same result.
The only solution I have found so far is to use pure JS through that same ExecuteScript method; basically avoid the overload with params selenium can embed.
driver.ExecuteScript("$('#base_element_id div input').click()");
In my case I am using the JQuery that is already on my page to make locating the element easier, but any form of truly pure JS should do the same thing.
EDIT:
After some additional testing, it turns out that my "fix" really did nothing. However, performing the same click more than once did cause the client side events to fire.
In my case I am checking a checkbox, so I needed to perform the click 3 times to leave it in the correct state and still have the client side events run.
This is very odd, and definitely needs some more work to figure out where the issue is at that makes this necessary.
Edit 2:
I think I have finally found a solution, and at least partial answer, that does not make me cringe.
It seems as though Selenium has an issue where sometimes it "loses" the focus of the browser. Considering how consistent and repeatable my issue is I don't think focus is the only problem in my case, however the solution works pretty well.
I was able to get the immediate parent of my checkbox, which was a div element, click that first to return focus to the page, then click the checkbox. After that sequence of events the client side events worked correctly.
I had problem triggering server side button click events so I found a solution on the net that I should do something like
<input type="submit" name="button" id="loginButton" value="Submit"
class="button-orange" alt="Register" title="Register" runat = "server" onclick ="this.disabled=true;__doPostBack('loginButton','')"/>
I did it, and it worked, but I would like to know what is going on!
Check this article:
Understanding the JavaScript __doPostBack Function
This method is used to submit (post back) a form to the server and allows ASP.NET framework to call appropriate event handlers attached to the control that raised the post back.
You usually (in simple scenarios) don't use the method directly - it is internally used by the controls you drop on the page.
The parameters passed to this function are stored in a hidden field and picked up by ASP.NET framework on the server-side in order to find the control that raised the post back.
simply said, it is used mainly by controls with AutoPostBack property
http://www.dotnetspider.com/resources/189-AutoPostBack-What-How-works.aspx
if you want to implement autopostback for your custom control, then you need to implement IPostBackDataHandler
The solution might be working but it's not a real fix.. better way will be to find why the button events are not triggering and fix the core of the problem.
Now to answer your questions.. PostBack is the term used to describe when the form is being submitted (posted) back to the same page. Simple as that.
Ordinary submit button would have been enough, but part of PostBack is the ability to identify which control triggered it, meaning what button or link was clicked.
To do such a thing ASP.NET is automatically adding hidden fields to the form and when clicking on element that should cause PostBack, JavaScript code is used to update the values of those hidden fields to the proper values indicating what was clicked - the argument you pass.
The name Microsoft chose to give to the JS function doing the above is __doPostBack - it's just a name of a function, ordinary JavaScript function that ASP.NET automatically writes to the browser.
Hope things are bit more clear now.
I was thinking of forcing an onblur handler to run by calling the element's blur method. But then, I thought it wouldn't work, because I remembered that calling submit on a FormElement does not cause its onsubmit method to be run.
After some experimentation, I found that calling blur does cause the element's onblur handler to get called. This seems very inconsistent, not that it surprises me (this is JS after all). Still, if there's a good reason for this, I'd like to know. Is there a good reason to call the handler in the case of blur but not submit?
I agree it seems inconsistent. My take is that OnSubmit behavior has a ton of legacy baggage because much of its functionality was designed so that people could code right inside of form elements. To this end onsubmit was used to validate input without cracking open a source editor or javascript file. My guess is that when they coded this behavior (a long time ago), this seemed wise because once you are in javascript the programmer can easily validate the input themselves so the automatic check isn't necessary. Seems like an oversight to me.
This following website on quirksmode specifically warns of this, so clearly many people are being confused by this.
http://www.quirksmode.org/js/forms.html
When I use AJAX for part of my page, such as a commentbox, in the reloaded box no JavaScript works. e.g. like cutetime or whatever. So I guess I have to reload the cutetime command (in every reload of the commentbox)
It works, but I think I have the cutetime command twice. If I have a confirm box or anything other, I get the confirm box or the add command twice.
I'll try to describe it in one sentence:
I need a way to get JavaScript working in a reloaded AJAX-Box.
P.S.: I think there is a very easy way because everybody uses it :)
If you replace an element anything attached to it is lost.
When using jQuery, you can avoid this issue by using live events. However, this doesn't work for plugins where you don't attach events. In that case you need to call whatever function enables something on your element again when replacing it.
Safari has a feature to prompt you if you're sure you want to close/refresh the page on which there are some forms which you typed into. This is useful in most cases, but in this case it's bugging me.
I'm hijacking the "submit" event on some forms and sending them to the server via XMLHttpRequest. However, Safari doesn't know that, so when I want to close the tab it displays that damn warning that form values have changed.
I know how to turn it off in OS X and I don't want that. I want to turn it off on this specific web page I'm building, and for all users with Safari. Surely there must be some JavaScript way—I don't care if it's proprietary to webkit.
Update: I tried this, but to no effect. Safari first warns about unsaved data, then triggers the "beforeunload" event.
if (Prototype.Browser.WebKit)
window.addEventListener('beforeunload', function(e) {
forms.invoke('reset')
})
I don't know Safari that deeply, but if you just submit the values and don't need them afterwards, why not simply reset the form? I would expect no change = no warning.
If you don't want to reset it straight away, you could even try hooking the reset command to the unbeforeunloadevent to do it when you close the page. Whether that works depends on when Safari checks for the changed form, though - before or after calling unload.
That's application behavior, so there mustn't really be any JavaScript way of modifying it. Every WebKit specific feature is documented pretty well, and I've never seen anything of the sort. Just clear your form fields if you're really that worried about it.
https://developer.apple.com/library/content/documentation/AppleApplications/Reference/SafariWebContent/Introduction/Introduction.html#//apple_ref/doc/uid/TP40002079-SW1
https://developer.apple.com/library/content/documentation/AppleApplications/Reference/SafariHTMLRef/Introduction.html#//apple_ref/doc/uid/30001261
The only way I see left around this is having a form consisiting of hidden inputs only, and a bunch of input elements that are not associated with the form. On submit, you fetch the values from the the elements, make your request and reset the internal form. You could even do the moving of the input elements out of the form via DOM so it would even degrade gracefully.
A lot of work and a bit hacky, but as far as I can see the only option if you can't change the workflow.
Try removing the action and method attributes from your form tag with Javascript after you bind submit. This way, Safari should no longer see the inputs as being part of a real form.