So I'm trying to display the values of a book in myLibrary but the when I do it displays it like this :
Zero To one
Peter Thiel
210
Has been read already
function() { return title + " " + "by" + " " + author + " " + pages + " " + "pages" + " " + isRead; }
It shouldn't display this part:
function() { return title + " " + "by" + " " + author + " " + pages + " " + "pages" + " " + isRead; }
Here's my code:
this.pages = pages;
this.isRead = isRead;
this.info = function() {
return title + " " + "by" + " " + author + " " + pages + " " + "pages" + " " + isRead;
}
}
const zeroToOne = new Book("Zero To one", "Peter Thiel", "210", "Has been read already");
function addBookToLibrary(bookToAdd) {
myLibrary.push(bookToAdd);
console.log(myLibrary);
for (let obj of myLibrary) {
console.log(obj);
card.textContent = Object.values(obj);
}
}
You have to call the info function :
console.log(obj.info());
I have code that works fine in JavaScript IDE like Webstorm, but when I try to port it to Java, using the Nashorn library (to run JS within a Java program), I get these errors: "Name: undefined, Age: undefined" (with possibly others to follow depending what's wrong here.)
Below is the full code. This coding approach below seems to work in general, but there are cases like this where I don't get the expected results.
Would appreciate any help or suggestions.
Thanks!
public class JavaScriptEvaluationExample
{
public static void main(String[] args) throws ScriptException, NoSuchMethodException
{
// Basic JavaScript evaluation
String json = "{\n" +
" \"name\": \"John\",\n" +
" \"age\": 30,\n" +
" \"cars\": [\n" +
" {\n" +
" \"name\": \"Ford\",\n" +
" \"models\": [\n" +
" \"Fiesta\",\n" +
" \"Focus\",\n" +
" \"Mustang\"\n" +
" ]\n" +
" },\n" +
" {\n" +
" \"name\": \"BMW\",\n" +
" \"models\": [\n" +
" \"320\",\n" +
" \"X3\",\n" +
" \"X5\"\n" +
" ]\n" +
" },\n" +
" {\n" +
" \"name\": \"Fiat\",\n" +
" \"models\": [\n" +
" \"500\",\n" +
" \"Panda\"\n" +
" ]\n" +
" }\n" +
" ]\n" +
"}";
String jsScript = "function parseJSONFields(param)\n" +
"{\n" +
" var result = \"\";\n" +
" var carName =\"\" ;\n" +
" var models = \"\";\n" +
" var name = param.name + \",\";\n" +
" var age = param.age;\n" +
" result = \"Name: \" + name + \" Age: \" + age + \"\\n\";\n" +
" for (item in param.cars)\n" +
" {\n" +
" result += \" \"+ \" >> \" + param.cars[item].name +\": \"\n" +
" result+= \" \" + param.cars[item].models\n" +
" result += \"\\n\";\n" +
" }\n" +
" return result;\n" +
"}";
System.out.println(runJS("parseJSONFields", json, jsScript));
}
// ------------------------------------------------------------------------------------------------
private static Object runJS(String functionName, String param, String script) throws ScriptException, NoSuchMethodException
// ------------------------------------------------------------------------------------------------
{
Object resultString = "";
String errorResultString = "";
ScriptEngine js = null;
try
{
if (param.length() > 0)
{
js = new ScriptEngineManager().getEngineByName("javascript");
js.eval(script);
Invocable inv = (Invocable) js;
}
}
catch (Exception e)
{
errorResultString = e.getMessage() + " ---> " + e.getMessage();
}
return errorResultString.length() > 0 ? errorResultString
: ((Invocable) js).invokeFunction(functionName, param);
}
}
Thanks to all who replied.
The problem was, as the first person noted, that I forgot the JSON.parse() statement to convert the string to a JSON object.
Thanks very much again.
I have an array of objects that i get from a json file. After getting the array with fs.readFileSync.
jsonData = JSON.stringify(fs.readFileSync('data.json'.toString(), 'utf8'));
parsedJsonData = JSON.parse(jsonData);
and when I do:
console.log(parsedJsonData);
it returns: 710, instead of what i expect to be 1
here is the array(with only one object)
[
{
"email": "ibrahim.m.fadel#gmail.com",
"username": "ibrahim fadel",
"password": {
"type": "Buffer",
"data": [
25,
0,
0,
0,
2,
115,
116,
114,
105,
110,
103,
0,
8,
0,
0,
0,
99,
97,
114,
101,
121,
51,
49,
0,
0
]
},
"id": 0
}
]
I simply want to find the amount of objects that there are in the array, which is 1 so I can loop through it
The unnecessary JSON.stringify() over a string is causing problems, look at this:
console.log(JSON.stringify("[\n" + "{\n" + " \"email\": \"ibrahim.m.fadel#gmail.com\",\n" + " \"username\": \"ibrahim fadel\",\n" + " \"password\": {\n" + " \"type\": \"Buffer\",\n" + " \"data\": [\n" + " 25,\n" + " 0,\n" + " 0,\n" + " 0,\n" + " 2,\n" + " 115,\n" + " 116,\n" + " 114,\n" + " 105,\n" + " 110,\n" + " 103,\n" + " 0,\n" + " 8,\n" + " 0,\n" + " 0,\n" + " 0,\n" + " 99,\n" + " 97,\n" + " 114,\n" + " 101,\n" + " 121,\n" + " 51,\n" + " 49,\n" + " 0,\n" + " 0\n" + " ]\n" + " },\n" + " \"id\": 0\n" + "}\n" + "]"))
.as-console-wrapper { max-height: 100% !important; top: 0; }
Is returning a escaped string, so when you call the function JSON.parse() this function actually is returning a string:
console.log(typeof JSON.parse(JSON.stringify("[\n" + "{\n" + " \"email\": \"ibrahim.m.fadel#gmail.com\",\n" + " \"username\": \"ibrahim fadel\",\n" + " \"password\": {\n" + " \"type\": \"Buffer\",\n" + " \"data\": [\n" + " 25,\n" + " 0,\n" + " 0,\n" + " 0,\n" + " 2,\n" + " 115,\n" + " 116,\n" + " 114,\n" + " 105,\n" + " 110,\n" + " 103,\n" + " 0,\n" + " 8,\n" + " 0,\n" + " 0,\n" + " 0,\n" + " 99,\n" + " 97,\n" + " 114,\n" + " 101,\n" + " 121,\n" + " 51,\n" + " 49,\n" + " 0,\n" + " 0\n" + " ]\n" + " },\n" + " \"id\": 0\n" + "}\n" + "]")))
.as-console-wrapper { max-height: 100% !important; top: 0; }
The solution is removing the call of JSON.stringify
console.log(JSON.parse("[\n" + "{\n" + " \"email\": \"ibrahim.m.fadel#gmail.com\",\n" + " \"username\": \"ibrahim fadel\",\n" + " \"password\": {\n" + " \"type\": \"Buffer\",\n" + " \"data\": [\n" + " 25,\n" + " 0,\n" + " 0,\n" + " 0,\n" + " 2,\n" + " 115,\n" + " 116,\n" + " 114,\n" + " 105,\n" + " 110,\n" + " 103,\n" + " 0,\n" + " 8,\n" + " 0,\n" + " 0,\n" + " 0,\n" + " 99,\n" + " 97,\n" + " 114,\n" + " 101,\n" + " 121,\n" + " 51,\n" + " 49,\n" + " 0,\n" + " 0\n" + " ]\n" + " },\n" + " \"id\": 0\n" + "}\n" + "]")
.length)
.as-console-wrapper { max-height: 100% !important; top: 0; }
I receive from the server xhtml code which I want to show in Android app like ebook reader. For this the Monocle library was chosen.
Next I prepare webview with follow code:
contentView.addJavascriptInterface(new LectureJSInterface(), "Android");
contentView.getSettings().setAllowFileAccess(true);
contentView.getSettings().setJavaScriptEnabled(true);
contentView.setBackgroundColor(0xFFECECEC);
contentView.setWebChromeClient(new WebChromeClient());
contentView.setWebViewClient(new WebViewClient() {
#Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
Global.dismissProgressDialog();
}
});
After this I download the xhtml code from the server and add to it JS code for working with Monocle:
private String prepareCode(String code) {
if ((code == null) || code.equals("")) return "";
String newCode = code.substring(code.indexOf("<html"), code.indexOf("<head>")+6);
newCode = newCode.concat(
"<script src=\"file:///android_asset/monocore.js\"></script>\n" +
"<link rel=\"stylesheet\" type=\"text/css\" href=\"file:///android_asset/monocore.css\" />\n" +
"<style>\n" +
" #reader {\n" +
" width: 100%;\n" +
" height: 100%;\n" +
" border: 0px solid #000;\n" +
" }\n" +
"</style>\n" +
"<script>\n" +
"\n" +
" var isNightMode = false;\n" +
" var isFirstLoading = false;\n" +
" var startPageNumber = 1;\n" +
"\n" +
" function setSettingsForFirstLoading(fontSize, pageNumber, nightMode) {\n" +
" Android.printLogInfo('setSettingsForFirstLoading()');\n" +
" isFirstLoading = true;\n" +
" isNightMode = nightMode;\n" +
" startPageNumber = pageNumber;\n" +
" window.changeFontSize(fontSize);\n" +
" }\n" +
"\n" +
" function changeFontSize(fontSize) {\n" +
" Android.printLogInfo('changeFontSize()');\n" +
" window.reader.formatting.setFontScale(fontSize);\n" +
" }\n" +
"\n" +
" function nightModeOn() {\n" +
" Android.printLogInfo('nightModeOn()');\n" +
" isNightMode = true;\n" +
" var i = 0;\n" +
" var frame;\n" +
" while (frame = window.reader.dom.find('component', i++)) {\n" +
" frame.contentDocument.body.style.backgroundColor = '#1F1F1F';\n" +
" frame.contentDocument.body.style.color = '#ECECEC';\n" +
" }\n" +
" }\n" +
"\n" +
" function nightModeOff() {\n" +
" Android.printLogInfo('nightModeOff()');\n" +
" isNightMode = false;\n" +
" var i = 0;\n" +
" var frame;\n" +
" while (frame = window.reader.dom.find('component', i++)) {\n" +
" frame.contentDocument.body.style.backgroundColor = '#ECECEC';\n" +
" frame.contentDocument.body.style.color = '#1F1F1F';\n" +
" }\n" +
" }\n" +
"\n" +
" function turnPage(pageNumber) {\n" +
" Android.printLogInfo('turnPage(' + pageNumber + ')');\n" +
" window.reader.moveTo({ page: pageNumber });\n" +
" }\n" +
"\n" +
" function savePercents() {\n" +
" Android.printLogInfo('savePercents()');\n" +
" Android.savePercents(window.reader.getPlace().percentAtTopOfPage());\n" +
" }\n" +
"\n" +
" function moveToPercents(percent) {\n" +
" Android.printLogInfo('moveToPercents(' + percent + ')');\n" +
" turnPage(window.reader.getPlace().pageAtPercentageThrough(percent));\n" +
" }\n" +
"\n" +
" function listenFor(evtName) {\n" +
" Monocle.Events.listen('reader', evtName, report);\n" +
" }\n" +
"\n" +
" function report(evt) {\n" +
" switch (evt.type) {\n" +
" case 'monocle:loaded':\n" +
" Android.calculateSeekBar(window.reader.getPlace().properties.component.lastPageNumber());\n" +
" break;\n" +
"\n" +
" case 'monocle:turn':\n" +
" Android.updatePagesCounter(window.reader.getPlace().pageNumber());\n" +
" break;\n" +
"\n" +
" case 'monocle:recalculated':\n" +
" if (isNightMode) nightModeOn();\n" +
" if (isFirstLoading) { isFirstLoading = false; turnPage(startPageNumber); }\n" +
" Android.calculateSeekBar(window.reader.getPlace().properties.component.lastPageNumber());\n" +
" Android.updatePagesCounter(window.reader.getPlace().pageNumber());\n" +
" break;\n" +
" }\n" +
" }\n" +
"\n" +
" function init() {\n" +
" var options = {\n" +
" flipper: Monocle.Flippers.Slider\n" +
" }\n" +
"\n" +
" listenFor('monocle:turn');\n" +
" listenFor('monocle:loaded');\n" +
" listenFor('monocle:recalculated');\n" +
"\n" +
" window.reader = Monocle.Reader('reader', null, options);\n" +
" }\n" +
"\n" +
" Monocle.Events.listen(window, 'load', init);\n" +
"</script>\n");
newCode = newCode.concat(code.substring(code.indexOf("<head>") + 6, code.indexOf("<body>") + 6));
newCode = newCode.concat("<div id=\"reader\">");
newCode = newCode.concat(code.substring(code.indexOf("<body>") + 6, code.indexOf("</body>")));
newCode = newCode.concat("</div>");
newCode = newCode.concat(code.substring(code.indexOf("</body>")));
return newCode;
}
After finishing this task the WebView loads it:
contentView.loadDataWithBaseURL(baseUrl, prepareCode(code), "text/html", "UTF-8", null);
What I have as results? I tested this app on six devices with Android 4.x and 5.x. On Android 4.x the entire content is shown correctly, but on Android 5.x I see a blank page. I should notice that the xhtml code was loaded because I can call JS-functions and get its results via JS Interface.
Are there any ideas about ways to fixing this bug?
Thanks in advance!
You can try uninstalling the webview system update.
or
Try monocle 2.3.1
or
https://github.com/joseph/Monocle/issues/259
I thought the below was not working because I was attempting XSS, but I tried performing a local port redirect to confirm, and it still wouldn't work. Can someone let me know if this is XSS or not, and if not, why it's not working?
<html>
<div id="output"></div>
<script src="prototype.js" type="text/javascript"></script>
<script type="text/javascript">
function test()
{
this.url = "http://www.google.com"
}
test.prototype.run = function()
{
var request = new Ajax.Request(this.url,
{
method: "get",
onSuccess: this.success.bind(this),
onFailure: function(response) { alert("failure"); }
});
};
test.prototype.success = function(response)
{
var debug = "this.url = " + this.url + ",<br>"
+ " response.status = " + response.status + ",<br>"
+ " response.statusText = " + response.statusText + ",<br>"
+ " response.readyState = " + response.readyState + ",<br>"
+ " response.responseText = " + response.responseText + ",<br>"
+ " response.responseXML = " + response.responseXML + ",<br>"
+ " response.responseJSON = " + response.responseJSON + ",<br>"
+ " response.headerJSON = " + response.headerJSON + ",<br>"
+ " response.request = " + response.request + ",<br>"
+ " response.transport = " + response.transport + ",<br>"
+ " response.transport.readyState = " + response.transport.readyState + ",<br>"
+ " response.transport.responseText = " + response.transport.responseText + ",<br>";
document.getElementById("output").update(debug);
};
new test().run();
</script>
</html>
it's not XSS (which is a way to attack the client side of web applications), but it is simply the same origin policy being in effect here. You can't simply request data with an Ajax request from a domain other than your own (your own meaning the one your web application was loaded from).
Learn more about it here: http://en.wikipedia.org/wiki/Same_origin_policy