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 相关文章推荐
jQuery1.6 类型判断实现代码
Sep 01 Javascript
JavaScript字符串对象split方法入门实例(用于把字符串分割成数组)
Oct 16 Javascript
jquery验证手机号是否正确实例讲解
Nov 17 Javascript
JavaScript与HTML的结合方法详解
Nov 23 Javascript
一道常被人轻视的web前端常见面试题(JS)
Feb 15 Javascript
JavaScript入门系列之知识点总结
Mar 24 Javascript
bootstrap的工具提示实例代码
May 17 Javascript
angularjs实现table增加tr的方法
Feb 27 Javascript
使用jquery DataTable和ajax向页面显示数据列表的方法
Aug 09 jQuery
vue单页缓存存在的问题及解决方案(小结)
Sep 25 Javascript
基于canvas实现手写签名(vue)
May 21 Javascript
基于JS实现计算24点算法代码实例解析
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
Smarty的配置与高级缓存技术分享
2012/06/05 PHP
LotusPhp笔记之:Cookie组件的使用详解
2013/05/06 PHP
PHP static局部静态变量和全局静态变量总结
2014/03/02 PHP
如何阻止网站被恶意反向代理访问(防网站镜像)
2014/03/18 PHP
PHP面向对象详解(三)
2015/12/07 PHP
laravel 5.3 单用户登录简单实现方法
2019/10/14 PHP
PHP实现简单注册登录系统
2020/12/28 PHP
用js实现的一个Flash滚动轮换显示图片代码生成器
2007/03/14 Javascript
Jquery AutoComplete自动完成 的使用方法实例
2010/03/19 Javascript
百度地图api应用标注地理位置信息(js版)
2013/02/01 Javascript
intro.js 页面引导简单用法 分享
2013/08/06 Javascript
setInterval()和setTimeout()的用法和区别示例介绍
2013/11/17 Javascript
js sort 二维数组排序的用法小结
2014/01/24 Javascript
详解Angularjs filter过滤器
2016/02/06 Javascript
jQuery实现百叶窗焦点图动画效果代码分享(附源码下载)
2016/03/14 Javascript
jQuery中的insertBefore(),insertAfter(),after(),before()区别介绍
2016/09/01 Javascript
AngularJS  ng-repeat遍历输出的用法
2017/06/19 Javascript
浅谈JS对html标签的属性的干预以及对CSS样式表属性的干预
2017/06/25 Javascript
详解JS函数stack size计算方法
2018/06/18 Javascript
小程序图片长按识别功能的实现方法
2018/08/30 Javascript
Vue-cli3.X使用px2 rem遇到的问题及解决方法
2019/08/08 Javascript
微信小程序事件 bindtap bindinput代码实例
2019/08/26 Javascript
react中Suspense的使用详解
2019/09/01 Javascript
Bootstrap FileInput实现图片上传功能
2021/01/28 Javascript
Python开发SQLite3数据库相关操作详解【连接,查询,插入,更新,删除,关闭等】
2017/07/27 Python
对Python3之进程池与回调函数的实例详解
2019/01/22 Python
python redis 删除key脚本的实例
2019/02/19 Python
python 利用浏览器 Cookie 模拟登录的用户访问知乎的方法
2019/07/11 Python
Python3.6 + TensorFlow 安装配置图文教程(Windows 64 bit)
2020/02/24 Python
浅谈JupyterNotebook导出pdf解决中文的问题
2020/04/22 Python
html5 视频播放解决方案
2016/11/06 HTML / CSS
茵宝(Umbro)英国官方商店:英国足球服装生产商
2016/12/29 全球购物
亿阳信通股份有限公司C#笔试题
2016/12/06 面试题
如何用Java实现列出某个目录下的所有子目录
2015/07/20 面试题
教育技术学专业职业规划书
2014/03/03 职场文书
小平小道观后感
2015/06/09 职场文书