Passed
Branchmaster (0bd49f)
by Plamen
01:29
created

table.js ➔ ... ➔ this.setSortByFirstLinkFirstSpan   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 9
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 7
c 1
b 0
f 0
nc 3
nop 2
dl 0
loc 9
rs 10
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.getFilterFieldsByTbaleID(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.getFilterFieldsByTbaleID = function(tableID){
280
        var fields = {filterBy: null, filter: null};
281
        var filterDiv = this.getFilterDivByTableIDOrNull(tableID);
282
        if(filterDiv !== null){
283
            var slctObj = filterDiv.getElementsByTagName("select")[0];
284
            var textObj = filterDiv.getElementsByTagName("input")[0];
285
            if(slctObj && slctObj.options[slctObj.selectedIndex].value !== "all"){
286
                fields.filterBy = slctObj.options[slctObj.selectedIndex].value;
287
            }
288
            if(textObj && textObj.value.length !== 0){
289
                fields.filter = encodeURIComponent(textObj.value.trim());
290
            }
291
        }
292
        return fields;
293
    };
294
295
    this.getFilterDivByTableIDOrNull = function(tableID){
296
        var res = null;
297
        if(document.getElementById(tableID).parentNode.getElementsByTagName("div").length > 0){
298
            for(var i = 0; i < document.getElementById(tableID).parentNode.getElementsByTagName("div").length; i++){
299
                if(document.getElementById(tableID).parentNode.getElementsByTagName("div")[i].getAttribute("class") === "filter"){
300
                    return document.getElementById(tableID).parentNode.getElementsByTagName("div")[i];
301
                }
302
            }
303
304
        }
305
        return res;
306
    };
307
308
    this.LoadData = function(tableContainer, rq){
309
        this.setVisability(tableContainer, false);
310
        if(window.XMLHttpRequest){
311
            xmlhttp = new XMLHttpRequest();/* code for IE7+, Firefox, Chrome, Opera, Safari */
312
        }else{ /** global: ActiveXObject */
313
            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...
314
        }
315
        for(var i = 0; i < this.tail.length; i++){
316
            var ex_xmlhttp = this.tail.shift();
317
            ex_xmlhttp.abort();
318
        }
319
        xmlhttp.onreadystatechange = function(){
320
            if(xmlhttp.readyState === 4 && xmlhttp.status === 200){
321
                d = JSON.parse(xmlhttp.responseText);
322
                table.DrawSection(tableContainer, d.body);
323
                table.DrawSection(tableContainer, d.footer, "tfoot");
324
                table.LoadEndCalback(tableContainer);
325
                table.setVisability(tableContainer, true);
326
                if(typeof rq === "object"){
327
                    var hover = document.getElementById(rq.tableId)
328
                                .getElementsByTagName("th")[rq.colNo].lang;
329
                    if(hover){
330
                        table.ColumnHover(tableContainer, rq.colNo);
331
                    }
332
                }
333
            }
334
        };
335
        xmlhttp.open("GET", this.RequestToUrl(rq), true);
336
        xmlhttp.send();
337
        this.tail.push(xmlhttp); //put in tail to may later abort any previous
338
    };
339
340
    this.setVisability = function(tableContainer, rq){
341
        var tbl = document.getElementById(tableContainer);
342
        if(rq === true){
343
            tbl.style.filter = "none";
344
            tbl.style.opacity = "1";
345
            tbl.style.cursor = "auto";
346
        }else if(rq === false){
347
            tbl.style.filter = "blur(1px)";
348
            tbl.style.opacity = "0.8";
349
            tbl.style.cursor = "wait";
350
        }else{
351
            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...
352
        }
353
    };
354
355
    this.getParent = function(obj, objType){
356
        while(obj && obj.tagName !== objType.toUpperCase()){
357
            obj = obj.parentNode;
358
        }
359
        return obj;
360
    };
361
362
    this.init = function(tableId){
363
        this.SetTheTableColumnsHoverEffect(tableId);
364
    };
365
366
    this.iePrior = function(v){
367
        var rv = false;
368
        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...
369
            var ua = navigator.userAgent;
370
            var re = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})");
371
            if(re.exec(ua) !== null){
372
                rv = parseFloat(RegExp.$1);
373
            }
374
            rv = rv < v ? true : false;
375
        }
376
        return rv;
377
    };
378
    this.loadJS = function(src){
379
        var s = document.createElement('script');
380
        s.src = src;
381
        document.getElementsByTagName('head')[0].appendChild(s);
382
    };
383
    this.loadCSS = function(src){
384
        var s = document.createElement('link');
385
        s.href = src;
386
        s.rel = "stylesheet";
387
        document.getElementsByTagName('head')[0].appendChild(s);
388
    };
389
390
    this.LoadEndCalback = function(tableId){
391
        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...
392
        }
393
    };
394
    this.AppendRowCalback = function(tableId){
395
        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...
396
        }
397
    };
398
};
399
400
/** Moves custom created filter to the Table's filter
401
 * @param {string} filterId
402
 * @param {string} tableId
403
 * @param {boolean} delay - needed in case the table is istill not executed */
404
function moveSelectorToTheTableFilter(filterId, tableId, delay){
405
    if(delay === true){
406
        setTimeout(function(){
407
            var filterDiv = document.getElementById(tableId)
408
                    .getElementsByTagName("div")[0];
409
            filterDiv.appendChild(document.getElementById(filterId));
410
        }, 500);
411
    }else{
412
        var filterDiv = document.getElementById(tableId)
413
                .getElementsByTagName("div")[0];
414
        filterDiv.appendChild(document.getElementById(filterId));
415
    }
416
}
417
418
function changeListCustomFilter(selectObj){
419
    var name = selectObj.getAttribute("name");
420
421
    var inUrlPos = document.URL.indexOf(name);
422
    var url = inUrlPos !== -1 ?
423
            document.URL.substring(0, (inUrlPos - 1)) :
424
            document.URL;
425
426
    var value = selectObj.options[selectObj.selectedIndex].value;
427
    if(value !== "{!--Empty--!}"){
428
        var clue = document.URL.indexOf("?") > 0 ? "&" : "?";
429
        url += (clue + name + "=" + value);
430
    }
431
432
    location.assign(url);
433
}
434
435
436
function tablesLoadData(){
437
    var tables = document.getElementsByTagName("table");
438
    var envPrior9 = table.iePrior(9);
439
    for(var i = 0; i < tables.length; i++){
440
        var isProcessable = envPrior9 ?
441
                typeof tables[i]["data-table"] !== 'undefined' :
442
                tables[i].hasAttribute("data-table");
443
        if(isProcessable && tables[i].getAttribute("data-table") === "js"){
444
            table.LoadData(tables[i].id);
445
            table.SetTheTableColumnsHoverEffect(tables[i].id);
446
        }
447
    }
448
    /*if(table.iePrior(10)){
449
     table.loadJS("/add/helpers/table/add/json2.js");
450
     }
451
     
452
     if(table.iePrior(8)){ //can be used to add apropriate tables links modifications
453
     // loadCSS("/add/helpers/table/add/ie7-and-down.css");
454
     }*/
455
}
456
457
/*if(window.addEventListener){window.addEventListener('load',tablesLoadData,false);} else if(window.attachEvent){window.attachEvent('onload',tablesLoadData);}*/