Passed
Branchmaster (06b979)
by Plamen
01:26
created

table.js ➔ ... ➔ this.setFilterFields   A

Complexity

Conditions 5
Paths 4

Size

Total Lines 10
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 5
eloc 7
c 1
b 0
f 0
nc 4
nop 2
dl 0
loc 10
rs 9.3333
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 && this.setSortByFirstLinkFirstSpan(span, i)){
39
                        break;
40
                    }
41
                }
42
            }
43
        };
44
        this.setSortByFirstLinkFirstSpan = function(span, i){
45
            var order = span.innerHTML;
46
            if(order.length === 1){
47
                this.rq.colNo = i;
48
                this.rq.colOrd = (order === window.strDesc) ?
49
                        "desc" : "asc";
50
            }
51
            return this.rq.colNo === i;
52
        };
53
        this.getFilter = function(){
54
            var r = this.getFilterFieldsByTableID(crntTableId);
55
            if(r.filter !== null){
56
                this.rq.filter = r.filter;
57
            }
58
            if(r.filterBy !== null){
59
                this.rq.filterBy = r.filterBy;
60
            }
61
        };
62
63
        /* Build request object */
64
        if(!this.checkSkip("sort")){
65
            this.getSort();
66
        }
67
        if(!this.checkSkip("filter")){
68
            this.getFilter();
69
        }
70
71
        this.rq.tableId = crntTableId;
72
        return this.rq;
73
    };
74
75
    this.RequestToUrl = function(rq){
76
        var url = location.pathname + ".json" + location.search;
77
        if(typeof rq === "object"){
78
            var getUrlVarName = {
79
                colNo: "col", colOrd: "ord", filter: "filter",
80
                filterBy: "filter-by", pageNo: "pg", exportType: "export",
81
                tableId: "table-id"
82
            };
83
            var flagFirst = location.search.length < 1 ? true : false;
84
            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...
85
                var clue = flagFirst === true ? "?" : "&";
86
                url += clue + getUrlVarName[r] + "=" + rq[r];
87
                flagFirst = false;
88
            }
89
        }
90
        return url;
91
    };
92
93
    this.Filter = function(field){
94
        var crntTableId = this.FilterGetTableId(field);
95
        if(crntTableId !== null){
96
            var request = {};
97
            var exRq = this.rq;
98
            this.BuildRequest(request, crntTableId);
99
            if(exRq === null ||
100
                    request.filter !== exRq.filter ||
101
                    request.filterBy !== exRq.filterBy
102
                    ){
103
                this.LoadData(crntTableId, request);
104
            }
105
        }
106
    };
107
108
    this.FilterGetTableId = function(field){
109
        if(field.tagName.toLowerCase() !== "select"){
110
            return field.getAttribute("data-table-id");
111
        }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...
112
            var f = field.parentNode.parentNode.getElementsByTagName("input")[0];
113
            return '' === f.value ? null : f.getAttribute("data-table-id");
114
        }
115
    };
116
117
    this.GoPage = function(lnk){
118
        var request = {};
119
        var table = this.getParent(lnk, "table");
120
        var crntTableId = table.getAttribute("id");
121
        this.BuildRequest(request, crntTableId);
122
        //check & serve pagination jump links
123
        var jumpDir = lnk.innerHTML.trim().substr(0, 1);
124
        if(jumpDir === "+" || jumpDir === "-"){
125
            var current = table.querySelector("tfoot .paging .a").innerHTML;
126
            var jump = lnk.innerHTML.replace("K", "000").replace("M", "000000000");
127
            var jumpPage = (parseInt(current) + parseInt(jump));
128
            lnk.parentNode.setAttribute("data-page", jumpPage);
129
            lnk.style.transform = "none";
130
        }
131
        request.pageNo = lnk.parentNode.hasAttribute("data-page") ?
132
                lnk.parentNode.getAttribute("data-page") :
133
                lnk.innerHTML;
134
        this.LoadData(crntTableId, request);
135
        return false;
136
    };
137
138
    this.Export = function(lnk, eType){
139
        var request = {};
140
        var crntTableId = this.getParent(lnk, "table").getAttribute("id");
141
        this.BuildRequest(request, crntTableId);
142
        request.exportType = ["CSV", "Excel"].indexOf(eType) >= 0 ? eType : "csv";
143
        window.open(this.RequestToUrl(request));
144
        return false;
145
    };
146
147
    this.Sort = function(colNo, lnk){
148
        var request = {};
149
        var crntTableId = this.getParent(lnk, "table").getAttribute("id");
150
        this.BuildRequest(request, crntTableId);
151
        if(Math.round(colNo) === request.colNo){
152
            request.colOrd = request.colOrd === "asc" ? "desc" : "asc";
153
        }else{
154
            request.colNo = Math.round(colNo);
155
            request.colOrd = "asc";
156
        }
157
        this.LoadData(crntTableId, request);
158
        /* Clear and add new sort arrow */
159
        var headSpans = this.getParent(lnk, "thead").getElementsByTagName("span");
160
        var length = headSpans.length;
161
        for(var i = 0; i < length; i++){
162
            headSpans[i].innerHTML = "";
163
        }
164
        lnk.getElementsByTagName("span")[0].innerHTML = (request.colOrd === "desc" ? window.strDesc : window.strAsc);
165
    };
166
167
    this.DrawSection = function(tableContainer, dt, tSection){
168
        var section = tSection === "tfoot" ? "tfoot" : "tbody";
169
        tSection = document.getElementById(tableContainer).
170
                getElementsByTagName(section)[0];
171
        this.clearSection(tSection);
172
        for(var i = 0; i < dt.length; i++){
173
            var row = dt[i];
174
            var tRow = document.createElement("tr");
175
176
            this.DrawRow(row, tRow);
177
178
            tSection.appendChild(tRow);
179
            if(section === "tfoot"){
180
                this.footerProcessPaginationLinks(tSection);
181
            }
182
            this.AppendRowCalback(tableContainer);
183
        }
184
    };
185
186
    this.DrawRow = function(row, tRow){
187
        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...
188
            var tCell = document.createElement("td");
189
            if(typeof row[cell] === "string" || typeof row[cell] === "number"){
190
                tCell.innerHTML = row[cell];
191
            }else if(typeof row[cell] === "object"){
192
                this.DrawCellFromObject(row, cell, tCell);
193
            }
194
            tRow.appendChild(tCell);
195
        }
196
    };
197
198
    this.DrawCellFromObject = function(row, cell, tCell){
199
        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...
200
            if(typeof row[cell][attr] === "string"){
201
                tCell.innerHTML = row[cell][attr];
202
            }else if(typeof row[cell][attr] === "object"){
203
                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...
204
                    tCell.setAttribute(v, row[cell][attr][v]);
205
                }
206
            }
207
        }
208
    };
209
210
    this.footerProcessPaginationLinks = function(tSection){
211
        var pLinks = tSection.querySelectorAll(".paging a");
212
        if(pLinks.length > 0){
213
            for(var j = 0; j < pLinks.length; j++){
214
                pLinks[j].setAttribute("href", "javascript:void(0);");
215
                pLinks[j].setAttribute("onclick", "return table.GoPage(this);");
216
            }
217
        }
218
    };
219
220
    this.clearSection = function(tSection){
221
        if(this.iePrior(9)){
222
            if(tSection.firstChild){
223
                while(tSection.firstChild){
224
                    tSection.removeChild(tSection.firstChild);
225
                }
226
            }
227
        }else{
228
            tSection.innerHTML = "";
229
        }
230
    };
231
232
    this.SetTheTableColumnsHoverEffect = function(tableContainer){
233
        if(this.iePrior(9)){
234
            return;
235
        }
236
        var tContainer = document.getElementById(tableContainer);
237
        var tHcells = tContainer.rows[0].cells;
238
        for(var i = 0; i < tHcells.length; i++){
239
            if(tHcells[i].firstChild.tagName === "A"){
240
                tHcells[i].firstChild.setAttribute("onmouseover", "table.ColumnHover('" + tableContainer + "'," + i + ");");
241
                tHcells[i].firstChild.setAttribute("onmouseout", "table.ColumnHover('" + tableContainer + "');");
242
            }
243
        }
244
        this.setPagingLinksSetActions(tContainer);
245
    };
