function SearchPanel(root_selector, search_page_id)
{
    if($(root_selector).length > 0)
    {
        this.rs = root_selector;
        this.slide_speed = 500;
        this.search_page_id = search_page_id;
        this.order_by = "date";

        this.prepopulating_fields = {'term' : 'keyword search ...', 'date_from' : 'dd/mm/yyyy', 'date_to' : 'dd/mm/yyyy'};

        this.initLoader();
        this.init();
    }
}


SearchPanel.prototype.$ = function(selector)
{
    return $(this.$rel(selector));
}


SearchPanel.prototype.$rel = function(selector)
{
    return this.rs + ' ' + selector;
}


SearchPanel.prototype.initLoader = function()
{
    $('#search_loader').html('<p>. </p>');
}


SearchPanel.prototype.init = function()
{
    this.$('.onchange-dosubmit').bind('change', {searchpanel: this}, this.updateSubmit);
    this.$('.onchange-dosubmitissue').bind('change', {searchpanel: this}, this.updateSubmitIssue);
    this.$('.onclick-dosubmit').bind('click',   {searchpanel: this}, this.updateSubmit);
    this.$('.onclick-forcesubmit').bind('click',   {searchpanel: this, force: true}, this.updateSubmit);
    this.$('.onclick-doupdatepanels').bind('click',   {searchpanel: this}, this.updateDynamicPanels);

    this.initFormValues();
    this.initMainSlider();
    this.initSubSliders();
    this.initDatePickers();
    this.initLiveEvents();
    this.initClearSearchButtons();
    this.setActiveClassesForPanels();
}

SearchPanel.prototype.initFormValues = function()
{
    var fields = {
        'term' : 'keyword search ...'
    };

    if(jQuery.ui === undefined)
        jQuery.extend(fields, {'date_from' : 'dd/mm/yyyy', 'date_to' : 'dd/mm/yyyy'});

    for(f in fields)
    {
        var buildEvent = function(field, content, focus)
        {
            return (function(e){
                if(focus)
                {
                    $(field).each(function(){
                        if(this.value == content)
                            this.value = '';
                    });
                }
                else
                {
                    $(field).each(function(){
                        if(this.value == '')
                            this.value = content;
                    });
                }
            });
        };

        var fn1 = buildEvent(this.$rel('#' + f), fields[f], false);
        var fn2 = buildEvent(this.$rel('#' + f), fields[f], true);
        this.$('#' + f).bind('blur', fn1);
        this.$('#' + f).bind('focus', fn2);
    }
}


SearchPanel.prototype.initMainSlider = function()
{
    var buildToggleEvent = function(btn, slider, speed, bottom)
    {
        return ( function() {
                var cb = function()
                {
                    if($(slider).css('display') == 'none')
                    {
                        $(bottom).addClass('searchbot');
                        $(bottom).removeClass('searchbot1');
                    }
                    else
                    {
                        $(bottom).addClass('searchbot1');
                        $(bottom).removeClass('searchbot');
                    }
                }
                $(slider).slideToggle(speed, cb);
            });}

    var f = buildToggleEvent(this.$rel('#searchadv'), this.$rel('#advsearchcontainer'), this.slide_speed, this.$rel('#advsearchbottom'));

    this.$('#searchadv').bind('click', f);
}


SearchPanel.prototype.initSubSliders = function()
{
    var panels = {
        'slide_date_btn':'slide_date_pnl',
        'slide_issue_btn':'slide_issue_pnl',
        'slide_specific_btn':'slide_specific_pnl',
        'slide_category_btn':'slide_category_pnl',
        'slide_type_btn':'slide_type_pnl',
        'slide_publication_btn':'slide_publication_pnl'
    };

    for(p in panels)
    {
        var buildToggleEvent = function(btn, slider, speed) { return ( function() { $(slider).slideToggle(speed); if($(btn).hasClass('search1')) { $(btn).addClass('search2'); $(btn).removeClass('search1'); } else { $(btn).addClass('search1'); $(btn).removeClass('search2'); }});};
        var f = buildToggleEvent(this.$rel('#' + p), this.$rel('#'+panels[p]), this.slide_speed);
        this.$('#'+p).bind('click', f);
    }
}


SearchPanel.prototype.initDatePickers = function()
{
    var now = new Date();

    var options = {
        dateFormat: 'dd/mm/yy',
        showOn: 'both',
        buttonImage: '/assets/images/calender.gif',
        buttonImageOnly: true,
        minDate: new Date(2000,0,1),
        maxDate: new Date(now.getFullYear(), 11, 31),
        changeMonth: true,
        changeYear: true
    };

    $('#date_from').datepicker(options);
    $('#date_to').datepicker(options);

    // don't want people typing in these inputs
    $('#date_from').bind('keydown', function(){return false;});
    $('#date_from').bind('keyup', function(){return false;});
    $('#date_from').bind('keypress', function(){return false;});

    $('#date_to').bind('keydown', function(){return false;});
    $('#date_to').bind('keyup', function(){return false;});
    $('#date_to').bind('keypress', function(){return false;});
}


SearchPanel.prototype.initLiveEvents = function()
{
    // no longer live - not using 'ajax' search anymore
    var num_per_page = this.$rel('#limit');
    var from = this.$rel('#limitfrom');
    var panel = this;

    // when show ddl is updated we reset some params in the search panel and submit it
    var f = function() { var val = this.value; $(num_per_page).each(function(){this.value = val; }); $(from).each(function(){this.value = 0; }); panel.submit(); };
    $('#show_ddl').bind('change', f);

    // when order by is updated we reset some params then re-submit
    var that = this;
    var builder = function(that) { 
    	return function (event) { 
    		that.order_by = event.data.order; 
    		$('#order_by').val(event.data.order); 
    		panel.submit(); 
    	}; 
    };

    var changeOrder = builder(this);
    $('#order_by_date').bind('click', {order: 'date'}, changeOrder);
    $('#order_by_relevancy').bind('click', {order: 'relevancy'}, changeOrder);
}


SearchPanel.prototype.updateSubmit = function(e)
{
    var t = (e !== undefined)? e.data.searchpanel : this;

    t.clearSpecificIssueFields();

    t.$('#limitfrom').each(function(){this.value = 0});
    var search_page = t.search_page_id;
    t.$('#page_id').each(function(){this.value = search_page});
    t.setActiveClassesForPanels();

    if(e && e.data && e.data.force)
        t.submit();
}


SearchPanel.prototype.updateSubmitIssue = function(e)
{
    var t = (e !== undefined)? e.data.searchpanel : this;
    var filled = true;
    var allblank = true; // determines if all fields are blank

    $('.onchange-dosubmitissue').each(function() {if(this.value == '') { filled = false; } else { allblank = false; } });

    if(filled || allblank)
        t.updateSubmit();
}


SearchPanel.prototype.submit = function(e)
{
    var t = (e !== undefined)? e.data.searchpanel : this;

    t.$('').each(function() {this.submit()});
}


SearchPanel.prototype.updateDynamicPanels = function(e)
{
     var postvars = {};
     var t = e.data.searchpanel;

    // builds the kvp of postvars also allowing for things like 'somefield[]'
    t.$('input, select').each(function(){
        if((this.type == 'checkbox' || this.type == 'radio') && !this.checked)
            return;

        var field_name = this.name;

        if(field_name.indexOf('[]') > 0)
        {
            field_name = field_name.split('[')[0];
            var ctr = 0;
            for(p in postvars)
                ctr = (p.indexOf(field_name + '[') === 0)? ctr+1 : ctr;
            field_name += '[' + ctr + ']';
        }

        var value = this.value;

        if(t.prepopulating_fields[field_name] !== undefined && value == t.prepopulating_fields[field_name])
            value = '';

        postvars[field_name] = value;
    });

    var post_update_builder = function(css_constraint, reload_criteria_display)
    {
        return function()
        {
            t.$('' + css_constraint + ' .onchange-dosubmit').bind('change', {searchpanel: t}, t.updateSubmit);
            t.$('' + css_constraint + ' .onclick-dosubmit').bind('click',   {searchpanel: t}, t.updateSubmit);

            if(reload_criteria_display)
                t.setActiveClassesForPanels();
        };
    }

    $('#slide_type_pnl').load('/scripts/ajax/searchpanel.php?random=random', $.extend({'mode':'typ'}, postvars), post_update_builder('#slide_type_pnl', false));
    $('#slide_category_pnl').load('/scripts/ajax/searchpanel.php?random=random', $.extend({'mode':'cat'}, postvars), post_update_builder('#slide_category_pnl', true));
}



SearchPanel.prototype.clearSpecificIssueFields = function()
{
        this.$('.onchange-dosubmitissue').each(function(){
            for(var i = 0, limit = this.options.length; i < length; i++)
                this.options[i].selected = false;
            this.selectedIndex = 0;
        });
}


SearchPanel.prototype.initClearSearchButtons = function()
{
    var search_object = this;

    var f = function()
    {
        var btn_id = this.parentNode.id;
        var pnl_id = btn_id.replace('btn', 'pnl');

        // close the scope on these vars
        var g = function(btn_id, pnl_id)
        {
            // click event for clear search
            return function()
            {
                $('#' + pnl_id + ' input, #' + pnl_id + ' select').each(function() {
                    if(this.tagName.toLowerCase() == 'input')
                    {
                        if(this.type == 'text')
                            this.value = '';
                        else if(this.type == 'checkbox' || this.type == 'radio')
                            this.checked = false;
                    }
                    else if(this.tagName.toLowerCase() == 'select')
                    {
                        this.selectedIndex = 0;
                    }
                });

                search_object.updateSubmit();

                return false;
            };
        };

        $(this).bind('click', g(btn_id, pnl_id));
    }


    $('.action-clearSearch').each(f);

    this.initClearFiltersButton();
}

/**
 * Sets classes on panels to state whether they have active input elements or not
 * used as part of clear search functionality to highlight whether panel has
 * active criteria to the user
 *
 * Now also lists active filters
 */
SearchPanel.prototype.setActiveClassesForPanels = function()
{
    var that = this;

    this.clearUiFilters();
    var showFilters = false;

    var f = function()
    {
        var btn_id = this.parentNode.id;
        var pnl_id = btn_id.replace('btn', 'pnl');

        var hasActivePanel = false;

        $('#' + pnl_id + ' input, #' + pnl_id + ' select').each(function()
        {
            var hasActive = false;
            if(this.tagName.toLowerCase() == 'input')
            {
                if(this.type == 'text' && (this.value != '' && this.value != 'dd/mm/yyyy'))
                    hasActive = true;
                else if((this.type == 'checkbox' || this.type == 'radio') && (this.checked == true))
                    hasActive = true;
            }

            if(hasActive)
            {
                hasActivePanel = true;
                that.addUiFilterOption(this);
            }
        });

        if(hasActivePanel)
        {
            $('#' + btn_id).addClass('active-fields');
            showFilters = true;
        }
        else
        {
            $('#' + btn_id).removeClass('active-fields');
        }
    }

    $('.action-clearSearch').each(f);

    if(showFilters)
        $('#filters').show();
    else
        $('#filters').hide();
}


/**
 * Adds a filter to the ui list for the element
 */
SearchPanel.prototype.addUiFilterOption = function(elm)
{
    // bit of effort to work the filter name out based off the html structure
    // but worth the effort to save on data suplication

    var name = null;
    var value = null;
    var that = this;

    this.$('label[for=' + elm.id + ']').each(function() {
        value = $(this).text();
        var pnl = this.parentNode;

        while(pnl.tagName.toLowerCase() != 'form') // quick escape to save going to the top of the dom
        {
            if($(pnl).hasClass('newf'))
            {
                var btn = $('#' + pnl.id.replace('_pnl', '_btn'));
                btn.each(function(){
                    name = $(this).text().replace('Search by ', '');
                    name = name.substr(0,1).toUpperCase() + name.substr(1);
                });
                break;
            }
            else
                pnl = pnl.parentNode;
        }
    });

    if(name !== null && value !== null) // valid filter
    {
        var ul = this.$('#filters_list');
        var li = $('<li><strong>' + name + ': </strong>' + value + '<span></span></li>');

        li.bind('click', function() {
            if(elm.type == 'text')
                elm.value = '';
            else if(elm.type == 'checkbox' || elm.type == 'radio')
                elm.checked = false;

            that.setActiveClassesForPanels();
        });


        li.appendTo(ul);
    }
}


SearchPanel.prototype.clearUiFilters = function()
{
    var fl = this.$('#filters_list');
    fl.html('');
}


SearchPanel.prototype.resetFilters = function()
{
    this.$('input[type=text], input[type=checkbox], input[type=radio]').each(function(){
        if(this.type.toLowerCase() == 'text')
        {
            this.value = '';
        } else if(this.type.toLowerCase() == 'checkbox' || this.type.toLowerCase() == 'radio')
        {
            this.checked = false;
        }
    });

    this.clearSpecificIssueFields();

    this.setActiveClassesForPanels();
}

SearchPanel.prototype.initClearFiltersButton = function()
{
    var that = this;
    this.$('.clearcriteria').bind('click', function(){that.resetFilters()});
}