(function($) {
    $.extend({
        eventsorter: new function() {
            var cacheTXT = [], cacheOBJ = [];

            // Порядок сортировки false - по возрастанию, true - по убыванию
            var sortOrder = {date: false, title: false, place: false};

            // Кэшируем данные таблицы
            function buildCache(table) {
                i = 0;
                $(table).find('.exclusive_row, .default_row').each(function () {
                    cacheTXT[i] = {}, cacheOBJ[i] = {}, j = 0;
                    $(this).find('td').each(function () {
                        key = getKey(j);
                        cacheTXT[i][key] = getText(this);
                        cacheOBJ[i][key] = this;
                        j++;
                    });
                    // 0 - эксклюзив, 1 - нет
                    cacheTXT[i]['type'] = $(this).attr('class').match(/exclusive_row/g) ? 0 : 1;
                    cacheTXT[i]['idx'] = i;
                    i++;
                });
                // Дату в секунды
                for (i = 0; i < cacheTXT.length; i++) {
                    cacheTXT[i].date = new Date(
                        cacheTXT[i].
                            date.
                                replace(/(\d{1,2})[\.](\d{1,2})[\.](\d{4}) ([0-2]?[0-9]:[0-5][0-9])/, "$3/$2/$1 $4")
                    ).getTime();
                }
            };

            function rebuildTable(table) {
                $(table).find('.exclusive_row, .default_row').remove();
                var exclusiveAfter = $(table).find('.guestlist_head').get(0);
                var defaultAfter   = $(table).find('.simple_head').get(0);
                for (i = 0; i < cacheTXT.length; i++) {
                    cls = 'simple_row ';
                    idx = cacheTXT[i]['idx'];
                    obj = document.createElement('tr');
                    $(obj).append(cacheOBJ[idx].date);
                    $(obj).append(cacheOBJ[idx].title);
                    $(obj).append(cacheOBJ[idx].place);
                    if (0 == cacheTXT[i]['type']) {
                        cls = cls + 'exclusive_row';
                        $(exclusiveAfter).after(obj);
                        exclusiveAfter = obj;
                    } else {
                        cls = cls + 'default_row';
                        $(defaultAfter).after(obj);
                        defaultAfter = obj;
                    }
                    obj.className = cls;
                }
            };

            function bindHeaders(table) {
                var i = 0;
                $(table).find('th').each(function () {
                    $(this).bind('click', {byField: getKey(i), t: table}, sortTable);
                    i++;
                });
            };

            function sortTable(event) {
                byField = event.data.byField;
                order   = sortOrder[byField] ? 'Desc' : 'Asc';
                eval('var sortWrapper = function(a, b) { return ' + 'sortBy' + ucfirst(byField) + order + '(a, b)' + '; };');
                cacheTXT.sort(sortWrapper);
                sortOrder[byField] = !sortOrder[byField];
                rebuildTable(event.data.t);
            };

            function getText(node) {
                if (!node) {
                    return '';
                }

                var t = "";

                if (node.childNodes[0] && node.childNodes[0].hasChildNodes()) {
                    t = node.childNodes[0].innerHTML;
                } else {
                    t = node.innerHTML;
                }

                return jQuery.trim(t.replace(/<\/?[^>]+>/gi, ''));
            };

            function getKey(idx) {
                switch (idx) {
                    case 0:
                        key = 'date';
                        break;
                    case 1:
                        key = 'title';
                        break;
                    default:
                        key = 'place';
                        break;
                }
                return key;
            };

            function ucfirst(s) {
                var f = s.charAt(0).toUpperCase();
                return f + s.substr(1, s.length-1);
            };

            function sortByDateAsc(a, b) {
                return a.date - b.date;
            };

            function sortByDateDesc(a, b) {
                return b.date - a.date;
            };

            function sortByTitleAsc(a, b, place) {
                key = !place ? 'title' : 'place';
                var x = a[key].toLowerCase();
                var y = b[key].toLowerCase();
                return ((x < y) ? -1 : ((x > y) ? 1 : 0));
            };

            function sortByTitleDesc(a, b, place) {
                key = !place ? 'title' : 'place';
                var x = a[key].toLowerCase();
                var y = b[key].toLowerCase();
                return ((y < x) ? -1 : ((y > x) ? 1 : 0));
            };

            function sortByPlaceAsc(a, b) {
                return sortByTitleAsc(a, b, 1);
            };

            function sortByPlaceDesc(a, b) {
                return sortByTitleDesc(a, b, 1);
            };

            this.construct = function() {
                return this.each(function() {
                    buildCache(this);
                    bindHeaders(this);
                })
            };
        }
    });

    $.fn.extend({
        eventsorter: $.eventsorter.construct
    });
})(jQuery);

