0

I have a .on(click) perfectly working the first time, but fails the second, in the way I describe below. This is the code:

$('.inline-edit').on('click', function() {
       if (!$(this).find(':input').length) {
             var current_val = $(this).find('span').html();
             $(this).html('<input type="text" class="txt" maxlength="27" value="' + current_val + '"/>');

             //On outside click, cancel
             $(this).unbind('clickoutside').bind('clickoutside', function(event) {
                  cancelEdit($(this), current_val);
             })
        }
});

When the <td> that has the class inline-edit are clicked, the value in the inner span is obtained, and an input is enabled. This way the user can do an inline edit. When the user clicks outside the <td>, the edit is canceled, calling cancelEdit(), which is:

function cancelEdit(element, value) {
    $(element).html('<span>' + value + '</span><img id="pencil_edit" src="/images/pencil_edit.png">');
}

The cancelEdit function returns the <td> to its original form, which is:

<td class="inline-edit">
     <span>abcdpqsdfsdfsdfrstuvwxyz<?php echo $i?></span>
     <img id="pencil_edit" src="/images/pencil_edit.png"/>
</td>

The problem is that after cancelEdit is called, now when the user clicks on the <td>, if they click over the <span> part (the text), the .on('click') function does not work properly, because the <span> element is being obtained, instead of the <td>. This however only happens the second time, even though the html is exactly the same as the first time. Why is this happening?

luqita
  • 4,008
  • 13
  • 60
  • 93
  • 1
    live has been depreciated. Have you tried using on() ? Also there is a plugin that already does that: Jeditable - jQuery in place edit plugin * http://www.appelsiini.net/projects/jeditable – Drew Aug 08 '13 at 17:08
  • No reason to use `live` anymore (unless your jQuery version is that old): http://stackoverflow.com/questions/8021436/turning-live-into-on-in-jquery – Ian Aug 08 '13 at 17:09
  • yes, on() doesn't change anything. – luqita Aug 08 '13 at 17:10
  • yes, this is a project that uses an old jquery version and I have to use live for now. – luqita Aug 08 '13 at 17:10
  • i changed everything to .on(), because the problem is the same. – luqita Aug 08 '13 at 17:11
  • Why did you change your question from `.live()` to `.on()`? Which are you actually asking about? Your code is no longer equivalent to the original. –  Aug 08 '13 at 17:11
  • both are the same, the question is independent to whether we use .live or .on... can we change the subject now? :) – luqita Aug 08 '13 at 17:12
  • No, they're not the same. –  Aug 08 '13 at 17:12
  • i just changed it in my code and the result is the same!!! – luqita Aug 08 '13 at 17:12
  • i mean it gives the same result/issues. – luqita Aug 08 '13 at 17:13
  • your losing the scope of $(this) when you set the unbind. – Rooster Aug 08 '13 at 17:15
  • @Rooster: He's binding to the same element, so `this` should be the same. –  Aug 08 '13 at 17:18
  • @CrazyTrain hmmm. Nice catch. I don't really use bind so it was more of a guess....He should really post a fiddle so I don't have to guess, because the world revolves around my chicken coop. – Rooster Aug 08 '13 at 17:21

3 Answers3

3

You need to stopPropagation I think fiddle:

$('.inline-edit').on('click', function(ev) {
       var td = $(this);
       if (!td.find(':input').length) {
             var current_val = td.find('span').html();
             td.html('<input type="text" class="txt" maxlength="27" value="' + current_val + '"/>');

             //On outside click, cancel
             td.one('clickoutside', function(event) {
                  cancelEdit(td, current_val);
             })
        }
    ev.stopPropagation();
});

function cancelEdit(element, value) {
    $(element).html('<span>' + value + '</span><img id="pencil_edit" src="http://placehold.it/20">');
}

I also set a variable for the element because there's really no need to keep calling $(this), over and over.

kalley
  • 18,072
  • 2
  • 39
  • 36
0

Try this:

$('body').on('click', '.inline-edit', function() {
       if (!$(this).find(':input').length) {
             var current_val = $(this).find('span').html();
             $(this).html('<input type="text" class="txt" maxlength="27" value="' + current_val + '"/>');

             //On outside click, cancel
             $(this).unbind('clickoutside').bind('clickoutside', function(event) {
                  cancelEdit($(this), current_val);
             })
        }
});
Deepak Biswal
  • 4,280
  • 2
  • 20
  • 37
0

I had accepted another answer, which works, but this is superior:

    $('.inline-edit').on('click', function(ev) {
       var td = $(this);
       if (!td.find(':input').length) {
             var current_val = td.find('span').html();
             td.html('<input type="text" class="txt" maxlength="27" value="' + current_val + '"/>');

             //On outside click, cancel
             td.unbind('clickoutside').bind('clickoutside', function(event) {
                  cancelEdit(td, current_val);
             })
        }
    });

I removed the event.stopPropagation() from above, which is not needed if cancelEdit looks like this:

function cancelEdit(element, value) {
    $(element).html('<span>' + value + '</span><img id="pencil_edit" src="/images/pencil_edit.png">');
    $(element).unbind('clickoutside');
}

The trick is unbinding the clickoutside, otherwise it remains binded to the element, even with the new html. Hope that helps someone in a similar situation.

luqita
  • 4,008
  • 13
  • 60
  • 93
  • That's a good solution. After seeing that, you could also do as in this [fiddle](http://jsfiddle.net/YAEdM/1/), using `.one` instead of `bind` – kalley Aug 10 '13 at 22:07
  • Looks good too :) Any reason to keep the ev.stopPropagation() though? – luqita Aug 12 '13 at 22:49
  • Yep. Even this seems to have issues depending on where you click: http://jsfiddle.net/YAEdM/3/. If you click directly on the text, there's still an issue (at least in Chrome). The other option would be to bind the `clickoutside` from within a `setTimeout`. – kalley Aug 13 '13 at 00:35