• 基于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的,贴个效果图吧,源码

  • 相关阅读:
    C++——多态
    C++——继承
    PAT1002 A+B for Polynomials
    PAT1001-A+B Format
    C++——运算符重载(下)
    图像处理与Python实现(岳亚伟)笔记二——彩色图像处理
    图像处理与Python实现(岳亚伟)笔记一
    827. Making A Large Island
    995. Minimum Number of K Consecutive Bit Flips (2021/2/18每日一题)
    685. Redundant Connection II (LeetCode 刷题笔记)
  • 原文地址:https://www.cnblogs.com/hambert/p/3050325.html
Copyright © 2020-2023  润新知