Editing an input inside a drag and droppable UL/LI - javascript

I know this is a fairly specific question, but I'm going for it...
I am using Orangoo's tools to make sortable list. The form works fine. See his example:
http://orangoo.com/AJS/examples/sortable_list.html
However, if I want to add inputs or other form elements, I cannot click on the input. The mouse will be there for a second and then disappear because the ondrag event handling stuff is taking over.
I don't want to remove the drag event from the LI because I do want to reorder the input elements. Instead, I want a way to keep the focus or ignore the ondrag handling if I click on an input. I can't figure out how to override the ondrag event though. If anyone is able to help, I would greatly appreciate it!

You need to stop the event from being fired for the drag and drop when the user clicks on an input. Just handle the mousedown event and use event.stopPropagation().
Example:
document.getElementById("input1").onmousedown = (function(e) {
e.stopPropagation();
});

Thanks for answering! I ended up giving in and just turning off the event handler.
<input id="inputId" name="inputName" value="some value" onmousedown="AJS.dnd.removeDragAble(this.parentNode);" onblur="AJS.AEV(this.parentNode, 'mousedown', this.parentNode._start_fn);" />

Related

blur event text field jquery

I have the blur event event on a text field
$(document).on('blur', '#inputEmail', function(event){
// logic here
});
When I put some text in the field click and drag on a draggable element using jQuery draggable, the event does not execute when I drop the element.
How can I fix this? It's kind of annoying.
Thanks in advance
If you want to keep the blur event, it might be a good idea to use the tradition event delegation approach. Listen for the blur event on your input with an id of inputEmail.
$("#inputEmail").on("blur", function(event) {
alert('hi');
});
http://jsfiddle.net/1qyhjshu/1
Edit: It looks like your first example worked for me as well.
http://jsfiddle.net/vbdxwt9b/
If you want to make hit on the button only after executing the code in blur event.You may hide the button and show he button after executing the blur function.
$("#inputEmail").blur( function(event) {
//code here
$("#btn").show();
});

onclick() and onblur() ordering issue

