How to change the overall mousepointer?

S

Stefan Mueller

I've a webpage with several tables and a button. If you click the
button the javascript function calc() gets called. This function does
several calculations and now I'm looking for a way to change the
mousepointer to an hourglass while the calculations are running.

My styles look like:
<style type="text/css">
th {cursor: pointer}
th.header1 {cursor: default}
th.header2 {cursor: default}
td {cursor: default}
...
</style>

I tried:
function calc() {
document.body.style.cursor = "wait";
...
}

Because the mousepointer e.g. doesn't change on the tables I tried
th.style.cursor = "wait";
th.header1.style.cursor = "wait";
th.header2.style.cursor = "wait";
td.style.cursor = "wait";
but it doesn't work.

Is there a way to change the mousepointer everywhere with one command
and to change it back afterwards?
Or do I have to change it on each object separately? If yes, how can I
change it e.g. on <th> or <th.header1>?
 
D

David Mark

I've a webpage with several tables and a button. If you click the
button the javascript function calc() gets called. This function does
several calculations and now I'm looking for a way to change the
mousepointer to an hourglass while the calculations are running.

This is a common UI mistake. The option shouldn't even be available
to scripts IMO. You should not change _my_ cursor to an hourglass as
(unlike real software), you have no ability to enforce what it means
(mouse actions are _discarded_). Clicks - for example - during your
monopolization of the browser UI will only be _delayed_.

The proper solution is to break up your calculations into multiple
steps and use timeouts to call each step in turn. Then the user isn't
bothered. Of course, they can still interact with your interface
during the calculations (without delays), which you will have to take
into consideration (perhaps hiding part of _your_ UI until the final
calculation is complete).
 
T

Thomas 'PointedEars' Lahn

Stefan said:
I've a webpage with several tables and a button. If you click the
button the javascript function calc() gets called. This function does
several calculations and now I'm looking for a way to change the
mousepointer to an hourglass while the calculations are running.

My styles look like:
<style type="text/css">
th {cursor: pointer}
th.header1 {cursor: default}
th.header2 {cursor: default}
td {cursor: default}
...
</style>

I tried:
function calc() {
document.body.style.cursor = "wait";
...
}

Because the mousepointer e.g. doesn't change on the tables I tried
th.style.cursor = "wait";
th.header1.style.cursor = "wait";
th.header2.style.cursor = "wait";
td.style.cursor = "wait";
but it doesn't work.

Unfortunately, you have told nothing further about your code, your
environment, or your observations, which leaves the following possibilities
for failure (in order of decreasing probability):

A) `th' and `td' are not references to the corresponding element objects,
so a ReferenceError exception is thrown (check the error console!).

B) The used ECMAScript implementation, like all I know, is single-threaded.
Additionally, changes to the user interface do not become apparent before
the current execution context is left. As a result, the property value
does change but the change does not have effect. You can work around
this by planning the property change for later execution (as if it was)
in its own DOM thread:

window.setTimeout("document.body.style.cursor = 'wait';", 0);

This should not break in any DOM implementation I know. Especially
Gecko 1.9.2-based browsers are known to increase the 0 value to 10
(We have discussed this before.) If unsure, use values greater than
or equal to 10.

C) `wait' is not supported by that layout engine (which is presumably
MSHTML-compatible); first assign "hourglass", then "wait". (It is
expected that for an unsupported "wait" value the setter of the
property reverts it back to the original value in MSHTML without
throwing an exception.)

D) `th' and `td' are references to the corresponding element objects,
but that DOM implementation does not support W3C DOM Level 2 CSS.
Is there a way to change the mousepointer everywhere with one command
and to change it back afterwards?

Probably yes, but I would recommend using at least two statements.
Or do I have to change it on each object separately?

Probably not. You could insert/remove or enable/disable a stylesheet that
has the following rule:

* {
cursor: hourglass !important;
cursor: wait !important;
}
If yes, how can I change it e.g. on <th> or <th.header1>?

Hopefully there is no such tag as `<th.header1>' in your document as that
would be invalid markup. As for `<th>...</th>', you need to retrieve a
reference to the element object that represents that element.

These are really DOM basics, so RTFM first:

<http://jibbering.com/faq/#posting>


PointedEars
 
T

Thomas 'PointedEars' Lahn

David said:
This is a common UI mistake. The option shouldn't even be available
to scripts IMO. You should not change _my_ cursor to an hourglass as
(unlike real software), you have no ability to enforce what it means

Quite obviously it means that something is happening for which completion
the user needs to wait.
(mouse actions are _discarded_).

What do you consider to be "mouse actions" and what do they have to do with
the pointer cursor?
Clicks - for example - during your monopolization of the browser UI will
only be _delayed_.

Depends, but why would that preclude the pointer cursor from being changed
into an appropriate shape, given that the implementation cannot recognize
it in time by itself due to the single-threadedness of script execution?
The proper solution is to break up your calculations into multiple
steps and use timeouts to call each step in turn. Then the user isn't
bothered. Of course, they can still interact with your interface
during the calculations (without delays), which you will have to take
into consideration (perhaps hiding part of _your_ UI until the final
calculation is complete).

One calculation step executed via window.setTimeout() should suffice.


PointedEars
 
D

David Mark

Quite obviously it means that something is happening for which completion
the user needs to wait.

That is not exactly what it means. It means that nothing will happen
when - for example - you click whatever UI element is presenting that
cursor (e.g. a window). It's as if you didn't click at all.
What do you consider to be "mouse actions" and what do they have to do with
the pointer cursor?

Click and what don't they have to do with the pointer cursor?
Depends, but why would that preclude the pointer cursor from being changed
into an appropriate shape, given that the implementation cannot recognize
it in time by itself due to the single-threadedness of script execution?

But the hourglass (or whatever shape the OS is set to use) is not
appropriate to indicate that clicks will be queued up during the
delay. You might use the hourglass/pointer hybrid for this in a
desktop app. In a script, you let the browser/OS handle that.
One calculation step executed via window.setTimeout() should suffice.

That's as maybe.
 
T

Thomas 'PointedEars' Lahn

David said:
That is not exactly what it means. It means that nothing will happen
when - for example - you click whatever UI element is presenting that
cursor (e.g. a window). It's as if you didn't click at all.

ISTM you are confusing the issue. From previous UI experience, when *I* see
an hourglass pointer, I assume that I need to wait, i.e. better not do
anything else, including clicking (YMMV). Therefore, I presume to signal
just that is what was intended here. Nothing more, nothing less.
Click and what don't they have to do with the pointer cursor?

OK, so clicks are (perhaps) discarded. Isn't that what the hourglass (or
whatever)-shaped wait cursor is supposed to mean, to signal to the user?

And clicks have nothing to do with shape of the pointer cursor, of course.
But the hourglass (or whatever shape the OS is set to use) is not
appropriate to indicate that clicks will be queued up during the
delay. You might use the hourglass/pointer hybrid for this in a
desktop app.

Usually yes, but it would depend on the use-case.
In a script, you let the browser/OS handle that.

AISB, the runtime environment cannot recognize that a single-threaded script
is going to take longer than expected until it is too late (and a warning
should be and is issued in some environments, e.g. Gecko); the halting
problem is still undecidable.

However, the script itself can cause the cursor change -- to whatever shape
appears be to appropriate for the task, including the hourglass/pointer
hybrid shape you are talking about, with the "progress" property value -- to
be performed in another DOM thread than the time-consuming part.[1]

BTW, the value for the property reset should be either "" or "auto", not
"default".
That's as maybe.

I beg your pardon?


PointedEars
___________
[1] As for the DOM thread notion, I think I found the that confirmed for
at least Gecko 1.9.2-based browsers (CMIIW), where in
<http://mxr.mozilla.org/mozilla1.9.2/source/dom/src/threads/nsDOMWorker.cpp>
I found (line numbers included from copypaste):

68 class nsDOMWorkerFunctions
69 {
....
75 // Same as window.setTimeout().
76 static JSBool SetTimeout(JSContext* aCx, JSObject* aObj, uintN aArgc,
77 jsval* aArgv, jsval* aRval) {
78 return MakeTimeout(aCx, aObj, aArgc, aArgv, aRval, PR_FALSE);
79 }
80
81 // Same as window.setInterval().
82 static JSBool SetInterval(JSContext* aCx, JSObject* aObj, uintN aArgc,
83 jsval* aArgv, jsval* aRval) {
84 return MakeTimeout(aCx, aObj, aArgc, aArgv, aRval, PR_TRUE);
85 }
....
100 private:
101 // Internal helper for SetTimeout and SetInterval.
102 static JSBool MakeTimeout(JSContext* aCx, JSObject* aObj, uintN aArgc,
103 jsval* aArgv, jsval* aRval,
PRBool aIsInterval);
....
126 JSBool
127 nsDOMWorkerFunctions::MakeTimeout(JSContext* aCx,
128 JSObject* /* aObj */,
129 uintN aArgc,
130 jsval* aArgv,
131 jsval* aRval,
132 PRBool aIsInterval)
133 {
134 nsDOMWorker* worker =
static_cast<nsDOMWorker*>(JS_GetContextPrivate(aCx));
135 NS_ASSERTION(worker, "This should be set by the DOM thread service!");
136
137 if (worker->IsCanceled()) {
138 return JS_FALSE;
139 }
140
141 PRUint32 id = worker->NextTimeoutId();
142
143 if (worker->IsClosing()) {
144 // Timeouts won't run in the close handler, fake success and bail.
145 *aRval = INT_TO_JSVAL(id);
146 return JS_TRUE;
147 }
148
149 nsRefPtr<nsDOMWorkerTimeout> timeout =
new nsDOMWorkerTimeout(worker, id);
150 if (!timeout) {
151 JS_ReportOutOfMemory(aCx);
152 return JS_FALSE;
153 }
154
155 nsresult rv = timeout->Init(aCx, aArgc, aArgv, aIsInterval);
156 if (NS_FAILED(rv)) {
157 JS_ReportError(aCx, "Failed to initialize timeout!");
158 return JS_FALSE;
159 }
160
161 rv = worker->AddFeature(timeout, aCx);
162 if (NS_FAILED(rv)) {
163 JS_ReportOutOfMemory(aCx);
164 return JS_FALSE;
165 }
166
167 rv = timeout->Start();
168 if (NS_FAILED(rv)) {
169 JS_ReportError(aCx, "Failed to start timeout!");
170 return JS_FALSE;
171 }
172
173 *aRval = INT_TO_JSVAL(id);
174 return JS_TRUE;
175 }
....
401 JSFunctionSpec gDOMWorkerFunctions[] = {
402 { "dump", nsDOMWorkerFunctions::Dump, 1,
0, 0 },
403 { "setTimeout", nsDOMWorkerFunctions::SetTimeout, 1,
0, 0 },
404 { "clearTimeout", nsDOMWorkerFunctions::KillTimeout, 1,
0, 0 },
405 { "setInterval", nsDOMWorkerFunctions::SetInterval, 1,
0, 0 },
406 { "clearInterval", nsDOMWorkerFunctions::KillTimeout, 1,
0, 0 },
407 { "importScripts", nsDOMWorkerFunctions::LoadScripts, 1,
0, 0 },
408 { "XMLHttpRequest", nsDOMWorkerFunctions::NewXMLHttpRequest, 0,
0, 0 },
409 { "Worker", nsDOMWorkerFunctions::NewWorker, 1,
0, 0 },
410 #ifdef MOZ_SHARK
411 { "startShark", js_StartShark, 0,
0, 0 },
412 { "stopShark", js_StopShark, 0,
0, 0 },
413 { "connectShark", js_ConnectShark, 0,
0, 0 },
414 { "disconnectShark", js_DisconnectShark, 0,
0, 0 },
415 #endif
416 { nsnull, nsnull, 0,
0, 0 }
417 };
 
D

David Mark

ISTM you are confusing the issue.

I may be confusing, but I don't think I'm confused.
From previous UI experience, when *I* see
an hourglass pointer, I assume that I need to wait, i.e. better not do
anything else, including clicking (YMMV).

Well, clicking (or any actions with the mouse) are certainly right
out. The UI programmer makes a conscious decision to display this
cursor and it doesn't always indicate that the app is going to be so
overwhelmed that it can't deal with user input. It just may not make
sense for the app to juggle UI requests with whatever other processing
it is doing. Regardless, mouse actions are discarded while this
cursor is displayed and it does mean wait to the user.
Therefore, I presume to signal
just that is what was intended here.  Nothing more, nothing less.
Okay.



OK, so clicks are (perhaps) discarded.  Isn't that what the hourglass (or
whatever)-shaped wait cursor is supposed to mean, to signal to the user?

