﻿($)
{
    var settings = "settings";
    var colData = "colData";




    $.fn.SFPTable = function(options) {

        return this.each(function(i) {
            var defaults = {
                pageSize: 5
                , lineCount: 0
                , currPage: -1
                , startPage: 0
                , pageCount: 0
                , cols: []
                , orgRows: []
                , rows: {}
                , defaultSortCol: 0
                , wrapper: {}
                , dateRegExp: /^(\d{1,2})\.(\d{1,2})\.(\d{2,4})/i
                , datePartGroupOrder: { Day: 1, Month: 2, Year: 3 }
                , timeFormat: 'tt.mm.ss'
                , emptyRow: {}
            }

            //Lagrer settings for dette objektet merget med defaults..

            var inlineSet;

            inlineSet = $(this).inlineOptions();

            var curSettings = $.extend(defaults, options, inlineSet);
            curSettings.table = this;

            //Gjemme den orginale tbody slik at vi kan legge til en ny en som vi skal fylle med linjer..
            $("tbody:first", this).hide();
            $(this).append('<tbody class="SFPBody" />');
            $(this).wrap($.SFPTable.api.wrapString());

            var newElem = $(this).parents(".SFP");
            curSettings.wrapper = newElem;
            var lines = $("tbody>tr", this);
            //Finne antall linjer
            curSettings.lineCount = lines.length;

            //Lager en tom rad for å kunne fylle opp...
            curSettings.emptyRow = $("<tr />")

            //legge på click på th... og finner ut hvilken type denne kolonnen er..
            //Og lage en tom td for hver th i emptyRow..
            $('thead:first th', this).each(function(i) {
                var colInfo = { ordinal: i, dir: 1, type: '', sortable: true };
                $.extend(colInfo, $(this).inlineOptions());

                if (colInfo.sortable) {
                    $(this).bind('click', $.SFPTable.api.headerClicked);
                    $(this).addClass('sortable');
                }
                colInfo.type = $(this).attr("type") || $.SFPTable.api.resolveType($("tbody>tr>td:eq(" + i + ")", curSettings.table).text(), curSettings);
                colInfo.settings = curSettings;
                curSettings.cols.push(colInfo);
                $(this).data(colData, colInfo);

                //Legger på td'r i den tomme raden. Like mange som vi har TH
                $(curSettings.emptyRow).append("<td>&nbsp;</td>");

            })


            //Looper gjennom alle linjene og cacher sortering og filter data i et settings object på hver linje.
            for (var x = 0; x < curSettings.lineCount; x++) { curSettings.orgRows.push($.SFPTable.api.retriveData(curSettings, lines[x])); }
            //Setter aktiver rader til den samme som orginale rader.. 
            curSettings.rows = curSettings.orgRows;
            curSettings.pageCount = Math.ceil(curSettings.rows.length / curSettings.pageSize);

            //lagrer settings for denne tabellen i data..
            $(this).data(settings, curSettings);

            //Oppretter paging og filter... Dette kan bli overidet hvis man vil det..
            $.SFPTable.api.constructPaging(curSettings, newElem)

            newElem.prepend("<div class='SFPFilterTop'><input type='text' class='SFPFilterInput'></div>");
            $(".SFPFilterInput", newElem).keyup($.SFPTable.api.filterChanged);


            $.SFPTable.api.sortArray(curSettings, [curSettings.cols[curSettings.defaultSortCol]]);
            $.SFPTable.api.showPage(curSettings, curSettings.startPage);
        })

    }
} (jQuery)




//Oppretter et namespace for api funksjoner.
$.SFPTable = {};
$.SFPTable.api = {};
$.SFPTable.events = {};


