0

I have a nested li which is editable. How can I get the particular li when there is 'keyup' event happened on that li. No jQuery please.

I tried to put eventlistener 'keyup' on all li but e.target is giving most outermost li (li#1) instead of (li#4). when I tested with 'click' event it is giving the exact li(li#4) being keyed up.

var numberList = document.querySelector("#numberList");
numberList.addEventListener('keyup', handler)

function handler(e){
  if(e.type === 'keyup'){
        getId(e)
    }
}
<ul id = "numberList">
<li id="1">
    one
    <ul>
        <li id="2">
            two
            <ul>
              <li id="4">four</li>
            </ul>
        </li>
        <li id="3">three</li>
    </ul>
<li id = "5">
    Five
    <ul>
        <li id="6">six</li>
    </ul>
   </li>

If I edit li having value "four", I should get li with id ="4" not id="1"

sosick
  • 624
  • 3
  • 17
  • 35

2 Answers2

1

<li> isn't a keyboard focusable element. It won't register keypress events like HTML form inputs, buttons, anchors or other interactive types.

A possible solution is to add a button inside your list items and have them receive the event and then traverse up to select its parent (list item) ID.

<li id="1">
    <button>one</button>
    <ul>
        <li id="2">
            <button>two</button>
            <ul>
              <li id="4"><button>four</button></li>
            </ul>
        </li>
        <li id="3"><button>three</button></li>
    </ul>
</li>
Josue Arce
  • 48
  • 3
0

Your comment caught my attention...

when i create li, I add li.contentEditable = "true";

So, if I understand this correctly, you're using JavaScript to generate your DOM elements. If that's the case, when you generate your contentEditable li at the same time you can assign the event listener to it specifically.

'use strict';

let ul1 = document.createElement('ul');
    ul1.id = 'numberList';

let li1 = document.createElement('li');
    li1.innerHTML = 'one';
    li1.id = 'li1';

let ul2 = document.createElement('ul');
    ul2.id = 'ul2';

let li2 = document.createElement('li');
    li2.innerHTML = 'two';
    li2.id = 'li2';

let ul3 = document.createElement('ul');
    ul3.id = 'ul3';

let li3 = document.createElement('li');
    li3.innerHTML = 'four';
    li3.id = 'li3';
    li3.contentEditable = true;
    li3.addEventListener('keyup', handler);

function handler(e){
  if(e.type === 'keyup'){
        console.log( this.id );
    }
}

ul3.appendChild( li3 );
li2.appendChild( ul3 );
ul2.appendChild( li2 );
li1.appendChild( ul2 );
ul1.appendChild( li1 );
document.body.appendChild( ul1 );
Doug
  • 1,435
  • 1
  • 12
  • 26
  • So it means as soon as I create the li I should add event listener to the li. – Syed Ijlal Haider Jun 27 '19 at 10:51
  • Yep. If you want to maintain your codebase, as is, I think this may be your best bet. Although, I would definitely recommend that instead of using contentEditable; nest a textbox in li#4. I don't know exactly the limitations of contentEditable, but a textbox has been heavily engineered for user input. – Doug Jun 27 '19 at 14:11
  • Yes I implemented the textbox and it has 'onkeyup' handler which worked for me. – Syed Ijlal Haider Jun 28 '19 at 01:53