17

I have a drag UI program, where the mouse cursor on the draggable element changes to a grabbing hand on click.

The problem is, I allow the drag to happen anywhere on screen, and the cursor changes over anchor tags, etc...

I've tried $('*').addClass('grabbing'), but it's REALLY expensive.

Is there a simple easy code efficient way to handle this?

Wesley
  • 5,381
  • 9
  • 42
  • 65

6 Answers6

13

Do it at the CSS level:

* {
   cursor: pointer;
}

doing it in jquery forces it to iterate every single node in the dom and rewrite its css classes. On a long document, that's a huge waste of time.

Marc B
  • 356,200
  • 43
  • 426
  • 500
  • 1
    But this will always be active. The cursor needs to change only while the mouse is down. It needs to happen in Javascript somehow. – Wesley Oct 12 '11 at 15:47
  • You can dynamically add/remove css rules via javascript. Just do it from within the onmousedown/onmouseup and it should be quicker than adding/removing classes from every dom node on the page. – Marc B Oct 12 '11 at 15:48
  • @Mark B Cool. Can you provide a new answer with an example? I'll give it a shot and if it works right I'll mark it. – Wesley Oct 12 '11 at 15:59
  • Same problem as the other answer - Other CSS elements and classes will override this if they specify a cursor. – Mike Christensen Oct 12 '11 at 16:03
  • 1
    @mike: there's always `!important`. – Marc B Oct 12 '11 at 16:32
  • @MarcB It seems I can add but not remove with this. If you figure out the code and post it as an answer I'll mark it. There is a JQuery Rule plugin that might work. – Wesley Oct 12 '11 at 17:03
  • @Wesley: .cssRules and .rules are just arrays. you can use regular array operations to remove a particular rule by deleting its corresponding array element. – Marc B Oct 12 '11 at 17:08
  • Can add as a subclass with !important to preserve without dynamically adding rules. `body.loading-cursor *{ cursor: wait !important; }` – Alistair R Nov 24 '17 at 03:27
  • 2
    still doesn't set the cursor for the whole page when BODY is shorter than 100% – Charon ME Mar 23 '22 at 11:03
2

I tried most of these, but not all elements will display the cursor. The quick and dirty method is to iterate the entire dom and set the cursor for each element.

document.querySelectorAll('*').forEach(function(node) {
    node.style.cursor = 'progress';
});

Execute ajax or whatever here....Followed by:

document.querySelectorAll('*').forEach(function(node) {
    node.style.cursor = 'default';
});
2

Though this is not a direct answer to this question but I want to draw attentions to that we can solve the problem differently.

By putting an empty fullscreen div on top of everything except drop zones, activate it after mousedown event. So we can simply change cursor for entire screen through :hover class of that div .

Makan
  • 641
  • 8
  • 13
2

try this

$('body').addClass('grabbing');

OR

$(document).addClass('grabbing');

//EDITED ANSWER

$('body').mousedown(function(e){
    $(this).css({'cursor':'pointer'});
}).mouseup(function(e){
    $(this).css({'cursor':'auto'});
});

If you firebug is on, you can see the changes in body style tag. But some how it's not working. You can take it as a reference and try similar approach the get solution.

Vikas Naranje
  • 2,350
  • 5
  • 30
  • 40
1

When you need it, you can invoke a single line of javascript:

document.body.style.setProperty('cursor', 'pointer');

When you want to undo it again, you can execute another single line:

document.body.removeAttribute('style'); 
Rounin
  • 27,134
  • 9
  • 83
  • 108
0

You can add a new stylesheet to the page/site.

https://codepen.io/Swell_boy/pen/oNMBbKq

const css = "* { cursor: grabbing !important; }",
  styletag = document.createElement("style");

styletag.type = "text/css";
if (styletag.styleSheet) {
  styletag.styleSheet.cssText = css;
} else {
  styletag.appendChild(document.createTextNode(css));
}

document.addEventListener("mouseup", function myFunction_Default() {
  styletag.remove();
});

document.addEventListener("mousedown", function myFunction_Grab() {
  document.body.appendChild(styletag);
});
Swell_boy
  • 1
  • 2