I have an input field that brings up a custom drop-down menu. I would like the following functionality:
When the user clicks anywhere outside the input field, the menu should be removed.
If, more specifically, the user clicks on a div inside the menu, the menu should be removed, and special processing should occur based on which div was clicked.
Here is my implementation:
The input field has an onblur() event which deletes the menu (by setting its parent's innerHTML to an empty string) whenever the user clicks outside the input field. The divs inside the menu also have onclick() events which execute the special processing.
The problem is that the onclick() events never fire when the menu is clicked, because the input field's onblur() fires first and deletes the menu, including the onclick()s!
I solved the problem by splitting the menu divs' onclick() into onmousedown() and onmouseup() events and setting a global flag on mouse down which is cleared on mouse up, similar to what was suggested in this answer. Because onmousedown() fires before onblur(), the flag will be set in onblur() if one of the menu divs was clicked, but not if somewhere else on the screen was. If the menu was clicked, I immediately return from onblur() without deleting the menu, then wait for the onclick() to fire, at which point I can safely delete the menu.
Is there a more elegant solution?
The code looks something like this:
<div class="menu" onmousedown="setFlag()" onmouseup="doProcessing()">...</div>
<input id="input" onblur="removeMenu()" ... />
var mouseflag;
function setFlag() {
mouseflag = true;
}
function removeMenu() {
if (!mouseflag) {
document.getElementById('menu').innerHTML = '';
}
}
function doProcessing(id, name) {
mouseflag = false;
...
}
I was having the exact same issue as you, my UI is designed exactly as you describe. I solved the problem by simply replacing the onClick for the menu items with an onMouseDown. I did nothing else; no onMouseUp, no flags. This resolved the problem by letting the browser automatically re-order based on the priority of these event handlers, without any additional work from me.
Is there any reason why this wouldn't have also worked for you?
onClick should not be replaced with onMouseDown.
While this approach somewhat works, the two are fundamentally different events that have different expectations in the eyes of the user. Using onMouseDown instead of onClick will ruin the predictability of your software in this case. Thus, the two events are noninterchangeable.
To illustrate: when accidentally clicking on a button, users expect to be able to hold down the mouse click, drag the cursor outside of the element, and release the mouse button, ultimately resulting in no action. onClick does this. onMouseDown doesn't allow the user to hold the mouse down, and instead will immediately trigger an action, without any recourse for the user. onClick is the standard by which we expect to trigger actions on a computer.
In this situation, call event.preventDefault() on the onMouseDown event. onMouseDown will cause a blur event by default, and will not do so when preventDefault is called. Then, onClick will have a chance to be called. A blur event will still happen, only after onClick.
After all, the onClick event is a combination of onMouseDown and onMouseUp, if and only if they both occur within the same element.
Replace on onmousedown with onfocus. So this event will be triggered when the focus is inside the textbox.
Replace on onmouseup with onblur. The moment you take out your focus out of textbox, onblur will execute.
I guess this is what you might need.
UPDATE:
when you execute your function onfocus-->remove the classes that you will apply in onblur and add the classes that you want to be executed onfocus
and
when you execute your function onblur-->remove the classes that you will apply in onfocus
and add the classes that you want to be executed onblur
I don't see any need of flag variables.
UPDATE 2:
You can use the events onmouseout and onmouseover
onmouseover-Detects when the cursor is over it.
onmouseout-Detects when the cursor leaves.
onFocus / onBlur are events that don't bubble. There are however focus events that do bubble. These being focusin and focusout.
Now to the solution: We wrap both the input and our dropdown into a div-element and set the tabindex of that div to -1 (so that it can recieve focus / but does not appear in the tab order). We now add an eventlistener for focusin and focusout to this div. And since these events do bubble a click on our input element will trigger our divs focusin event (which opens the drop-down)
The neat part now is that a click on our dropdown will also trigger the focusin event on our div (so we basically maintain focus which means: focusout/blur never fires and our dropdown stays open)
You can try this out with the code snippit below (the dropdown only closes on loss of focus - but if you want it to close when clicking on the dropdown aswell just uncomment the one line of JS)
const container = document.getElementById("container")
const dropDown = document.getElementById("drop-down")
container.addEventListener("focusin", (event) => {
dropDown.classList.toggle("hidden", false)
})
container.addEventListener("focusout", (event) => {
dropDown.classList.toggle("hidden", true)
})
dropDown.addEventListener("click", (event) => {
console.log("I - the drop down - have been clicked");
//dropDown.classList.toggle("hidden", true);
});
.container {
width: fit-content;
}
.drop-down {
width: 100%;
height: 200px;
border: solid 1px black
}
.hidden {
display: none
}
<div class="container" id="container" tabindex="-1">
<input id="input" />
<div class="drop-down hidden" id="drop-down" > Hi I'm a drop down </div>
</div>
there arises however one issue if you want to add your dropdown into the tabbing order, have buttons in your dropdown or in general have an element in the dropdown, that can recieve focus. Because then a click will give the element in the dropdown focus first. This triggers our container div to lose focus which closes the dropdown so the focus event can't bubble further and therefore can't trigger the focusin on our container.
We can solve this issue by expanding the focusout eventlistener a bit.
The new eventlistener is as follows:
container.addEventListener("focusout", (event) => {
dropDown.classList.toggle("hidden", !container.matches(":hover"))
})
We basically say: "don't you close that dropDown if someone is hovering over it" (This solution only considers mouse-use; but in that case this is fine, because the problem this tries to fix only ever occured when using a mouse, when tabbing onto/through the dropDown everything worked fine from the start)
change onclick by onfocus
even if the onblur and onclick do not get along very well, but obviously onfocus and yes onblur. since even after the menu is closed the onfocus is still valid for the element clicked inside.
I did and it worked.
An ideal solution I found to work for me was to simply add a timeout in my onBlur function. I used 250ms, that provided smooth behaviour for my blur event and allowed my onClick to fire before the onBlur. I used this example as a reference https://erikmartinjordan.com/onblur-prevents-onclick-react
You can use a setInterval function inside your onBlur handler, like this:
<input id="input" onblur="removeMenu()" ... />
function removeMenu() {
setInterval(function(){
if (!mouseflag) {
document.getElementById('menu').innerHTML = '';
}
}, 0);
}
the setInterval function will remove your onBlur function out from the call stack, add because you set time to 0, this function will be called immediately after other event handler finished

Jquery UI - dynamically bind the keypress event on the clicked div

jsFiddle demo link
Hi Guys,
I want to bind the keypress event handler when i click the div layer as given in the above demo. The feature is to use the delete key to remove the selected layer.
But when i hit the delete key, the keypress handler doesn't fire. Please suggest.
Remove '()':
$this.on("keypress", keyAction);
You are adding undefined as handler: $this.on("keypress", keyAction()) is equal to $this.on("keypress", undefined) in your case, as keyAction function does not return anything.
Also your div must be focusable, in order to receive keyboard events. For that reason you need to add tabindex on it:
<div class="dragClass" tabindex="0">
Then in selectAction focus your div to receive keypress event:
$this.focus();
This is the DEMO
For more information about adding keyboard events on static elements such as div, look at here:
Use this code it execute for delete key
$("#ParentDIV").keyDown(function (e) {
if (e.keyCode == 46) {
// Do it
}
});
In order for an element to receive keypress events, it needs focus. One way is to add a tabindex. If you click on your element then click a keyboard button in the below fiddle, you'll get your event. I stripped down the fiddle a bit and removed the draggable which is interfering with focus.
http://jsfiddle.net/e2yfC/27/

How do you exclude a page element from triggering a jQuery blur event?

I have an <input> that when focused on it shows a suggest drop down. When anything else is clicked the suggestions disappear. The problem is that I cannot seem to figure out to make it so that when the suggest <div> is clicked the blur event does not run.
Heres some of the HTML:
<label id="testTagsLabel">Tags:</label>
<input type="text" name="tags" id="testTags" placeholder="Ex: Poem, Edgar Allen Poe">
<div id="tagSuggest">
<ul>
<li class="tagSuggestTag">testtag</li>
<li class="tagSuggestTag">testtag2</li>
<li class="tagSuggestTag">testtag3</li>
<li class="tagSuggestTag">testtag4</li>
</ul>
</div>
Heres some of the JavaScript:
$('#testTags').focus(
function(){
$('#tagSuggest').show();
});
$('#testTags').blur(
function(){
$('#tagSuggest').hide();
});
Try something like:
$("#yourinput").blur(function(e) {
if(!$(e.target).is(".suggestDiv")) {
// close the suggest div
}
});
UPDATE: (oops, the code above doesn't work as I thought it would)
This should work:
$(document).click(function(e) {
if (!$(e.target).is("#suggest")) {
$("#suggest").hide();
}
});
Demo: http://jsfiddle.net/PNVCL/
UPDATE2:
I forgot that you still need blur, because you probably want to hide the suggest div when you switch into another input by hitting tab. Here's an updated demo: http://jsfiddle.net/PNVCL/1/
Clicking anywhere still closes the suggest div (except on the suggest div itself or the input) as well as hitting tab to switch to another input. Still needs improvements, but you should be able to pick up from here.
You should not use the blur event because it's impossible to make the difference between a blur caused by a click on the suggest box and another blur (tab, window blur, right click, ...).
A workaround given by #dakis is to use the click event on the document but the suggest box to close the box. I suggest to dynamically add and remove the document click handler to avoid overhead, and to allow the user to click in the field without closing the box.
Demo here: http://jsfiddle.net/fvwPn/
In addition I made the box to close when TAB is pressed. I also added a dirty hack version (commented) which uses the blur event and a big hack using a timeout (since the two events are fired independently, the delay depends on the client browser and speed... yep it's a dirty hack).

"onchange" event delayed in IE? (ok with Firefox)

It might be a beginner question but I can't understand why the onchange event is never called by IE while it works Ok with Firefox.
<input type="text" id="mytext" size="48" value="" onchange="execute()"/>
<button type="button" onclick="execute()">Go</button>
The execute function is called when the button is clicked but not when the text in the input box is changed.
Any idea?
IE only fires the onchange event when the element loses focus - if you were to click outside the element or tab to a different element it should fire then.
You can get around this by using a different event, for example onkeypress.
While annoying, it is not a bug that onchange is not fired until the element loses focus. (I get around the issue by having multiple bindings for different events; make sure not to clobber a handler and use an update aggregation if appropriate.)
Here is the "official" W3C documentation on the subject:
The onchange event occurs when a control loses the input focus and its value has been modified since gaining focus. This attribute applies to the following elements: INPUT, SELECT, and TEXTAREA.
Here is the MSDN reference:
This event is fired when the contents are committed and not while the value is changing. For example, on a text box, this event is not fired while the user is typing, but rather [it is fired] when the user commits the change by leaving the text box that has focus.
The behavior, while often annoying, is as specified.
As answered elsewhere, IE doesn't fire the event till you click outside the input field.
Just a quick expaination of how I fixed it with jQuery. (This is a translation of my code, so it may contain bugs...)
<input id="somecheck" name="somecheck" value="1" onchange="dosomething();">
...was changed to...
<input id="somecheck" name="somecheck" value="1">
<script language="javascript">
$(document).ready(function() {
$('#somecheck').change(function() { dosomething(); } );
});
</script>
For those new to jQuery you are basically waiting for the page to become fully loaded, then you are adding the event handler 'dosomething' to the input box.
As far as i remember, IE doesn't handle onchange event the same maner as FF.
The event will be fired when the mouse is clicked.
I advise you to use a library to handle events such as jQuery, Dojo, etc..
ohhh, I spent some time on that issue as well months ago.
I came up with this solution for FF/IE onchange
$("input[name*='delivery_method']").bind(($.browser.msie ? "click" : "change"), function() {
//your code here
});
IE does it after your input loses focus, which isn't until you click the button, tab out, or click somewhere else on the screen. Try onclick or one of the other events.

Categories

Resources