sky.js/sky.controls.js

214 lines
4.6 KiB
JavaScript

(function(SKY,$){
var defOptions = {
type: null,
nullable: true,
lookup: function(pattern,response){}
};
class SkySelect {
constructor(element,options){
this.options = Object.assign({},defOptions);
Object.assign(this.options, options);
var self = this;
element = $(element);
element.data("skySelect", this);
this.element = element;
this.wrap = $("<div></div>");
this.element.appendTo(this.wrap);
this.popup = $("<div></div>")
.addClass("skyselect-popup")
.appendTo(this.wrap);
this.element
.on("keydown", function(ev){ self.onKeyDown(ev); } )
.on("focusin", function(ev){ self.onFocusIn(ev); } )
.on("focusout", function(ev){ self.onFocusOut(ev); } )
.on("dblclick", function(ev){
self.open();
self.update();
} );
this.type = SKY.type(this.options.type);
this.selectedItem = null;
this.activeItem = null;
this.timer = null;
}
html(){ return this.wrap; }
open(){ this.popup.slideDown(); this.isOpen = true; return this; }
close(){
if (this.isOpen)
{
clearInterval(this.timer);
this.popup.hide();
this.isOpen = false;
if (this.options.nullable && (this.element.val()==""))
{
this.selectedItem = null;
} else {
this.element.val(
this.selectedItem ? this.options.render(this.selectedItem) : ""
);
}
this.activeItem = null;
}
return this;
}
markCurrentSelected(){
var self = this;
var currentSelectedIdentity = self.options.type.identity(self.selectedItem);
this.popup.children(".skyselect-item").each(function(){
var li = $(this);
var item = li.data("skyselect-item");
if (self.options.type.identity(item) == currentSelectedIdentity)
li.addClass("selected");
else
li.removeClass("selected");
});
}
markActive(item){
var self = this;
var currentActiveIdentity = self.options.type.identity(item);
self.activeItem = item;
this.popup.children(".skyselect-item").each(function(){
var li = $(this);
var item = li.data("skyselect-item");
if (self.options.type.identity(item) == currentActiveIdentity)
li.addClass("active");
else
li.removeClass("active");
});
}
select(item){
this.close();
this.selectedItem = item;
this.element.val(this.options.type.render(item));
this.markCurrentSelected();
}
update(){
var self = this;
self.options.lookup(
self.element.val(),
function(items){
self.items(items);
}
);
}
items(items){
var self = this;
this.popup.empty();
$.each( items, function(){
var item = this;
var li = $("<div></div>")
.addClass("skyselect-item")
.append(self.options.type.render(this))
.appendTo(self.popup)
.data("skyselect-item", this)
.on("click", function(ev){
self.select( item );
} )
.on("hover", function(ev){
self.markActive(item);
});
})
this.markCurrentSelected();
}
onKeyDown(ev){
var self = this;
switch (ev.which)
{
case 27: // ESC
this.close();
break;
case 38: // UP
if (this.isOpen){
var currentActiveLi = $(".skyselect-item.active", this.popup);
if (currentActiveLi.length){
var nextLi = currentActiveLi.next(".skyselect-item");
if (nextLi.length)
{
}
} else {
var firstLi = this.popup.first("skyselect-item");
if (firstLi.length)
this.markActive(firstLi.data("skyselect-item"));
}
}
break;
case 40: // DOWN
if (this.isOpen){
var currentActiveLi = $(".skyselect-item.active", this.popup);
if (currentActiveLi.length){
var nextLi = currentActiveLi.next(".skyselect-item");
if (nextLi.length)
{
}
} else {
var firstLi = this.popup.first(".skyselect-item");
if (firstLi.length)
this.markActive(firstLi.data("skyselect-item"));
}
} else {
this.open();
}
break;
default:
console.log("ev.which=" + ev.which);
if ((ev.which >= 32))
{
clearInterval(this.timer);
this.timer = setInterval( function(){
self.update();
}, 250);
this.open();
}
break;
}
}
onFocusIn(ev){
this.element.select();
}
onFocusOut(ev){
var self = this;
setTimeout( function(){ self.close(); }, 100 );
}
}
$.fn.skySelect = function(options){
$.each( this, function(index,item){
var skySelect = $(item).data("skySelect");
if (!skySelect)
skySelect = new SkySelect(item,options);
});
if (this.length == 1)
return $(this).data("skySelect");
return this;
}
}( SKY, jQuery ));