JS数量输入控件

   很早看到kissy首页 有数量输入控件,就随便看了下功能 感觉也不怎么难 所以也就试着自己也做了一个, 当然基本的功能和他们的一样,只是用了自己的编码思想来解决这么一个问题。特此给大家分享下!kissy demo链接 

  个人编写的 demo链接

  下面来一步步分析下我当初写代码的思路:

   1. 首先是HTMl代码如下:

<h3>demo1:步长为0.8,下限为0, 默认是1</h3>

<div id="demo1"></div>

<button id="s40">设为40</button>

<button id="increase">加一步</button>

<button id="decrease">减一步</button>

  而我打开控件demo页面时候 在火狐游览器firebug看到如下代码:

  JS数量输入控件

也就是说 <div id="demo1"></div> 里面的span input代码是JS自动生成的。

 2. 我JS代码做了如下事情:

      1.  先判断传进来的容器类型判断. 支持 demo1,#demo1,.demo1,$('#demo1') 这几种容器类型的传参数。如下代码判断:

/*

     * 判断传进来的容器参数类型

     */

    _type: function(){

        var self = this,

            _config = self.config,

            _cache = self.cache;

        if(_config.container != '') {



            if($.isPlainObject(_config.container)) {

            _config.container = _config.container;



            }else if(/^\./.test(_config.container)){

                _config.container = $(_config.container);



            }else if(/^#/.test(_config.container)) {

                _config.container = $(_config.container);



            }else if($('#' + _config.container)) {

                _config.container = $('#' + _config.container);



            }else {

                alert('传参的类型有误!请重新传参!');

            }



        }else {

            return;

        }

    },

      2. 渲染相对应容器里面的代码,也就是span input标签那些HTML代码。如下:

/*

     * 渲染html

     */

    _renderHTML: function(){

        var self = this,

            _config = self.config,

            _cache = self.cache;

        var html = '';

        html += '<span class="'+_config.elCls+'-amount-wrap">' + 

                    '<input type="text" title="请输入数字" value="'+_config.val+'" class="'+_config.elCls+'-amount-input"/>' +

                    '<span class="'+_config.elCls+'-amount-increase"></span>' + 

                    '<span class="'+_config.elCls+'-amount-decrease"></span>' + 

                '</span>';

        $(_config.container).append(html);

    },

  3. 绑定事件(包括点击,↑↓键操作等)。

     1. 点击下一页按钮 或者↑ 操作时候 调用 增加方法:increase 代码如下:

/*

     * 增加方法 获取input值 然后加个步长 (每次点击时候 判断此值是否大于maxVal)

     * @method {increase public}

     */

    increase: function() {

        var self = this,

            _config = self.config,

            _cache = self.cache;



        var inputVal = $.trim($('.' + _config.elCls + "-amount-input",_config.container).attr('value'));

        if(inputVal * 1 < _config.maxVal * 1) {

            

            var curVal = self._addFun(inputVal * 1,_config.step * 1);

            if(curVal >= _config.maxVal * 1) {

                curVal = _config.maxVal * 1;

            }

            $('.' + _config.elCls + "-amount-input",_config.container).val(curVal);

            $('.' + _config.elCls + "-amount-input",_config.container).attr('value',curVal);



            // 回调

            _config.nextFunc && $.isFunction(_config.nextFunc) && _config.nextFunc({value:curVal});

        }

            

    },

     2. 点击上一页按钮时候 或者 ↓键操作 时候 调用 decrease(减少方法)。如下代码:

/*

     * 减少方法 获取input值 然后减去步长 (每次点击时候 判断此值是否大于minVal)

     * @method {decrease public}

     */

    decrease: function() {

        var self = this,

            _config = self.config;

        var inputVal = $.trim($('.' + _config.elCls + "-amount-input",_config.container).attr('value'));

        if(inputVal * 1 > _config.minVal * 1) {

            var curVal = self._subtraction(inputVal * 1, _config.step * 1);

            if(curVal <= _config.minVal * 1) {

                curVal = _config.minVal * 1;

            }

            $('.' + _config.elCls + "-amount-input",_config.container).val(curVal);

            $('.' + _config.elCls + "-amount-input",_config.container).attr('value',curVal);



            // 回调

            _config.prevFunc && $.isFunction(_config.prevFunc) && _config.prevFunc({value:curVal});

        }

    },

     3. 同样支持在外部设置值 比如 我new一个实例后 我想点击一个按钮后 直接让此到某个值上 可以直接用new出来的实例调用setVal 方法。代码如下:

