Passed
Branchmaster (a4124d)
by Plamen
01:22
created

table.js ➔ ... ➔ this.BuildRequest   B

Complexity

Conditions 3
Paths 16

Size

Total Lines 55
Code Lines 38

Duplication

Lines 0
Ratio 0 %

Importance

Changes 6
Bugs 0 Features 0
Metric Value
cc 3
eloc 38
c 6
b 0
f 0
nc 16
nop 3
dl 0
loc 55
rs 8.968

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
var strAsc = String.fromCharCode(9650); //▲
2
var strDesc = String.fromCharCode(9660);//▼
3
var xmlhttp;
4
var d;
5
6
var table = new function(){
7
    this.rq = null;
8
    this.tail = [];
9
10
    this.ReloadData = function(tableId){
11
        var request = {};
12
        this.BuildRequest(request, tableId);
13
        this.LoadData(tableId, request);
14
    };
15
16
    this.BuildRequest = function(request, crntTableId, skipPropertyArray){
17
        this.rq = request;
18
        this.checkSkip = function(skipProperty){
19
            var result = false;
20
            if(skipPropertyArray && Object.prototype.toString
21
                    .call(skipPropertyArray) === '[object Array]'
22
                    ){
23
                if(skipPropertyArray.indexOf(skipProperty) >= 0){
24
                    result = true;
25
                }
26
            }
27
            return result;
28
        };
29
        this.getSort = function(){
30
            var thTags = document.getElementById(crntTableId)
31
                    .getElementsByTagName("thead")[0]
32
                    .getElementsByTagName("th");
33
            var length = thTags.length;
34
            for(var i = 0; i < length; i++){
35
                var link = thTags[i].getElementsByTagName("a")[0];
36
                if(link){
37
                    var span = link.getElementsByTagName("span")[0];
38
                    if(span){
39
                        var order = span.innerHTML;
40
                        if(order.length === 1){
41
                            this.rq.colNo = i;
42
                            this.rq.colOrd = (order === window.strDesc) ?
43
                                    "desc" : "asc";
44
                            return;
45
                        }
46
                    }
47
                }
48
            }
49
        };
50
        this.getFilter = function(){
51
            var r = this.getFilterFieldsByTbaleID(crntTableId);
52
            if(r.filter !== null){
53
                this.rq.filter = r.filter;
54
            }
55
            if(r.filterBy !== null){
56
                this.rq.filterBy = r.filterBy;
57
            }
58
        };
59
60
        /* Build request object */
61
        if(!this.checkSkip("sort")){
62
            this.getSort();
63
        }
64
        if(!this.checkSkip("filter")){
65
            this.getFilter();
66
        }
67
68
        this.rq.tableId = crntTableId;
69
        return this.rq;
70
    };
71
72
    this.RequestToUrl = function(rq){
73
        var url = location.pathname + ".json" + location.search;
74
        if(typeof rq === "object"){
75
            var getUrlVarName = {
76
                colNo: "col", colOrd: "ord", filter: "filter",
77
                filterBy: "filter-by", pageNo: "pg", exportType: "export",
78
                tableId: "table-id"
79
            };
80
            var flagFirst = location.search.length < 1 ? true : false;
81
            for(var r in rq){
1 ignored issue
show
Complexity introduced by
A for in loop automatically includes the property of any prototype object, consider checking the key using hasOwnProperty.

When iterating over the keys of an object, this includes not only the keys of the object, but also keys contained in the prototype of that object. It is generally a best practice to check for these keys specifically:

var someObject;
for (var key in someObject) {
    if ( ! someObject.hasOwnProperty(key)) {
        continue; // Skip keys from the prototype.
    }

    doSomethingWith(key);
}
Loading history...
82
                var clue = flagFirst === true ? "?" : "&";
83
                url += clue + getUrlVarName[r] + "=" + rq[r];
84
                flagFirst = false;
85
            }
86
        }
87
        return url;
88
    };
89
90
    this.Filter = function(field){
91
        var crntTableId = this.FilterGetTableId(field);
92
        if(crntTableId !== null){
93
            var request = {};
94
            var exRq = this.rq;
95
            this.BuildRequest(request, crntTableId);
96
            if(exRq === null ||
97
                    request.filter !== exRq.filter ||
98
                    request.filterBy !== exRq.filterBy
99
                    ){
100
                this.LoadData(crntTableId, request);
101
            }
102
        }
103
    };
104
105
    this.FilterGetTableId = function(field){
106
        if(field.tagName.toLowerCase() !== "select"){
107
            return field.getAttribute("data-table-id");
108
        }else{
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
109
            var f = field.parentNode.parentNode.getElementsByTagName("input")[0];
110
            return '' === f.value ? null : f.getAttribute("data-table-id");
111
        }
112
    };
113
114
    this.GoPage = function(lnk){
115
        var request = {};
116
        var table = this.getParent(lnk, "table");
117
        var crntTableId = table.getAttribute("id");
118
        this.BuildRequest(request, crntTableId);
119
        //check & serve pagination jump links
120
        var jumpDir = lnk.innerHTML.trim().substr(0, 1);
121
        if(jumpDir === "+" || jumpDir === "-"){
122
            var current = table.querySelector("tfoot .paging .a").innerHTML;
123
            var jump = lnk.innerHTML.replace("K", "000").replace("M", "000000000");
124
            var jumpPage = (parseInt(current) + parseInt(jump));
125
            lnk.parentNode.setAttribute("data-page", jumpPage);
126
            lnk.style.transform = "none";
127
        }
128
        request.pageNo = lnk.parentNode.hasAttribute("data-page") ?
129
                lnk.parentNode.getAttribute("data-page") :
130
                lnk.innerHTML;
131
        this.LoadData(crntTableId, request);
132
        return false;
133
    };
134
135
    this.Export = function(lnk, eType){
136
        var request = {};
137
        var crntTableId = this.getParent(lnk, "table").getAttribute("id");
138
        this.BuildRequest(request, crntTableId);
139
        request.exportType = ["CSV", "Excel"].indexOf(eType) >= 0 ? eType : "csv";
140
        window.open(this.RequestToUrl(request));
141
        return false;
142
    };
143
144
    this.Sort = function(colNo, lnk){
145
        var request = {};
146
        var crntTableId = this.getParent(lnk, "table").getAttribute("id");
147
        this.BuildRequest(request, crntTableId);
148
        if(Math.round(colNo) === request.colNo){
149
            request.colOrd = request.colOrd === "asc" ? "desc" : "asc";
150
        }else{
151
            request.colNo = Math.round(colNo);
152
            request.colOrd = "asc";
153
        }
154
        this.LoadData(crntTableId, request);
155
        /* Clear and add new sort arrow */
156
        var headSpans = this.getParent(lnk, "thead").getElementsByTagName("span");
157
        var length = headSpans.length;
158
        for(var i = 0; i < length; i++){
159
            headSpans[i].innerHTML = "";
160
        }
161
        lnk.getElementsByTagName("span")[0].innerHTML = (request.colOrd === "desc" ? window.strDesc : window.strAsc);
162
    };
163
164
    this.DrawSection = function(tableContainer, dt, tSection){
165
        var section = tSection === "tfoot" ? "tfoot" : "tbody";
166
        tSection = document.getElementById(tableContainer).
167
                getElementsByTagName(section)[0];
168
        this.clearSection(tSection);
169
        for(var i = 0; i < dt.length; i++){
170
            var row = dt[i];
171
            var tRow = document.createElement("tr");
172
173
            this.DrawRow(row, tRow);
174
175
            tSection.appendChild(tRow);
176
            if(section === "tfoot"){
177
                this.footerProcessPaginationLinks(tSection);
178
            }
179
            this.AppendRowCalback(tableContainer);
180
        }
181
    };
182
183
    this.DrawRow = function(row, tRow){
184
        for(var cell in row){
1 ignored issue
show
Complexity introduced by
A for in loop automatically includes the property of any prototype object, consider checking the key using hasOwnProperty.

When iterating over the keys of an object, this includes not only the keys of the object, but also keys contained in the prototype of that object. It is generally a best practice to check for these keys specifically:

var someObject;
for (var key in someObject) {
    if ( ! someObject.hasOwnProperty(key)) {
        continue; // Skip keys from the prototype.
    }

    doSomethingWith(key);
}
Loading history...
185
            var tCell = document.createElement("td");
186
            if(typeof row[cell] === "string" || typeof row[cell] === "number"){
187
                tCell.innerHTML = row[cell];
188
            }else if(typeof row[cell] === "object"){
189
                this.DrawCellFromObject(row, cell, tCell);
190
            }
191
            tRow.appendChild(tCell);
192
        }
193
    };
194
195
    this.DrawCellFromObject = function(row, cell, tCell){
196
        for(var attr in row[cell]){
1 ignored issue
show
Complexity introduced by
A for in loop automatically includes the property of any prototype object, consider checking the key using hasOwnProperty.

When iterating over the keys of an object, this includes not only the keys of the object, but also keys contained in the prototype of that object. It is generally a best practice to check for these keys specifically:

var someObject;
for (var key in someObject) {
    if ( ! someObject.hasOwnProperty(key)) {
        continue; // Skip keys from the prototype.
    }

    doSomethingWith(key);
}
Loading history...
197
            if(typeof row[cell][attr] === "string"){
198
                tCell.innerHTML = row[cell][attr];
199
            }else if(typeof row[cell][attr] === "object"){
200
                for(var v in row[cell][attr]){
1 ignored issue
show
Complexity introduced by
A for in loop automatically includes the property of any prototype object, consider checking the key using hasOwnProperty.

When iterating over the keys of an object, this includes not only the keys of the object, but also keys contained in the prototype of that object. It is generally a best practice to check for these keys specifically:

var someObject;
for (var key in someObject) {
    if ( ! someObject.hasOwnProperty(key)) {
        continue; // Skip keys from the prototype.
    }

    doSomethingWith(key);
}
Loading history...
201
                    tCell.setAttribute(v, row[cell][attr][v]);
202
                }
203
            }
204
        }
205
    };
206
207
    this.footerProcessPaginationLinks = function(tSection){
208
        var pLinks = tSection.querySelectorAll(".paging a");
209
        if(pLinks.length > 0){
210
            for(var j = 0; j < pLinks.length; j++){
211
                pLinks[j].setAttribute("href", "javascript:void(0);");
212
                pLinks[j].setAttribute("onclick", "return table.GoPage(this);");
213
            }
214
        }
215
    };
216
217
    this.clearSection = function(tSection){
218
        if(this.iePrior(9)){
219
            if(tSection.firstChild){
220
                while(tSection.firstChild){
221
                    tSection.removeChild(tSection.firstChild);
222
                }
223
            }
224
        }else{
225
            tSection.innerHTML = "";
226
        }
227
    };
228
229
    this.SetTheTableColumnsHoverEffect = function(tableContainer){
230
        if(this.iePrior(9)){
231
            return;
232
        }
233
        var tContainer = document.getElementById(tableContainer);
234
        var tHcells = tContainer.rows[0].cells;
235
        for(var i = 0; i < tHcells.length; i++){
236
            if(tHcells[i].firstChild.tagName === "A"){
237
                tHcells[i].firstChild.setAttribute("onmouseover", "table.ColumnHover('" + tableContainer + "'," + i + ");");
238
                tHcells[i].firstChild.setAttribute("onmouseout", "table.ColumnHover('" + tableContainer + "');");
239
            }
240
        }
241
        this.setPagingLinksSetActions(tContainer);
242
    };
243
244
    this.setPagingLinksSetActions = function(tContainer){
245
        var pLinks = tContainer.querySelectorAll("tfoot .paging a");
246
        if(pLinks.length > 0){
247
            for(var j = 0; j < pLinks.length; j++){
248
                pLinks[j].setAttribute("href", "javascript:void(0);");
249
                pLinks[j].setAttribute("onclick", "return table.GoPage(this);");
250
            }
251
        }
252
    };
253
254
    this.ColumnHover = function(tableContainer, index=null){
255
        if(!this.iePrior(9)){
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if !this.iePrior(9) is false. Are you sure this is correct? If so, consider adding return; explicitly.

This check looks for functions where a return statement is found in some execution paths, but not in all.

Consider this little piece of code

function isBig(a) {
    if (a > 5000) {
        return "yes";
    }
}

console.log(isBig(5001)); //returns yes
console.log(isBig(42)); //returns undefined

The function isBig will only return a specific value when its parameter is bigger than 5000. In any other case, it will implicitly return undefined.

This behaviour may not be what you had intended. In any case, you can add a return undefined to the other execution path to make the return value explicit.

Loading history...
256
            var rows = document.getElementById(tableContainer).rows;
257
            var upto = rows.length - 1;
258
            if(index === null){
259
                return this.columnHoverRelease(rows, upto);
260
            }
261
            for(var i = 0; i < upto; i++){
262
                rows[i].cells[index].setAttribute("lang", "col-hover");
263
            }
0 ignored issues
show
Best Practice introduced by
There is no return statement in this branch, but you do return something in other branches. Did you maybe miss it? If you do not want to return anything, consider adding return undefined; explicitly.
Loading history...
264
        }
265
    };
266
    this.columnHoverRelease = function(rows, upto){
267
        for(var i = 0; i < upto; i++){
268
            for(var j = 0; j < rows[i].cells.length; j++){
269
                if(rows[i].cells[j].lang){
270
                    rows[i].cells[j].removeAttribute("lang");
271
                }
272
            }
273
        }
274
    };
275
276
    this.getFilterFieldsByTbaleID = function(tableID){
277
        var fields = {filterBy: null, filter: null};
278
        var filterDiv = this.getFilterDivByTableIDOrNull(tableID);
279
        if(filterDiv !== null){
280
            var slctObj = filterDiv.getElementsByTagName("select")[0];
281
            var textObj = filterDiv.getElementsByTagName("input")[0];
282
            if(slctObj && slctObj.options[slctObj.selectedIndex].value !== "all"){
283
                fields.filterBy = slctObj.options[slctObj.selectedIndex].value;
284
            }
285
            if(textObj && textObj.value.length !== 0){
286
                fields.filter = encodeURIComponent(textObj.value.trim());
287
            }
288
        }
289
        return fields;
290
    };
291
292
    this.getFilterDivByTableIDOrNull = function(tableID){
293
        var res = null;
294
        if(document.getElementById(tableID).parentNode.getElementsByTagName("div").length > 0){
295
            for(var i = 0; i < document.getElementById(tableID).parentNode.getElementsByTagName("div").length; i++){
296
                if(document.getElementById(tableID).parentNode.getElementsByTagName("div")[i].getAttribute("class") === "filter"){
297
                    return document.getElementById(tableID).parentNode.getElementsByTagName("div")[i];
298
                }
299
            }
300
301
        }
302
        return res;
303
    };
304
305
    this.LoadData = function(tableContainer, rq){
306
        this.setVisability(tableContainer, false);
307
        if(window.XMLHttpRequest){
308
            xmlhttp = new XMLHttpRequest();/* code for IE7+, Firefox, Chrome, Opera, Safari */
309
        }else{ /** global: ActiveXObject */
310
            xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");/*code for IE6, IE5 */
0 ignored issues
show
Bug introduced by
The variable ActiveXObject seems to be never declared. If this is a global, consider adding a /** global: ActiveXObject */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
311
        }
312
        for(var i = 0; i < this.tail.length; i++){
313
            var ex_xmlhttp = this.tail.shift();
314
            ex_xmlhttp.abort();
315
        }
316
        xmlhttp.onreadystatechange = function(){
317
            if(xmlhttp.readyState === 4 && xmlhttp.status === 200){
318
                d = JSON.parse(xmlhttp.responseText);
319
                table.DrawSection(tableContainer, d.body);
320
                table.DrawSection(tableContainer, d.footer, "tfoot");
321
                table.LoadEndCalback(tableContainer);
322
                table.setVisability(tableContainer, true);
323
                if(typeof rq === "object"){
324
                    var hover = document.getElementById(rq.tableId)
325
                                .getElementsByTagName("th")[rq.colNo].lang;
326
                    if(hover){
327
                        table.ColumnHover(tableContainer, rq.colNo);
328
                    }
329
                }
330
            }
331
        };
332
        xmlhttp.open("GET", this.RequestToUrl(rq), true);
333
        xmlhttp.send();
334
        this.tail.push(xmlhttp); //put in tail to may later abort any previous
335
    };
336
337
    this.setVisability = function(tableContainer, rq){
338
        var tbl = document.getElementById(tableContainer);
339
        if(rq === true){
340
            tbl.style.filter = "none";
341
            tbl.style.opacity = "1";
342
            tbl.style.cursor = "auto";
343
        }else if(rq === false){
344
            tbl.style.filter = "blur(1px)";
345
            tbl.style.opacity = "0.8";
346
            tbl.style.cursor = "wait";
347
        }else{
348
            console.log("table error in the rq value"); /*Shows error*/
0 ignored issues
show
Debugging Code introduced by
console.log looks like debug code. Are you sure you do not want to remove it?
Loading history...
349
        }
350
    };
351
352
    this.getParent = function(obj, objType){
353
        while(obj && obj.tagName !== objType.toUpperCase()){
354
            obj = obj.parentNode;
355
        }
356
        return obj;
357
    };
358
359
    this.init = function(tableId){
360
        this.SetTheTableColumnsHoverEffect(tableId);
361
    };
362
363
    this.iePrior = function(v){
364
        var rv = false;
365
        if(/** global: navigator */ navigator.appName === 'Microsoft Internet Explorer'){
0 ignored issues
show
Bug introduced by
The variable navigator seems to be never declared. If this is a global, consider adding a /** global: navigator */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
366
            var ua = navigator.userAgent;
367
            var re = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})");
368
            if(re.exec(ua) !== null){
369
                rv = parseFloat(RegExp.$1);
370
            }
371
            rv = rv < v ? true : false;
372
        }
