Arrow keys: ← previous · → next 35 of 35
@nodedk/window
0.7.4 stable

window#

Browser navigation, storage, forms, JSON requests, and file uploads.

Install#

npm i @nodedk/window

Usage#

In a NodeDK scaffold application, the helpers are already exposed on window by the copied @nodedk/browser bundle. Use them directly in app/assets/js/base.js or HTML event handlers:

window.active()
window.store('filters', { status: 'active' })
console.log(window.store('filters')) // { status: 'active' }

See browser for the copy command and app/config/bundle.js setup. Several helpers call one another through window.

With a separate module-aware browser bundler, the exports can be installed directly:

var browser = require('@nodedk/window')
Object.assign(window, browser)

API#

  • active(options = {}): adds a class to links whose pathname matches the current page. options.selector defaults to 'a'; options.active defaults to 'active'. Returns undefined.
  • track(): stores the current URL under sessionStorage.track. Call before navigating away. Returns undefined.
  • back(): navigates to the stored track URL, or / when absent.
  • toggle(name, element): toggles a class on an element and removes it from other elements. Missing element does nothing. Returns undefined.
  • blur(element): removes .open from all elements unless the supplied element is within .toggle or .open. Returns undefined.
  • copy(input): selects and copies the value of an input or textarea, supplied as an element or selector. Returns undefined; clipboard completion is not awaited.
  • params(id): string IDs read a query parameter; numeric IDs read a zero-based pathname segment. Missing query values return ''; missing path segments return undefined. Omitting id returns ''.
<input id="share-url" value="https://example.com" readonly />
<button onclick="copy('#share-url')">Copy</button>

<div class="toggle" onclick="toggle('open', this)">Toggle</div>

cookie(key, value, options)#

Omit value to read a decoded cookie string or null. Supply a value to write it; null deletes it. Writes return undefined.

  • days: lifetime in days, default 30; 0 makes a session cookie.
  • path: default /.
  • domain, sameSite, secure: optional cookie attributes.
window.cookie('locale', 'nb', { days: 0, sameSite: 'Lax' })
console.log(window.cookie('locale')) // nb
window.cookie('locale', null)

store(key, value)#

Stores JSON in sessionStorage. Omit value to read it; missing or invalid JSON returns undefined. Invalid JSON is removed. Writes return the value; null deletes the key and returns the previous value. A falsy key clears all session storage and returns undefined.

flash(message, options = {})#

Shows a text message and returns its element, or null if the target is missing. A missing or empty message is read from a cookie, which is then deleted.

  • el: target selector, default .flash .message.
  • name: cookie name, default flash.
  • time: display duration in milliseconds, default 5000; falsy values use the default.
  • class: optional class, removed when the message fades.
  • scroll: set to false to avoid scrolling to the top.
<div class="flash"><span class="message"></span></div>
<button onclick="flash('Saved', { class: 'success' })">Save</button>

client(path, data = {}, options = {})#

Sends JSON and returns a promise for the parsed JSON response. path is the URL; data is serialized as the body. options.method defaults to POST; options.headers extends the JSON content-type header. Credentials are always included. Other options are ignored.

The body is always sent, so use a method that accepts a body. HTTP error responses are still parsed as JSON; fetch failures and invalid JSON reject.

async function save() {
  var result = await window.client('/account/update', {
    params: { name: 'Ada' }
  })
  if (result.ok === false) return window.flash(result.message)
  window.flash('Saved')
}

load(path, into)#

Fetches text and resolves to that text. into is an optional element or selector; when present, its HTML is replaced and inline script contents are evaluated. Use application-controlled HTML. HTTP statuses are not checked.

serialize(form)#

Returns a plain object from a form element or selector; a missing form returns {}. Disabled, unnamed, file, reset, submit, and button fields are skipped. Unchecked checkboxes and radio buttons are omitted; checked checkbox groups and multiple selects produce arrays. Dotted names create nested objects.

data-default supplies the value for an empty input. data-type overrides the input type:

  • array: comma-separated strings; [] becomes an empty array.
  • number: numeric conversion.
  • date: a Date; an unparseable value falls back to the current time.
  • null: null.
  • bool: false, 0, and off become false; other nonempty values become true.
<form id="profile">
  <input name="user.name" value="Ada" />
  <input name="user.age" value="32" data-type="number" />
  <input name="tags" value="news,events" data-type="array" />
</form>
console.log(window.serialize('#profile'))
// { user: { name: 'Ada', age: 32 }, tags: ['news', 'events'] }

submit(form, options = {})#

Submits a form element through window.client(form.action, { params: values }), using window.serialize. Returns a promise for undefined. A missing or non-form element does nothing.

  • error: fallback failure message; defaults to data-error.
  • success: message saved to the flash cookie after success; defaults to data-success.
  • redirect: success destination; defaults to data-redirect. Without it, reloads the page.

A response with ok: false displays message and any fields errors in em.<field>-errors. Inputs inside .field clear their associated error on changes. The first submit control is disabled during the request and restored on failure.

<form
  action="/account/update"
  data-success="Saved"
  data-redirect="/account"
  onsubmit="
    submit(this)
    return false
  "
>
  <div class="field">
    <input name="name" required />
    <em class="name-errors"></em>
  </div>
  <button type="submit">Save</button>
</form>

Uploads a File or Blob and resolves to { url }. Rejects with { error: { message } } on failure.

  • link.url: upload endpoint.
  • link.method: 'PUT' sends the file directly; other values use multipart POST.
  • link.headers: request headers for PUT.
  • link.location: public URL returned after PUT; otherwise the upload URL without its query string.
  • link.fields: form fields for POST. POST also appends file and expects a readable Location response header.
  • options.progress(event): receives upload events with loaded, total, and percent when a total is available.
  • options.error: overrides the failure message.

file(input)#

Handles selected files sequentially using window.client and window.upload. Takes a file input element and resolves with undefined. No selection does nothing.

The enclosing .field supplies data-action, which receives { params: { name, type, size } } and must return { data: link }. A response with ok: false stops the upload. Optional children are output, progress, input[type=hidden], picture source, and .spinner.

<div class="field" data-action="/files/presign">
  <input type="file" multiple onchange="file(this)" />
  <input type="hidden" name="files" />
  <output></output>
  <progress max="100" value="0"></progress>
</div>

The hidden value becomes comma-separated uploaded URLs; a picture source receives the first URL. The presign endpoint can use @nodedk/s3.

download(input, filename)#

Downloads a Blob, URL string, or element with an href. filename overrides the name; URL downloads otherwise use the last path segment, and Blob downloads default to download.

For Blobs, returns the temporary anchor element. URL downloads start an XMLHttpRequest and return undefined. Downloads are not awaited.

var data = new Blob(['hello'], { type: 'text/plain' })
window.download(data, 'hello.txt')

Created by Vidar Eldøy