Yes. That is exactly the point. You could change the cursor, but
then you would need to somehow prevent all mouse actions while the
wait cursor is present. If you click repeatedly during this long
calculation step, those clicks will be processed after the calculation
is done. They are queued up and there's nothing your script can do
about it as it is doing calculations at the time. Once finished with
the calculations, you change the cursor back and all of those clicks
are processed in turn. How would you stop them is the question. And
it's a minor question, especially when you consider the alternative
timeout-based solution that won't lockup the UI at all. ;)
And clicks have nothing to do with shape of the pointer cursor, of course..

Right. It's trivial to change the cursor to wait, non-trivial to
disallow all mouse actions for the document while that cursor is
displayed.
Usually yes, but it would depend on the use-case.
Right.


AISB, the runtime environment cannot recognize that a single-threaded script
is going to take longer than expected until it is too late (and a warning
should be and is issued in some environments, e.g. Gecko); the halting
problem is still undecidable.

I see what you are saying, but if a script goes South for more than a
second or two on this XP Pro box, clicking - for example - FF3.5 may
cause the cursor to change to an hourglass. Repeated clicking may
change the icon in the title bar to the default app icon and resource
usage sometimes goes through the roof. I'm sure these symptoms are
familiar to Windows users.
However, the script itself can cause the cursor change -- to whatever shape
appears be to appropriate for the task, including the hourglass/pointer
hybrid shape you are talking about, with the "progress" property value

Right. Not ashamed to admit I forgot the name of that one (or if it
was even offered). I don't care as I would never use it in a browser
script. :)

But I'm not saying it can't be done "right" if you really want to
present that interface.
-- to
be performed in another DOM thread than the time-consuming part.[1]

BTW, the value for the property reset should be either "" or "auto", not
"default".
Huh?
That's as maybe.

I beg your pardon?

Ah, don't apologize.
 
T

Thomas 'PointedEars' Lahn

David said:
[...] It's trivial to change the cursor to wait, non-trivial to
disallow all mouse actions for the document while that cursor is
displayed.

I would consider adding an absolutely positioned ([semi-]transparent) block
element at the size of the viewport fairly trivial :)
I see what you are saying, but if a script goes South for more than a
second or two on this XP Pro box, clicking - for example - FF3.5 may
cause the cursor to change to an hourglass.

OK, but you cannot make that assumption for all graphical browsers.
Repeated clicking may change the icon in the title bar to the default app
icon and resource usage sometimes goes through the roof. I'm sure these
symptoms are familiar to Windows users.

This is bad, indeed. (Fortunately, Windows is no longer my primary OS :))
-- to
be performed in another DOM thread than the time-consuming part.[1]

BTW, the value for the property reset should be either "" or "auto", not
"default".

Huh?

Are you referring to the first or the second paragraph? If the second one:

The initial value of the `cursor' property is "auto", indicating that the
user agent should display a context-sensitive shape. If you set the
`cursor' property to a value different than "auto" to indicate an operation
in progress, you would need to reset it afterwards. However, using
"default" for the reset causes the pointer to stay fixed (usually the common
arrow shape) instead of becoming context-sensitive again.

See also said:
Ah, don't apologize.

AFAIK, in formal English that question is a polite way for one to indicate
that something that has been said before was not understood, including a
request for an explanation (in my native language, it would correspond with
"Wie bitte?"). It was meant *that* way. Therefore, please explain what you
meant by this.


PointedEars
 
D

David Mark

David said:
Thomas said:
David Mark wrote:
Thomas 'PointedEars' Lahn wrote:
David Mark wrote:
On Dec 14, 9:09 pm, Stefan Mueller <[email protected]> wrote:
[...]  It's trivial to change the cursor to wait, non-trivial to
disallow all mouse actions for the document while that cursor is
displayed.

I would consider adding an absolutely positioned ([semi-]transparent) block
element at the size of the viewport fairly trivial :)
I see what you are saying, but if a script goes South for more than a
second or two on this XP Pro box, clicking - for example - FF3.5 may
cause the cursor to change to an hourglass.

OK, but you cannot make that assumption for all graphical browsers.

Fair enough. The other aspects of my argument still apply.
This is bad, indeed.  (Fortunately, Windows is no longer my primary OS :))

Yes, it sucks. :( So does FF3.5 (at least the revision I am
currently using) and FireBug for that matter. Maybe they are
concentrating on Macs.
-- to
be performed in another DOM thread than the time-consuming part.[1]
BTW, the value for the property reset should be either "" or "auto", not
"default".

Are you referring to the first or the second paragraph?  If the second one:

The part just above where I indicated confusion.
The initial value of the `cursor' property is "auto", indicating that the
user agent should display a context-sensitive shape.
Yes.

If you set the
`cursor' property to a value different than "auto" to indicate an operation
in progress, you would need to reset it afterwards.
Correct.

However, using
"default" for the reset causes the pointer to stay fixed (usually the common
arrow shape)
instead of becoming context-sensitive again.

Yes, that's a mistake if the OP did that. Set it to ''.

Thanks for that. :)
AFAIK, in formal English that question is a polite way for one to indicate
that something that has been said before was not understood, including a
request for an explanation (in my native language, it would correspond with
"Wie bitte?").

"Something please" is all I get out of that.

It was meant *that* way.  Therefore, please explain what you
meant by this.

I sometimes throw in quaint, outdated English expressions. I think it
makes my posts more cosmopolitan. :)

Oh, you mean the single calculation step sufficing? Well, it may be
true (in some contexts), but it doesn't really matter.
 
G

Garrett Smith

Stefan said:
I've a webpage with several tables and a button. If you click the
button the javascript function calc() gets called. This function does
several calculations and now I'm looking for a way to change the
mousepointer to an hourglass while the calculations are running.

Why is calc() so slow?
 
S

Stefan Mueller

Actually, I just liked to know if there's a way to change the
mousepointer on the whole webpage with only one command and to change
it back afterwards?
However, I got explained that I shouldn't change the mousepointer to
an hourglass rather I have to see that the function calc() doesn't
need so much time to process. Of course that's right, but the function
calc() sorts a huge table on the webpage and that lasts 5 or 10
seconds. The user has to wait until the table is sorted.

Therefore I see it exactly the way like Thomas 'PointedEars' Lahn
wrote in his post "From previous UI experience, when *I* see an
hourglass pointer, I assume that I need to wait, i.e. better not do
anything else, including clicking (YMMV). Therefore, I presume to
signal just that is what was intended here. Nothing more, nothing
less."
That's the only reason why I'd like to show on the whole webpage the
hourglass while the function calc() is doing its job.

Reading your posts I'm realizing that it's most probably not possible
to change the cursor to an hourglass on the whole page. The only ray
of hope I found is in the post from David Mark "It's trivial to change
the cursor to wait, non-trivial to disallow all mouse actions for the
document while that cursor is displayed.".
Is it really so trivial to change the cursor to an hourglass on the
whole webpage? And is it also trivial to change the cursor back to the
shape it was before (crosshair, pointer, ...)? If yes, please give me
a hint.
 
