<!DOCTYPE html>
<%
	// CREATE ALIASES
	const publicpage = locals.metadata.page.public
	const modules = locals.metadata.site.modules
	const metafields = locals.metadata.site.metafields
	const activity = locals.metadata.page.activity
	const object = locals.metadata.page.object
	const languages = locals.metadata.site.languages
	const language = locals.metadata.page.language
	const rights = locals.metadata.user.rights
	const pagedisplay = locals.metadata.page.display
	const anonymized = locals.metadata.page.query?.anonymize?.includes('true')
	const editing = ['contribute', 'edit'].includes(activity)
	const templated = locals.templated || locals.display_template !== null
%>
<html lang='<%- language %>'>
<head>

<% if (locals.data?.status >= 2 && !locals.data?.is_review) { %>
	<!-- TO DO: FINISH THIS -->
	<!-- <meta property='og:title' content='<%- locals.data.title %>' /> -->
	<!-- <meta property='og:type' content='article' /> -->
	<!-- <meta property='og:url' content='https://www.imdb.com/title/tt0117500/' /> -->
	<!-- <meta property='og:image' content='https://ia.media-imdb.com/images/rock.jpg' /> -->
<% } %>

<%- include ('../../partials/head.ejs') %>

<link rel='stylesheet' href='https://unpkg.com/leaflet@1.6.0/dist/leaflet.css'
	integrity='sha512-xwE/Az9zrjBIphAcBb3F6JVqxf46+CDLwfLMHloNu6KEQCAWi6HcDUbeOfBIptF7tcCzusKFjFw2yuvEpDL9wQ=='
	crossorigin=''/>
<script src='https://unpkg.com/leaflet@1.6.0/dist/leaflet.js'
	integrity='sha512-gZwIG9x3wUXg2hdXF6+rVkLF/0Vi9U8D2Ntg4Ga5I5BZpVkVxlJWbSQtXPSiUTtC0TjtGOmxa1AJPuV0CPthew=='
	crossorigin=''></script>

<script type="text/javascript">
	// INIT THE SOCKET
	// const socket = io()
	// const socket = io.connect('localhost:3000', {
	// 	reconnection: true,
	// 	reconnectionDelay: 1000,
	// 	reconnectionDelayMax : 5000,
	// 	reconnectionAttempts: Infinity
	// })

	// THE FOLLOWING IS INSPIRED BY:
	// https://www.programmersought.com/article/5248306768/
	// https://stackoverflow.com/questions/926916/how-to-get-the-bodys-content-of-an-iframe-in-javascript
	function loadHTML(url, source, target) {
		const iframe = document.createElement('iframe')
		iframe.style.display = 'none'
		iframe.src = url

		if (iframe.attachEvent){
			iframe.attachEvent('onload', function () {
				extractTarget(this, source, target)
			})
		} else {
			iframe.onload = function () {
				extractTarget(this, source, target)
			}
		}

		function extractTarget (node, source, target) {
			const doc = d3.select(node.contentDocument || node.contentWindow.document)
				.select(source)
				.attr('id', 'reference')
				// .classed('split-screen', true)
			doc.selectAll('.focus').classed('focus', false)
			doc.select('.pad > .inner > .meta-status').remove()
			doc.select('.pad > .inner > .meta-info').remove()
			doc.select('.pad > .inner > .scroll-nav').remove()
			doc.select('.media-input-group').remove()
			d3.select(target).html(doc.node().outerHTML)
			d3.select(node).remove()
		}
		document.body.appendChild(iframe)
	}
</script>
<%- include('./render.ejs') %>

</head>

<body>
<!-- <div class='fixed-bg hashed'></div> -->

<%- include ('../../partials/translations.ejs') %>
<%- include ('../../partials/menu-languages.ejs') %>

<!-- IF THIS PAD IS A FOLLOW UP, THEN DO NOT ADD THE MENU TO SAVE SCREEN SPACE -->
<% if (!pagedisplay.includes('adjacent')) { %>
	<header>
		<div class='inner'>
			<%- include ('../../partials/menu-logo.ejs') %>
		</div>
	</header>
<% } %>

<%- include ('../../partials/modals.ejs') %>

<% if (locals.source) { %>
	<% if (pagedisplay === 'adjacent-source') { %>
		<% if (object !== 'review' && !locals.data?.is_review) { %>
			<div class='display-option display-source split-screen lg'><a>
				<button><%- vocabulary['hide source'][language] %></button>
			</a></div>
		<% } %>
		<div id='source' class='document split-screen lg'></div>
		<script type='text/javascript'>
			loadHTML('../view/pad?id=<%- locals.source %><% if (object === "review" || locals.data?.is_review) { %>&anonymize=true<% } %>', '#pad', '#source')

			// const url = new URL(window.location) // url IS ALREADY DEFINED SOMEWHERE ELSE
			if (!queryparams) var queryparams = new URLSearchParams(url.search)
			queryparams.delete('display')

			d3.select('div.display-source a').attr('href', `?${queryparams.toString()}`)
		</script>
	<% } else { %>
		<div class='display-option display-source lg <% if (locals.data?.reviews?.length > 0) { %>split-screen<% } %>'><a>
			<button><%- vocabulary['display source'][language] %></button>
		</a></div>
		<script type='text/javascript'>
			if (!queryparams) var queryparams = new URLSearchParams(url.search)
			queryparams.set('display', 'adjacent-source')

			d3.select('div.display-source a').attr('href', `?${queryparams.toString()}`)
		</script>
	<% } %>
<% } %>

<!-- ONLY MAKE REVIEWS VIEWABLE IF THE PAD BELONGS TO THE CURRENT USER, OR IF THE CURRENT USER IS ONE OF THE REVIEWERS -->
<% if (locals.data?.reviews?.length > 0
	&& (locals.data.owner === locals.metadata.user.uuid || locals.data.reviews.some(d => d.owner === locals.metadata.user.uuid))
){ %>
	<% if (pagedisplay === 'adjacent-reviews') { %>
		<div class='display-option display-reviews split-screen right lg'><a>
			<button><%- vocabulary['hide reviews'][language] %></button>
		</a></div>
		<div id='reviews' class='document split-screen right lg'>
			<% locals.data.reviews.forEach((d, i) => { %>
				<div id='review-<%- i %>' class='review'></div>
			<% }) %>
		</div>
		<script type='text/javascript'>
			<% locals.data.reviews.forEach((d, i) => { %>
				loadHTML('../view/pad?id=<%- d.id %>', '#pad', '#review-<%- i %>')
			<% }) %>

			// const url = new URL(window.location) // url IS ALREADY DEFINED SOMEWHERE ELSE
			if (!queryparams) var queryparams = new URLSearchParams(url.search)
			queryparams.delete('display')

			d3.select('div.display-reviews a').attr('href', `?${queryparams.toString()}`)
		</script>
	<% } else { %>
		<div class='display-option display-reviews lg <% if (locals.source) { %>split-screen right<% } %>'><a>
			<button><%- vocabulary['display reviews'][language] %></button>
		</a></div>
		<script type='text/javascript'>
			if (!queryparams) var queryparams = new URLSearchParams(url.search)
			queryparams.set('display', 'adjacent-reviews')

			d3.select('div.display-reviews a').attr('href', `?${queryparams.toString()}`)
		</script>
	<% } %>
<% } %>


<!-- PB HERE WITH THE else if FOR SLIDESHOW OF A PAD THAT HAS A SOURCE BUT IS NOT DISPLAYED ADJACENT -->
<div class='document<% if ((locals.source || locals.data?.reviews?.length > 0) && !["adjacent-source", "adjacent-reviews", "slideshow"].includes(pagedisplay)) { %> offset<% } else if (locals.source && pagedisplay === "adjacent-source") { %> split-screen right<% } else if (locals.data?.reviews?.length > 0 && pagedisplay === "adjacent-reviews") { %> split-screen left<% } else if (pagedisplay === "slideshow") { %> slideshow<% } %>'>
	<main id='pad' class='pad'>
		<!-- BELOW ARE ENGAGEMENT FEATURES -->
		<!-- <% if (['edit', 'view'].includes(activity) && (locals.data && locals.data.published)) { %>
			<div class='engagement-input-group'>
				<div class='engagement bookmark <% if (locals.data.bookmarked) { %>active<% } %>' data-type='bookmark' data-count='<%- locals.engagement["bookmark"] %>'>
					<div class='label'><%- vocabulary['bookmark'][language](locals.data.bookmarked) %></div>
				</div>
				<ul>
					<% ['inspiration', 'approval', 'flag'].forEach(type => {
						let count = locals.engagement[`${type}s`] || 0
						let icon
						let label
						let active = false

						if (type === 'bookmark') {
							icon = 'bookmark'
							label = 'Bookmark'
							active = locals.data.bookmarked
						}
						else if (type === 'inspiration') {
							icon = 'wb_sunny'
							label = 'Inspiring'
							active = locals.data.inspired
						}
						else if (type === 'approval') {
							icon = 'thumb_up'
							label = 'Tested and validated'
							active = locals.data.approved
						}
						else if (type === 'flag') {
							icon = '()'
							label = 'For Tomorrow'
							active = locals.data.flagged
						}
					%>
						<li>
							<button class='engagement <% if (active) { %>active<% } %>' data-type='<%- type %>' data-count='<%- count %>'>
								<i class='material-icons-outlined'><%- icon %></i>
								<small><%- label %></small>
							</button>
						</li>
					<% }) %>
				</ul>
			</div>
		<% } %> -->
		<div class='inner'>
			<% if (editing) { %>
				<div class='meta-status status-<%- locals.data?.status || 0 %>'>
					<div class='btn-group'>
						<% if (editing) { %>
							<div class='save xs'>
								<form>
									<button type='button' onclick='partialSave()' disabled><%- vocabulary['save'][language] %></button>
								</form>
							</div>
						<% } %>
						<form method='GET' action='/publish/<%- `${object}s` %>'>
							<input type='hidden' name='id' value='<%- locals.data?.id %>'>
							<% if ((locals.data?.status || 0) < 1
								|| ((locals.data?.status || 0) === 2 && !locals.data?.publishable)
								|| (locals.data?.status || 0) === 3
								|| (object === 'review' && (locals.data?.status || 0) === 2))
							{ %>
								<% if (object === 'review') { %>
									<input type='hidden' name='source' value='<%- locals.source %>'>
									<button type='submit' class='publish' name='status' value='2' disabled><%- vocabulary['publish'][language] %></button>
								<% } else if (publicpage) { %>
									<button type='button' class='publish' name='status' value='1' onclick='saveAndSubmit(this)' disabled><%- vocabulary['submit'][language] %></button>
									<script type='text/javascript'>
										function saveAndSubmit (node) {
											partialSave()
											node.form.submit()
											// TO DO: PROVIDE FEEDBACK
											// CREATE A THANK YOU PAGE
											// AND MAYBE AUTO CREATE A PUBLIC PINBOARD FOR OPEN MOBILIZATIONS
											// SO THAT AUTHORS CAN GO CHECK THEM OUT
										}
									</script>
								<% } else { %>
									<button type='button' class='publish' disabled>Publish</button>
								<% } %>
							<% } else { %>
								<% if (object === 'review') { %>
									<input type='hidden' name='source' value='<%- locals.source %>'>
									<button type='submit' class='publish' name='status' value='2'><%- vocabulary['publish'][language] %></button>
								<% } else if (publicpage) { %>
									<!-- TO DO: INTERCEPT AND partialSave -->
									<button type='submit' class='publish' name='status' value='1'><%- vocabulary['submit'][language] %></button>
								<% } else { %>
									<button type='button' class='publish'><%- vocabulary['publish'][language] %></button>
								<% } %>
							<% } %>
							<% if (object !== 'review' && !publicpage) { %>
								<div class='dropdown'>
									<menu class='opts'>
										<% if (modules.some(d => d.type === 'reviews')) { %>
											<% if (locals.data?.status === 1) { %>
												<li class='opt'>
													<button type='submit' name='status' value='2'>
														<%- vocabulary['object status'][language](object, 2, false) %>
													</button>
												</li>
											<% } %>
											<% if (locals.data?.status <= 2 && locals.data?.review_status === 0) { %>
												<li class='opt'>
													<button type='button' name='review_status' value='1' onclick='selectReviewLanguage.call(this)'>
														<%- vocabulary['submit for review'][language] %>
													</button>
												</li>
											<% } %>
										<% } else { %>
											<% if (locals.data?.status === 1) { %>
												<li class='opt'>
													<button type='submit' name='status' value='2'>
														<%- vocabulary['internally'][language] %>
													</button>
												</li>
											<% } %>
											<% if (locals.data?.status <= 2 && locals.data?.publishable) { %>
												<li class='opt'>
													<button type='submit' name='status' value='3'>
														<%- vocabulary['externally'][language] %>
													</button>
												</li>
											<% } %>
										<% } %>
									</menu>
								</div>
							<% } %>
							<script type='text/javascript'>
								d3.select('button.publish')
								.on('click', function () { this.focus() })
								.on('focus', function () {
									const form = d3.select(this.form)
									const dropdown = form.select('.dropdown')
									if (dropdown.node()) {
										if (dropdown.node().style.maxHeight) dropdown.node().style.maxHeight = null
										else dropdown.node().style.maxHeight = `${Math.min(dropdown.node().scrollHeight, 300)}px`
										dropdown.selectAll('button').on('mousedown', _ => d3.event.preventDefault())
									}
								}).on('blur', function () {
									const form = d3.select(this.form)
									const dropdown = form.select('.dropdown')
									if (dropdown.node()) dropdown.node().style.maxHeight = null
								})

								async function selectReviewLanguage () { // THIS IS ALMOST THE SAME AS IN /browse/index.js
									const { name, value } = this

									const target_opts = <%- JSON.stringify(locals.metadata.menu.review_templates.map(d => { return { label: d.name, value: d.language, count: d.count, disabled: { value: d.disabled, label: vocabulary["missing reviewers"][language] }, type: 'radio', required: true } })) %>

									const formdata = { action: '/request/review',  method: 'POST' }
									const message = '<%- vocabulary["select review language"][language] %>'
									const opts = []
									opts.push({ node: 'select', name: 'language', label: '<%- vocabulary["select language"][language]() %>', options: target_opts })
									opts.push({ node: 'input', type: 'hidden', name: 'id', value: <%- locals.data?.id || JSON.stringify(null) %> })
									opts.push({ node: 'button', type: 'submit', name: name, value: value, label: '<%- vocabulary["submit for review"][language] %>' })
									const new_constraint = await renderFormModal({ message, formdata, opts })
								}

							</script>
						</form>
					</div>
				</div>
			<% } %>

			<!-- IF THE PAD IS A CONTRIBUTION TO A MOBILIZATION, DISPLAY THE MOBILIZATION INFORMATION -->
			<% if (locals.display_mobilization && !locals.data?.id && editing) { %>
				<div class='meta-info mobilization-info'>
					<h1><%- locals.display_mobilization.title %></h1>
					<p><%- locals.display_mobilization.description %></p>
				</div>
				<% if (pagedisplay !== 'slideshow') { %>
					<button class='scroll-nav' onclick='scrollToPad(this)'><label class='rotate'>&rsaquo;</label></button>
					<script type='text/javascript'>
						function scrollToPad (node) {
							let next = d3.select('.document:not(#source) main .inner .head').node()
							if (!next) next = d3.select('.document main .inner .body').node()
							window.scrollTo({
								top: next.offsetTop - 120,
								left: 0,
								behavior: 'smooth'
							})
						}
						window.addEventListener('scroll', function (e) {
							d3.select('button.scroll-nav').classed('hide', document.documentElement.scrollTop > 60)
						})
					</script>
				<% } %>
			<% } %>

			<!-- IF THE PAD IS AN OPEN CONTRBITUTION, DO NOT ADD THE TITLE, IT WILL BE DISPLAYED WITH A PROMPT IN THE media SECTIONS -->
			<% if (!(publicpage && editing && templated)) { %>
				<div class='head'>
					<% if (object !== 'review' && !locals.data?.is_review) { %>
						<% if (locals.metadata.page.referer?.includes('browse/pads')) { %>
							<a href='<%- locals.metadata.page.referer %>' class='return'><%- vocabulary['back to browse'][language] %></a>
						<% } else { %>
							<a href='<%- `/${language}/browse/pads/private` %>' class='return'><%- vocabulary['back to browse'][language] %></a>
						<% } %>
						<% if (editing) { %>
							<div class='title' data-placeholder='<%- vocabulary["untitled pad"][language] %>' onfocus='this.classList.add("focus")' onblur='partialSave("title")' contenteditable></div>
						<% } else { %>
							<div class='title' data-placeholder='<%- vocabulary["untitled pad"][language] %>'></div>
						<% } %>
						<!-- TO DO: FIX THIS: FOR SOME REASON NOTHING WORKS HERE WHEN IN REVIEW MODE -->
						<% if (!anonymized) { %>
							<% if (activity === 'edit') { %>
								<div class='contributor'><%- vocabulary['credit'][language](locals.data?.owner, locals.data?.ownername, 'contributors') %></div>
							<% } else { %>
								<div class='contributor'><%- vocabulary['credit'][language](locals.data?.iso3, locals.data?.country, 'countries') %></div>
							<% } %>
						<% } %>
					<% } else { %><!-- IF THE PAD IS A REVIEW, SO THE TITLE ONLY NEEDS TO BE THE REVIEWER ID -->
						<div class='title'>
							<%- vocabulary['review'][language](false, false) %> #<%- locals.data?.review_idx %>
						</div>
					<% } %>
				</div>
			<% } %>
			<div class='body'>
				<% if (!publicpage && !locals.display_mobilization && templated && (object !== 'review' && !locals.data?.is_review)) { %>
					<section class='description-layout layout view'><!-- THIS IS ALWAYS IN VIEW MODE IF DISPLAYED -->
						<% if (!publicpage) { %>
							<div class='meta-container template-container'>
								<div class='meta meta-template'>
									<i><%- vocabulary['pad based on'][language] %> </i>
									<a href='/<%- language %>/view/template?id=<%- locals.display_template.id %>'>
									<%- locals.display_template.title %></a>
								</div>
							</div>
						<% } %>
						<div class='media-container txt-container'>
							<div class='media media-txt'>
								<%- locals.display_template.description %>
							</div>
						</div>
					</section>
				<% } %>


				<% if (editing && !publicpage && (!templated || ![null, undefined].includes(locals.display_template.medium)))
				{ %>
					<button class='input-toolbox xs'><i class='material-icons'>edit</i></button>
					<div class='media-input-group input-group' tabindex=1>
						<% if (!templated) { %><button class='scroll-up m lg'><label>&rsaquo;</label></button><% } %>
						<div class='inner'>
							<div class='btn-group'>
							<% if (!templated) { %>
								<button id='input-media-section' title='Add a section.'><i class='material-icons'>add_circle</i></button>

								<div class='vertical-separator'></div>
								<!-- TO DO: TRANSLATE title INFO -->
								<form action='/upload/img' method='POST' enctype='multipart/form-data'>
									<input type='file' id='input-media-img' name='img' accept='image/*, .pdf' multiple>
									<label for='input-media-img' title='Upload an image. You can also use the “i” key as a keyboard shortcut.'><i class='material-icons'>add_photo_alternate</i></label>
								</form>
								<form action='/upload/video' method='POST' enctype='multipart/form-data'>
									<input type='file' id='input-media-video' name='video' accept='video/mp4,video/x-m4v,video/webm,video/*'>
									<label for='input-media-video' title='Add a video. You can also use the “v” key as a keyboard shortcut.'><i class='material-icons'>ondemand_video</i></label>
								</form>

								<button id='input-media-drawing' title='Add a drawing. You can also use the “d” key as a keyboard shortcut.'><i class='material-icons'>gesture</i></button>
								<button id='input-media-txt' title='Add a text block. You can also use the “t” key as a keyboard shortcut.'><i class='material-icons'>text_fields</i></button>
								<button id='input-media-embed' title='Embed a link or HTML code. Simply paste the link to the video to see it displayed. You can also use the “e” key as a keyboard shortcut.'><i class='material-icons'>code</i></button>
								<button id='input-media-checklist' title='Add a checklist. You can also use the “l” key as a keyboard shortcut.'><i class='material-icons'>check_box</i></button>
								<button id='input-media-radiolist' title='Add a radiolist. You can also use the “r” key as a keyboard shortcut.'><i class='material-icons'>radio_button_checked</i></button>

								<div class='vertical-separator'></div>
							<% } %>
							<% if (!templated || ![null, undefined].includes(locals.display_template.medium)) { %>
								<% metafields.forEach(d => { %>
									<button class='labeled' id='input-meta-<%- d.label %>' title='Add one or more <%- d.name %> tag(s).'>
										<img src='/imgs/icons/i-<%- d.label.replace(/\_/, "-") %>-btn.svg' alt='<%- d.name %>' onerror='this.onerror=null; this.src="/imgs/icons/i-generic-<%- d.type.replace(/\_/, "-") %>-btn.svg"' />
										<label class='lg'><span><%- vocabulary['add tags'][language](d.name.toLowerCase()) %></span></label>
									</button>
								<% }) %>
							<% } %>
							</div>
						</div>
						<% if (!templated) { %><button class='scroll-down m lg'><label>&rsaquo;</label></button><% } %>
					</div>
					<script type='text/javascript'>
						if (!mediaSize) var mediaSize = getMediaSize()
						if (mediaSize === 'xs') {
							d3.select('button.input-toolbox')
							.on('touchend, click', function () {
								d3.select(this).toggleClass('highlight')
								d3.select('.media-input-group').node().focus()
							})
							d3.select('.media-input-group').on('touchend', function () { this.focus() })
							.on('focus', function () {
								if (this.style.maxHeight) this.style.maxHeight = null
								else this.style.maxHeight = `${Math.min(this.scrollHeight, screen.height * .75)}px`
							}).on('blur', function () {
								 this.style.maxHeight = null
								 d3.select('button.input-toolbox').classed('highlight', false)
							})
						}
						<% if (!templated) { %>
							d3.select('.media-input-group')
							.each(function () {
								const node = this
								const sel = d3.select(this)
								const inner = sel.select('.inner')
								const height = inner.node().clientHeight || inner.node().offsetHeight
								const scrollheight = inner.node().scrollHeight
								const scrolltop = inner.node().scrollTop
								const buttonheight = inner.select('button').node().clientHeight || inner.select('button').node().offsetHeight

								sel.classed('overflowing', scrollheight > (height + buttonheight))

								sel.select('button.scroll-up')
									.classed('hide', scrollheight <= (height + buttonheight))
								.on('click', function () {
									inner.node().scrollTo({
										top: scrolltop - (height - buttonheight),
										left: 0,
										behavior: 'smooth'
									})
								})

								sel.select('button.scroll-down')
									.classed('hide', scrollheight <= (height + buttonheight))
								.on('click', function () {
									inner.node().scrollTo({
										top: scrolltop + height - buttonheight,
										left: 0,
										behavior: 'smooth'
									})
								})
							})
						<% } %>
					</script>
				<% } %>
			</div>
		</div>
	</main>
