1. __d("AsyncRequest", ["array-extensions", "event-extensions", "json", "Arbiter", "AsyncDOM", "AsyncResponse", "bootloader", "Cookie", "css-core", "dom", "Env", "JSCC", "Parent", "URI", "Util", "bind", "copyProperties", "evalGlobal", "goURI", "invokeCallbacks", "isEmpty"], function (global, require, requireLazy, module, exports) {
  2.     require("array-extensions");
  3.     require("event-extensions");
  4.     require("json");
  5.     var Arbiter = require("Arbiter");
  6.     var AsyncDOM = require("AsyncDOM");
  7.     var AsyncResponse = require("AsyncResponse");
  8.     var Bootloader = require("bootloader");
  9.     var Cookie = require("Cookie");
  10.     var CSS = require("css-core");
  11.     var DOM = require("dom");
  12.     var Env = require("Env");
  13.     var JSCC = require("JSCC");
  14.     var Parent = require("Parent");
  15.     var URI = require("URI");
  16.     var Util = require("Util");
  17.     var bind = require("bind");
  18.     var copyProperties = require("copyProperties");
  19.     var evalGlobal = require("evalGlobal");
  20.     var goURI = require("goURI");
  21.     var invokeCallbacks = require("invokeCallbacks");
  22.     var isEmpty = require("isEmpty");
  23.  
  24.     function AsyncRequest(uri) {
  25.         var dispatchResponse = bind(this, function (asyncResponse) {
  26.             try {
  27.                 this.clearStatusIndicator();
  28.                 if (!this.isRelevant()) {
  29.                     invokeErrorHandler(1010);
  30.                     return;
  31.                 }
  32.                 if (this.initialHandler(asyncResponse) !== false) {
  33.                     clearTimeout(this.timer);
  34.                     if (asyncResponse.jscc_map) {
  35.                         var jscc_map = eval(asyncResponse.jscc_map);
  36.                         JSCC.init(jscc_map);
  37.                     }
  38.                     if (this.handler) try {
  39.                         var suppress_onload = this.handler(asyncResponse);
  40.                     } catch (exception) {
  41.                         asyncResponse.is_last && this.finallyHandler(asyncResponse);
  42.                         throw exception;
  43.                     }
  44.                     if (suppress_onload !== AsyncRequest.suppressOnloadToken) {
  45.                         var domOps = asyncResponse.domops;
  46.                         if (domOps) AsyncDOM.invoke(domOps, this.getRelativeTo());
  47.                         asyncResponse.jscalls && invokeCallbacks([asyncResponse.jscalls]);
  48.                         var onload = asyncResponse.onload;
  49.                         if (onload) for (var ii = 0; ii < onload.length; ii++) try {
  50.                             (new Function(onload[ii])).apply(this);
  51.                         } catch (exception) {}
  52.                         if (this.lid) Arbiter.inform('tti_ajax', {
  53.                             s: this.lid,
  54.                             d: [this._sendTimeStamp || 0, (this._sendTimeStamp && this._responseTime) ? (this._responseTime - this._sendTimeStamp) : 0]
  55.                         }, Arbiter.BEHAVIOR_EVENT);
  56.                         var onafterload = asyncResponse.onafterload;
  57.                         if (onafterload) for (var ii = 0; ii < onafterload.length; ii++) try {
  58.                             (new Function(onafterload[ii])).apply(this);
  59.                         } catch (exception) {}
  60.                     }
  61.                     asyncResponse.is_last && this.finallyHandler(asyncResponse);
  62.                 }
  63.             } catch (exception) {}
  64.         });
  65.         var dispatchErrorResponse = bind(this, function (asyncResponse, isTransport) {
  66.             try {
  67.                 this.clearStatusIndicator();
  68.                 var async_error = asyncResponse.getError();
  69.                 if (this._sendTimeStamp) {
  70.                     var _duration = Date.now() - this._sendTimeStamp;
  71.                     var xfb_ip = this._xFbServer || '-';
  72.                     asyncResponse.logError('async_error', {
  73.                         duration: _duration,
  74.                         xfb_ip: xfb_ip
  75.                     });
  76.                 } else asyncResponse.logError('async_error');
  77.                 if ((!this.isRelevant()) || async_error === 1010) return;
  78.                 if (async_error == 1357008 || async_error == 1357007 || async_error == 1442002 || async_error == 1357001) {
  79.                     var is_confirmation = false;
  80.                     if (async_error == 1357008 || async_error == 1357007) is_confirmation = true;
  81.                     var payload = asyncResponse.getPayload();
  82.                     this._displayServerDialog(payload.__dialog, is_confirmation);
  83.                 } else if (this.initialHandler(asyncResponse) !== false) {
  84.                     clearTimeout(this.timer);
  85.                     try {
  86.                         if (isTransport) {
  87.                             this.transportErrorHandler(asyncResponse);
  88.                         } else this.errorHandler(asyncResponse);
  89.                     } catch (exception) {
  90.                         this.finallyHandler(asyncResponse);
  91.                         throw exception;
  92.                     }
  93.                     this.finallyHandler(asyncResponse);
  94.                 }
  95.             } catch (exception) {}
  96.         });
  97.         var _interpretTransportResponse = bind(this, function () {
  98.             if (this.getOption('suppressEvaluation')) {
  99.                 var r = new AsyncResponse(this, this.transport);
  100.                 return {
  101.                     asyncResponse: r
  102.                 };
  103.             }
  104.             var _sendError = function (p, error_code, str) {
  105.                     if (!window.send_error_signal) return;
  106.                     if (this._xFbServer) {
  107.                         error_code = '1008_' + error_code;
  108.                     } else error_code = '1012_' + error_code;
  109.                     send_error_signal('async_xport_resp', error_code + ':' + (this._xFbServer || '-') + ':' + p.getURI() + ':' + str.length + ':' + str.substr(0, 1600));
  110.                 };
  111.             var shield = "for (;;);";
  112.             var shieldlen = shield.length;
  113.             var text = this.transport.responseText;
  114.             if (text.length <= shieldlen) {
  115.                 _sendError(this, 'empty', text);
  116.                 return {
  117.                     transportError: 'Response too short on async to ' + this.getURI()
  118.                 };
  119.             }
  120.             var offset = 0;
  121.             while (text.charAt(offset) == " " || text.charAt(offset) == "\n") offset++;
  122.             offset && text.substring(offset, offset + shieldlen) == shield;
  123.             var safeResponse = text.substring(offset + shieldlen);
  124.             try {
  125.                 var response = eval('(' + safeResponse + ')');
  126.             } catch (exception) {
  127.                 _sendError(this, 'excep', text);
  128.                 return {
  129.                     transportError: 'eval() failed on async to ' + this.getURI()
  130.                 };
  131.             }
  132.             return interpretResponse(response);
  133.         });
  134.         var interpretResponse = bind(this, function (response) {
  135.             if (response.redirect) return {
  136.                 redirect: response.redirect
  137.             };
  138.             var r = new AsyncResponse(this);
  139.             if (response.__ar != 1) {
  140.                 r.payload = response;
  141.             } else {
  142.                 copyProperties(r, response);
  143.                 if (response.tplts) if (window.DynaTemplate) DynaTemplate.registerTemplates(response.tplts);
  144.             }
  145.             return {
  146.                 asyncResponse: r
  147.             };
  148.         });
  149.         var invokeResponseHandler = bind(this, function (interp) {
  150.             if (typeof (interp.redirect) != 'undefined') {
  151.                 (function () {
  152.                     this.setURI(interp.redirect).send();
  153.                 }).bind(this).defer();
  154.                 return;
  155.             }
  156.             if (this.handler || this.errorHandler || this.transportErrorHandler) if (typeof (interp.asyncResponse) != 'undefined') {
  157.                 var r = interp.asyncResponse;
  158.                 if (!this.isRelevant()) {
  159.                     invokeErrorHandler(1010);
  160.                     return;
  161.                 }
  162.                 if (r.inlinejs) evalGlobal(r.inlinejs);
  163.                 if (r.lid) {
  164.                     this._responseTime = Date.now();
  165.                     if (window.CavalryLogger) this.cavalry = CavalryLogger.getInstance(r.lid);
  166.                     this.lid = r.lid;
  167.                 }
  168.                 if (r.getError() && !r.getErrorIsWarning()) {
  169.                     var fn = dispatchErrorResponse;
  170.                 } else var fn = dispatchResponse;
  171.                 Bootloader.setResourceMap(r.resource_map);
  172.                 if (r.bootloadable) Bootloader.enableBootload(r.bootloadable);
  173.                 fn = fn.shield(null, r);
  174.                 fn = fn.defer.bind(fn);
  175.                 var is_transitional = false;
  176.                 if (this.preBootloadHandler) is_transitional = this.preBootloadHandler(r);
  177.                 r.css = r.css || [];
  178.                 r.js = r.js || [];
  179.                 Bootloader.loadResources(r.css.concat(r.js), fn, is_transitional, this.getURI());
  180.             } else if (typeof (interp.transportError) != 'undefined') {
  181.                 if (this._xFbServer) {
  182.                     invokeErrorHandler(1008);
  183.                 } else invokeErrorHandler(1012);
  184.             } else invokeErrorHandler(1007);
  185.         });
  186.         var invokeErrorHandler = bind(this, function (explicitError) {
  187.             try {
  188.                 if (!window.loaded && !this.getOption('handleErrorAfterUnload')) return;
  189.             } catch (ex) {
  190.                 return;
  191.             }
  192.             var r = new AsyncResponse(this);
  193.             var err;
  194.             try {
  195.                 err = explicitError || this.transport.status || 1004;
  196.             } catch (ex) {
  197.                 err = 1005;
  198.             }
  199.             if (this._requestAborted) err = 1011;
  200.             try {
  201.                 if (this.responseText == '') err = 1002;
  202.             } catch (ignore) {}
  203.             if (this.transportErrorHandler) {
  204.                 var desc, summary;
  205.                 var silent = true;
  206.                 if (false === navigator.onLine) {
  207.                     summary = "No network connection";
  208.                     desc = "Your browser appears to be offline. Please check your Internet connection and try again.";
  209.                     err = 1006;
  210.                 } else if (err >= 300 && err <= 399) {
  211.                     summary = "Redirection";
  212.                     desc = "Your access to Facebook was redirected or blocked by a third party at this time, please contact your ISP or reload. ";
  213.                     redir_url = this.transport.getResponseHeader("Location");
  214.                     if (redir_url) goURI(redir_url, true);
  215.                     silent = true;
  216.                 } else {
  217.                     summary = "Oops!";
  218.                     desc = "Something went wrong. We're working on getting this fixed as soon as we can. You may be able to try again.";
  219.                 }!this.getOption('suppressErrorAlerts');
  220.                 copyProperties(r, {
  221.                     error: err,
  222.                     errorSummary: summary,
  223.                     errorDescription: desc,
  224.                     silentError: silent
  225.                 });
  226.                 dispatchErrorResponse(r, true);
  227.             }
  228.         });
  229.         var handleResponse = function (response) {
  230.                 var asyncResponse = this.interpretResponse(response);
  231.                 this.invokeResponseHandler(asyncResponse);
  232.             };
  233.         var onStateChange = function () {
  234.                 try {
  235.                     if (this.transport.readyState == 4) {
  236.                         AsyncRequest._inflightPurge();
  237.                         try {
  238.                             if (typeof (this.transport.getResponseHeader) != 'undefined' && this.transport.getResponseHeader('X-FB-Debug')) this._xFbServer = this.transport.getResponseHeader('X-FB-Debug');
  239.                         } catch (ex) {}
  240.                         if (this.transport.status >= 200 && this.transport.status < 300) {
  241.                             AsyncRequest.lastSuccessTime = Date.now();
  242.                             invokeResponseHandler(_interpretTransportResponse());
  243.                         } else if (ua.safari() && (typeof (this.transport.status) == 'undefined')) {
  244.                             invokeErrorHandler(1002);
  245.                         } else if (window.Env && window.Env.retry_ajax_on_network_error && this.transport.status in {
  246.                             0: 1,
  247.                             12029: 1,
  248.                             12030: 1,
  249.                             12031: 1,
  250.                             12152: 1
  251.                         } && this.remainingRetries > 0) {
  252.                             --this.remainingRetries;
  253.                             delete this.transport;
  254.                             this.send(true);
  255.                             return;
  256.                         } else invokeErrorHandler();
  257.                         if (this.getOption('asynchronous') !== false) delete this.transport;
  258.                     }
  259.                 } catch (exception) {
  260.                     try {
  261.                         if (!window.loaded) return;
  262.                     } catch (ex) {
  263.                         return;
  264.                     }
  265.                     delete this.transport;
  266.                     if (this.remainingRetries > 0) {
  267.                         --this.remainingRetries;
  268.                         this.send(true);
  269.                     } else {
  270.                         !this.getOption('suppressErrorAlerts');
  271.                         if (window.send_error_signal) send_error_signal('async_xport_resp', '1007:' + (this._xFbServer || '-') + ':' + this.getURI() + ':' + exception.message);
  272.                         invokeErrorHandler(1007);
  273.                     }
  274.                 }
  275.             };
  276.         var onJSONPResponse = function (data, more_chunked_response) {
  277.                 var is_first = (this.is_first === undefined);
  278.                 this.is_first = is_first;
  279.                 if (this.transportIframe && !more_chunked_response) {
  280.                     if (this.cavalry) this.cavalry.collectBrowserTiming(this.transportIframe.contentWindow);
  281.                     (function (x) {
  282.                         document.body.removeChild(x);
  283.                     }).bind(null, this.transportIframe).defer();
  284.                 }
  285.                 if (ua.ie() >= 9 && window.JSON) data = window.JSON.parse(window.JSON.stringify(data));
  286.                 var r = this.interpretResponse(data);
  287.                 r.asyncResponse.is_first = is_first;
  288.                 r.asyncResponse.is_last = !more_chunked_response;
  289.                 this.invokeResponseHandler(r);
  290.                 return more_chunked_response;
  291.             };
  292.         copyProperties(this, {
  293.             onstatechange: onStateChange,
  294.             onjsonpresponse: onJSONPResponse,
  295.             invokeResponseHandler: invokeResponseHandler,
  296.             interpretResponse: interpretResponse,
  297.             handleResponse: handleResponse,
  298.             transport: null,
  299.             method: 'POST',
  300.             uri: '',
  301.             timeout: null,
  302.             timer: null,
  303.             initialHandler: bagofholding,
  304.             handler: null,
  305.             errorHandler: null,
  306.             transportErrorHandler: null,
  307.             timeoutHandler: null,
  308.             finallyHandler: bagofholding,
  309.             serverDialogCancelHandler: bagofholding,
  310.             relativeTo: null,
  311.             statusElement: null,
  312.             statusClass: '',
  313.             data: {},
  314.             file: null,
  315.             context: {},
  316.             readOnly: false,
  317.             writeRequiredParams: ['post_form_id'],
  318.             remainingRetries: 0,
  319.             option: {
  320.                 asynchronous: true,
  321.                 suppressErrorHandlerWarning: false,
  322.                 suppressEvaluation: false,
  323.                 suppressErrorAlerts: false,
  324.                 retries: 0,
  325.                 jsonp: false,
  326.                 bundle: false,
  327.                 useIframeTransport: false,
  328.                 tfbEndpoint: true,
  329.                 handleErrorAfterUnload: false
  330.             },
  331.             userActionID: '-'
  332.         });
  333.         this.errorHandler = AsyncResponse.defaultErrorHandler;
  334.         this.transportErrorHandler = bind(this, 'errorHandler');
  335.         if (uri != undefined) this.setURI(uri);
  336.         return this;
  337.     }
  338.     Arbiter.subscribe("page_transition", function (type, message) {
  339.         AsyncRequest._id_threshold = message.id;
  340.     });
  341.     copyProperties(AsyncRequest, {
  342.         receiveJSONPResponse: function (id, data, more_chunked_response) {
  343.             if (this._JSONPReceivers[id]) {
  344.                 if (!this._JSONPReceivers[id](data, more_chunked_response)) delete this._JSONPReceivers[id];
  345.             } else if (window.logJSError && !more_chunked_response) {
  346.                 var uri = (data.payload && data.payload.uri) || '';
  347.                 logJSError('ajax', {
  348.                     error: 'UnexpectedJsonResponse',
  349.                     extra: {
  350.                         id: id,
  351.                         uri: uri
  352.                     }
  353.                 });
  354.             }
  355.         },
  356.         _bundleRequest: function (request) {
  357.             if (request.getOption('jsonp') || request.getOption('useIframeTransport')) {
  358.                 request.setOption('bundle', false);
  359.                 return false;
  360.             } else if (!request.uri.isFacebookURI()) {
  361.                 request.setOption('bundle', false);
  362.                 return false;
  363.             } else if (!request.getOption('asynchronous')) {
  364.                 request.setOption('bundle', false);
  365.                 return false;
  366.             }
  367.             var path = request.uri.getPath();
  368.             if (!AsyncRequest._bundleTimer) AsyncRequest._bundleTimer = setTimeout(function () {
  369.                 AsyncRequest._sendBundledRequests();
  370.             }, 0);
  371.             AsyncRequest._allBundledRequests.push([path, request]);
  372.             return true;
  373.         },
  374.         _sendBundledRequests: function () {
  375.             clearTimeout(AsyncRequest._bundleTimer);
  376.             AsyncRequest._bundleTimer = null;
  377.             var bundled_requests = AsyncRequest._allBundledRequests;
  378.             AsyncRequest._allBundledRequests = [];
  379.             if (bundled_requests.length == 1) {
  380.                 var request = bundled_requests[0][1];
  381.                 request.setOption('bundle', false).send();
  382.                 return request;
  383.             }
  384.             if (bundled_requests.length === 0) return null;
  385.             var data = [];
  386.             for (var ii = 0; ii < bundled_requests.length; ii++) data.push([bundled_requests[ii][0], URI.implodeQuery(bundled_requests[ii][1].data)]);
  387.             var query_data = {
  388.                 data: data
  389.             };
  390.             var request = new AsyncRequest();
  391.             request.setURI('/ajax/proxy.php').setData(query_data).setMethod('POST').setInitialHandler(bagof(true)).setAllowCrossPageTransition(true).setHandler(function (r) {
  392.                 var payload = r.getPayload();
  393.                 var responses = payload.responses;
  394.                 if (responses.length != bundled_requests.length) {
  395.                     return;
  396.                 } else for (var ii = 0; ii < bundled_requests.length; ii++) {
  397.                     var path = bundled_requests[ii][0];
  398.                     var request = bundled_requests[ii][1];
  399.                     request.id = this.id;
  400.                     if (responses[ii][0] != path) {
  401.                         request.invokeResponseHandler({
  402.                             transportError: 'Wrong response order in bundled request to ' + path
  403.                         });
  404.                         continue;
  405.                     }
  406.                     var asyncResponse = request.interpretResponse(responses[ii][1]);
  407.                     request.invokeResponseHandler(asyncResponse);
  408.                 }
  409.             }).setTransportErrorHandler(function (response) {
  410.                 var paths = [];
  411.                 var interp = {
  412.                     transportError: response.errorDescription
  413.                 };
  414.                 for (var ii = 0; ii < bundled_requests.length; ii++) {
  415.                     var path = bundled_requests[ii][0];
  416.                     var request = bundled_requests[ii][1];
  417.                     paths.push(path);
  418.                     request.id = this.id;
  419.                     request.invokeResponseHandler(interp);
  420.                 }
  421.             }).send();
  422.             return request;
  423.         },
  424.         bootstrap: function (href, elem, is_post) {
  425.             var method = 'GET';
  426.             var readonly = true;
  427.             var data = {};
  428.             if (is_post || elem && (elem.rel == 'async-post' || elem.getAttribute && elem.getAttribute('forcemethod') == 'post')) {
  429.                 method = 'POST';
  430.                 readonly = false;
  431.                 if (href) {
  432.                     href = URI(href);
  433.                     data = href.getQueryData();
  434.                     href.setQueryData({});
  435.                 }
  436.             }
  437.             var status_elem = Parent.byClass(elem, 'stat_elem') || elem;
  438.             if (status_elem && CSS.hasClass(status_elem, 'async_saving')) return false;
  439.             var async = new AsyncRequest(href).setReadOnly(readonly).setMethod(method).setData(data).setNectarModuleDataSafe(elem).setRelativeTo(elem).setHandler(function (response) {
  440.                 Event.fire(elem, 'success', {
  441.                     response: response
  442.                 });
  443.             }).setErrorHandler(function (response) {
  444.                 if (Event.fire(elem, 'error', {
  445.                     response: response
  446.                 }) !== false) AsyncResponse.defaultErrorHandler(response);
  447.             });
  448.             if (status_elem) {
  449.                 async.setStatusElement(status_elem);
  450.                 var status_class = status_elem.getAttribute('data-status-class');
  451.                 status_class && async.setStatusClass(status_class);
  452.             }
  453.             async.send();
  454.             return false;
  455.         },
  456.         post: function (href, data) {
  457.             new AsyncRequest(href).setReadOnly(false).setMethod('POST').setData(data).send();
  458.             return false;
  459.         },
  460.         getLastId: function () {
  461.             return AsyncRequest._last_id;
  462.         },
  463.         _JSONPReceivers: {},
  464.         _allBundledRequests: [],
  465.         _bundleTimer: null,
  466.         suppressOnloadToken: {},
  467.         _last_id: 2,
  468.         _id_threshold: 2,
  469.         _inflight: [],
  470.         _inflightAdd: bagofholding,
  471.         _inflightPurge: bagofholding,
  472.         _inflightEnable: function () {
  473.             if (ua.ie()) {
  474.                 copyProperties(AsyncRequest, {
  475.                     _inflightAdd: function (ar) {
  476.                         this._inflight.push(ar);
  477.                     },
  478.                     _inflightPurge: function () {
  479.                         AsyncRequest._inflight = AsyncRequest._inflight.filter(function (ar) {
  480.                             return ar.transport && ar.transport.readyState < 4;
  481.                         });
  482.                     }
  483.                 });
  484.                 onunloadRegister(function () {
  485.                     AsyncRequest._inflight.each(function (ar) {
  486.                         if (ar.transport && ar.transport.readyState < 4) {
  487.                             ar.transport.abort();
  488.                             delete ar.transport;
  489.                         }
  490.                     });
  491.                 });
  492.             }
  493.         }
  494.     });
  495.     copyProperties(AsyncRequest.prototype, {
  496.         setMethod: function (m) {
  497.             this.method = m.toString().toUpperCase();
  498.             return this;
  499.         },
  500.         getMethod: function () {
  501.             return this.method;
  502.         },
  503.         setData: function (obj) {
  504.             this.data = obj;
  505.             return this;
  506.         },
  507.         _setDataHash: function () {
  508.             if (this.method != 'POST' || !this.getOption('tfbEndpoint') || this.data.phstamp) return;
  509.             var input_len = URI.implodeQuery(this.data).length;
  510.             var numeric_csrf_value = '';
  511.             for (var ii = 0; ii < this.data.fb_dtsg.length; ii++) numeric_csrf_value += this.data.fb_dtsg.charCodeAt(ii);
  512.             this.data.phstamp = '1' + numeric_csrf_value + input_len;
  513.         },
  514.         setFile: function (file) {
  515.             this.file = file;
  516.             return this;
  517.         },
  518.         getData: function () {
  519.             return this.data;
  520.         },
  521.         setContextData: function (key, value, enabled) {
  522.             enabled = enabled === undefined ? true : enabled;
  523.             if (enabled) this.context['_log_' + key] = value;
  524.             return this;
  525.         },
  526.         _setUserActionID: function () {
  527.             var ue = window.ArbiterMonitor && ArbiterMonitor.getUE() || '-';
  528.             this.userActionID = (window.EagleEye && EagleEye.getSessionID() || '-') + '/' + ue;
  529.         },
  530.         setURI: function (uri) {
  531.             var uri_obj = URI(uri);
  532.             if (this.getOption('useIframeTransport') && !uri_obj.isFacebookURI()) return this;
  533.             if (!this.getOption('jsonp') && !this.getOption('useIframeTransport') && !uri_obj.isSameOrigin()) return this;
  534.             this._setUserActionID();
  535.             if (!uri || uri_obj.isEmpty()) {
  536.                 if (window.send_error_signal && window.get_error_stack) {
  537.                     var data = {
  538.                         err_code: 1013,
  539.                         vip: '-',
  540.                         duration: 0,
  541.                         xfb_ip: '-',
  542.                         path: window.location.href,
  543.                         aid: this.userActionID
  544.                     };
  545.                     send_error_signal('async_error', JSON.stringify(data));
  546.                     send_error_signal('async_xport_stack', '1013:' + window.location.href + '::' + get_error_stack());
  547.                 }
  548.                 return this;
  549.             }
  550.             this.uri = uri_obj;
  551.             return this;
  552.         },
  553.         getURI: function () {
  554.             return this.uri.toString();
  555.         },
  556.         setInitialHandler: function (fn) {
  557.             this.initialHandler = fn;
  558.             return this;
  559.         },
  560.         setHandler: function (fn) {
  561.             if (!(typeof (fn) != 'function')) this.handler = fn;
  562.             return this;
  563.         },
  564.         getHandler: function () {
  565.             return this.handler;
  566.         },
  567.         setErrorHandler: function (fn) {
  568.             if (!(typeof (fn) != 'function')) this.errorHandler = fn;
  569.             return this;
  570.         },
  571.         setTransportErrorHandler: function (fn) {
  572.             this.transportErrorHandler = fn;
  573.             return this;
  574.         },
  575.         getErrorHandler: function () {
  576.             return this.errorHandler;
  577.         },
  578.         getTransportErrorHandler: function () {
  579.             return this.transportErrorHandler;
  580.         },
  581.         setTimeoutHandler: function (timeout, fn) {
  582.             if (!(typeof (fn) != 'function')) {
  583.                 this.timeout = timeout;
  584.                 this.timeoutHandler = fn;
  585.             }
  586.             return this;
  587.         },
  588.         resetTimeout: function (timeout) {
  589.             if (!(this.timeoutHandler === null)) if (timeout === null) {
  590.                 this.timeout = null;
  591.                 clearTimeout(this.timer);
  592.                 this.timer = null;
  593.             } else {
  594.                 var clear_on_quickling_event = !this._allowCrossPageTransition;
  595.                 this.timeout = timeout;
  596.                 clearTimeout(this.timer);
  597.                 this.timer = this._handleTimeout.bind(this).defer(this.timeout, clear_on_quickling_event);
  598.             }
  599.             return this;
  600.         },
  601.         _handleTimeout: function () {
  602.             this.abandon();
  603.             this.timeoutHandler(this);
  604.         },
  605.         setNewSerial: function () {
  606.             this.id = ++AsyncRequest._last_id;
  607.             return this;
  608.         },
  609.         setFinallyHandler: function (fn) {
  610.             this.finallyHandler = fn;
  611.             return this;
  612.         },
  613.         setServerDialogCancelHandler: function (fn) {
  614.             this.serverDialogCancelHandler = fn;
  615.             return this;
  616.         },
  617.         setPreBootloadHandler: function (fn) {
  618.             this.preBootloadHandler = fn;
  619.             return this;
  620.         },
  621.         setReadOnly: function (readOnly) {
  622.             if (!(typeof (readOnly) != 'boolean')) this.readOnly = readOnly;
  623.             return this;
  624.         },
  625.         setFBMLForm: function () {
  626.             this.writeRequiredParams = ["fb_sig"];
  627.             return this;
  628.         },
  629.         getReadOnly: function () {
  630.             return this.readOnly;
  631.         },
  632.         setRelativeTo: function (element) {
  633.             this.relativeTo = element;
  634.             return this;
  635.         },
  636.         getRelativeTo: function () {
  637.             return this.relativeTo;
  638.         },
  639.         setStatusClass: function (c) {
  640.             this.statusClass = c;
  641.             return this;
  642.         },
  643.         setStatusElement: function (element) {
  644.             this.statusElement = element;
  645.             return this;
  646.         },
  647.         getStatusElement: function () {
  648.             return ge(this.statusElement);
  649.         },
  650.         isRelevant: function () {
  651.             if (this._allowCrossPageTransition) return true;
  652.             if (!this.id) return true;
  653.             return this.id > AsyncRequest._id_threshold;
  654.         },
  655.         clearStatusIndicator: function () {
  656.             var statusElem = this.getStatusElement();
  657.             if (statusElem) {
  658.                 CSS.removeClass(statusElem, 'async_saving');
  659.                 CSS.removeClass(statusElem, this.statusClass);
  660.             }
  661.         },
  662.         addStatusIndicator: function () {
  663.             var statusElem = this.getStatusElement();
  664.             if (statusElem) {
  665.                 CSS.addClass(statusElem, 'async_saving');
  666.                 CSS.addClass(statusElem, this.statusClass);
  667.             }
  668.         },
  669.         specifiesWriteRequiredParams: function () {
  670.             return this.writeRequiredParams.every(function (param) {
  671.                 this.data[param] = this.data[param] || Env[param] || (ge(param) || {}).value;
  672.                 if (this.data[param] !== undefined) return true;
  673.                 return false;
  674.             }, this);
  675.         },
  676.         setOption: function (opt, v) {
  677.             if (typeof (this.option[opt]) != 'undefined') this.option[opt] = v;
  678.             return this;
  679.         },
  680.         getOption: function (opt) {
  681.             typeof (this.option[opt]) == 'undefined';
  682.             return this.option[opt];
  683.         },
  684.         abort: function () {
  685.             if (this.transport) {
  686.                 var old_handler = this.getTransportErrorHandler();
  687.                 this.setOption('suppressErrorAlerts', true);
  688.                 this.setTransportErrorHandler(bagofholding);
  689.                 this._requestAborted = 1;
  690.                 this.transport.abort();
  691.                 this.setTransportErrorHandler(old_handler);
  692.             }
  693.         },
  694.         abandon: function () {
  695.             clearTimeout(this.timer);
  696.             this.setOption('suppressErrorAlerts', true).setHandler(bagofholding).setErrorHandler(bagofholding).setTransportErrorHandler(bagofholding);
  697.             if (this.transport) {
  698.                 this._requestAborted = 1;
  699.                 this.transport.abort();
  700.             }
  701.         },
  702.         setNectarData: function (nctrParams) {
  703.             if (nctrParams) {
  704.                 if (this.data.nctr === undefined) this.data.nctr = {};
  705.                 copyProperties(this.data.nctr, nctrParams);
  706.             }
  707.             return this;
  708.         },
  709.         setNectarModuleDataSafe: function (elem) {
  710.             if (this.setNectarModuleData) this.setNectarModuleData(elem);
  711.             return this;
  712.         },
  713.         setNectarImpressionIdSafe: function () {
  714.             if (this.setNectarImpressionId) this.setNectarImpressionId();
  715.             return this;
  716.         },
  717.         setAllowCrossPageTransition: function (allow) {
  718.             this._allowCrossPageTransition = !! allow;
  719.             if (this.timer) this.resetTimeout(this.timeout);
  720.             return this;
  721.         },
  722.         send: function (isRetry) {
  723.             isRetry = isRetry || false;
  724.             if (!this.uri) return false;
  725.             !this.errorHandler && !this.getOption('suppressErrorHandlerWarning');
  726.             if (this.getOption('jsonp') && this.method != 'GET') this.setMethod('GET');
  727.             if (this.getOption('useIframeTransport') && this.method != 'GET') this.setMethod('GET');
  728.             this.timeoutHandler !== null && (this.getOption('jsonp') || this.getOption('useIframeTransport'));
  729.             if (!this.getReadOnly()) {
  730.                 this.specifiesWriteRequiredParams();
  731.                 if (this.method != 'POST') return false;
  732.             }
  733.             if (this.method == 'POST' && this.getOption('tfbEndpoint')) {
  734.                 this.data.fb_dtsg = Env.fb_dtsg;
  735.                 this.data.lsd = Cookie.get('lsd');
  736.             }
  737.             if (!isEmpty(this.context) && this.getOption('tfbEndpoint')) {
  738.                 copyProperties(this.data, this.context);
  739.                 this.data.ajax_log = 1;
  740.             }
  741.             if (window.Env && Env.force_param) copyProperties(this.data, Env.force_param);
  742.             if (!this.getReadOnly() && this.getOption('tfbEndpoint') && this.method == 'POST' && this.data.post_form_id_source === undefined) this.data.post_form_id_source = 'AsyncRequest';
  743.             if (window.Env) this.data.__user = Env.user;
  744.             this._setUserActionID();
  745.             if (this.getOption('bundle') && AsyncRequest._bundleRequest(this)) return true;
  746.             this.setNewSerial();
  747.             if (this.getOption('tfbEndpoint')) {
  748.                 this.uri.addQueryData({
  749.                     __a: 1
  750.                 });
  751.                 if (!this.getOption('asynchronous')) this.uri.addQueryData({
  752.                     __s: 1
  753.                 });
  754.                 if (Env.fb_isb) this.uri.addQueryData({
  755.                     fb_isb: Env.fb_isb
  756.                 });
  757.             }
  758.             this.finallyHandler = async_callback(this.finallyHandler, 'final');
  759.             var uri_str, query;
  760.             if (this.method == 'GET' || this.file) {
  761.                 uri_str = this.uri.addQueryData(this.data).toString();
  762.                 query = '';
  763.             } else {
  764.                 uri_str = this.uri.toString();
  765.                 this._setDataHash();
  766.                 query = URI.implodeQuery(this.data);
  767.             }
  768.             if (this.getOption('jsonp') || this.getOption('useIframeTransport')) {
  769.                 uri_str = this.uri.addQueryData({
  770.                     __a: this.id
  771.                 }).toString();
  772.                 AsyncRequest._JSONPReceivers[this.id] = async_callback(bind(this, 'onjsonpresponse'), 'json');
  773.                 if (this.getOption('jsonp')) {
  774.                     (function () {
  775.                         document.body.appendChild($N('script', {
  776.                             src: uri_str,
  777.                             type: "text/javascript"
  778.                         }));
  779.                     }).bind(this).defer();
  780.                 } else {
  781.                     var style = {
  782.                         position: 'absolute',
  783.                         top: '-9999999px',
  784.                         width: '80px',
  785.                         height: '80px'
  786.                     };
  787.                     this.transportIframe = $N('iframe', {
  788.                         src: "javascript:''",
  789.                         style: style
  790.                     });
  791.                     document.body.appendChild(this.transportIframe);
  792.                     this.transportIframe.src = uri_str;
  793.                 }
  794.                 return true;
  795.             }
  796.             if (this.transport) return false;
  797.             var transport = null;
  798.             try {
  799.                 transport = new XMLHttpRequest();
  800.             } catch (ignored) {}
  801.             if (!transport) try {
  802.                 transport = new ActiveXObject("Msxml2.XMLHTTP");
  803.             } catch (ignored) {}
  804.             if (!transport) try {
  805.                 transport = new ActiveXObject("Microsoft.XMLHTTP");
  806.             } catch (ignored) {}
  807.             if (!transport) return false;
  808.             transport.onreadystatechange = async_callback(bind(this, 'onstatechange'), 'xhr');
  809.             if (!isRetry) this.remainingRetries = this.getOption('retries');
  810.             if (window.send_error_signal || window.ArbiterMonitor) this._sendTimeStamp = this._sendTimeStamp || Date.now();
  811.             this.transport = transport;
  812.             try {
  813.                 this.transport.open(this.method, uri_str, this.getOption('asynchronous'));
  814.             } catch (ex) {
  815.                 return false;
  816.             }
  817.             var svn_rev = Env.svn_rev;
  818.             if (svn_rev) this.transport.setRequestHeader('X-SVN-Rev', String(svn_rev));
  819.             if (this.method == 'POST') this.transport.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
  820.             this.addStatusIndicator();
  821.             query = this.file || query;
  822.             this.transport.send(query);
  823.             if (this.timeout !== null) this.resetTimeout(this.timeout);
  824.             AsyncRequest._inflightAdd(this);
  825.             return true;
  826.         },
  827.         _displayServerDialog: function (model, is_confirmation) {
  828.             Bootloader.loadComponents('dialog', function () {
  829.                 var dialog = new Dialog(model);
  830.                 if (is_confirmation) dialog.setHandler(this._displayConfirmationHandler.bind(this, dialog));
  831.                 dialog.setCancelHandler(function () {
  832.                     this.serverDialogCancelHandler.apply(this, arguments);
  833.                     this.finallyHandler.apply(this, arguments);
  834.                 }.bind(this)).setCausalElement(this.relativeTo).setCloseHandler(this.finallyHandler.bind(this)).show();
  835.             }.bind(this));
  836.         },
  837.         _displayConfirmationHandler: function (dialog) {
  838.             this.data.confirmed = 1;
  839.             copyProperties(this.data, dialog.getFormData());
  840.             this.send();
  841.         }
  842.     });
  843.     module.exports = AsyncRequest;
  844. });