Advertisement
Guest User

AJAX

a guest
Sep 21st, 2016
208
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*
  2.   <<Asynchronous Javascript And Xml>>-контроллер
  3. #ajax
  4. */
  5. var ajax = {
  6.   urlonly: !('FormData' in window),
  7.  
  8.   /*
  9.   E_CONNECT: 0,
  10.   E_ABORTED: -1,
  11.   E_TIMEOUT: -2,
  12.   */
  13.  
  14.   get: function(url, opts) {
  15.     opts.method = 'GET';
  16.     return ajax.request(url, opts);
  17.   },
  18.   post: function(url, opts) {
  19.     opts.method = 'POST';
  20.     return ajax.request(url, opts);
  21.   },
  22.  
  23.   buildQuery: function(query) {
  24.     if (ajax.urlonly) {
  25.       return ajax.urlencode(query);
  26.     }
  27.  
  28.     return ajax.formData(query);
  29.   },
  30.  
  31.   urlencode: function(query) {
  32.     if (typeof query == 'string') {
  33.       return query;
  34.     }
  35.  
  36.     var s = [],
  37.         add = function( key, value ) {
  38.           s.push(encodeURIComponent( key ) + "=" + encodeURIComponent( value ));
  39.         },
  40.         buildParams = function ( prefix, obj, add ) {
  41.           if ( Array.isArray( obj ) ) {
  42.             // Serialize array item.
  43.             forEach( obj, function( i, v ) {
  44.                 buildParams( prefix + "[" + ( typeof v === "object" ? i : "" ) + "]", v, add );
  45.             });
  46.             return;
  47.           }
  48.           if (typeof obj == 'object' && obj) {
  49.             // Serialize object item.
  50.             for ( var name in obj ) {
  51.               buildParams( prefix + "[" + name + "]", obj[ name ], add );
  52.             }
  53.             return;
  54.           }
  55.           // Serialize scalar item.
  56.           add( prefix, obj );
  57.         };
  58.  
  59.     for ( var prefix in query ) {
  60.       buildParams( prefix, query[ prefix ], add );
  61.     }
  62.  
  63.     // Return the resulting serialization
  64.     return s.join('&');
  65.   },
  66.  
  67.   formData: function(query) {
  68.     if (query instanceof FormData) {
  69.       return query;
  70.     }
  71.  
  72.     var data = new FormData;
  73.     // each(query, data.append.bind(data));
  74.     for (var name in query) {
  75.       data.append(name, query[name]);
  76.     }
  77.  
  78.     return data;
  79.   },
  80.  
  81.   createResponse: function(xhr, other) {
  82.     if (!other) {
  83.       other = {};
  84.     }
  85.  
  86.     var response = {
  87.       url: xhr.responseURL || xhr.getResponseHeader('Location') || '',
  88.       status: other.status == null ? xhr.status : other.status,
  89.       statusText: other.statusText ? other.statusText : xhr.statusText,
  90.       text: xhr.status == 204 ? '' : xhr.responseText,
  91.       headers:  (function(xhr) {
  92.         var headers = {};
  93.  
  94.         forEach(
  95.           xhr.getAllResponseHeaders().split('\r\n').filter(function(v) { return v !== ''; }),
  96.           function(i, header) {
  97.             var parsed = header.split(': ');
  98.             headers[parsed[0]] = parsed[0] == 'Date' ? [parsed[1]] : parsed[1].split(/, ?/);
  99.           }
  100.         );
  101.  
  102.         return {
  103.           has: function(name) {
  104.             return name in headers;
  105.           },
  106.  
  107.           get: function(name) {
  108.             return headers[name] ? headers[name][0] : null;
  109.           },
  110.  
  111.           getAll: function(name) {
  112.             return headers[name] || null;
  113.           },
  114.  
  115.           set: function(name, value) {
  116.             headers[name] = Array.isArray(value) ? value : [value];
  117.           },
  118.  
  119.           append: function(name, value) {
  120.             if (!headers[name]) {
  121.               headers[name] = [];
  122.             }
  123.  
  124.             headers[name].push(value);
  125.           },
  126.  
  127.           delete: function(name) {
  128.             delete headers[name];
  129.           }
  130.         };
  131.       })(xhr),
  132.     };
  133.  
  134.     if (xhr.responseText && (xhr.getResponseHeader('Content-Type') || '').startsWith('application/json')) {
  135.       try {
  136.         response.json = JSON.parse(xhr.responseText);
  137.       } catch (e) {};
  138.     }
  139.     /*
  140.     else if (xhr.responseXML) {
  141.       response.xml = responseXML;
  142.     }
  143.     */
  144.  
  145.     return response;
  146.   },
  147.  
  148.   request: function(url, opts) {
  149.     if (!opts && typeof url == 'object') {
  150.       opts = url;
  151.       url = '';
  152.     } else if (url == undefined) {
  153.       url = '';
  154.     }
  155.  
  156.     //opts = ajax.createRequest(url, opts);
  157.  
  158.     opts = extend({
  159.       method: 'GET',
  160.  
  161.       //params: null, // params - для параметров URL,
  162.       body: null, // body - для тела запроса
  163.  
  164.       timeout: 0 // после timeout вызывается onError со статусом -1
  165.  
  166.       /*
  167.       onLoad: null,
  168.       onError: null,
  169.       onDone: null,
  170.       showProgress: null,
  171.       hideProgress: null,
  172.  
  173.       headers: {
  174.         'X-Requested-With': 'XMLHttpRequest'
  175.       }
  176.       */
  177.     }, opts || {});
  178.  
  179.     if (opts.showProgress) {
  180.       opts.showProgress();
  181.     }
  182.  
  183.     opts.method = opts.method.toUpperCase();
  184.  
  185.     /*
  186.     if (opts.data) {
  187.       if ( ['OPTIONS', 'HEAD', 'GET', 'DELETE'].includes(opts.method) ) {
  188.         opts.params = opta.data;
  189.       } else {
  190.         opts.body = opts.data;
  191.       }
  192.  
  193.       delete opts.data;
  194.     }
  195.     */
  196.  
  197.     if (opts.params) {
  198.       url += (url.includes('?') ? '&' : '?') + ajax.urlencode(opts.params);
  199.     }
  200.  
  201.     // TypeError: HEAD or GET Request cannot have a body. (c) ES6 fetch
  202.     if ( opts.body && !['OPTIONS', 'HEAD', 'GET', 'DELETE'].includes(opts.method) ) {
  203.       opts.body = ajax.buildQuery(opts.body);
  204.     } else {
  205.       opts.body = null;
  206.     }
  207.  
  208.     /*
  209.     if (!opts.headers['Content-Type'] && opts.body) {
  210.       opts.headers['Content-Type'] = ajax.urlonly ? 'application/x-www-form-urlencoded' : 'multipart/form-data';
  211.     }
  212.     */
  213.  
  214.     var done = function(error, other) {
  215.       var response = ajax.createResponse(xhr, other); // это может быть долго, поэтому сначала создаём response..
  216.  
  217.       if (opts.hideProgress) opts.hideProgress(); // .., а потом убираем прогресс
  218.  
  219.       if (!error && (xhr.status >= 200 && xhr.status < 300 || xhr.status == 304)) {
  220.         if (opts.onLoad) opts.onLoad(response);
  221.       } else {
  222.         if (opts.onError) opts.onError(response);
  223.       }
  224.  
  225.       if (opts.onDone) opts.onDone(response);
  226.     };
  227.  
  228.  
  229.     var xhr = new XMLHttpRequest;
  230.  
  231.     xhr.onload = done.pbind(false);
  232.  
  233.     xhr.onerror = done.pbind(true, { status: 0, statusText: 'Connection Error' });
  234.     xhr.onabort = done.pbind(true, { status: -1, statusText: 'Request Aborted' });
  235.  
  236.     if (opts.timeout) {
  237.       xhr.timeout = opts.timeout;
  238.       xhr.ontimeout = done.pbind(true, { status: -2, statusText: 'Request Timeout' });
  239.     }
  240.  
  241.     if (opts.progressLine) {
  242.       var lastState = -1;
  243.       xhr.onreadystatechange = (function(progressLine) {
  244.         if (lastState != xhr.readyState) {
  245.           animate(progressLine, { width: progressLine.parentNode.offsetWidth / 4 * xhr.readyState }, 100); // в % от длинны
  246.         }
  247.         lastState = xhr.readyState;
  248.       }).pbind(opts.progressLine);
  249.     }
  250.  
  251.  
  252.     xhr.open(opts.method, url, true); // нельзя отправлять Headers раньше .open(...)
  253.  
  254.  
  255.     if (opts.headers) {
  256.       for (var key in opts.headers) {
  257.         xhr.setRequestHeader(key, opts.headers[key]);
  258.       }
  259.     }
  260.  
  261.     xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
  262.  
  263.     if (opts.data && ajax.urlonly && !(opts.headers && opts.headers['Content-Type'])) {
  264.       xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
  265.     }
  266.  
  267.  
  268.     xhr.send(opts.body);
  269.  
  270.     return xhr;
  271.   }
  272. };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement