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('/page.jst')
12 //let session = await _require('/session.jst')
14 // initialize env.sessions, env.session_key, env.session
17 // initialize env.cart
24 // extract top-level directory name
25 assert(env.parsed_url.pathname.slice(0, 1) === '/')
26 let index = env.parsed_url.pathname.indexOf('/', 1)
27 let dir = index === -1 ? '' : env.parsed_url.pathname.slice(1, index)
31 globals.site_title + ': ' + (
34 menu.entries[menu.index[dir]].name
43 // extract top-level directory name
44 assert(env.parsed_url.pathname.slice(0, 1) === '/')
45 let index = env.parsed_url.pathname.indexOf('/', 1)
46 let dir = index === -1 ? '' : env.parsed_url.pathname.slice(1, index)
48 div(style="padding-left: calc(100vw - 100%);") {
49 div.container(style="margin-top: 5px; margin-bottom: 5px;") {
51 div.'col-sm-8'.vbottom {
54 div.'col-sm-4'.vbottom(style="padding-bottom: 15px;") {
57 // Object.prototype.hasOwnProperty.call(env.session, 'account')
58 // span#signed-in-status {
60 // `Signed in as ${env.session.account}.`
62 // 'Browsing as guest.'
66 // a#sign-in(href="" hidden="") {'Sign in'}
68 // a#sign-in(href="") {'Sign in'}
71 // a#sign-out(href="") {'Sign out'}
73 // a#sign-out(href="" hidden="") {'Sign out'}
77 //form(action="/search/index.html") {
79 // input.form-control(name="query" type="text" placeholder="Search") {}
80 // span.input-group-btn {
81 // button.btn.btn-default(type="submit") {
82 // _out.push(icon_search_mono)
87 form.form-inline.'my-2'.my-lg-0(action="/search/index.html") {
88 div.input-group.mb-3 {
89 input.form-control(name="query" type="text" placeholder="Search" aria-describedby="search-button") {}
90 div.input-group-append {
91 button.btn.btn-outline-secondary#search-button(type="submit") {
92 _out.push(icon_search_mono)
98 //div.'col-sm-1'.vbottom {
99 // // a nested div is used to avoid hover colour on the padding
100 // div.nav-li-a(style="text-align: center;") {
101 // a(href="/online_store/view_cart/index.html") {
103 // _out.push(icon_cart_small)
107 // `${(env.cart.items || []).length}`
116 nav.navbar.navbar-expand-lg.navbar-dark.bg-primary {
117 div.container { //div(style="padding-left: calc(100vw - 100%);") {
118 //a.navbar-brand(href="#") {'Navbar'}
120 button.navbar-toggler(type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation") {
121 span.navbar-toggler-icon {}
123 div.collapse.navbar-collapse#navbarSupportedContent {
124 ul.navbar-nav.mr-auto {
125 if (dir.length === 0)
127 a.nav-link(href="/index.html") {
129 span.sr-only {' (current)'}
134 a.nav-link(href="/index.html") {'Home'}
136 let entries = menu.entries
137 for (let i = 0; i < entries.length; ++i)
138 if (entries[i].navbar)
139 if (entries[i].dir === dir)
141 a.nav-link(href=`/${entries[i].dir}/index.html`) {
143 span.sr-only {' (current)'}
148 a.nav-link(href=`/${entries[i].dir}/index.html`) {
152 //li.nav-item.dropdown {
153 // a.nav-link.dropdown-toggle#navbarDropdown(href="#" role="button" data-toggle="dropdown" aria-expanded="false") {
156 // div.dropdown-menu(aria-labelledby="navbarDropdown") {
157 // a.dropdown-item(href="#") {
161 // a.dropdown-item(href="#") {
164 // div.dropdown-divider {}
165 // a.dropdown-item(href="#") {
166 // 'Something else here'
171 // a.nav-link.disabled {
176 ul.navbar-nav.ml-auto {
178 a.nav-link#give-feedback(href="") {'Give feedback'}
184 div(style="padding-left: calc(100vw - 100%); margin-top: 20px; margin-bottom: 40px;") {
189 div.footer(style="padding-left: calc(100vw - 100%);") {
191 a(rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/") {
192 img(alt="Creative Commons License" style="border-width:0" src="/images/by-sa_3.0_88x31.png") {}
196 a(href="https://git.ndcode.org/public/ndcode_site.git") {
199 ' and licensed under a '
200 a(rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/") {
201 'Creative Commons Attribution-ShareAlike 3.0 Unported License'
206 p {'Example code fragments embedded within the text are placed in the public domain unless otherwise noted.'}
208 p {`Copyright © ${new XDate().getUTCFullYear()} ${globals.copyright}.`}
213 //div#sign-in-modal.modal.fade(role="dialog") {
214 // div.modal-dialog {
215 // div.modal-content {
216 // div.modal-header {
217 // button.close(type="button" data-dismiss="modal") {
225 // form#sign-in-form(method="post" action="/sign_in.json" role="form") {
229 // label(for="sign-in-form-email") {'Email'}
230 // 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.") {}
231 // div.help-block.with-errors {}
238 // label(for="sign-in-form-password") {'Password'}
239 // input.form-control#sign-in-form-password(type="password" name="password" required="required" placeholder="Please enter your password" data-error="Password is required.") {}
240 // div.help-block.with-errors {}
244 // input.btn.btn-success.btn-send(style="display: none;" type="submit" value="Sign in") {}
248 // 'No account yet? '
249 // a(href="/my_account/sign_up/index.html") {'Sign up'}
253 // 'Forgot password? '
254 // a(href="/my_account/password_reset/index.html") {'Password reset'}
257 // div.modal-footer {
258 // button.btn.btn-primary(type="submit" form="sign-in-form") {
261 // button.btn.btn-default(type="button" data-dismiss="modal") {
269 div#feedback-modal.modal.fade(role="dialog") {
273 button.close(type="button" data-dismiss="modal") {
282 'Did you notice something not quite right, or just want to share your impression of this page?'
284 form#feedback-form(method="post" action="/feedback.html" role="form") {
288 label(for="feedback-form-message") {'Message *'}
289 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.") {}
290 div.help-block.with-errors {}
294 p {} // fix this later
299 'These fields are required.'
300 //'Contact form template by '
301 //a(href="https://bootstrapious.com/p/how-to-build-a-working-bootstrap-feedback-form" target="_blank") {'Bootstrapious'}
306 input.btn.btn-success.btn-send(style="display: none;" type="submit" value="Send message") {}
310 button.btn.btn-primary(type="submit" form="feedback-form") {
313 button.btn.btn-default(type="button" data-dismiss="modal") {
321 div#message-modal.modal.fade(role="dialog") {
325 button.close(type="button" data-dismiss="modal") {
333 p#message-modal-message {}
336 button.btn.btn-default(type="button" data-dismiss="modal") {
346 //script(src="/js/sha256.js") {}
349 //function get_cookie(name) {
350 // let entries = document.cookie.split(';');
351 // for (let i = 0; i < entries.length; ++i) {
352 // let fields = entries[i].split('=');
353 // if (fields[0].trim() === name)
354 // return decodeURIComponent(fields[1]);
359 //// this function can be overridden in a further script
360 //function sign_in_out(status) {
366 //$('#sign-in').click(
368 // $('#sign-in-form-email').text('')
369 // $('#sign-in-form-password').text('')
370 // $('#sign-in-modal').modal('show')
374 //$('#sign-in-modal').on(
377 // $('#sign-in-form-email').focus()
380 //// when sign in form is submitted, do not reload the page
385 // e.preventDefault()
388 // url: '/my_account/sign_in.json',
391 // email: $('#sign-in-form-email').val(),
393 // get_cookie('session_key') +
394 // $('#sign-in-form-password').val()
397 // success: (data, textStatus, jqXHR) => {
398 // $('#sign-in-modal').modal('hide')
399 // switch (data.result) {
400 // case 1: // success
401 // $('#signed-in-status').text(data.signed_in_status)
402 // $('#sign-in').hide()
403 // $('#sign-out').show()
404 // sign_in_out(true) // notify navbar caller
406 // case 2: // redirect
407 // location.href = data.redirect_href
410 // $('#message-modal-message').text(data.message)
411 // $('#message-modal').modal('show')
413 // error: (jqXHR, textStatus, errorThrown) => {
414 // $('#sign-in-modal').modal('hide')
415 // $('#message-modal-message').text(errorThrown)
416 // $('#message-modal').modal('show')
424 //$('#sign-out').click(
428 // url: '/my_account/sign_out.json',
430 // success: (data, textStatus, jqXHR) => {
431 // if (data.result) {
432 // $('#signed-in-status').text(data.signed_in_status)
433 // $('#sign-in').show()
434 // $('#sign-out').hide()
435 // sign_in_out(false) // notify navbar caller
437 // $('#message-modal-message').text(data.message)
438 // $('#message-modal').modal('show')
440 // error: (jqXHR, textStatus, errorThrown) => {
441 // $('#message-modal-message').text(errorThrown)
442 // $('#message-modal').modal('show')
451 $('#give-feedback').click(
453 $('#feedback-form-message').text('')
454 $('#feedback-modal').modal('show')
458 $('#feedback-modal').on(
461 $('#feedback-form-message').focus()
464 // when feedback form is submitted, do not reload the page
472 url: '/feedback.html',
475 page: window.location.href,
476 message: $('#feedback-form-message').val()
478 success: (data, textStatus, jqXHR) => {
479 $('#feedback-modal').modal('hide')
480 $('#message-modal-message').text(data)
481 $('#message-modal').modal('show')
483 error: (jqXHR, textStatus, errorThrown) => {
484 $('#feedback-modal').modal('hide')
485 $('#message-modal-message').text(errorThrown)
486 $('#message-modal').modal('show')