$(document).ready(function() {
    $('button').button();
} );
submenu_image = '/images/icons/submenu.png';

/*-------------------------------------*/
/*  Button functions                   */
/*-------------------------------------*/

function Button(label, action, options) {
    this.options = {
        label: label,
        disabled: false
    }
    if (options) {
        if (options.id) this.options.id = options.id;
        if (options.disabled) this.options.disabled = options.disabled;
        if (options.pagesize) this.options.pagesize = options.pagesize;
    };
    this.onClick = action;
    this._button = null;
    this._drawn = false;

    this.setDisabled = function(disabled) {
        this.options.disabled = disabled;
        this._redraw();
    };

    this.rollout = function(obj) {
        if (!this._drawn) {
            var attr = {
                disabled: this.options.disabled
            };
            if (this.options.id) attr['id'] = this.options.id;
            this._button = createElement('button', attr);
            $(this._button).html(this.options.label);
            $(this._button).click(this.onClick);
            obj.append(this._button);
            $(this._button).button();
            this._drawn = true;
        }
    };
    this._redraw = function() {
        if (this._drawn) {
    // Do nothing
    }
    };
};

/*-------------------------------------*/
/*  ButtonSet functions                */
/*-------------------------------------*/

function ButtonSet(options) {
    this.options = {
        checked: 0,
        disabled: false
    }
    if (options) {
        if (options.id) this.options.id = options.id;
        if (options.disabled) this.options.disabled = options.disabled;
        if (options.checked) this.options.checked = options.checked;
    };
    this._buttons = [];
    this._buttonset = null
    this._drawn = false;

    this.setDisabled = function(disabled) {
        this.options.disabled = disabled;
        this._redraw();
    };

    this.addButton = function(label, action, options) {
        var button = {
            label: label,
            action: action,
            id: this.options.id + this._buttons.length
        };
        if (options) {
            if (options.id) button.id = options.id;
            if (options.disabled) button.disabled = options.disabled;
            if (options.checked) button.checked = options.checked;
        }
        this._buttons[this._buttons.length] = button;
        this._redraw();
    }

    this.rollout = function(obj) {
        var attr = {
            disabled: this.options.disabled
        };
        if (this.options.id) attr.id = this.options.id;
        this._buttonset = createElement('span', attr);
        obj.append(this._buttonset);
        this._drawn = true;
        this._redraw();
    };
    this._redraw = function() {
        if (this._drawn) {
            $(this._buttonset).empty();
            for(var x=0; x<this._buttons.length; x++) {
                var button = this._buttons[x];
                var attr = {
                    type: 'radio',
                    name: this.options.id,
                    id: button.id,
                    value: button.label
                };
                if (button.checked) attr.checked = button.checked;
                var radio = createElement('input', attr);
                $(radio).click(button.action);
                $(this._buttonset).append(radio);

                attr = {
                    'for': button.id
                };
                var label = createElement('label', attr);
                $(label).html(button.label);
                $(this._buttonset).append(label);
                $(this._buttonset).buttonset();
            }
        }
    };
}

/*-------------------------------------*/
/*  Pager functions                    */
/*-------------------------------------*/

