/*
 [JSON Request Object]

 This script is based on http://www.xml.com/pub/a/2005/12/21/json-dynamic-script-tag.html.
 It was slightly modified to make it easier to use.

 Security Warning:
 "The dynamic <script> tag hack suffers from a problem. It allows a page
 to access data from any server in the web, which is really useful.
 Unfortunately, the data is returned in the form of a script. That script
 can deliver the data, but it runs with the same authority as scripts on
 the base page, so it is able to steal cookies or misuse the authorization
 of the user with the server. A rogue script can do destructive things to
 the relationship between the user and the base server."

 So, be extremely cautious in your use of this script.  According JSON.org,
 this method should only be used when the source is trusted.  See
 http://www.json.org/js.html.  Although this page refers to using eval() + XHR with JSON,
 the dynamic script approach is equivalent; they both evaluate unchecked JavasScript.
 When the source is not trusted, a JSON parser like the one on the json.org page should
 be used, to ensure only data, not code, is evaluated.  But if the server is trusted, the parser
 should not be used as it adds overhead.

 Sample Usage:
 <script type="text/javascript" src="jsr_class.js"></script>

 function callbackfunc(jsonData) {
      alert('Latitude = ' + jsonData.ResultSet.Result[0].Latitude +
            '  Longitude = ' + jsonData.ResultSet.Result[0].Longitude);
      aObj.removeScriptTag();
 }

 request = 'http://api.local.yahoo.com/MapsService/V1/geocode?appid=YahooDemo&
            output=json&callback=callbackfunc&location=78704';
 aObj = new JSONscriptRequest(request);
 aObj.makeRequest();

 Memory Usage:
 You should remove script tags you create as a result of making AJAX request if
 the client can potentially make lots of request.  This is to keep the web page (hence
 the browser's) memory overhead small.  In the case that you can't remove script tags
 individually, removeAllScriptTags() could be used.
*/


//------------------------------------------------------------- Class Variables

// Static script ID counter
JSONscriptRequest.scriptCounter = 1;

// Script Tag ID prefix
JSONscriptRequest.idPrefix = 'JscriptId';

//------------------------------------------------------------- Constructor

/**
 * Construct a JSON request object.  A new request object should be created  per request.
 *
 * @fullUrl   URL to the JSON aware web service.
 */
function JSONscriptRequest(fullUrl) {
    // TODO: handle the situation where the URL doesn't contain an ? (eylin)
    // TODO: handle the situation where the & in &noCacheIE isn't necessary (i.e. no parameter in URL) (eylin)

    // REST request path
    this.fullUrl = fullUrl; 
    // Keep IE from caching requests
    this.noCacheIE = '&noCacheIE=' + (new Date()).getTime();
    // Get the DOM location to put the script tag
    this.headLoc = document.getElementsByTagName("head").item(0);
    // Generate a unique script tag id
    this.scriptId = JSONscriptRequest.idPrefix + JSONscriptRequest.scriptCounter++;
}

//------------------------------------------------------------- Instance Methods

/**
 * Make the JSON request.  The JSON call back method will be invoked when the data returns.
 */
JSONscriptRequest.prototype.makeRequest = function () {
    // Builds the script tag and add it to the document, which effectively starts the request.

    // Create the script tag
    this.scriptObj = document.createElement("script");
    
    // Add script object attributes
    this.scriptObj.setAttribute("type", "text/javascript");
    this.scriptObj.setAttribute("charset", "utf-8");
    this.scriptObj.setAttribute("id", this.scriptId);

    // If the url doesn't already have parameters (question mark), add a question mark to it. 
    if (this.fullUrl.indexOf("?") == -1) {
        this.scriptObj.setAttribute("src", this.fullUrl + '?' + this.noCacheIE);
    } else {
        this.scriptObj.setAttribute("src", this.fullUrl + this.noCacheIE);
    }

    // Logging
    a10.debug('Making Json request: ' + this.fullUrl);

    // Add request to document, which starts the request.
    this.headLoc.appendChild(this.scriptObj);
}

/**
 * Remove script tag associated with this request.
 */
JSONscriptRequest.prototype.removeScriptTag = function () {
    // Destroy the script tag
    this.headLoc.removeChild(this.scriptObj);    
}

//------------------------------------------------------------- Class Methods

/* Remove all script tags generated by all prior JSON requests created using this class from the document.
   This method is useful when script tags are added to the document but not removed individually due to the the
   possibility of multiple requests happening at the same time and out-of-order responses.  In that case, the client
   would simply wipe out all script tags at the end of some period by calling this method.
 */
JSONscriptRequest.removeAllScriptTags = function () {
    var head = document.getElementsByTagName("head").item(0);
    var i;

    if (head) {
        var children = head.childNodes;

        for (i = 0; i < children.length; i++) {
            if (children[i].nodeType == 1 &&
                children[i].tagName == "SCRIPT" &&
                children[i].id.indexOf(JSONscriptRequest.idPrefix) == 0) {
                 head.removeChild(children[i]);
            }
        }
    }
}

