I currently have a Web Application that runs off a global Javascript-based API, and it is initialized like this:
var Api = {
someVar: "test",
someFunction: function() {
return "foo";
}
}
This API is shared across many “Widgets” that live in the Web Application, and they should all run off this single Api instance so they can pass data to each other.
AJAX is currently used to load these Widgets, for example in widgets/mywidget.html, and it’s placed in, say, <div id='widget_<random number>'>...</div>
Certain other parts of the code may choose to add more functionality to Api, and it’s currently done like this:
Api.myExtension = {
myNewFunction: function() {
return "bar";
}
}
However, some issues arise from this kind of usage:
Problem One: What if one Widget (these may be provided by third-parties) decides to hide some code within, and does something similar to Api = {}, destroying the global Api var everything lives on, and breaking the whole Application? Is it possible to protect this Api variable from being overwritten from outside? Only “extending” is allowed (adding new things), but “removing/changing” is not allowed. i.e.:
Api.foo = { test: "bar" } // allowed
Api.someVar = "changing the existing someVar"; // not allowed
The following code is located “inside” Api, for example:
var Api = {
Debug: {
Messages = new Array,
Write: function() {
Api.Debug.Messages.push("test"); // allowed
}
}
}
Api.Debug.Messages.push("test 2"); // not allowed
Probable Solutions I’ve Thought Of:
-
Suppose we simply use frames to resolve this issue. The
Apis provided are now separate from each other. However, there’s additional overhead when loadingApiagain and again if I have manyWidgets running, and they can no longer communicate with the “Host” of the widgets (the page where frames reside in), for example, I may want to tell the host to show a notification:Api.Notify.Show("Test"), but it cannot do so because thisApiis completely independent from other instances, and it cannot communicate with the “Host” -
Using something like a “getter” and “setter” function for the Api to be read and written. I’m unsure on how to implement this, so any help on directions on how to implement this is welcome!
-
A mixture of 1/2?
The only way (at least that I can think of) to protect your global variable is to prevent the Widgets from having a direct access to it. This can be achieved by using frames functions, as you suggested. You should create an object that contains all the functions that the Widgets should be able to use, and pass such to each Widget. For example:
This way, the Widgets could execute functions and communicate with the host or global variable
Api. To set variables, the Widget would be editing its private object, rather than the global one. For every frame (that represents a Widget), you must initialize or create a copy of thewidgetApiobject, and probably store it inside an array, in such a way that an instance of a Widget is stored in the mainApiobject.For example, given
<iframe id="widget"></iframe>You would do the following:
Additionally, in every frame you would need to set the
parentandtopvariables to null so that the Widgets wouldn’t be able to access the data of the main frame. I haven’t tested this method in a while, so there might be ways to get around setting those variables to null.