/* * Copyright (c) 2012, Andy Janata * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are permitted * provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this list of conditions * and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this list of * conditions and the following disclaimer in the documentation and/or other materials provided * with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** * AJAX utility functions for cah. Core library. Individual handlers should be elsewhere. * * @author ajanata */ cah.Ajax = {}; cah.Ajax.instance = {}; cah.ajax = {}; cah.ajax.ErrorHandlers = {}; cah.ajax.SuccessHandlers = {}; /** * An AJAX helper. This wraps around jQuery's AJAX function, and dispatches results to the * appropriate handler. * * @author Andy Janata (ajanata@socialgamer.net) * @constructor */ cah.Ajax = function() { // TODO run a timer to see if we have more than X pending requests and delay further ones until // we get results /** * Id->data map of active requests. This is so we can map back to the request data when we get a * response. * * @type {Object} * @private */ this.pendingRequests_ = {}; }; $(document).ready(function() { /** * Singleton instance for ajax utility. * * @type {cah.Ajax} */ cah.Ajax.instance = new cah.Ajax(); $.ajaxSetup({ cache : false, context : cah.Ajax.instance, error : cah.Ajax.instance.error, success : cah.Ajax.instance.done, timeout : cah.DEBUG ? undefined : 10 * 1000, // 10 second timeout for normal requests type : 'POST', url : cah.AJAX_URI, }); }); /** * Send an ajax request to the server, and store that the request was sent so we know when it gets * responded to. This should be used for data sent to the server, not long-polling. * * @param {cah.ajax.Builder} * builder Request builder containing data to use. */ cah.Ajax.prototype.requestWithBuilder = function(builder) { var jqXHR = $.ajax({ data : builder.data }); this.pendingRequests_[builder.getSerial()] = builder; cah.log.debug("ajax req", builder.data); if (builder.errback) { jqXHR.fail(builder.errback); } }; /** * Handler for when there is a communication-level error with an ajax request. This will likely be * because the server isn't responding or returned malformed data. * * @param {Object} * jqXHR The jQueryXmlHttpRequest. * @param {String} * textStatus Status message. * @param {String} * errorThrown Error cause. */ cah.Ajax.prototype.error = function(jqXHR, textStatus, errorThrown) { // TODO deal with this somehow // and figure out which request it was so we can remove it from pending debugger; cah.log.error(textStatus + " " + errorThrown); }; /** * Handler for when an ajax request is completed sucessfully. Examine the result and dispatch it to * the appropriate handler. * * @param {Object} * data Data returned from the server. */ cah.Ajax.prototype.done = function(data) { cah.log.debug("ajax done", data); if (data[cah.$.AjaxResponse.ERROR]) { // TODO cancel any timers or whatever we may have, and disable interface // or probably in individual error handlers as there are some errors that are fine like // "you don't have that card" etc. var req = this.pendingRequests_[data[cah.$.AjaxResponse.SERIAL]]; if (req && cah.ajax.ErrorHandlers[req.getOp()]) { cah.ajax.ErrorHandlers[req.getOp()](data); } else { cah.log.error(cah.$.ErrorCode_msg[data[cah.$.AjaxResponse.ERROR_CODE]]); } } else { var req = this.pendingRequests_[data[cah.$.AjaxResponse.SERIAL]]; if (req && cah.ajax.SuccessHandlers[req.getOp()]) { cah.ajax.SuccessHandlers[req.getOp()](data, req.data); } else if (req) { cah.log.error("Unhandled response for op " + req.getOp()); } else { cah.log.error("Response for unknown serial " + data[cah.$.AjaxResponse.SERIAL]); } } var serial = data[cah.$.AjaxResponse.SERIAL]; if (serial >= 0 && this.pendingRequests_[serial]) { delete this.pendingRequests_[serial]; } }; /** * Get a builder for an ajax request. * * @param {string} * op Operation code for the request. * @returns {cah.ajax.Builder} Builder to create the request. */ cah.Ajax.build = function(op) { return new cah.ajax.Builder(op); };