-2

Given the following HTML:

<div class="date">
<span>
    <i class="far fa-user"></i>&nbsp;{Name}
    <i class="fas fa-link"></i>&nbsp; LINK
    <i class="fas fa-sync-alt"></i>&nbsp;{ReblogSource}
</span>
<span>
    <!--irrelevant content-->
</span>
</div>

How do I completely remove <i class="far fa-user"></i>&nbsp;{Name} when {Name} could be any (number of) plain-text characters? The <span> it appears in is the first child of .date (though there are many other instance of <span> on the page), and the string I want to remove is the first child of that. Based on Christophe's answer, I thought I could try

var string = '/<i class="far fa-user"></i>.+<i class="fas fa-link"></i>/';
replace(string, '<i class="fas fa-link"></i>');

but evidently there's something wrong with that. I'm... rather bad at this language.

+: {ReblogSource} also becomes an unknown length/content string of plain text. <i> is FontAwesome. I would rather not have answers involve the second <span>, especially if it must be involved by exact content.

++: I see both answers work in the snippet, but for some strange reason, Tumblr doesn't want to make it work. I've attached a screenshot of my end of things here, but I have a feeling I'll need to troubleshoot on my own from here.

Nintendraw
  • 147
  • 8

2 Answers2

0

How about using DOMParser instead? Select the span, then remove its first three child nodes (two text nodes and the <i>):

const str = `<div class="date">
<span>
    <i class="far fa-user"></i>&nbsp;{Name}
    <i class="fas fa-link"></i>&nbsp; LINK
    <i class="fas fa-sync-alt"></i>&nbsp;{ReblogSource}
</span>
<span>
    <!--irrelevant content-->
</span>
</div>`;
const doc = new DOMParser().parseFromString(str, 'text/html');
const span = doc.querySelector('span');
span.childNodes[2].remove(); // text node
span.childNodes[1].remove(); // <i> tag
span.childNodes[0].remove(); // text node
console.log(doc.body.innerHTML);
CertainPerformance
  • 356,069
  • 52
  • 309
  • 320
  • I appreciate the comments you put beside the `childNodes` lines, but as a raw paste, this didn't seem to work. I suspect the issue might be how long the HTML on `constant` is (I saw way too many colors for it to have worked as a single object (? "quoted mass"; my terminology is rather imprecise), OR that `{ReblogSource}` and the entire second `` as well as `{Name}` don't appear exactly like that on my page, but I don't know enough to say... – Nintendraw Sep 20 '20 at 04:43
  • 1
    What do you mean, colors? single object? – CertainPerformance Sep 20 '20 at 04:48
  • Colors --> At least in Sublime Text 3, different words (e.g. `.class` and `#id`) will show up in different colors. I'm building a Tumblr website, and within ` – Nintendraw Sep 20 '20 at 04:53
  • I added a screenshot just now, but I think at this point, there's something else in the code preventing either answer from working when I try to plug it in. Time to go bug-hunting. Thank you for helping! – Nintendraw Sep 20 '20 at 05:09
0

You can use contents() which includes text nodes and each() and break when you get to .fa-link

$('.date span:first').contents().each(function() {
  const $el = $(this);
  if ($el.hasClass('fa-link')) {
    return false// breaks each loop
  }
  $el.remove();
});

console.log($('.date')[0].outerHTML)
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="date">
  <span>
    <i class="far fa-user">fa-user</i>&nbsp;{Name}
    some extra text
    more extra text
    <i class="fas fa-link">fa-link</i>&nbsp; LINK
    <i class="fas fa-sync-alt">fa-sync-alt</i>&nbsp;{ReblogSource}
</span>
  <span>
    irrelevant content
</span>
</div>

If the source html is a string just insert it into a temporary element and do same thing

const str = `<div class="date">
<span>
    <i class="far fa-user"></i>&nbsp;{Name}
    <i class="fas fa-link"></i>&nbsp; LINK
    <i class="fas fa-sync-alt"></i>&nbsp;{ReblogSource}
</span>
<span>
    irrelevant content
</span>
</div>`

const $div = $('<div>').html(str)

$div.find('.date span:first').contents().each(function() {
  const $el = $(this);
  if ($el.hasClass('fa-link')) {
    return false // breaks loop
  }
  $el.remove();
});
console.log($div.html())
charlietfl
  • 170,828
  • 13
  • 121
  • 150
  • Similar to CertainPerformance's answer, I worry that the length of the "quoted HTML" `str` is defined as will break the function. Said HTML includes `{ReblogSource}` and the entire second `` as well as `{Name}`; none of these appear exactly like that on my page. All I know about `{ReblogSource}` and `{Name}` is that they render as plain-text; it might be safest to quote the first 4 line of HTML or less. – Nintendraw Sep 20 '20 at 04:47
  • This solution gets rid of everything before the ``. Can see I added some extra text also and it is gone. Second span is still there, I uncommented irrelevant code so it displays – charlietfl Sep 20 '20 at 04:50
  • 1
    I don't see anything in your clarifications that changes any of this from working – charlietfl Sep 20 '20 at 04:58
  • I added a screenshot just now, but I think at this point, there's something else in the code preventing either answer from working when I try to plug it in. Time to go bug-hunting. Thank you for helping! – Nintendraw Sep 20 '20 at 05:09