Module web
The web
module is a simple virtual DOM manager, it creates a virtual and manages it based on a simple state.
Usage
Web = imp 'web'
page = Web::create title: 'Page Title'
page.add <div>This is a div</div>
page.add <p>A paragraph</p>
page.render() # Render to html
Page
The Web::Page
class is a node containing all the data for the page as well as the root element, it has all the needed methods to be rendered to html.
Page Functions
add
:- Adds a series of elements to the body of the page
find
:- Finds and returns a Node from the tree
render
:- Renders the entire page to either a static html or a dynamic js that manages states Example:coffee
page.render() # Renders dynamic JS page.render true # Renders static HTML
- Renders the entire page to either a static html or a dynamic js that manages states Example:
clone
:- Clone the entire page into a new node
style
:- Add a css style string to the head or a link tag to a css Example:coffee
page.style """ body { background: black } """ page.style href: "https://example.com/path/to/style.css" page.style body: background: 'black' # Style has quite the functionality too page.style { '@variables': { blackColor: 'black' } '@mixin whiteSheet(color)': { background: 'wheat', color: '$color' }, 'body': { background: '$blackColor' width: { default: '100%', '@media screen and (min-width: 700px)': '70%' } '& .button': { background: { default: '#09D0D0', ':hover': '#ffffff' }, color: { default: '#ffffff', ':hover': '#09D0D0' }, '--var-text-color': '@v prop_color' } '& > .sheet': { '@include': 'whiteSheet(#000000)' } } }
- Add a css style string to the head or a link tag to a css Example:
script
:- Add a script js to the body Example:coffee
page.script """ alert("hi") """ page.script src: "https://example.com/path/to/script.js"
- Add a script js to the body Example:
- Creating a page:
- You can use the
Web::create
to create a page Example:coffeepage = Web::create title: "Title", viewportMeta: true
- You can use the
State management
Web
comes with a small state manager used to manage state in dynamic pages.
Creating state
name = Web::state "John"
page.add <div>{name}</div>
Changing state
name = Web::state "John"
page.add <div>{name}</div>
# ...
name.value = '...'
Changing state in the client
To change the state in the client, you need to wrap your function to give it access to the state in the client.
name = Web::state "John"
changeName = Web::invokeState [name], (event, name) ->
name.value = "Jane"
page.add <div onClick={changeName}>{name}</div>
To use local variables, you can do:
localVar = "Jane"
changeName = Web::invokeState [name, localVar], (event, name, localVar) ->
name.value = localVar
More
Remember that only serializable data can be passed here. The Web::invokeState
function creates a string from a function that will be parsed into a function in the client js. So whatever you pass is gonna be parsed into a string.
The Web
namespace
The below are all the functions in the module.
isNode
:- Checks wether the given item is a node or not
createElement
:- Creates nodes Example:coffee
div = Web::createElement 'div', { attribute: "value" }, Web::createTextNode "Child" page.add div
- Creates nodes Example:
createTextNode
:- Creates a simple text node. Example:coffee
Web::createTextNode "Child" # Doesn't take anything else
- Creates a simple text node. Example:
bundle
:- Bundles a file into a browser js Example:coffee
Web::bundle './file.coffee'
- Bundles a file into a browser js Example:
Example
This example shows a full usage of the Web
module along with the serve module.
# @jsx Web.prototype.createElement
Web = imp 'web'
Svr = imp 'serve'
router = Svr::router type: 'auto'
router
.get '/ssr', (req) ->
page = Web::create title: 'SSR Rendered page'
buttonText = Web::state 'Click to show'
show = Web::state false
indices = [1..10]
changeStates = Web::invokeState [buttonText, show],
(event, buttonText, show) ->
buttonText.value = 'Showing'
show.value = true
page.add <div data-only-if={show}>{indices.map((i) -> <p>{i}</p>)}</div>
page.add <p onClick={changeStates}>{buttonText}</p>
Svr::html page.render()
.get '/client', () ->
page = Web::create title: 'Client rendered page'
page.script await Web::bundle realpath './client.coffee'
Svr::html page.render true
svr = Svr::create fetch: router.fetch
svr.port 3000
.listen
.log 'Listening on $port'