Skip to content

Instantly share code, notes, and snippets.

@trev-dev
Last active October 30, 2020 11:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save trev-dev/6f1caa8b7614ebd37ee1f424f383a8a9 to your computer and use it in GitHub Desktop.
Save trev-dev/6f1caa8b7614ebd37ee1f424f383a8a9 to your computer and use it in GitHub Desktop.
A functional example of an application entrypoint
import { pipe } from '../utilities'
import { Model } from './model'
import { HyperScriptView } from './view'
import {
MessageObject, Updater, MSG, Dispatcher, dispatchList
} from './update'
import createElement from 'virtual-dom/create-element'
import { diff, patch } from 'virtual-dom'
const getSlides =
(gallery: Element) =>
gallery.querySelectorAll('.slide')
const slideClickHandler =
(galleryId: string) =>
(dispatch: Dispatcher) =>
(slide: Element) =>
slide.addEventListener('click', () => {
const { dataset } = (slide as HTMLElement)
if (dataset.index === undefined) {
throw Error(`Slide index missing in Gallery ${galleryId}`)
}
const activateSlide: MessageObject = {
type: MSG.SET_SLIDE,
slideIndex: parseInt(dataset.index)
}
const getGalleryImages: MessageObject = {
type: MSG.SET_GALLERY,
galleryId
}
dispatch({ type: MSG.TOGGLE_LIGHTBOX, enabled: true })
// Stupid work around for display + opacity CSS timing
setTimeout(() => {
dispatchList(dispatch)(
{ type: MSG.SET_OVERLAY, overlay: true },
getGalleryImages,
activateSlide
)
}, 1)
})
const setupGallery =
(dispatch: Dispatcher) =>
(gallery: Element) => {
const slides: Element[] = pipe(gallery)(
getSlides,
Array.from
)
const galleryId = (gallery as HTMLElement).dataset.id
if (galleryId === undefined) {
throw Error('Gallery ID missing')
}
const handler = slideClickHandler(galleryId)(dispatch)
slides.forEach(handler)
}
/**
* Application entrypoint
* @param initModel Initial data model
* @param view Hyperscript view
* @param update Model updater
* @param node Root node
* @param galleries list of galleries to setup event listeners on
*/
export const app = (
initModel: Model,
view: HyperScriptView,
update: Updater,
node: HTMLElement,
galleries: Element[]
) => {
let model = initModel
let currentView = view(dispatch, model)
let rootNode = createElement(currentView)
node.appendChild(rootNode)
const prepareSlides = setupGallery(dispatch)
galleries.forEach(prepareSlides)
function dispatch(msg: MessageObject) {
model = update(msg, model)
let newView = view(dispatch, model)
const patches = diff(currentView, newView)
rootNode = patch(rootNode, patches)
currentView = newView
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment