These ten questions run the length of the chapter, and each turns on a behavior that is easy to get wrong: route patterns, the page lifecycle, routable tabs, Dom7 163 , form data, the searchbar, dates, the Store and Swiper 135,050 . Every snippet ran in the DevTools console of this chapter's finished BookNest (npm 2,036 run dev), on the home page with an iPhone user agent at 390 by 844 pixels, each in a freshly loaded page with an empty cart. Treat each numbered block as separate. Read it, write down what it prints and why, and only then check Appendix H, which gives the real output, the reason behind it and the section it comes from. If you run them yourself, a different time zone changes only question 8.
Questions
// 1. Which route does each URL match? (Sections 2.6.3, 2.6.5 and 2.8.1)
const router = app.views.main.router;
for (const url of ['/books/7/', '/books/007/', '/books/abc/', '/books/top/']) {
const m = router.findMatchingRoute(url);
console.log(url, '->', m ? m.route.path : 'no match');
}
// 2. Which of the home page's events fire on the way out and on the way back?
app.off('routeChange routeChanged');
const router = app.views.main.router;
const seen = [];
for (const name of ['pageInit', 'pageReinit', 'pageBeforeIn', 'pageAfterIn']) {
app.on(name, (page) => page.name === 'home' && seen.push(name));
}
router.navigate('/books/2/');
await new Promise((done) => setTimeout(done, 1500));
seen.push('--- back');
router.back();
await new Promise((done) => setTimeout(done, 1500));
console.log(seen.join(' '));
// 3. A book that does not exist: where is the router, and what does the toast say?
app.off('routeChange routeChanged');
const router = app.views.main.router;
router.navigate('/books/99/');
await new Promise((done) => setTimeout(done, 1500));
console.log(router.url, router.history.length, document.querySelector('.toast-text')?.textContent);// 4. Open a book, switch to its Notes tab, then go back once. Where are you?
app.off('routeChange routeChanged');
const router = app.views.main.router;
const pause = () => new Promise((done) => setTimeout(done, 1500));
router.navigate('/books/3/');
await pause();
router.navigate('/books/3/notes/');
await pause();
router.back();
await pause();
console.log(router.url, JSON.stringify(router.history));
// 5. A delegated Dom7 handler, nested matches and a getter on a collection.
const $ = app.$;
const box = $('<div class="card"><div class="card"><b>hi</b></div></div>').appendTo('body');
box.on('ping', '.card', function (e, n) {
console.log(`ping ${n} on`, this === box[0] ? 'outer' : 'inner');
});
box.find('b').trigger('ping', 1);
console.log(box.find('.card').length, $('.card', box[0]).text());
// 6. The filter panel's form with nothing touched: what does convertToData return?
const data = app.form.convertToData('#filter-form');
console.log(JSON.stringify(data));// 7. With the Catalog tab loaded, how many cards stay visible for each query?
const sb = app.searchbar.get('#view-catalog .searchbar');
const cards = '#view-catalog .book-card:not(.hidden-by-searchbar)';
const shown = () => document.querySelectorAll(cards).length;
for (const q of ['the', 'the harbor', 'harbor salt', 'Saffron,']) {
sb.search(q);
console.log(`"${q}" -> ${shown()}`);
}
// 8. In a browser set to Asia/Kuala_Lumpur (UTC+8), which date strings print?
const d = new Date(2026, 8, 26); // what the calendar returns for 26 September
console.log(Intl.DateTimeFormat().resolvedOptions().timeZone);
console.log(d.toISOString().slice(0, 10), d.toLocaleDateString('en-CA'));
// 9. What do the getter and the saved cart show after each step?
const store = app.store;
const count = store.getters.cartCount;
await store.dispatch('addToCart', 2);
await store.dispatch('addToCart', 2);
store.state.cart[0].qty = 5;
console.log(count.value, store.getters.cartTotal.value);
await store.dispatch('setQty', { id: 2, qty: 0 });
console.log(count.value, localStorage.getItem('booknest-cart'));
// 10. Which of the three listeners fire, and where does the Featured row end up?
const el = document.querySelector('swiper-container.featured');
const log = [];
for (const type of ['slidechange', 'swiperslidechange', 'swiper-slide-change']) {
el.addEventListener(type, () => log.push(type));
}
el.swiper.slideNext(0);
await new Promise((done) => setTimeout(done, 300));
console.log(log.join(', '), el.swiper.activeIndex, typeof el.swiper.slideTo);