D

David Mark

[...]
of hope I found is in the post from David Mark "It's trivial to change
the cursor to wait, non-trivial to disallow all mouse actions for the
document while that cursor is displayed.".
Is it really so trivial to change the cursor to an hourglass on the
whole webpage? And is it also trivial to change the cursor back to the
shape it was before (crosshair, pointer, ...)?

Well, perception is reality here. Cover the whole document with a
transparent DIV with a wait cursor. Remove it when done. You could
even use it to rebuff mouse actions by stopping their propagation.
Still, keyboard input will be queued until after the calculation is
done, which doesn't gibe with the wait signal.
 
T

Thomas 'PointedEars' Lahn

Stefan said:
Actually, I just liked to know if there's a way to change the
mousepointer on the whole webpage with only one command and to change
it back afterwards?
^
Yes, that is what you liked to know. (Avoid *asking* *non*-questions, they
are a waste of our time.)
However, I got explained that I shouldn't change the mousepointer to
an hourglass rather I have to see that the function calc() doesn't
need so much time to process.

I fail to see where. Are you sure you are not misinterpreting statements?
Of course that's right, but the function calc() sorts a huge table on the
webpage and that lasts 5 or 10 seconds. The user has to wait until the
table is sorted.

OK. But how can you possibly know how long it takes? Do you know the
runtime environment so exactly? That is unlikely for a "Web page".
Therefore I see it exactly the way like Thomas 'PointedEars' Lahn
wrote in his post "From previous UI experience, when *I* see an
hourglass pointer, I assume that I need to wait, i.e. better not do
anything else, including clicking (YMMV). Therefore, I presume to
signal just that is what was intended here. Nothing more, nothing
less."
That's the only reason why I'd like to show on the whole webpage the
hourglass while the function calc() is doing its job.

However, David was/is correct in pointing out essentially that users are
unpredictable (I did not think it necessary to point out explicitly
everywhere we were in agreement): If a user clicks while the script is
running anyway and the runtime environment cannot cope with it because it is
running a single-threaded script, this can have rather disastrous side
effects (extensive CPU load has been mentioned; browser crashs are possible,
too).

Still, if you set up DOM threads, like

Event listener
|
+- Change cursor
|
+- calc()
Change cursor back

that is, for example

/* or 'wait', but consider tabbed browsing */
window.setTimeout("....cursor = 'progress';", 10);

window.setTimeout("calc(); ....cursor = '';" 10),

there should not be any problem with that, and by contrast to the possible
alternative we discussed (not putting calc() in its own thread, but
preventing input actions to have effect) it should keep the browser and your
Web application responsive.
Reading your posts I'm realizing that it's most probably not possible
to change the cursor to an hourglass on the whole page.

I do not know which posting you have intended to post a follow-up to (you
have not quoted anything == bad), but you posted a follow-up to Garrett's
posting and I do not see anything in his simple question --

-- that implies what you ask for cannot be done.
The only ray of hope I found is in the post from David Mark "It's trivial
to change the cursor to wait, non-trivial to disallow all mouse actions
for the document while that cursor is displayed.".

Perhaps you should read more carefully and interpret less. It has been
discussed at great length and in great detail how it can be done. What you
appear to miss is that we also discussed if it should be done (David/me); if
yes, how it can be done best (David/me); and ultimately if it needs to be
done at all (Garrett).

Evidently again, this is not a support forum. We are striving to find the
best solutions to a problem here, not necessarily the quickest answer and
most certainly not the answer that you want to hear.
Is it really so trivial to change the cursor to an hourglass on the
whole webpage?
Yes.

And is it also trivial to change the cursor back to the
shape it was before (crosshair, pointer, ...)?
Yes.

If yes, please give me a hint.

It has been given already.

Learn to post properly. <http://jibbering.com/faq/#posting>


PointedEars
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,767
Messages
2,569,572
Members
45,045
Latest member
DRCM

Latest Threads

Top