开发者问题收集

创建一个 JavaScript 对象

2016-08-18
65

我会说我对 javascript 和 jQuery 相当了解,嗯,足以完成工作,而且做得很好。 但是我对 js 缺乏深入的理解。

我已经创建了一些用于突出显示表格元素的函数。 ctrl+单击切换选择 shift+单击+拖动突出显示选择

我的问题与我的实现是否是最好的方式无关,但...

我如何抽象此功能,以便我可以将其添加到任何表格中。比如,如果我添加更多突出显示功能等,并将其放在自己的 .js 文件中。我如何将其附加到任何 html 表格?

抱歉,如果这个问题已经得到解答,但我想不出要搜索什么。

谢谢。

****最新代码**** 此代码位于其自己的 .js 文件中,并附加到我的表格中。 所有当前功能都在那里。我唯一担心的是 .off() 函数。就我而言,我正在重新加载新表....当我输入此内容时,我意识到我应该清空表中的 tr,而不是一直重新创建一个新表,然后我就可以摆脱 .off() 调用。

$.fn.addEvents = function(obj) 
{
console.log("Adding events to table");
var properties = $.extend(true,
    {
    shifting: false,
    ctrling: false,
    mousing: false,
    mouseenter: 0,
    mouseleave: 0,
    mousestartindex: 0,
    mouseenterindex: 0,
    mouseleaveindex: 0,
    trajectory: null,
    tmptrajectory: null
    }, obj || {});

$(document)
.off('mouseup')
.on('mouseup', function(e)
    {
    properties.mousing = false;
    properties.trajectory = null;
    })
.off("keyup")
.on("keyup", function(e)
    {
    if(e.which == 16)
        {
        properties.shifting = false;
        }
    if(e.which == 17)
        {
        properties.ctrling = false;
        }
    })
.off("keydown")
.on("keydown", function(e)
    {
    if(e.which == 16)
        {
        properties.shifting = true;
        }
    if(e.which == 17)
        {
        properties.ctrling = true;
        }
    if($(this).find('tr.selected').length > 0)
        {
        switch(e.which)
            {
            //case 37: // left
                //break;

            case 38: // up
                var index = $(this).find('tr.selected').index();
                if(index > 0)
                    {
                    $(this).find('tr').removeClass('selected');
                    $(this).find('tr td').removeClass('selected');
                    $(this).find('tr:eq(' + index + ')').addClass('selected');
                    $(this).find('tr:eq(' + index + ') td').addClass('selected');
                    }
                break;

            //case 39: // right
                //break;

            case 40: // down
                var index = $(this).find('tr.selected').index();
                if(index < $(this).find('tr').length - 2)
                    {
                    $(this).find('tr').removeClass('selected');
                    $(this).find('tr td').removeClass('selected');
                    $(this).find('tr:eq(' + (index+2) + ')').addClass('selected');
                    $(this).find('tr:eq(' + (index+2) + ') td').addClass('selected');
                    }
                break;

            case 117: // f6
                var index = $(this).find('tr.selected').index();
                if(index > 0)
                    {
                    ....
                    }
                break;

            case 118: // f7
                var index = $(this).find('tr.selected').index();
                if(index  < $(this).find('tr').length - 1)
                    {
                    ....
                    }
                break;

            default: return; // exit this handler for other keys
            }
        e.preventDefault(); // prevent the default action (scroll / move caret)
        }
    return;
    });

return $(this)
.off('click')
.off('contextmenu')
.on('click', function()
    {
    if(!properties.ctrling && !properties.shifting)
        {
        $('#datatablebody tr, #datatablebody tr td').removeClass('selected');
        $(this).addClass('selected');
        $(this).find('td').addClass('selected');
        }
    else if(properties.ctrling && $(this).hasClass('selected'))
        {
        $(this).removeClass('selected');
        $(this).find('td').removeClass('selected');
        }
    else if(properties.ctrling && !$(this).hasClass('selected'))
        {
        $(this).addClass('selected');
        $(this).find('td').addClass('selected');
        }
    })
.on('contextmenu', function(ev)
    {
    ev.preventDefault();
    $('#datatablebody tr, #datatablebody tr td').removeClass('selected');
    $(this).addClass('selected');
    $(this).find('td').addClass('selected');
    showContextMenuTR($(this).closest('tr').attr('id'), ev.clientX, ev.clientY);
    return false;
    })
.off('mousedown')
.on('mousedown', function(e)
    {
    properties.mousing = true;
    properties.mousestartindex = $(this).index();
    if(properties.shifting && properties.mousing)
        {
        multiselectrow($(this));
        }
    })
.off('mouseenter')
.on('mouseenter', function(e)
    {
    properties.mouseenter = e.clientY;
    properties.mouseenterindex = $(this).index();

    if(properties.tmptrajectory === properties.trajectory)
        {
        if(properties.shifting && properties.mousing)
            {
            multiselectrow($(this));
            }
        }
    })
.off('mouseleave')
.on('mouseleave', function(e)
    {
    properties.mouseleave = e.clientY;

    if(properties.shifting && properties.mousing)
        {
        properties.tmptrajectory = properties.mouseenter - properties.mouseleave < 0?1:-1;
        }

    if(properties.trajectory != null && properties.tmptrajectory !== properties.trajectory && $(this).index() !== properties.mousestartindex)
        {
        if(properties.shifting && properties.mousing)
            {
            multiselectrow($(this));
            }
        }

    if(properties.shifting && properties.mousing)
        {
        if(properties.trajectory == null)
            {
            properties.trajectory = properties.tmptrajectory;
            }
        else if(properties.tmptrajectory !== properties.trajectory && $(this).index() === properties.mousestartindex)
            {
            properties.trajectory = properties.tmptrajectory;
            }
        }
    })
.off('mouseup')
.on('mouseup', function(e)
    {
    properties.mousing = false;
    properties.trajectory = null;
    if(properties.shifting && properties.mousing)
        {
        multiselectrow($(this));
        }
    }); 
}