function Pager(id, options) {
    this.name = id;
    this.options = {
        current: 0,
        length: 0,
        pagesize: 0,
        url: ''
    };
    this.options.current = parseInt(location.hash.substring(1));
    if (isNaN(this.options.current)) this.options.current = 0;
    if (options) {
        if (options.current) this.options.current = options.current;
        if (options.length) this.options.length = options.length;
        if (options.pagesize) this.options.pagesize = options.pagesize;
        if (options.url) this.options.url = options.url;
    }
    this._drawn = false;
    this._curpage = 0;
    this._pages = 0;
    this._container = null;

    this.setCurrent = function(current) {
        this.options.current = current;
        this._updateNumbers();
    };
    this.setPagesize = function(pagesize) {
        this.options.pagesize = pagesize;
        this._updateNumbers();
    };
    this.setLength = function(length) {
        this.options.length = length;
        this._updateNumbers();
    };

    this.rollout = function(obj) {
        this._container = createElement('div', {
            id: this.name
        });
        obj.append(this._container);
        this._drawn = true;
        this._updateNumbers();
    };
    this._updateNumbers = function() {
        if (this.options.current>this.options.length) this.options.current = this.options.length-1;

        var pages = Math.ceil(this.options.current / this.options.pagesize);
        this._curpage = pages + 1;
        pages = pages + Math.ceil((this.options.length - this.options.current) / this.options.pagesize);
        if (pages == 0) pages = 1;
        this._pages = pages;

        this._redraw();
    };
    this._redraw = function() {
        if (this._drawn) {
            var maxpages = 5;
            $(this._container).empty();
            var action;
            var button;
            var x;
            var options;

            if (this._curpage!=1) {
                action = this._buildAction(1);
                button = new Button('<< ', action);
                button.rollout($(this._container));

                action = this._buildAction(this._curpage-1);
                button = new Button('< ', action);
                button.rollout($(this._container));
            }

            var buttonset = new ButtonSet({
                id: this.name+'Pages'
            });
            if (this._pages == 1) {
                $(this._container).html('&nbsp;');
            }
            else if (this._pages < (maxpages + 1)) {
                for(x = 1; x<=this._pages; x++) {
                    action = this._buildAction(x);
                    options = {};
                    if (x == this._curpage) options.checked = 'checked';
                    buttonset.addButton(x, action, options);
                }
            } else {
                var before = this._curpage - 1;
                var after = this._pages - this._curpage;
                var half = Math.round((maxpages-1)/2);
                if (before > half) before = half;
                if (after > half) after = half;
                if (before < half) after += (half - before);
                if (after < half) before += (half - after);
                //alert(this._pages);
                for(x = (this._curpage - before); x<=(this._curpage + after); x++) {
                    action = this._buildAction(x);
                    options = {};
                    if (x == this._curpage) options.checked = 'checked';
                    var title = x;
                    if (x == (this._curpage - before) && x != 1) title = '..' + x;
                    if (x == (this._curpage + after) && x != this._pages) title = x + '..';
                    buttonset.addButton(title, action, options);
                }
            }
            buttonset.rollout($(this._container));

            if (this._curpage!=this._pages) {
                action = this._buildAction(this._curpage+1);
                button = new Button('> ', action);
                button.rollout($(this._container));

                action = this._buildAction(this._pages);
                button = new Button('>> ', action);
                button.rollout($(this._container));
            }

        }
    };
    this._buildAction = function(x) {
        var pager = this;
        var diff = (x - this._curpage);
        var index = this.options.current + (diff * this.options.pagesize);
        if (index < 0) index = 0;
        return function(event) {
            pager.setCurrent(index);
            pager.onUpdate(index);
        };
    };
    this._clickPage = function(event) {
        var page = $(event.target).attr('value') - 1;
        alert(this.options.current);
        location.href = this.options.url + '&gallery_page' + page;
    };
    this.onUpdate = function(index) {
    };
}

/*-------------------------------------*/
/*  List functions                     */
/*-------------------------------------*/

function List(id, options) {
    this.name = id;
    this.page_size = 0;
    this.start = parseInt(location.hash.substring(1));
    if (isNaN(this.start)) this.start = 0;
    this.end = options.length
    this.sort = false;
    this.filter = '';
    this.order_by = '';
    this.order = ['', false];
    this.dynamic = true;
    this.ajax_url = '/test/gallery/ajax_images.php';
    this.url = '/general/gallery.php';
    this.buffer = [];
    this.header = options.header;
    this.root = null;
    this.pager = null;
    this.displayed = 0;
    this.selectfilter = -2;
    if (options) {
        if (options.pagesize) {
            this.page_size = options.pagesize;
            this.dynamic = false;
        }
        if (options.length) this.end = options.length;
        if (options.current) this.start = options.current;
        if (options.url) this.url = options.url;
        if (options.ajax_url) this.ajax_url = options.ajax_url;
        if (options.title) this.title = options.title;
        if (options.pager) this.pager = options.pager;
        if (options.order) {
            this.sort = true;
            this.order = options.order;
            this.order_by = options.order[0];
            if (options.order[1]) this.order_by = this.order_by + ' DESC';
        }
        if (options.selectfilter) this.selectfilter = options.selectfilter;
    }

    this.calculateSize = function () {
        if (this.dynamic) {
            this.root = $('#' + this.name);
            this.root.empty();
            var list = this;
            var table = $('<table/>',
            {
                id: this.name,
                'class': 'list',
                'width': '100%'
            });
            table.appendTo(this.root);
            var tr = $('<tr/>');
            tr.appendTo(table);
            $.each(this.header.titles, function(key, item) {
                var th = $('<th/>', {
                    'class': 'clickable'
                });
                th.html(item);
                if (list.sort && list.order[0] == list.header.columns[key]) {
                    var icon = '/images/icons/sort_ascending.png';
                    if (list.order[1]) icon = '/images/icons/sort_descending.png';
                    var img = $('<img/>', {
                        src: icon
                    });
                    img.appendTo(th);
                }
                th.appendTo(tr);
            });
            var th_height = tr.height();
            tr = $('<tr/>');
            tr.appendTo(table);
            $.each(this.header.titles, function(key, item) {
                var td = $('<td/>');
                td.html(item);
                td.appendTo(tr);
            });
            var td_height = tr.height();
            this.root.empty();
            rows = Math.floor((this.root.height() - th_height)/(td_height));
            this.page_size = rows;
            this.pager.setPagesize(this.page_size);
        }
    }

    this.checkBuffer = function () {
        var end = this.start + this.page_size;
        if (end > (this.end+1)) end = this.end+1;
        var n=this.start;
        while(typeof(this.buffer[n])!="undefined" && n<end) {
            n++;
        }
        if (n<end) {
            this.root.empty();
            ajaxLoading(this.root);
            var str = 'start=' + n + '&length=' + (end - n + 1);
            if (this.sort) str = str + '&sort=' + urlencode(this.order_by);
            if (this.filter != '') str = str + '&filter=' + urlencode(this.filter);
            var list = this;
            var aj = $.ajax({
                url: this.ajax_url,
                type: 'POST',
                data: str,
                success: function(transport) {
                    var result = transport;
                    if (typeof(result)=='undefined') {
                        dialog_alert(list.title, translate('An error occured when trying to load the data') + ':' + transport.responseText, '/images/icons/dialogs/error.png', '');
                    }
                    $.each(result, function(key, item) {
                        list.buffer[key]=item;
                    });
                    list.fillList();
                },
                error: function(transport) {
                    dialog_alert(list.title, translate('An error occured when trying to load the data') + ':' + transport.responseText, '/images/icons/dialogs/error.png', '');
                }
            });
        } else this.fillList();
    }

    this.fillList = function () {
        var list = this;
        this.root.empty();
        var table = $('<table/>',
        {
            id: this.name,
            'class': 'list',
            'width': '100%'
        });
        table.appendTo(this.root);
        var tr = $('<tr/>');
        tr.appendTo(table);
        $.each(this.header.titles, function(key, item) {
            var th = $('<th/>');
            th.html(item);
            if (list.sort && item != '') {
                $(th).addClass('clickable');
                if (list.sort && list.order[0] == list.header.columns[key] && item != '') {
                    var icon = '/images/icons/sort_ascending.png';
                    if (list.order[1]) icon = '/images/icons/sort_descending.png';
                    var img = $('<img/>', {
                        src: icon
                    });
                    img.appendTo(th);
                }
                var action = list._buildSortAction(list.header.columns[key]);
                $(th).click(action);
            }
            th.appendTo(tr);
        });

        var end = this.start + this.page_size;
        if (end > this.end) end = this.end;
        this.displayed = end - this.start;
        var second = true;
        for(var x=this.start; x<end; x++) if (this.buffer[x]) {
            var classes = 'left';
            if (second) {
                second = false;
                classes = classes + ' second';
            } else second = true;
            if (this.selectfilter==-1) classes = classes + ' selectable';
            if (this.selectfilter==this.buffer[x]['UserID']) classes = classes + ' selectable';
            if (list.buffer[x]['link']) classes = classes + ' clickable';
            tr = $('<tr/>', {
                'class' : classes
            });
            $.each(this.header.columns, function(key, item) {
                var td = $('<td/>');
                if (list.header.align) td.addClass(list.header.align[key]);
                td.html(list.buffer[x][item]);
                if (list.buffer[x]['link'] && item!='Actions') {
                    var url = list.buffer[x]['link'];
                    td.click(function() {
                        location.href= url;
                    });
                }
                td.appendTo(tr);
            });
            tr.appendTo(table);
        //this._showListItem(x - this.start, tr);
        }
    /*$('.selectable').click( select );
        $('.selectable').mousedown( selecting );
        $('#contents').click( select );
        $(this.root).selectable({
            filter: '.selectable',
            distance: 1
        });*/
    }

    this._buildSortAction = function(column) {
        var list = this;
        var col = column;
        return function(event) {
            list.setOrderBy(col);
        };
    };

    this.setOrderBy = function(column) {
        if (this.order[0] == column) this.order[1] = !this.order[1];
        else this.order[0] = column;
        this.order_by = column;
        if (this.order[1]) this.order_by = this.order_by + ' DESC';
        this.buffer = [];
        setPreferences(this.name + '_List_OrderBy', this.order[0]);
        if (this.order[1]) setPreferences(this.name + '_List_OrderDescending', 'true');
        else setPreferences(this.name + '_List_OrderDescending', 'false');
        this.redraw();
    };

    this.setFilter = function(newFilter) {
        this.filter = newFilter;
        this.buffer = [];
        this.header = {};
        var list = this;
        this.clearList(function(){
            list.redraw()
        });
    };

    this._showListItem = function (x, div) {
        var interval = 400 / this.displayed;
        setTimeout(function() {
            div.fadeIn('fast');
        }, interval * x);
    };

    this.rollout = function () {
        this.root = $('#' + this.name);
        this.root.empty();
        if (this.pager == null) {
            this.pager = new Pager(this.name + 'Pager', {
                current: this.start,
                pagesize: this.page_size,
                length: this.end
            });
            this.pager.onUpdate = function(index) {
                location.hash = index;
            };
            this.pager.rollout($('#' + this.name + 'PagerContainer'));
        } else if (typeof(this.pager)=='string') {
            var destination = this.pager;
            this.pager = new Pager(this.name + 'Pager', {
                current: this.start,
                pagesize: this.page_size,
                length: this.end
            });
            this.pager.onUpdate = function(index) {
                location.hash = index;
            };
            this.pager.rollout($('#' + destination));
        }

        this.redraw();
    };

    this.clearList = function (func) {
        if (this.displayed>0) {
            this.displayed = 0;
            var list = this;
            if (!ie) $('.list tr').fadeOut('fast', function() {
                if (list.displayed == 0) {
                    list.displayed++;
                    func();
                }
            });
            else {
                this.root.empty();
                func();
            }
        }
        else func();
    };

    this.redraw = function () {
        var str = 'headers=true';
        if (this.filter != '') str = str + '&filter=' + this.filter;
        var list = this;
        ajaxLoading(this.root);
        var aj = $.ajax({
            url: this.ajax_url,
            type: 'POST',
            data: str,
            success: function(transport) {
                var result = transport;
                if (typeof(result)=='undefined') {
                    dialog_alert(list.title, translate('An error occured when trying to load the data') + ':' + transport.responseText, '/images/icons/dialogs/error.png', '');
                }
                list.end = result.length;
                list.pager.setLength(result.length);
                list.header = result;
                list.calculateSize();
                list.checkBuffer();
            },
            error: function(transport) {
                dialog_alert(list.title, translate('An error occured when trying to load the data') + ':' + transport.responseText, '/images/icons/dialogs/error.png', '');
            }
        });

    }

    var list = this;
    $(window).bind('changesize', function() {
        list.redraw();
    });

    window.onhashchange = function() {
        list.start = parseInt(location.hash.substring(1));
        if (isNaN(list.start)) list.start = 0;
        list.clearList(function() {
            list.checkBuffer();
        });
    }
}

/*-------------------------------------*/
/*  ImageList functions                */
/*-------------------------------------*/

function ImageList(id, options) {
    this.name = id;
    this.page_size = 0;
    this.start = parseInt(location.hash.substring(1));
    if (isNaN(this.start)) this.start = 0;
    this.end = options.length
    this.sort = false;
    this.filter = '';
    this.order_by = '';
    this.order = ['', false];
    this.dynamic = true;
    this.ajax_url = '/test/gallery/ajax_images.php';
    this.url = '/general/gallery.php';
    this.item_width = 180;
    this.item_height = 180;
    this.buffer = [];
    this.header = options.header;
    this.root = null;
    this.pager = null;
    this.lock = true;
    this.displayed = 0;
    this.selectfilter = -2;
    if (options) {
        if (options.pagesize) {
            this.page_size = options.pagesize;
            this.dynamic = false;
        }
        if (options.length) this.end = options.length;
        if (options.current) this.start = options.current;
        if (options.url) this.url = options.url;
        if (options.ajax_url) this.ajax_url = options.ajax_url;
        if (options.title) this.title = options.title;
        if (options.pager) this.pager = options.pager;
        if (options.item_width) this.item_width = options.item_width;
        if (options.item_height) this.item_height = options.item_height;
        if (options.order) {
            this.sort = true;
            this.order = options.order;
            this.order_by = options.order[0];
            if (options.order[1]) this.order_by = this.order_by + ' DESC';
        }
        if (options.selectfilter) this.selectfilter = options.selectfilter;
    }

    this.calculateSize = function () {
        if (this.dynamic) {
            this.root = $('#' + this.name);
            this.root.empty();
            var div = $('<div/>', {
                'class' : 'list_image selectable',
                'style': 'margin: 5px; width: ' + (this.item_width + 20) + 'px; height: ' + (this.item_height + 40) + 'px;'
            });
            div.html('&nbsp;')
            div.appendTo(this.root);
            cols = Math.floor((this.root.innerWidth())/($(div).outerWidth() + 10));
            rows = Math.floor((this.root.innerHeight())/($(div).outerHeight() + 10));
            this.page_size = cols * rows;
            if (this.page_size == 0) this.page_size = 1;
            this.pager.setPagesize(this.page_size);
            this.root.empty();
        }
    }

    this.checkBuffer = function () {
        var end = this.start + this.page_size;
        if (end > (this.end+1)) end = this.end+1;
        var n=this.start;
        while(typeof(this.buffer[n])!="undefined" && n<end) {
            n++;
        }
        if (n<end) {
            this.root.empty();
            ajaxLoading(this.root);
            var str = 'start=' + n + '&length=' + (end - n + 1);
            if (this.sort) str = str + '&sort=' + urlencode(this.order_by);
            if (this.filter != '') str = str + '&filter=' + urlencode(this.filter);
            var list = this;
            var aj = $.ajax({
                url: this.ajax_url,
                type: 'POST',
                data: str,
                success: function(transport) {
                    var result = transport;
                    if (typeof(result)=='undefined') {
                        dialog_alert(list.title, translate('An error occured when trying to load the data') + ':' + transport.responseText, '/images/icons/dialogs/error.png', '');
                    }
                    $.each(result, function(key, item) {
                        list.buffer[key]=item;
                    });
                    list.fillList();
                },
                error: function(transport) {
                    dialog_alert(list.title, translate('An error occured when trying to load the data') + ':' + transport.responseText, '/images/icons/dialogs/error.png', '');
                }
            });
        } else this.fillList();
    }

    this.fillList = function () {
        this.root.empty();
        var end = this.start + this.page_size;
        if (end > this.end) end = this.end;
        this.displayed = end - this.start;
        for(var x = this.start; x < end; x++) if (this.buffer[x]) {
            var classes = 'list_image';
            if (this.selectfilter==-1) classes = classes + ' selectable';
            if (this.selectfilter==this.buffer[x]['UserID']) classes = classes + ' selectable';
            var div = $('<div/>', {
                'id' : this.buffer[x]['ID'],
                'class' : classes,
                'style': 'width: ' + this.item_width + 'px; height: ' + (this.item_height + 20) + 'px;'
            });
            var element;
            var div2 = $('<div/>', {
                'align': 'center',
                'style': 'width: ' + this.item_width + 'px; height: ' + this.item_height + 'px;'
            });
            div2.appendTo(div);
            element = $('<a/>', {
                'href' : this.buffer[x]['link']
            });
            element.appendTo(div2);
            var image = $('<img/>', {
                'src' : this.buffer[x]['Image']
            });
            image.appendTo(element);
            //element = $('<br/>');
            //element.appendTo(div);
            element = $('<span/>');
            var url;
            url = this.buffer[x]['link'];
            element.html('<a href="' + url + '">' + this.buffer[x]['Name'] + '</a>');
            element.appendTo(div);
            div.appendTo(this.root);
        //this._showListItem(x - this.start, div);
        }
        $('.selectable').click( select );
        $('.selectable').mousedown( selecting );
        $('#contents').click( select );
        $(this.root).selectable({
            filter: '.selectable',
            distance: 1
        });
    }

    this._buildSortAction = function(column) {
        var list = this;
        var col = column;
        return function(event) {
            list.setOrderBy(col);
        };
    };

    this.setOrderBy = function(column) {
        if (this.order[0] == column) this.order[1] = !this.order[1];
        else this.order[0] = column;
        this.order_by = column;
        if (this.order[1]) this.order_by = this.order_by + ' DESC';
        this.buffer = [];
        setPreferences(this.name + '_List_OrderBy', this.order[0]);
        if (this.order[1]) setPreferences(this.name + '_List_OrderDescending', 'true');
        else setPreferences(this.name + '_List_OrderDescending', 'false');
        this.redraw();
    };

    this.setFilter = function(newFilter) {
        var list = this;
        this.filter = newFilter;
        if (this.lock) {
            setTimeout(function() {
                list.setFilter(filter);
            }, 10);
        } else {
            this.buffer = [];
            this.header = {};
            this.clearList(function(){
                list.redraw()
            });
        }
    };

    this._showListItem = function (x, div) {
        var interval = 400 / this.displayed;
        setTimeout(function() {
            div.fadeIn('fast');
        }, interval * x);
    };

    this.rollout = function () {
        this.root = $('#' + this.name);
        this.root.empty();
        if (this.pager == null) {
            this.pager = new Pager(this.name + 'Pager', {
                current: this.start,
                pagesize: this.page_size,
                length: this.end
            });
            this.pager.onUpdate = function(index) {
                location.hash = index;
            };
            this.pager.rollout($('#' + this.name + 'PagerContainer'));
        } else if (typeof(this.pager)=='string') {
            var destination = this.pager;
            this.pager = new Pager(this.name + 'Pager', {
                current: this.start,
                pagesize: this.page_size,
                length: this.end
            });
            this.pager.onUpdate = function(index) {
                location.hash = index;
            };
            this.pager.rollout($('#' + destination));
        }

        this.redraw();
    };

    this.clearList = function (func) {
        if (this.displayed>0) {
            this.displayed = 0;
            var list = this;
            if (!ie) $('.list_image').fadeOut('fast', function() {
                if (list.displayed == 0) {
                    list.displayed++;
                    func();
                }
            });
            else {
                this.root.empty();
                func();
            }
        }
        else func();
    };

    this.redraw = function () {
        var list = this;
        if (this.lock) {
            setTimeout(function() {
                list.redraw();
            }, 10);
        } else {
            this.lock = true;
            var str = 'headers=true';
            if (this.filter != '') str = str + '&filter=' + this.filter;
            ajaxLoading(this.root);
            var aj = $.ajax({
                url: this.ajax_url,
                type: 'POST',
                data: str,
                success: function(transport) {
                    var result = transport;
                    if (typeof(result)=='undefined') {
                        dialog_alert(list.title, translate('An error occured when trying to load the data') + ':' + transport.responseText, '/images/icons/dialogs/error.png', '');
                    }
                    //alert(result.length);
                    list.end = result.length;
                    list.pager.setLength(result.length);
                    list.item_width = result.item_width;
                    list.item_height = result.item_height;
                    list.calculateSize();
                    list.checkBuffer();
                    list.lock = false;
                },
                error: function(transport) {
                    dialog_alert(list.title, translate('An error occured when trying to load the data') + ':' + transport.responseText, '/images/icons/dialogs/error.png', '');
                    list.lock = false;
                }
            });
        }
    }

    var list = this;
    $(window).bind('changesize', function() {
        list.redraw();
    });

    window.onhashchange = function() {
        list.start = parseInt(location.hash.substring(1));
        if (isNaN(list.start)) list.start = 0;
        list.clearList(function() {
            list.redraw();
        });
    }
    this.lock = false;
}

/*-------------------------------------*/
/*  ItemList functions                 */
/*-------------------------------------*/

function ItemList(id, options) {
    this.name = id;
    this.page_size = 0;
    this.start = parseInt(location.hash.substring(1));
    if (isNaN(this.start)) this.start = 0;
    this.end = options.length
    this.sort = false;
    this.mode = 'image';
    this.captions = true;
    this.filter = '';
    this.order_by = '';
    this.order = ['', false];
    this.dynamic = true;
    this.ajax_url = '/test/gallery/ajax_images.php';
    this.url = '/general/gallery.php';
    this.item_width = 180;
    this.item_height = 180;
    this.buffer = [];
    this.selected = [];
    this.header = options.header;
    this.root = null;
    this.pager = null;
    this.lock = true;
    this.displayed = 0;
    this.selectfilter = -2;
    if (options) {
        if (options.pagesize) {
            this.page_size = options.pagesize;
            this.dynamic = false;
        }
        if (options.length) this.end = options.length;
        if (options.current) this.start = options.current;
        if (options.url) this.url = options.url;
        if (options.mode) this.mode = options.mode;
        if (options.ajax_url) this.ajax_url = options.ajax_url;
        if (options.title) this.title = options.title;
        if (options.pager) this.pager = options.pager;
        if (options.selected) this.pager = options.selected;
        if (options.item_width) this.item_width = options.item_width;
        if (options.item_height) this.item_height = options.item_height;
        if (options.order) {
            this.sort = true;
            this.order = options.order;
            this.order_by = options.order[0];
            if (options.order[1]) this.order_by = this.order_by + ' DESC';
        }
        if (options.selectfilter) this.selectfilter = options.selectfilter;
    }

    this.calculateSize = function () {
        if (this.mode == 'image') this._calculateSizeImage();
        else this._calculateSizeTable();        
    }
    
    this._calculateSizeTable = function () {
        if (this.dynamic) {
            //this.root = $('#' + this.name);
            this.root.empty();
            var list = this;
            var table = $('<table/>',
            {
                id: this.name,
                'class': 'list',
                'width': '100%'
            });
            table.appendTo(this.root);
            var tr = $('<tr/>');
            tr.appendTo(table);
            $.each(this.header.titles, function(key, item) {
                var th = $('<th/>', {
                    'class': 'clickable'
                });
                th.html(item);
                if (list.sort && list.order[0] == list.header.columns[key]) {
                    var icon = '/images/icons/sort_ascending.png';
                    if (list.order[1]) icon = '/images/icons/sort_descending.png';
                    var img = $('<img/>', {
                        src: icon
                    });
                    img.appendTo(th);
                }
                th.appendTo(tr);
            });
            var th_height = tr.height();
            tr = $('<tr/>');
            tr.appendTo(table);
            $.each(this.header.titles, function(key, item) {
                var td = $('<td/>');
                td.html(item);
                td.appendTo(tr);
            });
            var td_height = tr.height();
            this.root.empty();
            rows = Math.floor((this.root.height() - th_height)/(td_height));
            this.page_size = rows;
            this.pager.setPagesize(this.page_size);
        }
    }

    this._calculateSizeImage = function () {
        if (this.dynamic) {
            //this.root = $('#' + this.name);
            var item_height = this.item_height;
            if (this.captions) item_height += 20;
            this.root.empty();
            var div = $('<div/>', {
                'class' : 'list_image selectable',
                'style': 'width: ' + this.item_width + 'px; height: ' + item_height + 'px;'
            });
            div.html('&nbsp;')
            div.appendTo(this.root);
            cols = Math.floor((this.root.innerWidth())/($(div).outerWidth() + 10));
            rows = Math.floor((this.root.innerHeight())/($(div).outerHeight() + 10));
            this.page_size = cols * rows;
            if (this.page_size == 0) this.page_size = 1;
            this.pager.setPagesize(this.page_size);
            this.root.empty();
        }
    }

    this.checkBuffer = function () {
        var end = this.start + this.page_size;
        if (end > (this.end+1)) end = this.end+1;
        var n=this.start;
        while(typeof(this.buffer[n])!="undefined" && n<end) {
            n++;
        }
        if (n<end) {
            this.root.empty();
            ajaxLoading(this.root);
            var str = 'start=' + n + '&length=' + (end - n + 1);
            if (this.sort) str = str + '&sort=' + urlencode(this.order_by);
            if (this.filter != '') str = str + '&filter=' + urlencode(this.filter);
            var list = this;
            var aj = $.ajax({
                url: this.ajax_url,
                type: 'POST',
                data: str,
                success: function(transport) {
                    var result = transport;
                    if (typeof(result)=='undefined') {
                        dialog_alert(list.title, translate('An error occured when trying to load the data') + ':' + transport.responseText, '/images/icons/dialogs/error.png', '');
                    }
                    $.each(result, function(key, item) {
                        list.buffer[key]=item;
                    });
                    list.fillList();
                },
                error: function(transport) {
                    dialog_alert(list.title, translate('An error occured when trying to load the data') + ':' + transport.responseText, '/images/icons/dialogs/error.png', '');
                }
            });
        } else this.fillList();
    }

    this.fillList = function () {
        if (this.mode == 'image') this._fillListImage();
        else this._fillListTable();
    }
    
    this._fillListImage = function () {
        var item_height = this.item_height;
        if (this.captions) item_height += 20;
        this.root.empty();
        var end = this.start + this.page_size;
        if (end > this.end) end = this.end;
        this.displayed = end - this.start;
        for(var x = this.start; x < end; x++) if (this.buffer[x]) {
            var classes = 'list_item list_image';
            if (this.selectfilter==-1) classes = classes + ' selectable';
            if (this.selectfilter==this.buffer[x]['UserID']) classes = classes + ' selectable';
            var div = $('<div/>', {
                'id' : this.buffer[x]['ID'],
                'class' : classes,
                'style': 'width: ' + this.item_width + 'px; height: ' + item_height + 'px;'
            });
            var url = this.buffer[x]['link'];
            if (this.onClick) {
                div.click(this.onClick);
                url = '';
            }
            var element;
            var div2 = $('<div/>', {
                'align': 'center',
                'style': 'width: ' + this.item_width + 'px; height: ' + this.item_height + 'px;'
            });
            div2.appendTo(div);
            var image = $('<img/>', {
                'src' : this.buffer[x]['Image']
            });
            if (url != '') {
                element = $('<a/>', {
                    'href' : url
                });
                element.appendTo(div2);
                image.appendTo(element);
            } else {
                image.appendTo(div2);
            }
            //element = $('<br/>');
            //element.appendTo(div);
            if (this.captions) {
                element = $('<span/>');
                if (url != '') {
                    element.html('<a href="' + url + '">' + this.buffer[x]['Name'] + '</a>');
                } else {
                    element.html(this.buffer[x]['Name']);
                }
                element.appendTo(div);
            }
            div.appendTo(this.root);
        //this._showListItem(x - this.start, div);
        }
        this.setSelected(this.selected);
        $('.selectable').click( select );
        $('.selectable').mousedown( selecting );
        $('#contents').click( select );
        $(this.root).selectable({
            filter: '.selectable',
            distance: 1
        });
    }

    this._fillListTable = function () {
        if (this.header.titles) {
            var list = this;
            this.root.empty();
            var table = $('<table/>',
            {
                id: this.name,
                'class': 'list',
                'width': '100%'
            });
            table.appendTo(this.root);
            var tr = $('<tr/>');
            tr.appendTo(table);
            $.each(list.header.titles, function(key, item) {
                var th = $('<th/>');
                th.html(item);
                if (list.sort && item != '') {
                    $(th).addClass('clickable');
                    if (list.sort && list.order[0] == list.header.columns[key] && item != '') {
                        var icon = '/images/icons/sort_ascending.png';
                        if (list.order[1]) icon = '/images/icons/sort_descending.png';
                        var img = $('<img/>', {
                            src: icon
                        });
                        img.appendTo(th);
                    }
                    var action = list._buildSortAction(list.header.columns[key]);
                    $(th).click(action);
                }
                th.appendTo(tr);
            });

            var end = this.start + this.page_size;
            if (end > this.end) end = this.end;
            this.displayed = end - this.start;
            var second = true;
            for(var x=this.start; x<end; x++) if (this.buffer[x]) {
                var classes = 'list_item left';
                if (second) {
                    second = false;
                    classes = classes + ' second';
                } else second = true;
                if (this.selectfilter==-1) classes = classes + ' selectable';
                if (this.selectfilter==this.buffer[x]['UserID']) classes = classes + ' selectable';
                if (list.buffer[x]['link']) classes = classes + ' clickable';
                tr = $('<tr/>', {
                    'class' : classes
                });
                $.each(this.header.columns, function(key, item) {
                    var td = $('<td/>');
                    if (list.header.align) td.addClass(list.header.align[key]);
                    td.html(list.buffer[x][item]);
                    if (list.buffer[x]['link'] && item!='Actions') {
                        var url = list.buffer[x]['link'];
                        td.click(function() {
                            location.href= url;
                        });
                    }
                    td.appendTo(tr);
                });
                tr.appendTo(table);
            //this._showListItem(x - this.start, tr);
            }
        /*$('.selectable').click( select );
        $('.selectable').mousedown( selecting );
        $('#contents').click( select );
        $(this.root).selectable({
            filter: '.selectable',
            distance: 1
        });*/
        }
    }

    this._buildSortAction = function(column) {
        var list = this;
        var col = column;
        return function(event) {
            list.setOrderBy(col);
        };
    };

    this.setOrderBy = function(column) {
        if (this.order[0] == column) this.order[1] = !this.order[1];
        else this.order[0] = column;
        this.order_by = column;
        if (this.order[1]) this.order_by = this.order_by + ' DESC';
        this.buffer = [];
        setPreferences(this.name + '_List_OrderBy', this.order[0]);
        if (this.order[1]) setPreferences(this.name + '_List_OrderDescending', 'true');
        else setPreferences(this.name + '_List_OrderDescending', 'false');
        this.redraw();
    };

    this.setFilter = function(newFilter) {
        var list = this;
        this.filter = newFilter;
        if (this.lock) {
            setTimeout(function() {
                list.setFilter(newFilter);
            }, 10);
        } else {
            this.buffer = [];
            this.header = {};
            this.clearList(function(){
                list.redraw()
            });
        }
    };

    this._showListItem = function (x, div) {
        var interval = 400 / this.displayed;
        setTimeout(function() {
            div.fadeIn('fast');
        }, interval * x);
    };

    this.rollout = function (target) {
        this.root = $('#' + target);
        this.root.empty();
        if (this.pager == null) {
            this.pager = new Pager(this.name + 'Pager', {
                current: this.start,
                pagesize: this.page_size,
                length: this.end
            });
            this.pager.onUpdate = function(index) {
                location.hash = index;
            };
            this.pager.rollout($('#' + this.name + 'PagerContainer'));
        } else if (typeof(this.pager)=='string') {
            var destination = this.pager;
            this.pager = new Pager(this.name + 'Pager', {
                current: this.start,
                pagesize: this.page_size,
                length: this.end
            });
            this.pager.onUpdate = function(index) {
                location.hash = index;
            };
            this.pager.rollout($('#' + destination));
        }

        this.redraw();
    };

    this.clearList = function (func) {
        if (this.displayed>0) {
            this.displayed = 0;
            var list = this;
            if (!ie) $('.list_item').fadeOut('fast', function() {
                if (list.displayed == 0) {
                    list.displayed++;
                    func();
                }
            });
            else {
                this.root.empty();
                func();
            }
        } else {
            func();
        }
    };
    
    this.setSelected = function(new_selected) {
        this.selected = new_selected;
        var selectedids = '';
        $.each(new_selected, function(key, item) {
            if (selectedids != '') selectedids = selectedids + ', ';
            selectedids = selectedids + '#' + item;
        });
        $('.list_image').removeClass('selected');
        $(selectedids).addClass('selected');
    };

    this.redraw = function () {
        var list = this;
        if (this.lock) {
            setTimeout(function() {
                list.redraw();
            }, 10);
        } else {
            this.lock = true;
            var str = 'headers=true';
            if (this.filter != '') str = str + '&filter=' + this.filter;
            ajaxLoading(this.root);
            var aj = $.ajax({
                url: this.ajax_url,
                type: 'POST',
                data: str,
                success: function(transport) {
                    var result = transport;
                    if (typeof(result)=='undefined') {
                        dialog_alert(list.title, translate('An error occured when trying to load the data') + ':' + transport.responseText, '/images/icons/dialogs/error.png', '');
                    }
                    list.end = result.length;
                    list.pager.setLength(result.length);
                    list.item_width = result.item_width;
                    list.item_height = result.item_height;
                    list.captions = result.captions;
                    list.header = result;
                    list.calculateSize();
                    list.checkBuffer();
                    list.lock = false;
                },
                error: function(transport) {
                    dialog_alert(list.title, translate('An error occured when trying to load the data') + ':' + transport.responseText, '/images/icons/dialogs/error.png', '');
                    list.lock = false;
                }
            });
        }
    }

    var list = this;
    $(window).bind('changesize', function() {
        list.redraw();
    });

    window.onhashchange = function() {
        list.start = parseInt(location.hash.substring(1));
        if (isNaN(list.start)) list.start = 0;
        list.clearList(function() {
            list.redraw();
        });
    }
    this.lock = false;
}

function ajaxLoading(obj) {
    $(obj).empty();
    var div = $('<div/>', {
        style: 'text-align: center; vertical-align: middle; display: table-cell;'
    });
    div.width($(obj).width());
    div.height($(obj).height());
    div.appendTo(obj);
    var img = $('<img/>', {
        src: '/images/loading.gif',
        align: 'center'
    });
    img.appendTo(div);
}
