jquery插件开发之实现google+圈子选择功能


Posted in Javascript onMarch 10, 2014

jquery插件开发之实现google+圈子选择功能

具体原理与调用不详述,可看代码注释及DEMO演示(演示中mod.udata.js里有一个汉字转拼音方法,它并不是插件的一部分,但为插件提供了拼音搜索的功能)。

;(function ($) {
    /*
     * 基于jQuery实现类似Google+圈子选择功能插件(支持键盘事件)@Mr.Think(http://mrthink.net/)
     */
    $.fn.iChoose = function (options) {
        var SELF=this;
        var iset = $.extend({}, $.fn.iChoose.defaults, options);
        var _h,pull=null;
        var main=$(iset.choMain);
        var chose=$(iset.choCls,main);
        var input=$(SELF);
        var tips=$(iset.tips,main);
        var cls=iset.selCls;
        var ids=$(iset.chsIds);
        var _l=iset.limit;
        //若无列表数据则中断
        if(iset.data.length==0){return false}
        //初始化下拉列表
        var tpl='<div class="'+iset.pullCls+'"><ul>';
        var tplArr=[];
        $.each(iset.data,function(k,v){
            tplArr.push('<li data-mid="'+ v.mid+'" data-name="'+ v.filterName.toUpperCase()+'" class="hook_visible hook_'+v.mid+'">'+ v.name+'</li>');
        });
        tpl=tpl+tplArr.join('')+'</ul></div>';
        if(pull==null){
            main.append(tpl);
        }
        pull=$('.'+iset.pullCls,main);
        _h=pull.find('li').outerHeight(true);
        pull.width(main.width()-2);
        //操作函数
        var Action={
            init:function(){
                //列表鼠标划过
                pull.delegate('li.hook_visible','mouseover',function(){
                    $(this).addClass(cls).siblings().removeClass(cls);
                });
                //选择列表
                pull.delegate('li.hook_visible','click',function(){
                    Action.choose($(this));
                });
                //点击弹出列表
                chose.click(function(){
                    Action.show();
                });
                //移除已选择
                chose.delegate('.'+iset.removeEl,'click',function(){
                    Action.undock($(this));
                });
            },
            move: function(dir) {
                //上下移动 - 上::str=up | 下::step=down;
                var index;
                var item=pull.find('li.hook_visible').filter(':visible');
                var cur=item.filter('.'+cls);
                cur.size()==0 ? index=-1 : index=item.index(cur);
                item.eq(dir=='up' ? (index<1 ? 0 : index-1) : index+1).addClass(cls).siblings().removeClass(cls);
                //移动时跟随滚动
                if(item.size()>_l){
                    //下翻滚动
                    if(dir=='down'){
                        pull.scrollTop((index+2-_l)*_h);
                    }
                    //上翻滚动
                    if(dir=='up'){
                        pull.scrollTop((index-1)*_h);
                    }
                }
            },
            choose:function(el){
                //列表选择
                var mid=el.attr('data-mid');
                var name=el.text();
                tips.before('<div class="'+iset.selItemCls+'"><span>'+name+'</span><a href="javascript:;" class="'+iset.removeEl+'" data-mid="'+mid+'">x</a></div>');
                input.focus();
                el.hide().removeClass('hook_visible');
                //返回选中列表id
                ids.val() =='' ? ids.val(mid) : ids.val(ids.val()+','+mid);
                pull.find('li.hook_visible:first').addClass(cls).siblings().removeClass(cls);
                this.upstyle();
            },
            undock:function(el){
                //删除已选
                var mid=el.attr('data-mid');
                var idsArr=ids.val().split(',');
                input.focus();
                el.parent().remove();
                idsArr=$.grep(idsArr,function(v,k){
                   return v != mid;
                });
                ids.val(idsArr.join(','));
                pull.find('li.hook_'+mid).show().addClass('hook_visible');
                this.upstyle();
            },
            show:function(){
                //显示列表
                pull.slideDown(100,function(){Action.match('')});
                pull.find('li.hook_visible:first').addClass(cls).siblings().removeClass(cls);
                $(SELF).focus();
                tips.hide();
                input.addClass(iset.inputWCls);
            },
            hide:function(){
                //隐藏列表
                pull.slideUp(100);
                $(SELF).blur();
                tips.show();
                input.removeClass(iset.inputWCls);
            },
            upstyle:function(type){
                //更新下拉列表样式 - 当已选换行时 --
                var len=pull.find('li.hook_visible').size();
                if(type=='match'){
                    len=pull.find('li:visible').size();
                }
                if(len<_l){
                    pull.height(_h*len);
                    if(len==0){
                        this.hide();
                    }
                }else{
                    pull.height(_h*_l);
                }
                pull.css('top',chose.outerHeight());
            },
            match:function(str){
                //过滤选择 - 拼音选择须插件支持
                var visible=pull.find('li.hook_visible');
                visible.each(function(){
                    var name=$(this).attr('data-name');
                    name.match(str.toUpperCase())!=null ? $(this).show() : $(this).hide();
                });
                if(visible.size()==0 && $('.'+iset.noResCls).size()==0){
                    pull.find('li:first').before('<li class="'+iset.noResCls+'">暂无可选择列表</li>')
                }
                this.upstyle('match');
            },
            blur:function(str){
                //非选择区域点击隐藏
                pull.find('li.hook_visible').each(function(){
                    var name=$(this).text();
                    if(name == str){
                        Action.choose($(this));
                    }
                });
                input.val('');
            }
        }
        Action.init();
        //键盘控制 - 绑定输入表单
        $(this).on({
            //键盘弹起
            'keyup change':function(){
                var val= $.trim(input.val());
                Action.match(val);
            },
            //失去焦点
            'blur':function(){
                var val= $.trim(input.val());
                Action.blur(val);
            },
            //键盘按下 -- 捕获键盘值,以执行对应事件
            /*
            8  - delete;
            27 - esc;
            38 - up;
            40 - down;
            9  - tab;
            13 - enter
             */
            'keydown':function(e){
                switch (e.keyCode) {
                    case 8:
                        if($.trim(input.val())==''){
                            e.preventDefault();
                            var last=chose.find('.'+iset.removeEl+':last');
                            if(last.size()>0){
                                Action.undock(last);
                            }
                        }
                        break;
                    case 27:
                        e.preventDefault();
                        Action.hide();
                        break;
                    case 38:
                        e.preventDefault();
                        Action.move('up');
                        break;
                    case 40:
                        e.preventDefault();
                        Action.move('down')
                        break;
                    case 9:
                    case 13:
                        e.preventDefault();
                        Action.choose(pull.find('.'+cls));
                        break;
                    default:
                        $.noop();
                }
            }
        });
        //点击非当前区域隐藏弹出层
        main.click(function(e){
            e.stopPropagation();
        });
        $(document).click(function(){
           Action.hide();
        });
    }
    $.fn.iChoose.defaults = {
        /*
        data:传入值,可以实时ajax传上,演示中是json值,具体格式可参考mod.udatas.js中的$.map(...)
        limit:每次显示的条数,其他滚动显示
        choMain:载入区域id
        pullCls:弹出列表的class
        choCls:已选择列表的外围class
        selItemCls:已选择的单个元素class
        removeEl:删除元素的class
        selCls:列表高亮的class
        inputWCls:input的class
        tips:默认提示值元素钩子
        noResCls:列表中无结果时的cls
        chsIds:已选择列表的id值,传给后端用的。(此值亦可用回调函数把值从插件中回传出来)
         */
        data:UDatas,
        limit:5,
        choMain:'#iChooseMain',
        pullCls:'icm-list',
        choCls:'.icm-box',
        selItemCls:'icm-item',
        removeEl:'icm-delete',
        selCls:'selected',
        inputWCls:'icm-input-w',
        tips:'.icm-cur-txt',
        noResCls:'hook_noresult',
        chsIds:'#iChooseIds'
    }
})(jQuery);
Javascript 相关文章推荐
jQuery的实现原理的模拟代码 -2 数据部分
Aug 01 Javascript
DB.ASP 用Javascript写ASP很灵活很好用很easy
Jul 31 Javascript
50款非常棒的 jQuery 插件分享
Mar 29 Javascript
js转化毫秒为时间格式代码
Apr 10 Javascript
JavaScript数据结构和算法之图和图算法
Feb 11 Javascript
基于PHP和Mysql相结合使用jqGrid读取数据并显示
Dec 02 Javascript
轻松使用jQuery双向select控件Bootstrap Dual Listbox
Dec 13 Javascript
AngularJS基础 ng-selected 指令简单示例
Aug 03 Javascript
使用Bootstrap Tabs选项卡Ajax加载数据实现
Dec 23 Javascript
vue.js $refs和$emit 父子组件交互的方法
Dec 20 Javascript
vue2路由基本用法实例分析
Mar 06 Javascript
JS使用Chrome浏览器实现调试线上代码
Jul 23 Javascript
js实现通用的微信分享组件示例
Mar 10 #Javascript
jquery基础教程之数组使用详解
Mar 10 #Javascript
查询json的数据结构的8种方式简介
Mar 10 #Javascript
js 3秒后跳转页面的实现代码
Mar 10 #Javascript
php is_numberic函数造成的SQL注入漏洞
Mar 10 #Javascript
关于JavaScript对象的动态选择及遍历对象
Mar 10 #Javascript
使用js操作css实现js改变背景图片示例
Mar 10 #Javascript
You might like
消息持续发送的完整例子
2006/10/09 PHP
php HtmlReplace输入过滤安全函数
2010/07/03 PHP
PHP开发中解决并发问题的几种实现方法分析
2017/11/13 PHP
PHP中number_format()函数的用法讲解
2019/04/08 PHP
使用SMB共享来绕过php远程文件包含的限制执行RFI的利用
2019/05/31 PHP
laravel5.5添加echarts实现画图功能的方法
2019/10/09 PHP
js继承的实现代码
2010/08/05 Javascript
js计算精度问题小结
2013/04/22 Javascript
JQuery中SetTimeOut传参问题探讨
2013/05/10 Javascript
js 弹出框只弹一次(二次修改之后的)
2013/11/26 Javascript
JS小功能(button选择颜色)简单实例
2013/11/29 Javascript
用jquery等比例控制图片宽高的具体实现
2014/01/28 Javascript
node.js中的fs.write方法使用说明
2014/12/15 Javascript
JS实现超简单的汉字转拼音功能示例
2016/12/22 Javascript
详解AngularJs ui-router 路由的简单介绍
2017/04/26 Javascript
Angularjs验证用户输入的字符串是否为日期时间
2017/06/01 Javascript
基于jquery实现多级菜单效果
2017/07/25 jQuery
jQuery动态添加.active 实现导航效果代码思路详解
2017/08/29 jQuery
详解Vue2.0组件的继承与扩展
2018/11/23 Javascript
详解为生产环境编译Angular2应用的方法
2018/12/10 Javascript
仿iPhone通讯录制作小程序自定义选择组件的实现
2019/05/23 Javascript
Layui实现带查询条件的分页
2019/07/27 Javascript
vue-cli3项目升级到vue-cli4 的方法总结
2020/03/19 Javascript
Python群发邮件实例代码
2014/01/03 Python
python调用windows api锁定计算机示例
2014/04/17 Python
解决Django模板无法使用perms变量问题的方法
2017/09/10 Python
python中嵌套函数的实操步骤
2019/02/27 Python
windows 10 设定计划任务自动执行 python 脚本的方法
2019/09/11 Python
Python如何重新加载模块
2020/07/29 Python
详解Pycharm安装及Django安装配置指南
2020/09/15 Python
机电工程专业应届生求职信
2013/10/03 职场文书
中学实习教师自我鉴定
2013/12/12 职场文书
超市店庆活动方案
2014/08/31 职场文书
小学优秀教师材料
2014/12/15 职场文书
python 破解加密zip文件的密码
2021/04/22 Python
如何使用SQL Server语句创建表
2022/04/12 SQL Server