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 相关文章推荐
Extjs Ajax 乱码问题解决方案
Apr 15 Javascript
Javascript中的delete操作符详细介绍
Jun 06 Javascript
Jquery+Ajax+PHP+MySQL实现分类列表管理(下)
Oct 28 Javascript
JavaScript实现跑马灯抽奖活动实例代码解析与优化(二)
Feb 16 Javascript
给easyui的datebox控件添加清空按钮的实现方法
Nov 09 Javascript
vue+vuex+axio从后台获取数据存入vuex实现组件之间共享数据
Apr 22 Javascript
JavaScript对象_动力节点Java学院整理
Jun 23 Javascript
详解React-Native解决键盘遮挡问题(Keyboard遮挡问题)
Jul 13 Javascript
基于jQuery解决ios10以上版本缩放问题
Nov 03 jQuery
详解vue 动态加载并注册组件且通过 render动态创建该组件
May 30 Javascript
vue实现计算器功能
Feb 22 Javascript
JavaScript实现Tab标签页切换的最简便方式(4种)
Jun 28 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 获取远程网页内容的函数
2009/09/08 PHP
php实现图片添加水印功能
2014/02/13 PHP
php switch语句多个值匹配同一代码块的实现
2014/03/03 PHP
在PHP中使用X-SendFile头让文件下载更快
2014/06/01 PHP
onpropertypchange
2006/07/01 Javascript
Javascript 类型转换方法
2010/10/24 Javascript
网易JS面试题与Javascript词法作用域说明
2010/11/09 Javascript
javascript获取select的当前值示例代码(兼容IE/Firefox/Opera/Chrome)
2013/12/17 Javascript
JS生成不重复随机数组的函数代码
2014/06/10 Javascript
javascript文本框内输入文字倒计数的方法
2015/02/24 Javascript
AngularJS基础学习笔记之指令
2015/05/10 Javascript
jQuery实现监控页面所有ajax请求的方法
2015/12/10 Javascript
D3.js实现散点图和气泡图的方法详解
2016/09/21 Javascript
JS用斜率判断鼠标进入DIV四个方向的方法
2016/11/07 Javascript
解决URL地址中的中文乱码问题的办法
2017/02/10 Javascript
基于Bootstrap分页的实例讲解(必看篇)
2017/07/04 Javascript
Windows下快速搭建NodeJS本地服务器的步骤
2017/08/09 NodeJs
AngularJs ng-change事件/指令的用法小结
2017/11/01 Javascript
基于JSONP原理解析(推荐)
2017/12/04 Javascript
基于jQuery实现挂号平台首页源码
2020/01/06 jQuery
浅谈使用nodejs搭建web服务器的过程
2020/07/20 NodeJs
介绍Python的Django框架中的QuerySets
2015/04/20 Python
python利用datetime模块计算时间差
2015/08/04 Python
python实现对求解最长回文子串的动态规划算法
2018/06/02 Python
Python中操作各种多媒体,视频、音频到图片的代码详解
2020/06/04 Python
Python Spyder 调出缩进对齐线的操作
2021/02/26 Python
IE支持HTML5的解决方法
2009/10/20 HTML / CSS
唤醒头发毛囊的秘密武器:Grow Gorgeous
2016/08/28 全球购物
美国女性运动零售品牌:Lady Foot Locker
2017/05/12 全球购物
机械设计制造及其自动化专业求职信
2014/06/17 职场文书
css3实现背景图片颜色修改的多种方式
2021/04/13 HTML / CSS
JVM入门之类加载与字节码技术(类加载与类的加载器)
2021/06/15 Java/Android
sql server删除前1000行数据的方法实例
2021/08/30 SQL Server
canvas实现贪食蛇的实践
2022/02/15 Javascript
python使用BeautifulSoup 解析HTML
2022/04/24 Python
windows server2016安装oracle 11g的图文教程
2022/07/15 Servers