Passed
Branchmaster (b15fac)
by Plamen
01:32
created

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