统一下拉列表样式并实现select样式高度自定义的jQuery插件

好像很久没有更新过博客了,哈~
发布一款最近写的jQuery小插件,用于统一下拉表样式并实现select样式高度自定义。select样式如同input[type=file]一样,各系统平台各浏览器显示的都不一样,特别是ie~一切影响美感的东西较真的UI设计狮们是不会妥协的。兵来将挡,水来土淹,为了保持最近一个公司项目中部分下拉列表的美观统一,用一种变通的方式为select穿上一套标准的新衣:不论平台不论浏览器样式统一、样式高度自定义、不破坏select原有结构与功能(这意味着后端程序仍可像调用普通select那样取值)。

原理无须多讲,在需要改变样式的select后插入一个div容器,同时隐藏掉select。然后把select的相关信息(optgroup/option/value/selected等)取出来用dl展现,如此一来,改变div容器中元素样式即可。记得前年写过一个用input[type=hidden]存值,用dl模拟下拉列表的插件。两者原理差不多,只是本文中的可能更人性化,使用起来更方便些。
jQuery代码:点此查看样列

;(function($){
    /*
     * 统一select样式并实现样式高度自定义的jQuery插件@Mr.Think(http://mrthink.net/)
     */
    $.fn.iSimulateSelect=function(iSet){
        iSet=$.extend({
            selectBoxCls:'i_selectbox', //string类型,外围class名
            curSCls:'i_currentselected',//string类型,默认显示class名
            optionCls:'i_selectoption',//string类型,下拉列表class名
            selectedCls:'selected',//string类型,当前选中class名
            width:222,//number类型,模拟select的宽度
            height:300,//number类型,模拟select的最大高度
            zindex:20//层级顺序
        },iSet||{});
        this.hide();
        return this.each(function(){
           var self=this;
           var thisCurVal,thisSelect,cIndex=0;
           //计算模拟select宽度
           if(iSet.width==0){
              iSet.width=$(self).width();
           }
           var html='<div class="'+iSet.selectBoxCls+'" style="z-index:'+iSet.zindex+'"><div class="'+iSet.curSCls+'" style="width:'+iSet.width+'px">'+$(self).find('option:selected').text()+'</div><dl class="'+iSet.optionCls+'" style="display:none;width:'+iSet.width+'px">';
           //判断select中是否有optgroup
           //用dt替代optgroup,用dd替代option
           if($(self).find('optgroup').size()>0){
               $(this).find('optgroup').each(function(){
                   html+='<dt>'+$(this).attr('label')+'</dt>';
                   $(this).find('option').each(function(){
                        if($(this).is(':selected')){
                          html+='<dd class="'+iSet.selectedCls+'">'+$(this).text()+'</dd>';
                       }else{
                          html+='<dd>'+$(this).text()+'</dd>';
                       }
                   });
               });
           }else{
               $(this).find('option').each(function(){
                   if($(this).is(':selected')){
                      html+='<dd class="'+iSet.selectedCls+'">'+$(this).text()+'</dd>';
                   }else{
                      html+='<dd>'+$(this).text()+'</dd>';
                   }
               });
           }
           //将模拟dl插入到select后面
           $(self).after(html);
           //当前模拟select外围box元素
           thisBox=$(self).next('.'+iSet.selectBoxCls);
           //当前模拟select初始值元素
           thisCurVal=thisBox.find('.'+iSet.curSCls);
           //当前模拟select列表
           thisSelect=thisBox.find('.'+iSet.optionCls);
           /*
           若同页面还有其他原生select,请前往https://github.com/brandonaaron/bgiframe下载bgiframe,同时在此处调用thisSelect.bgiframe()
            */
           //thisSelect.bgiframe();

           //弹出模拟下拉列表
           thisCurVal.click(function(){
              $('.'+iSet.optionCls).hide();
              $('.'+iSet.selectBoxCls).css('zIndex',iSet.zindex);
              $(self).next('.'+iSet.selectBoxCls).css('zIndex',iSet.zindex+1);
              thisSelect.show();
           });
           //若模拟select高度超出限定高度,则自动overflow-y:auto
           if(thisSelect.height()>iSet.height){
               thisSelect.height(iSet.height);
           }
           //模拟列表点击事件-赋值-改变y坐标位置-...
           thisSelect.find('dd').click(function(){
               $(this).addClass(iSet.selectedCls).siblings().removeClass(iSet.selectedCls);
               cIndex=thisSelect.find('dd').index(this);
               thisCurVal.text($(this).text());
               $(self).find('option').eq(cIndex).attr('selected','selected');
               $('.'+iSet.selectBoxCls).css('zIndex',iSet.zindex);
               thisSelect.hide();
           });
           //非模拟列表处点击隐藏模拟列表
           //$(document)点击事件不兼容部分移动设备
           $('html,body').click(function(e){
                if(e.target.className.indexOf(iSet.curSCls)==-1){
                  thisSelect.hide();
                  $('.'+iSet.selectBoxCls).css('zIndex',iSet.zindex);
              }
           });
           //取消模块列表处取消默认事件
           thisSelect.click(function(e){
              e.stopPropagation();
           });
        });
    }
})(jQuery);

