npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

washi

v3.2.2

Published

One of many backbone-esque view helpers.

Downloads

17

Readme

washi

A small (2.2kb gzipped), Backbone-inspired, library for greater organization on small projects.

  1. Installation
  2. Basic Usage
  3. API

Installation

package.json

Washi is available on npm:

npm install --save washi

global

If npm isn't your thing, or you'd rather include Washi as vendor code, download it from the unpkg CDN:

https://unpkg.com/washi

This is a UMD module. It should interop perfectly with CommonJS and AMD, or otherwise as a global by accessing Washi.

Basic usage

var Washi = require('washi');
var $     = Washi.$;

var Sample = {
  ui: {
    title: '.title',
  },
  events: {
    // Use ui helper selectors as aliases with {element}
    'mousedown {title}, touchstart {title}' : 'doSomething',

    // Alternatively, follow the syntax used by Backbone.Marionette
    'click @ui.title': 'doSomethingElse'
  },
  initialize: function(options) {
    this.ui.title.forEach(function(e) {
      e.innerHTML = 'Washi is for Origami'
    });
  },
  doSomething: function() {
    var text = $.map(this.ui.title, el => el.innerHTML).join(' ')
    console.log(text)
  },
  doSomethingElse: function() {
    console.log("Something else")
  }
}

var sample = Washi(Sample, {
    el: "#sample-el"
})

Corresponding with:

<div id="sample">
  <h1 class="title">Paper Crane</h1>
</div>

API

  1. Washi Components
  2. Washi Utilities

Washi Components

Create a view component based upon a configuration:

let Sample = {
  ui: {
    title: '.title',
  },
  events: {
    'click @ui.title': 'doSomething'
  },
  initialize: function(options) {
    // Startup
    console.log("Hello, world!")
  },
  doSomething: function() {
    alert("click!")
  }
}

let sample = Washi(Sample, {
  el: "#sample-el"
})

initialize(options: Object)

Invoked after the Washi instance has been created. Use this method for setup behavior.

let Widget = {
  initialize: function(options) {
    console.log('all set!')
  }
}

let component = Washi(Widget, { el: document.body }) // "all set!"

events: Object

Attach event listeners to the element associated with the component. Keys in this object are selectors, values are string references to methods on the configuration object:

let Widget = {
  events: {
    'click button': 'onClick'
  },

  onClick: function(event) {
    alert("HELLO!")
  }
}

let component = Washi(Widget, { el: '.selector' })

component.query('button').invoke('click') // "HELLO!"

ui: Object

Preselect child nodes within the element provided to Washi. These selections are available in a few places.

As aliases to their underlying selectors in the events object

In the events object, @ui.{name} is replaced with the CSS selector for the UI entry:

let Widget = {
  ui: {
    'button': 'button'
  },
  events: {
    'click @ui.button': 'onClick'
  },
  onClick: function(event) {
    alert("HELLO!")
  }
}
As entries in this.ui

Reference the selected elements associated with a ui entry under this.ui:

let Widget = {
  ui: {
    'button': 'button'
  },
  initialize: function() {
    // An array of DOM elements
    this.ui.button.forEach(el => el.click())
    // Alternatively, a Washi chain
    this.ui.$button.invoke('click')
  }
}

Washi Utilities

Washi exposes a number of utility methods under the $ namespace:

  1. chain
  2. Array operations
  3. toArray
  4. extend
  5. has
  6. query
  7. queryAll
  8. invoke
  9. isBlank
  10. isDOM
  11. isFunction
  12. isObject
  13. isRegExp
  14. isString
  15. isUndefined
  16. matches
  17. on
  18. off
  19. result
  20. tap
  21. template
  22. append
  23. remove
  24. addClass
  25. removeClass
  26. toggleClass

chain(target: Object | Array)

Creates a pipeline for executing multiple operatins on a value, this can be a single object or a list of values. Use valueOf() to end the chain, returning the underlying value:

const $ = Washi.$

let chain = $.chain([1,2,3]).map(i => i + 1)
let result = chain.valueOf()

console.log(result) // [2,3,4]

Passing a string to Washi.$ executes document.querySelectorAll, converting the selection into a chain:

const $ = Washi.$

$('button').on('click', () => {
  alert("HI!")
})

Array operations

Washi.$ includes most ES5 methods from the Array prototype. The primary benefit of doing this is to work around DOM APIs that return "array like" values such as NodeList:

You can use these directly, however they are primary intended for use with chaining:

const $ = Washi.$

let internalLinks = $('a').filter(el => el.href.origin === window.location.origin)

internalLinks.on('click', () => console.log("Retention! Hurrah!"))

toArray(list: Enumerable)

Convert a list-like value, such as a NodeList returned from document.querySelectorAll into an array:

const $ = Washi.$

let links = document.querySelectorAll('a')
let hrefs = $.toArray(links).map(el => el.href)

extend(target: Object, ...others)

Given a list of arguments, extend a target object with additional properties:

const $ = Washi.$

let red = { r: 200, g: 0, b: 0 }
let blue = { r: 0, g: 0, b: 220 }

let purple = $.extend({}, red, blue) // { r: 200, g: 0, b: 200 }

Important: the first argument, target, is mutated. This is a destructive operation!

has(target: Object, property: String)

Returns true if a given object has a property. This is sugar around Object.prototype.hasOwnProperty that covers some edge cases, such as null or undefined values.

const $ = Washi.$

let styles = { color: 'blue', font: '14px Helvetica' }

$.has(styles, 'color')  // true
$.has(styles, 'border') // false

query(selector: String, root: HTMLElement = document)

Select an HTML element. When no second argument is given, selection occurs on the document. When no element is found, it returns null.

const $ = Washi.$

let btn = $.query('button')

if (btn) {
  btn.click()
}

queryAll(selector: String)

Select multiple HTML elements. The resulting selection is converted into an Array, making its safe to perform operations like forEach, map, and reduce. When no element is found, it returns an empty array.

const $ = Washi.$

let items = $('ul').queryAll('li')

items.forEach(el => console.log(item.innerHTML))

invoke(list: Array, method: String, ...arguments: any[])

Execute a method on each member of a list:

const $ = Washi.$

// Operate on data
let planets = ['Mercury', 'Venus', 'Earth', 'Mars']
$.invoke(planets, 'toUpperCase') // ['MERCURY', 'VENUS', 'EARTH', 'MARS']

// Or call methods on a list of elements
$('button').invoke('click')

isBlank(value: any)

Is a value null or undefined?

const $ = Washi.$

$.isBlank('')         // false
$.isBlank(false)      // false
$.isBlank(0)          // false
$.isBlank(null)       // true
$.isBlank(undefined)  // true

isDOM(value: any)

Is a value a DOM element?

const $ = Washi.$

$.isDOM({})          // false
$.isDOM(new Image()) // true

isFunction(value: any)

Is a value a function?

const $ = Washi.$

$.isFunction({})            // false
$.isFunction(function() {}) // true

isObject(value: any)

Is a value an object? This function helps to avoid pitfalls with type checking objects. For example: typeof null === 'object'!

const $ = Washi.$

$.isObject({})            // true
$.isObject([])            // true
$.isObject(null)          // false
$.isObject(function() {}) // false

isRegExp(value: any)

Is a value a regular expression?

const $ = Washi.$

$.isRegExp({})                  // false
$.isRegExp(/[A-Z]/)             // true
$.isRegExp(new RegExp("[A-Z]")) // true

isString(value: any)

Is a value a string?

const $ = Washi.$

$.isString({})            // false
$.isString("Hello world") // true

isUndefined(value: any)

Is a value undefined?

const $ = Washi.$

$.isUndefined(null)      // false
$.isUndefined('')        // false
$.isUndefined(0)         // false
$.isUndefined(undefined) // true

matches(el: Element, selector: String)

Returns true if the provided element matches a CSS selector. When possible, this function uses the Element.matches DOM API.

const $ = Washi.$

$.matches(document.body, '.class-name')

on(el: Element, event: String, callback: Function, capture: boolean)

Safely attach an event listener with extreme browser support (IE5+).

const $ = Washi.$

$.on(document.body, 'click', event => alert("CLICK!"))

// Or chain it:
$('button').on('click', event => alert("CLICK!"))

For more information about event listening, see EventTarget.addEventListener

off(el: Element, event: String, callback: Function, capture: boolean)

Safely remove an event listener with extreme browser support (IE5+).

const $ = Washi.$

let buttons = $('button')
let handler = event => alert("CLICK!")

buttons.on('click', handler)
buttons.invoke('click') // CLICK! CLICK! CLICK!

buttons.off('click', handler)
buttons.invoke('click') // silence

result(target: any, property: String, fallback: any)

Check for ownership of a value, optionally calling it if it is a function. If the value is undefined, return the fallback value.

const $ = Washi.$

$.result({}, 'method', 'missing') // 'missing'
$.result('foobar', 'toUpperCase', 'UNKNOWN') // 'FOOBAR'

tap(target: any, fn: Function, scope: any)

Calls a function at a given scope, passing in the target value as the only argument. This is primarily intended side-effects when chaining:

const $ = Washi.$

function render(items) {
  let p = document.createElement('p')

  p.innerHTML = items.join(', ')

  document.body.appendChild(p)
}

let dates = $([new Date('01-01-2000'), new Date('02-02-2010'])

template(target: any, fn: Function, scope: any)

An extremely simple templating language. Primary used for basic string replacement. For more serious uses, particulary with DOM manipulation, use a vetted templating language such as mustachejs.

const $ = Washi.$

$.template('{foo}', { foo: 'bar' }) //=> 'bar'
$.template('{foo}') //=> '{foo}'

append(parent: Element, ...elements: Element[])

Append a list of children to an element:

const $ = Washi.$

let planets = $(['Mercury', 'Venus', 'Earth', 'Mars'])

planets.map(item => {
  var el = document.createElement('li')
  el.innerHTML = item
  return el
})

$('ul').append(planets.valueOf())

remove(elements: Element | Element[])

Remove a single HTML element from its parent, or each element within a list:

const $ = Washi.$

// Remove buttons from a form:
$('#my-form button').remove()

addClass(element: Element, classes: String)

Add one or more class names to an element:

const $ = Washi.$

let el = document.createElement('button')

el.className = 'btn'

$.addClass(el, 'btn-large')

console.log(el.className) // 'btn btn-large'

removeClass(element: Element, classes: String)

Remove one or more class names to an element:

const $ = Washi.$

let el = document.createElement('button')

el.className = 'btn btn-large'

$.removeClass(el, 'btn btn-large')

console.log(el.className) // ''

toggleClass(element: Element, classes: String, keep?: Boolean)

Toggle one or more class names to an element. When provided, adds/removes the class names based upon the keep argument

const $ = Washi.$

let el = document.createElement('button')

el.className = 'btn'

$.toggleClass(el, 'active')
console.log(el.className) // 'btn active'

$.toggleClass(el, 'active')
console.log(el.className) // 'btn'

$.toggleClass(el, 'active', false)
console.log(el.className) // 'btn'

$.toggleClass(el, 'active', true)
console.log(el.className) // 'btn active'

Visit code.viget.com to see more projects from Viget.