How can I pass a user initiated action into an iframe? - javascript

I have an audio element on a page which is currently being loaded inside an iframe with zero height and width.
I'm using a postMessage from the parent page to tell the child page to play some audio.
This is working great on desktop browsers, however I'm having some trouble on mobile browsers. (I'm testing on Chrome for Android, but I think iOS will have the same problem).
Mobile browsers require that the media play() command is triggered by a user initiated action.
In my case, the user is clicking a button on the parent page to initiate the play, but it seems that the when doing the postMessage, the browser looses track of that.
Is there any way for me to get audio to play inside the iframe without making the page inside the iframe visible to the user?

You could try to directly access the inner DOM from the outside via myIframe.document. That way you can link your JavaScript objects and call a function upon click. That direct call may work better than posting a message.
Limitations may apply according to this question: How can I access the contents of an iframe with JavaScript/jQuery?

Related

Get tab URL from page action (WebExtensions, Android)

I would like to get the URL of the current tab within a page action popup.
At first it seems obvious: Just use the tabs API. But that doesn't seem to be available on Android if I deciphering the docs correctly. So I kept looking for something else and found the onClicked event of the pageAction API.
The pageAction API seems to be listed as compatible with Android and the onClicked event is marked as supported. So that implies that it would actually return a tabs.Tab object. But does it really? Has anyone tried it?
What is the best way to retrieve the URL? I know I could just use a content script and let that run in every single tab and create a long lived messaging connection to send the URL to the page action popup whenever it is requested. But that would be very inefficient and make the code insanely complicated compared to how easy it would be using the tabs API.
Is there anything else I could do?
Current (Firefox 54 and later)
As of Firefox 54, the tabs API is available in Firefox for Android. This means you can use the normal methods available to desktop Firefox. Specifically, chrome.tabs.query() or browser.tabs.query(). However, you will need the activeTab and/or tabs permissions in your manifest.json.
chrome.tabs.query:
chrome.tabs.query({active:true,currentWindow:true},function(tabs){
//'tabs' will be an array with only one element: an Object describing the active tab
// in the current window.
var currentTabUrl = tabs[0].url;
});
browser.tabs.query:
browser.tabs.query({active:true,currentWindow:true}).then(function(tabs){
//'tabs' will be an array with only one element: an Object describing the active tab
// in the current window.
var currentTabUrl = tabs[0].url;
});
Prior to Firefox 54
If you have defined a page/browser action popup
If you have defined a popup for your page/browser action, then the onClicked event does not fire. Your popup is not passed any information when it is created/shown. Thus, you will not receive a tabs.Tab object. The normal way to obtain tab information is from tabs.query, which, as you have already determined, is not (yet) available in Firefox for Android.
The APIs available to Firefox on Android are quite limited. For what you are wanting to do, using webNavigation events to keep a record of each tab's frame 0 URL would be more efficient than a content script in every page. You could use the webNavigation.onCommitted or webNavigation.onCompleted events depending on your needs. You will need to assume that the active tab of the current window is the one which most recently had a webNavigation event, or perhaps you could also monitor webRequest events. However, any way that you do it, which tab you assume to be the current tab will just be an assumption, and will be inaccurate under some circumstances.
A more accurate URL (and active tab determination) requires using a content script
If the page that is being visited changes the tab's URL through some method that does not trigger navigation, using webNavigation events will not give you the updated URL. As you have identified, without the tabs API, the only way to be certain you have the actual current URL for the tab, when you define an actual page/browser action popup (and thus don't get a tabs.Tab object), is to inject a content script into every page. You will either need the content scripts to continuously update the URLs, or be listening with storage.onChanged for a request for that information from your background/popup script. Communication from the background/popup scripts to content scripts must be accomplished through the storage API due to not having the tabs API (i.e. no tabs.sendMessage).
Using page/browser action onClicked
An alternative, which I have not tried on Firefox on Android, would be to not define an actual page/browser action popup. If you don't define an actual popup, you receive the onClicked event (getting the tabs.Tab Object with both the active tab's ID and the URL) and then can open a pseudo-popup1.
1. The implementation of opening a a pseudo-popup in my linked answer uses the tabs and windows APIs which are both currently unavailable for Firefox for Android. It could be re-written to use the above mentioned webNavigation listener to track tab URLs and window.open() to open the window used for the pseudo-popup. Again, I have not tested this with Firefox on Android to determine that it actually works.
You can get it this way with webextensions. Take into account that if you want to debug a popup, you have to "prevent popups to be closed" (4-squares icon at the top-right of the browser's toolbox)
var activeTabPromise = browser.tabs.query({active: true, currentWindow: true});
activeTabPromise.then((tabs) => {
console.log(tabs[0].url);
});
I hope this will help you,

iPad/Safari scrolling iframe does not allow host page to scroll (the iframe itself is scrolling)

What's the Problem:
Unfortunately I must use an Iframe in a web solution (tenant scoped SharePoint hosted App with App Parts).
The iframe needs around 50% of the website's space and the space for it in the host will be programmatically blown up in size so that there will be no scrolling bars shown. It works good on every browser except Safari. In Safari the touch event seems to be caught by the iframe window and will not be forwarded to the host window. Imagine this on the iPad: in over 50% of the page the user can't scroll down the page.
Hardware I used for testing:
Windows 8.1 (touch enabled screen) with latest version of Safari (5.1.7)
iPad with iOS version 8.4.1.
What I researched/tried so far:
This has nothing to do with everything that can be solved by "-webkit-overflow-scrolling: touch;" and similar approaches. From what I understood in my research, this will make the iframe scrollable but I need to make the host window scrollable when moving the finger in the iframe area. In other Browsers the iframe for example scrolls down until the end and then starts scrolling the host window
In some post one suggested to overlay the iframe with a div (z-index: 2) and then forward the click events from this overlaying div to the Iframe window ( I do have control on this Iframe window, so I can catch events in there). The overlaying div fixed the scrolling behaviour on my testing page but not in my target application, so it's not a reliable solution. Besides that: I managed the click event to be triggered (with same approach as in 3.) but could not manage to make it click links in my iframe-page (what I need... because this is the reason why I want the clicks to be forwarded.)
Another approach was to forward the touch events from the Iframe page to the host page. I did this via postMessages, JSON-stringified event parameters and a javascript library called "jquery.simulate.js" that is used to simulate touch events. I did not manage to trigger the touchmove event correctly on the parent window (and besides that I doubt that this is really good concerning user experience and performance)
I also thought about getting the simple html from the Iframe and add it to the host page programmatically. Unfortunately SharePoint hosted Apps are hosted on other subdomains, so due to the cross-browser restrictions I think is not worthid to follow.
Another approach was pointer-action: None; - This also breaks the link functionality and unfortunately worked only on the desktop
Setting scrolling="no" (or "yes") did not have any effect nowhere (maybe because it's gone in HTML5)
So here I am stuck... and it seems that no one else in this world has the same problem as I cannot find any really working idea anywhere. But I tested around 20 different websites with iframe - and I tested with the Desktop touch and the iPad.... and I have the same problem. I could not find a single Safari-Touch-working iframe throughout all suggestions and possible solutions.
How to reproduce:
A simple
<iframe src="http://www.w3schools.com"></iframe>
embedded on any html page with long content, Safari and a touch device (similar to the ones I used for testing) should be enough to reproduce.
What I want to know:
Does anyone have the same problem?
Could you put me into the right direction? I am actually unsure which of the above mentioned approaches I should continue to go on with
Do you have a completely new idea that I could follow?
Did you test this on any other device and know it's working? (I am thinking maybe downgrading could be a solution)
Edit: (Solution Nr. 2) The overlaying div makes the page indeed also scrollable in Safari, but I could not find the correct way how to forward the click event to the child successfully (meaning: which of the event parameters are necessary to be forwarded to trigger the click event in the child window?)
Edit: Searching again and found out that you cannot create events like clicking programmatically due to security reasons. Makes sense as this will be a big security issue if you could force the user to click on your ads for example.
How can I click on specific (x,y) coordinates on a web page?

back button issue in chrome

I am facing issue with the way back button works in Chrome.
I have a application where I am displaying a form in iframe inside the parents window.
So when the user clicks on back button the behavior on IE and Mozilla is that page in iFrame loads up again.
This iFrame page refresh when the user clicks browser back button is important in my case is because we need to keep a track of users who have logged in the application and accessed that iFrame content.
Now in Chrome the behavior of back button is different. When the user clicks on browser back button the user is taken back to previous page.
I need to alter this behavior for chrome and need to refresh the content in iFrame instead of moving back to previous page.
Anyone kindly who have idea on this help me out.
PS: I cant use jQuery in application.
Regards,
Well the short answer is you can't and you shouldn't. becoz this behavior is inconsistent across different browsers and even future versions of mozilla and ie may also change it's behavior.
Still you have some alternatives to achieve this kind of behavior.
You can use HTML5's history.pushState where on hashchange event you can refresh you frame whenever you want.

parent.opener doesn't work in webview Android

I have a problem. I need to return to parent Url from Frame opened in a Android Webview.
The sequence is: Open inside Webview new frame. Select in frame options and paramters. Call in frame javascript function like _"javascript:parent.opener.jsfunction"_. Parent Web doesn't open...
I don't have access to Web. I work only in Android side.
I test Web in a firefox for Android and it works.
Need help.
By default, WebView doesn't support multiple windows. If you check, I believe the parent field actually isn't set and doesn't point to the parent window (or anything at all). The same applies to other similar fields like opener and top.
You might be able to work through this by enabling support for multiple windows and then implementing onCreateWindow in your WebChromeClient. I think there's some more you have to do, but it's been a while and I don't recall the details.
One way I've hacked around this in the past is to use setJavascriptInterface and just set the name to parent or whichever field you want. Implement the appropriate methods as necessary on your Java object. This can get a bit messy, but it works.

Continuous Background Sound

How can I implement a continuous background sound in page that doesn't interrupt when the user moves from one page to another without using iframe?
use a trick, if having frameset is not an issue for you, construct your page with a frameset and use one frame for background (no size) where you play the sound and other (full 100%x100%) where you can navidate. This has also the advantage of hidding your navigation URL leaving just the site url on nav bar.
If you are insane, you could set an event listener on the timeupdate event of the <audio> element and store the currentTime in localStorage (or a cookie). Then, when you load a page, read that value and set the currentTime again. However, I imagine writing to localStorage dozens of times per second might be bad (but I won't make any performance claims until I test it!).
However, this solution requires a mordern browser with audio and localStorage support.

Categories

Resources