iOS WebView: open single hyperlink in external browser - html

There's a simple UIWebView in my iOS app. Hyperlinks open normally in my app itself. But there's a single hyperlink I want to open in external standard browser (Safari).
I image something like <a href="http://example.com" target="_safari">.
Is there anything like this?
I'm not able to make changes in the app itself. I have to do that on my website!

You can Use UIWebViewDelegate method for achieving that. Implement following method of the delegate
func webView(_ webView: UIWebView, shouldStartLoadWith request: URLRequest, navigationType: UIWebViewNavigationType) -> Bool {
let urlStr = request.url?.absoluteString
if //urlStr is string you want {
//launch external browser
return false
}
return true
}
This method will be called every time you try to load a url in web view. You can compare if its URL you want to load, if it matches then launch external browser and return false.

try this way
<a onclick="window.open('https://www.google.co.in/', '_system');" href="#">Google</a>

Related

HTML <object> - download file if it cannot be loaded

I have a web application that serves files for viewing. If it's a PDF, I simply attach it to an <object> element. However, the app supports serving word, excel, and powerpoint files. I have tried looking for ways to preview them online, but apparently we do not have the proper technology for that (at least not natively in a browser). So instead, I want the user to download the file to view locally.
The front-end is built with React and the back-end with Spring Boot. Currently, all static resources that are documents (PDF's, docs, spreadsheets, etc.) are served under the "/document-files/**" ant-matcher. Additionally, these resources can only be viewed privately, meaning that you have to be logged in to the application to view them. Here's how part of my SecurityConfig file looks like:
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
String documentRootPath = "file:" + this.documentRootPath;
registry.addResourceHandler("/resources/**").addResourceLocations("resources/");
registry.addResourceHandler("/document-files/**").addResourceLocations(documentRootPath);
}
#Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests() // ant matchers below are api routes and the baseUri for serving documents
.antMatchers("/clients/**", "/projects/**", "/documents/**", "/document-files/**").authenticated()
.anyRequest().permitAll() //... additional method chaining omitted for brevity
}
The problem is apparently just on the front end. I don't think it has anything to do with the configuration, but I posted it for reference. With this configuration I can download and preview PDF files just fine, using <object> but for all other files, the file does not load, so in <object> I add a link to open the file like so:
render() {
// some code omitted for brevity
return (
<Module>
{!this.state.currDoc ? (
<ul className={this.state.displayType}>{list}</ul>
) : (
<object
data={"/document-files" + this.state.filePath}
type={this.mimeTypes[document.fileType]}
title={"Current Document: " + document.description + "." + document.fileType.toLowerCase()}>
{document.fileType === "PDF" ? "File could not be loaded!" : <div id="download-prompt">This file cannot be previewed online, click below to download and open locally.<a href={"http://localhost:3000/document-files" + this.state.filePath} download>Open</a></div>}
</object>
)}
</Module>
);
}
Upon clicking, the "save as" dialog box appears with the file name populated and the correct mime type but once I hit save, Chrome displays "Failed - No File". I have tried writing the href with and without the hostname. I've also tried removing the download attribute, but it redirects the page back to itself. I've even tried onLoad attribute on <object> but apparently that only works for images. I checked the network tab on dev tools and there is no record of the file being downloaded, unlike PDFs where the request is noted down.
How can I make non-PDF files download correctly using this setup?
Thanks to javilobo8's GitHubGist, I found a way to download files using Axios, which library I was already using in my app to begin with. For quick reference, here is his code:
axios({
url: 'http://localhost:5000/static/example.xlsx',
method: 'GET',
responseType: 'blob', // important
}).then((response) => {
const url = window.URL.createObjectURL(new Blob([response.data]));
const link = document.createElement('a');
link.href = url;
link.setAttribute('download', 'file.pdf');
document.body.appendChild(link);
link.click();
});
Also, there's multiple ways to work with Blobs, depending on if you're in IE, a browser that supports HTML5's Blob object, or another browser. This question helps split the code in 3 ways to form the dataUri for downloading raw data.
After setting up my <a> tag, I just trigger the click event and the non-PDF file downloads!

wkwebview - display image from documents directory into local html