function multiselectrow(obj)
{
if($(obj).hasClass('selected'))
    {
    $(obj).removeClass('selected');
    $(obj).find('td').removeClass('selected');
    }
else
    {
    $(obj).addClass('selected');
    $(obj).find('td').addClass('selected');
    }
}
3个回答

您可以将所有这些包装在一个函数中,因为您有一些与单独选择相关的局部变量

$.fn.addEvents = function(obj) {
    var properties = $.extend(true, {
        shifting: false,
        ctrling: false,
        mousing: false,
        mouseenter: 0,
        mouseleave: 0,
        trajectory: null
    }, obj || {});

    return $(this)
        .off('click')
        .off('contextmenu')
        .on('click', function() {
            .....
        })
        .on('mouseleave', function(e) {

            //rename your local variables with `properties.` prefix
            properties.mouseleave = e.clientY;

            if (properties.shifting && properties.mousing) {
                tmptrajectory = properties.mouseenter - properties.mouseleave < 0 ? 1 : -1;
            }

            if ($(this).hasClass('selected') && properties.shifting && properties.mousing && properties.trajectory != null && properties.trajectory != tmptrajectory) {
                $(this).removeClass('selected');
                $(this).find('td').removeClass('selected');
            }
            ....
        });
}

用法

$('#datatablebody tr').addEvents({ shifting: false, ctrling: true }); //custom settings

$('#someother tr').addEvents(); //default settings
Ja9ad335h
2016-08-18

您可以将该功能添加到一个类中,然后将该类添加到您想要影响的表中... 在这里我创建了类 .myTableBeh ,并且具有该类的所有表都将具有您编程的行为。

    var shifting = false;
    var ctrling = false;
    var mousing = false;
    var mouseenter = 0;
    var mouseleave = 0;
    var trajectory = null;

    $('.myTableBeh tr')
    .off('click')
    .off('contextmenu')
    .on('click', function()
        {
        if(!ctrling)
            {
            $('.myTableBeh tr, .myTableBeh tr td').removeClass('selected');
            $(this).addClass('selected');
            $(this).find('td').addClass('selected');
            }
        else if(ctrling && $(this).hasClass('selected'))
            {
            $(this).removeClass('selected');
            $(this).find('td').removeClass('selected');
            }
        else if(ctrling && !$(this).hasClass('selected'))
            {
            $(this).addClass('selected');
            $(this).find('td').addClass('selected');
            }
        })
    .on('contextmenu', function(ev)
        {
        ev.preventDefault();
        $('.myTableBeh tr, .myTableBeh tr td').removeClass('selected');
        $(this).addClass('selected');
        $(this).find('td').addClass('selected');
        showContextMenuTR($(this).closest('tr').attr('id'), ev.clientX, ev.clientY);
        return false;
        })
    .off('mousedown')
    .on('mousedown', function(e)
        {
        mousing = true;
        multiselectrow($(this));
        })
    .off('mouseenter')
    .on('mouseenter', function(e)
        {
        mouseenter = e.clientY;
        multiselectrow($(this));
        })
    .off('mouseleave')
    .on('mouseleave', function(e)
        {
        mouseleave = e.clientY;

        if(shifting && mousing)
            {
            tmptrajectory = mouseenter - mouseleave < 0?1:-1;
            }

        if($(this).hasClass('selected') && shifting && mousing && trajectory != null && trajectory != tmptrajectory)
            {
            $(this).removeClass('selected');
            $(this).find('td').removeClass('selected');
            }

        if(shifting && mousing && trajectory == null)
            {
            trajectory = tmptrajectory;
            }
        })
    .off('mouseup')
    .on('mouseup', function(e)
        {
        mousing = false;
        trajectory = null;
        multiselectrow($(this));
        });
