Skip to content

Commit 48766e4

Browse files
committed
Adding prev/next exploration of htmx mechanics.
1 parent ab29779 commit 48766e4

File tree

3 files changed

+161
-0
lines changed

3 files changed

+161
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ with.
1010

1111
## My JavaScript Demos - I Love JavaScript!
1212

13+
* [Exploring Prev/Next Mechanics In HTMX](https://bennadel.github.io/JavaScript-Demos/demos/htmx-prev-next)
1314
* [Pixel Art With Alpine.js](https://bennadel.github.io/JavaScript-Demos/demos/pixel-art-alpine)
1415
* [Movie Ranking With Sortable.js And Kendall Tau Distance](https://bennadel.github.io/JavaScript-Demos/demos/movie-rank)
1516
* [Using :scope To Identify The Host Element In A CSS Selector](https://bennadel.github.io/JavaScript-Demos/demos/scope-pseudo-class)

demos/htmx-prev-next/index.htm

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8" />
5+
<link rel="stylesheet" type="text/css" href="./main.css" />
6+
</head>
7+
<body>
8+
9+
<h1>
10+
Exploring Prev/Next Mechanics In HTMX
11+
</h1>
12+
13+
<table border="1" cellpadding="10" cellspacing="5">
14+
<template data-repeat="5">
15+
<tr>
16+
<td class="prevTarget">
17+
Prev
18+
</td>
19+
<td>
20+
<button
21+
onclick="selectNext( this, '.nextTarget' )"
22+
class="selectNext">
23+
Select Next
24+
</button>
25+
</td>
26+
<td>
27+
<button
28+
onclick="selectPrev( this, '.prevTarget' )"
29+
class="selectPrev">
30+
Select Prev
31+
</button>
32+
</td>
33+
<td class="nextTarget">
34+
Next
35+
</td>
36+
</tr>
37+
</template>
38+
</table>
39+
40+
<script type="text/javascript">
41+
42+
cloneRows();
43+
44+
/**
45+
* I add the "selected" class to the "closest next" element that matches the given
46+
* selector.
47+
*/
48+
function selectNext( fromNode, cssSelector ) {
49+
50+
resetSelection();
51+
// Find matching nodes using depth-first traversal of the DOM.
52+
// --
53+
// Note: I don't need Array.from() in this case, but I'm keeping it in order
54+
// to maintain some mechanical symmetry with the selectPrev() method.
55+
var matchingNodes = Array.from( document.querySelectorAll( cssSelector ) );
56+
57+
// The querySelectorAll() method returns the matching nodes in a depth-first
58+
// order. Therefore, as we iterate FORWARDS over the collection, the first
59+
// node that identifies as coming AFTER the fromNode is the "next" matching
60+
// node in DOM-order.
61+
for ( var node of matchingNodes ) {
62+
63+
if ( fromNode.compareDocumentPosition( node ) === Node.DOCUMENT_POSITION_FOLLOWING ) {
64+
65+
node.classList.add( "selected" );
66+
break;
67+
68+
}
69+
70+
}
71+
72+
}
73+
74+
/**
75+
* I add the "selected" class to the "closest previous" element that matches the
76+
* given selector.
77+
*/
78+
function selectPrev( fromNode, cssSelector ) {
79+
80+
resetSelection();
81+
// Find matching nodes using depth-first traversal of the DOM. Then, reverse
82+
// them so that our subsequent for-of loop is iterating over the nodes from
83+
// the end of the document's node list.
84+
var matchingNodes = Array.from( document.querySelectorAll( cssSelector ) )
85+
.reverse()
86+
;
87+
88+
// The querySelectorAll() method returns the matching nodes in an depth-first
89+
// order. Therefore, as we iterate BACKWARDS over the collection (thanks to
90+
// the .reverse() call), the first node that identifies as coming BEFORE the
91+
// fromNode is the "previous" matching node in DOM-order.
92+
for ( var node of matchingNodes ) {
93+
94+
if ( fromNode.compareDocumentPosition( node ) === Node.DOCUMENT_POSITION_PRECEDING ) {
95+
96+
node.classList.add( "selected" );
97+
break;
98+
99+
}
100+
101+
}
102+
103+
}
104+
105+
/**
106+
* I remove the "selected" class from the currently-selected node.
107+
*/
108+
function resetSelection() {
109+
110+
document.querySelector( ".selected" )
111+
?.classList
112+
.remove( "selected" )
113+
;
114+
115+
}
116+
117+
/**
118+
* I flesh-out the table rows using the template.
119+
*/
120+
function cloneRows() {
121+
122+
var table = document.querySelector( "table" );
123+
var template = document.querySelector( "template" );
124+
var repeat = +( template.dataset.repeat ?? 5 );
125+
126+
for ( var i = 1 ; i <= repeat ; i++ ) {
127+
128+
var clone = template.content.cloneNode( true );
129+
130+
clone.firstElementChild.dataset.id = i;
131+
table.append( clone );
132+
133+
}
134+
135+
}
136+
137+
</script>
138+
139+
</body>
140+
</html>

demos/htmx-prev-next/main.css

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
2+
body {
3+
font-family: verdana, arial, sans-serif ;
4+
font-size: 18px ;
5+
}
6+
7+
button {
8+
border: 1px solid #999999 ;
9+
color: inherit ;
10+
cursor: pointer ;
11+
font-family: inherit ;
12+
font-size: 20px ;
13+
padding: 5px 10px ;
14+
}
15+
16+
.selected {
17+
font-weight: bold ;
18+
background: gold ;
19+
}
20+

0 commit comments

Comments
 (0)