If the condition is not met when the mouse moves quickly

CSS

.selected { background-color: Red; color: #ffffff; } 

JQuery

 $(document).on('mousemove', '#mytable tr', function (e) { var currentColoumn = $(e.target).closest('td').index(); if ($(this).find("td").eq(currentColoumn).hasClass('selected') == true) { e.preventDefault(); return false; } }); 

HTML

 <table border="1" id="mytable "> <tr> <td> 9:30 AM </td> <td> 30 </td> <td> </td> <td class="selected"> SELECTED </td> <td> </td> </tr> </table> 

I need to check the condition in tr mouse move, where if td has the class selected, mouse movement stops. If the condition is not met when the mouse moves quickly

Demo

+4
source share
6 answers

As you use on here, attaches an event listener to the document and applies a callback to any mousemove events for the rows in the #mytable element. This means that the on internal call is converted to a delegate call.
As a rule, I am all for delegating events for obvious reasons (performance is the most obvious of all). However, when you delegate mouse events, your handler is called every time the event fires. When does the mouse not move somewhere in the document ? When the client reads, the window is minimized or not focused.

Although jQuery hides this, your code actually does this:

 document.body.addEventListener('mousemove',function(e) { var parent, target = (e = e || window.event).target || e.srcElement; if (target.tagName.toLowerCase() === 'tr') {//this reverse DOM lookup is probably cached, but anyway parent = target; while(parent = parent.parentNode) {//or something if (parent.getAttribute('id') === 'myTable') { break; } if (parent === document.body) {//not child of #myTable return e; } } if (yourCallbackFunction.apply(target, [e]) === false) {//remember: return false in jQ == preventDefault + stopPropagation: e.preventDefault(); e.stopPropagation(); } } }, false); 

The callback is only called when the element is a child of #mytable , but every time the mouse moves, an event handler is called!
When delegating such events, it would be wiser to do this:

 $('#myTable').on('mousemove', 'tr', function() { //your code here }); 

Thus, the event handler is called only when the mousemove event occurs inside the #mytable element. Since this is all that you are interested in, what you should do.

The violin you are associated with is also packed with live calls. live deprecated for many years, one of the reasons: it was slooow.
Another thing to look for if the problem is speed: avoid excessive DOM calls using closures, for example. DOM calls are slow!

If speed is still a problem, do not use jQuery: use VanillaJs if everything is done correctly ... it will always be faster than lib

+3
source

I think the approach just needs some tweaking. Constraints can be calculated at the click of a cell; when the mouse moves, you know when to stop staining cells.

Here's a breakdown:

 jQuery(function($) { document.onselectstart = function () { return false; } var $table = $('#contentPlaceHolderMain_tableAppointment'), columns = [], dragInfo = null; $table.find('td').each(function() { var i = $(this).index(); (columns[i] = columns[i] || []).push(this); }); 

This creates a composite array so that you can reference each column more easily. This will come in handy later.

  $table.on('mouseup', function() { // reset selection dragInfo = null; }); 

This is the same as the previous code, except that you notice two differences:

  • I am setting the click event handler to $table instead of document ; this prevents some overhead from getting clicks outside the table.

  • Since .live() deprecated, .on() should be used instead.

Go to the mousedown handler.

  $table.on('mousedown', 'td', function() { var $this = $(this), columnIndex = $this.index(); if ($this.is('.selected') || columnIndex < 2) { return; } var thisRow = $this.parent().index(), selectionRowAbove = -Infinity, selectionRowBelow = Infinity; $.each(columns[columnIndex], function(rowIndex) { if ($(this).is('.selected')) { if (rowIndex < thisRow && rowIndex > selectionRowAbove) { selectionRowAbove = rowIndex; } else if (rowIndex > thisRow && rowIndex < selectionRowBelow) { selectionRowBelow = rowIndex; } } }); 

By adding a listener on td instead of tr , you do not need to find the closest cell; It is calculated for you. This part of the function produces red cells above and below the current cell.

  // unmark cells $table.find(".csstdhighlight").removeClass("csstdhighlight"); dragInfo = { column: columnIndex, enclosure: { above: selectionRowAbove, below: selectionRowBelow }, min: thisRow, max: thisRow }; $this.addClass('csstdhighlight'); }); 

The last part of the function saves all the drag and drop data that you will need later.

  $table.on('mousemove', 'td', function() { if (!dragInfo) { return; } var $this = $(this), columnIndex = $this.index(), rowIndex = $this.parent().index(); if (columnIndex != dragInfo.column || rowIndex == 0 || rowIndex <= dragInfo.enclosure.above || rowIndex >= dragInfo.enclosure.below) { dragInfo = null; return; } 

These conditions ensure that the choice remains within the limits that we determined earlier.

  // mark cells var cells = [columns[columnIndex][rowIndex]]; while (dragInfo.min > rowIndex) { cells.push(columns[columnIndex][dragInfo.min--]); } while (dragInfo.max < rowIndex) { cells.push(columns[columnIndex][dragInfo.max++]); } $(cells).addClass('csstdhighlight'); }); }); 

The last part of the function marks the choice; he does this by calculating the differences between the last call, so you don’t need to mark the cells again.

Demo

+1
source

However, there is one half-solution that could be made.

Use CSS on the body to hide the actual mouse pointer, then display a fake mouse pointer (just a normal image) at the location of the mouse.

If the mouse pointer is out of bounds, stop the fake cursor in the bounding box.

I don’t know what your use case is, but it will be MUCH better if you do not hide the real mouse cursor, but display some oversized mouse cursor in the bounding box. Basically the same effect and much more convenient.

0
source

Consider a different approach to solving the problem of mousemove ceasing to secrete a cell. Instead of "stopping when moving through the cell with the selected class"

Try stopping if there is a cell with the selected class between the source cell and the current cell. This ensures that if a quick move prevents the mousemove from being delegated to your "selected" cells, it will still be able to detect that you went through one.

0
source

I think the main problem here is that the mouse does not stop at every single cell. The mouse usually looks like it moves continuously, but when I move it quickly, it jumps around, skipping large gaps between them.

I think you have already seen this affect. Therefore, you select a range of cells, not just the one you are pointing to (current cell). However, you are checking to see if the current cell is selected, and not one of the cells between the cells.

The solution is to check everything between cells to make sure they are not selected. jQuery has a filter function that does it nicely. I used your code to use the filter:

 $("#contentPlaceHolderMain_tableAppointment tr").live('mousemove', function (e) { // Compares with the last and next row index. var currentRow = $(this).closest("tr")[0].rowIndex; var currentColoumn = $(e.target).closest('td').index(); var allRows = $('#contentPlaceHolderMain_tableAppointment tr'); var previousRowIndex = parseInt(lastRow, 10); var currentRowIndex = parseInt(currentRow, 10); var traversedRows; if (previousRowIndex < currentRowIndex) traversedRows = allRows.slice(previousRowIndex, parseInt(currentRowIndex + 1)); else { traversedRows = allRows.slice(currentRowIndex, previousRowIndex) } var affectedCells = traversedRows.children(':nth-child(' + parseInt(currentColoumn + 1) + ')'); if ($(this).find("td").eq(currentColoumn).hasClass('selected') == true || affectedCells.filter('.selected').length > 0) { if (flag != false) { flag = false; e.preventDefault(); return false; } } if (currentRow == 0) { flag = false; return false; } //cross cell selection. if (colIndex != currentColoumn) { flag = false; return; } if (flag) { affectedCells.addClass('csstdhighlight'); e.preventDefault(); return false; } }); 

Violin: http://jsfiddle.net/Jg58G/7/

There is still a problem where some cells need to be selected, but this is not the case. Now that you have the row of the selected cell, you can redo the slice logic to slice in the right place. I will leave this part to you.

0
source

Please note that this is exactly what you are aiming for, but it is easy to adapt. Using mouse shortcut on calls should have better performance.

Fiddle at: http://jsfiddle.net/VJG4F/

 $(document).ready(function () { // setup var doc = this; doc.checkOver = false; doc.activeCell = { x: -1, y: -1 }; doc.lastCell = { x: -1, y: -1 }; doc.highlightClass = 'csstdhighlight'; doc.selectionClass = 'selected'; doc.selectionText = 'SELECTED'; // start checking on mousedown $('#contentPlaceHolderMain_tableAppointment td').on('mousedown', function (e) { doc.checkOver = true; // set active and last cell for reference doc.lastCell.x = doc.activeCell.x = $(this).closest('td').index(); doc.lastCell.y = doc.activeCell.y = $(this).closest("tr").index(); // highlight selected cells var cellSelector = '#contentPlaceHolderMain_tableAppointment tr:eq(' + doc.activeCell.y + ') td:eq(' + doc.activeCell.x + ')'; $(cellSelector).addClass(doc.highlightClass); // check for movement $('#contentPlaceHolderMain_tableAppointment td').on('mouseover', function (e) { if (!(doc.checkOver)) return; // get current cell for reference var currCell = { x: $(e.target).closest('td').index(), y: $(e.target).closest('tr').index() }; // verify mouse is over a different cell if ( !((currCell.y != doc.lastCell.y && currCell.y != -1) || (currCell.x != doc.lastCell.x && currCell.x != -1)) ) return false; // make sure other cells are not highlighted $('#contentPlaceHolderMain_tableAppointment td').removeClass(doc.highlightClass); // highlight selected cells var topLeft = { x: Math.min(currCell.x, doc.activeCell.x), y: Math.min(currCell.y, doc.activeCell.y) }; var botRight = { x: Math.max(currCell.x, doc.activeCell.x), y: Math.max(currCell.y, doc.activeCell.y) }; for (var x=topLeft.x;x<=botRight.x;x++) { for (var y=topLeft.y;y<=botRight.y;y++) { var cellSelector = '#contentPlaceHolderMain_tableAppointment tr:eq(' + y + ') td:eq(' + x + ')'; $(cellSelector).addClass(doc.highlightClass); } } // update last cell doc.lastCell.y = currCell.y; doc.lastCell.x = currCell.x; return false; }); // check for mouseup $('#contentPlaceHolderMain_tableAppointment td').on('mouseup', function (e) { // stop checking for movement $('#contentPlaceHolderMain_tableAppointment td').off('mouseup'); $('#contentPlaceHolderMain_tableAppointment td').off('mouseout'); // get current cell for reference var currCell = { x: $(this).closest("td").index(), y: $(this).closest('tr').index() }; // make sure cells are not highlighted $('#contentPlaceHolderMain_tableAppointment td').removeClass(doc.highlightClass); // select cells var topLeft = { x: Math.min(currCell.x, doc.activeCell.x), y: Math.min(currCell.y, doc.activeCell.y) }; var botRight = { x: Math.max(currCell.x, doc.activeCell.x), y: Math.max(currCell.y, doc.activeCell.y) }; // single cell - toggle if( topLeft.x == botRight.x && topLeft.y == botRight.y ) { var cellSelector = '#contentPlaceHolderMain_tableAppointment tr:eq(' + topLeft.y + ') td:eq(' + topLeft.x + ')'; $(cellSelector).toggleClass(doc.selectionClass); if( $(cellSelector).text() == doc.selectionText ) $(cellSelector).text(''); else $(cellSelector).text(doc.selectionText); // multi-cell, select all } else { for (var x=topLeft.x;x<=botRight.x;x++) { for (var y=topLeft.y;y<=botRight.y;y++) { var cellSelector = '#contentPlaceHolderMain_tableAppointment tr:eq(' + y + ') td:eq(' + x + ')'; $(cellSelector).addClass(doc.selectionClass); $(cellSelector).text(doc.selectionText); } } } // reset doc.checkOver = false; doc.activeCell.y = -1; doc.activeCell.x = -1; doc.lastCell.y = -1; doc.lastCell.x = -1; return false; }); return false; // prevent default }); }); 
0
source

Source: https://habr.com/ru/post/1496964/


All Articles