var Select = new Class({
options: {
multiple: true,
elements: '',
filter: ['input', 'textarea'],
selected: false
},
Implements: [Events, Options],
initialize: function(options){
this.setOptions(options);
this.context = $(this.options.context) || document.body;
if(this.options.selected !== false)
this.select(this.options.selected);
this.context.addEvent('mouseup', (function(e){
if(this.isItem(e.target) && !this.options.filter.contains(e.target.get('tag'))){
var cel = e.target.bubble(this.getElements());
if(
this.options.multiple == 'freestyle' ||
(this.options.multiple && e.control && !e.shift)
){
this.toggle(cel);
this.anchor = cel;
} else if(this.options.multiple && e.shift){
if(!e.control)
this.unselectAll([this.anchor, cel]);
this.getElements().map(function(el, i){
if(
(
this.getIndex(this.anchor) < this.getIndex(cel) &&
i > this.getIndex(this.anchor) &&
i < this.getIndex(cel)
) || (
this.getIndex(this.anchor) > this.getIndex(cel) &&
i < this.getIndex(this.anchor) &&
i > this.getIndex(cel)
)
)
this.toggle(el);
}, this);
this.select(cel);
} else {
this.unselectAll(cel);
this.select(cel);
this.anchor = cel;
}
}
}).bind(this));
},
getElements: function(fn){
var els =  this.context.getElements(this.options.elements);
if(fn) return els.map(fn);
return els;
},
getElement: function(element){
if($type(element) == 'number')
return this.getElements()[element];
else if($type(element) == 'string'){
if(element == 'next')
dir = 1;
else if(element == 'previous')
dir = -1;
if(this.getSelection().length == 0){
if(dir == -1) i = this.getElements().length;
else i = -1;
}
else if(this.getIndex(this.getSelection()[0]) == this.getElements().length - 1 && dir == 1)
i = -1;
else if(this.getIndex(this.getSelection()[0]) == 0 && dir == -1)
i = this.getElements().length;
else
i = this.getIndex(this.getSelection()[0]);
return this.getElements()[i + dir];
}
},
getIndex: function(el){
return this.getElements().indexOf(el);
},
select: function(el){
var els;
if(el == 'next' || el == 'previous')
els = $splat(this.getElement(el));
else
els = $splat($type(el) == 'number' ? this.getElements()[el] : $$(el));
if(!this.options.multiple)
this.unselectAll(els);
els.each(function(el){
if(el.retrieve('selected') !== true){
el.store('selected', true).addClass('selected');
this.fireEvent('select', el);
this.fireEvent('change', el);
}
}, this);
},
unselect: function(el){
var el = $$(el);
if(el.length == 0)
return this.unselectAll();
el.store('selected', false).removeClass('selected');
this.fireEvent('unselect', el);
this.fireEvent('change', el);
},
unselectAll: function(exclude){
exclude = $splat(exclude);
this.getSelection().each(function(el){
if(!exclude.contains(el))
this.unselect(el);
}, this);
this.fireEvent('unselectAll');
},
toggle: function(el){
if(el.retrieve('selected'))
this.unselect(el);
else
this.select(el);
},
isItem: function(el){
var el = $(el);
return el.getParents().some(function(item){
return this.getElements().contains(item);
}, this) || this.getElements().contains(el);
},
getSelection: function(property, bind){
return this.getElements().filter(function(el){
return el.retrieve('selected');
}).map(function(el){
if($type(property) == 'string')
return el.get(property);
else if($type(property) == 'function')
return property.call(bind || this, el);
else return el;
}, bind || this);
},
getUnselection: function(){
return this.getElements().filter(function(el){
return !el.retrieve('selected');
});
}
});
