paperclip

controller logic:

npm install paperclip
12 downloads in the last day
361 downloads in the last week
983 downloads in the last month

Paperclip.js Alt ci

Paperclip is a fast, data-bindable templating system inspired by Mustache, Angular, Derby, and Knockout. It's supported on all major browsers: IE8+, Firefox, Chrome, Safari, Opera, as well as Node.js.

Paperclip works by listening to bindable objects, and updating the template if anything changes. Unlike angular.js, paperclip takes a more explicit approach to updating templates. If you want to change a value in a template manually, you can easily do so by calling bindable.set(property, value). Here's an example.

Paperclip translates HTML directly to JavaScript. For example, the following hello.pc file:

hello {{name}}!

is translated to:

module.exports = function(fragment, block, element, text, textBlock, parser, modifiers) {
    return fragment([ text("hello "), block({
        value: {
            fn: function() {
                return this.get([ "name" ]);
            },
            refs: [ [ "name" ] ]
        }
    }, void 0), text("! ") ]);
};

This means a few things:

  • Super fast. 10k list items in ~ 500 MS.
  • Works very well on older browsers such as IE8.
  • You can customize paperclip to generate your own sort of markup language.
  • No metamorph tags, or other things that pollute the DOM, and cause strange bugs.

Features

Examples

Third-party components:

Installation

npm install paperclip -g

Compiling a script

paperclip -i template.pc -o template.pc.js

Syntax

Paperclip takes on a mustache / handlebars approach with variables, blocks, and pollyfills. Paperclip also allows basic inline javascript, similar to angular.js.

Blocks

Paperclip support variable blocks, just like Angular.js. For example:

hello {{ name.first }} {{ name.last }}!

You can also specify blocks within attributes. For example:

my favorite color is <span style="color: {{color}}">{{color}}</span>

If you want to add some sugar, go ahead and drop-in some javascript:

hello {{ message || "world!" }}!

Modifiers

Modifiers format data in a variable block. A good example of this might be presenting data to the user depending on their locale. For example:

translation modifier:

paperclip.modifier("t", function(value) {
  return i18n.t(value);
})

template usage:

{{ "hello.world" | t() }}

Modifiers can be chained together. For example, you can send a strong message to your users by writing something like:

{{ "hello.world" | t() | uppercase() }}!!!

Which might produce:

HELLO WORLD!!!

Modifiers also accept parameters. For example:

paperclip.modifier("divide", function(value, num) {
  return Math.round((value || 0) / num);
});

template usage:

A human that is {{age}} years old is like a {{ age | divide(5.6) }} year old dog!

Binding Operators

Paperclip comes with various binding operators that give you full control over how references are handled. You can easily specify whether to bind one way, two ways, or not at all. Here's the basic syntax:

<input data-bind="{{ model: <=>fullName }}" /> <!-- two-way data-binding against input -->
<input data-bind="{{ model: =>fullName }}" /> <!-- bind value once, and bind input value to fullName -->
<input data-bind="{{ model: <=fullName }}" /> <!-- bind to input once -->
{{ =fullName }} <!-- unbound helper - get fullName value, but don't watch for changes -->

Note that that =fullName tells paperclip not to watch the reference, so any changes to fullName don't get reflected in the view. Here's an example.

Binding helpers are especially useful for paperclip components. Say for instance you have a date picker:

{{
    datePicker: {
      currentDate: <=>currentDate
    }
}}

The above example will apply a two-way data-binding to the datePicker.currentDate property and the currentDate property of the view controller.

Block Helpers

{{ html: content }}

Similar to escaping content in mustache ({{{content}}}). For example:

{{ html: content }}

{{#if: condition }}

Conditional block helper. For example:

{{#if: age > 18 }}
  You're legally able to vote in the U.S.
{{/}}

Custom Block Helpers

Paperclip also allows you to register your own block helpers. This is similar to custom angular.js directives.

TODO example

data-bind attributes

data-bind attributes are borrowed from knockout.js. This is useful if you want to attach behavior to any DOM element.

{{ model: context }}

Input data-binding. For example:

<input type="text" name="message" data-bind="{{ model: this }}"></input> {{ message }}

You can also reference message directly. For example

<input type="text" data-bind="{{ model: <=>message }}"></input> {{ message }}

Notice the <=> operator. This tells paperclip to bind both ways. See binding operators.

{{ event: expression }}

Executed when an event is fired on the DOM element. Here are all the available events:

  • onChange - called when an element changes
  • onClick - called when an element is clicked
  • onLoad - called when an element loads - useful for <img />
  • onSubmit - called on submit - useful for <form />
  • onMouseDown - called on mouse down
  • onMouseUp - called on mouse up
  • onMouseOver - called on mouse over
  • onMouseOut - called on mouse out
  • onKeyDown - called on key down
  • onKeyUp - called on key up
  • onEnter - called on enter key up
  • onDepete - called on delete key up

Basic example:

<input type="text" data-bind="{{ model: <=>name, onEnter: sayHello() }}"></input>

{{ show: bool }}

Toggles the display mode of a given element. This is similar to the {{#if: expression }} conditional helper.

{{ css: styles }}

Sets the css of a given element. For example:

<strong data-bind="{{
  css: {
      cool    : temp > 0,
      warm    : temp > 60,
      hot     : temp > 90
  }
}}"> It's pretty warm! </strong>

{{ style: styles }}

Sets the style of a given element. For example:

<span data-bind="{{
  style: {
    color       : color,
    'font-size' : size
  }
}}"> Hello World </span>

{{ disable: bool }}

Toggles the enabled state of an element.

Custom data-bind helpers

TODO

Pollyfills

Pollyfills are similar to angular directives, but they should only be used to provide support for features not implemented in older browsers. A good example of this is paperclip-placeholder-pollyfill. If you need to create a custom component, create as a block helper.

API

template paperclip.template(sourceOrScriptName)

translates the source, or script into a paperclip template. For example.

elements template.bind(context)

Creates the DOM elements, and binds the elements to the given context.

elements.toFragment()

Casts the elements as a document fragment.

elements.unbind()

Unbinds the elements from the given context.

Node.js Usage

You can easily run paperclip in node. All you need to do is swap out the DOM factory.

var paperclip = require("paperclip"),
nofactor      = require("nofactor"),
bindable      = require("bindable");

var template = paperclip.template("<h1>Hello {{name}}</h1>", { nodeFactory: nofactor.string });

var element = template.bind(new bindable.Object({ name: "Jon" })).render();

console.log(renderer.toString());

Here's an example: http://runnable.com/UwVueJLcL9ZTAABN/hello-paperclip-for-node-js

npm loves you