373
        return rv;
374
    };
375
    this.loadJS = function(src){
376
        var s = document.createElement('script');
377
        s.src = src;
378
        document.getElementsByTagName('head')[0].appendChild(s);
379
    };
380
    this.loadCSS = function(src){
381
        var s = document.createElement('link');
382
        s.href = src;
383
        s.rel = "stylesheet";
384
        document.getElementsByTagName('head')[0].appendChild(s);
385
    };
386
387
    this.LoadEndCalback = function(tableId){
388
        if(tableId){/*Allows override*/
0 ignored issues
show
Comprehensibility Documentation Best Practice introduced by
This code block is empty. Consider removing it or adding a comment to explain.
Loading history...
389
        }
390
    };
391
    this.AppendRowCalback = function(tableId){
392
        if(tableId){/*Allows override*/
0 ignored issues
show
Comprehensibility Documentation Best Practice introduced by
This code block is empty. Consider removing it or adding a comment to explain.
Loading history...
393
        }
394
    };
395
};
396
397
/** Moves custom created filter to the Table's filter
398
 * @param {string} filterId
399
 * @param {string} tableId
400
 * @param {boolean} delay - needed in case the table is istill not executed */
401
function moveSelectorToTheTableFilter(filterId, tableId, delay){
402
    if(delay === true){
403
        setTimeout(function(){
404
            var filterDiv = document.getElementById(tableId)
405
                    .getElementsByTagName("div")[0];
406
            filterDiv.appendChild(document.getElementById(filterId));
407
        }, 500);
408
    }else{
409
        var filterDiv = document.getElementById(tableId)
410
                .getElementsByTagName("div")[0];
411
        filterDiv.appendChild(document.getElementById(filterId));
412
    }
413
}
414
415
function changeListCustomFilter(selectObj){
416
    var name = selectObj.getAttribute("name");
417
418
    var inUrlPos = document.URL.indexOf(name);
419
    var url = inUrlPos !== -1 ?
420
            document.URL.substring(0, (inUrlPos - 1)) :
421
            document.URL;
422
423
    var value = selectObj.options[selectObj.selectedIndex].value;
424
    if(value !== "{!--Empty--!}"){
425
        var clue = document.URL.indexOf("?") > 0 ? "&" : "?";
426
        url += (clue + name + "=" + value);
427
    }
428
429
    location.assign(url);
430
}
431
432
433
function tablesLoadData(){
434
    var tables = document.getElementsByTagName("table");
435
    var envPrior9 = table.iePrior(9);
436
    for(var i = 0; i < tables.length; i++){
437
        var isProcessable = envPrior9 ?
438
                typeof tables[i]["data-table"] !== 'undefined' :
439
                tables[i].hasAttribute("data-table");
440
        if(isProcessable && tables[i].getAttribute("data-table") === "js"){
441
            table.LoadData(tables[i].id);
442
            table.SetTheTableColumnsHoverEffect(tables[i].id);
443
        }
444
    }
445
    /*if(table.iePrior(10)){
446
     table.loadJS("/add/helpers/table/add/json2.js");
447
     }
448
     
449
     if(table.iePrior(8)){ //can be used to add apropriate tables links modifications
450
     // loadCSS("/add/helpers/table/add/ie7-and-down.css");
451
     }*/
452
}
453
454
/*if(window.addEventListener){window.addEventListener('load',tablesLoadData,false);} else if(window.attachEvent){window.attachEvent('onload',tablesLoadData);}*/