Android web view load javascript in random order / not loading - javascript

I have an issue with a web view I'm using.
The javascript files used to render the view properly MUST be loaded in a specific order.
On browser (chrome mobile; safari desktop, ...) it works well.
However in my web view the result is unpredictable.
This is one of the latests failing run I had:
The HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<title></title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<style>
body {
font-family: Monospace;
background-color: #000;
color: #fff;
margin: 0px;
overflow: hidden;
}
</style>
</head>
<body>
<canvas class="emscripten" id="canvas" oncontextmenu="event.preventDefault()"></canvas>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="js/script1.js"></script>
<script src="js/script2.js"></script>
<script src="js/script3.js"></script>
<script src="js/script4.js"></script>
... More scripts...
</body>
</html>
Here is the Java code:
mWebView = (WebView)findViewById(R.id.webView);
mWebView.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);
//mWebView.getSettings().setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.setHorizontalFadingEdgeEnabled(false);
mWebView.setScrollbarFadingEnabled(false);
mWebView.setVerticalFadingEdgeEnabled(false);
mWebView.setOverScrollMode(View.OVER_SCROLL_NEVER);
mWebView.loadUrl("http://192.168.1.24:8000/path/to/index.html");
The issue is that randomly, javascript files are interpreted in wrong order or just not loaded.
From my understanding, javascript MUST be loaded in declaration order.
Am I wrong ?
Is there anything I can do to change that behavior ? (other than concatenating all JS together..)

