I have the following snippets: http://jsfiddle.net/L7rne/5/ and http://jsfiddle.net/L7rne/6/
It turns out that if you pause execution of the script in the click event handler, then the checkbox is checked, even though there is event.preventDefault().
I tried this in Firefox 7 and Chrome 15 and both behave in the same way.
I'm almost sure that it's a correct behaviour but somehow I cannot find any reference why it's like that.
Could someone point me in the right direction?
EDIT:
When you start with checked checkboxes then it becomes even more interesting:
http://jsfiddle.net/L7rne/8/ - the checkbox becomes unchecked but its value stays checked
http://jsfiddle.net/L7rne/9/ - the checkbox becomes unchecked but its value becomes false
(This is consistent with pure Javascript code using checkbox.checked and checkbox.getAttribute('checked'), so I'm not pasting another jsfiddle snippets)
EDIT2:
COBOLdinosaur in one of the comments pointed me to this: http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-flow-cancelation, but IMHO that only confirms my point of view...
not sure I'm understanding the problem. why wouldn't it be the right behaviour?
seriously, let's say you write some code that shows/hides a div based on whether a checkbox is ticked or not.
so, you write an onclick. if the checkbox is unticked, and then you click it, what do you think should be done to the div? obviously, you would expect the event to find the checkbox to be checked.
By time the event handler fires, the event has already taken place, and the browser is re-rendering in response. If the handler gets suspended, then the browser completes the work because nothing prevented it.
Its like calling the police to a bank robbery, and they are in a traffic accident on the way. The robbers get away. The deed is done.
Related
I introduced a bug at some point (live version doesn't have this issue) but haven't been able to figure out what caused it.
I have a button in React (it's just a div with an onClick).
The button has an onClick and a :hover CSS effect.
The button is loaded by clicking on another div (which works on the first click).
After loading the button (and its wrapper content), the button doesn't do anything on the first click. Without doing anything else, clicking again let's it work fine.
Currently I have a debug message in my onClick, so it looks something like this
onClick={(e) => {
console.log("ONclicked! " + this.props.alt);
// e.stopPropagation();
// various callbacks
}}>
I also have similar console.log debug messages on all of the button's parents, all the way up to the root React element (i.e. clicking anywhere on the page shoots out a message, except when clicking on this particular button the first time). Even the root element does not register anything on the first click..
None of these messages appear on the first click.
Again, without doing anything else, just clicking one more time in the same spot fires the onClick as expected.
Other questions about "first click not working" I've seen are all about the state not updating on the first click. In my case I'm not even trying to update the state, I don't seem to be getting the onClick called at all.
I've looked through all the commits for this version and still haven't been able to figure out the problem. Any ideas on what can cause this behavior? The weirdest part to me is that the second click works, while the first doesn't seem to do anything. But nothing about the state/DOM is changing between the first and second click (since the first click doesn't seem to be registered at all). I think this rules out things like a misconfigured pointer-events CSS rule?
Edit:
Upon further exploration, it seems that the first click actually triggers onMouseEnter, which seems totally nuts lol... But I added a console.log to onMouseEnter and it's definitely triggering exactly when I make the first click, and NOT on subsequent clicks.
Edit 2:
But this mouseEnter thing only happens in Firefox, not Chrome. But the first click not working bug is in both browsers.
Edit 3:
onMouseDown is firing properly, but onClick still only happens on the second time the button is clicked (at which point onMouseDown has fired twice).
Also, double checked and confirmed that I don't use stopPropagation anywhere which seems to be a common source of this problem.
Figured it out!
In another adjacent div, I had an onBlur handler. In that handler, I called setState() on the component (hiding another div when that div is unfocused).
To show the button that was having issues, I clicked in something in the div with the onBlur. This gave it focus. When I did a first click outside on the button that appeared, it triggered blur.
Apparently, the setState() call interfered with the click in some way, including causing the weird behavior I described with mouseEnter being retriggered. Perhaps the setState caused a redraw, which then caused mouseEnter to be fired again? Maybe the quick redraw also stops the onClick from going through, even though mouseDown is fired? (something to do with event ordering?) I'm still not sure why exactly that happens.
But after removing the setState() call, the first click on the button works as expected.
And thus ends a couple hours of painful debugging.
I had the same problem, in your onClick function you have to persist your event.
onClick={(e) => {
e.persist();
console.log("ONclicked! " + this.props.alt);
// e.stopPropagation();
// various callbacks
}}>
see this link for more explanation on the subject: https://deepscan.io/docs/rules/react-missing-event-persist
If you are using Intellij or WebStorm this happens when running javascript debug mode.
I'm having difficulties with getting the .change() event in jQuery to trigger when I change the value of a select drop down. I've already searched for a possible solution though the ones I came across do not seem to work for me...
Basically I have an event on a site which is set as a variable product in WooCommerce, with different time slots. I have written a reasonably complex algorithm to detect whether the maximum number of people have taken that time slot in order to let the user know that the time and date they want is available or not. That part works, though I need to add a trigger on the time slot drop down in order to fire the check.
For debugging purposes I did this:
$('#time-slot').on('change', function() {
console.log("changed");
});
Where '#time-slot' is the ID of the select box. However, this does not seem to trigger the console.log text when I change the select. I even tried the following in my console:
$('#time-slot').trigger('change');
But the "changed" text did not appear in my console.
Then I changed my code so that it would trigger on a click instead. In my console now:
$('#time-slot').trigger('click');
And this time the text appeared in my console just fine - I even tried it with various other random events such as mouseup, mousedown and focus each time manually triggering the event and every other one worked - except change which is the one I really need.
Is change no longer supported? Or is it that I'm coding it incorrectly? The version of jQuery I am using is 1.11.3.
Hopefully there is a simple solution that maybe I'm just overlooking!
Thank you
I've been wracking my brain over this and cannot figure it out for the life of me.
Here's a test page I built for the sake of this discussion:
http://jsbin.com/garokalocu
Let's assume this page is very complex and I didn't build it, and I'm trying to see the code that runs when the user clicks "Do It." So I open the debugger, open the side pane and click "Events." I checkmark the click event for #execute which is the button.
Now I click the button, and the code hits the breakpoint. But strangely, the name "Bob" has already been filled in, so clearly it flew right past the actual code, and lands me here:
I don't understand what's going on here. So I tried something else, a new feature in Firefox that I thought might be handy. If I inspect the code, there are little "ev" tags on certain DOM elements. Supposedly you can click those and see the code.
Well, that was fruitless. I'd be forever grateful if someone could please tell me how on earth to debug jQuery events, and see the actual code that gets executed. Thanks!
You see jQuery as the handler because you used jQuery to make those listeners. jQuery code is called when event is triggered. If you used normal JS addEventListener, they will show up in the event without having to step through.
According to the article here the feature is coming in Firefox 34, so if you use Firefox beta it should have the behavior you want.
I am trying to do all dom manipulations off screen and then make it visible. Which works, except now I have the situation where I am trying to do it with a form which I want to focus on the first input text upon rendering it on the browser.
Something like: myForm.prependTo(myDiv).show().find('input:first').focus();
Problem is that the focus is being called before the form has finished rendering which is causing the lovely error 'Can't move focus to the control because it is invisible, not enabled, or of a type that does not accept the focus'
How do other web developers handle the similiar situation of manipulating elements off screen and then making it visible? I wish jQuery had something like myForm.prependTo(myDiv, function() { /* on render code here */ })
I know one way of doing it is setting a timeout and when it fires I put focus on the input, but I feel like that's not really the cleanest way to do things. I know the iframe has an onload event, so I'm curious if people usually draw their elements in some hidden iframe and listen for its load event to know when the element has finished rendering? If so could you point me to an example of doing this?
myForm.prependTo(myDiv).show(function(e){
$(this).find('input:first').focus();
});
I know I'm 7 years late, but I had a similar problem, which I solved by putting the stuff I needed to happen after the render in a ready handler.
I had a restore function that worked, but there was zero or near zero visual feedback that the element had been restored.
I tried emptying the element first. It still worked, but still had zero visual feedback.
$("#someSelector").empty();
restore();
Then I discovered ready() happens after the rendering; so I changed it to something like....
$("#someSelector").empty().ready(function() {
restore();
});
Now the restore() doesn't happen until after the empty() action RENDERS. This means my element APPEARS to empty out and then refill (it always did, but now the user can see it happen).
I found this solution somehow a few days ago for a different problem with some vague search that I can't remember. Then I needed it again but couldn't exactly remember what I did. Now my searches included the word "jquery" and "render" and lead me here.
I ended up going thru my code to find out what I did, and I thought it might be a good idea to post it here in case other people stumble on this post and actually need to execute something AFTER rendering happens.
Cheers.
I have taken a look around Stack Overflow on the topic of onblur but so far have not been able to locate an approach to solve what I want to do.
What I have is a simple two column tables with an unknown number of rows. Rows are created at render time based on the number of boxes being shipped. Each column has the following name and id for the input box:
For column 1: shipItems[ rowNum ].barcode
For column 2: shipItems[ rowNum ].trackingcode
Pretty straight forward. What I want to do is validate the trackingcode and if in error alert the user and re-focus the cursor on the column/row that caused the problem. Users will be using a scanner to scan in the information.
Every things works except that I can not get the cursor to go back to the column/input that caused the issue in the onBlur event.
My understanding is that when the onBlur event fires the element is losing focus and thus the focus is being transferred to the new/next element.
I have tried to playing around with the onfocus event, onkeypress events but still have not been successful.
I am open to any ideal to get this done, I have spend way to much time on it as it is. JQuery is not out of the questions or just plan old Javascript.
UPDATE
Here is a link to the script on jsFiddle:
After reviewing your code, best I can tell you are experiencing an unusual bug in jQuery. I have seen some quirky things happen when using focus() (like having to use setTimeout). But, in your case the $(this) is somehow not resolving correctly when calling focus().
At first I thought it was because the id is not following HTML-4 standards, but correcting the id did not help. $(this) still failed to focus, despite the fact it correctly refers to the <input> element. Then I tried identifying the id with jQuery as a string $("'#" + thisId + "'")...still did not work. But, a hard coded id did work...
So, here's how I modified your code and worked around the problem to get it to focus
if( null === $text.match(/\b(1Z ?[0-9A-Z]{3} ?[0-9A-Z]{3} ?[0-9A-Z]{2} ?[0-9A-Z]{4} ?[0-9A-Z]{3} ?[0-9A-Z]|[\dT]\d\d\d ?\d\d\d\d ?\d\d\d)\b/))
{
alert("No Match");
//$(this).focus();//don't use jquery $this
var thisId = $(this).attr('id');//get the id
//use the setTimeout workaround for firefox
setTimeout(function() {
document.getElementById(thisId).focus();//use javascript to set focus
},0);
$(this).css('background-color','Red');
}
Feel free to look at the fiddle (linked above). This approach does correct the focus problem.
I figured out the issue. It turns out that IE and FireFox have very different behavior when it comes to onBlur.
I was calling focus() during the execution of the blur(). since the blur has not completed it either ignored the focus command or executes and then completes the blur.
Some browsers the focus command can cause a blur to be triggered thus creating an infinite loop with the cursor bouncing between the two fields.
Using a timeout will cause the focus to trigger outside of the blur call back function.
Under IE I can make use of onBlur and have no issues, under FF the focus never got called event with a timeout, so it needs an onChange.
I have updated my script - it runs fine on IE - http://jsfiddle.net/boyd4715/3wbtQ/34/