DIEGO CARRASCAL
2016-08-18

感谢@JAG的回答,我能够为任何处理突出显示的HTML表格创建一个不错的附加组件。

查看工作版本的fiddle,如果您发现它对您的网站有帮助或有用,请使用它。

您甚至可以实现键来在表格中上下移动tr的位置。我删除了我的实现,因为它特定于我正在从事的项目。

我这样做是为了让您必须将鼠标悬停在表格上才能与其交互,将鼠标移开以取消焦点。

https://jsfiddle.net/kwj74kg0/2/

//Add the events simply by running this
$('#dtable tr').addEvents(0);


/**
* This add on can be applied and customized to any html tr set i.e. $('#tableid tr').addEvents()
* It will add highlighting capability to the table.
* 
* Single click highlight tr
* Click -> Shift + click highlight/toggle range
* Shift+MouseDown+Drag highlight/toggle range
* Ctrl+Click toggle item
*
* 
* @author Michaela Ervin
*
* @param tabindex
* 
* Help from JAG on http://stackoverflow.com/questions/39022116/create-a-javascript-object
*/
$.fn.addEvents = function(tabindex) 
{
console.log("Adding events to table");
var properties = $.extend(true,
    {
    shifting: false,
    ctrling: false,
    mousing: false,
    mouseenter: 0,
    mouseleave: 0,
    mousestartindex: 0,
    mouseenterindex: null,
    mouseleaveindex: null,
    trajectory: null,
    tmptrajectory: null
    }, {});

/**
 * Add events to closest table.  
 */
$(this)
.closest('table')
.attr('tabindex', tabindex)
.off('mouseenter')
.on('mouseenter', function()
    {
    $(this).focus();
    })
.off('mouseleave')
.on('mouseleave', function()
    {
    $(this).blur();
    properties.mousing = false;
    properties.trajectory = null;
    properties.mouseenterindex = null;
    properties.mouseleaveindex = null;
    properties.mouseintermediateindex = null;
    })
.off("keyup")
.on("keyup", function(e)
    {
    if(e.which == 16)
        {
        properties.shifting = false;
        }
    if(e.which == 17)
        {
        properties.ctrling = false;
        }
    })
.off("keydown")
.on("keydown", function(e)
    {
    if(e.which == 16)
        {
        properties.shifting = true;
        }
    if(e.which == 17)
        {
        properties.ctrling = true;
        }
    if($(this).find('tr.selected').length > 0)
        {
        switch(e.which)
            {
            //case 37: // left
                //break;

            case 38: // up
                var index = $(this).find('tr.selected').index();
                if(index > 0)
                    {
                    $(this).find('tr').removeClass('selected');
                    $(this).find('tr td').removeClass('selected');
                    $(this).find('tr:eq(' + index + ')').addClass('selected');
                    $(this).find('tr:eq(' + index + ') td').addClass('selected');
                    }
                break;

            //case 39: // right
                //break;

            case 40: // down
                var index = $(this).find('tr.selected').index();
                if(index < $(this).find('tr').length - 2)
                    {
                    $(this).find('tr').removeClass('selected');
                    $(this).find('tr td').removeClass('selected');
                    $(this).find('tr:eq(' + (index+2) + ')').addClass('selected');
                    $(this).find('tr:eq(' + (index+2) + ') td').addClass('selected');
                    }
                break;  

            case 117: // f6
                var index = $(this).find('tr.selected').index();
                if(index > 0)
                    {
                    //Function to move tr 'up'.
                    }
                break;

            case 118: // f7
                var index = $(this).find('tr.selected').index();
                if(index  < $(this).find('tr').length - 1)
                    {
                    //Function to move tr 'down'.
                    }
                break;

            default: return; // exit this handler for other keys
            }
        e.preventDefault(); // prevent the default action (scroll / move caret)
        }
    return;
    });


/**
 * Add tr specific events
 */
return $(this)
.off('click')
.on('click', function()
    {
    if(!properties.shifting && properties.mouseenterindex != null)
        {
        properties.mouseenterindex = null;
        properties.mousing = false;
        }

    if(!properties.ctrling && !properties.shifting && properties.mouseenterindex == null)
        {
        $(this).parent().find('tr').removeClass('selected');
    $(this).parent().find('tr td').removeClass('selected');
        $(this).addClass('selected');
        $(this).find('td').addClass('selected');
        }
    else if(properties.ctrling && $(this).hasClass('selected'))
        {
        $(this).removeClass('selected');
        $(this).find('td').removeClass('selected');
        }
    else if(properties.ctrling && !$(this).hasClass('selected'))
        {
        $(this).addClass('selected');
        $(this).find('td').addClass('selected');
        }

    if(properties.mouseenterindex == null)
        {
        properties.mouseenterindex = $(this).index();
        }
    else if(properties.shifting && properties.mouseenterindex != null)
        {
        properties.mouseleaveindex = $(this).index();
        highlightRange($(this).parent(), properties.mouseenterindex, properties.mouseleaveindex, properties.mouseenterindex);
        properties.mouseenterindex = null;
        properties.mouseleaveindex = null;
        }
    })
.off('contextmenu')
.on('contextmenu', function(ev)
    {
    ev.preventDefault();
    $(this).parent().find('tr').removeClass('selected');
    $(this).parent().find('tr td').removeClass('selected');
    $(this).addClass('selected');
    $(this).find('td').addClass('selected');
    //Put your context menu here
    return false;
    })
.off('mousedown')
.on('mousedown', function(e)
    {
    properties.mousing = true;
    properties.mousestartindex = $(this).index();
    if(properties.shifting && properties.mousing && properties.mouseenterindex == null)
        {
        multiselectrow($(this));
        }
    })
.off('mouseenter')
.on('mouseenter', function(e)
    {
    properties.mouseenter = e.clientY;

    if(properties.tmptrajectory === properties.trajectory)
        {
        if(properties.shifting && properties.mousing)
            {
            multiselectrow($(this));
            }
        }
    })
.off('mouseleave')
.on('mouseleave', function(e)
    {
    properties.mouseleave = e.clientY;

    if(properties.shifting && properties.mousing)
        {
        properties.tmptrajectory = properties.mouseenter - properties.mouseleave < 0?1:-1;
        }

    if(properties.trajectory != null && properties.tmptrajectory !== properties.trajectory && $(this).index() !== properties.mousestartindex)
        {
        if(properties.shifting && properties.mousing)
            {
            multiselectrow($(this));
            }
        }

    if(properties.shifting && properties.mousing)
        {
        if(properties.trajectory == null)
            {
            properties.trajectory = properties.tmptrajectory;
            }
        else if(properties.tmptrajectory !== properties.trajectory && $(this).index() === properties.mousestartindex)
            {
            properties.trajectory = properties.tmptrajectory;
            }
        }
    })
.off('mouseup')
.on('mouseup', function(e)
    {
    properties.mousing = false;
    properties.trajectory = null;
    if(!properties.shifting)
        {
        properties.mouseenterindex = null;
        properties.mouseleaveindex = null;
        }
    });
}

function multiselectrow(obj)
{
if($(obj).hasClass('selected'))
    {
    $(obj).removeClass('selected');
    $(obj).find('td').removeClass('selected');
    }
else
    {
    $(obj).addClass('selected');
    $(obj).find('td').addClass('selected');
    }
}

function highlightRange(obj, start, end, mouseenterindex)
{
if(start < end)
    {
    for(var i=start; i<=end; i+=1)
        {
        if(i !== mouseenterindex)
            {
            multiselectrow($(obj).find('tr').eq(i));
            }
        }
    }
else
    {
    for(var i=start; i>=end; i-=1)
        {
        if(i !== mouseenterindex)
            {
            multiselectrow($(obj).find('tr').eq(i));
            }
        }
    }
}
Michaela Ervin
2016-08-25