Your scripts will work on the web site but for make it work on the android you need to load the scripts manually. See the function how it load the script from assets.
private void injectScriptFile(WebView view, String scriptFile) {
InputStream input;
try {
input = getAssets().open(scriptFile);
byte[] buffer = new byte[input.available()];
input.read(buffer);
input.close();
// String-ify the script byte-array using BASE64 encoding !!!
String encoded = Base64.encodeToString(buffer, Base64.NO_WRAP);
view.loadUrl("javascript:(function() {" +
"var parent = document.getElementsByTagName('head').item(0);" +
"var script = document.createElement('script');" +
"script.type = 'text/javascript';" +
// Tell the browser to BASE64-decode the string into your script !!!
"script.innerHTML = window.atob('" + encoded + "');" +
"parent.appendChild(script)" +
"})()");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
See Here Example
also make sure you enabled JS:
webSettings.setJavaScriptEnabled(true);
and the manifest ofcourse:
<uses-permission android:name="android.permission.INTERNET" />

Related

Windows.Forms.WebBrowser loading page with local SVG file

I have an HTML page that generating in C# project. it works, when I open this page in IE.
<!DOCTYPE HTML>
<meta http-equiv='X-UA-Compatible' content='IE=10' />
<html lang='en'>
<head>
<title>TemplateSVG</title>
<script type='text/javascript' src='InterfaceSVG.js'></script>
</head>
<body style='margin: 0; overflow: hidden;'>
<div class="page-content">
<object id='idSVG' type='image/svg+xml' data='D:\Examples\ExampleFla.svg'></object>
</div>
</body>
</html>
I loaded getting text in Web browser
if (webBrowser.Document == null)
{
webBrowser.DocumentText = theHTMLtext;
}
else
{
webBrowser.Document.OpenNew(true);
webBrowser.DocumentText = theHTMLtext;
}
But file InterfaceSVG.js isn't find.
When I give full Path to js file src='D:\[Path]\InterfaceSVG.js'
JS script generate exception on line with getSVGDocument().
var SvgDoc;
window.addEventListener('load', function () {
SvgDoc = document.getElementById("idSVG");
if (SvgDoc == null) { alert("error"); return; }
SvgDoc = SvgDoc.getSVGDocument(); // IE created Access Deny.
});
Edit:
Try to insert text from js file.
<script>Text from InterfaceSVG.js </scipt>
But it generates the same exception (Access Deny) on line with getSVGDocument()
I saved result HTML page in a folder with SVG file and use function Navigateinstead of DocumentText. Now it works... but I don't want to write on disk anything.
string path = Path.GetDirectoryName(pathToSvgFile);
string file = "\\"+Path.GetFileNameWithoutExtension(pathToSvgFile);
string newfile = path + file;
File.WriteAllText(newfile, theHTMLtext);
webBrowser.Navigate(newfile);
I found how need to open a user Page.
Create template HTML page without scripts.
<!DOCTYPE HTML>
<meta http-equiv='X-UA-Compatible' content='IE=10' />
<html lang='en'>
<head>
<title>Empty Page</title>
</head>
<body style='margin: 0; overflow: hidden; '>
<div class="page-content">
<object id='idSVG' style='height: 100%; width: 100%; position:absolute;' type='image/svg+xml' data='{0}'></object>
</div>
</body>
</html>
Add script files and change text body of HTML page what you need in event webBrowser.Navigated.
static string PathToSvgFile;
public static void OpenSVG(this WebBrowser webBrowser, string pathToSvgFile)
{
if (webBrowser.ReadyState == WebBrowserReadyState.Complete || webBrowser.ReadyState == WebBrowserReadyState.Uninitialized)
{
webBrowser.Navigate([Path to emptyPage.html]);
PathToSvgFile = pathToSvgFile;
webBrowser.Navigated += webBrowser_Navigated;
}
}
private static void webBrowser_Navigated(object sender, WebBrowserNavigatedEventArgs e)
{
var webBrowser = ((WebBrowser)sender);
HtmlElementCollection head = webBrowser.Document.GetElementsByTagName("head");
if (head != null)
{
var element = webBrowser.Document.CreateElement("script");
element.SetAttribute("type", "text/javascript");
var elementDom = (MSHTML.IHTMLScriptElement)element.DomElement;
elementDom.src = [JavaScriptFile.js];
((HtmlElement)head[0]).AppendChild(element);
}
webBrowser.Document.Body.InnerHtml = String.Format(webBrowser.Document.Body.InnerHtml, PathToSvgFile);
webBrowser.Navigated -= webBrowser_Navigated;
}

Firefox not executing JavaScript files that were loaded dynamically

I'm trying to load two scripts that were functionally deferred on account of their type attributes being non-standard i.e. text/javascript/defer. Doing this causes the parser to ignore them so I want to reload them using JavaScript.
My HTML is as below:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>No Title</title>
<meta name="keywords" content="">
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script type="text/javascript/defer" src="assets/js/test3.js"></script>
<script type="text/javascript/defer" src="assets/js/test4.js"></script>
<script type="text/javascript" src="assets/js/jquery.js"></script>
<script>
$(document).ready(function(){
var defer_js_collection_obj = $("[type='text/javascript/defer']"),
el_head_rq_obj = $('head'),
el_head_obj = el_head_rq_obj[0]
;
if(defer_js_collection_obj.length > 0)
{
//Reload JavaScript
defer_js_collection_obj.each(function() {
var file_src_outer_html_str = this.outerHTML;
var file_src_res_arr = file_src_outer_html_str.match("src *\= *[\"\']{1}(.*?)[\"\']{1}");
var file_src_str = file_src_res_arr[1];
var fileref = document.createElement('script');
fileref.setAttribute("type", "text/javascript");
fileref.setAttribute("src", file_src_str);
document.getElementsByTagName("head")[0].appendChild(fileref);
});
//Unload JavaScript with defer tag
for(var j = defer_js_collection_obj.length-1; j >= 0; j--)
{
defer_js_collection_obj[j].parentNode.removeChild(defer_js_collection_obj[j]);
}
}
});
</script>
</head>
<body>
<div>Load Deferred JavaScript</div>
</body>
</html>
jquery.js is version 1.11.2. test3.js and test4.js reference the javascript files I want to load, and they contain console.log('test3.js is loaded'); and console.log('test4.js is loaded'); respectively.
The issue I'm having is that this script works virtually everywhere else except on Firefox. I'm on a Mac OS X 10.10.5 using Firefox 46.0.1, and I don't see the console.log message when I load the script.
How can I fix this?
It might be a mime type issue. Do you happen to see any message in the console stating "not well-formed"? In any case, this seemed to work for me and I agree that your code did not work in FF when I first tried it.
$(document).ready(function(){
console.log("main");
var $body = $($("body")[0]);
var $scripts = $("[type='text/javascript/defer']");
$scripts.each(function(){
var scriptTag = document.createElement("script");
scriptTag.setAttribute("type", "text/javascript");
scriptTag.setAttribute("src", $(this).attr("src"));
$body.append(scriptTag);
});
});
Try to append your script at the end of body, so instead do:
document.getElementsByTagName("body")[0].appendChild(fileref);

How to include common xsl file inside other xsl files?

I have several xsl files that need to include common xsl file. So instead of including the javascript files in each one of them I would like to create a Common.xsl that will include the java script files and all xsl files will include it.
The question is how to do that?
I tried some suggested methods using including javascript file but with no success, in the browser console I get errors:
Uncaught ReferenceError: jQuery is not defined
Uncaught ReferenceError: $ is not defined
It looks like the jquery was not included.
I tried to do something like this:
<"script type="text/javascript" src="common.js" />
or
(function() {
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = "../jquery/jquery-1.9.1.min.js";
document.getElementsByTagName('head')[0].appendChild(script)
})();
Edit:
I answered my question see answer below.
<xsl:element name="script">
<xsl:attribute name="src">common.js</xsl:attribute>
/* common code */
</xsl:element>
That should do the trick
I solved my issue by the following code using xsl instead of javascript files:
I have created a Common.xsl file that includes all my common javascript files.
Common.xsl
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template name="Common">
<link rel="stylesheet" href="SiteRef_getCSS?CSSName=Site/site.css" type="text/css"/>
<script type="text/javascript" src="SiteRef_getJS?JSName=jquery/jquery-1.11.1.min.js"/>
<script type="text/javascript" src="SiteRef_getJS?JSName=Site/common.js"/>
<script type="text/javascript" src="SiteRef_getJS?JSName=Site/MessagesConstants.js"/>
<script type="text/javascript" src="SiteRef_getJS?JSName=Site/win_functions.js"/>
<script type="text/javascript" src="SiteRef_getJS?JSName=Site/resizeFunctions.js"/>
</xsl:template>
On every xsl file that need those includes I added the following lines:
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:include href="common/Common.xsl"/> <!-- Here I include the Common.xsl -->
<xsl:template match="/Reflection">
<xsl:text disable-output-escaping='yes'><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "SiteRef_getCSS?CSSName=Site/xhtml1-transitional.dtd"></xsl:text>
<html>
<head>
<title><xsl:value-of select="Localization/ViewAbout"/></title>
<xsl:call-template name="Common"/> <!-- Here I apply the tamplate of the common includes -->
<body>
.
.
.
</body>
</xsl:template>
</xsl:transform>
In order resolve the include URI (see xsl:include) in my java application server I had to implement the URIResolver resolve() function:
public class XslURIResolver implements URIResolver
{
private static final String XSL_PATH = System.getProperty("user.dir") + File.separatorChar + INetlayerConstants.c_UI_PATH + INetlayerConstants.c_XSL_PATH;
#Override
public Source resolve(String href, String base) throws TransformerException
{
DOMSource xslDomSource;
try
{
DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance();
dFactory.setNamespaceAware(true);
DocumentBuilder dBuilder = dFactory.newDocumentBuilder();
InputStream in = new FileInputStream(XSL_PATH + href);
InputSource xslInputSource = new InputSource(in);
Document xslDoc = dBuilder.parse(xslInputSource);
xslDomSource = new DOMSource(xslDoc);
xslDomSource.setSystemId(XSL_PATH + href);
return xslDomSource;
}
catch (ParserConfigurationException e)
{
e.printStackTrace();
}
catch (SAXException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
return null;
}
}
And then before transformation I set the URIResolver:
TransformerFactory tFactory = TransformerFactory.newInstance();
tFactory.setURIResolver(new XslURIResolver());
That's about it, hope it helps someone...

Transfer VB.NET variable to JavaScript

***VB.HTML
#Code
Dim SS_ID = Request.QueryString("SS_ID")
Dim initial_QRY
Dim ctrRecord
If SS_ID <> "" then
initial_QRY = "SELECT * FROM Tbl_rsSKUSetup WHERE SKUSetup_ItemID='" & SS_ID & "'"
ctrRecord = db.Query(initial_QRY).Count
If ctrRecord = 0 Then
System.Diagnostics.Process.Start("C:\Users\ushuam00\Documents\My Web Sites\EmptySite5\_Files\skuSetupGenericData.xlsm")
Else If ctrRecord > 0 Then
Else
End Code
***JavaScript
function alertCounter(){
alert('');
}
I want ctrRecord to be placed inside alter of JavaScript. Now I have the VBHTML on event "onload" calling alertCounter() All I have to see if I can capture ctrRecord so I can display it under alert.
I got this simple solution
display the ctrRecord inside the body where your VB.net code rest
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
#ctrRecord
</body>
</html>
then call JS via iFrame using onload event
Javascript
function alertCounter(){
alert(searchFrame.document.body.innerText);
}

Android - JavaScript interface not working in android 3.0

I'm using JavaScript interface for checking if Google's StreetView is available. My problem is that from android 3.0 code stopped working, and I am unnable to find why. Problem is that methods from "JavascriptCheck" interface are never called and Logcat doesn't show any errors.
Java code:
public void showStreetView(GeoPoint geoPoint) {
WebSettings webSettings = webView.getSettings();
webSettings.setJavaScriptEnabled(true);
webView.addJavascriptInterface(new JavascriptCheck(), "Android");
lat = geoPoint.getLatitudeE6()/1E6;
lon = geoPoint.getLongitudeE6()/1E6;
webView.loadDataWithBaseURL("", context.getString(R.string.html_streetview, lat, lon), "text/html", "UTF-8", "");
}
public class JavascriptCheck {
public void hasStreetview(boolean hasStreetview) {
if (hasStreetview) {
openStreetView();
} else {
Toast.makeText(context, context.getString(R.string.loc_no_street_view), Toast.LENGTH_SHORT).show();
}
}
}
WebView in layout file:
<WebView android:id="#+id/webView"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:visibility="gone">
</WebView>
JavaScript string:
<string name="html_streetview">
<html>
<head>
<script src=\"http://maps.google.com/maps?file=api&v=2& sensor=false\" type=\"text/javascript\"/>
</head>
<body>
<script type=\"text/javascript\">
var testPoint = new GLatLng(%1$s, %2$s);
var svClient = new GStreetviewClient();
svClient.getNearestPanoramaLatLng(testPoint, function (nearest) {
if ((nearest !== null) && (testPoint.distanceFrom(nearest) <= 100)) {
Android.hasStreetview(true);
} else {
Android.hasStreetview(false);
}
});
</script>
</body>
</html>
</string>
Solved my problem long ago, just wanted to share with others. Honeycomb and later Android versions require that you use full html <script> tags. Also it is better to keep script string in assets folder. My assets/index.html looks like this now:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
<script src="http://maps.googleapis.com/maps/api/js?sensor=false" type="text/javascript"></script>
<script type="text/javascript">
var sv = new google.maps.StreetViewService();
function hasStreet(lat, lon) {
var point = new google.maps.LatLng(lat, lon);
sv.getPanoramaByLocation(point, 50, isSVAvailable);
}
function isSVAvailable(data, status) {
if (status == google.maps.StreetViewStatus.OK) {
Android.hasStreetview(true);
} else {
Android.hasStreetview(false);
}
}
</script>
</head>
<body></body>
</html>
I too was using this function and have seen it broken since I tried upgrading my app for ICS. It seems that the Javascript won't execute if you have an external src link. If you take out the javascript src link and add some logging you'll see that the script will run (and obviously return false all the time).
I know in the docs they recommend not using javascript that calls into your native code unless you control all elements in the javascript but perhaps now they explicitly stop code from running that references an external resource?

Categories

Resources