0

I have a list string like below.

<p>sub1/sub2/sub3</p>

How can we get sub1 if mouse clicks on sub1? For example:

  • If click on sub1 return sub1

  • If click on sub2 return sub1/sub2

  • If click on sub3 return sub1/sub2/sub3

How can I do that?

6
  • that impossible, Please use <span>sub1</span> Commented Dec 4, 2019 at 9:48
  • As you have a single text node within the p you cannot easily determine which word was clicked on. A better approach would be to put each word in its own element and then add click handlers to those elements. Commented Dec 4, 2019 at 9:48
  • encapsulate each in new span and check where the mouse is clicked and then decide. Commented Dec 4, 2019 at 9:48
  • Is it possible to wrap sub1, sub2, sub3 into span ? Commented Dec 4, 2019 at 9:48
  • You can not do it , you have to use 2 different <p> tags for the same. Commented Dec 4, 2019 at 9:49

4 Answers 4

4

All thing load from database, I can't put it in to a span

In this case split the text by / in to an array, then wrap each element in the array in a span and append it back to the DOM. Then you can add the delegated event handler to get the text of the current element and all previous siblings. Try this:

$('p')
  .html((i, h) => h.split('/').map(w => `<span>${w}</span>`).join('/'))
  .on('click', 'span', function() {
    var text = $(this).prevAll().addBack().map((i,e) => e.textContent).get().join('/');
    console.log(text);
  });
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<p>sub1/sub2/sub3</p>
<p>sub4/sub5/sub6</p>

On IE it does not work

This is because I used ES6 arrow functions, which IE doesn't support because it's incredibly outdated. If you need IE support change those to anonymous functions:

$('p')
  .html(function(i, h) {
    return h.split('/').map(w => `<span>${w}</span>`).join('/');
  })
  .on('click', 'span', function() {
    var text = $(this).prevAll().addBack().map(function() {
      return this.textContent;
    }).get().join('/');
    console.log(text);
  });
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<p>sub1/sub2/sub3</p>
<p>sub4/sub5/sub6</p>

Sign up to request clarification or add additional context in comments.

2 Comments

When he clicks on the second one, he want the first one too "if click on sub2 return sub1/sub2"
Because I used ES6 arrow functions, which IE doesn't support because it's incredibly outdated. If you need IE support change those to anonymous functions. I updated the answer with an example of that
1

One way you can surround each text with span element:

$('p').html($('p').text().split('/').map(el => '<span>'+el+'</span>').join('/'));
$('span').click(function(i){
  var j = $(this).index();
  var t;
  if(j > 0){
    t = $('span:lt('+j+')').map(function(_,s){
      return $(s).text();
    }).get().join('/');
    t = t+'/'+$(this).text();
  }
  else t = $(this).text();
  console.log(t)
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<p>sub1/sub2/sub3</p>

2 Comments

False, he said "if click on sub2 return sub1/sub2"
@Jérémy, you are right, didn't notice that. There might be other feasible solution, I have updated the answer with a solution:)
0

You should use a markup like <span data-sub="1">sub1</span>/<span data-sub="2">sub2</span>/<span data-sub="3">sub3</span>, so you will know which part of the text was clicked.

$('[data-sub]').on('click', function (event) {
  const currentNumber = $(event.currentTarget).data('sub');
  let texts = [];
  $('[data-sub]').each(function (index, element) {
    if ($(event.currentTarget).data('sub') <= currentNumber) {
      texts.push($(element).text());
    }
  });
  return texts.join('/');
});

Comments

0

Here is a solution using only javascript with your main paragraph having an id of subs:

const subs = document.querySelector('#subs');

subs.innerHTML = subs.textContent.split('/').map(function (text, i) {
    return `<span data-nr="${i + 1}">${text}</span>`;
}).join('/');

subs.addEventListener('click', function (evt) {
    const spans = Array.prototype.slice.call(subs.querySelectorAll('span'));
    const texts = spans.filter(function (span) {
        return span.dataset.nr <= evt.target.dataset.nr;
    })
    .map(function (span) { return span.textContent; }) ;

    console.log(texts.join('/'));
});

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.