246
247
    this.setPagingLinksSetActions = function(tContainer){
248
        var pLinks = tContainer.querySelectorAll("tfoot .paging a");
249
        if(pLinks.length > 0){
250
            for(var j = 0; j < pLinks.length; j++){
251
                pLinks[j].setAttribute("href", "javascript:void(0);");
252
                pLinks[j].setAttribute("onclick", "return table.GoPage(this);");
253
            }
254
        }
255
    };
256
257
    this.ColumnHover = function(tableContainer, index=null){
258
        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...
259
            var rows = document.getElementById(tableContainer).rows;
260
            var upto = rows.length - 1;
261
            if(index === null){
262
                return this.columnHoverRelease(rows, upto);
263
            }
264
            for(var i = 0; i < upto; i++){
265
                rows[i].cells[index].setAttribute("lang", "col-hover");
266
            }
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...
267
        }
268
    };
269
    this.columnHoverRelease = function(rows, upto){
270
        for(var i = 0; i < upto; i++){
271
            for(var j = 0; j < rows[i].cells.length; j++){
272
                if(rows[i].cells[j].lang){
273
                    rows[i].cells[j].removeAttribute("lang");
274
                }
275
            }
276
        }
277
    };
278
279
    this.getFilterFieldsByTableID = function(tableID){
280
        var fields = {filterBy: null, filter: null};
281
        var filterDiv = this.getFilterDivByTableIDOrNull(tableID);
282
        if(filterDiv !== null){
283
            this.setFilterFields(fields, filterDiv);
284
        }
285
        return fields;
286
    };
287
    this.setFilterFields = function(fields, filterDiv){
288
        var slctObj = filterDiv.getElementsByTagName("select")[0];
289
        if(slctObj && slctObj.options[slctObj.selectedIndex].value !== "all"){
290
            fields.filterBy = slctObj.options[slctObj.selectedIndex].value;
291
        }
292
        var textObj = filterDiv.getElementsByTagName("input")[0];
293
        if(textObj && textObj.value.length !== 0){
294
            fields.filter = encodeURIComponent(textObj.value.trim());
295
        }
296
    };
297
298
    this.getFilterDivByTableIDOrNull = function(tableID){
299
        var res = null;
300
        if(document.getElementById(tableID).parentNode.getElementsByTagName("div").length > 0){
301
            for(var i = 0; i < document.getElementById(tableID).parentNode.getElementsByTagName("div").length; i++){
302
                if(document.getElementById(tableID).parentNode.getElementsByTagName("div")[i].getAttribute("class") === "filter"){
303
                    return document.getElementById(tableID).parentNode.getElementsByTagName("div")[i];
304
                }
305
            }
306
307
        }
308
        return res;
309
    };
310
311
    this.LoadData = function(tableContainer, rq){
312
        this.setVisability(tableContainer, false);
313
        if(window.XMLHttpRequest){
314
            xmlhttp = new XMLHttpRequest();/* code for IE7+, Firefox, Chrome, Opera, Safari */
315
        }else{ /** global: ActiveXObject */
316
            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...
317
        }
318
        for(var i = 0; i < this.tail.length; i++){
319
            var ex_xmlhttp = this.tail.shift();
320
            ex_xmlhttp.abort();
321
        }
322
        xmlhttp.onreadystatechange = function(){
323
            if(xmlhttp.readyState === 4 && xmlhttp.status === 200){
324
                d = JSON.parse(xmlhttp.responseText);
325
                table.DrawSection(tableContainer, d.body);
326
                table.DrawSection(tableContainer, d.footer, "tfoot");
327
                table.LoadEndCalback(tableContainer);
328
                table.setVisability(tableContainer, true);
329
                if(typeof rq === "object"){
330
                    var hover = document.getElementById(rq.tableId)
331
                                .getElementsByTagName("th")[rq.colNo].lang;
332
                    if(hover){
333
                        table.ColumnHover(tableContainer, rq.colNo);
334
                    }
335
                }
336
            }
337
        };
338
        xmlhttp.open("GET", this.RequestToUrl(rq), true);
339
        xmlhttp.send();
340
        this.tail.push(xmlhttp); //put in tail to may later abort any previous
341
    };
342
343
    this.setVisability = function(tableContainer, rq){
344
        var tbl = document.getElementById(tableContainer);
345
        if(rq === true){
346
            tbl.style.filter = "none";
347
            tbl.style.opacity = "1";
348
            tbl.style.cursor = "auto";
349
        }else if(rq === false){
350
            tbl.style.filter = "blur(1px)";
351
            tbl.style.opacity = "0.8";
352
            tbl.style.cursor = "wait";
353
        }else{
354
            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...
355
        }
356
    };
357
358
    this.getParent = function(obj, objType){
359
        while(obj && obj.tagName !== objType.toUpperCase()){
360
            obj = obj.parentNode;
361
        }
362
        return obj;
363
    };
364
365
    this.init = function(tableId){
366
        this.SetTheTableColumnsHoverEffect(tableId);
367
    };
368
369
    this.iePrior = function(v){
370
        var rv = false;
371
        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...
372
            var ua = navigator.userAgent;
373
            var re = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})");
374
            if(re.exec(ua) !== null){
375
                rv = parseFloat(RegExp.$1);
376
            }
377
            rv = rv < v ? true : false;
378
        }
379
        return rv;
380
    };
381
    this.loadJS = function(src){
382
        var s = document.createElement('script');
383
        s.src = src;
384
        document.getElementsByTagName('head')[0].appendChild(s);
385
    };
386
    this.loadCSS = function(src){
387
        var s = document.createElement('link');
388
        s.href = src;
389
        s.rel = "stylesheet";
390
        document.getElementsByTagName('head')[0].appendChild(s);
391
    };
392
393
    this.LoadEndCalback = function(tableId){
394
        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...
395
        }
396
    };
397
    this.AppendRowCalback = function(tableId){
398
        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...
399
        }
400
    };
401
};
402
403
/** Moves custom created filter to the Table's filter
404
 * @param {string} filterId
405
 * @param {string} tableId
406
 * @param {boolean} delay - needed in case the table is istill not executed */
407
function moveSelectorToTheTableFilter(filterId, tableId, delay){
408
    if(delay === true){
409
        setTimeout(function(){
410
            var filterDiv = document.getElementById(tableId)
411
                    .getElementsByTagName("div")[0];
412
            filterDiv.appendChild(document.getElementById(filterId));
413
        }, 500);
414
    }else{
415
        var filterDiv = document.getElementById(tableId)
416
                .getElementsByTagName("div")[0];
417
        filterDiv.appendChild(document.getElementById(filterId));
418
    }
419
}
420
421
function changeListCustomFilter(selectObj){
422
    var name = selectObj.getAttribute("name");
423
424
    var inUrlPos = document.URL.indexOf(name);
425
    var url = inUrlPos !== -1 ?
426
            document.URL.substring(0, (inUrlPos - 1)) :
427
            document.URL;
428
429
    var value = selectObj.options[selectObj.selectedIndex].value;
430
    if(value !== "{!--Empty--!}"){
431
        var clue = document.URL.indexOf("?") > 0 ? "&" : "?";
432
        url += (clue + name + "=" + value);
433
    }
434
435
    location.assign(url);
436
}
437
438
439
function tablesLoadData(){
440
    var tables = document.getElementsByTagName("table");
441
    var envPrior9 = table.iePrior(9);
442
    for(var i = 0; i < tables.length; i++){
443
        var isProcessable = envPrior9 ?
444
                typeof tables[i]["data-table"] !== 'undefined' :
445
                tables[i].hasAttribute("data-table");
446
        if(isProcessable && tables[i].getAttribute("data-table") === "js"){
447
            table.LoadData(tables[i].id);
448
            table.SetTheTableColumnsHoverEffect(tables[i].id);
449
        }
450
    }
451
    /*if(table.iePrior(10)){
452
     table.loadJS("/add/helpers/table/add/json2.js");
453
     }
454
     
455
     if(table.iePrior(8)){ //can be used to add apropriate tables links modifications
456
     // loadCSS("/add/helpers/table/add/ie7-and-down.css");
457
     }*/
458
}
459
460
/*if(window.addEventListener){window.addEventListener('load',tablesLoadData,false);} else if(window.attachEvent){window.attachEvent('onload',tablesLoadData);}*/