skip to Main Content

i want to make an Jupyter notebook-like input, where i have spans as inputs, and when the user clicks Enter a new input is added to the page and so on. the problem is the listener for click event works only on the first input. how can i make it functional on all the blocks.


    $inputSpan.on('click', function() {
        $inputSpan.attr('contenteditable', 'true').focus();
    });

    $inputSpan.on('blur', function() {
        $inputSpan.removeAttr('contenteditable');
    });

    $inputSpan.on('keydown', function(event) {
        if (event.key === 'Enter') {
            if (event.shiftKey) {
                // ... action for enter click
            } else {
                // ... end editing 
                $inputSpan.blur();
                event.preventDefault();
                add_block(); // this function append a new block to the page
            }
        }
    });

above is the code i used.

2

Answers


  1. Here’s how you can modify your code to use event delegation:

    1. Attach the event listeners to a parent element that will contain all the dynamically added input blocks.
    2. Use the .on() method to delegate the event to the newly added input blocks.

    Assuming your input blocks are within a container element with the ID inputContainer, you can modify your code as follows:

    $(document).ready(function() {
    // Parent container for the input spans
    const $inputContainer = $('#inputContainer');
    
    // Function to add a new input block
    function add_block() {
        const $newInputSpan = $('<span class="input-block"></span>').text('Click to edit');
        $inputContainer.append($newInputSpan);
    }
    
    // Delegated click event for input spans
    $inputContainer.on('click', '.input-block', function() {
        $(this).attr('contenteditable', 'true').focus();
    });
    
    // Delegated blur event for input spans
    $inputContainer.on('blur', '.input-block', function() {
        $(this).removeAttr('contenteditable');
    });
    
    // Delegated keydown event for input spans
    $inputContainer.on('keydown', '.input-block', function(event) {
        if (event.key === 'Enter') {
            if (event.shiftKey) {
                // ... action for shift + enter click
            } else {
                // ... end editing 
                $(this).blur();
                event.preventDefault();
                add_block(); // this function appends a new block to the page
            }
        }
    });
    
    // Initial block
    add_block(); });
    
    Login or Signup to reply.
  2. I’ve created a runnable snippet that demonstrates the behavior you desire. Note that I have used INPUTs instead of SPANs, but this doesn’t effect how to do it / how to make it work

    function add_block(e) {
      console.log("add_block: " + e.target);
      let toAdd = e.target.closest("P").cloneNode(true);
      console.log("to add: " + toAdd);
      addListeners($(toAdd.querySelector("INPUT")));
      $(e.target).after(toAdd);
    }
    
    function addListeners($inputSpan) {
    
    $inputSpan.on('click', function() {
            $inputSpan.attr('contenteditable', 'true').focus();
            console.log("click");
        });
    
        $inputSpan.on('blur', function() {
            $inputSpan.removeAttr('contenteditable');
            console.log("blur");
        });
    
        $inputSpan.on('keydown', function(event) {
          console.log("keydown");
            if (event.key === 'Enter') {
                if (event.shiftKey) {
                    // ... action for enter click
                } else {
                    // ... end editing 
                    $inputSpan.blur();
                    event.preventDefault();
                    add_block(event); // this function append a new block to the page
                }
            }
        });
        console.log("foo");
    }
    
    addListeners($("INPUT"));
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
    <P>Enter Info:<Input name="foo" /></P>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search