last.fm has this nifty feature when you're adding an event. you have the Artists field, and when you start typing in it, another text field appears beneath it. when you start typing in that next field, another new field appears beneath and so on. I've been trying to figure out how to mimic this functionality using jquery but I can make it work on the first, stationary, field only. any ideas?
edit:
actually, nope, it's not working even for the stationary one, since it adds the field on EVERY key press
edit2:
alrighty, so some fine folks have already solved my adding issue, now, how would one go about adding the field only after the first time a key is pressed.
You are probably only binding your handler to the first static input, and not the dynamically created ones. Use .live() to do your event binding. That will bind the event to future elements that match the selector.
To make sure you only add one new one, make sure you only add it when typing into the last textbox. Check $(this).closest(".container").next(".container").length to make sure there isn't already a new textbox.
$("input.myClass").live("keyup", function (e) {
var $container = $(this).closest(".container");
if (this.value && !$container.next(".container").length) {
var $newContainer $("<div>").insertAfter($container).addClass("container");
...
}
});
Live is the right idea but closest is overkill: jsFiddle
$("input").live("keyup", function (){
if ( !$(this).next('input').length ) $(this).after('<input type="text"></input>');
});
Related
I have the following JSFiddle set up. At the moment, I have three divs, each with their own input. Each input has a checkbox where another input can be added. If unchecked the input is then removed again. The code for this is
$(function() {
$('input:checkbox[name="labelNewline"]').change(function() {
if ( $(this).is(':checked') ){
var clone = $(this).parent().siblings(".labelAndInput").first().clone().insertAfter($(this).parent());
clone.addClass('clone');
} else {
$(this).parent().siblings(".clone").remove();
}
});
});
I am trying now to do something else. If a new line is added, the new input should also get a checkbox with the ability to add a new input. So I no longer want to limit this to only one input being added. However, if the checkbox for an input is unchecked, it should remove its related input.
Would something like this be possible?
Thanks
Yes, it's possible.
Here's a working fiddle:
https://jsfiddle.net/yvnyk69v/1/
Things of note:
$("#testingContainer").delegate('input:checkbox[name="labelNewline"]', 'change', function() {
The delegate function is really useful in this case. What it does it it takes an element, and will apply an event handler to any element that matches the selector specified in the delegate function, even if it's added after code has already run.
The UI was pretty simple, so I was able to target elements with next and previous. If it becomes more complex, you may want to add a an attribute or class to more easily identify the corresponding inputs.
I have created a list of input tags wrapped in a div to produce an editable text list.
However, when I add a new element to this list by hitting Enter, the new empty element is automatically populated with the last keyboard input, instead of being blank.
Here is a link the JsBin describing the issue:
https://jsbin.com/kovipurace/edit?html,output
I am expecting an empty input instead.
Is there a way to implement the expected behaviour correctly?
I initially based my code off of the CommentForm in the react tutorial, but I have deliberately not used a form tag to give cleaner use of the hitting the Enter key (don't want to mess around with e.preventDefault() etc.) I have also put in additional functionality in the actual version to allow updating existing values using an onBlur event.
What I have tried:
I have (correctly, hopefully!) implemented controlled components as stated in the docs.
I have experimented with using defaultValue and instead of value but the effect is the same. In both cases I am using {this.props.value}
You create new textentries with textEntry text.
keyHasBeenPressed : function(e) {
if (e.keyCode == 13) {
var textEntry = this.refs.textEntry.value;
this.props.createEntry(textEntry);
}
},
All you need is to make the args of createEntry blank.
this.props.createEntry();
https://jsbin.com/daqura/1/edit?html,output
I found help on #reactjs IRC channel and commenters here.
In the keyHasBeenPressed function, the state needs to be set explicitly again, as it is in handleChange.
getInitialState is just used to intialize state once in a component's life cycle.
I've got a form where I'm trying to do the sort of thing you often see with tags: there's a textfield for the first tag, and, if you put something into it, a new and similar textfield appears to receive another tag. And so on. I've gotten the basics of this working by setting up a jQuery .blur() handler for the textfield: after the value is entered and the user leaves the field, the handler runs and inserts the new field into the form. The handler is pretty vanilla, something like:
$('input.the_field_class').blur(function () { ... });
where .the_field_class identifies the input field(s) that collect the values.
My problem is that, while the new textfield is happily added to the form after the user enters the first value, the blur handler doesn't fire when the user enters something into the newly-added field and then leaves it. The first field continues to work properly, but the second one never works. FWIW, I've watched for and avoided any id and name clashes between the initial and added fields. I had thought that jQuery would pick up the added textfield, which has the same class markings as the first one, and handle it like the original one, but maybe I'm wrong -- do I need to poke the page or some part of it with some sort of jQuery initialization thing? Thanks!
Without seeing your code in more of its context, it's hard to know for sure, but my best guess is that you're attaching a handler to the first field, but there is no code that gets called to attach it to the new field. If that's the case, you have a few options, two of which are:
1) In your blur() handler, include code to attach the blur handler to the newly created field.
2) Use jQuery's event delegation to attach a handler to the field container, and listen for blur events on any field in the container:
<div class="tag-container">
<input class="the_field_class" /> <!-- initial tag field -->
</div>
<script>
var $tagContainer = $('.tag-container');
var createNewField = function() {
$tagContainer.append($('<input class="the_field_class" />');
};
$tagContainer.on('blur', 'input.the_field_class', createNewField());
</script>
Which is better will depend on your use case, but I'd guess that the 2nd option will be better for you, since you're unlikely to be dealing with tons of blur events coming from the container.
I have two inputs that together form a single semantic unit (think an hours and minutes input together forming a time input). If both inputs lose focus I want to call some Javascript function, but if the user merely jumps between those two, I don't want to trigger anything.
I've tried wrapping these two inputs in a div and adding an onBlur to the div, but it never triggers.
Next I tried adding onBlurs to both inputs and having them check the other's :focus attribute through jQuery, but it seems that when the onBlur triggers the next element hasn't received focus yet.
Any suggestions on how to achieve this?
EDIT: Someone questioned the purpose of this. I'd like to update a few other fields based on the values contained by both these inputs, but ideally I don't want to update the other fields if the user is still in the process of updating the second input (for instance if the user tabs from first to second input).
I made a working example here:
https://jsfiddle.net/bs38V/5/
It uses this:
$('#t1, #t2').blur(function(){
setTimeout(function(){
if(!$('#t1, #t2').is(':focus')){
alert('all good');
}
},10);
});
var focus = 0;
$(inputs).focus(function() { focus++ });
$(inputs).blur(function() {
focus--;
setTimeout(function() {
if (!focus) {
// both lost focus
}
}, 50);
});
An alternative approach is to check the relatedTarget of the blur event. As stated in the MDN documentation this will be the element which is receiving the focus (if there is one). You can handle the blur event and check if the focus has now been put in your other input. I used a data- attribute to identify them, but you could equally well use the id or some other information if it fits your situation better.
My code is from an angular project I've worked on, but the principle should translate to vanilla JS/other frameworks.
<input id="t1" data-customProperty="true" (blur)="onBlur($event)">
<input id="t2" data-customProperty="true" (blur)="onBlur($event)">
onBlur(e: FocusEvent){
const semanticUnitStillHasFocus = (val.relatedTarget as any)?.dataset?.customProperty === "true";
// Do whatever you like with this knowledge
}
What is the purpose of this behavior ?
The blur event triggers when a field looses focus, and only one field can gain focus at a time.
What you could do, in case of validation for instance, is to apply the same function on blur for both the fields and check the values of the fields altogether.
Without a context, it is difficult to help you more.
d.
I used a jquery combobox for autocompletion and I needed to clean its value.
I got into a solution which is like this: http://jsfiddle.net/BbWza/30/
The problem is that the code below clears all textboxes of all combos in the screen. I'd like to clear only ONE combo (let's say the first one, for example).
$('.ui-autocomplete-input').focus().val('');
Although there is only one clear link button, it doesn't matter which combo will be cleared as long as only one is.
The solution should work for N combos in the screen. E.g. Each button should empty its corresponding combo.
You can add ids to the generated fields by adding this line as the last line of _create():
input.attr( 'id', $(select).attr( 'id' )+'-input' );
Now you can select individual fields with the ids:
$('#combobox-input').focus().val('');
To clear just only one combo you must select it with it's id:
$('#combobox').focus().val('');
$('#combobox').autocomplete('close');
with your code you are selecting all comboboxes because you are using a class selector.
EDIT if you want to make two buttons (one for each combobox) you could do:
$('.clicky').click(function() {
var combo= $(this).prevAll('input:first');
combo.focus().val('');
combo.autocomplete('close');
return false;
});
fiddle here: http://jsfiddle.net/BbWza/39/
Your jsfiddle is a little ambiguous as to which combo box should be cleared - there are two combo boxes but only one clear link, so it's not obvious if the link is supposed to clear just one or both combo boxes.
I suspect in the real world that each combo box would have it's own clear link. Selecting the right text box for your clear link all depends on your html. One simple case would be where the clear link is the next sibling to your <select> element:
<select class="combo">
...
</select>
Clear
Then you could create the combos in one call by using class. Then create the clear click handlers all at once. The handler would use .prevAll(".ui-autocomplete-input") to find its associated textbox.
$("select.combo").combobox();
$("a.clearCombo").click(function () {
$(this).prevAll('.ui-autocomplete-input').first()
.focus()
.val('')
.autocomplete('close');
return false;
});
Working demo at jsfiddle
If your link is not a sibling of your combo box, that's ok. Either find its parent that is a sibling and use the above approach. Or, if that won't work, find the common parent of both the combo and the link. This only works if the common parent contains only one combo and one link:
<span class="comboContainer">
<span>
<select class="combo">
...
</select>
</span>
Clear
</span>
You use .closest(".comboContainer") and .find(".ui-autocomplete-input"):
$("select.combo").combobox();
$("a.clearCombo").click(function () {
$(this).closest(".comboContainer").find('.ui-autocomplete-input')
.focus()
.val('')
.autocomplete('close');
return false;
});
Working demo at jsfiddle
The nice thing about these techniques is that the link doesn't need to know the id of its associated combobox. We can just infer it from the html. This makes it very easy to move combos around and add new ones.
Two suggestions:
Add a clear method to your plugin. Your widget users shouldn't have to know its internal workings. In your example, you have to know that widget uses .autocomplete(). This also prevents you from changing your implementation later. Adding a "clear" method would simplify your click handler to just $(this).prevAll("select.combo").combobox("clear").
Give your widget the option to create the clear button itself. Users can always disable it and add their own clear button if they want.
Well, in the example the following would only clear the last combobox:
$('.ui-autocomplete-input').last().focus().val('');
This would clear the first one:
$('.ui-autocomplete-input').first().focus().val('');
You can clear it in event "close" of the autocomplete
$("#your-input").autocomplete({
source: items,
close: function (event, ui) {
$(this).val("");
}
});
How to give clear button for autocombobox please tell me
You can add ids to the generated fields by adding this line as the last line of _create():
input.attr( 'id', $(select).attr( 'id' )+'-input' );
Now you can select individual fields with the ids:
$('#combobox-input').focus().val('');