</div>

<footer>
	<% if (locals.metadata.site.engagementtypes.includes('comment')
		&& locals.data?.status >= 2
		&& !pagedisplay.includes('adjacent')
	) { %>
		<div class='inner'>
			<% if (pagedisplay !== 'slideshow') { %>
				<h2><%- locals.comments?.length || 0 %> <%- vocabulary['comment'][language](false, locals.comments?.length !== 1).toLowerCase() %></h2>
				<form action='/comment' method='POST'>
					<input type='hidden' name='id' value='<%- locals.data?.id %>'>
					<input type='hidden' name='object' value='<%- object %>'>
					<textarea id='input-media-comment' name='message' onkeyup='adjustarea(this)' data-placeholder='test' onchange='fixLabel(this)' onfocus='changeLabel(this, true)' onblur='changeLabel(this, false)' required></textarea>
					<label for='input-media-comment'><%- vocabulary['comment publicly'][language] %></label>
					<div class='btn-group'>
						<button type='submit' disabled><%- vocabulary['comment'][language](true) %></button>
					</div>
				</form>

				<ul class='comments'>
					<% locals.comments?.forEach(d => { %>
						<li class='comment'>
							<div class='head'>
								<div class='meta meta-data'>
									<div class='meta meta-contributor'><a href='../browse/pads/public?contributors=<%- d.contributor %>'><%- d.ownername %></a></div>
									<div class='meta meta-date'><%- vocabulary['date'][language](d.date) %></div>
								</div>
							</div>
							<div class='body'>
								<%- d.message %>
							</div>
							<div class='foot'>
								<button type='button' class='expand-collapsed <% if (d.replies?.length > 0) { %>wide<% }%>'>
									<% if (d.replies?.length > 0) { %><%- vocabulary['expand replies'][language](d.replies.length) %>
									<%} else { %><%- vocabulary['reply'][language](true) %><%} %>
								</button>
								<div class='collapsed'>
									<% if (d.replies?.length > 0) { %>
										<ul class='comments replies'>
											<% d.replies.forEach(c => { %>
											<li class='comment'>
												<div class='head'>
													<div class='meta meta-data'>
														<div class='meta meta-contributor'><a href='../browse/pads/public?contributors=<%- d.contributor %>'><%- c.ownername %></a></div>
														<div class='meta meta-date'><%- vocabulary['date'][language](c.date) %></div>
													</div>
												</div>
												<div class='body'>
													<%- c.message %>
												</div>
											</li>
											<% }) %>
										</ul>
									<% } %>
									<form action='/comment' method='POST'>
										<input type='hidden' name='id' value='<%- locals.data?.id %>'>
										<input type='hidden' name='object' value='<%- object %>'>
										<input type='hidden' name='source' value='<%- d.id %>'>
										<textarea id='input-media-comment' name='message' onkeyup='adjustarea(this)' data-placeholder='test' onchange='fixLabel(this)' onfocus='changeLabel(this, true)' onblur='changeLabel(this, false)' required></textarea>
										<!-- <label for='input-media-comment' data-label='Jeremy'>Reply publicly</label> -->
										<label for='input-media-comment'><%- vocabulary['reply publicly'][language] %></label>
										<div class='btn-group'>
											<button type='submit' disabled><%- vocabulary['reply'][language](true) %></button>
										</div>
									</form>
								</div>
							</div>
						</li>
					<% }) %>
				</ul>
			<% } else { %>
				<div class='dots'></div>
			<% } %>
		</div>

		<script type='text/javascript'>
			// INSPIRED BY https://stackoverflow.com/questions/995168/textarea-to-resize-based-on-content-length
			function changeLabel (node, focus) {
				for (let label of node.labels) {
					const sel = d3.select(label)
					if (focus || node.value.trim().length > 0) sel.html('<%- locals.metadata.user.name %>')
					else sel.html('<%- vocabulary["comment publicly"][language] %>')
				}
			}

			function adjustarea(node) {
				node.style.height = `${ node.scrollHeight - 20 }px` // WE HAVE A 2x10px PADDING IN THE CSS
				const submit = d3.select(node.parentNode).select('button[type=submit]').node()
				submit.disabled = node.value.trim().length === 0
			}
			d3.selectAll('footer textarea').each(function () { adjustarea(this) })

			d3.selectAll('.expand-collapsed').on('click', function () {
				const collapsed = this.nextElementSibling
				if (collapsed.classList.contains('collapsed')) collapsed.style.maxHeight = `${collapsed.scrollHeight}px`
				d3.select(this.remove())
			})

			// https://stackoverflow.com/questions/1349404/generate-random-string-characters-in-javascript
			// function makeid(length) {
			// 	var result = '';
			// 	var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
			// 	var charactersLength = characters.length;
			// 	for ( var i = 0; i < length; i++ ) {
			// 		result += characters.charAt(Math.floor(Math.random() * charactersLength));
			// 		if (result.split(' ').last().length === 10) result += ' '
			// 	}
			// 	return result;
			// }

			// const comments = d3.select('footer ul.comments')
			// .addElems('li', 'comment', d3.range(10).map(d => makeid(Math.random() * 1000)))

			// const chead = comments.addElems('div', 'head')
			// 	.addElems('div', 'meta meta-data')
			// chead.addElems('div', 'meta meta-contributor').html('Contributor name')
			// chead.addElems('div', 'meta meta-date').html(new Date(Date.now()).toString())

			// comments.addElems('div', 'body').html(d => d)

		</script>
	<% } else if (pagedisplay === 'slideshow') { %>
		<div class='inner'>
			<div class='dots'></div>
		</div>
	<% } %>
</footer>


<script type='text/javascript'>
	const metafields = <%- JSON.stringify(metafields || {}) %>

	// ADD ALL INTERACTION WITH MEDIA AND META INPUT BUTTONS
	d3.select('.media-input-group #input-media-section')
	.on('mousedown', function () {
		this['__active_node__']	= d3.selectAll('.media-layout.focus').nodes()?.last()?.nextSibling
	}).on('click', function () {
		addSection({ lang: '<%- language %>', sibling: this['__active_node__'], focus: true })
		this['__active_node__'] = null
	})

	d3.select('.media-input-group #input-media-img + label')
	.on('mousedown', function () {
		this.control['__active_node__']	= d3.selectAll('.media-container.focus, .meta-container.focus').nodes()?.last()?.nextSibling
	})
	d3.select('.media-input-group #input-media-img')
	.on('change', function () {
		uploadImg({ form: this.form, lang: '<%- language %>', sibling: this['__active_node__'], focus: true })
		this['__active_node__'] = null
	})

	d3.select('.media-input-group #input-media-video + label')
	.on('mousedown', function () {
		this.control['__active_node__']	= d3.selectAll('.media-container.focus, .meta-container.focus').nodes()?.last()?.nextSibling
	})
	d3.select('.media-input-group #input-media-video')
	.on('change', function () {
		uploadVideo({ form: this.form, lang: '<%- language %>', sibling: this['__active_node__'], focus: true })
		this['__active_node__'] = null
	})

	d3.select('.media-input-group #input-media-drawing')
	.on('mousedown', function () {
		this['__active_node__']	= d3.selectAll('.media-container.focus, .meta-container.focus').nodes()?.last()?.nextSibling
	}).on('click', function () {
		addDrawing({ lang: '<%- language %>', sibling: this['__active_node__'], focus: true })
		this['__active_node__'] = null
	})

	d3.select('.media-input-group #input-media-txt')
	.on('mousedown', function () {
		this['__active_node__']	= d3.selectAll('.media-container.focus, .meta-container.focus').nodes()?.last()?.nextSibling
	}).on('click', function () {
		addTxt({ lang: '<%- language %>', sibling: this['__active_node__'], focus: true })
		this['__active_node__'] = null
	})

	d3.select('.media-input-group #input-media-embed')
	.on('mousedown', function () {
		this['__active_node__']	= d3.selectAll('.media-container.focus, .meta-container.focus').nodes()?.last()?.nextSibling
	}).on('click', function () {
		addEmbed({ lang: '<%- language %>', sibling: this['__active_node__'], focus: true })
		this['__active_node__'] = null
	})

	d3.select('.media-input-group #input-media-checklist')
	.on('mousedown', function () {
		this['__active_node__']	= d3.selectAll('.media-container.focus, .meta-container.focus').nodes()?.last()?.nextSibling
	}).on('click', function () {
		addChecklist({ lang: '<%- language %>', sibling: this['__active_node__'], focus: true })
		this['__active_node__'] = null
	})

	d3.select('.media-input-group #input-media-radiolist')
	.on('mousedown', function () {
		this['__active_node__']	= d3.selectAll('.media-container.focus, .meta-container.focus').nodes()?.last()?.nextSibling
	}).on('click', function () {
		addRadiolist({ lang: '<%- language %>', sibling: this['__active_node__'], focus: true })
		this['__active_node__'] = null
	})

	// const centerpoint = <% if (locals.metadata.user.centerpoint) { %>[<%- JSON.stringify(locals.metadata.user.centerpoint) %>]<% } else { %>[]<% } %>;
	// d3.select('.media-input-group #input-meta-location')
	// .on('click', _ => addMap({ centerpoints: centerpoint }, '<%- language %>', true))
	// .on('touchend', _ => addMap({ centerpoints: centerpoint }, '<%- language %>', true))


	metafields.forEach(d => {
		d3.select(`.media-input-group #input-meta-${d.label}`)
		.on('mouseover', function () {
			d3.select(this).select('label').style('width', function () { return `${this.scrollWidth}px` })
		}).on('mouseout', function () {
			d3.select(this).select('label').style('width', 0)
		}).on('mousedown', function () {
			this['__active_node__']	= d3.selectAll('.media-container.focus, .meta-container.focus').nodes()?.last()?.nextSibling || null
		}).on('click', function () {
			const data = { level: 'meta', name: d.label, constraint: d.limit || null, required: d.required, options: d.options || null }
			if (d.type === 'txt') addTxt({ data, lang: '<%- language %>', sibling: this['__active_node__'], focus: true })
			if (d.type === 'embed') addEmbed({ data, lang: '<%- language %>', sibling: this['__active_node__'], focus: true })
			if (d.type === 'checklist') addChecklist({ data, lang: '<%- language %>', sibling: this['__active_node__'], focus: true })
			if (d.type === 'radiolist') addRadiolist({ data, lang: '<%- language %>', sibling: this['__active_node__'], focus: true })
			// THE FOLLOWING ARE ALWAYS META
			if (d.type === 'tag') addTags({ data, lang: '<%- language %>', sibling: this['__active_node__'], focus: true })
			if (d.type === 'index') addIndexes({ data, lang: '<%- language %>', sibling: this['__active_node__'], focus: true })
			if (d.type === 'location') addLocations({ data, lang: '<%- language %>', sibling: this['__active_node__'], focus: true })
			if (d.type === 'attachment') addAttachment({ data, lang: '<%- language %>', sibling: this['__active_node__'], focus: true })

			d3.select(this).select('label').style('width', 0)
			this['__active_node__'] = null
		})
	})

	const centerpoint = <%- JSON.stringify(locals.metadata.user.country.lnglat || {}) %>

	const taglists = <%- JSON.stringify(locals.tags || {}) %>

	const templated = <%- JSON.stringify(templated) %>;
	const httpquery = <%- JSON.stringify(locals.metadata.page.query) %>;

	const publicpage = <%- JSON.stringify(publicpage) %>;
	let activity = '<%- activity %>';
	const editing = <%- JSON.stringify(editing || false) %>;
	const rights = <%- rights %>;

	// let published = false
	let status = <%- locals.data?.status || 0 %>;
	// let activestatus = <%- locals.data?.status || 0 %>

	const main = d3.select('#pad')
	const head = main.select('.head')
	const body = main.select('.body')
	const foot = main.select('.foot')
	const footer = d3.select('footer')

	// ADD THE INTERACTION BEHAVIOR FOR THE TITLE INPUT
	head.select('.title')
	.on('keydown', function () {
		const evt = d3.event
		if (evt.code === 'Enter' || evt.keyCode === 13) {
			evt.preventDefault()
			this.blur()
		}
	})

	// THE FOUR FOLLOWING FUNCTIONS ARE FOR THE SAVING MECHANISM
	function retrieveItems (sel, datum, items) {
		// MEDIA
		if (datum.type === 'title') {
			datum.txt = (sel.select('.media-title').node() || sel.select('.meta-title').node()).innerText
			datum.has_content = datum.txt?.trim()?.length > 0
			items.push(datum)
		}
		if (['img', 'mosaic', 'video'].includes(datum.type)) {
			if (datum.type === 'mosaic') datum.has_content = datum?.srcs?.filter(b => b)?.length > 0
			else datum.has_content = datum.src !== null && datum.src !== undefined
			items.push(datum)
		}
		else if (datum.type === 'drawing') {
			datum.has_content = datum.shapes?.length > 0
			items.push(datum)
		}
		else if (datum.type === 'txt') {
			datum.txt = (sel.select('.media-txt').node() || sel.select('.meta-txt').node()).innerHTML
			datum.has_content = datum.txt?.trim()?.length > 0
			items.push(datum)
		}
		else if (datum.type === 'embed') {
			datum.html = (sel.select('.media-embed').node() || sel.select('.meta-embed').node()).innerHTML
			datum.has_content = datum.html?.trim()?.length > 0
			items.push(datum)
		}
		else if (['checklist', 'radiolist'].includes(datum.type)) {
			datum.has_content = datum.options.filter(b => b.name?.length && b.checked).length > 0
			const clone = JSON.parse(JSON.stringify(datum))
			clone.options = clone.options.filter(b => b.name?.length)
			items.push(clone)

			// datum.options = datum.options.filter(b => b.name && b.name.length)
			// items.push(datum)
		}
		// SPECIFIC META
		else if (datum.type === 'location') {
			datum.has_content = datum.centerpoints?.length > 0
			items.push(datum)
		}
		else if (['tag', 'index'].includes(datum.type)) {
			datum.has_content = (datum.sdgs?.length || datum.tags?.length) > 0 // THIS IS LEGACY FOR THE ACTION PLANNING PLATFORM: TO DO: DEPRECATE
			items.push(datum)
		}
		else if (datum.type === 'attachment') {
			datum.has_content = datum.srcs?.length > 0
			items.push(datum)
		}

	}
	function getStatus () {
		const completion = []

		const title = head.select('.title').node()?.innerText || (body.select('.media-title').node() || body.select('.meta-title').node())?.innerText || '<%- vocabulary["missing title"][language] %>'
		completion.push(title?.trim()?.length > 0)

		let metacompletion = JSON.parse(JSON.stringify(metafields)).filter(d => d.required).map(d => d.label)

		function checkCompletion (d) {
			<% if ((templated && [null, undefined].includes(locals.display_template.medium)) || publicpage) { %>
				if (d.required === null || d.required === undefined) throw 'there is no requirement: this should not happen'
				if (d.required === false) return true
				else return d.has_content === true
			<% } else { %>
				metacompletion = metacompletion.map(c => c === d.name ? d.has_content === true : c)
			<% } %>
		}

		main.selectAll('.layout:not(.description-layout)')
		.each(function (d) {
			const items = []
			const sel = d3.select(this)

			sel.selectAll('.media-container, .meta-container')
			.each(function (c) {
				const sel = d3.select(this)
				const ingroup = sel.findAncestor('group-container')
				// GROUPS
				if (c.type === 'group') {
					// const groupitems = []
					sel.selectAll('.media-group-items')
						.each(function () {
							const sel = d3.select(this)
							const subitems = []
							sel.selectAll('.media-container, .meta-container')
								.each(function (b) {
									retrieveItems(d3.select(this), b, subitems)
								})
							// completion.push(!subitems.map(checkCompletion).unique().includes(false))
							completion.push(subitems.map(checkCompletion).every(d => d === true))
						})
				} else {
					if (!ingroup) retrieveItems(sel, c, items)
					// completion.push(!items.map(checkCompletion).unique().includes(false))
				}
			})
			// if (items.length) completion.push(!items.map(checkCompletion).unique().includes(false))
			if (items.length) completion.push(items.map(checkCompletion).every(d => d === true))
		})

		<% if ((templated && [null, undefined].includes(locals.display_template.medium)) || publicpage) { %>
			console.log('override default requirements')
			return completion.every(d => d === true)
		<% } else { %>
			console.log('default requirements')
			return metacompletion.every(d => d === true)
		<% } %>
		// if (!templated) return metacompletion.every(d => d === true)
		// else return !completion.unique().includes(false)
		// else return completion.every(d => d === true)
	}
	function compileContent (attr) {
		const content = {}
		// COLLECT TITLE
		// let title = head.select('.title').node().innerText
		let title = head.select('.title').node()?.innerText || (body.select('.media-title').node() || body.select('.meta-title').node())?.innerText || '<%- vocabulary["missing title"][language] %>'
		if (title.length > 99) title = `${title.slice(0, 98)}…`
		// MAYBE INCLUDE ALERT IF title IS EMPTY
		// COLLECT ALL MEDIA
		const sections = []
		main.selectAll('.layout:not(.description-layout)')
		.each(function (d) {
			const items = []
			const sel = d3.select(this)

			sel.selectAll('.media-container, .meta-container')
			.each(function (c) {
				const sel = d3.select(this)
				const ingroup = sel.findAncestor('group-container')
				// GROUPS
				if (c.type === 'group') {
					const groupitems = []
					sel.selectAll('.media-group-items')
						.each(function () {
							const sel = d3.select(this)
							const subitems = []
							sel.selectAll('.media-container, .meta-container')
								.each(function (b) {
									retrieveItems(d3.select(this), b, subitems)
								})
							groupitems.push(subitems)
						})
					c.items = groupitems
					items.push(c)
				} else {
					if (!ingroup) retrieveItems(sel, c, items)
				}
			})

			d.title = (sel.select('.section-header h1').node() || {}).innerText
			d.lead = (sel.select('.media-lead').node() || {}).innerHTML
			d.instruction = (sel.select('.media-repeat button div').node() || {}).innerHTML
			d.items = items
			sections.push(d)
		})

		// const location = main.select('.location-container').node() ? main.select('.location-container').datum() : null // THIS IS NOT NEEDED
		// let skills = main.select('.skills-container').node() ? main.select('.skills-container').datum().tags.map(d => d.name) : null

		// THIS SHOULD REPLAE WHAT IS ABOVE

		// if (main.select('.sdgs-container').node()) {
		// 	main.selectAll('.sdgs-container').each(d => {
		// 		d.tags.forEach(c => {
		// 			// THE FILTERING HERE IS MAINLY FOR LEGACY, BECAUSE ORIGINALLY sdgs WERE ONLY THE keys, NOT THE { key: INT, name: STR } OBJECT
		// 			if (Object.keys(c).includes('key') && Object.keys(c).includes('name')) {
		// 				allTags.push({ id: c.key, name: c.name, type: d.type.slice(0, -1) })
		// 			}
		// 		})
		// 	})
		// }

		const allTags = []
		metafields.filter(d => ['tag', 'index'].includes(d.type)).forEach(d => {
			main.selectAll(`.${d.label}-container .tag input:checked`)
			.each(c => {
				// THE FILTERING HERE IS MAINLY FOR LEGACY, BECAUSE ORIGINALLY tags WERE ONLY THE names, NOT THE { id: INT, name: STR } OBJECT
				if (c.id && c.name && c.type) allTags.push({ id: c.id, type: c.type, name: c.name })
			})
		})
		content.tagging = allTags

		if (main.select('.location-container').node()) {
			content.locations = main.select('.location-container')?.datum()?.centerpoints
		} else content.locations = null

		const otherMetadata = []
		metafields.filter(d => !['tag', 'index', 'location'].includes(d.type))
		.forEach(d => {
			main.selectAll(`.${d.label}-container`)
			.each(c => {
				retrieveItems(d3.select(this), c, otherMetadata)
			})
		})
		content.metadata = otherMetadata.map(d => {
			const { id, level, has_content, instruction, required, ...metadata } = d
			const { type, name } = metadata
			const valuekey = Object.keys(metadata).find(c => <%- JSON.stringify(locals.metadata.site.media_value_keys) %>.includes(c))
			const value = metadata[valuekey]

			if (Array.isArray(value)) {
				return value.filter(c => {
					if (valuekey === 'options') return c.checked === true
					else return c
				}).map(c => {
					if (valuekey === 'options') return { type, name, value: c.name, key: c.id }
					else return { type, name, value: c }
				})
			} else return { type, name, value }
		}).flat()

		// COMPILE FULL TXT FOR SEARCH
		const fullTxt = `${title}\n\n
			${sections.map(d => d.title).join('\n\n').trim()}\n\n
			${sections.map(d => d.lead).join('\n\n').trim()}\n\n
			${sections.map(d => d.items).flat().filter(d => d.type === 'txt')
				.map(d => d.txt).join('\n\n').trim()}\n\n
			${sections.map(d => d.items).flat().filter(d => d.type === 'embed')
				.map(d => d.html).join('\n\n').trim()}\n\n
			${sections.map(d => d.items).flat().filter(d => d.type === 'checklist')
				.map(d => d.options.filter(c => c.checked).map(c => c.name)).flat().join('\n\n').trim()}
			${sections.map(d => d.items).flat().filter(d => d.type === 'radiolist')
				.map(d => d.options.filter(c => c.checked).map(c => c.name)).flat().join('\n\n').trim()}
			${sections.map(d => d.items).flat().filter(d => d.type === 'group').map(d => d.items)
				.filter(d => d.type === 'txt')
				.map(d => d.txt).join('\n\n').trim()}\n\n
			${sections.map(d => d.items).flat().filter(d => d.type === 'group').map(d => d.items)
				.filter(d => d.type === 'embed')
				.map(d => d.html).join('\n\n').trim()}\n\n
			${sections.map(d => d.items).flat().filter(d => d.type === 'group').map(d => d.items)
				.filter(d => d.type === 'checklist')
				.map(d => d.options.filter(c => c.checked).map(c => c.name)).flat().join('\n\n').trim()}
			${sections.map(d => d.items).flat().filter(d => d.type === 'group').map(d => d.items)
				.filter(d => d.type === 'radiolist')
				.map(d => d.options.filter(c => c.checked).map(c => c.name)).flat().join('\n\n').trim()}`

		// ALWAYS SEND fullTxt
		content.full_text = fullTxt

		// COLLECT DELETED MATERIAL (THIS WILL BE CLEARED FROM SESSIONSTORAGE UPON SUCCESS)
		const deletion = JSON.parse(window.sessionStorage.getItem('deleted')) || []

		// IF THIS IS A NEW PAD, CHECK WHETHER IT HAS A SOURCE
		// if (activity === 'contribute')
		// ALWAYS SEND THE SOURCE (BECAUSE reviews DEPEND ON THE SOURCE)
		content.source = <%- locals.source || JSON.stringify(locals.source) || JSON.stringify(null) %>;
		// ALWAYS SAVE THE TITLE
		content.title = title
		if (!attr || ['title', 'lead', 'media', 'meta', 'group'].includes(attr)
		|| sections.map(d => d.items).flat().unique('type', true).includes(attr)) {
			content.sections = JSON.stringify(sections)
		}
		// if (!attr || attr === 'meta' || meta.unique('type', true).includes(attr)) content.meta = JSON.stringify(meta)
		// if (!attr || attr === 'location') content.location = JSON.stringify(location)
		// if (!attr || attr === 'sdgs') content.sdgs = JSON.stringify(sdgs)
		// if (!attr || attr === 'tag') content.tags = JSON.stringify(tags)
		// if (!attr || attr === 'skills') content.skills = JSON.stringify(skills)
		// if (!attr || attr === 'datasources') content.datasources = JSON.stringify(datasources)

		// FULL TEXT
		// if (!attr || ['title', 'lead', 'txt', 'embed', 'checklist', 'radiolist', 'tags', 'group'].includes(attr))


		// ALWAYS SEND status
		const completion = getStatus()

		if (completion) status = Math.max(1, status)
		else status = 0
		content.status = status
		// ALWAYS SEND deletion IF THERE IS SOMETHING TO DELET
		if (deletion.length) content.deletion = deletion

		return content
	}
	function partialSave (attr) {
		return new Promise(resolve => {
			console.log('saving')
			// FIRST CHECK IF THIS IS A NEW PAD
			const content = compileContent(attr)
			// CHECK IF THE PAD ALREADY HAS AN id IN THE DB
			const url = new URL(window.location)
			const queryparams = new URLSearchParams(url.search)
			let id = queryparams.get('id')
			if (id) content.id = +id
			const template = queryparams.get('template')
			if (template) content.template = +template
			const mobilization = queryparams.get('mobilization')
			if (mobilization) content.mobilization = +mobilization

			POST('/save/<%- object %>', content)
			.then(res => {
				// ADD THE NOTIFICATION
				window.sessionStorage.removeItem('changed-content')

				if (!mediaSize) var mediaSize = getMediaSize()
				if (mediaSize === 'xs') {
					const save_btn = d3.select('.meta-status .btn-group .save').classed('saved', true)
					save_btn.select('button')
						.html('<%- vocabulary["changes saved"][language] %>')
					window.setTimeout(_ => {
						save_btn.classed('saved', false)
						.select('button').each(function () { this.disabled = true })
							.html('<%- vocabulary["save"][language] %>')
					}, 1000)
				} else {
					const menu_logo = d3.select('nav#site-title .inner')
					menu_logo.select('.save').classed('saved', true)
						.select('button')
						.html('<%- vocabulary["changes saved"][language] %>')
					window.setTimeout(_ => {
						menu_logo.selectAll('div.create, h1, h2').classed('hide', false)
						menu_logo.selectAll('div.save').classed('hide', true)
					}, 1000)
				}

				// REMOVE ITEMS TO DELETE
				window.sessionStorage.removeItem('deleted')
				// CHANGE THE URL TO INCLUDE THE PAD ID
				if (!id) { // INSERT
					id = res.object
					queryparams.append('id', id)
					url.search = queryparams.toString()
					// BASED ON:
					// https://usefulangle.com/post/81/javascript-change-url-parameters
					// https://www.30secondsofcode.org/blog/s/javascript-modify-url-without-reload
					const nextURL = url.toString().replace('contribute', 'edit')
					const nextTitle = 'Update pad' // TO DO: RESET FOR TEMPLATE
					const nextState = { additionalInformation: 'Updated the URL with JS' }
					window.history.pushState(nextState, nextTitle, nextURL)
					// REMOVE THE templates MENU
					// d3.select('nav#filter').remove()

					// SET THE ID FOR THE PUBLISH AND GENERATE FORMS
					d3.selectAll('div.meta-status form input[name="id"]').attr('value', id)
					// d3.select('div.meta-status form.generate-pdf input[name="id"]').attr('value', res.object)
				}

				updateStatus(content.status)
				resolve(id)

			}).catch(err => console.log(err))
		})
	}
	function updateStatus (_status) {
		if (!_status) {
			const completion = getStatus()
			if (completion) _status = Math.max(1, status)
			else _status = 0
		}

		// ACTIVATE THE PUBLISHING OPTIONS AT THE END
		const metastatus = d3.select('div.meta-status')
			.classed('status-0 status-1', false)
			.classed(`status-${_status}`, true)
		metastatus.select('div.btn-group form button.publish')
			.attr('disabled', _status >= 1 ? null : true)
		metastatus.select('div.btn-group form button.generate-pdf')
			.attr('disabled', _status > 0 ? null : true)
	}

	let keyTrack = []
	window.addEventListener('keydown', function (e) {
		e = e || event
		keyTrack.push(e.keyCode)

		if (editing) {
			// SHIFT + ENTER LEAVES THE FOCUSED CELL
			if (keyTrack.includes(16) && e.keyCode === 13
				&& (main.selectAll('.media-container.focus, .meta-container.focus').size())
			) {
				e.preventDefault()
				main.selectAll('.media-container, .meta-container').classed('focus', false)
					.selectAll('.media-txt, .media-embed, .media-checklist .list-item, .media-radiolist .list-item')
				.each(function () { this.blur() })
				main.selectAll('.media-container .inset, .meta-container .inset').style('max-height', null)
				autofillTitle()
			}
			// PROVIDE HIGHLIGHT FEEDBACK
			if (
				![head.selectAll('div.title').nodes(), main.selectAll('.section-header h1').nodes(), main.selectAll('input[type=text], input[type=number]').nodes(), footer.selectAll('textarea').nodes()].flat().includes(document.activeElement)
				&& !(main.selectAll('.layout.focus *:focus').size())
				&& !(main.selectAll('.media-container.focus, .meta-container.focus').size() ||
					main.selectAll('.media-container *:focus, .meta-container *:focus').size())
				&& !d3.select('.modal').node()
				&& !templated
			) {
				if (e.key === 'i' || e.keyCode === 73) main.select('label[for=input-media-img]').classed('highlight', true)
				if (e.key === 'd' || e.keyCode === 68) main.select('label[for=input-media-drawing]').classed('highlight', true)
				if (e.key === 't' || e.keyCode === 84) main.select('label[for=input-media-txt]').classed('highlight', true)
				if (e.key === 'l' || e.keyCode === 76) main.select('label[for=input-media-checklist]').classed('highlight', true)
				if (e.key === 'r' || e.keyCode === 82) main.select('label[for=input-media-radiolist]').classed('highlight', true)
				if (e.key === 'v' || e.keyCode === 86) main.select('label[for=input-media-video]').classed('highlight', true)
				if (e.key === 'e' || e.keyCode === 69) main.select('label[for=input-media-embed]').classed('highlight', true)
			}
		}
		// SET THE LEFT/RIGHT KEYBOARD NAVIGATION IF IN SLIDESHOW DISPLAY
		<% if (pagedisplay === 'slideshow') { %>
			if (document.activeElement === document.body) { // NOTHING IS IN FOCUS/ BEING EDITED
				if (e.key === 'ArrrowRight' || e.keyCode === 39) {
					d3.select('button.slide-nav.next:not(.hide)').node()?.click()
				}
				if (e.key === 'ArrowLeft' || e.keyCode === 37) {
					d3.select('button.slide-nav.prev:not(.hide)').node()?.click()
				}
			}
		<% } %>
	})
	window.addEventListener('keyup', function (e) {
		e = e || event
		if (editing) {
			if (
				![head.selectAll('div.title').nodes(), main.selectAll('.section-header h1').nodes(), main.selectAll('input[type=text], input[type=number]').nodes(), footer.selectAll('textarea').nodes()].flat().includes(document.activeElement)
				&& !(main.selectAll('.layout.focus *:focus').size())
				&& !(main.selectAll('.media-container.focus, .meta-container.focus').size() ||
					main.selectAll('.media-container *:focus, .meta-container *:focus').size())
				&& !d3.select('.modal').node()
				&& !templated
			) {
				if (!templated) {
					if (e.key === 'i' || e.keyCode === 73) {
						main.select('label[for=input-media-img]').classed('highlight', false)
						d3.select('#input-media-img').node().click()
					}
					if (e.key === 'v' || e.keyCode === 86) {
						main.select('label[for=input-media-video]').classed('highlight', false)
						d3.select('#input-media-video').node().click()
					}
					if (e.key === 'd' || e.keyCode === 68) {
						main.select('label[for=input-media-drawing]').classed('highlight', false)
						d3.select('#input-media-drawing').node().click()
					}
					if (e.key === 't' || e.keyCode === 84) {
						main.select('label[for=input-media-txt]').classed('highlight', false)
						d3.select('#input-media-txt').node().click()
					}
					if (e.key === 'e' || e.keyCode === 69) {
						main.select('label[for=input-media-embed]').classed('highlight', false)
						d3.select('#input-media-embed').node().click()
					}
					if (e.key === 'l' || e.keyCode === 76) {
						main.select('label[for=input-media-checklist]').classed('highlight', false)
						d3.select('#input-media-checklist').node().click()
					}
					if (e.key === 'r' || e.keyCode === 82) {
						main.select('label[for=input-media-radiolist]').classed('highlight', false)
						d3.select('#input-media-radiolist').node().click()
					}
				}
			} else {
				if ((d3.select(e.srcElement).classed('media')
						|| d3.select(e.srcElement).classed('meta')
						|| d3.select(e.srcElement).classed('title')
					) && !(
					[e.srcElement.nodeName, e.srcElement.tagName].map(d => d.toLowerCase()).includes('input')
					&& (
						d3.select(e.srcElement).findAncestor('search')?.node()
						|| d3.select(e.srcElement).findAncestor('filter-or-add')?.node()
						)
					)
				) {
					if (editing) {
						if (!publicpage) switchButtons('<%- language %>')
						else window.sessionStorage.setItem('changed-content', true)
					}
					// THIS PICKS UP ON KEYSTROKES IN media OR meta OUTSIDE OF INPUT FIELDS
				}
			}
		}

		keyTrack = keyTrack.filter(d => d !== e.keyCode)
	})
	window.addEventListener('mouseup', function (e) {
		e = e || event
		if (editing) {
			const focused_node = d3.select('.focus')
			const target = d3.select(e.target)
			const media = target.findAncestor('media')
			const meta = target.findAncestor('meta')
			const section = target.findAncestor('layout')
			const inputgroup = target.findAncestor('input-group')
			if (!inputgroup) {
				main.selectAll('.layout').filter(function () { return section ? this !== section.node() : true })
					.classed('focus', false)
			}
			const containers = main.selectAll('.media-container, .meta-container')
				.filter(function () {
					if (media) return this !== media.node()
					else if (meta) return this !== meta.node()
					else if (d3.select(this).classed('group-container focus') && inputgroup) return false
					else return true
				})
			containers.classed('focus', false)
				.selectAll('.inset')
				.style('max-height', null)
			main.selectAll('.media-input-group label, .meta-input-group label').classed('highlight', false)

			if (focused_node.node() && focused_node.classed('title')) {
				if (!document.activeElement.classList.contains('title')) {
					focused_node.classed('focus', false)
				}
			} else {
				autofillTitle()
			}
		}
	})

	// POPULATE THE PAGE
	if (activity === 'contribute' && templated) {
		const template = <%- JSON.stringify(locals.display_template || {}) %>;

		if (template.sections) {
			const title_instruction = template.sections.map(d => d.items || d.structure).flat()
				.find(d => d.type === 'title')?.instruction
			if (title_instruction) head.select('.title').attr('data-placeholder', title_instruction)

			template.sections.forEach(async d => {
				<% if (pagedisplay === 'slideshow') { %>
					await addSlides({ data: d, lang: '<%- language %>' })
				<% } else { %>
					addSection({ data: d, lang: '<%- language %>' })
				<% } %>
			})
		}
		<% if (pagedisplay === 'slideshow') { %>
			initSlideshow()
		<% } %>
		// CLEAR CHANGES
		window.sessionStorage.removeItem('changed-content')
	} else if (['edit', 'view'].includes(activity)) {
		const data = <%- JSON.stringify(locals.data || {}) %>;

		// THIS WAS AN ATTEMPT TO FLATTEN THE DATA STRCUTURE FOR SLIDES,
		// BUT DOING THIS WOULD MAKE THE CURRENT SAVING MECHANISM FAIL
		// BECAUSE IT IS DEPENDENT ON THE DOM section STRUCTURE
		// const { template, status, liked, disliked, sections, ...titleinfo } = data
		// const slides = [ titleinfo ]
		// data.sections.forEach(d => {
		// 	const { items, structure, ...titleinfo } = d
		// 	slides.push(titleinfo)

		// 	d.items.forEach(c => {
		// 		slides.push(c)
		// 	})
		// })

		<% if (object !== 'review' && !locals.data?.is_review) { %>
			if (data.title) head.select('.title').html(data.title)
		<% } %>

		if (data.sections) {
			data.sections.forEach(async d => {
				<% if (pagedisplay === 'slideshow') { %>
					await addSlides({ data: d, lang: '<%- language %>' }) // TO DO: RESTRICT THIS TO ONLY TEMPLATED PADS OR view MODE
				<% } else { %>
					await addSection({ data: d, lang: '<%- language %>' })
				<% } %>
			})
		} else { // THIS IS AN AUTO GENERATED PAD
			if (templated) { // IF IT IS TEMPLATED, THEN DISPLAY TEMPLATE STRUCTURE
				const template = <%- JSON.stringify(locals.display_template || {}) %>;

				if (template.sections) {
					const title_instruction = template.sections.map(d => d.items || d.structure).flat()
						.find(d => d.type === 'title')?.instruction
					if (title_instruction) head.select('.title').attr('data-placeholder', title_instruction)

					template.sections.forEach(async d => {
						<% if (pagedisplay === 'slideshow') { %>
							await addSlides({ data: d, lang: '<%- language %>' })
						<% } else { %>
							await addSection({ data: d, lang: '<%- language %>' })
						<% } %>
					})
				}
			}
		}
		<% if (pagedisplay === 'slideshow') { %>
			initSlideshow()
		<% } %>
		// CLEAR CHANGES
		window.sessionStorage.removeItem('changed-content')
	} else (async _ => await addSection({ lang: '<%- language %>' }))()


	let idx = 0

	// FOR SLIDESHOW VIEW
	function addSlides (kwargs) { // NOTE: SLIDES ARE NECESSARILY TEMPLATED OR IN VIEW MODE ONLY
		const { data, lang, sibling, focus } = kwargs || {}
		let { title, lead, structure, items, repeat, group, instruction } = data || {}
		if (!title) title = ''
		if (!lead) lead = ''
		if (!structure) structure = []
		if (!items) items = []

		if (editing && templated && (!items.length || sibling)) items = JSON.parse(JSON.stringify(structure))

		// DETERMINE ID TO KNOW WHETHER SECTION CAN BE REMOVED
		// const section_id = uuidv4()

		return new Promise(resolve => {
			d3.selectAll('.media-layout').classed('focus', false)

			const section = d3.select('main#pad div.inner div.body')
				.insertElem(sibling || '.media-input-group', 'section', `media-layout layout ${activity}`)
				.classed('repeat', repeat || false)
				// .classed('focus', focus && !templated)
				.datum({ type: 'section', title, lead, structure, items, repeat, group })
			.on('click.focus', function () { d3.select(this).classed('focus', editing && !templated) })
			// .addElems('div', 'inner')

			// THIS ALL GOES INTO A SLIDE: THIS IS ACTUALLY THE ONLY THING THAT CHANGES
			if (title || lead) {
				const titleslide = section.addElems('div', 'title-slide')

				if (title) {
					titleslide.addElems('div', 'section-header')
						.addElems('h1')
						.html(d => d.title)
				}

				if (lead) {
					const medialead = new Media({
						parent: titleslide.node(),
						type: 'lead',
						datum: { type: 'lead', lead: lead },
						lang: lang
					})
					// REMOVE THE PLACEMENT OPTIONS: TITLES CANNOT BE MOVED
					if (medialead.opts) medialead.opts.remove()

					medialead.media.html(d => d.lead)
				}
			}
			// END SLIDE

			if (repeat) {
				// HIDE THE PREVIOUS REPEAT BUTTONS FOR THE GROUP
				d3.selectAll('.layout.repeat').filter(d => d.group === group)
					.select('.repeat-container').classed('hide', true)

				const mediarepeat = new Media({
					parent: section.node(),
					type: 'repeat',
					datum: { type: 'repeat', instruction: instruction },
					lang: lang
				})
				// REMOVE THE PLACEMENT OPTIONS: TITLES CANNOT BE MOVED
				if (mediarepeat.opts) mediarepeat.opts.remove()
				if (mediarepeat.instruction) mediarepeat.instruction.remove()

				mediarepeat.media.addElems('button')
				.on('click.repeat', function () {
					const sel = d3.select(this)

					const promises = []
					section.findAncestor('pad').selectAll('.body>*')
					.each(function (d, i) {
						promises.push(new Promise(async resolve => {
							if (this === section.node()) {
								kwargs.sibling = `section:nth-child(${i + 2})`
								kwargs.focus = true

								const new_section = await addSlides(kwargs) // THIS TOO IS DIFFERENT TO addSection
								initSlideshow()
							}
							resolve()
						}))
					})

					Promise.all(promises)
					.then(_ => switchslide(idx))
				}).addElems('div').attrs({
					'data-placeholder': d => '<%- vocabulary["repeat section"][language] %>'
				}).html(d => d.instruction)
			}

			const displaypromises = []
			if (items.length) {
				section.each(function (d) {
					d.items.forEach(c => displaypromises.push(new Promise(async resolvedisplay => {
						await populateSection(c, lang, this)
						resolvedisplay()
					})))
				})
			}
			Promise.all(displaypromises).then(_ => resolve(section))

		}).then(section => {
			return section.node()
		})
	}
	function initSlideshow () {
		// TRANSFORM THE MAIN #pad INTO A SLIDESHOW
		// d3.select('.document').classed('slideshow', true)
			// .select('#pad').classed('slideshow', true)
		// TRANSFORM ALL .media-container TO .slide
		const slidewidth = main.node().clientWidth || main.node().offsetWidth || main.node().scrollWidth
		const inner = main.select('.inner')

		if (d3.selectAll('.slide').size() === 0) {
			inner.select('.meta-info').classed('slide', true)
			inner.select('.head').classed('slide', true)
		}

		d3.selectAll('.title-slide, .description-layout:not(.hide), .media-layout > .media-container:not(.lead-container):not(.hide), .media-layout > .meta-container:not(.hide)')
			.classed('slide', true)

		// PREVENT GROUPS FROM ANIMATING IN
		d3.selectAll('.media-group-items').classed('animate-in', false)

		// ADD BUTTON TO SAVE AND GENERATE PDF AT THE END
		const status_slide = d3.select('.meta-status')
		if (status_slide.node()) {
			const last_slide = d3.selectAll('.slide').last().node()
			last_slide.parentNode.append(status_slide.node())
			status_slide.classed('slide', true)
		}

		const slides = d3.selectAll('.slide')

		// ADD BUTTONS TO NAVIGATE
		inner.addElems('button', 'slide-nav', [{ label: '&lsaquo;', class: 'prev' }, { label: '&rsaquo;', class: 'next' }])
		.each(function (d) { d3.select(this).classed(d.class, true) })
			.classed('hide', d => {
				const sel = d3.select(this)
				let focus_id = 0
				d3.selectAll('.slide').each(function (c, i) {
					if (d3.select(this).classed('slide-in-view')) focus_id = i
				})
				return (d.class === 'prev' && focus_id === 0) || (d.class === 'next' && focus_id === d3.sels)
			}).html(d => d.label)
		.on('click', d => {
			if (d.class === 'prev') switchslide(idx - 1)
			else if (d.class === 'next') switchslide(idx + 1)
		}).on('mouseup', function () {
			d3.event.stopPropagation()
			// LOSE FOCUS OF THIS BUTTON TO RE-ENABLE KEYBOARD NAVIGATION
			this.blur()
		})

		// IF THE SLIDE IN VIEW IS HIDDEN (e.g. AFTER CLICKING ON A REPEAT SECTION BUTTON), THEN AUTO MOVE TO THE NEXT SLIDE
		// const slideinview = d3.select('.slide.slide-in-view')
		// if (slideinview.classed('hide')) {
		// 	let focus_id = 0
		// 	slides.each(function (c, i) {
		// 		if (d3.select(this).classed('slide-in-view')) focus_id = i
		// 	})
		// 	if (focus_id < slides.size() - 1) switchslide(focus_id - 1, focus_id + 1)
		// 	else switchslide(focus_id + 1, focus_id - 1)
		// 	console.log(slideinview)
		// 	slideinview.classed('slide slide-next slide-prev slide-in-view', false)
		// }

		// ADD DOTS
		footer.select('.dots').addElems('div', 'dot', new Array(slides.size()).fill(0))
		.classed('highlight', (d, i) => i === 0)
		.on('click', (d, i) => { switchslide(i) })

		inner.on('scroll', function () {
			if (this.scrollLeft % slidewidth === 0) {
				idx = Math.round(this.scrollLeft / slidewidth)
				d3.selectAll('.dot').classed('highlight', (d, i) => i === idx)
				d3.selectAll('button.slide-nav').classed('hide', d => {
					return (d.class === 'prev' && idx === 0) || (d.class === 'next' && idx === slides.size() - 1)
				})
			}
		})
	}
	function switchslide (i) {
		const slidewidth = main.node().clientWidth || main.node().offsetWidth || main.node().scrollWidth
		main.select('.inner').node().scrollTo({
			top: 0,
			left: i * slidewidth,
			behavior: 'smooth'
		})
		return idx = i
	}

</script>

</body>
</html>
