NHibernate+spring.net+jquery打造UI控件库(mvc+webform两种实现) combox,shadow控件的初步实现(包括键盘,过滤功能)(附代码下载)
如果这个控件不是已经着手几天了,本不打算写下去啦。既然完成啦,就发给大家用用吧。
效果图先上吧:没兴趣的就没必要看下去,免得浪费大家的时间
先说说阴影控件吧:
IE:<div class="sw-ie-shadow"></diiv>然后用滤镜过滤边缘
其他浏览器:
2 <div class="sh">
3 <div class="shl"></div>
4 <div class="shr"></div>
5 <div class="shc"></div>
6 </div>
7 <div class="sc">
8 <div class="scl"></div>
9 <div class="scr"></div>
10 <div class="scc"></div>
11 </div>
12 <div class="sf">
13 <div class="sfl"></div>
14 <div class="sfr"></div>
15 <div class="sfc"></div>
16 </div>
17 </div>
18
19
实现的目标:
$(div).shadow();返回一个shadow对象。
具体实现以下:
2 Sw.Namespace("$.sw");
3 $.fn.extend({
4 shadow: function(options) {
5 returnnew $.sw.shadow(this, options);
6 }
7 });
8 $.sw.shadow = Class({
9 container: null,
10 shadow: null,
11 template: $.browser.msie ?
12 '<div class="sw-ieshadow"></div>' :
13 '<div class="sw-shadow"><div class="sh"><divclass="shl"></div><div class="shr"></div><div class="shc"></div></div><div class="sc"><div class="scl"></div><div class="scr"></div><div class="scc"></div></div><div class="sf"><div class="sfl"></div><div class="sfr"></div><div class="sfc"></div></div></div>',
14 isRendered: $(".sw-ie-shadow").length >0|| $(".sw-shadow").length >0,
15 initialize: function(container, options) {
16 this.container = $(container);
17 if (!this.isRendered) { $(document.body).append(this.template); }
18 this.initComponent();
19 },
20 setPosition: function(element, val) {
21 var size = Sw.Size.fromElement(this.container, 2).add(val.width, val.height);
22 $(element).css({
23 top: parseInt($(this.container)[0].style.top) - val.top,
24 left: parseInt($(this.container)[0].style.left) - val.left,
25 height: size.height,
26 width: size.width,
27 zIndex: parseInt(this.container.css("zIndex")) - val.zIndex
28 });
29 },
30 show: function() { this.shadow.show(); },
31 hide: function() { this.shadow.hide(); },
32 initComponent: function() {
33 var me =this;
34 if ($.browser.msie) {
35 this.shadow = $("div.sw-ie-shadow").css("filter", "progid:DXImageTransform.Microsoft.alpha(opacity=30) progid:DXImageTransform.Microsoft.Blur(pixelradius=4)").hide();
36 this.setPosition(this.shadow, { top: 2, left: 4, height: -1, width: -1, zIndex: 1 });
37 }
38 else {
39 this.shadow = $("div.sw-shadow").hide();
40 this.setPosition(this.shadow, { top: 2, left: 3, height:6, width:6, zIndex: 1 });
41 $(".sc", this.shadow).children().andSelf().each(function() {
42 $(this).css("height", me.container.outerHeight() -4);
43 });
44 };
45 },
46 refresh: function() {
47
48 this.initComponent();
49 this.show();
50 }
51 });
52 })(jQuery);
53
下面先接着说说combox控件的实现吧
<div class="wrap">
<input>文本框</input><input>隐藏域</input><div>picker</div>
<div>
自然而然,我们的目标是:
$(input).combox(options)
其中的option { store: 数据源, selectedChange: 选中触发事件, selectedItem:默认选中项
具体用法,我示例有详细说明。
实现过程:
Sw.Namespace("$.sw");
$.fn.extend({
combox: function(options) {
returnnew $.sw.combox(this, options);
}
});
$.sw.combox = Class({
input: null,
hidField: false,
picker: null,
wrapper: null,
options: null,
store: null,
container: null,
shadow: null,
selectedItem: false,
textAlias: null,
valueAlias: false,
query: null,
initialize: function(input, options) {
this.input = $(input);
this.options = $.extend({}, $.sw.combox.defaults, options);
this.store =this.options.store;
this.initComponent(input);
},
initComponent: function() {
this.input.css("width", this.options.width).val(this.options.emptyText).focus(function() { $(this).val(""); });
this.wrapper = $(this.input).wrap("<div/>").parent().addClass(this.options.comboxCss);
if (this.options.hidField) {
this.hidField = $("<input/>").attr({ "id": "h"+this.input.attr("id"), "type": "hidden" }).appendTo(this.wrapper);
}
this.picker = $("<div />").hoverClass("picker-hover").appendTo(this.wrapper).addClass(this.options.pickerCss).css("left", this.input.width());
this.render();
this.addEvents();
},
render: function() {
if (this.store) {
var me =this;
this.textAlias = me.store.fields.text;
var maxWidth = [];
this.valueAlias = me.store.fields.value == undefined ?"" : me.store.fields.value;
this.container = $("<div/>").click(function(e) { Sw.stop(e); })
.width(Sw.Size.fromElement(this.input, 2).width +7).appendTo($(document.body));
this.options.autoHeight ?this.container.css("max-height", this.options.height) : this.container.css("height", this.options.height);
var listItems = $("<ul/>").appendTo(this.container);
$(this.store.data).each(function(index, item) {
maxWidth.push($("<li/>").hoverClass("hover").appendTo(listItems).html("<span>"+ item[me.textAlias] +"</span>").attr({ "stext": item[me.textAlias], "svalue": me.valueAlias ==""?"" : item[me.valueAlias] }).click(function(e) {
me.selectedChange(item); Sw.stop(e);
}).find("span").outerWidth());
});
maxWidth = maxWidth.sort(function(a, b) {
return a - b;
});
if (maxWidth[maxWidth.length -1] >=this.container.width()) {
$("li", this.container).width(maxWidth[maxWidth.length -1] +3);
}
this.container.addClass(this.options.containerCss);
if (this.options.selectedItem) {
this.selectedItem =this.getDefaultSeletecd(this.options.selectedItem);
this.renderSeletecd();
}
var size = Sw.Size.fromElement(this.input, 2);
var offset = Sw.Offset.fromElement(this.input).add(0, size.height).applyTo(this.container);
this.shadow =new $.sw.shadow(this.container);
//或者这样写也行this.shadow = $(this.container).shadow();
maxWidth = listItems = size = offset =null;
}
},
removeClass: function() {
$("li", this.container).removeClass("selected");
},
getDefaultSeletecd: function(defaultValue) {
if (this.valueAlias !="") {
return $(this.store.data).jget(defaultValue[this.valueAlias], this.valueAlias);
}
else {
return defaultValue;
}
},
renderSeletecd: function() {
if (this.selectedItem) {
this.setValue(this.selectedItem);
this.removeClass();
if (this.valueAlias !="") {
$("li[svalue='"+this.getValue() +"']", this.container).first().addClass("selected");
}
else {
$("li[stext='"+this.getText() +"']", this.container).first().addClass("selected");
}
}
},
hide: function() {
this.container.hide();
this.shadow.hide();
this.input.removeClass("focus");
this.picker.removeClass("picker-focus");
},
show: function() {
this.container.show();
$("ul li", this.container).show();
this.input.addClass("focus");
this.picker.addClass("picker-focus");
this.shadow.refresh();
this.shadow.show();
},
addEvents: function() {
var me =this;
this.wrapper.click(function() {
me.input.focus();
me.show();
$(document).one("click", function(event) {
me.hide();
});
returnfalse;
});
//key
this.input.keyup(function(e) {
me.onKeyup(e);
});
},
getSeletedItem: function() {
var currenSelected =this.container.children('ul').children('li.selected');
return currenSelected.length >0? currenSelected.first() : false;
},
prevResult: function() {
$currenSelected =this.getSeletedItem();
if ($currenSelected)
$currenSelected.removeClass("selected").prev("li:visible").addClass("selected");
else
$("ul li:visible", this.container).last().addClass("selected");
},
nextResult: function() {
$currenSelected =this.getSeletedItem();
if ($currenSelected)
$currenSelected.removeClass("selected").next("li:visible").addClass("selected");
else
$("ul li:visible", this.container).first().addClass("selected");
},
onKeyup: function(e) {
if ((/27$|38$|40$/.test(e.keyCode)) || (/^13$|^9$/.test(e.keyCode) &&this.getSeletedItem())) {
Sw.stop(e);
switch (e.keyCode) {
case Sw.keyCode.Up:
this.prevResult();
break;
case Sw.keyCode.Down:
this.nextResult();
break;
case13:
this.selectedResult();
break;
case Sw.keyCode.Esc:
this.hide();
break;
}
}
elseif (this.input.val() !=this.query) {
this.query =this.input.val();
this.filter();
}
},
filter: function() { //是否异步调用
if (this.options.async) { //do something()
}
else {
var reg =new RegExp('^'+this.query +'.*$', 'im');
$("ul li", this.container).each(function() {
if (reg.test($(this).attr("stext")))
$(this).show();
else
$(this).hide();
});
this.shadow.refresh();
}
},
setValue: function(item) {
this.input.val(item[this.textAlias]);
if (this.hidField &&this.valueAlias && item[this.valueAlias]) {
this.hidField.val(item[this.valueAlias]);
}
},
selectedResult: function() {
var text =this.textAlias;
var selectedResult =this.getSeletedItem();
var selectedItem ='{"'+this.textAlias +'":"'+ selectedResult.attr("stext") +'","'+this.valueAlias +'":"'+ selectedResult.attr("svalue") +'"}';
this.selectedChange($.parseJSON(selectedItem));
},
selectedChange: function(item) {
this.selectedItem = item;
this.renderSeletecd();
var evt =this.options.selectedChange;
if (evt && $.isFunction(evt)) {
evt.call(this, this.getText(), this.getValue());
}
evt =null;
this.hide();
},
getText: function() { returnthis.input.val(); },
getValue: function() { returnthis.hidField ?this.hidField.val() : ""; }
})
$.extend($.sw.combox, {
defaults: {
hidField: true,
comboxCss: "sw-combox",
pickerCss: "picker",
containerCss: "sw-combox-container",
emptyText: "select a value",
width: 100,
height: 200,
autoHeight: true,
filter: true,
async: false,
selectedChange: false,
store: false,
selectedItem: false
}
});
})(jQuery);
唉,终于写完啦,松了一口气。这也许是这个系列最后一篇啦。原因以下:
1.自定义表单的实现还要花很多精力
2.之前一年来没有参加代码的工作,对互联网技术的发展真的一头雾水,就像园友说的那样,哥竟不知jquery
已经有那么多的UI库啦,呵呵,自己还一个人在蛮搞。简直是闭门造车。
3.虽然只完成几个小控件,但我真的有身心疲惫的感觉,没有一点激情,动力
当然,有这方面兴趣的朋友,特别是有自定义表单设计的朋友,请多多交流。