Skip to content
You said:
authors.php
File
authors_run.php
File
I have attached the front-end and back-end code for my "Authors" page. The Authors list is growing too long. How can I add an option to type the first letter(s) of an author's last name to jump to it?
ChatGPT said:
Thought for 1m 5s
Do it client-side: add a small “jump” search box above the list, tag each author link with a data-last attribute, and use JavaScript to scroll to the first match as you type.
1) Update authors_run.php to add id + data-last
Replace your “display results” loop with this:
while ($row = mysqli_fetch_assoc($result_list)) {
$author_id = (int)$row['author_id'];
$author_name = trim($row['author_name']);
// Try to infer last name:
// - If name is stored as "Last, First", last is before comma
// - Otherwise use the last word as last name
if (strpos($author_name, ',') !== false) {
$last = trim(strtok($author_name, ','));
} else {
$parts = preg_split('/\s+/', $author_name);
$last = trim(end($parts));
}
$safe_name = htmlspecialchars($author_name, ENT_QUOTES, 'UTF-8');
$safe_last = htmlspecialchars($last, ENT_QUOTES, 'UTF-8');
echo "<a
id='author-$author_id'
class='author-link'
data-last='$safe_last'
href='author.php?author_id=$author_id'
>$safe_name</a><br>";
}
2) Update authors.php to add the input + wrapper div + JS
Where you currently include '../run_code/authors_run.php';, wrap it in a container and add a text box above it:
<label for="authorJump"><strong>Jump to author (type last name):</strong></label><br>
<input
type="text"
id="authorJump"
placeholder="e.g., Smi"
autocomplete="off"
style="max-width:320px; width:100%; padding:8px; margin:6px 0 14px;"
>
<div id="authorList">
<?php include '../run_code/authors_run.php'; ?>
</div>
<script>
(() => {
const input = document.getElementById('authorJump');
const list = document.getElementById('authorList');
function norm(s) {
return (s || '').toString().trim().toLowerCase();
}
function clearHighlights() {
list.querySelectorAll('.author-hit').forEach(a => a.classList.remove('author-hit'));
}
function jump() {
const q = norm(input.value);
clearHighlights();
if (!q) return;
const links = list.querySelectorAll('a.author-link');
let hit = null;
for (const a of links) {
const last = norm(a.dataset.last);
const full = norm(a.textContent);
// Prefer matching last name; fall back to full display text
if (last.startsWith(q) || full.startsWith(q)) { hit = a; break; }
}
if (hit) {
hit.classList.add('author-hit');
hit.scrollIntoView({ behavior: 'smooth', block: 'center' });
}
}
input.addEventListener('input', jump);
// Optional: Enter opens the highlighted author
input.addEventListener('keydown', (e) => {
if (e.key === 'Enter') {
const hit = list.querySelector('a.author-link.author-hit');
if (hit) window.location.href = hit.href;
}
});
})();
</script>
<style>
/* cheap but effective */
.author-hit { background: #fff3a0; padding: 2px 4px; border-radius: 4px; }
</style>
Why this works (and won’t hurt performance)
No extra database queries.
The page loads once, then the user can “type-to-jump” instantly.
scrollIntoView() gives the “jump” behavior you asked for (not a filter), and the highlight makes it obvious where you landed.
If your author_name format is not “Last, First” or “First Last” (for example “Grant, James (ed.)”), tell me the format and I’ll tweak the last-name extraction so it’s bulletproof.
You said:
authors_run.php
File
authors.php
File
I believe I did what you said. The Authors list no longer appears, and nothing happens when I enter something in the jump input box.
ChatGPT said:
Thought for 1m 42s
Right now, your uploaded files do not include the “jump input + JS” at all, and your authors_run.php is still outputting plain links with no class="author-link" and no data-last. So even if you type in a box, the script has nothing to hook into.
That explains both symptoms:
Nothing happens when you type → because the JS isn’t on the page (or it can’t find #authorList / .author-link).
Authors list not appearing → usually a PHP fatal error (often from a bad include path). Your authors_run.php does include 'database.php'; which is fragile when the file is included from another directory.
Here’s the “it will work” version.
Fix 1: Make the database include unbreakable (authors_run.php)
Use __DIR__ so PHP includes from the file’s own folder, not whatever the current script happens to be:
<?php
// Connect to database (adjust path if your database.php is elsewhere)
require_once __DIR__ . '/database.php';
$sql_list = "SELECT * FROM authors ORDER BY author_name;";
$result_list = mysqli_query($connection, $sql_list);
$sql_count = "SELECT COUNT(*) AS count FROM authors;";
$result_count = mysqli_query($connection, $sql_count);
if (!$result_list || !$result_count) {
echo "<p><strong>DB query failed:</strong> " . htmlspecialchars(mysqli_error($connection)) . "</p>";
return;
}
$row = mysqli_fetch_assoc($result_count);
echo "<h3>" . (int)$row['count'] . " Authors</h3><br>";
while ($row = mysqli_fetch_assoc($result_list)) {
$author_id = (int)$row['author_id'];
$author_name = trim($row['author_name']);
// Infer last name: "Last, First" OR "First Last"
if (strpos($author_name, ',') !== false) {
$last = trim(strtok($author_name, ','));
} else {
$parts = preg_split('/\s+/', $author_name);
$last = trim(end($parts));
}
$safe_name = htmlspecialchars($author_name, ENT_QUOTES, 'UTF-8');
$safe_last = htmlspecialchars($last, ENT_QUOTES, 'UTF-8');
echo "<a
id='author-$author_id'
class='author-link'
data-last='$safe_last'
href='author.php?author_id=$author_id'
>$safe_name</a><br>";
}
⚠️ If your database.php is not in the same folder as authors_run.php, change that line to something like:
require_once __DIR__ . '/../database.php'; (one level up)
Fix 2: Actually add the jump input + JS (authors.php)
Put this right before you include authors_run.php:
<label for="authorJump"><strong>Jump to author (type last name):</strong></label><br>
<input
type="text"
id="authorJump"
placeholder="e.g., Smi"
autocomplete="off"
style="max-width:320px; width:100%; padding:8px; margin:6px 0 14px;"
>
<div id="authorList">
<?php include '../run_code/authors_run.php'; ?>
</div>
<script>
(() => {
const input = document.getElementById('authorJump');
const list = document.getElementById('authorList');
if (!input || !list) return;
const norm = s => (s || '').toString().trim().toLowerCase();
function clearHighlights() {
list.querySelectorAll('.author-hit').forEach(a => a.classList.remove('author-hit'));
}
function jump() {
const q = norm(input.value);
clearHighlights();
if (!q) return;
const links = list.querySelectorAll('a.author-link');
let hit = null;
for (const a of links) {
const last = norm(a.dataset.last);
if (last.startsWith(q)) { hit = a; break; }
}
if (hit) {
hit.classList.add('author-hit');
hit.scrollIntoView({ behavior: 'smooth', block: 'center' });
}
}
input.addEventListener('input', jump);
})();
</script>
<style>
.author-hit { background: #fff3a0; padding: 2px 4px; border-radius: 4px; }
</style>
Fast way to confirm what’s wrong (no guessing)
Open the Authors page and view page source.
Search for authorJump. If it’s not there, you didn’t actually paste the input+script into the page that’s running.
If the author list is blank: turn on PHP errors temporarily at the very top of authors.php:
<?php
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
?>
If your include path is broken, you’ll immediately see the error.
If you paste your actual live file contents (or upload the edited versions again), I can point to the exact line that’s breaking. But the two fixes above cover the most common “list disappeared + JS does nothing” failure modes: fatal include error and missing hooks/classes/IDs.
You said:
I uploaded my updated files to you. Authors.php does include the “jump input + JS” that you gave me.
ChatGPT said:
Thought for 40s
I pulled the two files you uploaded in this chat and… they’re not the versions you think they are.
What I’m actually seeing in your uploads
authors.php: does not contain authorJump, the <script>, or the #authorList wrapper. Also it literally contains a line with ... in the middle of the HTML, which suggests you pasted a truncated snippet into the file at some point.
authors_run.php: is unchanged from your old version: no class="author-link", no data-last, and it still does include 'database.php'; (which commonly breaks when the file is included from another directory).
So your symptoms make perfect sense:
The JS can’t run because it’s not actually in the loaded page (or it has nothing to target).
The author list can disappear if authors_run.php dies on include 'database.php'.
Let’s fix it in a way that can’t silently fail.
1) Replace authors_run.php with this (copy/paste the whole thing)
This fixes the fragile DB include and outputs the data-last + class hooks your JS needs.
<?php
// Always include db relative to THIS file's folder:
require_once __DIR__ . '/database.php';
$sql_list = "SELECT * FROM authors ORDER BY author_name;";
$sql_count = "SELECT COUNT(*) AS count FROM authors;";
$result_list = mysqli_query($connection, $sql_list);
$result_count = mysqli_query($connection, $sql_count);
if (!$result_list || !$result_count) {
echo "<p><strong>DB query failed:</strong> " . htmlspecialchars(mysqli_error($connection)) . "</p>";
return;
}
$row = mysqli_fetch_assoc($result_count);
echo "<h3>" . (int)$row['count'] . " Authors</h3><br>";
while ($row = mysqli_fetch_assoc($result_list)) {
$author_id = (int)$row['author_id'];
$author_name = trim($row['author_name']);
// Infer last name: "Last, First" OR "First Last"
if (strpos($author_name, ',') !== false) {
$last = trim(strtok($author_name, ','));
} else {
$parts = preg_split('/\s+/', $author_name);
$last = trim(end($parts));
}
$safe_name = htmlspecialchars($author_name, ENT_QUOTES, 'UTF-8');
$safe_last = htmlspecialchars($last, ENT_QUOTES, 'UTF-8');
echo "<a
id='author-$author_id'
class='author-link'
data-last='$safe_last'
href='author.php?author_id=$author_id'
>$safe_name</a><br>";
}
If your database.php is not in the same folder as authors_run.php, change that one line to something like:
require_once __DIR__ . '/../database.php';
2) In authors.php, insert the jump UI + wrapper immediately before the include
Find this:
<?php
include '../run_code/authors_run.php';
?>
Replace it with this:
<label for="authorJump"><strong>Jump to author (type last name):</strong></label><br>
<input
type="text"
id="authorJump"
placeholder="e.g., Smi"
autocomplete="off"
style="max-width:320px; width:100%; padding:8px; margin:6px 0 14px;"
>
<div id="authorList">
<?php include '../run_code/authors_run.php'; ?>
</div>
<script>
(() => {
const input = document.getElementById('authorJump');
const list = document.getElementById('authorList');
// If either is missing, nothing can work:
if (!input || !list) return;
const norm = s => (s || '').toString().trim().toLowerCase();
function clearHighlights() {
list.querySelectorAll('.author-hit').forEach(a => a.classList.remove('author-hit'));
}
function jump() {
const q = norm(input.value);
clearHighlights();
if (!q) return;
const links = list.querySelectorAll('a.author-link');
for (const a of links) {
const last = norm(a.dataset.last);
if (last.startsWith(q)) {
a.classList.add('author-hit');
a.scrollIntoView({ behavior: 'smooth', block: 'center' });
break;
}
}
}
input.addEventListener('input', jump);
})();
</script>
<style>
.author-hit { background: #fff3a0; padding: 2px 4px; border-radius: 4px; }
</style>
3) Remove the literal ... from your authors.php
Your uploaded authors.php contains a ... line inside the HTML. That’s not a comment; it’s real text and it’s a red flag that the file you edited isn’t the one you’re running, or you pasted a truncated example into production.
Delete it.
4) Quick sanity checks (takes 30 seconds)
Load the Authors page → Right-click → View Page Source → search for authorJump
If it’s not there, you’re editing one file but serving another.
Open DevTools Console:
If you see errors like “Cannot find database.php” or a PHP error output, your include path was the problem (fixed by __DIR__).
If you want, tell me where database.php physically lives relative to authors_run.php (same folder? one level up?), and I’ll give you the exact correct require_once path so you don’t have to guess.
Is this conversation helpful so far?
No file chosenNo file chosen
ChatGPT can make mistakes. Check important info.