/*
* tinyselect
*
* licensed under mit license.
*
* @version 1.0.4
* @author pekka harjamäki
*/
;(function($) {
"use strict";
var tinyselect = {
/* ******************************************************************* *
* class initializers
* ******************************************************************* */
init: function($el, options) {
$el.data("tinyselectobj",this);
this.config = $.extend({
showsearch: true,
txtloading: "loading...",
txtajaxfailure: "error...",
dataurl: null,
dataparser: null
},options);
this.state = {
container: null,
selectbox: null,
itemcontainer: null,
searchcontainer: null,
searchbox: null,
$el: null,
open: false,
ajaxpending: false,
selectedvalue: -1,
originalitemdata: [],
filtereditemdata: []
};
this.readselect($el);
this.createselect($el);
},
createselect: function($el) {
// create container for select, search and options
this.state.container = $("
").
addclass("tinyselect").
css({ width: $el.css("width") });
// create the select element
this.state.selectbox = $("
").
addclass("selectbox").
on("click", { self:this }, this.onselectboxclicked );
this.state.container.append(this.state.selectbox);
// create container to hold search and results
this.state.dropdown = $("
").
addclass("dropdown").
hide();
this.state.container.append(this.state.dropdown);
// add search as first element
if(this.config.showsearch)
this.createsearch(this.state.dropdown);
// create ul to hold items
this.state.itemcontainer = $("").
addclass("itemcontainer");
this.state.dropdown.append(this.state.itemcontainer);
//
this.createitems();
// hide original select element and add new component to below
$el.hide().after(this.state.container);
this.state.$el = $el;
// hide select content when clicked elsewhere in the document
$(document).on("click", {self: this}, this.ondocumentclicked );
},
createitems: function(selected) {
var l1, opt;
// remove all
this.state.itemcontainer.empty();
//
for(l1=0; l1").
text( opt.text ).
addclass( "item" ).
attr( "data-value", opt.val );
if( opt.val == this.state.selectedvalue )
{
this.state.selectbox.html( opt.text );
newli.addclass("selected");
}
newli.on("click", { self:this }, this.onselectliclicked );
this.state.itemcontainer.append(newli);
}
},
createsearch: function($el) {
this.state.searchcontainer = $("
").
addclass("searchcontainer");
this.state.searchbox = $(" ").
addclass("searchbox").
on("click",function(e) { e.stoppropagation(); }).
on("keyup",{ self: this }, this.onsearchkeypress);
this.state.searchcontainer.append($(" "));
this.state.searchcontainer.append(this.state.searchbox);
this.state.dropdown.append(this.state.searchcontainer);
},
readselect: function($el) {
var self = this;
$el.find("option").each(function(index){
var opt = $(this);
self.state.originalitemdata.push({ val: opt.val() , text: opt.text() });
});
this.state.filtereditemdata = this.state.originalitemdata;
this.state.selectedvalue = $el.val();
},
setajaxindicator: function(failure) {
this.state.ajaxpending = true;
this.state.itemcontainer.empty();
if(this.state.searchcontainer !== null)
this.state.searchcontainer.hide();
var newli = $(" ");
if(!failure)
{
newli.text( this.config.txtloading ).
addclass( "loadindicator" );
} else {
newli.text( this.config.txtajaxfailure ).
addclass( "loaderrorindicator" );
}
this.state.itemcontainer.append(newli);
},
/* ******************************************************************* *
* event handlers
* ******************************************************************* */
ondocumentclicked: function(e) {
var self = e.data.self;
if( self.state.open )
self.onselectboxclicked(e);
},
onsearchkeypress: function(e) {
var self = e.data.self,
sval = $(e.currenttarget).val();
if(sval.length === 0)
{
self.state.filtereditemdata = self.state.originalitemdata;
} else {
self.state.filtereditemdata = self.state.originalitemdata.filter(function(item){
return item.text.tolowercase().indexof(sval) >= 0 ? true: false;
});
}
self.createitems();
},
onselectboxclicked: function(e) {
var self = e.data.self;
// do nothing, if currently animating
if(self.state.dropdown.is(":animated"))
return;
// close selectbox
if( self.state.open )
{
self.state.open = false;
self.state.selectbox.removeclass("open");
self.state.dropdown.slideup(100);
return;
}
// open selectbox
if(self.config.dataurl !== null)
{
self.setajaxindicator(false);
$.ajax({
url: self.config.dataurl,
datatype: "json",
type: "get"
}). done( function(data) { self.onajaxloadsuccess(self, data); } ).
fail( function(data) { self.onajaxloaderror(self, data); } );
}
self.state.open = true;
self.state.selectbox.addclass("open");
self.state.dropdown.slidedown(100);
},
onajaxloadsuccess: function(self,data) {
self.state.ajaxpending = false;
if(self.config.dataparser !== null )
{
data = self.config.dataparser(data, self.state.selectedvalue);
}
self.state.$el.empty();
data.foreach(function(v){
if(v.selected)
self.state.selectedvalue = v.val;
self.state.$el.append(
$(" ").
text( v.text ).
val( v.val )
);
});
self.state.$el.val( self.state.selectedvalue );
self.state.originalitemdata = data;
self.state.filtereditemdata = data;
if(this.state.searchcontainer !== null)
this.state.searchcontainer.show();
self.createitems();
},
onajaxloaderror: function(self,data) {
self.setajaxindicator(true);
},
onselectliclicked: function(e) {
var self = e.data.self,
item = $(e.currenttarget);
self.state.dropdown.find("li").each(function() {
$(this).removeclass("selected");
});
item.addclass("selected");
self.state.selectbox.html( item.text() );
self.state.selectedvalue = item.attr("data-value");
self.state.$el.val(self.state.selectedvalue);
self.state.$el.trigger("change");
},
/* ******************************************************************* *
* external callbacks
* ******************************************************************* */
};
/* ******************************************************************* *
* plugin main
* ******************************************************************* */
$.fn.tinyselect = function(options) {
if( typeof(options) != "undefined" )
{
}
return this.each(function(){
var sel = object.create(tinyselect);
sel.init( $(this) , options);
});
};
}(jquery));