Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /* ============ DEFERRED OBJECT ===========
- used by Requester */
- var Deferred = function()
- {
- this.cbh_ = [];
- this.ebh_ = [];
- this.fired_ = false;
- }
- Deferred.prototype = {
- callback: function(data) {
- return this.fire(true, data);
- },
- errback: function(data) {
- return this.fire(false, data);
- },
- fire: function(status, result) {
- if (this.fired_) return false;
- this.fired_ = true;
- this.status_ = status;
- this.result_ = result;
- this.broadcast_();
- return true;
- },
- fired: function() {
- return this.fired_;
- },
- addCallback: function(fn) {
- this.cbh_.push(fn);
- this.broadcast_();
- return this;
- },
- addErrback: function(fn) {
- this.ebh_.push(fn);
- this.broadcast_();
- return this;
- },
- broadcast_: function() {
- if (!this.fired_) return;
- this.broadcast_impl_(this.status_ ? this.cbh_ : this.ebh_, this.result_);
- this.cbh_ = [];
- this.ebh_ = [];
- },
- broadcast_impl_: function(list, arg) { // called only from 'broadcast_'
- for(var cb = 0; cb < list.length; ++cb) {
- list[cb].call(this, arg);
- }
- }
- };
- /* ============ REQUESTER OBJECT ===========
- Incapsulates cross-domain http async requests in userjs.
- The data is passed through window.name varible. */
- var serializeData = function(a) {
- if (!(a instanceof Array)) a = [a];
- var r = '[ ';
- for(var i = 0; i < a.length; ++i) {
- // r += "'" + a[i].toString().replace(/\\/g, '\\\\').replace(/\n/g, '\\n').replace(/'/g, "\\'") + "', ";
- // UNCOMMENT THIS
- }
- return (r += ']');
- }
- var unserializeData = function(s) {
- return eval(s); // Mind security!
- }
- var explode = function(s, delim, n) {
- var p = 0;
- var g = [];
- for(var i = 0; n == undefined || i < n-1; ++i) {
- var index = s.indexOf(delim, p);
- if (index == -1) break;
- g[i] = s.slice(p, index);
- p = index+1;
- }
- if (n != undefined || i < n-1) {
- g[i] = s.slice(p);
- }
- return g;
- }
- /**
- * Cross domain requests from Opera UserJS. Singleton.
- * A user-js handler at requested page must exist to prepare and return data to requesting page.
- *
- * Usage: let A is requesting page. B is a page at the remote domain to request from,
- * A.domain, B.domain are the domains of A and B.
- * Create a UserJS at A calling Requester.request, passing to B, and url of a page at A.domain.
- * The latter page is called a stub and is used to exchange data with original requesting window.
- * It must be an arbitrary page at original domain, better small-sized.
- * Then create a UserJS handler for B. Get passed arguments by calling Requester.getArguments(),
- * make proper preparations and requests (e.g. XMLHttpRequests to B.domain webservice), and return
- * resulting array by calling Requester.returnData().
- */
- Requester = {
- default_timeout: 15000,
- token: 'XDR1',
- /**
- * Make cross-domain request.
- *
- * @param request_url URL to load
- * @param stub_url any URL at requesting domain used to exchange data with original Requester
- * @param data an array of strings to pass to handler script at 'request_url'
- * @param timeout generate timeout error after 'timeout' msec
- * @return deferred object receiving events
- */
- request: function (request_url, stub_url, data, timeout)
- {
- if (timeout == undefined) timeout = this.default_timeout;
- var req_id = 'request'+(new Date()).getTime();
- var iframe = document.createElement('iframe');
- document.body.appendChild(iframe);
- iframe.setAttribute('src', request_url);
- iframe.setAttribute('style', 'display: none;');
- iframe.contentWindow.name = this.token + '#' + req_id + '#' + stub_url + '#' + serializeData(data);
- var deferred = new Deferred();
- deferred.iframe = iframe;
- deferred.req_id = req_id;
- window[req_id] = deferred;
- setTimeout(function() {
- if (!deferred.fired()) {
- deferred.errback(-1);
- }
- }, timeout);
- deferred.addCallback(this.disposeFrame);
- deferred.addErrback(this.disposeFrame);
- return deferred;
- },
- /**
- * Get rid of a deferred object and frame having been used. Used internally
- */
- /* private */ disposeFrame: function() {
- this.iframe.parentNode.removeChild(this.iframe);
- delete(window[this.req_id]);
- },
- /**
- * UserJS handler at requested url calls it to get the array of data passed by requesting script.
- *
- * @see Requester#request
- * @returns array of data, or false if nothing requested by this requester
- */
- getArguments: function() {
- var args = explode(window.name, '#', 4);
- if (args[0] != this.token)
- return false;
- return unserializeData(args[3]);
- },
- /**
- * Pass an array of data to requesting page as a result.
- * Deferred callback will be called with this array as an argument.
- */
- returnData: function(data) {
- var args = explode(window.name, '#', 4);
- var req_id = args[1];
- var stub_url = args[2];
- window.name = this.token + '#' + req_id + '#' + stub_url + '#' + serializeData(data);
- location.replace(stub_url);
- },
- /**
- * Check if we are in stub.
- *
- * @return true if location.href is the stub page. False otherwise.
- */
- inStub: function() {
- var args = explode(window.name, '#', 4);
- var token = args[0];
- var stub_url = args[2];
- return token == this.token && location.href == stub_url;
- },
- /**
- * Pass the collected result to original requesting page.
- */
- runStub: function() {
- var args = explode(window.name, '#', 4);
- window.name = '';
- var req_id = args[1];
- var data = args[3];
- if (!window.parent[req_id]) {
- log_("Requester: Deferred object disappeared.");
- return;
- }
- deferred = window.parent[req_id];
- window.parent.setTimeout(function() { // run in parent window thread
- deferred.callback(unserializeData(data));
- }, 0);
- },
- };
- if (Requester.inStub())
- {
- Requester.runStub();
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement