views:

100

answers:

3

I have a Javascript object that I want to pass in more parameters, but the documentation is non-existant. My only option seems to be to reverse engineer the Javascript object to see what parameters and values I can pass in.

For example, I want to see if there is a "zoom" parameter for the object and what values I can pass into the "mapType" parameter:

<script type="text/javascript" src="http://maps.google.com/maps?oe=utf-8&amp;amp;file=api&amp;amp;v=2&amp;amp;key=your-gmap-key"&gt;&lt;/script&gt;
<script type="text/javascript" src="https://share.findmespot.com/spot-widget/js/SpotMain.js"&gt;&lt;/script&gt;
<script type="text/javascript">
 var widget = new Spot.Ui.LiveWidget({ renderTo: "spot-live-widget",
   feeds: [ "0Wl3diTJcqqvncI6NNsoqJV5ygrFtQfBB" ],
   height: 400,
   width: 500,
   mapType: "physical"
 });
</script>
<div id="spot-live-widget"/>

Any ideas on how to do that?

+2  A: 

Function#toString

Most Javascript implementations will return the source code of a function if you call the function instance's toString method:

function foo() {
    return a;
}
alert(foo.toString()); // Alerts "function foo() { return a; }"

This is non-standard behavior, but widely-supported; you may find it quite useful for reverse-engineering. Calling it on the Spot.Ui.LiveWidget function may be interesting, as well as on functions bound to the properties of the object it returns. Which brings us to...

Edit Of course, if unobfuscated source is available (shout out to Sean), you don't need this...

Looping through Properties: for..in

If it's really a Javascript object, you can do this to find out what properties it has:

var name, own;

for (name in obj) {
    own = obj.hasOwnProperty(name);
    alert(name + " (" + (own ? "own" : "inherited") + ")");
}

That will tell you the names of its (enumerable) properties and whether those are properties of the instance itself, or its prototype object.

for..in Example

function Thingy() {
}
Thingy.prototype.alpha = "a";

var t = new Thingy();
t.beta = "2";

The loop above would show:

    alpha (inherited)
    beta (own)

(In no particular order.)

Further Information

Enumerable vs. Non-Enumerable properties

Note that not all properties are "enumerable". For instance, all (or nearly all) of the properties specified by the spec on objects like Array, String, etc. are non-enumerable. But until recently that was just something that could be done by the Javascript implementation itself; there was no mechanism for marking your own properties as being non-enumerable. The new 5th edition spec provides a means of doing that, but it isn't widely supported or used (yet).

Non-Existant Properties

The object you're querying may change its behavior based on whether a property is present or not; in that situation, you'd have no way of knowing, since a non-existant property doesn't show up in the for..in loop (unlike a property that exists but has an undefined value, which does). E.g.:

function doSomething(options) {
    if (options.foo) {
        // There's a `foo` and it has a value; do something with it
}

The foo property may not exist at all on options, so this reverse-engineering wouldn't reveal that the code did something with it.

Warning

Do not try the for..in loop above on host objects, such as DOM nodes. It may work in some implementations, but usually not, and in some cases (IE6) it'll crash the browser. It's totally safe for Javascript objects, though.

T.J. Crowder
+1 Nice one.(pad)
c0mrade
+3  A: 

Well... you could look at the source...

Your code leads to https://share.findmespot.com/spot-widget/js/SpotMain.js which leads to https://share.findmespot.com/spot-widget/js/Spot.js, which you unpack using http://jsbeautifier.org/ which shows you that no, it cannot take a 'zoom' parameter in its constructor, but it does have a setZoomAndCenter method

setZoomAndCenter: function (C) {
    var B = new GLatLngBounds;
    for (var A = 0; A < C.length; A++) {
        B.extend(C[A].getPoint())
    }
    this._map.setZoom(this._map.getBoundsZoomLevel(B));
    this._map.setCenter(B.getCenter())
},

And from this we can see that it has a 'private' member _map, which has a setZoom method.

Does this help?

UPDATE

The above method was actually a member of Spot.Ui.MapRenderer, not the LiveWidget.

The MapRenderer is used internally by LiveWidget but is not exposed...

Sean Kinsey
WOW it more than helps! It's brilliant!! It gets me through a lot.. but stuck on an undefined function when trying: widget.setZoomAndCenter(new GLatLng(0, 0), 6); Am I trying this correctly?
TruMan1
I have no knowledge of this widget other that what I glanced at.Which function is undefined? What does `"setZoomAndCenter" in widget` return (true if the method is present)?
Sean Kinsey
See my updated answer.
Sean Kinsey
A: 

There is no guarantee that the properties listed in a configuration parameter will match those of the resulting object, or that they will be copied to the resulting object even if they are.

The only way to find out is to look at the code in the LiveWidget "constructor" function, and see what properties it expects from the configuration parameter.

Paul Butcher