如何调用?
1、在页面中引入上面的插件代码;
2、$(select).iSimulateSelect({…});
3、相关参数及功能,请参考插件中的注释说明。

若在ie6下,同页面中有未调用插件元素,为避免被原生select遮盖,请下载bgiframe插件,并在代码中关于bgiframe调用的公位置取消注释。另外,在调用插件的select后面插入的是一个相对定位元素,如果select前后还有其他行内元素,尽量使用float定位,或者给select外围加一个容器再进行绝对定位。

点击加减或手动改变表单值(支持键盘控制)的jQuery插件

大多电子商务网站购物车页面,都有通过点击来增减商品数量的功能,特地根据常规功能写了一个jQuery插件。
购物车常用功能
实现的功能:
1、可通过点击增加或减小定义的input值;
2、可手动输入input值,且支持键盘控制:上右为加,下左为减;
3、可设定表单的最大最小值,并对input值进行了非负整数判断;
4、定义了回调函数,输出表单最后的input值和所改变input的索引值。也可在插件中稍稍修改一下,把想返回的值传到一个hidden input中;
点此查看样列
jQuery代码:

$.fn.iVaryVal=function(iSet,CallBack){
	/*
	 * Minus:点击元素--减小
	 * Add:点击元素--增加
	 * Input:表单元素
	 * Min:表单的最小值,非负整数
	 * Max:表单的最大值,正整数
	 */
	iSet=$.extend({Minus:$('.J_minus'),Add:$('.J_add'),Input:$('.J_input'),Min:0,Max:20},iSet);
	var C=null,O=null;
	//插件返回值
	var $CB={};
	//增加
	iSet.Add.each(function(i){
		$(this).click(function(){
			O=parseInt(iSet.Input.eq(i).val());
			(O+1<=iSet.Max) || (iSet.Max==null) ? iSet.Input.eq(i).val(O+1) : iSet.Input.eq(i).val(iSet.Max);
			//输出当前改变后的值
			$CB.val=iSet.Input.eq(i).val();
			$CB.index=i;
			//回调函数
			if (typeof CallBack == 'function') {
                CallBack($CB.val,$CB.index);
            }
		});
	});
	//减少
	iSet.Minus.each(function(i){
		$(this).click(function(){
			O=parseInt(iSet.Input.eq(i).val());
			O-1<iSet.Min ? iSet.Input.eq(i).val(iSet.Min) : iSet.Input.eq(i).val(O-1);
			$CB.val=iSet.Input.eq(i).val();
			$CB.index=i;
			//回调函数
			if (typeof CallBack == 'function') {
				CallBack($CB.val,$CB.index);
		  	}
		});
	});
	//手动
	iSet.Input.bind({
		'click':function(){
			O=parseInt($(this).val());
			$(this).select();
		},
		'keyup':function(e){
			if($(this).val()!=''){
				C=parseInt($(this).val());
				//非负整数判断
				if(/^[1-9]\d*|0$/.test(C)){
					$(this).val(C);
					O=C;
				}else{
					$(this).val(O);
				}
			}
			//键盘控制:上右--加,下左--减
			if(e.keyCode==38 || e.keyCode==39){
				iSet.Add.eq(iSet.Input.index(this)).click();
			}
			if(e.keyCode==37 || e.keyCode==40){
				iSet.Minus.eq(iSet.Input.index(this)).click();
			}
			//输出当前改变后的值
			$CB.val=$(this).val();
			$CB.index=iSet.Input.index(this);
			//回调函数
			if (typeof CallBack == 'function') {
                CallBack($CB.val,$CB.index);
            }
		},
		'blur':function(){
			$(this).trigger('keyup');
			if($(this).val()==''){
				$(this).val(O);
			}
			//判断输入值是否超出最大最小值
			if(iSet.Max){
				if(O>iSet.Max){
					$(this).val(iSet.Max);
				}
			}
			if(O<iSet.Min){
				$(this).val(iSet.Min);
			}
			//输出当前改变后的值
			$CB.val=$(this).val();
			$CB.index=iSet.Input.index(this);
			//回调函数
			if (typeof CallBack == 'function') {
                CallBack($CB.val,$CB.index);
            }
		}
	});
}

若有bug,请以评论形式及时反馈~

多屏自动切换jQuery效果,可手动切换

油翁酌油沥钱,自钱孔入而钱不湿。因曰:“我亦无他, 唯手熟尔”。
好久没有好好的写过代码了,博客也有好几个月没有更新。忙于工作,忙于人身大事,忙于琐碎。最近相对清闲,正好一个做后端的朋友求助于我,帮他写一个新蛋网首页多屏自动切换效果。顺便分享之。
多屏自动切换jQuery效果
思路很简单,详见代码。本来是想封装成插件的,但一想,这种效果,也不大可能同时用多个,就偷懒直接写了。相关自定义的变量都放在一起了,一些功能函数也都有注释。自测兼容性良好,若有BUG请反馈。
点此查看样列
jQuery代码:

	var imgField=$('#J_imgList');
	var imgList=$('#J_imgList>li');
	var navField=$('#J_navList');
	var navList=$('#J_navList>li');
	var btnPrev=$('#J_prev');
	var btnNext=$('#J_next');
	var turnPage=4;//每屏显示数
	var T=5000;//切换间隔时间
	var turnT=300;//animate时间
	var N=0;//图片初始索引
	var P=1;//屏初始索引

	var goFun=null;
	var hoverFun=null;
	var triggerFun=null;
	var delayFun=null
	var navListW=navList.outerWidth(true);
	var turnPages=Math.ceil(navList.size()/turnPage);
	//初始图片区域高度与标题区域宽度
	imgField.height(imgList.size()*imgList.height());
	navField.width(navList.size()*navListW);
	//初始自动切换
	GO();
	//自动切换
	function GO() {
		imgField.stop().animate({
			marginTop:-N*(imgList.height())
		},turnT);
		navList.eq(N).addClass('hover').siblings().removeClass('hover');
		if(N%turnPage==0) {
			navField.stop().animate({
				marginLeft:-N*navListW+'px'
			},turnT);
		}
		N++;
		N= N>=imgList.size()?0:N;
		P=Math.ceil(N/turnPage);
		goFun=setTimeout(GO,T);
	}

	//停止切换
	function STOP() {
		clearTimeout(goFun);
	}

	//标题划过移出
	navList.hover( function() {
		clearTimeout(delayFun);
		STOP();
		N=navList.index(this);
		imgField.stop().animate({
			marginTop:-N*(imgList.height())
		},turnT);
		$(this).addClass('hover').siblings().removeClass('hover');
	}, function() {
		N++;
		delayFun=setTimeout(GO,T)
	});
	//图片划过移出
	imgList.hover( function() {
		N=imgList.index(this);
		navList.eq(N).trigger('mouseover');
	}, function() {
		navList.eq(N).trigger('mouseleave');
	});
	//左切换
	btnPrev.click( function() {
		if(P==1) {
			navField.animate({
				marginLeft:-turnPage*navListW*(turnPages-1)+'px'
			},turnT);
			P=turnPages;
		} else {
			STOP();
			P--;
			navField.animate({
				marginLeft:-turnPage*navListW*(P-1)+'px'
			},turnT);
		}
		navList.eq((P-1)*turnPage).trigger('mouseover');
		GO();
	});
	//右切换
	btnNext.click( function() {
		if(P==turnPages) {
			navField.animate({
				marginLeft:0
			},turnT);
			P=1;
		} else {
			STOP();
			P++;
			navField.animate({
				marginLeft:-turnPage*navListW*P+'px'
			});
		}
		navList.eq((P-1)*turnPage).trigger('mouseover');
		GO();
	});

基于jQuery的可用于选项卡及幻灯的切换插件

基于jQuery的可用于选项卡及幻灯的切换插件
最近公司项目页面中用到选项卡与幻灯比较多,特地写了个集选项卡、幻灯片与播放控制于一体的插件,同页面可多次使用。思路就不说了,记得以前写过一个自动切换的幻灯插件:http://mrthink.net/jq-plugin-ifadeslide/,思路有部分是类似的。当然,本文中插件源码中也有注释~
插件核心代码:点此查看样例

$.fn.WIT_SetTab=function(iSet){
	/*
	 * @Mr.Think
	 * Nav: 导航钩子;
	 * Field:切换区域
	 * K:初始化索引;
	 * CurCls:高亮样式;
	 * Auto:是否自动切换;
	 * AutoTime:自动切换时间;
	 * OutTime:淡入时间;
	 * InTime:淡出时间;
	 * CrossTime:鼠标无意识划过时间
	 * Ajax:是否开启ajax
	 * AjaxFun:开启ajax后执行的函数
	 */
	iSet=$.extend({Nav:null,Field:null,K:0,CurCls:'cur',Auto:false,AutoTime:4000,OutTime:100,InTime:150,CrossTime:60},iSet||{});
	var acrossFun=null,hasCls=false,autoSlide=null;
	//切换函数
	function changeFun(n){
		iSet.Field.filter(':visible').fadeOut(iSet.OutTime, function(){
			iSet.Field.eq(n).fadeIn(iSet.InTime).siblings().hide();
		});
		iSet.Nav.eq(n).addClass(iSet.CurCls).siblings().removeClass(iSet.CurCls);
	}
	//初始高亮第一个
	changeFun(iSet.K);
	//鼠标事件
	iSet.Nav.hover(function(){
		iSet.K=iSet.Nav.index(this);
		if(iSet.Auto){
			clearInterval(autoSlide);
		}
		hasCls = $(this).hasClass(iSet.CurCls);
		//避免无意识划过时触发
		acrossFun=setTimeout(function(){
			//避免当前高亮时划入再次触发
			if(!hasCls){
				changeFun(iSet.K);
			}
		},iSet.CrossTime);
	},function(){
		clearTimeout(acrossFun);
		//ajax调用
		if(iSet.Ajax){
			iSet.AjaxFun();
		}
		if(iSet.Auto){
			//自动切换
			autoSlide = setInterval(function(){
	            iSet.K++;
	            changeFun(iSet.K);
	            if (iSet.K == iSet.Field.size()) {
	                changeFun(0);
					iSet.K=0;
	            }
	        }, iSet.AutoTime)
		}
	}).eq(0).trigger('mouseleave');
}

基于jQuery淡入淡出可自动切换的幻灯插件(2011.01.11更新)

此插件是对10年8月20日的文章的更新, 之前的版本有诸多bug…抱着对读者负责的态度,又重写了一次.

更新内容:
1. 用户快速划过按钮时不触发鼠标事件;
2. 鼠标划入当前图片按钮时不闪烁;
3. 简化并优化代码.
使用方法就不详述了, 请参见源码及相关注释:点此查看DEMO

$.fn.iFadeSlide = function(iSet){
	/*
	 * iSet可选参数说明:
	 * iSet.field==>幻灯区域内的图片集
	 * iSet.ico==>按钮钩子
	 * iSet.high==>按钮高亮样式
	 * iSet.interval==>图片切换时间
	 * iSet.leaveTime==>不触发鼠标划入事件的最大时间值
	 * iSet.fadeInTime==>淡入时间
	 * iSet.fadeOutTime==>淡出时间
	 * 调用方式$(document).iFadeSlide({field:'...',ico:'...',...})
	 */
    iSet = $.extend({high:'high',interval:3000,leaveTime:150,fadeOutTime:400,fadeInTime:400},iSet);
    var imgField = $(iSet.field || '#slide>img');
    var icoField = $(iSet.ico || '#ico');
	var curIndex = 0;
    var slideInterval = iSet.interval || 3000;
    var hoverTime = iSet.leaveTime || 150;
    var fadeOutTime = iSet.fadeOutTime || 400;
    var fadeInTime = iSet.fadeInTime || 400;
    var icos=null, fastHoverFun = null, autoSlideFun = null, hasIcoHighCls = null, changeFun = null,max=null;;
    var icoHtml = '<ul>';
	max=imgField.size();
	//按图片传入对应的按钮
    imgField.each(function(i){
        icoHtml += '<li>' + (i + 1) + '</li>';
    });
    icoHtml += '</ul>';
    icoField.append(icoHtml);
	//淡入淡出函数
    changeFun = function(n){
        imgField.filter(':visible').fadeOut(fadeOutTime, function(){
            imgField.eq(n).fadeIn(fadeInTime)
            icos.eq(n).addClass(iSet.high).siblings().removeClass(iSet.high);
        });
    }
    icos = icoField.find('ul>li');
	//为第一个按键初始化高亮
    icos.first().addClass(iSet.high);
	//按钮鼠标划入划出事件
    icos.hover(function(){
        clearInterval(autoSlideFun);
        curIndex = icos.index(this);
        hasIcoHighName = $(this).hasClass(iSet.high);
		//setTimeout避免用户快速(无意识性划过)划过时触发事件
        fastHoverFun = setTimeout(function(){
			//鼠标划入当前图片按钮时不闪烁
            if (!hasIcoHighName) {
                changeFun(curIndex);
            }
        }, hoverTime);
    }, function(){
        clearTimeout(fastHoverFun);
		//自动切换
        autoSlideFun = setInterval(function(){
            curIndex++;
            changeFun(curIndex);
            if (curIndex ==max ) {
				changeFun(0);
                curIndex = 0;
            }
        }, slideInterval)
    }).eq(0).trigger('mouseleave');

    //当鼠标划入图片区域时停止切换
    imgField.hover(function(){
        curIndex = imgField.index(this);
        clearInterval(autoSlideFun);
    }, function(){
        icos.eq(curIndex).trigger('mouseleave');
    });
}