Passed
Push — master ( bbb3b3...d3127e )
by Plamen
01:36
created

table.js ➔ ... ➔ Init   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

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