Trigger synthetic ExtJS event from jQuery or vanilla javascript event - javascript

There exists a website implemented with ExtJS 3.1.
I want to pre-fill some fields automatically. The problem is, that some fields are not validated by ExtJS when automatically filling them.
I can trigger the validation by firing ExtJS's blur event:
field.fireEvent('blur', field);
However, I don't want to do this. I want that validation to be triggered by a normal event triggered via jQuery:
$field.blur();
What I am asking here is the following:
How to trigger the blur event of a textbox in the same way the browser does it, so that also ExtJS's event handlers run?
BTW: The reason why I don't want to manually fire the ExtJS event is simple: This solution seems to work for ExtJA 3.1 but no longer for 4.2 and I don't want to write special handling code for every version of ExtJS.
If you want to play around a little bit:
Here is the URL: https://www.pantaenius.com/en/service/login/request-a-quote.html?utm_source=http%3A%2F%2Fwww.pantaenius.com%2Fen%2Famerican-yacht-insurance.html&utm_medium=direct&domain_segment=33
Open it in Chrome, open Chrome's developer console and paste the following text:
delete console.log
var $city = jQuery('#ext-comp-1080');
var city = Ext.ComponentMgr.all.filterBy(function(x) { return x.isXType('combo') && x.id==='ext-comp-1080'; }).items[0];
var blurEventFireFn = city.events.blur.listeners[0].fireFn;
city.events.blur.listeners[0].fireFn = function(field) { console.log('ExtJS blur fired!'); blurEventFireFn(field); };
When you click in the City field and then in some other field, you will see the output ExtJS blur fired! in the console. You will see the same output when you execute city.fireEvent('blur', city);. However, you won't see that output when you execute $city.blur();, $city.trigger('blur'); or
var event = document.createEvent('HTMLEvents');
event.initEvent('blur', true, true);
$city.get(0).dispatchEvent(event);
Any ideas how to create this bridge between normal events and ExtJS events would be greatly appreciated.

Simulating the native event with your bit of code does work (in non-IE browsers):
var event = document.createEvent('HTMLEvents');
event.initEvent('blur', true, true);
$city.get(0).dispatchEvent(event);
However you should avoid the problem rather than giving it a weird cure, by using the validator of the field instead of a blur event listener. This way, the setValue method of the field will trigger its validation...
If you're really stuck with it, instead of adding a (probably fragile) layer of complexity by simulating events, I would just call the onBlur method of the fields directly. That's the handler that is added to the DOM by Ext. It is present in 3.x and 4.x, and it doesn't rely on specific browsers...

Related

javascript function "document.getElementById()" does the work as expected

I am working on a browser recording test, in which I am entering a value into an Input field with an
auto search trigger functionality.
document.getElementById('InputFieldWIthSearchFunctionality').value = "Saurav";
But the search is not triggered if I set the value to the field as above.
Kindly help.
Just setting the value will not call the onchange and/or oninput event listeners of the input field. The auto search trigger is probably listening to this event.
You can dispatch both of these events manually to the input field:
const elem = document.getElementById("InputFieldWIthSearchFunctionality");
// create onchange event
const onchangeEvent = document.createEvent("HTMLElements");
onchangeEvent.initEvent("onchange", false, true);
// create oninput event
const oninputEvent = document.createEvent("HTMLElements");
oninputEvent.initEvent("oninput", false, true);
// dispatch events to the input field
elem.dispatchEvent(onchangeEvent);
elem.dispatchEvent(oninputEvent);
This definitely works in Chrome and all browsers using Chromium, I did not test any other browser, that would be up to you.
Information about manually dispatching events taken from this answer: https://stackoverflow.com/a/2856602/7846567
Think of it this way... by setting the value directly using JS, you are shortcutting the typical UI that a real user would use thus causing this issue. JS should be used sparingly (almost never) if you are trying to write tests that act like a user would and now you can see why.
In Java you would do this
driver.findElement(By.id("InputFieldWIthSearchFunctionality")).sendKeys("Saurav");
which would cause the search to fire in your case.

onChange event firing incorrectly after being loaded programmatically

I have an APEX application where there are many drop down items. I've bound change event handlers to them using the bind function of jQuery.
Now when I load the content of a drop-down programmatically using $('#ELEMENT').trigger('apexrefresh'), the drop-down reloads but the change event handler fires automatically.
How do I prevent this from happening? I tried avoiding binding the event handler using bind and instead adding the onChange attribute to the element. The incorrect behaviour was still present.
Here is the skeletal code:
$(document).ready(function()
{
$('#P7021_MSG_DEF').bind('change', function(e)
{
console.log('bound function onChange() msg_def');
updateStartWord();
}
);
});
function updateMsgDef()
{
console.log('function updateMsgDef() ');
$('#P7021_MSG_DEF').one('apexafterrefresh', function()
{
if( $x('P7021_RESTORE_CHK').value == 'Y')
{
setdefault('P7021_MSG_DEF', vJson.msg_def);
}
updateStartWord();
}
).trigger('apexrefresh');
}
In the above code, when the updateMsgDef is called from another function the function updateStartWord() gets called twice - once by updateMsgDef() itself and again by the onChange handler that was bound to P7021_MSG_DEF item.
If anyone could help on this?
Calling $('#ELEMENT').trigger('apexrefresh') is going to trigger the change event. Short of going back to the drawing board altogether, the solution is going to be a hack whatever you do. You could poke about in (and quite possibly break) Oracle's javascript. You could write your own AJAX to populate the select list.
The easiest way might be to check in your onChange event which element currently has focus, eg:
onChange = "if($( document.activeElement).attr('id')=='YOUR_PAGE_ELEMENT')
{ $( document.activeElement).trigger('apexrefresh'); };"
If the user has changed the select list, it should still have focus. There's no guarantee that will work in all browsers, but I think it should be ok in current Chrome and IE versions.
I've been in a similar situation to yours, and have come to accept that if the page logic is too complicated to implement using DAs, maintaining it is likely going to be a nightmare whatever happens. Much as I like "proper" programming, Apex is really all about the declarative controls.

Deleting the text from text fields by triggering the keypress event for backspace

I want to delete data from a content-editable div, on click event of a button. I want this button to actually behave as backspace button. is that feasible ? Expecting sample code for this.
I found this.
But it is not working for me . can anyone help please ?
I tried this also:
I tried the keypress events first to manually trigger the event for backspace :
var press = jQuery.Event("keyup");
press.ctrlKey = false;
press.which = 8;
press.keyCode = 8;
$("#myDiv").trigger(press);
It triggers the event but not actually updating.
An event triggered by Javascript (with element.dispatchEvent or jQuery's trigger) is called "untrusted" and is sent to the event handler with Event.isTrusted set to false. The documentation on this is near-impossible to find; look at www.w3.org/TR/DOM-Level-3-Events/#h3_trusted-events. What this means is that the default action for that event will not occur: keypress events do not enter text. The element never sees your backspace event. The handlers that you attached in Javascript will work, just not the built-in effects.
Honestly, I do not see what the security advantage of this is, but that's the way modern browsers work.
I have a library that simulates keypresses; see my sendkeys plugin.
The code is on github: get the files bililiteRange.js and jquery.sendkeys.js.
After including those two files, you can do: $("#myDiv").sendkeys("{backspace}") and it should work.

DOM problem with click initiating a focusout event on a different input

I have an <input type=text> with focusout event handler
I have a <button> with click event handler
Focusout checks whether format in input box is correct. It does so by testing input value against a regular expression. If it fails it displays a message (a div fades-in and -out after some time) and refocuses my input by calling
window.setTimout(function() { $(this).focus(); }, 10);
since I can't refocus in focusout event handler. focusout event can't be cancelled either. Just FYI.
Click collects data from input elements and sends it using Ajax.
The problem
When user TABs their way through the form everything is fine. When a certain input box failes formatting check it gets refocused immediately after user presses TAB.
But when user doesn't use TAB but instead clicks on each individual input field everything works fine until they click the button. focusout fires and sets time-out for refocusing. Since time-out is so short focusing happens afterwards and then click event fires and issues an Ajax request.
Question
I have implemented my formatting check as an independent jQuery plugin that I want to keep that way. It uses .live() to attach focusout on all input fields with a particular attribute where format regular expression is defined.
Data submission is also generic and I don't want to make it dependant on formatting plugin. They should both stay independent.
How can I prevent click event from executing without making these two plugins dependant?
Example code I'm fiddling with
After some searching I've seen that all major browser support document.activeElement but I can't make it work in Chrome. FF and IE both report this being the active element, but Chrome always says it's BODY that is active even though click fired on the button element.
Check this code http://jsfiddle.net/Anp4b/1/ and click on the button. Test with Chrome and some other browser and see the difference.
You could use a flag...
Live demo: http://jsfiddle.net/Anp4b/4/
So your question is:
How can I prevent click event from executing without making these two plugins dependent?
Well, you obviously cannot prevent the click event. If the user wants to click the button, he will, and the click event will trigger. There's nothing you can do about that.
So the answer to the above question is: You cannot.
Based on the current conditions, you have to - inside the click handler - retrieve the validation result, and based on that result, decide if form submission should or should not occur.
JS Code:
$("#Name").focusout(function(){
var that = this;
valid = this.value.length ? true : false;
!valid && window.setTimeout(function() {
$(that).focus();
}, 0);
});
$("#Confirm").click(function(e) {
if ( !valid ) { return false; }
e.preventDefault();
alert('AJAX-TIME :)');
});
HTML Code:
<input type="text" id="Name">
<button id="Confirm">OK</button>
Is there are reason you use .focusout instead of .blur?
Using a flag is a good idea, but I would rather use a class on the element. By using classes to determine the state you can also style it accordingly. Here's my example based on your fiddle.
Another solution that hopefully gives the result you are looking for.
1) Create a named click handler:
var clickHandler = function(e){ /** submit form or whatever you want to do**/ };
$("button").click(clickHandler);
2) Add the following to the focusout event when it's failing validation:
$("button").unbind("click", clickHandler).one("click", function(){ button.click(clickHandler); return false;});
You can find an example of this here.

If an onfocus event handler is added with attachEvent, how can I access it?

Background:
I'm writing a script (in VBA, if that matters) to input data into a web-based system. Some of the system's validation is only run when a field is focused, so I've been calling .Focus on the fields in VBA to force it to run. But that steals the systemwide focus; rather annoying if I am doing anything else while the job is running.
I want the validation to be triggered without stealing the focus. So I am trying to directly call whatever event handler is registered to the input field.
Problem:
All event handlers in the web app are added with element.attachEvent(), which means the onfocus and onblur properties (which I believe are the ones I want) are not set.
Is there any way to retrieve the handlers without resorting to even more evil hacks?
Alternatively, is there a better way to do this without having to find the event handlers? I'm pretty new to JavaScript, so I could easily be missing something.
Edit: Is there any other reason the focus might be stolen by the VBA code? I cannot find any other references to .Focus or even AutoIt's WinActivate, but even with the suggestions here, the problem still occurs.
The whole VBA part aside, you appear to have a reference to an element, so you can try calling element.focus() or element.blur() to trigger the focus and blur events respectively.
Take a look at this post.
This function should fire the event for you:
function fireEvent(element,event){
if (document.createEventObject){
// dispatch for IE
var evt = document.createEventObject();
return element.fireEvent('on'+event,evt)
}
else{
// dispatch for firefox + others
var evt = document.createEvent("HTMLEvents");
evt.initEvent(event, true, true ); // event type,bubbling,cancelable
return !element.dispatchEvent(evt);
}
}
Do you have access to the application you are interacting with (to be able to add this function)?

Categories