I am doing some research on a running website, and the behavior of the code just surprises me.
They defined a function named '__jsload' and bind it to window.
window._jsload = function(hJ, hK) {
var i = d2.getModuleInfo(hJ);
i.status = d2.Request.LOADED;
if (hK !== "") {
d2.run(hJ, hK)
} else {
if (window.map) {
var e = new a6("ongetmodules_fail");
e.moduleName = hJ;
window.map.fire(e)
}
var T = document.createElement("script");
var hI = d2.MD5Mapping[hJ];
T.src = d2.Config.jsModPath + hJ + "_" + hI + ".js";
document.getElementsByTagName("head")[0].appendChild(T)
}
};
In the run function, there's only an eval(), it seems nothing is stored for future use.
run: function(T, hI) {
var hM = this.getModuleInfo(T);
var hP = this.Dependency[T];
if (hP) {
for (var hK = 0; hK < hP.length; hK++) {
var hL = this.getModuleInfo(hP[hK]);
if (hL.status !== this.Request.COMPLETED) {
hL.modsNeedToRun.push({
name: T,
code: hI
});
return
}
}
}
try {
eval(hI)
} catch (hN) {
return
}
hM.status = this.Request.COMPLETED;
for (var hK = 0, hJ = hM.callbacks.length; hK < hJ; hK++) {
hM.callbacks[hK]()
}
hM.callbacks.length = 0;
for (hK = 0; hK < hM.modsNeedToRun.length; hK++) {
var hO = hM.modsNeedToRun[hK];
this.run(hO.name, hO.code)
}
hM.modsNeedToRun.length = 0
},
Then all the module are written in the following manner.
/**/_jsload&&_jsload(
// this should be the module name
'glcommon',
// this should be the module content
'function aO(e,i)......'
)
I have a little experience in coding in python, so I thought those loaded modules will be special objects, and I can access functions defined in the module by just calling them.
import pandas as pd
pd.DataFrame()
And I searched some references on coding in javascript, they mentioned something like 'import/export' and maybe 'require'. After importing the module, I can call exported function just by calling the name.
// in sayHi.js
export function sayHi(user) {
alert(`Hello, ${user}!`);
}
// in main.js
import {sayHi} from './sayHi.js';
alert(sayHi); // function...
sayHi('John'); // Hello, John!
None of these things happens in that website I'm researching on. There's even no 'export' in the whole module text.
So, here rises my question.
Is it possible to call the function in a module in the web console? If it's not bound to the window object, will it still be possible?
We all know that currently a lot of web pages are dynamic, when a certain event happens, a certain function relate to it should be called. So, where are those functions saved? Are they still reachable during the web is running?
3.How can I debug modules like the above ones, when you can't get a pretty printed version of code and make some breakpoints? I tried to go step by step, but all the functions go into the text versioned module, and I can't make a breakpoint.
Related
After reading the following article,
http://javascriptplayground.com/blog/2012/04/javascript-module-pattern/
I have decided to start implementing modules in my JS.
Unfortunately, the module I am using does not seem to be keeping the private variable private,
var popoverOptionsModule = (function() {
var _stopAskingList = [];
var addToStopAskingList = function(itemToAdd) {
if (_stopAskingList.indexOf(itemToAdd) === -1){
_stopAskingList.push(itemToAdd);
}
}
var getStopAskingList = function() {
return _stopAskingList;
}
return {
addToStopAskingList: addToStopAskingList,
getStopAskingList: getStopAskingList,
};
})();
popoverOptionsModule._stopAskingList = 4;
console.log(popoverOptionsModule._stopAskingList);
As you can see, I am able to change the value of
popoverOptionsModule._stopAskingList and log the update to the console... I thought this was not supposed to happen. Thanks for your help!
JS is completely dynamically typed, so when you have the line
popoverOptionsModule._stopAskingList = 4;
You've just created this variable and assigned it a value, hence why the next line succeeds. If you didn't have this line, then the subsequent console.log would report undefined. This code would work too
popoverOptionsModule._abc = 4;
console.log(popoverOptionsModule._abc);
Remember that this isn't actually a private variable in the same way that OO languages implement protection levels, rather it's just an API pattern that attempts to hide it from the caller.
I'm currently trying to make a HTML/JavaScript Windows 8 modern application in which I want to access a local XML file that is in the installation directory.
After reading many ideas and code snippets around the web, I came up with a convoluted asynchronous method of accessing the file, which works. However, is this the best/correct way to do something as simple as accessing a local XML file?
Additionally, I'd like to be able to have a function load the xml file, and save the XMLDocument object as a "global" variable, so that on button presses and other triggers, the XMLDocument object can be accessed and parsed. This is where all the problems start, since one method is async, and then the variables are undefined, etc....
(function () {
"use strict";
WinJS.UI.Pages.define("/pages/reader/reader.html", {
// This function is called whenever a user navigates to this page. It
// populates the page elements with the app's data.
ready: function (element, options) {
// TODO: Initialize the page here.
var button = document.getElementById("changeText");
button.addEventListener("click", this.buttonClickHandler, false);
var dropdown = document.getElementById("volumeDropdown");
dropdown.addEventListener("change", this.volumeChangeHandler, false);
var loadSettings = new Windows.Data.Xml.Dom.XmlLoadSettings;
loadSettings.prohibitDtd = false;
loadSettings.resolveExternals = false;
//previous attempt, also didn't work:
//this.xmlDoc = null;
//this.loadXMLdoc(this, this.testXML);
//also not working:
this.getXmlAsync().then(function (doc) {
var xmlDoc = doc;
});
//this never works also, xmlDoc always undefined, or an error:
//console.log(xmlDoc);
},
buttonClickHandler: function (eventInfo) {
// doesn't work, xmlDoc undefined or error:
console.log(xmlDoc);
},
volumeChangeHandler: function (eventInfo) {
var e = document.getElementById("volumeDropdown");
// of course doesn't work, since I can't save the XMLDocument object into a variable (works otherwise):
var nodelist2 = xmlDoc.selectNodes('//volume[#name="volumeName"]/chapter/#n'.replace('volumeName', list[0]));
var volumeLength = nodelist2.length;
for (var index = 0; index < volumeLength; index++) {
var option = document.createElement("option");
option.text = index + 1;
option.value = index + 1;
var volumeDropdown = document.getElementById("chapterDropdown");
volumeDropdown.appendChild(option);
}
},
getXmlAsync: function () {
return Windows.ApplicationModel.Package.current.installedLocation.getFolderAsync("books").then(function (externalDtdFolder) {
externalDtdFolder.getFileAsync("book.xml").done(function (file) {
return Windows.Data.Xml.Dom.XmlDocument.loadFromFileAsync(file);
})
})
},
loadXMLdoc: function (obj, callback) {
var loadSettings = new Windows.Data.Xml.Dom.XmlLoadSettings;
loadSettings.prohibitDtd = false;
loadSettings.resolveExternals = false;
Windows.ApplicationModel.Package.current.installedLocation.getFolderAsync("books").then(function (externalDtdFolder) {
externalDtdFolder.getFileAsync("book.xml").done(function (file) {
Windows.Data.Xml.Dom.XmlDocument.loadFromFileAsync(file, loadSettings).then(function (doc) {
var nodelist = doc.selectNodes("//volume/#name");
var list = [];
for (var index = 0; index < nodelist.length; index++) {
list.push(nodelist[index].innerText);
};
for (var index = 0; index < list.length; index++) {
var option = document.createElement("option");
option.text = list[index] + "new!";
option.value = list[index];
var volumeDropdown = document.getElementById("volumeDropdown");
volumeDropdown.appendChild(option);
};
var nodelist2 = doc.selectNodes('//volume[#name="volumeName"]/chapter/#n'.replace('volumeName', list[0]));
var volumeLength = nodelist2.length;
for (var index = 0; index < volumeLength; index++) {
var option = document.createElement("option");
option.text = index + 1;
option.value = index + 1;
var volumeDropdown = document.getElementById("chapterDropdown");
volumeDropdown.appendChild(option);
};
obj.xmlDoc = doc;
callback(obj);
})
})
});
},
initializeXML: function (doc, obj) {
console.log("WE ARE IN INITIALIZEXML NOW")
obj.xmlDoc = doc;
},
testXML: function (obj) {
console.log(obj.xmlDoc);
},
});
})();
In summary with all these complicated methods failing, how should I go about doing something as simple as loading an XML file, and then having it available as an object that can be used by other functions, etc.?
Thanks for your help!
PS:
I'm very new to JavaScript and Windows 8 Modern Apps/ WinAPIs.
Previous experience all in Python and Java (where doing this is trivial!).
There are a couple of things going on here that should help you out.
First, there are three different loading events for a PageControl, corresponding to methods in your page class. The ready method (which is the only one the VS project template includes) gets called only at the end of the process, and is thus somewhat late in the process for doing an async file load. It's more appropriate to do this work within the init method, which is called before any elements have been created on the page. (The processed method is called after WinJS.UI.processAll is complete but before the page has been added to the DOM. ready is called after everything is in the DOM.)
Second, your getXMLAsync method looks fine, but your completed handler is declaring another xmlDoc variable and then throwing it away:
this.getXmlAsync().then(function (doc) {
var xmlDoc = doc; //local variable gets discarded
});
The "var xmlDoc" declares a local variable in the handler, but it's discarded as soon as the handler returns. What you need to do is assign this.xmlDoc = doc, but the trick is then making sure that "this" is the object you want it to be rather than the global context, which is the default for an anonymous function. The pattern that people generally use is as follows:
var that = this;
this.getXmlAsync().then(function (doc) {
that.xmlDoc = doc;
});
Of course, it's only after that anonymous handler gets called that the xmlDoc member will be valid. That is, if you put a console.log at the end of the code above, after the });, the handler won't have been called yet from the async thread, so xmlDoc won't get be valid. If you put it inside the handler immediately after that.xmlDoc = doc, then it should be valid.
This is all just about getting used to how async works. :)
Now to simplify matters for you a little, there is the static method StorageFile.getFileFromApplicationUriAsync which you can use to get directly to in-package file with a single call, rather than navigating folders. With this you can load create the XmlDocument as follows:
getXmlAsync: function () {
return StorageFile.getFileFromApplicationUriAsync("ms-appx:///books/book.xml").then((function (file) {
return Windows.Data.Xml.Dom.XmlDocument.loadFromFileAsync(file);
}).then(function (xmlDoc) {
return xmlDoc;
});
}
Note that the three /// are necessary; ms-appx:/// is a URI scheme that goes to the app package contents.
Also notice how the promises are chained instead of nested. That's typically a better structure, and one that allows a function like this to return a promise that will be fulfilled with the last return value in the chain. This can then be used with the earlier bit of code that assigns that.xmlDoc, and you avoid passing in obj and a callback (promises are intended to avoid such callbacks).
Overall, if you have any other pages in your app to which you'll navigate, you'll really want to load this XML file and create the XmlDocument once for the app, not with the specific page. Otherwise you'd be reloading the file every time you navigate to the page. For this reason, you could choose to do the loading on app startup, not page load, and use WinJS.Namespace.define to create a namespace variable in which you store the xmlDoc. Because that code would load on startup while the splash screen is visible, everything should be ready when the first page comes up. Something to think about.
In any case, given that you're new to this space, I suggest you download my free ebook, Programming Windows Store Apps with HTML, CSS, and JavaScript, 2nd Edition, where Chapter 3 has all the details about app startup, page controls, and promises (after the broader introductions of Chapters 1 and 2 of course).
Ok, first up I know an object has no reference to it's container unless explicitly defined, so I am looking for a work around here.
Take the following code (heavily simplified from my use case for readability):
var cid = 0;
var Command = function(c) {
this.id = cid += 1;
this.transient = false;
return this;
}
var sid = 0;
var CommandSet = function() {
this.id = sid += 1;
this.commands = [];
this.transients = 0;
return this;
}
CommandSet.prototype.parent = null;
CommandSet.prototype.recurse = function(callback) {
callback.call(this);
if (this.parent instanceof CommandSet) {
this.parent.recurse(callback);
}
}
CommandSet.prototype.createSubset = function() {
var set = new CommandSet();
set.parent = this;
set.commands = this.commands;
set.transients = this.transients;
return set;
}
CommandSet.prototype.addCommand = function(c) {
if (c instanceof Command) {
this.commands.push(c);
if (c.transient) {
this.recurse(function() {
this.transients++;
});
}
}
return this;
}
CommandSet.prototype.toggleTransient = function(c) {
if (c instanceof Command) {
c.transient = true;
this.recurse(function() {
this.transients++;
});
}
return this;
}
If I then do the following (http://jsfiddle.net/5KGd8/1/):
var s1 = new CommandSet();
var c1 = new Command();
var c2 = new Command();
s1.addCommand(c1).addCommand(c2);
var s2 = s1.createSubset();
var s3 = s1.createSubset();
s2.toggleTransient(c1);
console.log(s1);
console.log(s2);
console.log(s3);
s1 now has 1 transient, s2 now has 1 transient but s3 still has none despite containing a reference to the same Command objects.
Possible solutions:
I could build a reference into each command which stores all the
sets it is located inside and iterate through those, however this is
going to cause some serious memory issues as the real nature of my
application requires that subsets can be garbage collected (The user
will create a lot of them anonymously often without realising) and this will retain a
reference to them after they have been used. The parent reference is fine as I want the parent set to exist as long as it has a surviving subset.
I could explicitly force the user to run a delete function on a
subset when it is no longer needed which would remove all internal references to it but this complicates things for
them and I like things to work automagically. The nature of my application means I would like the user to create subsets at times where they may not even realise they have done so (Through other functions which create and perform on subsets).
Can anyone think of a way to solve this problem without the issues described in my two solutions?
Sorry, this is not an answer but want to make sure I understand the problem.
A CommandSet can have Commands, when you change a Command's transient property you would like the CommandSet(s) that contain that Command to have an updated counter of transient the Commands it contains.
If the story ends here you could simply have Command maintain a list of CommandSet that the Command is in and update it's containers.
This would not work however because you would have CommandSets created in a function and when these go out of scope they won't be garbage collected because the Command(s) they contain would hold a reference to them. These commands would not go out of scope with the CommandSets because they are also contained in other (global) CommandSets.
Re assigning a primitive type (transients) does not re assign that in the subset or main set, but what if transients was not a primitive?
In the constructor:
this.transients = {count:0};
In createSubset
set.transients = this.transients
In the toggleTransient
this.transients.count++; or --
No matter if you fiddle with transients in subset or main set, as long as you use the toggleTransient it'll change count for all.
I have the following dart code:
$ cat helloworld.dart
main() => print('Hello world!');
$
The javascript code generated by the dart compiler for the above code is as follows:
$ cat helloworld.dart.app.js
function native_ListFactory__new(typeToken, length) {
return RTT.setTypeInfo(
new Array(length),
Array.$lookupRTT(RTT.getTypeInfo(typeToken).typeArgs));
}
function native_ListImplementation__indexOperator(index) {
return this[index];
}
function native_ListImplementation__indexAssignOperator(index, value) {
this[index] = value;
}
function native_ListImplementation_get$length() {
return this.length;
}
function native_ListImplementation__setLength(length) {
this.length = length;
}
function native_ListImplementation__add(element) {
this.push(element);
}
function native_BoolImplementation_EQ(other) {
return typeof other == 'boolean' && this == other;
}
function native_BoolImplementation_toString() {
return this.toString();
}
<snapped>
var static$uninitialized = {};
var static$initializing = {};
function $inherits(child, parent) {
if (child.prototype.__proto__) {
child.prototype.__proto__ = parent.prototype;
} else {
function tmp() {};
tmp.prototype = parent.prototype;
child.prototype = new tmp();
child.prototype.constructor = child;
}
}
isolate$inits.push(function(){
isolate$current.Duration$DartMILLISECONDS_PER_MINUTE$field = static$uninitialized;
isolate$current.Duration$DartMILLISECONDS_PER_HOUR$field = static$uninitialized;
isolate$current.Duration$DartMILLISECONDS_PER_DAY$field = static$uninitialized;
isolate$current.Duration$DartSECONDS_PER_HOUR$field = static$uninitialized;
isolate$current.Duration$DartSECONDS_PER_DAY$field = static$uninitialized;
isolate$current.Duration$DartMINUTES_PER_DAY$field = static$uninitialized;
}
);
RunEntry(unnamedd9297f$main$member, this.arguments ? (this.arguments.slice ? [].concat(this.arguments.slice()) : this.arguments) : []);
$
And the size of helloworld.dart.app.js is 102k!
When ran in optimize mode, it generated the following javascript - helloworld.dart.js which is of size 20k
$ cat helloworld.dart.js
var e;function f(a,b){if(b>=0&&b<a.length)return b;h(i(b))};var j={},k={};function aa(a,b,c){if(b)a.g=function(){return b.call(c)}}function ba(a,b,c,d){function g(b,g,t,m){return a.call(c,d,b,g,t,m)}aa(g,b,c);return g}function l(a,b){if(a.prototype.__proto__)a.prototype.__proto__=b.prototype;else{var c=function(){};c.prototype=b.prototype;a.prototype=new c;a.prototype.constructor=a}}function ca(a,b){return typeof a=="number"&&typeof b=="number"?a+b:a.na(b)}function da(a){a/=4;return a<0?Math.ceil(a):Math.floor(a)}
function o(a,b){if(a===void 0)return b===void 0;else if(typeof a==typeof b&&typeof a!="object")return a===b;return a.G(b)}function h(a){a&&typeof a=="object"&&Error.captureStackTrace&&Error.captureStackTrace(a);throw a;}function p(){var a=new q;a.f=s("ya",ea);a.va="";a.qa="";a.N=[];h(a)}var u={d:0};
<snapped>
y.push(function(){x.fb=j;x.eb=j;x.gb=j});y.push(function(){x.Ta=j;x.Sa=j;x.Ra=j;x.Wa=j;x.Va=j;x.Ua=j});(function(a,b){if(!A){var c=new ya;oa=c;sa(c,function(){a(b)});Ea();x=c}})(function(){return qb()(1,u,"Hello world!")},this.arguments?this.arguments.slice?[].concat(this.arguments.slice()):this.arguments:[]);
$
Why is the javascript code which was generated by a dart compiler so huge?
What problem are they trying to solve by generating such huge javascript files?
Side Note: The javascript files were so huge, SO threw the following error:
Oops! Your question couldn't be submitted because: body is limited to 30000 characters; you entered 140984
What problem are they trying to solve by generating such huge javascript files?
The problem of balancing Dart to be optimal in the majority of cases, rather than just this one personal, specific, contrived, useless example program that nobody would ever seriously try to use in a production project.
If you would like to get even a better JavaScript, try the Frog compiler instead of DartC. Frog ist written in Dart itself.
http://turbomanage.wordpress.com/2011/12/09/dart-dev-mode-cometh/
Note, this blogpost above is a bit outdated. You can meanwhile use the Dart SDK for Frog:
http://gsdview.appspot.com/dart-editor-archive-continuous/3058/
This post might also be of interest for you, Seth shows how the Frog generated JS looks like:
http://blog.sethladd.com/2011/12/10-lessons-from-porting-javascript-to.html
Here is how you can enable Frog in current Editor:
https://groups.google.com/a/dartlang.org/group/misc/msg/5dfe04c69ed0fed3
Why is the javascript code which was generated from a dart code by a dart compiler is so huge?
Because it includes a Dart runtime.
What problem are they trying to solve by generating such huge javascript files?
The problem of running code that is not JavaScript in a browser.
this is my first post, but i'm excited to join this community. I have a question regarding JavaScript which I am completely stumped about.
I'm writing a JavaScript application which pulls data from a server using ajax and adds it to a chart. I'm using Jquery and Highcharts as the framework and then writing my own JavaScript 'wrapper' around Highcharts to produce the interface.
When the processData function get called back with the jSON response, it begins with i=1, even though i shouldn't even be initialized or even declared yet. Other variables are set as well. (I know this from using chrome developer tools to debug). This makes my loop not execute and none of my data gets added to the chart.
I don't know how much code to show, but these are the most relevant parts. I can add more if needed.
function getData(series, min, max, numpts) {
if (series === undefined) {
console.log("error on getData");
return;
}
var request = {};
request.series = series;
if (min !== undefined) {
request.start = min;
} //in seconds
if (max !== undefined) {
request.end = max;
}
if (numpts !== undefined) {
request.numpts = numpts;
}
$.getJSON('/data', request, processData);
return;
}
function processData(data) {
// handle the data after it comes back from an ajax request
var curSeries,
chartSeries,
curPoint;
for (var i = 0; i < data.length; i ++) {
curSeries = data[i];
chartSeries = chart.get(curSeries.name);
if (chartSeries === null) {
//alert("oops");
chart.addSeries(curSeries);
} else {
for (var j = 0; j < curSeries.data.length; j ++) {
curPoint = curSeries.data[j];
chartSeries.addPoint(curPoint, false);
}
}
}
chart.redraw();
}
These are both methods of a class I declared called graph.
Thanks if anyone has any ideas!
-Matt P
I'd console inspect your data object to make sure it's what you expect, as that loop should be working fine even if i is pre-declared: you're assigning 0 to it at the beginning of the loop, anyway.
The only reason I can think of that i would be defined and initialized before you defined and initialized it is if somewhere else in your codebase you don't initialize the i with the var keyword. Doing that would dump it into the global scope (the window object), making it available via closure to any and every function in your codebase.
If it's not in one of your files, it may be in the highcharts graphing library (in which case run very quickly away from said library).