/*

     * 可以供外部直接设置值

     * @method {setVal public} 

     */

    setVal: function(val) {

        var self = this,

            _config = self.config;



        // 简单的判断下 此值是否是数字型的

        if(/\d/.test(val)) {

            $('.' + _config.elCls + "-amount-input",_config.container).val(val);

            $('.' + _config.elCls + "-amount-input",_config.container).attr('value',val);

        }

    },

     4. 由于需求不断的变增 所以配置项时候 步长有可能是小数 比如 点击一下 增加0.5步长 那么在计算的时候 会有误差(因为计算机存储的是以2进制存储的),那么处理这样的方法用到了 上一篇文章  关于javascript中对浮点加,减,乘,除的精度分析 .

可配置的参数如下

container  必须,控件插入的容器 默认为空
 val  1          // input初始值 默认为1 可以根据自己配置
 step  1,        // 步长 一次改变的变化值 默认为 1
 minVal  0,       // 限下值 默认为0
 maxVal  100,   // 限上值 默认为100
 elCls  'data', // 自定义的前缀的类名 默认为data
 prevFunc   点击上一页按钮 的回调函数
 nextFunc   点击下一页按钮的 回调函数

下面贴下HTML代码如下:

<h3>demo1:步长为0.8,下限为0, 默认是1</h3>

<div id="demo1"></div>

<button id="s40">设为40</button>

<button id="increase">加一步</button>

<button id="decrease">减一步</button>

CSS代码:

.data-amount-wrap{position:relative;height:28px;display:block}

    .data-amount-input{

        color: #666;

        font-size: 12px;

        margin:0;

        padding:3px 2px 0 3px;

        height:26px;

        border:1px solid;

        border-color:#848484 #E0E0E0 #E0E0E0 #848484;

        width:60px;

        line-height:26px;

        margin-left:16px;

    }

    .data-amount-increase,.data-amount-decrease{

        position: absolute;

        /*width:16px;height: 14px;*/cursor: pointer;

        width:0;height:0;overflow:hidden;

        border-style:solid;

    }

    .data-amount-increase{left:85px;top:1px;border-width: 14px 0 14px 14px;border-color:transparent  transparent  transparent green;}

    .data-amount-decrease{left:0;top:1px;border-width: 14px 14px 14px 0;border-color:transparent red transparent  transparent ;}

    button{margin:15px 0 0;}
View Code

JS代码如下:

/**

 * 数量输入控件

 */



 function Amount(options) {

    

    this.config = {

        container : '',      // 必须,控件插入的容器 默认为空

        val       : 1,       // 初始值 默认为1

        step      : 1,       // 一次改变的变化值 默认为1

        minVal    : 0,       // 限下值 默认为0

        maxVal    : 100,     // 限上值 默认为100

        elCls     : 'data',  // 自定义的前缀的类名 默认为data

        prevFunc  : null,    // 点击上一页回调函数

        nextFunc  : null     // 点击下一页回调函数

    };



    this.cache = {

        decimalLen : 1  // 默认为1

    };



    this.init(options);

 }

 

 Amount.prototype = {

    

    constructor: Amount,



    init:function(options){

        

        this.config = $.extend(this.config,options || {});

        var self = this,

            _config = self.config,

            _cache = self.cache;

        

        // 先判断传进来的容器类型

        self._type();

        

        // 渲染HTML代码

        self._renderHTML();

        

        // 点击事件

        self._bindEnv();

    },

    /*

     * 判断传进来的容器参数类型

     */

    _type: function(){

        var self = this,

            _config = self.config,

            _cache = self.cache;

        if(_config.container != '') {



            if($.isPlainObject(_config.container)) {

            _config.container = _config.container;



            }else if(/^\./.test(_config.container)){

                _config.container = $(_config.container);



            }else if(/^#/.test(_config.container)) {

                _config.container = $(_config.container);



            }else if($('#' + _config.container)) {

                _config.container = $('#' + _config.container);



            }else {

                alert('传参的类型有误!请重新传参!');

            }



        }else {

            return;

        }

    },

    /*

     * 渲染html

     */

    _renderHTML: function(){

        var self = this,

            _config = self.config,

            _cache = self.cache;

        var html = '';

        html += '<span class="'+_config.elCls+'-amount-wrap">' + 

                    '<input type="text" title="请输入数字" value="'+_config.val+'" class="'+_config.elCls+'-amount-input"/>' +

                    '<span class="'+_config.elCls+'-amount-increase"></span>' + 

                    '<span class="'+_config.elCls+'-amount-decrease"></span>' + 

                '</span>';

        $(_config.container).append(html);

    },

    /*

     * 点击事件

     */

    _bindEnv: function() {

        var self = this,

            _config = self.config,

            _cache = self.cache;



        // 点击事件 事件代理

        $(_config.container).unbind('click');

        $(_config.container).bind('click',function(e){

            var target = e.target;

            if($(target).hasClass(_config.elCls+"-amount-increase")) {

                // 执行increase method

                self.increase();



            }else if($(target).hasClass(_config.elCls+"-amount-decrease")) {

                // 执行 decrease method

                self.decrease();

            }

        });

        

        // 键盘事件 键盘向上 键码是38 向下是 40

        $('.' + _config.elCls+"-amount-input",_config.container).keyup(function(e){

            

            var keyCode = e.keyCode;

            if(keyCode == 40) {

                self.decrease();

            }else if(keyCode == 38) {

                self.increase();

            }

        });



    },

    /*

     * 增加方法 获取input值 然后加个步长 (每次点击时候 判断此值是否大于maxVal)

     * @method {increase public}

     */

    increase: function() {

        var self = this,

            _config = self.config,

            _cache = self.cache;



        var inputVal = $.trim($('.' + _config.elCls + "-amount-input",_config.container).attr('value'));

        if(inputVal * 1 < _config.maxVal * 1) {

            

            var curVal = self._addFun(inputVal * 1,_config.step * 1);

            if(curVal >= _config.maxVal * 1) {

                curVal = _config.maxVal * 1;

            }

            $('.' + _config.elCls + "-amount-input",_config.container).val(curVal);

            $('.' + _config.elCls + "-amount-input",_config.container).attr('value',curVal);



            // 回调

            _config.nextFunc && $.isFunction(_config.nextFunc) && _config.nextFunc({value:curVal});

        }

            

    },

    /*

     * 减少方法 获取input值 然后减去步长 (每次点击时候 判断此值是否大于minVal)

     * @method {decrease public}

     */

    decrease: function() {

        var self = this,

            _config = self.config;

        var inputVal = $.trim($('.' + _config.elCls + "-amount-input",_config.container).attr('value'));

        if(inputVal * 1 > _config.minVal * 1) {

            var curVal = self._subtraction(inputVal * 1, _config.step * 1);

            if(curVal <= _config.minVal * 1) {

                curVal = _config.minVal * 1;

            }

            $('.' + _config.elCls + "-amount-input",_config.container).val(curVal);

            $('.' + _config.elCls + "-amount-input",_config.container).attr('value',curVal);



            // 回调

            _config.prevFunc && $.isFunction(_config.prevFunc) && _config.prevFunc({value:curVal});

        }

    },

    /*

     * 可以供外部直接设置值

     * @method {setVal public} 

     */

    setVal: function(val) {

        var self = this,

            _config = self.config;



        // 简单的判断下 此值是否是数字型的

        if(/\d/.test(val)) {

            $('.' + _config.elCls + "-amount-input",_config.container).val(val);

            $('.' + _config.elCls + "-amount-input",_config.container).attr('value',val);

        }

    },

    /*

     * JS加法 解决精度问题

     * @method {_addFun private}

     * @param {arg1,arg2} int或者float,double

     */ 

    _addFun: function(arg1,arg2) {

         var firstArg,

             lastArg,

             differ,

             m;

        try{

            firstArg = arg1.toString().split('.')[1].length;

        }

        catch (e){

            firstArg = 0;

        }

        try{

            lastArg = arg2.toString().split('.')[1].length;

        }

        catch (e){

            lastArg = 0;

        }

        differ = Math.abs(firstArg - lastArg);

        m = Math.pow(10,Math.max(firstArg,lastArg));

        if(differ > 0) {

            var dm = Math.pow(10,differ);

            if(firstArg > lastArg) {

                arg1 = Number(arg1.toString().replace(".", ""));

                arg2 = Number(arg2.toString().replace(".", "")) * dm;



            }else {

                arg1 = Number(arg1.toString().replace(".", "")) * dm;

                arg2 = Number(arg2.toString().replace(".", ""));

            }

        }else {

            arg1 = Number(arg1.toString().replace(".", ""));

            arg2 = Number(arg2.toString().replace(".", ""));

        }

        return (arg1 + arg2) / m;

    },

    /*

     * JS减法 解决精度问题

     * @method {_subtraction private}

     * @param {arg1,arg2} int或者float,double

     */

    _subtraction: function(arg1,arg2) {

        var firstArg,

         lastArg,

         differ,

         m;

         try{

            firstArg = arg1.toString().split('.')[1].length;

         }catch (e){

            firstArg = 0;

         }



         try{

            lastArg = arg2.toString().split('.')[1].length;

         }

         catch (e){

            lastArg = 0;

         }

         differ = Math.pow(10, Math.max(firstArg, lastArg));

         m = (firstArg > lastArg) ? firstArg : lastArg;

         return ((arg1 * differ - arg2 * differ) / differ).toFixed(m);

    }

 };
View Code

初始化代码如下:

 // 初始化

     $(function(){

        var a = new Amount({

            container : '#demo1',

            step : '0.8',

            maxVal : '100'

        })

        $('#s40').click(function(){

            a.setVal(40);

        });

        $("#increase").click(function(){

            a.increase();

        });



        $("#decrease").click(function(){

            a.decrease();

        });

     });

 

demo下载

你可能感兴趣的:(js)