Is This Onblur Behavior a Bug?

Description of the issue:
the onblur event is firing twice when leaving an input field, causing a problem.

Steps to Reproduce (add as many as necessary): 1. 2. 3.

  1. Create input fields on webpage
  2. Add onblur attribute to input fields to:
    a. Post message to javascript log
    b. Send the value of the input to the server via ajax
    c. Server receives new value and id of field , which it uses to update database
    d. Observe onblur firing twice

Actual Result (gifs and screenshots are welcome!):

Expected result:
onblur fires once instead of twice.

Reproduces how often:
Whenever editing data in fields with onblur event.

Operating System and Brave Version(See the About Brave page in the main menu):
macOS 10.15.4
Brave Version 1.20.31 Chromium: 88.0.4315.5 (Official Build) nightly (x86_64)
(https://brave.com/latest/)

Additional Information:
Image where the problem is happening

To login to where you can access the page with the problem, use these credentials, then navigage as shown in video
(unfortunately, the problem has been fixed on the demo page, so the problem no longer can be run. However, it can be viewed in the video linked below).

URL https://hlows-dev.work/rmw_baselines/0base/_0base.php

u demo@houston-data.com
p simple

LINK to VIDEO showing and explaining problem:
https://legacy-systems.biz/longview2500/public_links/public/programming/brave_onblur_problem/

Looking into this now; immediately I can see that we only have the multiple events when you have one input focused, and you select another input. If you have an input focused and then select the body of the page, only a single blur event is fired. Ideally we would have a reduced demo too, with as little code possible to reproduce the issue. Is that possible?

As an example, I put together this small test script:

const onBlur = (label) => {
    const time = (new Date).toLocaleTimeString();
    const message = `Blur fired for ${label}`; 
    output.textContent = `${time} ${message}\n${output.textContent}`;
}

for ( let i = 0; i < 5; i++ ) {
    const br = document.createElement("br");
    const element = document.createElement("input");
    element.value = `Element ${i}`;
    element.addEventListener("blur", onBlur.bind(this, element.value));
    [ element, br ].forEach( el => document.body.appendChild( el ) );
}

document.body.appendChild(
    document.createElement("textarea")
).id = "output";

You can test the results here: https://jsfiddle.net/jonathansampson/w1zeaypk/

In Brave I’m seeing the expected results (a single blur event when blurring).

2 Likes

Thank you for taking time to look at this. I appreciate it a lot.

You are 100% correct on every point you put in English. Unfortunately, I do not understand how to run the demo you provided. I went to the code pen, and tried running the code, but I did not see indication of onblur events happening as I moved among the elements. I do not know how to view the console in the codepen. Putting that aside…

As you said, the problem occurs in my original demo only when attempting to move focus from one input field to another, without moving focus to another kind of element in between.

SIMPLER DEMO OF PROBLEM SHOWS PROBLEM IS IN MY JAVASCRIPT, NOT THE BROWSER

Regarding a simpler demo, I made just such a thing before seeing your comment. The problem does not occur in the simpler demo. Here are links to the simpler demo and a brief video explaining what caused the double-onblur.

SIMPLE DEMO THAT DOES NOT HAVE THE PROBLEM
https://legacy-systems.biz/longview2500/public_links/public/programming/brave_onblur_demo/

VIDEO EXPLAINING (4:45 at normal speed, 1:15 at 3x speed, still intelligible)
https://legacy-systems.biz/longview2500/public_links/public/programming/brave_onblur_solution_video

ATTEMPT TO EXPLAIN WITH WORDS ONLY

The simpler demo leaves out one of the actions taking place in the demo I shared in the OP. The simpler demo does not include a refresh of the list when an item is edited.

The extra onblur makes complete sense. Reason it makes sense: when onblur is the result of putting focus into another input field, and the onblur event includes replacing all the input fields, it makes sense the refresh would trigger an onblur from the field that has just received focus. Somehow, FireFox completes the onblur before putting focus into the 2nd input field, so the 2nd onblur does not happen. In Brave, focus happens in the 2nd field before the onblur from the first field fires. I guess it makes sense that onblur would have to precede onfocus in the 2nd field, but I am not seeing this as a bug. Maybe there is a strict rule that says the onblur must precede the onfocus, but instead of that, I am making all the input fields default to read-only, then adding a pencil (edit) icon for each input field, so the user will have to tap the edit icon before the field will b editable. That will prevent the double-onblur.

There is a twist worth noticing. There is a difference between the way Brave and FireFox handle this particular javascript. I am not aware of a reason why one or the other would be the “correct” behavior. I would, however, like to know why there is a difference between how the browsers handle this scenario.

I created another test to see which order the blur/focus events were fired in Firefox and Brave; they appear to be fired in the same order. I suspect there may still be something different in your demo. I’ll take a look momentarily.

Firefox on left, and Brave on right:

Update: I took a quick look at your demo, and realized you were using attribute-based event handlers. So I updated my demo to include these as well (inputs c, and d). However, I still do not observe a difference between Firefox and Brave for either approach:

2 Likes

You are awesome to do all that work, quite the dedication.

I want to give you credit for solving the problem.

The double-onblur event is the result of placing the focus into an input field that is removed from the DOM then recreated by the onblur event of leaving an input field. The sequence of events is:

STEP 1 - place cursor inside input field in list id=input1.
STEP 2 - place cursor in a different input field in list id=input2. Result:
input1 onblur occurs
onblur method includes recreating all the input fields, including input2. When input2 is recreated while the cursor is in input2, onblur for input2 fires, That is two onblurs from moving from one input to another.

SOLUTION: do not recreate the input fields when moving from one field to another. The input fields need to be recreated only when an item is deleted or added, not when edited.

I am not seeing that in your examples.

You’re correct that my examples do not involve any deletion of elements. Very happy to hear that you were able to identify the issue :slightly_smiling_face:

I would like to reiterate that I am extremely impressed with the attention you gave to my problem and I am delighted to have learned the problem was entirely my making, Brave operated flawlessly.

Brave functions better than any other browser. No other browser protects people from unwanted fingerprinting of our systems. It is important that we need not disclose our identifies when we do not want to.

The people who put Brave together have done a fantastic job. Thank you a million times.

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.