Reputation: 6025
I have an event handler attached to a class, as so:
$('#container').on('click', '.myClass', function (e) {...
Within this handler I want to attach a different click handler to the element that has been clicked. When the temporary handler has been clicked, I want to re-enable the original handler.
What I'm trying to do (as shown in this fiddle) is allow a section of text to be clicked, change that to an input text box, and then submit the change to recreate the text.
I've tried the following without success as found at the fiddle:
$('#container').on('click', '.submit', function (e) {
var $this = $(this),
new_text = $this.prev().val();
e.stopPropagation();
$this.parent().off('click.temp').html(new_text);
});
$('#container').on('click', '.test', function (e) {
var $this = $(this);
$this.html("<input type='text' value='" + $this.text() + "'/><input class='submit' value='Submit' type='submit'>");
$this.on('click.temp', function (e) {
e.stopPropagation();
});
});
Using an .off()
doesn't seem to cancel the original handler on the class because it is attached to the class not the element.
I think I've partly answered my question with e.stopPropagation()
, but it's still not quite working and I'm not convinced I'm going about this the best way :)
Note: This post relates to the idea but does not use this
.
Upvotes: 1
Views: 1262
Reputation: 66693
I basically restructured your code so that the events are turned on and off in the same manner.
Updated Demo: http://jsfiddle.net/qZVzY/6/
Updated Code
onClickReadMode
- is the event handler when the div is clicked while in read mode
onClickEditMode
- is the event handler when the div is clicked while in edit mode
function onClickReadMode(_elem) {
console.log('onClickReadMode');
var $this = _elem, text = $this.text();
$this.html("<input class='text' type='text' value='" + text + "'/><input class='.submit' value='Submit' type='submit'>");
_elem.off('click.before');
_elem.on('click.after', function() {
onClickEditMode($(this));
});
_elem.find('.text').on('click.stopevent', function(e) {
e.stopPropagation();
return false;
});
}
function onClickEditMode(_elem) {
console.log('onClickEditMode');
var $this = _elem;
var new_text = $this.find('input').val();
$this.html(new_text);
_elem.off('click.after');
_elem.on('click.before', function() {
onClickReadMode($(this));
});
}
$('.test').on('click.before', function (e) {
onClickReadMode($(this));
});
Upvotes: 1
Reputation: 87073
You can do it simply like following:
function testClick() {
var $this = $(this),
text = $this.text();
// you have to off the click like this
$('#container').off('click', '.test');
$this.html(
"<input class='text' type='text' value='" + text + "'/><input class='submit' value='Submit' type='submit'>"
);
$this.find('.submit').on('click', function(e) {
e.stopPropagation();
var new_text = $this.find('input.text').val();
$this.html(new_text);
$('#container').on('click', '.test', testClick); // again on click
});
}
$('#container').on('click', '.test', testClick);
function testClick() {
var $this = $(this),
text = $this.text();
// you have to off the click like this
$('#container').off('click', '.test');
$this.html("<input class='text' type='text' value='" + text + "'/><input class='submit' value='Submit' type='submit'>");
}
$('#container').on('click', '.submit', function(e) {
e.stopPropagation();
var new_text = $(this).prev('input.text').val();
$(this).parent().html(new_text);
$('#container').on('click', '.test', testClick); // again on click
});
$('#container').on('click', '.test', testClick);
Upvotes: 2
Reputation: 150070
Rather than adding and removing handlers for the inputs on the fly, I'd stick with delegated event handlers like you're already doing in the click handler that creates the inputs:
$('#container').on('click', '.test', function (e) {
var $this = $(this);
$this.removeClass("test")
.html("<input type='text' value='" + $this.text() + "'/><input id='me' value='Submit' type='button'>");
});
$('#container').on('click', 'input[type="button"]', function (e) {
var $this = $(this),
new_text = $this.prev().val();
$this.parent().addClass("test")
.html(new_text);
});
On click of a '.test' div replace its contents with inputs like you were doing, but also remove the "test" class so that further clicks on the div won't do anything (for the moment).
On click of a submit button change the div back to just show the text, and add the class back again so that the previous click handler takes effect again.
Note: I've changed your buttons from type="submit"
to type="button"
because they're not actually used to submit a form.
Demo: http://jsfiddle.net/4vmQ4/5/
Upvotes: 1