1

I have a floating bar at the top which is being shown/hidden as user scrolls the page up or down. I need to hide it completely when Dojo/browser scrolls the page programmatically, e.g. when putting focus on an invalid element in a form.

Is it possible to know that the scrolling occurred because of user input?

Greg
  • 8,230
  • 5
  • 38
  • 53
  • possible duplicate of [Detect whether scroll event was created by user](http://stackoverflow.com/questions/7035896/detect-whether-scroll-event-was-created-by-user) – Brilliand Apr 10 '14 at 19:58
  • Not a perfect duplicate, but since the answer to that question is "that can't be done in JavaScript at all", the answer is the same if you include Dojo. (Detecting when Dojo itself does the scrolling might be possible, but won't cover all cases.) – Brilliand Apr 10 '14 at 20:00

1 Answers1

0

This can't be done in general, but can be done in the specific case mentioned in the question, namely to detect that the scrolling occurred because Dojo is trying to put focus on an invalid element in a form. To do that it's necessary to override the validate method in dijit/form/Form so that it can automatically override the focus method in all widgets in the form:

    validate: function(){
        var self = this;
        var children = this._getDescendantFormWidgets();
        array.forEach(children, function(child){
            if(typeof(child.focus) === "function" && !child._uuiIsModded){
                child._uuiOldFocus = child.focus;
                child.focus = self._onProgrammaticFocus;
                child._uuiIsModded = true;
            }
        });

        return this.inherited(arguments);
    },

    _onProgrammaticFocus: function(){
        topic.publish("on-programmatic-focus", this);
        this._uuiOldFocus.apply(this, arguments);
    },

The new validate method amends all widgets contained in a form. The amendment is to replace the standard focus method with a custom method _onProgrammaticFocus, which fires the event on-programmatic-focus before calling the standard focus method. That way the event is fired only when the focus is put on the widget programmatically in response to a validation error and not when the widget is selected by the user:

  • when user puts focus on a widget by selecting the widget with a mouse or tapping on it the focus method IS NOT CALLED
  • when the form widget contains invalid value, the standard behavior of the validate method is to amend the widget with CSS classes that show the validation error and put focus on the widget by calling the focus method. In this case the focus should be already amended and fire the "on-programmatic-focus" event.

Please remember, that this is a hack that replaces the standard focus method and may not work if there are problems in other parts of your code. Specifically, in some cases __uuiOldFocus may become undefined if your widgets containing other widgets don't inherit dijit/_Container. This is because this._getDescendantFormWidgets() returns different children than method toObject from dom/dom-form. The method this._getDescendantFormWidgets() used in form validation relies on the fact that all widgets containing other widgets should inherit the dijit/_Container mixin (which initializes this.containerNode with the current DOM node).

Greg
  • 8,230
  • 5
  • 38
  • 53