0

I am using jQuery .replaceWith method to enable users to reply or cancel commenting on a post. The reply button works as it creates a text box when clicked. However, clicking the cancel button refreshes the page instead of going back to the original post without page reload. How can I make the cancel button function properly? Thank you for your help!

        <form method="post">
            <input type="hidden" name="post_id" value="{{ p.key.id() }}">
            <input type="hidden" name="user_id" value="{{ user.key.id() }}">
            <input type="button" name="reply" id="{{ p.key.id() }}" value="Reply">
        </form>

        <script>
            $("#{{ p.key.id() }}").click(function() {

                var reply = $("<textarea name='reply_content' style='resize: none; width: 550px; height: 100px;'></textarea><br><input type='submit' name='reply' value='Reply'><input type='submit' id='cancel_{{ p.key.id() }}' value='Cancel'>")

                $("#{{ p.key.id() }}").replaceWith(reply);

            });

            $("#cancel_{{ p.key.id() }}").click(function() {

                var cancel = $("<input type='button' name='reply' id='{{ p.key.id() }}'' value='Reply'>");

                $("#{{ p.key.id() }}").replaceWith(cancel);

            });

        </script>
Young
  • 419
  • 3
  • 19
  • What is {{ p.key.id() }} in your selectors for jQuery? – calcazar Nov 02 '16 at 15:27
  • @calcazar I'm using Jinja2 template so I'm passing a variable from the server side to my template. – Young Nov 02 '16 at 15:37
  • cancel_whateverid is being added dynamically, therefore you'll have to either bind the event when it is added, or use even delegation. the dupe has code samples. (note that the "accepted" answer isn't always the best) – Kevin B Nov 02 '16 at 15:38
  • @KevinB Thanks so much for the help. I'll try the latter as when I tried binding the event, the cancel button became unresponsive. – Young Nov 02 '16 at 15:48

1 Answers1

1

EDIT: Now that I know more information, I'm updating my old answer.

New Answer:

I looked over the code and realized that there were a couple of things going on. The first was a delegation issue which occurs when you tie an event to an object and then remove it from the DOM which is what is happening with that replaceWith. You can read more about delegation here:

https://learn.jquery.com/events/event-delegation/

The second issue is that you made your buttons submit. Because of this, the form was trying to POST to the SS and thus the refresh. In the JS fiddle below; I have changed them to buttons but if you require the submit, you can just use e.preventDefault to prevent the form from submitting.

The third issue was what I believe you trying to hide the textarea and reply buttons on the cancel button click. This didn't work because you would have replaced the reply button and not the entire form itself which caused the buttons to change but the textarea to persist.

Now I'm sure there are cleaner ways of doing it on jsFiddle but I'm hoping this got the point across with what was going on.

The fixes that I applied was to save the original state (for the cancel button to go back to), fix the buttons and events, and change the cancel button to just repopulate using the original state.

EDIT 2: I forgot to attach the new fiddle!

https://jsfiddle.net/6s03k0eb/5/

OLD Answer:

So there are a couple of things going on here. First The below is an invalid HTML ID

<input type="button" name="reply" id="{{ p.key.id() }}" value="Reply">

Id's can't start with a number and should most definitely not contain brackets. If this id, is being populated by the server then you definitely need to update the jQuery with the proper ID and not the server side variable:

Incorrect

  $("#{{ p.key.id() }}")

Correct

  $("#someID")

The reason your page keeps on refreshing is because you have a JS error due to the invalid jQuery selector so the button does its default action which is to submit the form.

Here is a JS fiddle showing the code working with the proper ID values: https://jsfiddle.net/6s03k0eb/

calcazar
  • 1,120
  • 1
  • 12
  • 22
  • I'd be rather surprised if that wasn't a template string that's being parsed server-side before being returned to the client, considering the first half of the code does work, even with said "invalid jquery selector" – Kevin B Nov 02 '16 at 15:33
  • Right.. but the JS shouldn't be referencing the Server-side variable. It should be referencing the DOM object. – calcazar Nov 02 '16 at 15:34
  • Right, but he's outputting the script with – Kevin B Nov 02 '16 at 15:34
  • I'm not entirely sure that's what's going on without more information. If you check the JS fiddle with the exact code he wrote; it works and causes no refresh – calcazar Nov 02 '16 at 15:35
  • well, no, your jsfiddle refreshes when you click cancel. *checkmate* – Kevin B Nov 02 '16 at 15:36
  • @calcazar@kevin @kevin is right. I'm using Jinja2 template and server-side variables are being passed to the template. I'm just providing a unique ID to each post so the jQuery method only responses to that specific post. – Young Nov 02 '16 at 15:41
  • @kevin I made additional changes and revised my answer based on the new information. – calcazar Nov 02 '16 at 16:20
  • 1
    @calcazar Your new solution is working beautifully! I modified the variables and was able to make the cancel feature work specifically for a selected post. Thank you so much for your help! – Young Nov 02 '16 at 17:43