11document . addEventListener ( 'DOMContentLoaded' , function ( ) {
22 // only load on open issues page for now
3- var issueSelect = document . querySelector ( ".open-issues select " ) ;
3+ var issueSelect = document . querySelector ( ".open-issues #label-filter " ) ;
44 if ( ! issueSelect ) {
55 return ;
66 }
77
8- issueSelect . onchange = issueSelectHandler ;
8+ issueSelect . onchange = function ( event ) {
9+ issueSelectHandler ( event ) ;
10+ applySorting ( ) ;
11+ } ;
12+
13+ var sortSelect = document . querySelector ( ".open-issues #sort-order" ) ;
14+ if ( sortSelect ) {
15+ sortSelect . onchange = function ( ) {
16+ applySorting ( ) ;
17+ } ;
18+ }
919
1020 // load issues label when using back button
1121 window . addEventListener ( 'popstate' , loadIssues . bind ( null , true ) ) ;
@@ -17,27 +27,35 @@ document.addEventListener('DOMContentLoaded', function() {
1727function loadIssues ( isPopState ) {
1828 var params = new URLSearchParams ( window . location . search ) ;
1929 var label = params . get ( 'label' ) ;
30+ var sort = params . get ( 'sort' ) ;
2031
21- if ( ! label ) {
22- return ;
32+ if ( sort ) {
33+ var sortSelect = document . querySelector ( '.open-issues #sort-order' ) ;
34+ if ( sortSelect ) {
35+ sortSelect . value = sort ;
36+ }
37+ }
38+
39+ if ( label ) {
40+ issueSelectHandler ( label , isPopState ) ;
41+ var issuesList = document . querySelector ( '.open-issues #label-filter' ) ;
42+ issuesList . value = label ;
2343 }
2444
25- issueSelectHandler ( label , isPopState ) ;
26- var issuesList = document . querySelector ( '.open-issues select' ) ;
27- issuesList . value = label ;
45+ applySorting ( ) ;
2846}
2947
3048function issueSelectHandler ( event , isPopState ) {
3149 if ( event . target ) {
32- var selectedOption = this . options [ this . selectedIndex ] . value ;
50+ var selectedOption = event . target . options [ event . target . selectedIndex ] . value ;
3351 } else {
3452 // page loads will set the event as just the selected label from params
3553 var selectedOption = event ;
3654 }
3755
3856 // don't set params on the back button
3957 if ( ! isPopState ) {
40- setIssueParams ( selectedOption ) ;
58+ setParams ( ) ;
4159 }
4260
4361 // hide all elements first
@@ -47,17 +65,158 @@ function issueSelectHandler(event, isPopState) {
4765 } ) ;
4866
4967 // show the selected options
50- var selectedOption = selectedOption === 'all' ? 'li' : `. ${ selectedOption } ` ;
51- var items = document . querySelectorAll ( ` .issues-list ${ selectedOption } ` ) ;
68+ var selector = selectedOption === 'all' ? 'li' : '.' + selectedOption ;
69+ var items = document . querySelectorAll ( ' .issues-list ' + selector ) ;
5270 items . forEach ( function ( item ) {
53- item . style . display = 'block'
71+ item . style . display = 'block' ;
5472 item . parentElement . closest ( 'li' ) . style . display = 'block' ;
5573 } ) ;
5674}
5775
58- function setIssueParams ( label ) {
76+ function getIssueDays ( element ) {
77+ // Parse "(Open X days)" from the issue title text
78+ var text = element . textContent || '' ;
79+ var match = text . match ( / \( O p e n \s + ( \d + ) \s + d a y s ? \) / i) ;
80+ if ( match ) {
81+ return parseInt ( match [ 1 ] , 10 ) ;
82+ }
83+ return 0 ;
84+ }
85+
86+ function applySorting ( ) {
87+ var sortSelect = document . querySelector ( '.open-issues #sort-order' ) ;
88+ if ( ! sortSelect ) return ;
89+
90+ var sortOrder = sortSelect . value ;
91+ if ( sortOrder === 'default' ) {
92+ // Restore original order by reloading — but simpler to just not sort
93+ // We store original order on first run
94+ restoreOriginalOrder ( ) ;
95+ setParams ( ) ;
96+ return ;
97+ }
98+
99+ // Sort issues within each library's issues-list
100+ var issuesLists = document . querySelectorAll ( '.issues-list' ) ;
101+ issuesLists . forEach ( function ( list ) {
102+ var items = Array . from ( list . querySelectorAll ( ':scope > li' ) ) ;
103+
104+ // Store original order if not already stored
105+ if ( ! list . dataset . originalOrder ) {
106+ list . dataset . originalOrder = 'stored' ;
107+ items . forEach ( function ( item , index ) {
108+ item . dataset . originalIndex = index ;
109+ } ) ;
110+ }
111+
112+ items . sort ( function ( a , b ) {
113+ var daysA = getIssueDays ( a ) ;
114+ var daysB = getIssueDays ( b ) ;
115+ if ( sortOrder === 'newest' ) {
116+ return daysA - daysB ; // fewer days = newer = first
117+ } else {
118+ return daysB - daysA ; // more days = older = first
119+ }
120+ } ) ;
121+
122+ // Re-append in sorted order
123+ items . forEach ( function ( item ) {
124+ list . appendChild ( item ) ;
125+ } ) ;
126+ } ) ;
127+
128+ // Also sort the library-level list items by their oldest/newest issue
129+ var topList = document . querySelector ( '.open-issues > ul' ) ;
130+ if ( topList ) {
131+ var libraryItems = Array . from ( topList . querySelectorAll ( ':scope > li' ) ) ;
132+
133+ if ( ! topList . dataset . originalOrder ) {
134+ topList . dataset . originalOrder = 'stored' ;
135+ libraryItems . forEach ( function ( item , index ) {
136+ item . dataset . originalIndex = index ;
137+ } ) ;
138+ }
139+
140+ libraryItems . sort ( function ( a , b ) {
141+ var issuesA = a . querySelectorAll ( '.issues-list > li' ) ;
142+ var issuesB = b . querySelectorAll ( '.issues-list > li' ) ;
143+ var maxA = getMaxDays ( issuesA , sortOrder ) ;
144+ var maxB = getMaxDays ( issuesB , sortOrder ) ;
145+ if ( sortOrder === 'newest' ) {
146+ return maxA - maxB ;
147+ } else {
148+ return maxB - maxA ;
149+ }
150+ } ) ;
151+
152+ libraryItems . forEach ( function ( item ) {
153+ topList . appendChild ( item ) ;
154+ } ) ;
155+ }
156+
157+ setParams ( ) ;
158+ }
159+
160+ function getMaxDays ( issues , sortOrder ) {
161+ var result = sortOrder === 'newest' ? Infinity : 0 ;
162+ issues . forEach ( function ( issue ) {
163+ var days = getIssueDays ( issue ) ;
164+ if ( sortOrder === 'newest' ) {
165+ result = Math . min ( result , days ) ;
166+ } else {
167+ result = Math . max ( result , days ) ;
168+ }
169+ } ) ;
170+ return result === Infinity ? 0 : result ;
171+ }
172+
173+ function restoreOriginalOrder ( ) {
174+ // Restore library-level order
175+ var topList = document . querySelector ( '.open-issues > ul' ) ;
176+ if ( topList && topList . dataset . originalOrder ) {
177+ var libraryItems = Array . from ( topList . querySelectorAll ( ':scope > li' ) ) ;
178+ libraryItems . sort ( function ( a , b ) {
179+ return ( parseInt ( a . dataset . originalIndex ) || 0 ) - ( parseInt ( b . dataset . originalIndex ) || 0 ) ;
180+ } ) ;
181+ libraryItems . forEach ( function ( item ) {
182+ topList . appendChild ( item ) ;
183+ } ) ;
184+ }
185+
186+ // Restore issue-level order within each list
187+ var issuesLists = document . querySelectorAll ( '.issues-list' ) ;
188+ issuesLists . forEach ( function ( list ) {
189+ var items = Array . from ( list . querySelectorAll ( ':scope > li' ) ) ;
190+ items . sort ( function ( a , b ) {
191+ return ( parseInt ( a . dataset . originalIndex ) || 0 ) - ( parseInt ( b . dataset . originalIndex ) || 0 ) ;
192+ } ) ;
193+ items . forEach ( function ( item ) {
194+ list . appendChild ( item ) ;
195+ } ) ;
196+ } ) ;
197+ }
198+
199+ function setParams ( ) {
59200 var params = new URLSearchParams ( window . location . search ) ;
60- params . set ( "label" , label ) ;
61- var newUrl = `${ window . location . protocol } //${ window . location . host } ${ window . location . pathname } ?${ params . toString ( ) } ` ;
62- window . history . pushState ( { path :newUrl } , '' , newUrl ) ;
201+
202+ var labelSelect = document . querySelector ( '.open-issues #label-filter' ) ;
203+ if ( labelSelect && labelSelect . value && labelSelect . value !== 'all' ) {
204+ params . set ( "label" , labelSelect . value ) ;
205+ } else {
206+ params . delete ( "label" ) ;
207+ }
208+
209+ var sortSelect = document . querySelector ( '.open-issues #sort-order' ) ;
210+ if ( sortSelect && sortSelect . value && sortSelect . value !== 'default' ) {
211+ params . set ( "sort" , sortSelect . value ) ;
212+ } else {
213+ params . delete ( "sort" ) ;
214+ }
215+
216+ var query = params . toString ( ) ;
217+ var newUrl = window . location . protocol + '//' + window . location . host + window . location . pathname ;
218+ if ( query ) {
219+ newUrl += '?' + query ;
220+ }
221+ window . history . pushState ( { path : newUrl } , '' , newUrl ) ;
63222}
0 commit comments