简体   繁体   中英

How to get first text node of a string while containing bold and italic tags?

  1. String(s) is dynamic
  2. It is originated from onclick event when user clicks anywhere in dom
  3. if string(s)'s first part that is:

    " login<b>user</b>account "

is enclosed in some element like this :

" <div>login<b>user</b>account</div> ",

then I can get it with this:

alert($(s).find('*').andSelf().not('b,i').not(':empty').first().html());
// result is : login<b>user</b>account

But how can i get the same result in this condition when it is not enclosed in any element .ie when it is not enclosed in any element?

I tried this below code which works fine when first part do not include any <b></b> but it only gives "login" when it does include these tags.

 var s = $.trim('login<b>user</b> account<tbody> <tr> <td class="translated">Lorem ipsum dummy text</td></tr><tr><td class="translated">This is a new paragraph</td></tr><tr><td class="translated"><b>Email</b></td></tr><tr><td><i>This is yet another text</i></td> </tr></tbody>');

    if(s.substring(0, s.indexOf('<')) != ''){
       alert(s.substring(0, s.indexOf('<')));
    }

Note: Suggest a generic solution that is not specific for this above string only. It should work for both the cases when there is bold tags and when there ain't any.

So it's just a b or a i , heh?

A recursive function is always the way to go. And this time, it's probably the best way to go.

var s = function getEm(elem) {
    var ret = ''

    // TextNode? Great!
    if (elem.nodeType === 3) {
        ret += elem.nodeValue;
    }

    else if (elem.nodeType === 1 &&
        (elem.nodeName === 'B' || elem.nodeName === 'I')) {

        // Element? And it's a B or an I? Get his kids!
        ret += getEm(elem.firstChild);
    }

    // Ain't nobody got time fo' empty stuff.
    if (elem.nextSibling) {
        ret += getEm(elem.nextSibling);
    }

    return ret;
}(elem);

Jsfiddle demonstrating this: http://jsfiddle.net/Ralt/TZKsP/

PS: Parsing HTML with regex or custom tokenizer is bad and shouldn't be done.

You're trying to retrieve all of the text up to the first element that's not a <b> or <i> , but this text could be wrapped in an element itself. This is SUPER tricky. I feel like there's a better way to implement whatever it is you're trying to accomplish, but here's a solution that works.

function initialText(s){
  var test  = s.match(/(<.+?>)?.*?<(?!(b|\/|i))/);

  var match = test[0];
  var prefixed_element = test[1];

  // if the string was prefixed with an element tag
  // remove it (ie '<div> blah blah blah')
  if(prefixed_element) match = match.slice(prefixed_element.length);

  // remove the matching < and return the string
  return match.slice(0,-1);
}

You're lucky I found this problem interesting and challenging because, again, this is ridiculous.

You're welcome ;-)

Try this:

if (s.substring(0, s.indexOf('<')) != '') {
  alert(s.substring(0, s.indexOf('<tbody>')));
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM