// BehaviorShow : Shows or hides the element based on the result of 'test', also runs 'action'
var BehaviorShow = GenericBehavior.create('BehaviorShow', {
    onDraw: function(event) {
        event.elem = this.e;
        if (this.args.test(event)) {
            if (this.args.action) { this.args.action(event); }
            this.e.show();
        } else {
            this.e.hide();
        }
    }
});

// BehaviorRollover : Standard rollover, where the on and off states contain on and off within the image name
var BehaviorRollover = GenericBehavior.create('BehaviorRollover', {
	onAttach: function(event, elem, args) {
		this.tellSuper('onAttach', event, elem, args);
        return this.onAltered(event);
    },
    onAltered: function(event) {
        var src = this.e.src;
        var bits = src.match(/^(.*)_(on|off)\.(.*?)$/);
        if ( bits == null ) { return false; }
        this.src_base = bits[1];
        this.src_extension = bits[3];
        var preload = new Image();
        preload.src = this.src_base + '_on.' + this.src_extension;
        return true;
     },
	onmouseover: function(event) {
        this.selected = true;
        this.onDraw(event);
	},
	onmouseout: function(event) {
        this.selected = false;
        this.onDraw(event);
	},
    onDraw: function(event) {
        if (this.e.hasClassName('selected')) { this.selected = true; }
        if (this.selected) {
            this.e.src = this.src_base + '_on.' + this.src_extension;
        }
        else{
            this.e.src = this.src_base + '_off.' + this.src_extension;
        }
        this.selected = false;
    }
});


// BehaviorRadioGroup : Elements in the same set will act in a mutually exclusive manner.  The on: function will be called when an element is clicked, and the off: function of all the other elements will be called.  The state: parameter determines the element's initial state.
var BehaviorRadioGroup = GenericBehavior.create('BehaviorRadioGroup', {
    onAttach: function(event, elem, args) {
		this.tellSuper('onAttach', event, elem, args);
        this.addToSet(args.set);
        this.state = this.args.state;
        this.new_state = null;
        return true;
    },
    onclick: function(evt) {
        this.new_state = true;
        this.tellMySet('setState', false);
        this.tellMySet('onDraw', evt);
    },
    setState: function(state) {
        if (this.new_state != null) { state = this.new_state; }
        this.state = state;
        this.new_state = null;
    },
    onDraw: function(evt) {
        var me = this;
        this.state ? this.args.on(me) : this.args.off(me);
    }
});




// BehaviorShowMenu : Shows a menu div below the given element when it is rolled over.
var BehaviorShowMenu = GenericBehavior.create('BehaviorShowMenu', {
    onAttach: function(event, elem, args) {
		this.tellSuper('onAttach', event, elem, args);
        Object.applyDefaults(args, {
           menu_id: this.e.id + '_menu',
           attach_position: 'bottom',
           set: 'default'
        });
        
        // find the menu div
        this.menu_id = args.menu_id || this.e.id + '_menu';
        this.menu = el(this.menu_id);
        if (!this.menu) { return false; }
        this.menu.hide();
                
        // add to menu set
        this.addToSet(args.set);
        
        // setup the rollovers
        this.menu.addBehavior(this.hider, {show_menu: this});         this.onAltered(event);
        this.within = 0;
        GenericEventManager.addIdleObserver(this);
                
        return true;
    },
    onAltered: function(event) {
        BehaviorRollover.prototype.onAltered.call(this, event);

        // position it by menu title
        var pos = Position.positionedOffset(this.e);
        this.menu.style.position = 'absolute';
        this.menu.style.left = pos[0] + 'px';
        this.menu.style.top = pos[1] + this.e.getHeight() + 'px';
    },
	onmouseover: function(event) {
        this.within = 1;
        this.tellSet(this.set, 'drawMenu', event);
	},
    onmouseout: function(event) {
        this.within = 0;
    },
    onIdle: function(event) {
        if (this.within != this.lastwithin) { 
            this.drawMenu(event);
        }
    },
    onDraw: function(event) {
        if (this.e.hasClassName('selected')) {
            newsrc = this.src_base + '_on.' + this.src_extension;
        }
        else {
            newsrc = this.src_base + '_off.' + this.src_extension;
        }
        if (this.e.src != newsrc) { this.e.src = newsrc; }
        this.within = false;
        this.drawMenu(event);
    },
    drawMenu: function(event) {
        this.onAltered(event);
        var newsrc;
        if (this.within) {
            this.menu.show();
            newsrc = this.src_base + '_on.' + this.src_extension;
        } else {
            this.menu.hide();
            if (!this.e.hasClassName('selected'))
                newsrc = this.src_base + '_off.' + this.src_extension;
        }
        if (newsrc && this.e.src != newsrc) { this.e.src = newsrc; }
        this.lastwithin = this.within;
    }
});
BehaviorShowMenu.prototype.hider = GenericBehavior.create('BehaviorShowMenu.hider', {
	onAttach: function(event, elem, args) {
        this.e = elem;
        this.show_menu = args.show_menu;
        return true;
    },
    onmouseover: function(event) {
        this.show_menu.within = 1;
    },
    onmouseout: function(event) {
        this.show_menu.within = 0;
    }
});



// Manages a div containing elements for pagination
var BehaviorPagination = GenericBehavior.create('BehaviorPagination', {
    onAttach: function(event, elem, args) {
		this.tellSuper('onAttach', event, elem, args);
        this.addToSet(args.set);
        this.snapshot();
        return true;
    },
    onDraw: function(event) {
        var me = this;
        var args = me.args;

        me.page_num = $val(args.page_num) || 1;
        me.num_items = $val(args.num_items) || 1;
        me.items_per_page = $val(args.items_per_page) || 1;
        me.selected_page_class = $val(args.selected_page_class); 
        me.next = me.e.el(args.next);
        me.prev = me.e.el(args.prev);
        me.all = me.e.el(args.all);
        me.number = me.e.el(args.number);
        me.number_holder = me.e.el(args.number_holder) || me.number.parentNode;
        me.action = args.action;
        
        me.num_pages = Math.ceil(me.num_items / me.items_per_page);
        
        me.num_pages > 1 ? me.e.show() : me.e.hide();
 
        if (event.args) {
            me.page_num = event.args.page_num || me.page_num;
        }
        
        me.number_list = me.number_holder.addBehavior(BehaviorLooper, {
            data: GenericUtil.filledArray(me.num_pages, 1),
            repeat: me.number,
            action: function(a) {
               var index = a.index;
               if (index+1 == me.page_num) { 
                    a.node.addClassName(me.selected_page_class);
               }
               a.node.innerHTML = index + 1;
               a.node.onclick = me.gotopage_func(index + 1);
            }
        });
        if (me.page_num == 'all') {
            me.all.addClassName(me.selected_page_class);
        }
        
        me.prev_page_num = 
            (me.page_num > 1) ? me.page_num - 1 : 1;
        me.next_page_num =
            (me.page_num < me.num_pages) ? me.page_num + 1 : me.num_pages;

        me.next.onclick = me.gotopage_func(me.next_page_num);
        me.prev.onclick = me.gotopage_func(me.prev_page_num);
        me.all.onclick = me.gotopage_func('all');
        
        me.number_list.onDraw(event);
    },    
    gotopage_func: function (pagenum) {
        var me = this;
        return function(event) {
            me.action(pagenum);
            me.page_num = pagenum;
            me.tellSet(me.set, 'onRedraw', {args: {page_num: pagenum}});
        };
    }
});




// Input box with default text that clears when the box gains focus
var BehaviorTextBoxClear = GenericBehavior.create('BehaviorTextBoxClear', {
    onAttach: function(event, elem, args) {
		this.tellSuper('onAttach', event, elem, args);
        this.args.blanktext = this.args.blanktext || this.e.value;
        return true;
    },
    onfocus: function(event) {
        if (this.e.value == this.args.blanktext) {
          this.e.value = "";
        }
        return true;
    },
    onblur: function(event) {
        if (this.e.value == '') {
            this.e.value = this.args.blanktext;
        }
        return true;
    }
});


// Limit the number of characters in a textarea

var BehaviorTextAreaMaxLength_forcemax = function(event) {
    var maxlength = this.args.maxlength || this.e.getAttribute('maxlength');
    if (this.args.counter) { 
        this.args.counter.innerHTML = maxlength - this.e.value.length;
    }
    if (this.e.value.length > maxlength) {
        this.e.value = this.e.value.substr(0, maxlength);
        return false;
    }
    return true;
};
var BehaviorTextAreaMaxLength = GenericBehavior.create('BehaviorTextAreaMaxLength', {
    onIdle: BehaviorTextAreaMaxLength_forcemax,
    onchange: BehaviorTextAreaMaxLength_forcemax,
    onkeyup: BehaviorTextAreaMaxLength_forcemax,
    onDraw: BehaviorTextAreaMaxLength_forcemax
});



var GenericProgress = Class.create();
Object.extend(GenericProgress.prototype, {
    initialize: function(args) {
        this.args = args;
    },
    onDraw: function() {
        var args = this.args;
        var container = el(args.container);
        var background = el(args.background);
        var indicator = el(args.indicator);
        
        var container_loc = Position.cumulativeOffset(container);
        var top = container_loc[1];
        var left = container_loc[0];
        
        var dims = EL.getDimensions(container);
        background.style.top = top+'px';
        background.style.left = left+'px';
        background.style.width = (dims.width) + 'px';
        background.style.height = (dims.height) + 'px';
        var indicator_dims = EL.getDimensions(indicator);
        indicator.style.top = 
            top + ((dims.height - indicator_dims.height) / 2) + 'px';
        indicator.style.left = 
            left + ((dims.width - indicator_dims.width) / 2) + 'px';
            
        background.style.display = 'block';
        indicator.style.display = 'block';
    },
    onClear: function() {
        var args = this.args;
        var background = el(args.background);
        var indicator = el(args.indicator);    

        background.style.display = 'none';
        indicator.style.display = 'none';
    },
    onStart: function() {
        this.onDraw();
    },
    onComplete: function() {
        this.onClear();
    },
    onException: function() {
        this.onClear();
    },
    onFailure: function() {
        this.onClear();
    },
    onTimeout: function() {
        this.onClear();
    }
});

