1'use strict'; 2 3;(function(){ 4 5 /************************ ATTENTION *************************** 6 * Please do not use Bitrix CoreJS in this class. * 7 * This class can be called on page without Bitrix Framework * 8 **************************************************************/ 9 10 if (!window.BX) 11 { 12 window.BX = {}; 13 } 14 else if (window.BX.RestClient) 15 { 16 return; 17 } 18 19 var BX = window.BX; 20 21 BX.RestClient = function (options) 22 { 23 options = options || {}; 24 25 this.endpoint = options.endpoint || '/rest'; 26 this.queryParams = options.queryParams || ''; 27 this.cors = options.cors === true; 28 }; 29 30 BX.RestClient.prototype.callMethod = function(method, params, callback, sendCallback, logTag) 31 { 32 return ajax({ 33 method: method, 34 data: params, 35 callback: callback, 36 sendCallback: sendCallback, 37 logTag: logTag, 38 endpoint: this.endpoint, 39 queryParams: this.queryParams, 40 cors: this.cors 41 }); 42 }; 43 44 /* 45 calls = [[method,params],[method,params]]; 46 calls = [{method:method,params:params},[method,params]]; 47 calls = {call_id:[method,params],...}; 48 */ 49 BX.RestClient.prototype.callBatch = function(calls, callback, bHaltOnError, sendCallback, logTag) 50 { 51 var cmd = Utils.isArray(calls) ? [] : {}; 52 var cnt = 0; 53 var cb = function(cmd) { 54 ajax.batch(cmd, callback, bHaltOnError, sendCallback, this.endpoint, this.queryParams, this.cors, logTag); 55 }.bind(this); 56 57 for(var i in calls) 58 { 59 var method = null, params = null; 60 61 if(!!calls[i] && calls.hasOwnProperty(i)) 62 { 63 if(Utils.isArray(calls[i])) 64 { 65 method = calls[i][0]; 66 params = calls[i][1]; 67 } 68 else if(!!calls[i].method) 69 { 70 method = calls[i].method; 71 params = calls[i].params; 72 } 73 74 if(!!method) 75 { 76 cnt++; 77 cmd[i] = [method, params]; 78 } 79 } 80 } 81 82 if(cnt > 0) 83 { 84 var e = function(i) 85 { 86 return function(str) 87 { 88 cmd[i] = cmd[i][0] + '?' + str; 89 if(--cnt <= 0) 90 cb(cmd); 91 } 92 }; 93 94 for(var c in cmd) 95 { 96 if(cmd.hasOwnProperty(c)) 97 { 98 ajax.prepareData(cmd[c][1], '', e(c)); 99 } 100 } 101 } 102 }; 103 104 BX.RestClient.prototype.setEndpoint = function(url) 105 { 106 this.endpoint = url; 107 }; 108 109 BX.RestClient.prototype.enableCorsRequest = function(value) 110 { 111 this.cors = value === true; 112 }; 113 114 BX.RestClient.prototype.setQueryParams = function(params) 115 { 116 this.queryParams = params; 117 }; 118 119 /* self init for bitrix env */ 120 if (typeof BX.namespace !== 'undefined') 121 { 122 var BXRest = new BX.RestClient(); 123 124 if (typeof BX.rest == 'undefined') 125 { 126 BX.rest = {}; 127 } 128 129 BX.rest.callMethod = function (method, params, callback, sendCallback, logTag) 130 { 131 return BXRest.callMethod(method, params, callback, sendCallback, logTag); 132 }; 133 134 /* 135 calls = [[method,params],[method,params]]; 136 calls = [{method:method,params:params},[method,params]]; 137 calls = {call_id:[method,params],...}; 138 */ 139 BX.rest.callBatch = function (calls, callback, bHaltOnError, sendCallback, logTag) 140 { 141 return BXRest.callBatch(calls, callback, bHaltOnError, sendCallback, logTag); 142 }; 143 } 144 145 var Utils = { 146 isArray: function(item) { 147 return item && Object.prototype.toString.call(item) == "[object Array]"; 148 }, 149 isFunction: function(item) { 150 return item === null ? false : (typeof (item) == "function" || item instanceof Function); 151 }, 152 isString: function(item) { 153 return item === '' ? true : (item ? (typeof (item) == "string" || item instanceof String) : false); 154 }, 155 isDomNode: function(item) { 156 return item && typeof (item) == "object" && "nodeType" in item; 157 }, 158 isDate: function(item) { 159 return item && Object.prototype.toString.call(item) == "[object Date]"; 160 }, 161 buildQueryString: function(params) 162 { 163 var result = ''; 164 for (var key in params) 165 { 166 if (!params.hasOwnProperty(key)) 167 { 168 continue; 169 } 170 var value = params[key]; 171 if(this.isArray(value)) 172 { 173 value.forEach(function(valueElement, index) 174 { 175 result += encodeURIComponent(key + "[" + index + "]") + "=" + encodeURIComponent(valueElement) + "&"; 176 }); 177 } 178 else 179 { 180 result += encodeURIComponent(key) + "=" + encodeURIComponent(value) + "&"; 181 } 182 } 183 184 if(result.length > 0) 185 { 186 result = result.substr(0, result.length - 1); 187 } 188 return result; 189 }, 190 clone: function(obj, bCopyObj) 191 { 192 var _obj, i, l; 193 if (bCopyObj !== false) 194 bCopyObj = true; 195 196 if (obj === null) 197 return null; 198 199 if (this.isDomNode(obj)) 200 { 201 _obj = obj.cloneNode(bCopyObj); 202 } 203 else if (typeof obj == 'object') 204 { 205 if (this.isArray(obj)) 206 { 207 _obj = []; 208 for (i=0,l=obj.length;i<l;i++) 209 { 210 if (typeof obj[i] == "object" && bCopyObj) 211 _obj[i] = this.clone(obj[i], bCopyObj); 212 else 213 _obj[i] = obj[i]; 214 } 215 } 216 else 217 { 218 _obj = {}; 219 if (obj.constructor) 220 { 221 if (this.isDate(obj)) 222 _obj = new Date(obj); 223 else 224 _obj = new obj.constructor(); 225 } 226 227 for (i in obj) 228 { 229 if (typeof obj[i] == "object" && bCopyObj) 230 _obj[i] = this.clone(obj[i], bCopyObj); 231 else 232 _obj[i] = obj[i]; 233 } 234 } 235 236 } 237 else 238 {
239 _obj = obj; 240 } 241 242 return _obj; 243 } 244 }; 245 246 var ajax = function(config) 247 { 248 var hasCallback = !!config.callback && Utils.isFunction(config.callback); 249 var promise = typeof BX.Promise === 'undefined' || hasCallback? null: new BX.Promise(); 250 var sendCallback = config.sendCallback || function() {}; 251 var withoutRestoringCsrf = config.withoutRestoringCsrf || false; 252 var loginAttempt = config.loginAttempt || 0; 253 254 var xhr = ajax.xhr(); 255 256 var url = config.endpoint + '/' + ajax.escape(config.method) + '.json'+(config.logTag? '?logTag='+config.logTag: ''); 257 258 xhr.open('POST', url); 259 xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); 260 261 if (config.cors) 262 { 263 xhr.withCredentials = true; 264 } 265 266 var bRequestCompleted = false; 267 268 // IE fix 269 xhr.onprogress = function(){}; 270 xhr.ontimeout = function(){}; 271 xhr.timeout = 0; 272 273 xhr.onload = function() 274 { 275 if(bRequestCompleted) 276 return; 277 278 xhr.onload = function() {}; 279 280 var bSuccess = ajax.isSuccess(xhr); 281 282 var status = xhr.status; 283 if(bSuccess) 284 { 285 var data = xhr.responseText; 286 287 if(data.length > 0) 288 { 289 try 290 { 291 data = JSON.parse(data); 292 } 293 catch(e) 294 { 295 bSuccess = false; 296 } 297 } 298 299 if (status == 401) 300 { 301 if (data.extended_error === 'user_not_authorized' && loginAttempt === 0) 302 { 303 if (data.sessid) 304 { 305 console.warn('BX.rest: csrf-token has expired, replace to a new token'); 306 BX.message({'bitrix_sessid': data.sessid}); 307 } 308 309 if('BXDesktopSystem' in window) 310 { 311 console.warn('BX.rest: you are not authorized, trying to log in'); 312 config.loginAttempt = 1; 313 BXDesktopSystem.Login({ 314 // todo: support auth failure callback in future (when it is ready) 315 success: function() 316 { 317 console.warn('BX.rest: successfully logged in, repeating request'); 318 if (!hasCallback) 319 { 320 config.callback = function(result) 321 { 322 if (result.error()) 323 { 324 promise.reject(result); 325 } 326 else 327 { 328 promise.fulfill(result); 329 } 330 } 331 } 332 ajax(config); 333 } 334 }); 335 return true; 336 } 337 }
338 else if (data.sessid && !withoutRestoringCsrf) 339 { 340 BX.message({'bitrix_sessid': data.sessid}); 341 console.warn('BX.rest: your csrf-token has expired, send query with a new token'); 342 343 config.withoutRestoringCsrf = true; 344 345 if (!hasCallback) 346 { 347 config.callback = function(result) 348 { 349 if (result.error()) 350 { 351 promise.reject(result); 352 } 353 else 354 { 355 promise.fulfill(result); 356 } 357 } 358 } 359 ajax(config); 360 361 return true; 362 } 363 } 364 else if (status == 0) 365 { 366 data = {result: {}, error: "ERROR_NETWORK", error_description: "A network error occurred while the request was being executed."}; 367 } 368 else 369 { 370 if (status == 200) 371 { 372 if (data.length <= 0) 373 { 374 data = {result: {}, error: "BLANK_ANSWER", error_description: "Empty answer with correct http code, network error possible."}; 375 } 376 } 377 else if (data.length <= 0) 378 { 379 data = {result: {}, error: "BLANK_ANSWER_WITH_ERROR_CODE", error_description: 'Empty answer with error http code: '+status}; 380 } 381 } 382 } 383 384 xhr = null; 385 if(bSuccess) 386 { 387 var res = new ajaxResult(data, config, status); 388 if(hasCallback) 389 { 390 config.callback.apply(window, [res]); 391 } 392 else 393 { 394 if (res.error()) 395 { 396 promise.reject(res); 397 } 398 else 399 { 400 promise.fulfill(res); 401 } 402 } 403 } 404 else 405 { 406 var res = new ajaxResult({ 407 error: "ERROR_UNEXPECTED_ANSWER", 408 error_description: "Server returned an unexpected response.", 409 ex: {} 410 }, config, 0); 411 if(hasCallback) 412 { 413 config.callback.apply(window, [res]); 414 } 415 else 416 { 417 promise.reject(res); 418 } 419 } 420 }; 421 422 xhr.onerror = function(e) 423 { 424 var res = new ajaxResult({ 425 error: "ERROR_NETWORK", 426 error_description: "A network error occurred while the request was being executed.", 427 ex: e 428 }, config, 0); 429 if(hasCallback) 430 { 431 config.callback.apply(window, [res]); 432 } 433 else 434 { 435 promise.reject(res); 436 } 437 }; 438 439 var query_data = ''; 440 if (config.queryParams) 441 { 442 query_data = Utils.buildQueryString(config.queryParams); 443 } 444 else if (typeof BX.bitrix_sessid !== 'undefined') 445 { 446 query_data = 'sessid=' + BX.bitrix_sessid(); 447 } 448 449 if(typeof config.start !== 'undefined') 450 { 451 query_data += '&start=' + parseInt(config.start); 452 } 453 454 if(!!config.data) 455 { 456 ajax.prepareData(config.data, '', function(res) 457 { 458 query_data += '&' + res; 459 xhr.send(query_data); 460 sendCallback(xhr); 461 }); 462 } 463 else 464 { 465 xhr.send(query_data); 466 sendCallback(xhr); 467 } 468 469 return hasCallback || !promise? xhr: promise; 470 }; 471 472 ajax.batch = function(calls, callback, bHaltOnError, sendCallback, endpoint, queryParams, cors, logTag) 473 { 474 return ajax({ 475 method: 'batch', 476 data: {halt: !!bHaltOnError ? 1 : 0, cmd: calls}, 477 callback: function(res, config, status) 478 { 479 if(!callback) 480 { 481 return false; 482 } 483 484 var error = res.error(); 485 var data = res.data(); 486 var result = Utils.isArray(calls) ? [] : {}; 487 488 for(var i in calls) 489 { 490 if(!!calls[i] && calls.hasOwnProperty(i)) 491 { 492 if(Utils.isString(calls[i])) 493 { 494 var q = calls[i].split('?'); 495 } 496 else 497 { 498 q = [ 499 Utils.isArray(calls[i]) ? calls[i][0] : calls[i].method, 500 Utils.isArray(calls[i]) ? calls[i][1] : calls[i].data 501 ]; 502 } 503 504 if ( 505 data 506 && typeof data.result !== 'undefined' 507 && ( 508 typeof data.result[i] !== 'undefined' 509 || typeof data.result_error[i] !== 'undefined' 510 ) 511 ) 512 { 513 result[i] = new ajaxResult({ 514 result: typeof data.result[i] !== 'undefined' ? data.result[i] : {}, 515 error: data.result_error[i] || undefined, 516 total: data.result_total[i], 517 time: data.result_time[i], 518 next: data.result_next[i] 519 }, { 520 method: q[0], 521 data: q[1], 522 callback: callback, 523 endpoint: endpoint, 524 queryParams: queryParams, 525 cors: cors 526 }, res.status); 527 } 528 else if (error) 529 { 530 result[i] = new ajaxResult({ 531 result: {}, 532 error: error.ex, 533 total: 0 534 }, {
535 method: q[0], 536 data: q[1], 537 callback: callback, 538 endpoint: endpoint, 539 queryParams: queryParams, 540 cors: cors 541 }, res.status); 542 } 543 } 544 } 545 546 callback.apply(window, [result]); 547 }, 548 sendCallback: sendCallback, 549 endpoint: endpoint, 550 queryParams: queryParams, 551 cors: cors, 552 logTag: logTag 553 }); 554 }; 555 556 ajax.xhr = function() 557 { 558 return new XMLHttpRequest(); 559 }; 560 561 ajax.escape = function(str) 562 { 563 return encodeURIComponent(str); 564 }; 565 566 ajax.prepareData = function(arData, prefix, callback) 567 { 568 var data = '', objects = []; 569 if(Utils.isString(arData) || arData === null) 570 { 571 callback.call(document, arData || ''); 572 } 573 else 574 { 575 for(var i in arData) 576 { 577 if(!arData.hasOwnProperty(i)) 578 { 579 continue; 580 } 581 582 var name = ajax.escape(i); 583 584 if(prefix) 585 name = prefix + '[' + name + ']'; 586 587 if(typeof arData[i] === 'object') 588 { 589 if(Utils.isArray(arData[i]) && arData[i].length <= 0) 590 { 591 continue; 592 } 593 594 objects.push([name, arData[i]]); 595 } 596 else 597 { 598 if(data.length > 0) 599 { 600 data += '&'; 601 } 602 603 if(typeof arData[i] === 'boolean') 604 { 605 data += name + '=' + (arData[i]? 1: 0); 606 } 607 else 608 { 609 data += name + '=' + ajax.escape(arData[i]) 610 } 611 } 612 } 613 614 var cnt = objects.length; 615 if(cnt > 0) 616 { 617 var cb = function(str) 618 { 619 data += (!!str ? '&' : '') + str; 620 if(--cnt <= 0) 621 { 622 callback.call(document, data) 623 } 624 }; 625 626 var cnt1 = cnt; 627 for(var i = 0; i < cnt1; i++) 628 { 629 if(Utils.isDomNode(objects[i][1])) 630 { 631 if(objects[i][1].tagName.toUpperCase() === 'INPUT' && objects[i][1].type === 'file') 632 { 633 if(fileReader.canUse()) 634 { 635 fileReader(objects[i][1], (function(name) 636 { 637 return function(result) 638 { 639 if(Utils.isArray(result) && result.length > 0) 640 { 641 cb(name + '[0]=' + ajax.escape(result[0]) + '&' + name + '[1]=' + ajax.escape(result[1])); 642 } 643 else 644 { 645 cb(name + '='); 646 } 647 } 648 })(objects[i][0])); 649 } 650 } 651 else if(typeof objects[i][1].value !== 'undefined') 652 { 653 cb(objects[i][0] + '=' + ajax.escape(objects[i][1].value)); 654 } 655 else 656 { 657 cb(''); 658 } 659 } 660 else if(Utils.isDate(objects[i][1])) 661 { 662 cb(objects[i][0] + '=' + ajax.escape(objects[i][1].toJSON())); 663 } 664 else if(Utils.isArray(objects[i][1]) && objects[i][1].length <= 0) 665 { 666 cb(objects[i][0] + '='); 667 } 668 else 669 { 670 ajax.prepareData(objects[i][1], objects[i][0], cb); 671 } 672 } 673 } 674 else 675 { 676 callback.call(document, data) 677 } 678 } 679 }; 680 681 ajax.isSuccess = function(xhr) 682 { 683 return typeof xhr.status === 'undefined' || (xhr.status >= 200 && xhr.status < 300) || xhr.status === 304 || xhr.status >= 400 && xhr.status < 500 || xhr.status === 1223 || xhr.status === 0; 684 }; 685 686 var ajaxResult = function(answer, query, status) 687 { 688 this.answer = answer; 689 this.query = Utils.clone(query); 690 this.status = status; 691 692 if(typeof this.answer.next !== 'undefined') 693 { 694 this.answer.next = parseInt(this.answer.next); 695 } 696 697 if(typeof this.answer.error !== 'undefined') 698 { 699 this.answer.ex = new ajaxError(this.status, typeof this.answer.error === 'string' ? this.answer : this.answer.error) 700 } 701 }; 702 703 ajaxResult.prototype.data = function() 704 { 705 return this.answer.result; 706 }; 707 708 ajaxResult.prototype.time = function() 709 { 710 return this.answer.time; 711 }; 712 713 ajaxResult.prototype.error = function() 714 { 715 return this.answer.ex; 716 }; 717 718 ajaxResult.prototype.error_description = function() 719 { 720 return this.answer.error_description; 721 }; 722 723 ajaxResult.prototype.more = function() 724 { 725 return !isNaN(this.answer.next); 726 }; 727 728 ajaxResult.prototype.total = function() 729 { 730 return parseInt(this.answer.total); 731 }; 732 733 ajaxResult.prototype.next = function(cb) 734 { 735 if(this.more()) 736 { 737 this.query.start = this.answer.next; 738 739 if(!!cb && Utils.isFunction(cb)) 740 { 741 this.query.callback = cb; 742 } 743 744 return ajax(this.query); 745 } 746 747 return false;
748 }; 749 750 var ajaxError = function(status, ex) 751 { 752 this.status = status; 753 this.ex = ex; 754 }; 755 756 ajaxError.prototype.getError = function() 757 { 758 return this.ex; 759 }; 760 761 ajaxError.prototype.getStatus = function() 762 { 763 return this.status; 764 }; 765 766 ajaxError.prototype.toString = function() 767 { 768 return this.ex.error + ( 769 !!this.ex.error_description 770 ? ': ' + this.ex.error_description 771 : '' 772 ) + ' (' + this.status + ')'; 773 }; 774 775 var arrayBufferToData = function(arrayBuffer) 776 { 777 var uint8 = new Uint8Array(arrayBuffer); 778 var data = ''; 779 780 // TypedArray.prototype.forEach is not supported in some browsers as IE. 781 if (typeof uint8.forEach === 'function') 782 { 783 uint8.forEach(function (value) 784 { 785 data += String.fromCharCode(value); 786 }); 787 } 788 else 789 { 790 var length = uint8.length; 791 for (var i = 0; i < length; i += 1) 792 { 793 data += String.fromCharCode(uint8[i]); 794 } 795 } 796 return btoa(data); 797 }; 798 799 var fileReader = function(fileInput, cb) 800 { 801 if(fileReader.canUse()) 802 { 803 var files = fileInput.files, 804 len = 0, 805 result = fileInput.multiple ? [] : null; 806 807 for(var i = 0, f; f = files[i]; i++) 808 { 809 var reader = new window.FileReader(); 810 811 reader.BXFILENAME = files[i].name; 812 813 reader.onload = function(e) 814 { 815 e = e || window.event; 816 817 var res = [this.BXFILENAME, arrayBufferToData(e.target.result)]; 818 819 if(result === null) 820 result = res; 821 else 822 result.push(res); 823 824 if(--len <= 0) 825 { 826 cb(result); 827 } 828 }; 829 830 reader.readAsArrayBuffer(f); 831 } 832 len = i; 833 if(len <= 0) 834 { 835 cb(result); 836 } 837 } 838 }; 839 840 fileReader.canUse = function() 841 { 842 return !!window.FileReader; 843 }; 844 845})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.