easyui源码翻译1.32--Combo(自定义下拉框)

时间:2023-03-08 20:52:47

前言

扩展自$.fn.validatebox.defaults。使用$.fn.combo.defaults重写默认值对象。下载该插件翻译源码

自定义下拉框显示一个可编辑的文本框和下拉面板在html页面。这是构建其他复杂的组合部件(如:combobox,combotree,combogrid等)之前需要构建的最基本的组件

依赖关系

  • validatebox
  • panel

源码

/**
* jQuery EasyUI 1.3.2
*
*翻译:qq 1364386878 自定义下拉框
*/
(function ($) {
//调整组件宽度
function _resize(jq, width) {
var opts = $.data(jq, "combo").options;
var combo = $.data(jq, "combo").combo;
var panel = $.data(jq, "combo").panel;
if (width) {
opts.width = width;
}
if (isNaN(opts.width)) {
var c = $(jq).clone();
c.css("visibility", "hidden");
c.appendTo("body");
opts.width = c.outerWidth();
c.remove();
}
combo.appendTo("body");
var combotext = combo.find("input.combo-text");
var comboarrow = combo.find(".combo-arrow");
var arrowWidth = opts.hasDownArrow ? comboarrow._outerWidth() : 0;//下拉箭头宽度
combo._outerWidth(opts.width)._outerHeight(opts.height);
combotext._outerWidth(combo.width() - arrowWidth);
combotext.css({ height: combo.height() + "px", lineHeight: combo.height() + "px" }); comboarrow._outerHeight(combo.height());
panel.panel("resize", {
width: (opts.panelWidth ? opts.panelWidth : combo.outerWidth()),
height: opts.panelHeight
});
combo.insertAfter(jq);
};
//是否显示下拉箭头
function setDownArrow(jq) {
var opts = $.data(jq, "combo").options;
var combo = $.data(jq, "combo").combo;
if (opts.hasDownArrow) {
combo.find(".combo-arrow").show();
} else {
combo.find(".combo-arrow").hide();
}
};
// 渲染组件
function renderCombo(target) {
$(target).addClass("combo-f").hide();
var combo = $("<span class=\"combo\"></span>").insertAfter(target);
var text = $("<input type=\"text\" class=\"combo-text\">").appendTo(combo);//将text框添加到combo
$("<span><span class=\"combo-arrow\"></span></span>").appendTo(combo);//将下来箭头添加到combo
$("<input type=\"hidden\" class=\"combo-value\">").appendTo(combo);//将隐藏域添加到combo以存放combo的value
var combpanel = $("<div class=\"combo-panel\"></div>").appendTo("body");//将下来面板添加到body
//设置下拉面板
combpanel.panel({
doSize: false,
closed: true,
cls: "combo-p",
style: { position: "absolute", zIndex: 10 },
onOpen: function () {
$(this).panel("resize");
}
});
var name = $(target).attr("name");
if (name) {
combo.find("input.combo-value").attr("name", name);
$(target).removeAttr("name").attr("comboName", name);
}
text.attr("autocomplete", "off");//关闭自动完成
return { combo: combo, panel: combpanel };
};
//销毁Combo
function _destroy(jq) {
var textBox = $.data(jq, "combo").combo.find("input.combo-text");
textBox.validatebox("destroy");
$.data(jq, "combo").panel.panel("destroy");
$.data(jq, "combo").combo.remove();
$(jq).remove();
};
//绑定事件
function bindEvents(jq) {
var combo = $.data(jq, "combo");
var opts = combo.options;
var combo2 = $.data(jq, "combo").combo;
var panel = $.data(jq, "combo").panel;
var combotext = combo2.find(".combo-text");
var comboarrow = combo2.find(".combo-arrow");//下拉箭头
$(document).unbind(".combo").bind("mousedown.combo", function (e) {
//鼠标点击combo外,关闭选择面板
var p = $(e.target).closest("span.combo,div.combo-panel");
if (p.length) {
return;
}
var combopanel = $("body>div.combo-p>div.combo-panel");
combopanel.panel("close");
});
//移除事件处理器
combo2.unbind(".combo");
panel.unbind(".combo");
combotext.unbind(".combo");
comboarrow.unbind(".combo");
//若组件未禁用,添加以下事件处理器
if (!opts.disabled) {
combotext.bind("mousedown.combo", function (e) {
$("div.combo-panel").not(panel).panel("close");
////该方法将停止事件的传播,阻止它被分派到其他 Document节点,
e.stopPropagation();
}).bind("keydown.combo", function (e) {
switch (e.keyCode) {
case 38://小键盘上箭头
opts.keyHandler.up.call(jq);
break;
case 40://小键盘下箭头
opts.keyHandler.down.call(jq);
break;
case 13://Enter键
e.preventDefault();
opts.keyHandler.enter.call(jq);
return false;
case 9://Tab键
case 27://Esc键
hidePanel(jq);
break;
default:
if (opts.editable) {
if (combo.timer) {
clearTimeout(combo.timer);
}
combo.timer = setTimeout(function () {
var q = combotext.val();
if (combo.previousValue != q) {
combo.previousValue = q;
$(jq).combo("showPanel");
opts.keyHandler.query.call(jq, combotext.val());
_validate(jq, true);
}
}, opts.delay);
}
}
});
//下拉箭头绑定事件
comboarrow.bind("click.combo", function () {
if (panel.is(":visible")) {
hidePanel(jq);
} else {
$("div.combo-panel").panel("close");
$(jq).combo("showPanel");
}
combotext.focus();
}).bind("mouseenter.combo", function () {
$(this).addClass("combo-arrow-hover");
}).bind("mouseleave.combo", function () {
$(this).removeClass("combo-arrow-hover");
}).bind("mousedown.combo", function () {
});
}
};
//showPanel
function _showPanel(jq) {
var opts = $.data(jq, "combo").options;
var combo = $.data(jq, "combo").combo;
var panel = $.data(jq, "combo").panel;
if ($.fn.window) {
//若放在窗口里面,则显示在窗口之上
panel.panel("panel").css("z-index", $.fn.window.defaults.zIndex++);
}
panel.panel("move", {
left: combo.offset().left,
top: getOffsetTop()
});
if (panel.panel("options").closed) {
panel.panel("open");
opts.onShowPanel.call(jq);
}
(function () {
if (panel.is(":visible")) {
panel.panel("move", {
left: getOffsetLeft(),
top: getOffsetTop()
});
setTimeout(arguments.callee, 200);
}
})();
//* 获取Left位置
function getOffsetLeft() {
var left = combo.offset().left;
if (left + panel._outerWidth() > $(window)._outerWidth() + $(document).scrollLeft()) {
left = $(window)._outerWidth() + $(document).scrollLeft() - panel._outerWidth();
}
if (left < 0) {
left = 0;
}
return left;
};
// 获取TOP位置
function getOffsetTop() {
var top = combo.offset().top + combo._outerHeight();
if (top + panel._outerHeight() > $(window)._outerHeight() + $(document).scrollTop()) {
top = combo.offset().top - panel._outerHeight();
}
if (top < $(document).scrollTop()) {
top = combo.offset().top + combo._outerHeight();
}
return top;
};
};
// 隐藏下拉选择面板
function hidePanel(jq) {
var opts = $.data(jq, "combo").options;
var panel = $.data(jq, "combo").panel;
panel.panel("close");
opts.onHidePanel.call(jq);
};
//校验值
function _validate(jq, tag) {
var opts = $.data(jq, "combo").options;
var textBox = $.data(jq, "combo").combo.find("input.combo-text");
textBox.validatebox(opts);
if (tag) {
textBox.validatebox("validate");
}
};
// 设置禁用/启用组件样式
function _disable(jq, disabled) {
var opts = $.data(jq, "combo").options;
var combo = $.data(jq, "combo").combo;
if (disabled) {
opts.disabled = true;
$(jq).attr("disabled", true);
combo.find(".combo-value").attr("disabled", true);
combo.find(".combo-text").attr("disabled", true);
} else {
opts.disabled = false;
$(jq).removeAttr("disabled");
combo.find(".combo-value").removeAttr("disabled");
combo.find(".combo-text").removeAttr("disabled");
}
};
// 清空combo值
function _clear(jq) {
var opts = $.data(jq, "combo").options;
var combo = $.data(jq, "combo").combo;
if (opts.multiple) {
combo.find("input.combo-value").remove();
} else {
combo.find("input.combo-value").val("");
}
combo.find("input.combo-text").val("");
};
//获取text值
function _getText(jq) {
var combo = $.data(jq, "combo").combo;
return combo.find("input.combo-text").val();
};
//设置text值
function _setText(jq, text) {
var combo = $.data(jq, "combo").combo;
combo.find("input.combo-text").val(text);
_validate(jq, true);
$.data(jq, "combo").previousValue = text;
};
//获取值(多选)
function _getValues(jq) {
var values = [];
var combo = $.data(jq, "combo").combo;
combo.find("input.combo-value").each(function () {
values.push($(this).val());
});
return values;
};
//设置值(多选)
function _setValues(jq, values) {
var opts = $.data(jq, "combo").options;
var nowValues = _getValues(jq);//获取当前值数组
var combo = $.data(jq, "combo").combo;
combo.find("input.combo-value").remove();//清空原来的值
var name = $(jq).attr("comboName");
for (var i = 0; i < values.length; i++) {
var _4c = $("<input type=\"hidden\" class=\"combo-value\">").appendTo(combo);
if (name) {
_4c.attr("name", name);
}
_4c.val(values[i]);
}
var tmp = [];
for (var i = 0; i < nowValues.length; i++) {
tmp[i] = nowValues[i];
}
var aa = [];
for (var i = 0; i < values.length; i++) {
for (var j = 0; j < tmp.length; j++) {
if (values[i] == tmp[j]) {
aa.push(values[i]);
//splice()方法用于插入、删除或替换数组的元素,详细参考http://www.w3school.com.cn/js/jsref_splice.asp
tmp.splice(j, 1);
break;
}
}
}
////若设置值数组与原值数组不相等,则将设置值数组、原值数组返回给onChange事件作为参数,并响应事件
if (aa.length != values.length || values.length != nowValues.length) {
if (opts.multiple) {
opts.onChange.call(jq, values, nowValues);
} else {
opts.onChange.call(jq, values[0], nowValues[0]);
}
}
};
//获取值(单选)
function _getValue(jq) {
var values = _getValues(jq);
return values[0];
};
//设置值(单选)
function _setValue(jq, value) {
_setValues(jq, [value]);
};
//初始化combo值
function initValue(jq) {
var opts = $.data(jq, "combo").options;
var fn = opts.onChange;
opts.onChange = function () { };
//如果设置多选
if (opts.multiple) {
if (opts.value) {
if (typeof opts.value == "object") {
_setValues(jq, opts.value);
} else {
_setValue(jq, opts.value);
}
} else {
_setValues(jq, []);
}
opts.originalValue = _getValues(jq);
} else {
_setValue(jq, opts.value);
opts.originalValue = opts.value;
}
opts.onChange = fn;
};
//实例化下拉框
$.fn.combo = function (target, parm) {
if (typeof target == "string") {
return $.fn.combo.methods[target](this, parm);
}
target = target || {};
return this.each(function () {
var combo = $.data(this, "combo");
if (combo) {
$.extend(combo.options, target);
} else {
var r = renderCombo(this);
combo = $.data(this, "combo", {
options: $.extend({},
$.fn.combo.defaults,
$.fn.combo.parseOptions(this),
target),
combo: r.combo,
panel: r.panel,
previousValue: null
});
$(this).removeAttr("disabled");
}
$("input.combo-text", combo.combo).attr("readonly", !combo.options.editable);
setDownArrow(this);//设置是否显示下拉箭头
_disable(this, combo.options.disabled);//设置是否禁用
_resize(this);
bindEvents(this);
_validate(this);
initValue(this);//初始化combo值
});
};
//默认方法
$.fn.combo.methods = {
//返回属性对象
options: function (jq) {
return $.data(jq[0], "combo").options;
},
//返回下拉面板对象
panel: function (jq) {
return $.data(jq[0], "combo").panel;
},
//返回文本框对象
textbox: function (jq) {
return $.data(jq[0], "combo").combo.find("input.combo-text");
},
//销毁该组件
destroy: function (jq) {
return jq.each(function () {
_destroy(this);
});
},
// 调整组件宽度
resize: function (jq, width) {
return jq.each(function () {
_resize(this, width);
});
},
//显示下拉面板
showPanel: function (jq) {
return jq.each(function () {
_showPanel(this);
});
},
//隐藏下拉面板
hidePanel: function (jq) {
return jq.each(function () {
hidePanel(this);
});
},
//禁用组件
disable: function (jq) {
return jq.each(function () {
_disable(this, true);
bindEvents(this);
});
},
//启用组件
enable: function (jq) {
return jq.each(function () {
_disable(this, false);
bindEvents(this);
});
},
//验证输入的值
validate: function (jq) {
return jq.each(function () {
_validate(this, true);
});
},
//返回验证结果
isValid: function (jq) {
var combo = $.data(jq[0], "combo").combo.find("input.combo-text");
return combo.validatebox("isValid");
},
//清除控件的值
clear: function (jq) {
return jq.each(function () {
_clear(this);
});
},
//重置控件的值
reset: function (jq) {
return jq.each(function () {
var opts = $.data(this, "combo").options;
if (opts.multiple) {
$(this).combo("setValues", opts.originalValue);
} else {
$(this).combo("setValue", opts.originalValue);
}
});
},
//获取输入的文本
getText: function (jq) {
return _getText(jq[0]);
},
//设置输入的文本
setText: function (jq, text) {
return jq.each(function () {
_setText(this, text);
});
},
//获取组件值的数组
getValues: function (jq) {
return _getValues(jq[0]);
},
//设置组件值的数组
setValues: function (jq, values) {
return jq.each(function () {
_setValues(this, values);
});
},
//获取组件的值
getValue: function (jq) {
return _getValue(jq[0]);
},
//设置组件的值
setValue: function (jq, value) {
return jq.each(function () {
_setValue(this, value);
});
}
};
//解析器 定义属性转化为options
$.fn.combo.parseOptions = function (target) {
var t = $(target);
return $.extend({}, $.fn.validatebox.parseOptions(target),
$.parser.parseOptions(target, ["width", "height", "separator",
{ panelWidth: "number", editable: "boolean", hasDownArrow: "boolean", delay: "number" }]),
{
panelHeight: (t.attr("panelHeight") == "auto" ? "auto" : parseInt(t.attr("panelHeight")) || undefined),
multiple: (t.attr("multiple") ? true : undefined),
disabled: (t.attr("disabled") ? true : undefined),
value: (t.val() || undefined)
});
};
//默认属性和事件
$.fn.combo.defaults = $.extend({}, $.fn.validatebox.defaults, {
width: "auto",//组件的宽度
height: 22,//组件的高度
panelWidth: null,//下拉面板宽度
panelHeight: 200,//下拉面板高度
multiple: false,//定义是否支持多选
separator: ",",//在多选的时候使用何种分隔符进行分割
editable: true,//定义用户是否可以直接输入文本到字段中
disabled: false,//定义是否禁用字段
hasDownArrow: true,//定义是否显示向下箭头按钮。
value: "",//字段的默认值
delay: 200,//最后一次输入事件与执行搜索之间的延迟间隔(执行自动完成功能的延迟间隔)
//在用户按下键的时候调用一个函数
keyHandler: {
up: function () {},
down: function () {},
enter: function () {},
query: function (q) {}
},
//当下拉面板显示的时候触发
onShowPanel: function () {},
//当下拉面板隐藏的时候触发
onHidePanel: function () {},
//当字段值改变的时候触发
onChange: function (newValue, oldValue) {}
});
})(jQuery);