//Vise frem en gitt side..
$.SFPTable.api.showPage = function(data, pageNo) {

    if (data.currPage == pageNo) return;
    var tbody = $(".SFPBody", data.table);

    //Tømmer det som vises frem nå..
    tbody.empty();

    var startIndex = pageNo * data.pageSize;
    var endIndex = startIndex + data.pageSize;

    var tr, y;
    y = 0;
    for (var x = startIndex; x < endIndex; x++) {
        if (x < data.rows.length) { tr = data.rows[x].tr; } else { tr = $(data.emptyRow).clone(); }
        $(tr).attr('class', '');
        if (y % 2) { $(tr).addClass('SFPEvenRow'); } else { $(tr).addClass('SFPOddRow'); }
        tbody.append(tr);
        y++;
    }

    if (startIndex == 0) {
        $("#NavPrev", data.wrapper).removeClass("Prev").addClass('PrevDisabled');
        $("#NavFirst", data.wrapper).removeClass("First").addClass('FirstDisabled');
    } else {
        $("#NavPrev", data.wrapper).removeClass("PrevDisabled").addClass('Prev');
        $("#NavFirst", data.wrapper).removeClass("FirstDisabled").addClass('First');
    }


    if (endIndex >= data.rows.length) {
        $("#NavNext", data.wrapper).removeClass("Next").addClass("NextDisabled");
        $("#NavLast", data.wrapper).removeClass("Last").addClass("LastDisabled");
    } else {
        $("#NavNext", data.wrapper).removeClass("NextDisabled").addClass("Next");
        $("#NavLast", data.wrapper).removeClass("LastDisabled").addClass("Last");
    }


    $(".SFPCurPage", data.wrapper).text(pageNo + 1);
    $(".SFPPageCount", data.wrapper).text(data.pageCount);
    $(".SFPFilterCount", data.wrapper).text(data.rows.length);
    $(".SFPTotLines", data.wrapper).text(data.lineCount);
    data.currPage = pageNo;
}


$.SFPTable.api.constructPaging = function(settings, elem) {
    elem.append('<div class="SFPPaging"><table class="SFPPagingTable" border="0"  style="empty-cells: show;" ><tr><td class="Navigate First" id="NavFirst" ></td><td class="Navigate Prev" id="NavPrev"></td><td class="Info">Viser&nbsp;side&nbsp;<span class="SFPCurPage"></span>&nbsp;av&nbsp;<span class="SFPPageCount"></span></td><td class="Navigate Next" id="NavNext"></td><td class="Navigate Last" id="NavLast"></td></tr><tr><td colspan="5" class="SFPFilterInfo">Viser&nbsp;<span class="SFPFilterCount"></span>&nbsp;av totalt <span class="SFPTotLines"></span>&nbsp;linjer</td></tr></table></div>')

    $("#NavPrev", elem).data('settings', settings).click($.SFPTable.api.prevPage);
    $("#NavNext", elem).data('settings', settings).click($.SFPTable.api.nextPage);
    $("#NavFirst", elem).data('settings', settings).click($.SFPTable.api.firstPage);
    $("#NavLast", elem).data('settings', settings).click($.SFPTable.api.lastPage);
}


$.SFPTable.api.retriveData = function(settings, row) {
    var ret = {};
    var cols = $(">td", row);

    ret.tr = row;
    ret.rowText = $(row).text();
    ret.cols = [];
    var val;

    for (var x = 0; x < cols.length; x++) {
        //Lagt på muligheten for å sende med en egen verdi for sortering, dette er fint hvis det fks er en kolonne som inneholder bilder/ikoner.. 
        val = $(cols[x]).attr('sortData') || $(cols[x]).text();
        switch (settings.cols[x].type) {
            case "Int":
                ret.cols.push(parseInt(val));
                break;
            case "Float":
                ret.cols.push(parseFloat(val));
                break;
            case "Date":
                var m = settings.dateRegExp.exec(val);
                if (!m) {
                    settings.cols[x].type = "Text"
                    ret.cols.push(val.toLowerCase());
                    break;
                }
                var d = new Date;

                d.setFullYear(m[settings.datePartGroupOrder.Year], m[settings.datePartGroupOrder.Month], m[settings.datePartGroupOrder.Day]);
                ret.cols.push(d);
                break;
            default:
                //Normaliserer stringer til lowerCase. 
                ret.cols.push(val.toLowerCase());
        }

    }
    return ret;
}

$.SFPTable.api.sortArray = function(settings, cols) {

    var functionStr = 'var sortFunc = function(a,b) {  var ret; ';
    for (var x = 0; x < cols.length; x++) {
        functionStr += 'ret = ' + cols[x].dir.toString() + ' * $.SFPTable.api.sort' + cols[x].type + '(a.cols[' + cols[x].ordinal + '],b.cols[' + cols[x].ordinal + ']);';
        functionStr += 'if(ret != 0) return ret;'
        //Når det er multikolonne sortering må vi sjekke alle kolonner helt til vi finner en som er ulik..
    }
    functionStr += 'return 0}';
    eval(functionStr);
    settings.rows.sort(sortFunc);
    settings.currPage = -1;
}

$.SFPTable.api.sortText = function(a, b) { if (a < b) return -1; if (a > b) return 1; return 0 }
$.SFPTable.api.sortInt = function(a, b) { return a - b }
$.SFPTable.api.sortFloat = function(a, b) { return a - b }
$.SFPTable.api.sortDate = function(a, b) { return a - b }
//Legg til fler funksjoner her hvis man trenger flere typer å sortere på..


$.SFPTable.api.headerClicked = function(e) {
    //Vi må kalle sortering for denne kolonnen..
    var colInfo = $(this).data(colData);
    colInfo.dir *= -1;

    $(this.parentNode).find('th').removeClass('sortAsc').removeClass('sortDesc');

    //Legg til og fjerne klasser på header'n avhenging av hva det er vi sorterer på..
    if (colInfo.dir == 1) $(this).addClass('sortAsc');
    else $(this).addClass('sortDesc');

    //Sjekke om <ctrl> er nede. Da skal vi legge på en denne kolonnen..

    if (e.controlKey) {
        colInfo.settings.sorting.push(colInfo);
    } else {
        colInfo.settings.sorting = [colInfo];
    }

    $.SFPTable.api.sortArray(colInfo.settings, colInfo.settings.sorting);
    $.SFPTable.api.showPage(colInfo.settings, 0);
}

$.SFPTable.api.resolveType = function(val, settings) {

    var m = settings.dateRegExp.exec(val);
    if (m) return "Date";

    if (parseInt(val)) {
        if (parseInt(val) == parseFloat(val)) return "Int";
        return "Float";
    }

    return "Text";
}


$.SFPTable.api.wrapString = function(settings) {
    return "<div class='SFP'><div class='SFPTable'></div></div>";
}

$.SFPTable.api.filterChanged = function(e) {
    var curSettings = $(this).parents('.SFP:first').find("table").data(settings);

    curSettings.rows = new Array;

    var m = new RegExp("[\s\S]*?" + $(this).val() + "[\s\S]*", "i");

    for (var x = 0; x < curSettings.orgRows.length; x++) {
        if (m.exec(curSettings.orgRows[x].rowText)) {
            curSettings.rows.push(curSettings.orgRows[x]);
        }
    }

    curSettings.currPage = -1;
    curSettings.pageCount = Math.ceil(curSettings.rows.length / curSettings.pageSize);
    $.SFPTable.api.showPage(curSettings, 0);

}

$.SFPTable.api.nextPage = function() {
    var curSettings = $(this).data(settings);
    if (curSettings.currPage < curSettings.pageCount - 1) $.SFPTable.api.showPage(curSettings, curSettings.currPage + 1);

}

$.SFPTable.api.prevPage = function() {
    var curSettings = $(this).data(settings);
    if (curSettings.currPage > 0) $.SFPTable.api.showPage(curSettings, curSettings.currPage - 1);
}

$.SFPTable.api.lastPage = function() {
    var curSettings = $(this).data(settings);
    if (curSettings.currPage < curSettings.pageCount - 1) $.SFPTable.api.showPage(curSettings, curSettings.pageCount - 1);

}

$.SFPTable.api.firstPage = function() {
    var curSettings = $(this).data(settings);
    if (curSettings.currPage > 0) $.SFPTable.api.showPage(curSettings, 0);
}
