MOBILE-2235 iframe: Fix clicks in deep iframe links
parent
56faa66adc
commit
69e4fdd036
|
@ -319,58 +319,86 @@ export class CoreIframeUtilsProvider {
|
||||||
while (el && el.tagName !== 'A') {
|
while (el && el.tagName !== 'A') {
|
||||||
el = el.parentElement;
|
el = el.parentElement;
|
||||||
}
|
}
|
||||||
if (!el || el.tagName !== 'A') {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const link = <HTMLAnchorElement> el;
|
|
||||||
|
|
||||||
const scheme = this.urlUtils.getUrlScheme(link.href);
|
const link = <CoreIframeHTMLAnchorElement> el;
|
||||||
if (!link.href || (scheme && scheme == 'javascript')) {
|
if (!link || link.treated) {
|
||||||
// Links with no URL and Javascript links are ignored.
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (scheme && scheme != 'file' && scheme != 'filesystem') {
|
// Add click listener to the link, this way if the iframe has added a listener to the link it will be executed first.
|
||||||
// Scheme suggests it's an external resource.
|
link.treated = true;
|
||||||
event.preventDefault();
|
link.addEventListener('click', this.linkClicked.bind(this, element, link));
|
||||||
|
}, {
|
||||||
|
capture: true // Use capture to fix this listener not called if the element clicked is too deep in the DOM.
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const frameSrc = element.src || element.data,
|
/**
|
||||||
frameScheme = this.urlUtils.getUrlScheme(frameSrc);
|
* A link inside a frame was clicked.
|
||||||
|
*
|
||||||
|
* @param element Frame element.
|
||||||
|
* @param link Link clicked.
|
||||||
|
* @param event Click event.
|
||||||
|
*/
|
||||||
|
protected linkClicked(element: HTMLFrameElement | HTMLObjectElement, link: HTMLAnchorElement, event: Event): void {
|
||||||
|
if (event.defaultPrevented) {
|
||||||
|
// Event already prevented by some other code.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// If the frame is not local, check the target to identify how to treat the link.
|
const scheme = this.urlUtils.getUrlScheme(link.href);
|
||||||
if (frameScheme && frameScheme != 'file' && frameScheme != 'filesystem' &&
|
if (!link.href || (scheme && scheme == 'javascript')) {
|
||||||
(!link.target || link.target == '_self')) {
|
// Links with no URL and Javascript links are ignored.
|
||||||
// Load the link inside the frame itself.
|
return;
|
||||||
if (element.tagName.toLowerCase() == 'object') {
|
}
|
||||||
element.setAttribute('data', link.href);
|
|
||||||
} else {
|
|
||||||
element.setAttribute('src', link.href);
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
if (scheme && scheme != 'file' && scheme != 'filesystem') {
|
||||||
}
|
// Scheme suggests it's an external resource.
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
// The frame is local or the link needs to be opened in a new window. Open in browser.
|
const frameSrc = (<HTMLFrameElement> element).src || (<HTMLObjectElement> element).data,
|
||||||
if (!this.sitesProvider.isLoggedIn()) {
|
frameScheme = this.urlUtils.getUrlScheme(frameSrc);
|
||||||
this.utils.openInBrowser(link.href);
|
|
||||||
} else {
|
// If the frame is not local, check the target to identify how to treat the link.
|
||||||
this.sitesProvider.getCurrentSite().openInBrowserWithAutoLoginIfSameSite(link.href);
|
if (frameScheme && frameScheme != 'file' && frameScheme != 'filesystem' &&
|
||||||
}
|
(!link.target || link.target == '_self')) {
|
||||||
} else if (link.target == '_parent' || link.target == '_top' || link.target == '_blank') {
|
// Load the link inside the frame itself.
|
||||||
// Opening links with _parent, _top or _blank can break the app. We'll open it in InAppBrowser.
|
|
||||||
event.preventDefault();
|
|
||||||
this.utils.openFile(link.href).catch((error) => {
|
|
||||||
this.domUtils.showErrorModal(error);
|
|
||||||
});
|
|
||||||
} else if (this.platform.is('ios') && (!link.target || link.target == '_self')) {
|
|
||||||
// In cordova ios 4.1.0 links inside iframes stopped working. We'll manually treat them.
|
|
||||||
event.preventDefault();
|
|
||||||
if (element.tagName.toLowerCase() == 'object') {
|
if (element.tagName.toLowerCase() == 'object') {
|
||||||
element.setAttribute('data', link.href);
|
element.setAttribute('data', link.href);
|
||||||
} else {
|
} else {
|
||||||
element.setAttribute('src', link.href);
|
element.setAttribute('src', link.href);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
// The frame is local or the link needs to be opened in a new window. Open in browser.
|
||||||
|
if (!this.sitesProvider.isLoggedIn()) {
|
||||||
|
this.utils.openInBrowser(link.href);
|
||||||
|
} else {
|
||||||
|
this.sitesProvider.getCurrentSite().openInBrowserWithAutoLoginIfSameSite(link.href);
|
||||||
|
}
|
||||||
|
} else if (link.target == '_parent' || link.target == '_top' || link.target == '_blank') {
|
||||||
|
// Opening links with _parent, _top or _blank can break the app. We'll open it in InAppBrowser.
|
||||||
|
event.preventDefault();
|
||||||
|
this.utils.openFile(link.href).catch((error) => {
|
||||||
|
this.domUtils.showErrorModal(error);
|
||||||
|
});
|
||||||
|
} else if (this.platform.is('ios') && (!link.target || link.target == '_self')) {
|
||||||
|
// In cordova ios 4.1.0 links inside iframes stopped working. We'll manually treat them.
|
||||||
|
event.preventDefault();
|
||||||
|
if (element.tagName.toLowerCase() == 'object') {
|
||||||
|
element.setAttribute('data', link.href);
|
||||||
|
} else {
|
||||||
|
element.setAttribute('src', link.href);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subtype of HTMLAnchorElement, with some calculated data.
|
||||||
|
*/
|
||||||
|
type CoreIframeHTMLAnchorElement = HTMLAnchorElement & {
|
||||||
|
treated?: boolean; // Whether the element has been treated already.
|
||||||
|
};
|
||||||
|
|
Loading…
Reference in New Issue