Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Show an hourglass cursor when lengthy processes are underway #72

Open
backplane-import opened this issue Oct 16, 2011 · 9 comments
Open

Comments

@backplane-import
Copy link

Imported from backplanejs Google Code issue 72.

Reporter markbirbeck
Date 7 Jul 2010 4:01:41 PM UTC

At the moment the slowness of the XForms processor when running IE leaves users a bit confused as to when the form is usable.

To get around this we should display an hourglass cursor whenever any lengthy operations are taking place.

(Note that this is a feature that could be used outside of the XForms module, so I'm marking this as being in the 'core'.)


Ticket status set to Accepted

Priority: Medium
Type: Enhancement

@backplane-import
Copy link
Author

Comment by markbirbeck on 7 Jul 2010 4:12:28 PM UTC

So one way we might do this is to create a method to turn on the hourglass, and another to turn it off.

We then call these two methods at the beginning and end of any potentially lengthy processes, such as XForms event handling. (That will then cover things like 'xforms-rebuild', and so on.)

However, we don't want the hourglass to appear immediately, since if the operation is short it will get very annoying. So the logic will probably be something like this:

  1. Call the 'hourglass on' function with a parameter of the number of seconds to wait.
  2. In the function, set a timer for the number of seconds, and reference a callback function.
  3. Return to the caller.
  4. After the number of seconds has elapsed, store the current cursor, and then turn on the hourglass cursor, and return.
  5. In the 'hourglass off' function, either set the cursor back to what it was before, or if the time hasn't elapsed yet, just turn off the timer.

It's possible that the 'hourglass on' function will need to return a handle that can be used in the 'hourglass off' function.


Updates

Added label: performance

@backplane-import
Copy link
Author

Update by markbirbeck on 7 Jul 2010 7:54:49 PM UTC

Owner set to creaven

@backplane-import
Copy link
Author

Comment by creaven on 8 Jul 2010 7:43:06 AM UTC

to show/hide cursor we can add this to css:
.freeze, .freeze *{
cursor:wait !important;
}
and after add/remove this class from html element (document.documentElement.add/removeClass('freeze'))

@backplane-import
Copy link
Author

Comment by creaven on 14 Jul 2010 1:54:17 PM UTC

show test page which works slow and moment when want to show hourglass

@backplane-import
Copy link
Author

Comment by [email protected] on 15 Jul 2010 10:09:00 AM UTC

Someone is preparing a test form.

But note that since this is a function I'd like to have generally available in the library, there doesn't need to be anything XForms-specific in the tests. In other words, this could be tested using a simple setTimer() to emulate a long running task.

@backplane-import
Copy link
Author

Comment by [email protected] on 15 Jul 2010 11:06:03 AM UTC

Test form attached.

Vary the number of iterations to affect the length of time taken to finish processing. Example timings for IE7 and Chrome are detailed in the form.


Attachments

test-setvalue-loop.html (2.7 KB)

@backplane-import
Copy link
Author

Comment by creaven on 15 Jul 2010 3:06:46 PM UTC

it's impossible, because javascript executes timer function too late, test:

var timer = setTimeout(function(){alert('a');}, 100);
var begin = +new Date;
for(var i = 0; i < 2000000; i++){
    var a = Math.random()*1e5*Math.random();
    var b = a*a*a;
}

IE shows alert not after 100ms, but after it executes slow loop code (on my computer loop execution takes more than 100ms)

implemented in:
http://code.google.com/r/creavenmoro-backplanejs/source/detail?r=629a226955955250988df4103f4be0256b80902f
http://code.google.com/r/creavenmoro-backplanejs/source/detail?r=a2be71cc2c991ea8fdd2dfd7e0b4c981eee90443

removed in:
http://code.google.com/r/creavenmoro-backplanejs/source/detail?r=7adf4583e84ac10f6f696229f0fc7832e6c2c8ed

@backplane-import
Copy link
Author

Comment by markbirbeck on 15 Jul 2010 7:29:22 PM UTC

What happens if the slow loop code is placed into a setTimout() with a delay of zero or 1?

If that works, then I think your original code is ok, since most of the XForms event handling is executed using setTimeout() to emulate threading.

To put it another way, if anyone adds code that can't be interrupted in order to allow the hourglass then there is nothing we can do about it, so we might as well write the code the best we can, given those constraints.

@backplane-import
Copy link
Author

Comment by creaven on 19 Jul 2010 4:44:14 PM UTC

What happens if the slow loop code is placed into a setTimout() with a delay of zero or 1?
it's imposible for @while, because code must be executed in one moment

if remove setTimeout, it's too don't work. During loop browser freezed and don't change cursor seted before loop, test:

//util.js
(function() {

var count = 0;

this.Hourglass = function(delay) {
this.delay = delay || 1000;
};

Hourglass.prototype = {

on: function() {
    count++;
    this.start();
},

off: function() {
    count--;
    if(!count){
        removeClass(document.documentElement, 'hourglass');
    }
},

start: function() {
    addClass(document.documentElement, 'hourglass');
}

};

function addClass(element, className) {
if(!hasClass(element, className)) element.className = element.className + ' ' + className;
};

function removeClass(element, className) {
element.className = element.className.replace(new RegExp('(^|\s)' + className + '(?:\s|$)'), '$1');
};

function hasClass(element, className) {
return new RegExp('(^|\s)' + className + '(?:\s|$)').test(element.className);
};

})();

<title></title> <style type="text/css"> .hourglass, .hourglass *{ cursor:wait !important; } </style> <script src="util.js" type="text/javascript"></script> <script type="text/javascript"> var hourglass = new Hourglass(1500);//start delay 1500;
        var Process = function(options) {
            this.dur = options.dur || 1000;
            this.onStart = options.onStart || function() {};
            this.onFinish = options.onFinish || function() {};
        };

        Process.prototype = {

            start: function() {
                var self = this;
                setTimeout(function() {self.finish.apply(self);}, this.dur);
                this.onStart();
            },

            finish: function() {
                this.onFinish();
            }

        };

        var longProcess = new Process({

            dur: 9000,

            onStart: function(){
                document.title = 'start long process';
                hourglass.on();
                for(var i = 0; i < 30000; i++){
                    var moo = document.createElement('moo');
                    document.body.appendChild(moo);
                    document.body.removeChild(moo);
                }
                document.title = 'moo'
            },

            onFinish: function(){
                document.title = 'finish long process';
                hourglass.off();
            }

        });

        function startLong() {
            longProcess.start();
        }

    </script>
</head>
<body>
    <button onclick="startLong()">start long process</button>
</body>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant