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判断小数点两位和自动删除小数两位后的数字
Mar 19 Javascript
使用jQuery重置(reset)表单的方法
May 05 Javascript
web前端设计师们常用的jQuery特效插件汇总
Dec 07 Javascript
JavaScript判断数组重复内容的两种方法(推荐)
Jun 06 Javascript
基于jPlayer三分屏的制作方法
Dec 21 Javascript
微信小程序 Button 组件详解及简单实例
Jan 10 Javascript
Node.js设置CORS跨域请求中多域名白名单的方法
Mar 28 Javascript
vue+mockjs模拟数据实现前后端分离开发的实例代码
Aug 08 Javascript
vue组件实现弹出框点击显示隐藏效果
Oct 26 Javascript
JavaScript学习笔记之DOM操作实例分析
Jan 08 Javascript
js HTML DOM EventListener功能与用法实例分析
Apr 27 Javascript
vue修改Element的el-table样式的4种方法
Sep 17 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
javascript数组与php数组的地址传递及值传递用法实例
2015/01/22 PHP
PHP rsa加密解密使用方法
2015/04/27 PHP
php 一维数组的循环遍历实现代码
2017/04/10 PHP
ThinkPHP实现的rsa非对称加密类示例
2018/05/29 PHP
PHP 实现文件压缩解压操作的方法
2019/06/14 PHP
国外Lightbox v2.03.3 最新版 下载
2007/10/17 Javascript
IE event.srcElement和FF event.target 功能比较
2010/03/01 Javascript
Javascript面向对象编程(二) 构造函数的继承
2011/08/28 Javascript
Jquery+Ajax+PHP+MySQL实现分类列表管理(上)
2015/10/28 Javascript
基于原生js运动方式关键点的总结(推荐)
2017/10/01 Javascript
JavaScript程序设计高级算法之动态规划实例分析
2017/11/24 Javascript
jQuery实现的回车触发按钮事件功能示例
2018/03/25 jQuery
Angularjs中的$apply及优化使用详解
2018/07/02 Javascript
如何理解Vue的v-model指令的使用方法
2018/07/19 Javascript
JS 实现微信扫一扫功能
2018/09/14 Javascript
webpack配置proxyTable时pathRewrite无效的解决方法
2018/12/13 Javascript
bootstrap-treeview实现多级树形菜单 后台JSON格式如何组织?
2019/07/26 Javascript
JavaScript写个贪吃蛇小游戏(超详细)
2020/03/17 Javascript
[07:40]DOTA2每周TOP10 精彩击杀集锦vol.4
2014/06/25 DOTA
Python找出文件中使用率最高的汉字实例详解
2015/06/03 Python
python简单分割文件的方法
2015/07/30 Python
Pycharm技巧之代码跳转该如何回退
2017/07/16 Python
python购物车程序简单代码
2018/04/18 Python
python 获取utc时间转化为本地时间的方法
2018/12/31 Python
Python实现的读取文件内容并写入其他文件操作示例
2019/04/09 Python
利用python numpy+matplotlib绘制股票k线图的方法
2019/06/26 Python
Django 拆分model和view的实现方法
2019/08/16 Python
Python filter过滤器原理及实例应用
2020/08/18 Python
HTML5调用手机发短信和打电话功能
2020/04/29 HTML / CSS
抽象类和接口的区别
2012/09/19 面试题
工作分析计划书
2014/04/30 职场文书
2014年教师党员自我评议
2014/09/19 职场文书
大学生翘课检讨书范文
2014/10/06 职场文书
2014社会治安综合治理工作总结
2014/12/04 职场文书
2015年高校就业工作总结
2015/05/04 职场文书