基于Jquery和Ajax的多选框

  哈哈,终于我也在博客园开通博客了,怎么说现在我也算进入it行业了,以后看来要在这里好好开垦一番了。

  现在就说说我仿照人才网做的多选框吧,之前做一个项目的时候需要用到基于Ajax的多选框,网上找了一下,发现都不是我想要的,后来发现求职网站上的多选框比较符合我的要求,但是他那是本地缓存的,我想要的是用Ajax请求从数据库获得数据再填充到多选框的,于是我将他修改一番,做出一个基于Jquery和Ajax的通用多选框。

  首先用Jquery定义一个没有名称的匿名函数

1 (function ($) {
2 ......
3 })(jQuery);

匿名函数在js中因为也是对象,所以需要双括号包裹起来,这个结构说明,我使用了匿名函数,并且立刻执行这个匿名函数。在此Jquery匿名函数内,他会自己创建Jquery对象。再啰嗦一下,这个结构和

a=function($) 
{
......
};
a(jquery);

是等价的。

  搭好函数后,需要为此插件定义一些Jquery全局对象,这用到了Jquery的extend扩展方法

//弹出层
    $.openLayer = function (p) {
        var param = $.extend({
            returnValue: "",             //以,分隔的选取结果id存放的位置id,默认为一个input。
            returnText: "",             //以,分隔的选取结果文字存放的位置id,可以为span,div等容器。
            title: "请选择",             //弹出窗口标题
             650,                 //弹出窗口宽度
            span_ { d1: 70 },     //可以自定义每一层级数据项显示宽度,用来对其排版。
            url: "",                     //ajax请求url
            dragEnable: true             //是否允许鼠标拖动
        }, p || {});

既然是全局变量,也就是说如果以后有同样名字的Jquery参数,那么原来的参数值将被覆盖。这对于插件开发那是大大有好处呀,就像一个软件的各种设置有默认值,你可以自己更改一样

  至此,插件的外壳搭建好了,现在将实现功能。首先定义一个对象,在这个对象里面填充各种将要被调用的函数,包括css插入

init_style: function () { //初始化css
                var margin = 4;
                var width = param.width - margin * 5;

                var css = "<style>";
                var aotu = "border:2px groove";
                css += "#popupAddr {position:absolute;border:3px ridge;" + param.width + "px;background-color:#e3e3e3;z-index:99;box-shadow:5px 5px 5px rgba(0,0,0,0.5)}";
                css += "#bodybg {100%;position:absolute;top:0;left:0;background-color:#000000;opacity:0.5}";
                css += "#heads {font-size:12px}";
                css += "#headdiv {color:white;background-color:#3C85ff;font-size:13px;line-height:30px;padding:0 12px;margin:1px;" + aotu + "}";
                css += "#close {float:right}";
                css += "#selArea {" + width + "px;min-height:48px;margin:" + margin + "px;padding:5px;background-color:#f4f4f4;float:left;" + aotu + "}";
                $("head").append(css + "</style>");
            }

这里不讨论在js里面插入css的缺点,不过有一个好处就是这个插件将只需要调用一个js文件,不需要调用css文件了,另外我一直在想用字符串追加和栈哪个效率高,似乎在不同浏览器表现不一样,这里估且用+=吧;头部初始化

init_Container: function () { //初始化头部和内容容器
                var close = "<span id='_cancel' style='cursor:pointer;'>[取消]</span>&nbsp;&nbsp;<span id='_ok' style='cursor:pointer;'>[确定]</span>";
                //头部
                var htmlDiv = "<div id='heads'><div id='headdiv'><span title='全选/全不选'><input type='checkbox' id='selectAll'/>" + param.title + "</span><span id='close'>" + close + "</span></div>";
                //内容容器创建部分
                htmlDiv += "<div id='container'><div id='selArea'><div>已选择:</div></div><div id='d1'></div></div></div>";
                pop.html(htmlDiv);
            },

添加数据到容器

add_data: function (targetid) { //添加数据到容器,添加事件,初始化下一层次容器
                var data = ''; //返回数据变量

                $.ajax({
                    type: "post",                     //post方式
                    url: param.url,                 //ajax查询url
                    async: false,                     //同步方式,便于拿到返回数据做统一处理
                    success: function (d) { //ajax请求成功后返回数据
                        data = d;
                    }
                });
                //没有数据或者错误,添加提示信息返回
                if (data == "") {
                    $("#selArea").append("<span style='color:red;'>获取数据失败!</span>");
                    return;
                }

                var spanWidth = eval("param.span_width." + targetid.attr("id")); //每个数据显示项的宽度
                spanWidth = (spanWidth == undefined ? param.span_width.d1 : spanWidth); //没有设置的话,就使用第一个数据容器的值
                var inspanWidth = ($.browser.msie) ? 1 : 3; //内部文字和checkbox之间的距离

                var dat = data.split(','); //根据设定分隔符对数据做第一次分隔,获得数据项数组
                var html = ''; //格式化数据存放容器,为了提高效率,使用了字符串
                var ss;
                //循环获得格式化的显示字符串
                for (var i = 0, l = dat.length; i < l; i++) {
                    ss = dat[i].split(':'); //第二次分隔,获得每个数据项中的数据值和显示字符串
                    html += "<span title='" + dat[i] + "' style='" + spanWidth + "px;white-space:nowrap;float:left;'><input type='checkbox' value='" + ss[0] + "'><span style='margin-left:" + inspanWidth + "px;'>" + ss[1] + "</span></span>";
                }
                targetid.html(html); //格式化的html代码放入目标容器
            },

原本除了可以填充Ajax获取的数据还可以填充缓存数据的,后来被我去掉了;初始化自启事件

init_event: function () { //绑定已选择框中checkbox的事件,确定,取消事件响应
                var selArea = $("#selArea"),
                    d1 = $("#d1");
                selArea.delegate('input', 'click', function () {
                    $(this).parent().remove();
                    d1.find("input[value=" + this.value + "]").attr("checked", false);
                });
                d1.delegate('input', 'click', function () {
                    if (this.checked) {
                        selArea.append($(this).parent().clone().css({ "width": "", "background": "", "border": "" }));
                    } else {
                        selArea.find("input[value=" + this.value + "]").parent().remove();
                    }
                });
                $("#selectAll").click(function () {
                    selArea.find("input").each(function () {
                        this.click();
                    });
                    if (this.checked) {
                        d1.find("input").each(function () {
                            this.click();
                        });
                    }
                });
                $("#_cancel").click(function () {
                    bodybg.hide();
                    pop.hide();
                });
                $("#_ok").click(function () {
                    var vals = "";
                    var txts = "";
                    selArea.find("input").each(function () {
                        vals += "," + this.value;
                        txts += "," + $(this).next().text();
                    });
                    fs.set_returnVals(param.returnValue, vals);
                    fs.set_returnVals(param.returnText, txts);

                    bodybg.hide();
                    pop.hide();
                });
            },

这里使用Jquery的delegate() 方法,而不是 live(),据说效率高些,因为他不是监听多个子元素的事件,而是监听一个母元素的事件,再判断是哪个子元素,点击确定按钮时value将被赋值给returnValue对应的元素,text将被赋值给returnText对应的元素;

;控件移动方法

move: function () {
                if (param.dragEnable) { //允许鼠标拖动
                    var move = false; //移动标记
                    var ox, oy; //鼠标离控件左上角的相对位置
                    pop.mousedown(function (e) {
                        move = true;
                        ox = e.pageX - parseInt(pop.css("left"));
                        oy = e.pageY - parseInt(pop.css("top"));
                    }).mousemove(function (e) {
                        if (move) {
                            var x = e.pageX - ox; //移动时根据鼠标位置计算控件左上角的绝对位置
                            var y = e.pageY - oy;
                            pop.css({ top: y, left: x }); //控件新位置
                        }
                    }).mouseup(function () { move = false; });
                }
            },

  至此,对象声明好了,现在只需要调用声明好的对象里的方法即可

var pop = $("#popupAddr"); //创建一个div元素
        var bodybg = $("#bodybg"); //创建背景层

        if (pop.length == 0) {
            fs.init_style(); //初始化样式
            pop = $("<div id='popupAddr'></div>");
            $("body").append(pop);
            bodybg = $("<div id='bodybg'></div>");
            $("body").append(bodybg);
            fs.move();
        }
        fs.init_Container(); //弹出层内容
        fs.add_data($("#d1")); //添加数据
        fs.init_event();

        //初始化已选中的项
        fs.init_selected();

        //让多选框居中显示
        var yPos = ($(window).height() - pop.height()) / 2;
        var xPos = ($(window).width() - pop.width()) / 2;
        pop.css({ top: yPos, left: xPos }).show();

        bodybg.height(document.body.scrollHeight);
        bodybg.show();
        pop.show();

当一个页面多个这种控件时,有些方法是只需要执行一次的,如css插入方法和控件移动方法。

  呼呼,终于写完了,用的时候写上

$("xxx").click(function () {
            $.openLayer({
                returnText: "xxx",
                title: "xxx",
                returnValue: "xxx",
                span_ { d1: 120 },
                url: "/xxx/xxx"
            });
        });

此控件接收的数据格式是"xxx:xxx,xxx:xxx...",即是vluae:text然后用逗号分开。另外我是加了jquery-1.7.1.min.js的,贴个效果图吧,源码

原文地址:https://www.cnblogs.com/hambert/p/3050325.html