Loading local HTML with local Javascript Sources in a WKWebView (iOS, Swift) - javascript

I am trying to load a local html file in a WKWebView for a iOS app (Swift 4.2). Unfortunately, this local file contains javascript code that does not seem to be executed.
Below is this html file (taken from https://www.verovio.org/tutorial.xhtml?id=topic00):
<html>
<head>
<title>Verovio Hello World! example</title>
<script src="verovio-toolkit.js" type="text/javascript" ></script>
<script src="jquery-3.1.1.min.js" type="text/javascript" ></script>
</head>
<body>
Hello World!
<div id="svg_output"/>
<script type="text/javascript">
var vrvToolkit = new verovio.toolkit();
$.ajax({
url: "Beethoven_StringQuartet_op.18_no.2.mei"
, dataType: "text"
, success: function(data) {
var svg = vrvToolkit.renderData(data);
$("#svg_output").html(svg);
}
});
</script>
</body>
</html>
And below the view controller file written in swift:
import UIKit
import WebKit
class ViewController: UIViewController, WKUIDelegate, WKNavigationDelegate {
#IBOutlet weak var webView: WKWebView!
override func viewDidLoad() {
super.viewDidLoad()
webView.uiDelegate = self
webView.navigationDelegate = self
let url = Bundle.main.url(forResource: "index", withExtension: "html", subdirectory: "html")!
webView.loadFileURL(url, allowingReadAccessTo: url)
}
}
Files are local under "Build Phases/Copy Bundle Resources" in the project properties. I also tried to put them in a directory but without any success. Below the file organization inside the project.
EDIT: When I change the url in the html file from Beethoven.mei to https://www.verovio.org/gh-tutorial/mei/Beethoven_StringQuartet_op.18_no.2.mei (same file but on Verovio's website), anything works good!!
So:
Local .js resources work fine
The issue comes from jquery not able to load local text file
Any idea on how to make jquery able to load the local file?
Thank you!
M.

According to the docs, loadFileURL does this:
If readAccessURL references a single file, only that file may be loaded by WebKit. If readAccessURL references a directory, files inside that file may be loaded by WebKit.
The url you got is a url of a file, namely the HTML file. You need the url of the directory. You can do this by calling deletingLastPathComponent:
webView.loadFileURL(url, allowingReadAccessTo: url.deletingLastPathComponent())

First check your index.html file has scr path for js. if like below, that means js files contain in js folder. so you need to add reference to that folder while add to project.
<script src="js/jquery.js"></script>
then get the main resource path like below
let path = Bundle.main.resourcePath! + "/\(folderName)/\(fileName)"
print("path:=",path )
after that load that file to webView
do {
let contents = try String(contentsOfFile: path, encoding: .utf8)
let baseUrl = URL(fileURLWithPath: path)
webView.loadHTMLString(contents as String, baseURL: baseUrl)
} catch {
print ("File HTML error")
}

You can use the loadHTMLString method to load the HTML, as below:
let url = Bundle.main.url(forResource: "index", withExtension: "html", subdirectory: "html")!
do {
let html = try String(contentsOf: url)
webView.loadHTMLString(html, baseURL: url.deletingLastPathComponent())
} catch ....
The baseURL point to your app directory in file system. You can write in the src property of the script tag relative location that is interpreted as relative to baseURL.

Related

Access JSON file from src/* folder inside script tag of index.html

I am working on React Application and want to access a JSON file which is part of my src folder inside the index.html file. I have tried using the AJAX script however I can only access the files from the public folder.
The below code snippet works for the files inside the public folder
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"> </script>
<script>
$(function() {
$.getJSON("./config.json", function (data) {
console.log("JSON Data => ", data)
});
});
</script>
Using the above approach, I cannot access the JSON files inside the ./src/config.json.

import environment variable inside html and javascript

I have a maven project with folders like myproject/src/main/resources/public. I am using this maven project just to make a war and deploy my UI code (containing HTML5, JavaScript(with jQuery), CSS etc) to tomcat server and nothing java related.
And inside public folder, I have index.html and builder.js files defined.
index.html which has the following line:
<button type="button" id = "bButton " onclick="location.href='https://myserver-dev.com/Builder/builder.html'">Builder</button>
And another JS file builder.js where I am setting env variable like this:
// var envURL = "http://localhost:8080";
var envURL = "https://myserver-dev.com";
//var envURL = "https://myserver-test.com";
I was thinking of creating a separate JS file, maybe something like properties.js or env.js and put the following in it so that I can just import it in html and js files whenever needed:
// var envURL = "http://localhost:8080";
var envURL = "https://myserver-dev.com";
//var envURL = "https://myserver-test.com";
If I do that what would be the best way to get the envURL inside index.html and builder.js at appropriate places?

Android WebView: How to access JS function from assets folder

I'm loading a local HTML file in my WebView and executing my JS-Function like so:
webview.evaluateJavascript("start();", null);
It works as long as I have the function declared in <script></script> tags in the HTML file.
...
<body>
<script type="text/javascript">
function start(){
}
</script>
</body>
...
But now I'm first using Webpack to bundle my Javascript code into a single JS file and store this in the assets folder of my app and load it like so:
<script type="text/javascript" src="file:///android_asset/js/bundle.js"></script>
The new bundle.js file contains the start function but now I can't call it, because it's not defined.
What I'm missing here?
EDIT: Ok my function is only accessible in the bundle.js. There are multiple ways to make it work, as I want:
Define global variable with webpack
I choose the following solution to make my function accessible in the global context:
window.start = function() {
}

How to Access Local JavaScript File from a Cloud Functions HTML File?

I am trying to simply access a JavaScript file from within an HTML file using the script src attribute, and I have been unable to do so. Both files are in my functions folder.
I have the following Cloud Function index.js file in my functions folder:
const functions = require('firebase-functions');
const db = require('./admin');
var viewerApp = require('./viewerApp');
exports.view = functions.https.onRequest(viewerApp);
the viewApp.js file looks like this:
const express = require("express");
const fs = require('fs');
const viewerApp = express();
module.exports =
viewerApp.get('/:collection_name/:id', (req, res) =>
{
var viewerHTML = fs.readFileSync('./viewerApp.html').toString();
var id = req.params.id;
var collection_name = req.params.collection_name;
var rendered_HTML = eval(viewerHTML);
res.send(rendered_HTML);
}
)
You will notice the eval(viewerHTML) statement, which refers to a separate html file called viewerApp.html, which basically contains a template literal and looks like so:
<!DOCTYPE html>
<html lang="en">
<body>
...
</body>
</html>
(if someone has a better suggestion for separating the HTML into a separate file while being able to use ${variables} that would be helpful as well, as eval() is not ideal and perhaps is part of what is causing my problem)
The above works fine, except that I cannot figure out how to reference a JavaScript file located in the same functions folder, which means I would need to include all my JavaScript in the viewerApp.html file, which will be a mess.
I have tried all these possibilities in the viewerApp.html file (to try and refer to a JavaScript file called test.js):
<script src="./test.js"></script>
<script src="/test.js"></script>
<script src="test.js"></script>
<script src=test.js></script>
All of the above yield the following error in the console:
Uncaught SyntaxError: Unexpected token < test.js:2
(I get the same error if I try and refer to a filename that doesn't exist so I suspect a problem in the file path or limitation on the ability to access the local file system)
I don't know what to make of the error being related to a < character, as the content of test.js is simply:
console.log("logging happened");
Any assistance would be MUCH appreciated. Thank you!!
The problem in the end was that I did not initialize and configure firebase hosting which seems to be what allows html/js/css and other static files to be accessible in HTML returned from the cloud function. Once I did that and setup the public folder, I was able to refer to the test.js file by putting it in the public folder. That plus addition tweaks to the rewrite section of the firebase.json file, and I was all set. Following this video helped a lot and contains all the required steps.

Downloading multiple files and zip - Chrome extension

Is it possible to download multiple images into the sandbox file system (without the "save as" dialog box, or at-max one saveas dialog) ?
after downloading them, i'd like to ZIP them into one.. is there any javascript archive library?
Thanks in advance..
You can use zip.js for this.
It does already have API for fetching contents to be zipped from HTTP (cf. zip.HttpReader constructor) and for writing generated zip on HTML5 filesystem (cf. zip.FileWriter constructor).
Here is an example using the filesystem API:
index.html file:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Zip JSON data from the BBC into HTML5 FileSystem</title>
</head>
<body>
<script src="zip.js"></script>
<script src="zip-fs.js"></script>
<script src="zip-ext.js"></script>
<script src="example.js"></script>
</body>
</html>
example.js file:
// create a zip virtual filesystem
var fs = new zip.fs.FS();
// add some files into the zip filesystem
// add the "bbc-music.json" file in the root directory
fs.root.addHttpContent("bbc-music.json",
"http://www.bbc.co.uk/programmes/genres/music.json");
// add the "bbc-learning.json" file in the root directory
fs.root.addHttpContent("bbc-learning.json",
"http://www.bbc.co.uk/programmes/genres/learning.json");
// create a file named "test.zip" in the root directory of the HTML5 filesystem
createFile("test.zip", function(fileEntry) {
// export the zip content into "test.zip" file
fs.root.exportFileEntry(fileEntry, function() {
console.log("done");
});
});
// function to create a file in the HTML5 temporary filesystem
function createFile(filename, callback) {
webkitRequestFileSystem(TEMPORARY, 4 * 1024 * 1024, function(fs) {
fs.root.getFile(filename, { create : true }, callback);
});
}
You can access images as regular parts of some web-pages or download them separately by means of XMLHTTPRequests. After this you can zip them in a single archive using JSZip JavaScript library. The zip can be stored as a file without a "Save As" dialog (try the example on the site). Though I'm not sure why you need the sandbox.
There exist other JavaScript libraries for zipping, for example, some are mentioned in other SO answer.

Categories