Passed
Branchmaster (43aff3)
by Plamen
01:32
created

table.js ➔ ... ➔ sortBySpan   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 8
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 6
c 1
b 0
f 0
nc 3
nop 2
dl 0
loc 8
rs 10
1
var TableRequestSort = function(rq, strDesc){
2
    function sortBySpan(span, i){
3
        var order = span.innerHTML;
4
        if(order.length === 1){
5
            rq.colNo = i;
6
            rq.colOrd = order === strDesc ? "desc" : "asc";
7
        }
8
        return rq.colNo === i;
9
    }
10
    
11
    var thTags = document.getElementById(rq.tableId)
12
            .getElementsByTagName("thead")[0]
13
            .getElementsByTagName("th");
14
    var length = thTags.length;
15
    for(var i = 0; i < length; i++){
16
        var link = thTags[i].getElementsByTagName("a")[0];
17
        if(link){
18
            var span = link.getElementsByTagName("span")[0];
19
            if(span && sortBySpan(span, i)){
20
                break;
21
            }
22
        }
23
    }
24
};
25
var TableRequestFilter = function(rq){
26
    function getFilterFieldsByTableID(tableID){
27
        var fields = {filterBy: null, filter: null};
28
        var filterDiv = getFilterDivByTableIDOrNull(tableID);
29
        if(filterDiv !== null){
30
            setFilterBy(fields, filterDiv);
31
            setFilterValue(fields, filterDiv);
32
        }
33
        return fields;
34
    }
35
    function getFilterDivByTableIDOrNull(tableID){
36
        var res = null;
37
        if(document.getElementById(tableID).parentNode.getElementsByTagName("div").length > 0){
38
            for(var i = 0; i < document.getElementById(tableID).parentNode.getElementsByTagName("div").length; i++){
39
                if(document.getElementById(tableID).parentNode.getElementsByTagName("div")[i].getAttribute("class") === "filter"){
40
                    return document.getElementById(tableID).parentNode.getElementsByTagName("div")[i];
41
                }
42
            }
43
44
        }
45
        return res;
46
    }
47
    function setFilterBy(fields, filterDiv){
48
        var slctObj = filterDiv.getElementsByTagName("select")[0];
49
        if(slctObj && slctObj.options[slctObj.selectedIndex].value !== "all"){
50
            fields.filterBy = slctObj.options[slctObj.selectedIndex].value;
51
        }
52
    }
53
    function setFilterValue(fields, filterDiv){
54
        var textObj = filterDiv.getElementsByTagName("input")[0];
55
        if(textObj && textObj.value && textObj.value.length !== 0){
56
            fields.filter = encodeURIComponent(textObj.value.trim());
57
        }
58
    }
59
60
    var r = getFilterFieldsByTableID(rq.tableId);
61
    if(r.filter !== null){
62
        rq.filter = r.filter;
63
    }
64
    if(r.filterBy !== null){
65
        rq.filterBy = r.filterBy;
66
    }
67
};
68
//https://addyosmani.com/resources/essentialjsdesignpatterns/book/#singletonpatternjavascript
69
var TableSingleton = (function(){
70
    // Instance stores a reference to the Singleton
71
    var instance;
72
    function initInstance(){
73
        // Singleton
74
        // Private methods and variables
75
        function BuildRequest(rq, crntTableId){
76
            rq.tableId = crntTableId;
77
            TableRequestSort(rq, instance.strDesc);
78
            TableRequestFilter(rq, crntTableId);
0 ignored issues
show
Bug introduced by
The call to TableRequestFilter seems to have too many arguments starting with crntTableId.
Loading history...
79
        }
80
        function getParent(obj, objType){
81
            while(obj && obj.tagName !== objType.toUpperCase()){
82
                obj = obj.parentNode;
83
            }
84
            return obj;
85
        }
86
        function FilterGetTableId(field){
87
            if(field.tagName.toLowerCase() !== "select"){
88
                return field.getAttribute("data-table-id");
89
            }
90
            var f = field.parentNode.parentNode.getElementsByTagName("input")[0];
91
            return '' === f.value ? null : f.getAttribute("data-table-id");
92
        }
93
        var tail = [];
94
        function LoadData(tableContainer, rq){
95
            instance.setVisability(tableContainer, false);
96
            if(window.XMLHttpRequest){
97
                var xmlhttp = new XMLHttpRequest();/* code for IE7+, Firefox, Chrome, Opera, Safari */
98
            }else{ 
99
                xmlhttp = new window.ActiveXObject("Microsoft.XMLHTTP");/*code for IE6, IE5 */
100
            }
101
            for(var i = 0; i < tail.length; i++){
102
                var ex_xmlhttp = tail.shift();
103
                ex_xmlhttp.abort();
104
            }
105
            xmlhttp.onreadystatechange = function(){
106
                if(xmlhttp.readyState === 4 && xmlhttp.status === 200){
107
                    var d = JSON.parse(xmlhttp.responseText);
108
                    table.DrawSection(tableContainer, d.body);
109
                    table.DrawSection(tableContainer, d.footer, "tfoot");
110
                    table.LoadEndCalback(tableContainer);
111
                    table.setVisability(tableContainer, true);
112
                    if(typeof rq === "object"){
113
                        var hover = document.getElementById(rq.tableId)
114
                                    .getElementsByTagName("th")[rq.colNo].lang;
115
                        if(hover){
116
                            table.ColumnHover(tableContainer, rq.colNo);
117
                        }
118
                    }
119
                }
120
            };
121
            xmlhttp.open("GET", RequestToUrl(rq), true);
122
            xmlhttp.send();
123
            tail.push(xmlhttp); //put at tail to can abort later any previous
124
        }
125
        function RequestToUrl(rq){
126
            var url = location.pathname + ".json" + location.search;
127
            if(typeof rq === "object"){
128
                var getUrlVarName = {
129
                    colNo: "col", colOrd: "ord", filter: "filter",
130
                    filterBy: "filter-by", pageNo: "pg", exportType: "export",
131
                    tableId: "table-id"
132
                };
133
                var flagFirst = location.search.length < 1 ? true : false;
134
                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...
135
                    var clue = flagFirst === true ? "?" : "&";
136
                    url += clue + getUrlVarName[r] + "=" + rq[r];
137
                    flagFirst = false;
138
                }
139
            }
140
            return url;
141
        }
142
        function columnHoverRelease(rows, upto){
143
            for(var i = 0; i < upto; i++){
144
                for(var j = 0; j < rows[i].cells.length; j++){
145
                    if(rows[i].cells[j].lang){
146
                        rows[i].cells[j].removeAttribute("lang");
147
                    }
148
                }
149
            }
150
        }
151
        function clearSection(tSection){
152
            if(iePrior(9)){
153
                if(tSection.firstChild){
154
                    while(tSection.firstChild){
155
                        tSection.removeChild(tSection.firstChild);
156
                    }
157
                }
158
            }else{
159
                tSection.innerHTML = "";
160
            }
161
        }
162
        function iePrior(v){
163
            var rv = false;
164
            if(window.navigator.appName === 'Microsoft Internet Explorer'){
165
                var ua = window.navigator.userAgent;
166
                var re = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})");
167
                if(re.exec(ua) !== null){
168
                    rv = parseFloat(RegExp.$1);
169
                }
170
                rv = rv < v ? true : false;
171
            }
172
            return rv;
173
        }
