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 相关文章推荐
在Node.js中实现文件复制的方法和实例
Jun 05 Javascript
如何在node的express中使用socket.io
Dec 15 Javascript
JavaScript中使用Object.create()创建对象介绍
Dec 30 Javascript
浅谈Cookie的生命周期问题
Aug 02 Javascript
AngularJS控制器之间的通信方式详解
Nov 03 Javascript
AngularJS中的DOM操作用法分析
Nov 04 Javascript
Bootstrap基本组件学习笔记之input输入框组(9)
Dec 07 Javascript
原生js实现无限循环轮播图效果
Jan 20 Javascript
Java中int与integer的区别(基本数据类型与引用数据类型)
Feb 19 Javascript
jQuery插件imgAreaSelect基础讲解
May 26 jQuery
详解Vue整合axios的实例代码
Jun 21 Javascript
JS实现的小火箭发射动画效果示例
Dec 08 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
解析PHP中empty is_null和isset的测试
2013/06/29 PHP
php利用smtp类实现电子邮件发送
2015/10/30 PHP
jquery+json实现的搜索加分页效果
2010/03/31 Javascript
javascript跨浏览器的属性判断方法
2014/03/16 Javascript
JavaScript判断浏览器类型的方法
2015/02/10 Javascript
KnockoutJS 3.X API 第四章之表单value绑定
2016/10/10 Javascript
jQuery.ajax实现根据不同的Content-Type做出不同的响应
2016/11/03 Javascript
JavaScript实现多栏目切换效果
2016/12/12 Javascript
javascript中apply/call和bind的使用
2017/02/15 Javascript
jQuery实现锚点向下平滑滚动特效示例
2017/08/29 jQuery
vue2.0 实现页面导航提示引导的方法
2018/03/13 Javascript
Vue render深入开发讲解
2018/04/13 Javascript
使用Vue的slot插槽分发父组件内容实现高度复用、更加灵活的组件(推荐)
2018/05/01 Javascript
微信小程序tabbar底部导航
2018/11/05 Javascript
JS实现的点击按钮图片上下滚动效果示例
2019/01/28 Javascript
vue 实现一个简单的全局调用弹窗案例
2020/09/10 Javascript
Electron+vue从零开始打造一个本地播放器的方法示例
2020/10/27 Javascript
python获取元素在数组中索引号的方法
2015/07/15 Python
Python模糊查询本地文件夹去除文件后缀的实例(7行代码)
2017/11/09 Python
Python OpenCV获取视频的方法
2018/02/28 Python
python3解析库pyquery的深入讲解
2018/06/26 Python
Django如何自定义model创建数据库索引的顺序
2019/06/20 Python
Python二维码生成识别实例详解
2019/07/16 Python
Python 限定函数参数的类型及默认值方式
2019/12/24 Python
Python改变对象的字符串显示的方法
2020/08/01 Python
Python logging模块handlers用法详解
2020/08/14 Python
matplotlib 范围选区(SpanSelector)的使用
2021/02/24 Python
详解CSS3的图层阴影和文字阴影效果使用
2016/06/09 HTML / CSS
Europcar比利时:租车
2019/08/26 全球购物
创建文明城市标语
2014/06/16 职场文书
大学军训自我鉴定大全
2014/09/18 职场文书
2014学校领导四风对照检查材料思想汇报
2014/09/23 职场文书
垂直极限观后感
2015/06/08 职场文书
开业典礼致辞
2015/07/29 职场文书
css中z-index: 0和z-index: auto的区别
2021/08/23 HTML / CSS
Python采集股票数据并制作可视化柱状图
2022/04/04 Python