Special Tags
Special THINK Reference Tags
The THINK Refence viewer has four buttons on the top of each page than can link to
other pages in the database. These buttons are configured by special tags placed in the
HTML before it's compiled. These tags are formatted as:
"the button name" is the label on the button in the viewer. "The page title" is the name
of the target page (as contained within the tags) of the html page that the</span></div><div class="chunk"><span class="style0">button is to go to. "The menu char" sets the keyboard equivalent for the button and</span></div><div class="chunk"><span class="style0">lists it under the "Reference" menu in the THINK Reference Viewer.</span></div><div class="chunk"><span class="style0">You can also specify links to other pages with the database by using the following tag:</span></div><div class="chunk"><span class="style5"><!-- @TR LINK -->Name of other page<!-- @TR /LINK --></span></div><div class="chunk"><span class="style0">The text for the link must exactly match the title for the html page that the user wants</span></div><div class="chunk"><span class="style0">to go to. This text will be underlined in the viewer.</span></div><div class="chunk"><span class="style5"><!-- @TR CODE -->"My Code" --></span></div><div class="chunk"><span class="style0">The text for the link must exactly match the title for the html page that the user wants</span></div><div class="chunk"><span class="style0">to go to. This text will be underlined in the viewer.</span></div><div class="chunk"><span class="style0">Lastly, you can use the <!-- --> tags to enclose any comments.</span></div><div class="backlinks"><div class="backlinks-title">Referenced by (2):</div><ul class="backlinks-list"><li><a href="0.html">Compiler Documentation</a></li><li><a href="../THINK Ref Compiler/0.html">Compiler Documentation (THINK Ref Compiler)</a></li></ul></div></div><script> let crossrefData = null; const searchInput = document.getElementById('search-input'); const searchResults = document.getElementById('search-results'); let selectedIndex = -1; let currentResults = []; // Load crossref data on first search async function loadCrossrefData() { if (crossrefData !== null) return; try { const response = await fetch('../crossref.json'); crossrefData = await response.json(); } catch (e) { crossrefData = []; console.error('Failed to load crossref.json:', e); } } function escapeHtml(text) { const div = document.createElement('div'); div.textContent = text; return div.innerHTML; } function highlightMatch(text, query) { if (!query) return escapeHtml(text); const escaped = escapeHtml(text); const regex = new RegExp('(' + query.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') + ')', 'gi'); return escaped.replace(regex, '<span class="highlight">$1</span>'); } async function search(query) { if (!query || query.length < 2) { searchResults.classList.remove('visible'); currentResults = []; return; } await loadCrossrefData(); const lowerQuery = query.toLowerCase(); currentResults = crossrefData.filter(item => item.name.toLowerCase().includes(lowerQuery) ).slice(0, 50); currentResults.sort((a, b) => { const aLower = a.name.toLowerCase(); const bLower = b.name.toLowerCase(); const aExact = aLower === lowerQuery; const bExact = bLower === lowerQuery; const aStarts = aLower.startsWith(lowerQuery); const bStarts = bLower.startsWith(lowerQuery); if (aExact && !bExact) return -1; if (bExact && !aExact) return 1; if (aStarts && !bStarts) return -1; if (bStarts && !aStarts) return 1; return a.name.localeCompare(b.name); }); if (currentResults.length === 0) { searchResults.innerHTML = '<div class="search-result"><span class="name">No results found</span></div>'; } else { searchResults.innerHTML = currentResults.map((item, idx) => ` <div class="search-result${idx === selectedIndex ? ' selected' : ''}" data-index="${idx}"> <div class="name">${highlightMatch(item.name, query)}</div> <div class="location">${escapeHtml(item.db)}</div> </div> `).join(''); } searchResults.classList.add('visible'); selectedIndex = -1; } function navigateToResult(index) { if (index >= 0 && index < currentResults.length) { const item = currentResults[index]; window.location.href = '../' + encodeURIComponent(item.db) + '/' + item.page + '.html'; } } function updateSelection() { const items = searchResults.querySelectorAll('.search-result'); items.forEach((item, idx) => { item.classList.toggle('selected', idx === selectedIndex); }); if (selectedIndex >= 0 && items[selectedIndex]) { items[selectedIndex].scrollIntoView({ block: 'nearest' }); } } searchInput.addEventListener('input', (e) => { search(e.target.value); }); searchInput.addEventListener('keydown', (e) => { if (e.key === 'ArrowDown') { e.preventDefault(); if (selectedIndex < currentResults.length - 1) { selectedIndex++; updateSelection(); } } else if (e.key === 'ArrowUp') { e.preventDefault(); if (selectedIndex > 0) { selectedIndex--; updateSelection(); } } else if (e.key === 'Enter') { e.preventDefault(); if (selectedIndex >= 0) { navigateToResult(selectedIndex); } else if (currentResults.length > 0) { navigateToResult(0); } } else if (e.key === 'Escape') { searchResults.classList.remove('visible'); selectedIndex = -1; } }); searchResults.addEventListener('click', (e) => { const result = e.target.closest('.search-result'); if (result && result.dataset.index !== undefined) { navigateToResult(parseInt(result.dataset.index)); } }); document.addEventListener('click', (e) => { if (!e.target.closest('.search-box')) { searchResults.classList.remove('visible'); } }); searchInput.addEventListener('focus', () => { if (searchInput.value.length >= 2) { search(searchInput.value); } }); </script></body></html>