174
        function setPagingLinksSetActions(tContainer){
175
            var pLinks = tContainer.querySelectorAll("tfoot .paging a");
176
            if(pLinks.length > 0){
177
                for(var j = 0; j < pLinks.length; j++){
178
                    pLinks[j].setAttribute("href", "javascript:void(0);");
179
                    pLinks[j].setAttribute("onclick", "return table.GoPage(this);");
180
                }
181
            }
182
        }
183
        function footerProcessPaginationLinks(tSection){
184
            var pLinks = tSection.querySelectorAll(".paging a");
185
            if(pLinks.length > 0){
186
                for(var j = 0; j < pLinks.length; j++){
187
                    pLinks[j].setAttribute("href", "javascript:void(0);");
188
                    pLinks[j].setAttribute("onclick", "return table.GoPage(this);");
189
                }
190
            }
191
        }
192
        function SetTheTableColumnsHoverEffect(tableContainer){
193
            if(iePrior(9)){
194
                return;
195
            }
196
            var tContainer = document.getElementById(tableContainer);
197
            var tHcells = tContainer.rows[0].cells;
198
            for(var i = 0; i < tHcells.length; i++){
199
                if(tHcells[i].firstChild.tagName === "A"){
200
                    tHcells[i].firstChild.setAttribute("onmouseover", "table.ColumnHover('" + tableContainer + "'," + i + ");");
201
                    tHcells[i].firstChild.setAttribute("onmouseout", "table.ColumnHover('" + tableContainer + "');");
202
                }
203
            }
204
            setPagingLinksSetActions(tContainer);
205
        }
206
        
207
        return {
208
            rq: null,
209
            strAsc: String.fromCharCode(9650), //&#9650;
210
            strDesc: String.fromCharCode(9660),//&#9660; 
211
            ReloadData: function(tableId){
212
                var request = {};
213
                BuildRequest(request, tableId);
214
                LoadData(tableId, request);
215
            },
216
            Filter: function(field){
217
                var crntTableId = FilterGetTableId(field);
218
                if(crntTableId !== null){
219
                    var request = {};
220
                    var exRq = this.rq;
221
                    BuildRequest(request, crntTableId);
222
                    if(exRq === null ||
223
                        request.filter !== exRq.filter ||
224
                        request.filterBy !== exRq.filterBy
225
                    ){
226
                        LoadData(crntTableId, request);
227
                    }
228
                }
229
            },
230
            GoPage: function(lnk){
231
                var request = {};
232
                var table = getParent(lnk, "table");
233
                var crntTableId = table.getAttribute("id");
234
                BuildRequest(request, crntTableId);
235
                //check & serve pagination jump links
236
                var jumpDir = lnk.innerHTML.trim().substr(0, 1);
237
                if(jumpDir === "+" || jumpDir === "-"){
238
                    var current = table.querySelector("tfoot .paging .a").innerHTML;
239
                    var jump = lnk.innerHTML.replace("K", "000").replace("M", "000000000");
240
                    var jumpPage = (parseInt(current) + parseInt(jump));
241
                    lnk.parentNode.setAttribute("data-page", jumpPage);
242
                    lnk.style.transform = "none";
243
                }
244
                request.pageNo = lnk.parentNode.hasAttribute("data-page") ?
245
                                    lnk.parentNode.getAttribute("data-page") :
246
                                    lnk.innerHTML;
247
                LoadData(crntTableId, request);
248
                return false;
249
            },
250
            Export: function(lnk, eType){
251
                var request = {};
252
                var crntTableId = getParent(lnk, "table").getAttribute("id");
253
                BuildRequest(request, crntTableId);
254
                request.exportType = ["CSV", "Excel"].indexOf(eType) >= 0 ?
255
                                        eType : 
256
                                        "csv";
257
                window.open(RequestToUrl(request));
258
                return false;
259
            },
260
            Sort: function(colNo, lnk){
261
                var request = {};
262
                var crntTableId = getParent(lnk, "table").getAttribute("id");
263
                BuildRequest(request, crntTableId);
264
                if(Math.round(colNo) === request.colNo){
265
                    request.colOrd = (request.colOrd === "asc" ? "desc" : "asc");
266
                }else{
267
                    request.colNo = Math.round(colNo);
268
                    request.colOrd = "asc";
269
                }
270
                LoadData(crntTableId, request);
271
                /* Clear and add new sort arrow */
272
                var headSpans = getParent(lnk, "thead").getElementsByTagName("span");
273
                var length = headSpans.length;
274
                for(var i = 0; i < length; i++){
275
                    headSpans[i].innerHTML = "";
276
                }
277
                lnk.getElementsByTagName("span")[0].innerHTML = (request.colOrd === "desc" ? this.strDesc : this.strAsc);
278
            },
279
            DrawSection: function(tableContainer, dt, tSection){
280
                var section = tSection === "tfoot" ? "tfoot" : "tbody";
281
                tSection = document.getElementById(tableContainer).
282
                            getElementsByTagName(section)[0];
283
                clearSection(tSection);
284
                for(var i = 0; i < dt.length; i++){
285
                    var row = dt[i];
286
                    var tRow = document.createElement("tr");
287
288
                    this.DrawRow(row, tRow);
289
290
                    tSection.appendChild(tRow);
291
                    if(section === "tfoot"){
292
                        footerProcessPaginationLinks(tSection);
293
                    }
294
                    this.AppendRowCalback(tableContainer);
295
                }
296
            },
297
            DrawRow: function(row, tRow){
298
                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...
299
                    var tCell = document.createElement("td");
300
                    if(typeof row[cell] === "string" || typeof row[cell] === "number"){
301
                        tCell.innerHTML = row[cell];
302
                    }else if(typeof row[cell] === "object"){
303
                        this.DrawCellFromObject(row, cell, tCell);
304
                    }
305
                    tRow.appendChild(tCell);
306
                }
307
            },
308
            DrawCellFromObject: function(row, cell, tCell){
309
                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...
310
                    if(typeof row[cell][attr] === "string"){
311
                        tCell.innerHTML = row[cell][attr];
312
                    }else if(typeof row[cell][attr] === "object"){
313
                        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...
314
                            tCell.setAttribute(v, row[cell][attr][v]);
315
                        }
316
                    }
317
                }
318
            },
319
            ColumnHover: function(tableContainer, index){
320
                if(!iePrior(9)){
321
                    var rows = document.getElementById(tableContainer).rows;
322
                    var upto = rows.length - 1;
323
                    if(typeof index === "undefined"){
324
                        columnHoverRelease(rows, upto);
325
                    } else {
326
                        for(var i = 0; i < upto; i++){
327
                            rows[i].cells[index].setAttribute("lang", "col-hover");
328
                        }
329
                    }
330
                }
331
            },
332
            setVisability: function(tableContainer, rq){
333
                var tbl = document.getElementById(tableContainer);
334
                if(rq === true){
335
                    tbl.style.filter = "none";
336
                    tbl.style.opacity = "1";
337
                    tbl.style.cursor = "auto";
338
                }else if(rq === false){
339
                    tbl.style.filter = "blur(1px)";
340
                    tbl.style.opacity = "0.8";
341
                    tbl.style.cursor = "wait";
342
                }else{
343
                    console.error("table error in the rq value");
344
                }
345
            },
346
            init: function(tableId){
347
                SetTheTableColumnsHoverEffect(tableId);
348
            },
349
            LoadEndCalback: function(){},/*Allows override: function(tableId){if(tableId){...}}*/
350
            AppendRowCalback:  function(){}/*Allows override: function(tableId){if(tableId){...}}*/
351
        };
352
    }
353
    return {
354
        //Get the Singleton instance if one exists, or create one if it doesn't
355
        getInstance: function(){
356
            if(!instance){
357
                instance = initInstance();
358
            }
359
            return instance;
360
        }
361
    };
362
})();
363
var table = TableSingleton.getInstance();
364