示例代码

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Basic Combo - jQuery EasyUI Demo</title>
<link rel="stylesheet" type="text/css" href="../../themes/default/easyui.css">
<link rel="stylesheet" type="text/css" href="../../themes/icon.css">
<link rel="stylesheet" type="text/css" href="../demo.css">
<script type="text/javascript" src="../../jquery-1.8.0.min.js"></script>
<script src="../../plugins2/jquery.parser.js"></script>
<script src="../../plugins2/jquery.validatebox.js"></script>
<script src="../../plugins2/jquery.panel.js"></script>
<script src="../../plugins2/jquery.combo.js"></script>
</head>
<body>
<h2>Basic Combo</h2>
<div class="demo-info" style="margin-bottom:10px">
<div class="demo-tip icon-tip"></div>
<div>Click the right arrow button to show drop down panel that can be filled with any content.</div>
</div>
<select id="cc" style="width:150px"></select>
<div id="sp">
<div style="color:#99BBE8;background:#fafafa;padding:5px;">Select a language</div>
<input type="radio" name="lang" value="01"><span>Java</span><br/>
<input type="radio" name="lang" value="02"><span>C#</span><br/>
<input type="radio" name="lang" value="03"><span>Ruby</span><br/>
<input type="radio" name="lang" value="04"><span>Basic</span><br/>
<input type="radio" name="lang" value="05"><span>Fortran</span>
</div>
<script type="text/javascript">
$(function(){
$('#cc').combo({
required:true,
editable:false
});
$('#sp').appendTo($('#cc').combo('panel'));
$('#sp input').click(function(){
var v = $(this).val();
var s = $(this).next('span').text();
$('#cc').combo('setValue', v).combo('setText', s).combo('hidePanel');
});
});
</script>
</body>
</html>

插件效果

easyui源码翻译1.32--Combo(自定义下拉框)