﻿// Data Grid Juqery Widget
(function($, undefined) {
    $.widget("ui.datagrid", {
        sort: '',
        sortDir: '',
        page: '',
        pageSize: '',
        search:'',
        searchBox: '',
        reloadUrl: '',
        optional:null,
        headers:null,
        cols:null,
        colNames:null,
        postEvents:null,
        txt: {},
        searchField:'',
        btnSearch:'',
        btnSearchClear:'',
        // IDs & Classes
        _classSort: 'sort',
        _classWrap: 'wrap',
        _classSearch: 'search',
        _classHighlight: 'hl',
        _idDataGrid : 'dgTable',
        _idPaging: 'paging',
        _idPagingDiv: 'divPaging',
        _idRowsPerPage: 'rpp',
        _idRowsPerPageDiv: 'divRPP',
        _idTBData: 'tbData',
        // Resizing
        resize: true,
        mouseDown: false,
        start: undefined,
        cellIndex: null,
        startW: 0,
        cellW: 0,
        _create: function() {
            this.reloadUrl = this.options.reloadUrl;
            this.searchBox = $(this.options.searchBox);
            this.btnSearch = $(this.options.btnSearch);
            this.btnSearchClear = $(this.options.btnSearchClear);
            this.sort = $(this.options.sort);
            this.sortDir = $(this.options.sortDir);
            this.page = $(this.options.page);
            this.pageSize = $(this.options.pageSize);
            this.optional = this.options.optional;
            this.postEvents = this.options.postEvents;
            this.txt = this.options.txt;
            
            this.headers = this.options.headers;
            this.cols = this.options.cols;
            this.resize = this.options.resize==undefined ? true : this.options.resize;
            this.txt = this.options.txt;
            this.headers = this.options.headers;
            this.cols = this.options.cols;

            this.initBind();
            // Show down/up arrow for the default
            $(this.element.get(0)).html(this.initTable());
            this.reload(true);
            $(this.element.get(0)).find('#' + this.sort.val()).addClass(this.sortDir.val());
        },
        initBind: function() {
            var that = this;
            var txt = that.txt;

            // Events that happen outside of this grid
            this.btnSearch.click(function () {
                that.search();
            });
            this.btnSearchClear.click(function () {
                that.searchBox.val(txt['SearchField']).click(function() { 
                    $(this).val('').unbind('click'); 
                });
                that.reload(true);
            });
            this.searchBox.keyup(function (e) {
                if (e.keyCode == 13) {
                    that.search();
                }
            }).val(txt['SearchField']).click(function() { 
                $(this).val('').unbind('click'); 
            });

            // Events that happen inside of this grid
            var grid = $(this.element.get(0));
            grid.find('#' + this._idPaging).live('change', function() {
                $(that.page).val($(this).val());
                that.reload(false);
            });
            grid.find('#' + this._idRowsPerPage).live('change', function() {
                $(that.pageSize).val($(this).val());
                that.reload(true);
            });
            grid.find('.' + this._classSort).live('click', function() {
                var sortColumn = $(this).attr('id');
                that.setSortDir(sortColumn);
                that.sort.val(sortColumn);
                that.reload(true);
            });
            grid.find('td').live('mouseover mouseout', function(event) {
                if (event.type == 'mouseover') {
                    $(this).parent('tr').css('background-color','#F9F9F9');
                } else {
                    $(this).parent('tr').css('background-color','');
                }             
            });
        },
        initTable: function() {
            var ID = 0;
            var HEADER_TEXT = 1;
            var SORTABLE = 2;
            var tbl = "<table id='" + this._idDataGrid + "' border='0' cellpadding='0' cellspacing='0'>";
            tbl += "<thead><tr>";
            for(var i = 0; i < this.headers.length; i++) {
                if (this.headers[i].length > 1) {
                    if (this.headers[i][SORTABLE]) {
                        tbl += String.format("<th><a id='{0}' class='{1}'>{2}</a></th>", this.headers[i][ID], this._classSort, this.headers[i][HEADER_TEXT]);
                    } else {
                        tbl += String.format("<th><a id='{0}'>{1}</a></th>", this.headers[i][ID], this.headers[i][HEADER_TEXT]);
                    }
                } else {
                    tbl += String.format("<th>{0}</th>", this.headers[i][ID]);
                }
            }
            tbl += "</tr></thead><tbody id='" + this._idTBData + "'><tr><td colspan='" + this.headers.length + "'>" + this.txt['Loading'] + "</td></tr></tbody>";
            tbl += "</table>";
            return tbl;
        },
        jsonToRows: function(json) {
            //Patterns for table thead & tbody
            var rows = '';
            var tr = "<tr>{0}</tr>";
            var td = "<td>{0}</td>";
            var DB_COLUMN_NAME = 0;
            var SEARCHED = 0;
            var DEFAULT_WIDTH = 1;
            var MAX_WIDTH = 2;
            if (json) {
                if (json.colNames && json.data.length > 0) {
                    for (var i = 0; i < json.data.length; i++) {
                        var tbC = '';
                        for(var j = 0; j < this.cols.length; j++) {
                            if (typeof this.cols[j] === 'string'){ 
                                // This column is a customer cell.
                                tbC += String.format(td, window[this.cols[j]](json.colNames, json.data[i]));
                            } else {
                                var colData = json.data[i][json.colNames[this.headers[j][DB_COLUMN_NAME]]];
                                if ($.trim(colData)=='') {
                                    colData = "—";
                                }
                                
                                var c = (this.cols[j][SEARCHED]) ? this._classSearch : '';
                                var w = this.cols[j][DEFAULT_WIDTH];
                                if (c.length > 0 || w > 0) {
                                    var p = '';
                                    if (c.length > 0) {
                                        p = '<p class="' + c + '"';
                                    } else {
                                        p = '<p';
                                    }
                                    if (w > 0) {
                                        p += ' style="width:' + w + 'px; max-width:' + this.cols[j][MAX_WIDTH] + 'px;"';
                                    }
                                    p += '>';
                                    tbC += String.format(td, p + Common.HtmlEncode(colData) + '</p>');
                                } else {
                                    tbC += String.format(td, Common.HtmlEncode(colData));
                                }
                            }
                        }
                        rows += String.format(tr, tbC);
                    }
                } else {
                    rows += String.format(tr, "<td colspan='" + this.headers.length + "'>" + this.txt['NoData'] + "</td>");
                }
                this.paging(json.noRows);
            }
            return rows;
        },
        paging: function(totalRows) {
            var that = this;
            var pageSize = this.pageSize.val();
            var currentPage = this.page.val();
            var grid = $(this.element.get(0));

            grid.find('#' + this._idPagingDiv).remove();
            grid.find('#' + this._idRowsPerPageDiv).remove();

            if (totalRows && totalRows > 0) {
                var rowsPP = "<select id=\"" + this._idRowsPerPage + "\">";
                for (var i = 1; i <= 10; i++) {
                    if (i*10 == pageSize) {
                        rowsPP += String.format("<option value=\"{0}\" selected>{0}</option>", i*10);
                    } else {
                        rowsPP += String.format("<option value=\"{0}\">{0}</option>", i*10);
                    }
                }
                rowsPP += "</select>";
                rowsPP = "<div id=\"" + this._idRowsPerPageDiv + "\">" + String.format(this.txt['RowsFound'] + ' ', totalRows) + String.format(this.txt['ItemsPerPage'], rowsPP) + "</div>";
                grid.append(rowsPP);
                
                // Create paging code
	            var totPages = Math.ceil(totalRows / pageSize);
	            if (totPages > 1) {
	                var pager = '<div id="' + this._idPagingDiv + '"><a id="m_left"></a><div id="o_left"></div><div class="paginator_p_wrap"><div class="paginator_p_bloc"></div></div><div id="o_right"></div><a id="m_right"></a><div class="paginator_slider" class="ui-slider ui-slider-horizontal ui-widget ui-widget-content ui-corner-all"><a class="ui-slider-handle ui-state-default ui-corner-all" href="#"></a></div></div>'
                    grid.append(pager);
                    $("#" + this._idPagingDiv).jPaginator({ 
                        nbPages:totPages, 
                        selectedPage:currentPage,
                        overBtnLeft:'#o_left', 
                        overBtnRight:'#o_right', 
                        maxBtnLeft:'#m_left', 
                        maxBtnRight:'#m_right',
                        minSlidesForSlider:2, 
                        onPageClicked: function(a,num) { 
                            $(that.page).val(num);
                            that.reload(false);
                        }
                    });
	            }
            } else {
                grid.find('#' + this._idRowsPerPageDiv).remove();
                grid.find('#' + this._idPagingDiv).remove();
            }
        },
        reload: function(reset) {
            var that = this;
            var grid = $(this.element.get(0));
            if (reset) {
                that.page.val('1');     
            }
			var queryStr;
			if (that.reloadUrl.indexOf('.php') > -1) {
				// Build query string for PHP
				queryStr = '&search=' + that.getSearchTxt() + '&sort=' + that.sort.val() + '&sortDir=' + that.sortDir.val() + '&page=' + that.page.val() + '&pageSize=' + that.pageSize.val();
				if (that.optional) {
					for (var i = 0; i < that.optional.length; i++) {
						queryStr += "&" + that.optional[i][0] + "=" + $(that.optional[i][1]).val();
					}
				}
			} else {
				// Build query string for .Net
				queryStr = "{'search':'" + that.getSearchTxt() + "','sort':'" + that.sort.val() + "','sortDir':'" + that.sortDir.val() + "','page':" + that.page.val() + ",'pageSize':" + that.pageSize.val();
				// Append the query string with optional parameters
				if (that.optional) {
					for (var i = 0; i < that.optional.length; i++) {
						queryStr += ",'" + that.optional[i][0] + "':'" + $(that.optional[i][1]).val() + "'";
					}
				}
				queryStr += "}";
			}

            Common.showNotify(that.txt['Loading']);
            grid.fadeTo('fast',.5);

			// Depending on how this's used(aspx and php are supported), use a different source.
			if (that.reloadUrl.indexOf('.php') > -1) {
				if (window.XMLHttpRequest) {
					// code for IE7+, Firefox, Chrome, Opera, Safari
					xmlhttp = new XMLHttpRequest();
				} else {
					// code for IE6, IE5
					xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
				}
				xmlhttp.onreadystatechange = function() {
					if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
						var JSONobject = JSON.parse(xmlhttp.responseText);
						that.renderOutput(JSONobject);
					}
				}
				xmlhttp.open("GET", that.reloadUrl + queryStr, true);
				xmlhttp.send();
			} else if (that.reloadUrl.indexOf('.aspx') > -1) {
				$.ajax({
					type: "POST",
					url: that.reloadUrl,
					cache: false,
					data: queryStr,
					contentType: "application/json; charset=utf-8",
					dataType: "json",
					success: function(msg) {
						if (msg.d == false) {
							alert(that.txt['UnknownErr']);
						} else {
							that.renderOutput(msg.d);
						}
						grid.fadeTo('fast',1);
						Common.hideNotify();
					}
				});
			}
        },
		renderOutput: function(resp) {
            var that = this;
			var grid = $(this.element.get(0));
			grid.find('#' + that._idTBData).html(that.jsonToRows(resp));
			grid.find('.' + that._classSort).removeClass('asc').removeClass('desc');
			grid.find('#' + that.sort.val()).addClass(that.sortDir.val());
			if (that.postEvents) {
			   for(var i = 0; i < that.postEvents.length; i++) {
					window[that.postEvents[i]]();
				}
			}

			// Run post events [optional]
			if (that.postEvents) {
			   for(var i = 0; i < that.postEvents.length; i++) {
					window[that.postEvents[i]]();
				}
			}

			// Add resize event
			if (that.resize) {
				grid.find('th').mousedown(function(e) {
					$(this).css('cursor','col-resize');
					that.start = $(this);
					if (that.cellIndex == null) {
						that.cellIndex = e.target.cellIndex;
					} else {
						if (that.cellIndex != e.target.cellIndex) {
							var s = '';
						}
					}
					that.mouseDown = true;
					that.startW = e.pageX;
					that.cellW = $(this).width();
				}).mousemove(function(e) {
					if (that.mouseDown) {
						var newW = that.cellW + (e.pageX - that.startW);
						var tdP = grid.find('tr').find('>:eq('+e.target.cellIndex+')>p');

						var maxW = tdP.css('max-width');
						if (maxW) {
							maxW = parseInt(tdP.css('max-width').slice(0, -2));
							if (newW > maxW) {
								newW = maxW;
							}
						} 
						tdP.css('width', newW + 'px').gridEllipsis();
						if (tdP.hasClass(that._classSearch) && that.getSearchTxt() != '') {
							that.highlightSearchedTxt(tdP);
						}
						$(that.start).width(newW);
					}
				}).mouseup(function() {
					that.mouseDown = false;
				}).mouseover(function(e) {
					if (that.cellIndex != null && that.cellIndex != e.target.cellIndex) {
						that.mouseDown = false;
					}
				});
				grid.find('td p').gridEllipsis();
			}
			that.highlightSearchedTxt('');
			grid.fadeTo('fast',1);
			Common.hideNotify();
		},
		getSearchTxt: function() {
            return (this.searchBox.val() == this.txt['SearchField']) || (this.searchBox.val() == '') ? '' : escape(this.searchBox.val());
        },
        search: function() {
			if (this.getSearchTxt() == '') {
                alert(this.txt['EnterTxt']);
                this.searchBox.val(this.txt['SearchField']).click(function() { 
                    $(this).val('').unbind('click'); 
                });
            } else {
                this.reload(true);
            }
            return false;
        },
        setSortDir: function(column) {
            if (this.sort.val() == column) {
                if (this.sortDir.val() == 'desc') {
                    this.sortDir.val('asc');
                } else {
                   this.sortDir.val('desc');
                }
            } else {
                this.sortDir.val('desc');
            }
        },
        highlightSearchedTxt: function(obj) {
			var searchTxt = this.getSearchTxt();
            if (searchTxt != '') {
                var that = this;
                searchTxt = unescape(searchTxt).replaceAll('\\','/');
				if (obj == '') {
					obj = $(this.element.get(0)).find('.' + this._classSearch);
				}
                $.each(obj, function(ind, val) {
                    var cell = $(this);
                    var matches = [];
                    var txt = cell.html().replaceAll('\\','/');
                    var index = 0;
                    while (txt.toLowerCase().indexOf(searchTxt.toLowerCase(), index) != -1) {
                        index = txt.toLowerCase().indexOf(searchTxt.toLowerCase(), index);
                        if (index >= 0) {
                            matches.push(index)
                            index = index + searchTxt.length;
                        } else {
                            index = -1;
                        }
                    }
                    while (matches.length > 0) {
                        var i = matches.pop();
                        txt = txt.substring(0, i) + '<span class="' + that._classHighlight + '">' + txt.substring(i, i + searchTxt.length) + '</span>' + txt.substring(i + searchTxt.length, txt.length);
                    }
                    cell.html(txt.replaceAll('/','\\').replaceAll('<\\','</'));
                });
            }
        }
    });
})(jQuery);
