gnorman
gnorman

Reputation: 163

Select everything between two array[index] selectors

I am building online courses out of webpages which are setup in this way:

<h1>Chapter 1</h1>
<p>Welcome to the chapter 1 overview.</p>
<h2>Unit A</h2>
<p>This is the first unit of the first chapter.</p>
<h1>Chapter 2</h1>
<p>This is the chapter 2 overview</p>

In order to automate the task of converting these webpages to online courses, I need to do 2 things:

  1. Select all of the Headings and determine their order/heirachy like so:

document.body.innerHTML = "<div align='left' id='mySpecial'></div>" + document.body.innerHTML;
myHeadings = document.querySelectorAll("h1, h2, h3, h4");
for(var i=0; i<=myHeadings.length-1; i++){
	if (myHeadings[i].outerHTML.includes('h1') == true){
		document.getElementById('mySpecial').innerHTML += '<br>>H1: '+myHeadings[i].innerText
	}
	if (myHeadings[i].outerHTML.includes('h2') == true){
		document.getElementById('mySpecial').innerHTML += '<br>>-->H2: '+myHeadings[i].innerText;
	}
	if (myHeadings[i].outerHTML.includes('h3') == true){
		document.getElementById('mySpecial').innerHTML += '<br>>-->-->H3: '+myHeadings[i].innerText;
	}
}

The above script creates an array containing each H1, H2 and H3 in the order that they occur then adds a table of contents to the beginning of the document.

  1. What I now must do is select everything (all innerHTML) that exists in between two specific headings. For example; I know that the corresponding content for the first heading consists of all html between myHeadings[0] and myHeadings[1] and so forth. I have not found a way to select everything between two selectors when using array[index] type selectors like this. See the pseudo-code below and the EVERYTHING_BETWEEN() function which theoretically returns all HTML between two array[index] selectors.

document.body.innerHTML = "<div align='left' id='mySpecial'></div>" + document.body.innerHTML;
myHeadings = document.querySelectorAll("h1, h2, h3, h4");
for(var i=0; i<=myHeadings.length-1; i++){
	if (myHeadings[i].outerHTML.includes('h1') == true){
		document.getElementById('mySpecial').innerHTML += '<br>>H1: '+myHeadings[i].innerText
        document.getElementById('mySpecial').innerHTML += EVERYTHING_BETWEEN(myHeadings[i], myHeadings[i+1])
	}
	if (myHeadings[i].outerHTML.includes('h2') == true){
		document.getElementById('mySpecial').innerHTML += '<br>>-->H2: '+myHeadings[i].innerText;
        document.getElementById('mySpecial').innerHTML += EVERYTHING_BETWEEN(myHeadings[i], myHeadings[i+1])
	}
	if (myHeadings[i].outerHTML.includes('h3') == true){
		document.getElementById('mySpecial').innerHTML += '<br>>-->-->H3: '+myHeadings[i].innerText;
        document.getElementById('mySpecial').innerHTML += EVERYTHING_BETWEEN(myHeadings[i], myHeadings[i+1])
	}
}

Does anyone know of a solution?

Upvotes: 1

Views: 204

Answers (1)

Aplet123
Aplet123

Reputation: 35512

Assuming that all your headers have the same parent element (which they do in your example), this function will work:

function EVERYTHING_BETWEEN (el1, el2) {
    var siblings = Array.from(el1.parentNode.children); // get an array of all siblings
    var between =  siblings.slice(siblings.indexOf(el1) + 1, siblings.indexOf(el2)); // get the subarray of elements between
    return between.map(v => v.outerHTML).join(""); // replace each with their outerHTML and join
}

Upvotes: 1

Related Questions