PageSourceSearch

https://secure.mygov.in/modules/custom/mygov_os_json/js/more-item.js?v=1.x

js mygov.in collected 2026-10-01 08:46:31 UTC 7,337 bytes, 263 lines download raw bytes

1(function (Drupal, once) {
2
3  Drupal.behaviors.moreTabsDropdown = {
4    attach(context) {
5
6      /* ===============================
7         Inject CSS (only once)
8      =============================== */
9      if (!document.getElementById('mygov-more-tabs-style')) {
10        const style = document.createElement('style');
11        style.id = 'mygov-more-tabs-style';
12        style.innerHTML = `
13          .search-tabs .more-tab { position: relative; }
14
15          .search-tabs .more-toggle {
16            background: none;
17            border: none;
18            cursor: pointer;
19          }
20
21          .search-tabs .more-toggle::after {
22            content: " ▼";
23            font-size: 12px;
24          }
25
26          .search-tabs .more-dropdown {
27            position: absolute;
28            top: 100%;
29            left: 0;
30            display: none;
31            min-width: 220px;
32            background: #fff;
33            border: 1px solid #e0e0e0;
34            list-style: none;
35            margin: 0;
36            padding: 6px 0;
37            z-index: 1000;
38            border-radius: 6px;
39            box-shadow: 0 8px 20px rgba(0,0,0,0.08);
40          }
41
42          .search-tabs .more-tab.is-open .more-dropdown {
43            display: block;
44          }
45
46          .search-tabs .more-dropdown li a {
47            display: block;
48            padding: 8px 16px;
49            text-decoration: none;
50          }
51
52          .search-tabs .more-dropdown li a:hover {
53            background: #f5f5f5;
54          }
55        `;
56        document.head.appendChild(style);
57      }
58
59      /* ===============================
60         Main Logic
61      =============================== */
62
63      once('more-tabs-dropdown', '.search-tabs .tabs-list', context)
64        .forEach(function (tabsList) {
65
66          const allItems = Array.from(tabsList.querySelectorAll(':scope > li'));
67          if (allItems.length <= 6) return;
68
69          let searchByItem = null;
70          const categoryItems = [];
71
72          allItems.forEach((item) => {
73            if (item.querySelector('.date-filter')) {
74              searchByItem = item;
75            } else {
76              categoryItems.push(item);
77            }
78          });
79
80          if (categoryItems.length <= 6) return;
81
82          const activeItem = tabsList.querySelector('li.active');
83
84          // First 6 visible
85          const visibleItems = categoryItems.slice(0, 6);
86          const dropdownItems = categoryItems.slice(6);
87
88          /* ===============================
89             Create More dropdown
90          =============================== */
91
92          const moreLi = document.createElement('li');
93          moreLi.classList.add('more-tab');
94
95          const moreBtn = document.createElement('button');
96          moreBtn.type = 'button';
97          moreBtn.classList.add('more-toggle');
98          moreBtn.setAttribute('aria-expanded', 'false');
99          moreBtn.textContent = 'More';
100
101          const dropdown = document.createElement('ul');
102          dropdown.classList.add('more-dropdown');
103
104          dropdownItems.forEach(item => dropdown.appendChild(item));
105
106          moreLi.appendChild(moreBtn);
107          moreLi.appendChild(dropdown);
108
109          if (searchByItem) {
110            tabsList.insertBefore(moreLi, searchByItem);
111          } else {
112            tabsList.appendChild(moreLi);
113          }
114
115          /* ===============================
116             SWAP LOGIC (Prime ⇄ Media)
117          =============================== */
118
119          if (activeItem && dropdown.contains(activeItem)) {
120
121            const currentVisible = Array.from(
122              tabsList.querySelectorAll(':scope > li')
123            ).filter(li =>
124              !li.classList.contains('more-tab') &&
125              !li.querySelector('.date-filter')
126            );
127
128            const lastVisible = currentVisible[currentVisible.length - 1];
129
130            // Move active outside before More
131            tabsList.insertBefore(activeItem, moreLi);
132
133            // Move last visible into dropdown
134            dropdown.insertBefore(lastVisible, dropdown.firstChild);
135          }
136
137          /* ===============================
138             Toggle
139          =============================== */
140
141          moreBtn.addEventListener('click', function (e) {
142            e.preventDefault();
143            e.stopPropagation();
144
145            const isOpen = moreLi.classList.toggle('is-open');
146            moreBtn.setAttribute('aria-expanded', isOpen);
147          });
148
149          document.addEventListener('click', function () {
150            moreLi.classList.remove('is-open');
151            moreBtn.setAttribute('aria-expanded', 'false');
152          });
153
154        });
155    }
156  };
157
158})(Drupal, once);
159
160
161// (function (Drupal, once) {
162
163//   Drupal.behaviors.mygovSearchHighlight = {
164//     attach: function (context) {
165
166//       // Get search term (second placeholder inside results count)
167//       const placeholders = context.querySelectorAll('.results-count em.placeholder');
168
169//       if (placeholders.length < 2) {
170//         return;
171//       }
172
173//       const term = placeholders[1].textContent.trim();
174
175//       if (!term) {
176//         return;
177//       }
178
179//       // Whole word match (prevents culture match for future)
180//       const regex = new RegExp("\\b(" + term.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') + ")\\b", "gi");
181
182//       once('mygovSearchHighlight', context.querySelectorAll('.search-result-item')).forEac
182h(function (item) {
183
184//         const targets = item.querySelectorAll('.title, .body');
185
186//         targets.forEach(function (element) {
187//           element.innerHTML = element.innerHTML.replace(
188//             regex,
189//             "<span class='search-highlight'>$1</span>"
190//           );
191//         });
192
193//       });
194
195//     }
196//   };
197
198// })(Drupal, once);
199
200(function (Drupal, once) {
201
202  Drupal.behaviors.mygovSearchHighlight = {
203    attach: function (context) {
204
205      const placeholders = context.querySelectorAll('.results-count em.placeholder');
206
207      if (placeholders.length < 2) {
208        return;
209      }
210
211      const term = placeholders[1].textContent.trim();
212      if (!term) {
213        return;
214      }
215
216      const escaped = term.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
217      const regex = new RegExp("\\b(" + escaped + ")\\b", "gi");
218
219      once('mygovSearchHighlight', context.querySelectorAll('.search-result-item'))
220        .forEach(function (item) {
221
222          item.querySelectorAll('.title, .body').forEach(function (element) {
223            highlightText(element);
224          });
225
226        });
227
228      function highlightText(node) {
229
230        node.childNodes.forEach(function (child) {
231
232          // If text node → replace safely
233          if (child.nodeType === Node.TEXT_NODE) {
234
235            if (regex.test(child.textContent)) {
236
237              const span = document.createElement('span');
238              span.innerHTML = child.textContent.replace(
239                regex,
240                "<span class='search-highlight'>$1</span>"
241              );
242
243              child.replaceWith(span);
244            }
245
246          }
247
248          // If element node → recurse (INCLUDING <a>)
249          else if (
250            child.nodeType === Node.ELEMENT_NODE &&
251            !['SCRIPT', 'STYLE'].includes(child.tagName)
252          ) {
253            highlightText(child);
254          }
255
256        });
257
258      }
259
260    }
261  };
262
263})(Drupal, once);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.