I have a TWebBrowser on a FireMonkey app (Android and iOS).
I'd like to be able to intercept (trap) hyperlink clicks in the TWebBrowser and do something different with them.
I've found references to working with the BeforeNavigate2 event. However, I see no way of adding a procedure for that event in the Object Inspector. And I'm not sure if that event exists for Android or iOS; or if it's just a Windows event.
Is there any way to get to intercept hyperlink clicks cross platform?
[Edit]
My ultimate goal here is to intercept a hyperlink click in the browser component and do something different with it (e.g., I'd like to spawn it off to the native browser instead).
OnShouldStartLoadWithRequest doesn't trigger on a click. Actually it doesn't seem to trigger anywhere for me. Others have had this issue (Incus J).
OnDidStartLoad does trigger; however, it appears to carry on with the page load in the background regardless of what's going on in the trigger. I can add a myWebBrowser.Stop in the trigger; however, it does not reliably work. I suspect that sometimes the page load completes before the Stop gets fired off.
Playing with OnDidFinishLoad and using the GoBack method proved awkward because the previous page would reload to the top of the page instead of what was being shown in the control (if the user scrolled).
Am I stuck trying to hack Android/iOS equivalents of TWindowsWebBrowserService as Incus J suggests in the thread I reference above?
Related
I've searched for this specific issue here on StackOverflow and the various Apple/WebKit bug reporting systems but have yet to find it specifically cited (which just doesn't seem possible).
The problem:
On our payment page we have various form fields (inputs & selects). For PCI/security purposes we have an iframe that serves the credit card number field (the iframe only has that one field - nothing else).
The issue is that for just iOS users, they sometimes cannot put the focus on the credit card number field. There appears to be 2 different, but related iOS webkit bugs. See the UPDATE below.
If they simply navigate down from one field to another, it usually works. But if they bounce around fields, they can get into the scenario where try-as-they-might they cannot get the focus into the credit card number field it doesn't look like the credit card field gets the focus (appears to be a rendering issue).
Initially we thought maybe there was JS or some invisible DIV getting into the way, but I eventually was able to create an HTML-only example to recreate the problem. (Instructions on how to recreate the issue are on the example page.) Linking to codepen requires I include some code:
<iframe src="iframe.html"></iframe>
I've consistently been able to recreate this issue on iOS 10-12 devices (an iOS 9 device didn't seem to have the problem).
For posterity I'm going to supply the work-around I came across in a separate, but semi-related WebKit bug. However, I was wondering if others out there had stumbled upon this problem and discovered other work-arounds.
UPDATE:
After digging in further I've discovered we're suffering from 2 separate bugs. The first is mostly as I describe above, but seems to be more of a rendering issue where iOS doesn't look like it's putting the focus on a field. However, if you go to the codepen example new example I setup and follow the steps, even when it doesn't look like the field has the focus, if you type the text will render correctly.
The second problem is less likely to happen but is more detrimental. It requires 3 criteria to trip:
The iframe's source has to be cross-origin
Parent page is attaching an event listener to either touchstart, touchmove or touchend (even as simple as an empty function call)
The iframe’s field is off-screen when a different field has focus and the keyboard is present.
The result of these 3 things is that the user cannot place focus on the iframe field at all (typing goes nowhere although document.activeElement shows the last parent page input having focus). Reestablishing the ability to get the focus in the iframe can be difficult, generally need to have a parent page input that can be focused while the iframe field is visible then the user can move their focus to the iframe field from there.
If any of the 3 criteria is changed (not cross-domain, no event listeners on those 3 touch events or the iframe is visible), then only the first – less-prohibitive – bug is present.
I will update my "answer" below with this realization as well.
Update 2: The new example I put up shows both bugs in action; the first page is Bug #1 with a link to the cross-origin Bug #2 example.
Problem is resolved in my environment by adding #Ryan L's suggestion document.addEventListener('touchstart', {}); in the IFrame.
This is good as it's very simple to add and is specific to the IFrame, not affecting the container page.
Problem description: cannot 'touch' (select, edit) another form field on Safari running on iDevices (phone & pad) running iOS 12. This only happens on pages in an IFrame where the container page has added some touch events. Very obscure set of conditions that are difficult to debug.
I believe I have found a fix for this frustrating little bug, and like most bugs it's a super simple fix.
All that needs to be done is to apply a the following css to the input within the iframe.
input:hover {
cursor: text
}
Here's an updated example: https://codepen.io/ryanoutloud/project/full/AEKGjj
Now as to the bug itself, the focus is actually on the intended field and any entry from the keyboard will be registered properly. Once typing begins the caret jumps into proper position. The
issue I found with the ontouchstart="" solution is that it simply removes the caret from view entirely once focus is placed on a field.
Here's the work-around I stumbled upon: add ontouchstart="" to each of the form input elements (probably selects too).
This came from one of the work-arounds provided on this WebKit bug related to outer page click events not dispatching properly to an iframe (in the context of zooming).
I have not pushed this to production yet, but initial tests seem to indicate this works. I did have to put this on both the parent & iframe form elements to fully fix the problem. I'll probably leverage JavaScript to attach this to the form fields without needing to add the property to each form element.
Open to any other suggestions or concerns with this approach.
this work for me
document.addEventListener('keydown', function(e) {
window.focus()
$(':focus').focus()
});
I am trying to make my job easier by creating simple AHK scrips to auto-fill certain forms online.
Im not really good at explaining, but hopefully someone will understand what Im saying. The problem is that this website has certain textboxes with dropdown auto-suggestions turned on, and it has a delay when selecting those textboxes. I assume when selecting textbox it is pulling data from some database which is causing delay. Now my question is. Is it possible to turn off dropdown menu on websites or even in entire browser if necessary? I really want to my script to tab-in, wright down whats needed, tab-out without delay.
Autocomplete dropdown lists are just JS scripts. So there is no way, I think, to disable them by clicking checkbox in browser settings.
First, try to disable JS completely.
Also, if only few sites are involved, you could try to find out what JS libraries are used and disable them in browser JS console.
Are you planning to do this via keypresses or via COM?
I imagine that via keypresses you could not avoid focusing the elements and triggering the information lookup.
AutoHotkey can interact with webpages on Internet Explorer using COM (Component Object Model).
COM can launch/latch onto an IE instance, detect if the page is loading/has loaded, navigate to a particular url, and set the text of web elements,
quite possibly without triggering the drop-down lists. I haven't tested if COM can disable elements, it's possible.
Also, Acc.ahk may be able to set the text of elements.
I'm wondering if there is any good way to essentially apply - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string to forms in a webview.
The result would be reacting to every typed/deleted letter in a web form.
Right now I'm using a timer that fires every .1 seconds to check the but it's not a very good solution and causes some bad behavior that appears to lock up the ability to call any other Javascript evalutations..
One way to go about this would be to "inject" some javascript code into the page, that would attempt navigation whenever the event you are interested in happens.
You'd catch and cancel that Navigation on the UIWebView, and use the navigation event as your event handler (possibly passing data in the url itself).
The series of events will be like this:
Event (e.g. change of value in a field) fires in JS.
Injected code Navigates to a certain (bogus) url.
Your app's Obj-C code will (listen to and) receive a navigation event. your code will check the url and find it is the one expected by the event. You can pass additional event data on the url itself.
The app code will cancel the navigation, so nothing actually changes on the page
Your app will react in whatever way you want to that event.
You didn't mention if you had control over the content of the web pages, so I'm not going into details on how to inject that javascript code. Let me know if that's something you want described.
I have been successful in augmenting/changing many DOM events, without actually owning the web pages that my UIWebView is navigating to, essentially giving the user a different experience when browsing these pages through my app than through a regular mobile browser.
hope that helps.
P.S. there might be an easier way using PhoneGap. I would be interested to know if that can shorten things.
I'd like to develop a voice chat application that would run inside of a web browser. My main concern is implementing push-to-talk functionality when the site doesn't have focus.
Say, for example, that the user is playing a video game, and they decide to press and hold the "C" key to indicate that they'd like to talk. I want my web application to respond to that, even though it wouldn't have focus at the time. Is this possible (using any language)?
I can't see any way of doing this without installing some client side functionality (such as an ActiveX component or similar) - a browser won't normall allow JavaScript or similar code to handle keypresses when the window is not active as this would be a security vulnerability.
It isn't necessarily impossible, but as of right now, it is.
Keyboard events target the currently-in-focus DOM element. Currently, all web browsers will remove focus from any DOM element when the browser is minimized, or when the user clicks outside of the page.
With the increased focus on web-app-support in modern browsers, this rule could theoretically change, but I haven't heard of any browser vendors considering it.
When you get a new badge on stackoverflow.com, a bar appears at the top of the screen informing you of your achievement. It sticks around until the user closes it.
I rather like that system of informing the user about new news related to the site or their account. It's fairly unintrusive, but still clearly communicates the information. Even if all users receive a notification this way, it sticks around for each user until they have acknowledged seeing it.
I'm running a system using Ruby on Rails on a PostGres database. What's the best way to implement a similar system on my setup?
Edit: Just to clarify, I'm interested both in the server side and client side of the setup.
The effect can be accomplished with jQuery and the slideDown method (http://api.jquery.com/slideDown/). Set an onClick event to make the element slideUp, hide, or hit an AJAX call to let you know that the user got the message and dismissed it.
You could set the contents of the element (I'd go with a div) via an AJAX call, or you could simply populate the div with the appropriate message when generating your page, start the div off as hidden, and then kick off the slideDown method when the page load is complete via a $(document).ready definition (http://think2loud.com/jquery-document-ready-howto/).
You could use something like the jquery popup bubble extension: http://www.farmcode.org/post/2009/04/06/jQuery-popup-bubble-extension.aspx