I have an app with downloaded images to be displayed in local html. I am still using Objective-C because this app is 4 years old.
When first launch the app, it will download the images and other dynamic content (which I check, it is in Documents/content/ directory).
I have this code to get the content location:
NSString *contentBasePath = [app.contentManager contentBasePath];
which I get:
/var/mobile/Containers/Data/Application/4AFD30E2-F4F7-405A-9FE9-1857EEC11CC7/Documents/content
Then I have a few html pages that will call the downloaded images dynamically:
<div class="box-round benefits-thumbnail" style="background-image:url('file://{{../contentBasePath}}/{{filename}}');"></div>
Which I check, {{../contentBasePath}} will get:
/var/mobile/Containers/Data/Application/4AFD30E2-F4F7-405A-9FE9-1857EEC11CC7/Documents/content
and {{filename}} will get
example.jpg
which is all correct.
All this works with uiwebview. However I need to use wkwebview, the image did not show up.
I tried:
<div class="box-round benefits-thumbnail" style="background-image:url('{{../contentBasePath}}/{{filename}}');"></div>
and it still not working.
I googled and read around and it seems like wkwebview do not allow absolute path. so I tried as per this suggest:
[_webConfig.preferences setValue:#YES forKey:#"allowFileAccessFromFileURLs"];
and still not working.
How can I resolve this?
Seems like this is a limitation of the WebKit. As a workaround, you can write the HTML contents into a file in the documents directory and load it using [webView loadFileURL:fileUrl allowingReadAccessToURL:dirUrl]
Link to docs: https://developer.apple.com/documentation/webkit/wkwebview/1414973-loadfileurl
The files must be in the document directory.
I implemented the following to retrieve a document:
let documentDirUrl = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
let fileNameWithExtension = "IMG_0002.PNG"
let indexFileUrl = documentDirUrl.appendingPathComponent(fileNameWithExtension)
if FileManager.default.fileExists(atPath: indexFileUrl.path) {
webView.loadFileURL(indexFileUrl, allowingReadAccessTo: documentDirUrl)
}

Load Images from https URL within HTML on WebView

I am trying to load an HTML file on WebView. The HTML contains image URLs. When I try to run that image URL on Web Browser, it works. The image gets displayed. But the same image does not get loaded in WebView in my app.
I found this question on Apple Developer Forum, it is still unanswered. Any help would be appreciated. Thanks
I faced a similar issue a few months ago, and I fixed it by replacing UIWebView with WKWebView.
WKWebView is the official replacement of UIWebView, take a look at its documentation:
Starting in iOS 8.0 and OS X 10.10, use WKWebView to add web content
to your app. Do not use UIWebView or WebView.
Please try to fetch your images using WKWebView.
Step 1: import WebKit in your class
import WebKit
Step 2: Add WebKit delegate to your controller
class ViewController: UIViewController, WKUIDelegate
Step 3: create variable of WKWebView type
var webView: WKWebView!
Step 4: Configure WKWebView. Override loadView() function with following line of code
let webConfiguration = WKWebViewConfiguration()
webView = WKWebView(frame: .zero, configuration: webConfiguration)
webView.uiDelegate = self
view = webView
Step 5: In viewDidLoad() pass URLRequest to webView()
let url = "your URL"
let request = URLRequest(url: url!)
webView.load(request)

get dynamically loaded html using alamofire + swift

I am trying to request a website's html code and use it in an app in Xcode (Swift 3.0) and the pod Alamofire. In the html code online, the data contents that I want to scrape are in a div class that returns data from an Events calendar, in the form of a javascript web plugin. Since the website is not static, when I request the html and print the resulting response as a string, the data I want is not contained in the string. A message appears that says:
<noscript>Your browser must support JavaScript to view this content.
Please enable JavaScript in your browser settings then try again.
Events calendar powered by Trumba
</noscript>
My code using Alamofire looks like:
func downloadCalendar(){
Alamofire.request(urlString).responseString { (AlamofireResponse) in
print(AlamofireResponse.result.value!)
}
}
The urlString is a variable for the actual webpage's url.
Is there a way to get all of the html that appears in the html online into Xcode using Alamofire? If it's not possible with Alamofire is there another way to do this using Swift?
I've tried to accomplish a similar thing, unfortunately to no avail...
It seams AlamoFire grabs the first response it gets....
There is a workaround - use UIWebView:
static let webView = UIWebView()
self.webView.loadRequest(URLRequest.init(url: URL.init(string:"http://example.com")!)
DispatchQueue.main.asyncAfter(deadline: .now()+10.0) {[unowned self] in
if let html = self.webView.stringByEvaluatingJavaScript(from: "document.documentElement.outerHTML")
{print(html)}
}
Where 10.0 is the approx number of seconds required for javascript to finish loading the webpage data.
However since: it's not thread safe, you must use a singleton webView,
import UIKit and can't do it in the background - it's far from the perfect solution...
It might be easier to setup a proxy webserver in between to do the parsing for you.
Cheers!

Opening view controller from web view

I want to have a web view that loads a webpage. Webpage has few buttons and when you click a button from the web page it has to open a view-controller.
Is this possible?
I bet you are gonna use UKWebView and yes its possible to communicate between your webview and website through evaluateJavaScript(). In this way one can easily communicate between their website and app:
webView.evaluateJavaScript("document.getElementById('someElement').innerText") { (result, error) in
if error != nil {
print(result)
}
}