So I've been working on this all day and I can't figure out how to get it to work. I have a table with TD's filled with content which is drawn from a database using a JQuery "getJSON" command. I have an event handler set-up so that when you double click a TD element, its contents become a INPUT element with the default value of the enclosing TD's previous contents.
The INPUT element is created inside a Javascript object named "Input" like so:
var Input = function() {
var obj = this;
obj.docElement = $('<input/>').attr('type', 'text').val(obj.defaultValue);
}
All of this is working so far. My problem is, I want the user to be able to hit the RETURN key while the INPUT is selected to signify they've finished editing that field. I've tried something like the following:
$(obj.docElement).bind('keydown', function(e) {
if(e.which == 13) {
// do something
}
}
This works fine for the first time you edit a field; however, if you edit a field multiple times it stops working. Also if you randomly double click TD's eventually it breaks. I tested it and determined that the INPUT element stops registering any type event, as if the "bind" no longer existed on it.
I've done lots of googling and determined that the regular JQuery "bind" handler placed on an INPUT element is unreliable. Therefore I decided to attach the event handler to the document object instead using the following:
$(document).bind('keydown', function(e) {
// do something
}
I know I can use "e.target" to get the target element that the action is executed on (and this works for me, e.target correctly refers to the INPUT element).
My question is, how do I get the object that created the INPUT element in the first place? I need to be able to execute functions contained within the corresponding "Input"
class that was used to create the INPUT element. I need to call these functions from within the "$(document).bind" function. So basically I need to be able to get an INPUT element's parent/creator Input object.
If I haven't explained anything clearly enough, just let me know. Any help in this matter would be greatly appreciated! I'm also open to suggestions for alternative methods (other than using "$(document).bind").
Thanks!
I think I understand the problem ...
You can traverse the DOM to find the parent document element, but that's not what you mean, right? You want the parent script element that has a bunch of logic that operates on the element.
I suspect that it is probably easiest to provide some sort of reference to the parent when the input element is created ... pass this to the event handler, or set it in a globally accessible location (like a current_element_parent var).
I agree with tobyhede. You can either add a custom attribute to the INPUT element that refers back to the parent, or keep a map in memory that maps the dynamically created INPUT element to the parent that created it. When you trap the Return key, simply remove the relationship from the map so it can be added again if the user clicks it again.
Related
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 a table with data, and when I click on a cell in a certain column, I want it to change into a select dropdown for the user to choose a category for that row (which will be written to the database by AJAX but that'll come later).
I've done something similar before with text boxes using this, which works great, but I'm not sure if I'm modifying it correctly.
I've created a JSFiddle which shows the problem I'm having. I click on the text and it turns into a select element as expected, but when I click on that to choose an option, the dropdown doesn't stay open and I can't select anything. Debugging has shown me that when I click the dropdown, it runs the $("td.ChooseType").click() routine again so I've tried to suppress that by removing the class then adding it back on on selection, but that hasn't solved it. On the rare occasion that the dropdown stays open, I am unable to select anything by either mouse or keyboard.
All of the users will be on IE8 unfortunately, so I need it to be compatible with that.
Thanks!
You need to use event delegation, as otherwise that click event is always bound to that td - regardless of whether its class changes.
Simply change:
$("td.ChooseType").click(function() {
To:
$("table").on('click', '.ChooseType', function () {
JSFiddle demo.
Purely as an alternative to the accepted answer, you can remove an attached handler with unbind. So instead of adding and removing the class, you could unbind and rebind your handler. Only requirement is that the function can't be in-line, but has to be declared separately.
example: http://jsbin.com/qiqunici/1/edit
var handler = function () {
$(this).unbind('click', handler); //unbind the clicked element only
//create and change the element
//inside the select-change event, instead of addClass, re-attach:
{
//$(this).parent().addClass("ChooseType").text(selected).find('select').remove();
$(this).parent().click(handler).text(selected).find('select').remove();
}
};
$("td.ChooseType").click(handler);
I am just getting into Jquery and I am stuck on a little bit of a bug. In my HTML I generate some H tags and Labels. These H tags and Labels have an on click function that will take that element whether it be an H tag or Label and pass it off to a method (setProperties(this)).
This method will capture what was written inside the input field and assign it to that element. My bug is that after I click on 2 elements it will change to whatever was in the input on both. I am assuming the elements are now listening to the input field and assigning there text value to what was inside the input field. I am curious on how I could rearrange my code to make what ever you element you click on. That field will be the unique field to change.
Variables :
Element is the element I click on such as a H tag or Label
the id ChangeText is the input element where you type to change the label or H tags value.
function inputfield(element){
$("#changeText").on("blur",function(){
$(element).text($("#changeText").val());
});
}
Here is a Jfiddle of what my problem is. If you click on two of the test texts and then change the value of the input. It will change both. I am looking to change only one.
http://jsfiddle.net/QMsQq/5/
It appears that when the inputfield function is called, you are setting the onblur to fire.
The on function will last after the inputfield function call. Try calling "off" to remove prior set on events from changeText.
function inputfield(element){
$("#changeText").off().on("blur",function(){
$(element).text($("#changeText").val());
});
}
Warning: untested code.
http://jsfiddle.net/QMsQq/6/ Updated your fiddle to show my solution
Assign the element to a variable.
var $elem = $('whatever');
and pass that as the argument. And I think you want to fire on focus of an element (click).
Also, here is a VERY simple vanilla js example of what I think you're getting at:
http://jsfiddle.net/Lqf25/3/
Hopefully that helps a smidge.
Edit:
ok, for your fiddle:
Your input syntax is jacked. (missing '>' and you don't need '/input' anyway)
Don't use (onClick) in html. Separate your concerns - javascript goes in the script file, not inline. See my fiddle for an example. Although, from reading your latest posts I don't think it's quite what you want - I'm actually a little confused on what exactly you're trying to do...
Edit 2:
Try this: http://jsfiddle.net/w88xr/3/
I think that's what you're looking for.
I want to know if it's possible to select a textarea's content when it gets modified. In jQuery, I'd do the following:
$("texarea").on("change", function (e) {
$(this).select(); // the content gets selected for copy/cut operations
});
I know it's a bad practice to directly manipulate DOM elements from within an angular controller, so if you know how I can do this cleanly, I'd be happy to learn how!
I think you can do the following, attach an event handler to your textfield element using onblur and onfocus attributes. Write two functions for each as follows:
onfocus get the initial content of the textfield
onblur get the final content and compare to the initial content if there is a difference the run the select function
If you want it to be in real time your could also use onkeyup and onkeydown
Would it be possible for me to dynamically add an event handler to a form field. I need to do this, because in the scope of the work I am doing - the form field to which this is added is chosen dynamically.
So, I want to know if something like this would work:
document.forms['Form1'].elements['chosen_field'].onkeydown = some_function();
EDIT:
Another sub-question here. I want to pass on the event to some_function(), but do not want to return anything back. Is there a way I can do that? Essentially I am using some_function() to update some JS variable - and for that I need to find out what key was pressed.
When you assign event handlers like this
document.forms['Form1'].elements['chosen_field'].onkeydown = some_function();
You are saying assign whatever some_function returns to this keydown event.
You need to drop the () from it so you assign a reference to the function.
document.forms['Form1'].elements['chosen_field'].onkeydown = some_function;