1 var Ajax =
function(table){
6 this.urlGenerator =
false;
9 this.loaderElement = this.createLoaderElement();
10 this.msgElement = this.createMsgElement();
11 this.loadingElement =
false;
12 this.errorElement =
false;
13 this.loaderPromise =
false;
15 this.progressiveLoad =
false;
18 this.requestOrder = 0;
22 Ajax.prototype.initialize =
function(){
25 this.loaderElement.appendChild(this.msgElement);
27 if(this.table.options.ajaxLoaderLoading){
28 if(typeof this.table.options.ajaxLoaderLoading ==
"string"){
29 template = document.createElement(
'template');
30 template.innerHTML = this.table.options.ajaxLoaderLoading.trim();
31 this.loadingElement =
template.content.firstChild;
33 this.loadingElement = this.table.options.ajaxLoaderLoading;
37 this.loaderPromise = this.table.options.ajaxRequestFunc || this.defaultLoaderPromise;
39 this.urlGenerator = this.table.options.ajaxURLGenerator || this.defaultURLGenerator;
41 if(this.table.options.ajaxLoaderError){
42 if(typeof this.table.options.ajaxLoaderError ==
"string"){
43 template = document.createElement(
'template');
44 template.innerHTML = this.table.options.ajaxLoaderError.trim();
45 this.errorElement =
template.content.firstChild;
47 this.errorElement = this.table.options.ajaxLoaderError;
51 if(this.table.options.ajaxParams){
52 this.setParams(this.table.options.ajaxParams);
55 if(this.table.options.ajaxConfig){
56 this.setConfig(this.table.options.ajaxConfig);
59 if(this.table.options.ajaxURL){
60 this.setUrl(this.table.options.ajaxURL);
63 if(this.table.options.ajaxProgressiveLoad){
64 if(this.table.options.pagination){
65 this.progressiveLoad =
false;
66 console.error(
"Progressive Load Error - Pagination and progressive load cannot be used at the same time");
68 if(this.table.modExists(
"page")){
69 this.progressiveLoad = this.table.options.ajaxProgressiveLoad;
70 this.table.modules.page.initializeProgressive(this.progressiveLoad);
72 console.error(
"Pagination plugin is required for progressive ajax loading");
78 Ajax.prototype.createLoaderElement =
function (){
79 var el = document.createElement(
"div");
80 el.classList.add(
"tabulator-loader");
84 Ajax.prototype.createMsgElement =
function (){
85 var el = document.createElement(
"div");
87 el.classList.add(
"tabulator-loader-msg");
88 el.setAttribute(
"role",
"alert");
94 Ajax.prototype.setParams =
function(params, update){
96 this.params = this.params || {};
98 for(let key in params){
99 this.params[key] = params[key];
102 this.params = params;
106 Ajax.prototype.getParams =
function(){
107 return this.params || {};
111 Ajax.prototype.setConfig =
function(config){
112 this._loadDefaultConfig();
114 if(typeof config ==
"string"){
115 this.config.method = config;
117 for(let key in config){
118 this.config[key] = config[key];
124 Ajax.prototype._loadDefaultConfig =
function(force){
126 if(!
self.config || force){
131 for(let key in
self.defaultConfig){
132 self.config[key] =
self.defaultConfig[key];
138 Ajax.prototype.setUrl =
function(url){
143 Ajax.prototype.getUrl =
function(){
148 Ajax.prototype.loadData =
function(inPosition){
151 if(this.progressiveLoad){
152 return this._loadDataProgressive();
154 return this._loadDataStandard(inPosition);
158 Ajax.prototype.nextPage =
function(diff){
163 margin = this.table.options.ajaxProgressiveLoadScrollMargin || (this.table.rowManager.getElement().clientHeight * 2);
166 this.table.modules.page.nextPage()
167 .then(()=>{}).
catch(()=>{});
172 Ajax.prototype.blockActiveRequest =
function(){
173 this.requestOrder ++;
176 Ajax.prototype._loadDataProgressive =
function(){
177 this.table.rowManager.setData([]);
178 return this.table.modules.page.setPage(1);
181 Ajax.prototype._loadDataStandard =
function(inPosition){
182 return new Promise((resolve, reject)=>{
183 this.sendRequest(inPosition)
185 this.table.rowManager.setData(data, inPosition)
199 Ajax.prototype.generateParamsList =
function(data, prefix){
203 prefix = prefix ||
"";
205 if ( Array.isArray(data) ) {
206 data.forEach(
function(item, i){
207 output = output.concat(
self.generateParamsList(item, prefix ? prefix +
"[" + i +
"]" : i));
209 }
else if (typeof data ===
"object"){
210 for (var key in data){
211 output = output.concat(
self.generateParamsList(data[key], prefix ? prefix +
"[" + key +
"]" : key));
214 output.push({key:prefix, value:data});
221 Ajax.prototype.serializeParams =
function(params){
222 var output = this.generateParamsList(params),
225 output.forEach(
function(item){
226 encoded.push(encodeURIComponent(item.key) +
"=" + encodeURIComponent(item.value));
229 return encoded.join(
"&");
234 Ajax.prototype.sendRequest =
function(silent){
237 requestNo, esc, query;
239 self.requestOrder ++;
240 requestNo =
self.requestOrder;
242 self._loadDefaultConfig();
244 return new Promise((resolve, reject)=>{
245 if(
self.table.options.ajaxRequesting.call(
this.table,
self.url,
self.params) !==
false){
253 this.loaderPromise(url,
self.config,
self.params).then((data)=>{
254 if(requestNo ===
self.requestOrder){
255 if(
self.table.options.ajaxResponse){
256 data =
self.table.options.ajaxResponse.call(
self.table,
self.url,
self.params, data);
260 console.warn(
"Ajax Response Blocked - An active ajax request was blocked by an attempt to change table data while the request was being made");
265 self.loading =
false;
268 console.error(
"Ajax Load Error: ", error);
269 self.table.options.ajaxError.call(
self.table, error);
273 setTimeout(
function(){
277 self.loading =
false;
289 Ajax.prototype.showLoader =
function(){
290 var shouldLoad = typeof this.table.options.ajaxLoader ===
"function" ? this.table.options.ajaxLoader() : this.table.options.ajaxLoader;
296 while(this.msgElement.firstChild) this.msgElement.removeChild(this.msgElement.firstChild);
297 this.msgElement.classList.remove(
"tabulator-error");
298 this.msgElement.classList.add(
"tabulator-loading");
300 if(this.loadingElement){
301 this.msgElement.appendChild(this.loadingElement);
303 this.msgElement.innerHTML = this.table.modules.localize.getText(
"ajax|loading");
306 this.table.element.appendChild(this.loaderElement);
310 Ajax.prototype.showError =
function(){
313 while(this.msgElement.firstChild) this.msgElement.removeChild(this.msgElement.firstChild);
314 this.msgElement.classList.remove(
"tabulator-loading");
315 this.msgElement.classList.add(
"tabulator-error");
317 if(this.errorElement){
318 this.msgElement.appendChild(this.errorElement);
320 this.msgElement.innerHTML = this.table.modules.localize.getText(
"ajax|error");
323 this.table.element.appendChild(this.loaderElement);
326 Ajax.prototype.hideLoader =
function(){
327 if(this.loaderElement.parentNode){
328 this.loaderElement.parentNode.removeChild(this.loaderElement);
333 Ajax.prototype.defaultConfig = {
337 Ajax.prototype.defaultURLGenerator =
function(url, config, params){
340 if(params && Object.keys(params).length){
341 if(!config.method || config.method.toLowerCase() ==
"get"){
342 config.method =
"get";
344 url += (url.includes(
"?") ?
"&" :
"?") + this.serializeParams(params);
352 Ajax.prototype.defaultLoaderPromise =
function(url, config, params){
353 var
self =
this, contentType;
355 return new Promise(
function(resolve, reject){
358 url =
self.urlGenerator(url, config, params);
361 if(config.method.toUpperCase() !=
"GET"){
362 contentType = typeof
self.table.options.ajaxContentType ===
"object" ?
self.table.options.ajaxContentType :
self.contentTypeFormatters[
self.table.options.ajaxContentType];
365 for(var key in contentType.headers){
370 if(typeof config.headers[key] ===
"undefined"){
371 config.headers[key] = contentType.headers[key];
375 config.body = contentType.body.call(
self, url, config, params);
378 console.warn(
"Ajax Error - Invalid ajaxContentType value:",
self.table.options.ajaxContentType);
385 if(typeof config.headers ===
"undefined"){
389 if(typeof config.headers.Accept ===
"undefined"){
390 config.headers.Accept =
"application/json";
393 if(typeof config.headers[
"X-Requested-With"] ===
"undefined"){
394 config.headers[
"X-Requested-With"] =
"XMLHttpRequest";
397 if(typeof config.mode ===
"undefined"){
398 config.mode =
"cors";
401 if(config.mode ==
"cors"){
403 if(typeof config.headers[
"Access-Control-Allow-Origin"] ===
"undefined"){
404 config.headers[
"Access-Control-Allow-Origin"] = window.location.origin;
407 if(typeof config.credentials ===
"undefined"){
408 config.credentials =
'same-origin';
411 if(typeof config.credentials ===
"undefined"){
412 config.credentials =
'include';
425 console.warn(
"Ajax Load Error - Invalid JSON returned", error);
428 console.error(
"Ajax Load Error - Connection Error: " + response.status, response.statusText);
433 console.error(
"Ajax Load Error - Connection Error: ", error);
437 console.warn(
"Ajax Load Error - No URL Set");
444 Ajax.prototype.contentTypeFormatters = {
447 'Content-Type':
'application/json',
449 body:
function(url, config, params){
450 return JSON.stringify(params);
456 body:
function(url, config, params){
457 var output = this.generateParamsList(params),
458 form =
new FormData();
460 output.forEach(
function(item){
461 form.append(item.key, item.value);
469 Tabulator.prototype.registerModule(
"ajax", Ajax);