1 let assert = require('assert')
2 let XDate = require('xdate')
4 return async (env, head, body, scripts) => {
5 //let cart = await _require('/online_store/cart.jst')
6 let globals = await env.site.get_json('/_config/globals.json')
7 //let icon_cart_small = await env.site.get_min_svg('/_svg/icon_cart_small.svg')
8 let icon_search_mono = await env.site.get_min_svg('/_svg/icon_search_mono.svg')
9 let logo_large = await env.site.get_min_svg('/_svg/logo_large.svg')
10 let menu = await env.site.get_menu('/_menu.json')
11 let page = await _require('/_lib/page.jst')
13 // initialize env.cart
20 // extract top-level directory name
21 assert(env.parsed_url.pathname.slice(0, 1) === '/')
22 let index = env.parsed_url.pathname.indexOf('/', 1)
23 let dir = index === -1 ? '' : env.parsed_url.pathname.slice(1, index)
27 globals.site_title + ': ' + (
30 menu.entries[menu.index[dir]].name
39 // extract top-level directory name
40 assert(env.parsed_url.pathname.slice(0, 1) === '/')
41 let index = env.parsed_url.pathname.indexOf('/', 1)
42 let dir = index === -1 ? '' : env.parsed_url.pathname.slice(1, index)
46 div.row.align-items-center.py-3 {
51 div.'mb-1'.text-right {
52 span#signed-in-status {
53 if (env.signed_in_as !== null)
54 `Signed in as ${env.signed_in_as}.`
59 if (env.signed_in_as !== null)
60 a#sign-in(href="" hidden="") {'Sign in'}
62 a#sign-in(href="") {'Sign in'}
64 if (env.signed_in_as !== null)
65 a#sign-out(href="") {'Sign out'}
67 a#sign-out(href="" hidden="") {'Sign out'}
70 form/*.form-inline*/(action="/search/index.html") {
72 input.form-control(name="query" type="text" placeholder="Search" aria-describedby="search-button") {}
73 div.input-group-append {
74 button.btn.btn-outline-secondary#search-button(type="submit") {
75 _out.push(icon_search_mono)
82 //div.'col-sm-1'.vbottom {
83 // // a nested div is used to avoid hover colour on the padding
84 // div.nav-li-a(style="text-align: center;") {
85 // a(href="/online_store/view_cart/index.html") {
87 // _out.push(icon_cart_small)
91 // `${(env.cart.items || []).length}`
100 nav.navbar.navbar-expand-lg.navbar-dark.bg-primary.scrollbar-fix {
102 //a.navbar-brand(href="#") {'Navbar'}
104 button.navbar-toggler(type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation") {
105 span.navbar-toggler-icon {}
107 div.collapse.navbar-collapse#navbarSupportedContent {
108 ul.navbar-nav.mr-auto {
109 if (dir.length === 0)
111 a.nav-link(href="/index.html") {
113 span.sr-only {' (current)'}
118 a.nav-link(href="/index.html") {'Home'}
120 let entries = menu.entries
121 for (let i = 0; i < entries.length; ++i)
122 if (entries[i].navbar)
123 if (entries[i].dir === dir)
125 a.nav-link(href=`/${entries[i].dir}/index.html`) {
127 span.sr-only {' (current)'}
132 a.nav-link(href=`/${entries[i].dir}/index.html`) {
136 //li.nav-item.dropdown {
137 // a.nav-link.dropdown-toggle#navbarDropdown(href="#" role="button" data-toggle="dropdown" aria-expanded="false") {
140 // div.dropdown-menu(aria-labelledby="navbarDropdown") {
141 // a.dropdown-item(href="#") {
145 // a.dropdown-item(href="#") {
148 // div.dropdown-divider {}
149 // a.dropdown-item(href="#") {
150 // 'Something else here'
155 // a.nav-link.disabled {
160 ul.navbar-nav.ml-auto {
162 a.nav-link#give-feedback(href="") {'Give feedback'}
173 footer.scrollbar-fix {
175 a(rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/") {
176 img(alt="Creative Commons License" style="border-width:0;" src="/images/by-sa_3.0_88x31.png") {}
180 a(href="https://git.ndcode.org/public/ndcode_site.git") {
183 ' and licensed under a '
184 a(rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/") {
185 'Creative Commons Attribution-ShareAlike 3.0 Unported License'
190 p {'Example code fragments embedded within the text are placed in the public domain unless otherwise noted.'}
192 p {`Copyright © ${new XDate().getUTCFullYear()} ${globals.copyright}.`}
197 //div#sign-in-modal.modal.fade(role="dialog") {
198 // div.modal-dialog {
199 // div.modal-content {
200 // div.modal-header {
201 // span.h4.modal-title {'Sign in'}
204 // form#sign-in-form(method="post" action="/sign_in.json" role="form") {
208 // label(for="sign-in-form-email") {'Email'}
209 // input.form-control#sign-in-form-email(type="text" name="email" placeholder="Please enter your email address" required="required" data-error="Email address is required.") {}
210 // div.help-block.with-errors {}
217 // label(for="sign-in-form-password") {'Password'}
218 // input.form-control#sign-in-form-password(type="password" name="password" required="required" placeholder="Please enter your password" data-error="Password is required.") {}
219 // div.help-block.with-errors {}
223 // input.btn.btn-success.btn-send(style="display: none;" type="submit" value="Sign in") {}
227 // 'No account yet? '
228 // a(href="/my_account/sign_up/index.html") {'Sign up'}
232 // 'Forgot password? '
233 // a(href="/my_account/password_reset/index.html") {'Password reset'}
236 // div.modal-footer {
237 // button.btn.btn-primary(type="submit" form="sign-in-form") {
240 // button.btn.btn-outline-secondary(type="button" data-dismiss="modal") {
248 div#feedback-modal.modal.fade(role="dialog") {
252 span.h4.modal-title {'Give feedback'}
256 'Did you notice something not quite right, or just want to share your impression of this page?'
258 form#feedback-form(method="post" action="/feedback.html" role="form") {
262 label(for="feedback-form-message") {'Message *'}
263 textarea.form-control#feedback-form-message(name="message" placeholder="Please tell us your thoughts" rows="4" required="required" data-error="Please, leave us a message.") {}
264 div.help-block.with-errors {}
268 p {} // fix this later
273 'These fields are required.'
274 //'Contact form template by '
275 //a(href="https://bootstrapious.com/p/how-to-build-a-working-bootstrap-feedback-form" target="_blank") {'Bootstrapious'}
280 input.btn.btn-success.btn-send(style="display: none;" type="submit" value="Send message") {}
284 button.btn.btn-primary(type="submit" form="feedback-form") {
287 button.btn.btn-outline-secondary(type="button" data-dismiss="modal") {
295 div#message-modal.modal.fade(role="dialog") {
299 span.h4.modal-title {'Message'}
302 p#message-modal-message {}
305 button.btn.btn-outline-secondary(type="button" data-dismiss="modal") {
315 //script(src="/js/sha256.js") {}
318 //function get_cookie(name) {
319 // let entries = document.cookie.split(';');
320 // for (let i = 0; i < entries.length; ++i) {
321 // let fields = entries[i].split('=');
322 // if (fields[0].trim() === name)
323 // return decodeURIComponent(fields[1]);
328 //// this function can be overridden in a further script
329 //function sign_in_out(status) {
335 //$('#sign-in').click(
337 // $('#sign-in-form-email').text('')
338 // $('#sign-in-form-password').text('')
339 // $('#sign-in-modal').modal('show')
343 //$('#sign-in-modal').on(
346 // $('#sign-in-form-email').focus()
349 //// when sign in form is submitted, do not reload the page
354 // e.preventDefault()
357 // url: '/my_account/sign_in.json',
360 // email: $('#sign-in-form-email').val(),
362 // get_cookie('session_key') +
363 // $('#sign-in-form-password').val()
366 // success: (data, textStatus, jqXHR) => {
367 // $('#sign-in-modal').modal('hide')
368 // switch (data.result) {
369 // case 1: // success
370 // $('#signed-in-status').text(data.signed_in_status)
371 // $('#sign-in').hide()
372 // $('#sign-out').show()
373 // sign_in_out(true) // notify navbar caller
375 // case 2: // redirect
376 // location.href = data.redirect_href
379 // $('#message-modal-message').text(data.message)
380 // $('#message-modal').modal('show')
382 // error: (jqXHR, textStatus, errorThrown) => {
383 // $('#sign-in-modal').modal('hide')
384 // $('#message-modal-message').text(errorThrown)
385 // $('#message-modal').modal('show')
393 //$('#sign-out').click(
397 // url: '/my_account/sign_out.json',
399 // success: (data, textStatus, jqXHR) => {
400 // if (data.result) {
401 // $('#signed-in-status').text(data.signed_in_status)
402 // $('#sign-in').show()
403 // $('#sign-out').hide()
404 // sign_in_out(false) // notify navbar caller
406 // $('#message-modal-message').text(data.message)
407 // $('#message-modal').modal('show')
409 // error: (jqXHR, textStatus, errorThrown) => {
410 // $('#message-modal-message').text(errorThrown)
411 // $('#message-modal').modal('show')
420 $('#give-feedback').click(
422 $('#feedback-form-message').text('')
423 $('#feedback-modal').modal('show')
427 $('#feedback-modal').on(
430 $('#feedback-form-message').focus()
433 // when feedback form is submitted, do not reload the page
441 url: '/feedback.html',
444 page: window.location.href,
445 message: $('#feedback-form-message').val()
447 success: (data, textStatus, jqXHR) => {
448 $('#feedback-modal').modal('hide')
449 $('#message-modal-message').text(data)
450 $('#message-modal').modal('show')
452 error: (jqXHR, textStatus, errorThrown) => {
453 $('#feedback-modal').modal('hide')
454 $('#message-modal-message').text(errorThrown)
455 $('#message-modal').modal('show')