简体   繁体   中英

How to wrap the first word of a title with a span

I would like to achieve something similar , but to wrap first word of every <h1> tag with a <span> tags. It should look like this:

 <h1><span>This</span> is a title</h1>

I quess it's doneable without a plugin...

Use JavaScript String#repalce method

 var tag = document.querySelector('h1'); tag.innerHTML = tag.innerHTML.replace(/^\s*\w+/, '<span style="color:red">$&</span>');
 <h1>This is a title </h1>


FYI: Since it recreates the inner elements it will destroy any handler attached to its descendant element.


UPDATE: In case you want to update all h1 tag then you need to get all h1 and iterate over them.

 Array.from(document.querySelectorAll('h1')).forEach(function(ele) { ele.innerHTML = ele.innerHTML.replace(/^\s*\w+/, '<span style="color:red">$&</span>'); });
 <h1>This is a title </h1> <h1>This is a title </h1> <h1>This is a title </h1> <h1>This is a title </h1> <h1>This is a title </h1>

Sincerely, that task was very difficult, Great Question: By the way. I think that an acceptable solution could be what follows. I replaced all first word of h1 tag without loosing listeners... Hope it helps!

 function WrapFirstH1WordCtrl() { let titles = this.querySelectorAll("h1"); let test = this.getElementById('test'); test.onclick = () => console.log("HELLO GUYS"); Array.prototype.forEach.call(titles, (title) => { let value = title.firstChild.nodeValue; let t = /^(\w+)/.exec(value).pop(); let span = this.createElement('span'); span.innerHTML = t || ""; title.firstChild.nodeValue = value.replace(t, "") title.insertBefore(span, title.firstChild); }); } document.addEventListener('DOMContentLoaded', WrapFirstH1WordCtrl.bind(document))
 span { background: lightseagreen; }
 <h1>foo 1 <button id="test">HELLO AND KEEP LISTENERS</button></h1> <h1>foo 2</h1> <h1>foo 3</h1> <h1>foo 4</h1> <h1>foo 5</h1> <h1>foo 6</h1> <h1>foo 7</h1> <h1>foo 8</h1> <h1>foo 9</h1> <h1>foo 10</h1> <h1>foo 11</h1> <h1>foo 12</h1> <h1>foo 13</h1> <h1>foo 14</h1> <h1>foo 15</h1> <h1>foo 16</h1> <h1>foo 17</h1> <h1>foo 18</h1> <h1>foo 19</h1> <h1>foo 20</h1> <h1>foo 21</h1> <h1>foo 22</h1> <h1>foo 23</h1> <h1>foo 24</h1> <h1>foo 25</h1> <h1>foo 26</h1> <h1>foo 27</h1> <h1>foo 28</h1> <h1>foo 29</h1> <h1>foo 30</h1>

This might be an option. Not very elegant but should do the job. If i am not mistaking this should only effect the first textNode of the h1 element. The rest is just inserting the created span before the existing elements, not affecting descendant elements. Correct me if i am wrong. ;)

 var titles = document.querySelectorAll('.title'); titles.forEach(function(e) { var childNodes = [].slice.call(e.childNodes), txtContent = childNodes.shift().textContent, span; e.childNodes[0].textContent = ''; txtContent.split(' ').forEach(function(s, i) { if(i > 0) { e.insertBefore(document.createTextNode(" " + s), e.children[1]); } else { span = document.createElement('span'); span.textContent = s; e.insertBefore(span, e.firstChild); } }) })
 span { color: red; }.baz { color: green; }
 <h1 class="title">Hello World</h1> <h1 class="title">Hello Foo Bar <span class="baz">Baz</span></h1>

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