Skip to content

Instantly share code, notes, and snippets.

@jonurry
Created March 26, 2018 17:25
Show Gist options
  • Select an option

  • Save jonurry/f04be3c611e620844d2c66b2fa6f2870 to your computer and use it in GitHub Desktop.

Select an option

Save jonurry/f04be3c611e620844d2c66b2fa6f2870 to your computer and use it in GitHub Desktop.
15.3 Looping a triangle (Eloquent JavaScript Solutions)
<style>
button {
background-color: whitesmoke;
}
.selected {
background-color: white;
}
</style>
<tab-panel>
<div data-tabname="one">Tab one</div>
<div data-tabname="two">Tab two</div>
<div data-tabname="three">Tab three</div>
</tab-panel>
<script>
function clickTab(e) {
let tabs = e.target.parentNode.parentNode.querySelectorAll('[data-tabname]');
for (let tab of tabs) {
if (tab.getAttribute('data-tabname') == e.target.textContent) {
tab.hidden = false;
} else {
tab.hidden = true;
};
};
e.target.parentNode.childNodes.forEach((node) => {
node.className = '';
});
e.target.className = 'selected';
};
function asTabs(node) {
let buttons = document.createElement('div');
let first = true;
for (let tab of node.children) {
let button = document.createElement('button');
button.textContent = tab.getAttribute('data-tabname');
button.onclick = clickTab;
if (first) {
button.className = 'selected';
tab.hidden = false;
first = false;
} else {
tab.hidden = true;
}
buttons.appendChild(button);
}
node.insertBefore(buttons, node.firstChild);
}
asTabs(document.querySelector("tab-panel"));
</script>
@jonurry

jonurry commented Mar 26, 2018

Copy link
Copy Markdown
Author

Hints

One pitfall you might run into is that you can’t directly use the node’s childNodes property as a collection of tab nodes. For one thing, when you add the buttons, they will also become child nodes and end up in this object because it is a live data structure. For another, the text nodes created for the whitespace between the nodes are also in childNodes, but should not get their own tabs. You can use children instead of childNodes to ignore text nodes.

You could start by building up an array of tabs, so that you have easy access to them. To implement the styling of the buttons, you could store objects that contain both tab panel and its button.

I recommend writing a separate function for changing tabs. You can either store the previously selected tab, and only change the styles needed to hide that and show the new one, or you can just update the style of all tabs every time a new tab is selected.

You might want to call this function immediately, to make the interface start with the first tab visible.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment