javascript - shift多选事件

业务需求:一般的多选,我们会给用户很多的 checkbox,让用户挨个点击,我们可以做一个优化,像 PC 一样,按住 shift 可以多选。

shift多选事件

直接调用原生的 onkeydown、onkeyup,如果代码组织得不好,会导致代码混乱,这里进行一个简单的封装。

想要进一步封装组件,需要有一定的计算能力,维护成本较高,但是相对的,能获取不错的用户体验。

注意:侦听的是 document 的事件,这是个全局的事件,事件不用之后,需要进行解绑,避免产生冲突。

/**
 * Shift多选事件,注意需要调用unbind()解绑
 *
 * E.G.:
 * var shiftClickEvent = new ShiftClickEvent({
 *         onkeydown: function () {
 *        },
 *         onkeyup: function () {
 *        }
 *    });
 */
function ShiftClickEvent(opts) {
	var isPressing = false;
	document.onkeydown = function (event) {
		event.preventDefault();
		var e = event || window.event || arguments.callee.caller.arguments[0];
		if (isPressing === false && e && e.keyCode === 16) {
			isPressing = true;
			if (opts.onkeydown !== undefined) {
				opts.onkeydown();
			}
		}
	};
	document.onkeyup = function (event) {
		event.preventDefault();
		var e = event || window.event || arguments.callee.caller.arguments[0];
		if (e && e.keyCode === 16) {
			isPressing = false;
			if (opts.onkeyup !== undefined) {
				opts.onkeyup();
			}
		}
	};
	return {
		isPressingShift: function () {
			// 是否按住Shift按键
			return isPressing;
		},
		unbind: function () {
			document.onkeydown = undefined;
			document.onkeyup = undefined;
		}
	}
}

样例

jquery环境下,封装一个可以多选的表格。

css样式
/**
 * 去除浏览器默认的Shift多选效果
 */
.cannot-select {
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
}
/**
 * 点击高亮
 */
.mul-table-click{
    background-color: lightyellow;
}
/**
 * 单选高亮
 */
.mul-table-select{
    background-color: lightyellow;
}
/**
 * 多选高亮
 */
.high-light-multi{
    background-color: lightgray;
}
jquery控件封装
(function () {

    function MultiSelectTable(options) {
        var table = options.el;
        table.addClass('mul-table-cannot-select');
        var trList = [], currentData = [];

        // Shift多选,需要记住前一次点击的行,和正在点击的行
        var preClickRow = -1, curClickRow = -1;
        // Shift事件
        var shiftClickEvent = new ShiftClickEvent({
            onkeydown: function () {
                preClickRow = -1;
                for (var i = 0; i < trList.length; i++) {
                    trList[i].removeClass('mul-table-multi');
                }
            },
            onkeyup: function () {
                if (preClickRow === -1) {
                    curClickRow = -1;
                }
                if (curClickRow !== -1) {
                    if (curClickRow < preClickRow) {
                        curClickRow = preClickRow + curClickRow;
                        preClickRow = curClickRow - preClickRow;
                        curClickRow = curClickRow - preClickRow;
                    }
                    highLightRowByRange(preClickRow, curClickRow);
                    options.onMultiSelect(preClickRow, curClickRow);
                }
            }
        });

        // 行点击事件
        function bindEvent(tr, data, i) {
            tr.click(function (evt) {
                if (shiftClickEvent.isPressingShift()) {
                    //按住Shift的时候,不触发点击事件
                    preClickRow = curClickRow;
                    curClickRow = i;
                } else {
                    //高亮点击行
                    curClickRow = i;
                    highLightRow(i);
                    options.onClickRow(data, i);
                }
            });
        }

        // 渲染数据列表(值得改造的代码,可以用模版引擎优化)
        function render(list) {
            currentData = list;
            if (list !== undefined) {
                for (var i = 0; i < list.length; i++) {
                    var ele = list[i];
                    var tr = $('<tr id="grid-' + i + '"><td>' + ele[options.textField] + '</td></tr>');
                    bindEvent(tr, ele, i);
                    trList.push(tr);
                    tr.appendTo(table);
                }
            }
        }

        /**
         * 高亮选中的行
         * @param start 开始行
         * @param end   结束行
         */
        function highLightRowByRange(start, end) {
            for (var i = 0; i < trList.length; i++) {
                var ele = trList[i];
                ele.removeClass('mul-table-click');
                if (i >= start && i <= end) {
                    ele.addClass('mul-table-multi');
                } else {
                    ele.removeClass('mul-table-multi');
                }
            }
        }

        /**
         * 高亮选中的行
         * @param id 行号
         */
        function highLightRow(id) {
            var idStr = 'grid-' + id;
            for (var j = 0; j < trList.length; j++) {
                var ele = trList[j];
                ele.removeClass('mul-table-multi');
                if (idStr === trList[j].attr('id')) {
                    ele.addClass('mul-table-click');
                } else {
                    ele.removeClass('mul-table-click');
                }
            }
        }

        /**
         * 选中行,通过Js直接选中某一行(选中的时候,不移除多选的css样式)
         * @param id
         */
        function selectRow(id) {
            var idStr = 'grid-' + id;
            for (var j = 0; j < trList.length; j++) {
                var ele = trList[i];
                if (idStr === trList[j].attr('id')) {
                    ele.addClass('mul-table-select');
                    options.onClickRow(currentData[j], j);
                } else {
                    ele.removeClass('mul-table-select');
                }
            }
        }


        return {
            selectRow: selectRow,
            render: render,
            destroy: function () {
                //控件销毁
                table.empty();
                trList = [];
                shiftClickEvent.unbind();
            }
        }
    }

    window.MultiSelectTable = MultiSelectTable;
})();
使用以及效果
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<link href="./mul-table.css" rel="stylesheet" type="text/css"/>
<body>
<table id="table"></table>
</body>
<script src="../jquery.js" type="application/x-javascript"></script>
<script src="./mul-table.js" type="application/x-javascript"></script>
<script>
    var table = MultiSelectTable({
        onMultiSelect: function (start, end) {
            console.log(start);
            console.log(end);
        },
        onClickRow: function (data, i) {
            console.log(data);
        },
        textField: 'label'
        , el: $('#table')
    });

    table.render([
        {
            label: '1312313'
        }, {
            label: '1312313'
        }, {
            label: '1312313'
        }, {
            label: '1312313'
        }, {
            label: '1312313'
        }
    ]);
</script>
</html>

posted on 2020-10-19 21:40  疯狂的妞妞  阅读(974)  评论(0编辑  收藏  举报

导航