Is there a way to use event.preventDefault with focusOut? If not, why?

After some more research I've found out that only certain events are 'cancelable'.

  • Quoted from http://help.dottoro.com/ljwolcsp.php

    You can check whether an event can be canceled with the cancelable property in all browsers except in Internet Explorer before version 9. Although the cancelable property exists in Firefox, it always returns true, regardless of the cancelable state of the event. There is no way to determine whether an event can be canceled in Internet Explorer before version 9.

    Note that the use of the preventDefault method and the returnValue property on a non-cancelable event does not cause an error. When an event handler returns false, the event will be canceled. You can use it instead of the preventDefault method and the returnValue property. See Example 2 below.

  • Each event in Javascript has a cancelable property that is defined as 'true' if the event can be prevented or 'false' if the event cannot be cancelled. Ref: http://help.dottoro.com/ljeosnqv.php

  • An example script from http://help.dottoro.com/ljeosnqv.php demonstrating this property can be found here on jsFiddle (to save space). Note the comments in the code about how Firefox always returns true for the cancelable property in the event object.

The general principal being:

 $('selector').on(eventType, function (event) {
    alert(('cancelable' in event));   //will return true
    alert(event.cancelable);      //will return true if event can be cancelled
                                  //NOTE: Firefox mistakenly always returns true
});
  • Events have a preset order of occuring depending on the situation. For example if a mouse button is clicked the order of eventTriggers would be: mousedown, mouseup, and click. Ref: www.w3.org/TR/DOM-Level-2-Events/events.html#Events-Event-initMouseEvent

  • Quoted from http://www.w3.org/TR/2003/NOTE-DOM-Level-3-Events-20031107/events.html#Events-flow-cancelation

    A 'cancelable event' is an event associated with a default action which is allowed to be canceled during the DOM event flow. At any phase during the event flow, the triggered event listeners have the option of canceling the default action or allowing the default action to proceed. In the case of the hyperlink in the browser, canceling the action would have the result of not activating the hyperlink. Not all events defined in this specification are cancelable events.

  • Sometimes the sequence of events has it that the DOM default action will occur before the event you are looking to cancel even shows up, in these cases, you cannot cancel the default action because it has already taken place. That is to say the default action occurs before the dispatch of the event.


MY SOLUTION:

That being said I did manage to find a solution to my problem and more/less this problem. Essentially I had an eventListener with an element for focusin already and I wanted this element to keep focus.

<div id='display'></div>
$('#idBox').on('focusin', function () {
  $('#div').append('focused');
  //do something
}

Initially I tried using a setTimeout event when I clicked off, but I found that wasn't good because it triggered my focusin event again. So what we need is an event that is dispatched before the DOM's default action of switching focus. I did find that there is an event that meets this requirement, but is only available to IE... typical. For your information it is: "onbeforedeactivate" and it is cancelable. However since cross browser compatibility is important, we should not use this eventTrigger. Rather I found that the event mousedown occurs before the DOM starts its focus-changing behaviours.

So what we could do is:

$(document).on('mousedown', function(event) { 
       target = event.target;     // the element clicked on
       myTarget = document.getElementById("idBox");   // the element to keep focus
       if (target !== myTarget) {   
           event.preventDefault();  //prevent default DOM action
           event.stopPropagation();   //stop bubbling
           return false;   // return
       }
});

There are many other ways of going about it. I personally don't like setting an eventListener to the entire document, but to demonstrate the basics it serves its purpose.


Footnote: A great article to read to learn more about event handling in Javascript is http://help.dottoro.com/ljtdqwlx.php An amazing resource I stumbled across.


We know that it is the click function that cause the issue. So in the normal explorer like chrome, you can detact the mousedown event and then preventDefault.

But this doesn't work in ie, but we can use the beforedeactivate event instead http://msdn.microsoft.com/en-us/library/windows/apps/jj569321.aspx. It can be deteact in ie when the focus is changing. so just prevent it.

code would like this:

       $inp.on('blur', function(){

            self.hide();
        });

        isIE && $inp.on('beforedeactivate', function(evt){
            mousedown && evt.preventDefault();
        });

        $holder.on('mousedown', function(evt){
            evt.preventDefault();
            mousedown = 1;
        });