Piu JavaScript Reference

October 9, 2025 · View on GitHub

Copyright 2017-2025 Moddable Tech, Inc.
Revised: October 9, 2025

About This Document

Piu is a user interface framework designed to run on microcontrollers. The programming interface to Piu is a JavaScript API of global constructors, functions, and objects that define the containment hierarchy, appearance, behavior, and flow of applications. This document provides details on the objects that define the Piu API and important related concepts.

Table of Contents

Inheritance Hierarchy

Figure 1 summarizes the inheritance hierarchy for the objects described in this document.

Figure 1. Piu Inheritance Hierarchy

This image shows a prototype inheritance diagram for a UI component system. At the root is Object.prototype, which branches out to eight main prototype objects: Behavior, Content, Skin, Sound, Style, Texture, Timeline, and Transition. Content.prototype further connects to Container.prototype, which links to four components: Image, Label, Port, and Text. Container.prototype also connects to Application, Column, Layout, and Row. Layout.prototype connects to Die.prototype, and Row.prototype connects to Scroller.prototype. All nodes are represented as rectangular boxes with blue borders connected by lines showing the inheritance relationships.

The basic relationship between these objects in the context of a Piu application is as follows:

  • Graphical parts of the user interface are all content objects
  • skin, style, and texture objects customize the look (colors, fonts, etc.) of content objects
  • behavior objects are bound to content objects to handle events
  • timeline and transition objects animate content objects

Introduction to Important Concepts

This section explains important concepts related to Piu applications and defines some of the terms used throughout the rest of this document.

Containment Hierarchy and Appearance

The graphical user interface elements of Piu applications are composed of a hierarchy of content objects. The basic structure is as follows:

  • The application object is the root of the containment hierarchy
  • container objects are branches of the containment hierarchy
  • content objects are leaves of the containment hierarchy

Applications use constructors to define content and container objects. These objects are attached to the containment hierarchy using the add, insert, and replace functions, and are removed from the containment hierarchy using the remove and replace functions. See Functions in the section Container Object for descriptions of these properties.

Bound and Unbound Contents

Contents that are not attached to the containment hierarchy are called unbound contents; contents attached to the containment hierarchy, bound contents. Only objects that are part of the containment hierarchy appear on screen.

Unbound contents do not participate in layout. They are neither measured nor fitted; consequently, their position and size are undefined and cannot be changed.

let content = new Content();
let before = content.position;	// undefined
application.add(content);
let after = content.position;	// {x: 160, y:120} (assuming the application is 320x240)

Constraints

The coordinates of an object define implicit constraints on its position and size.

For example, centered content and contents whose sizes/position are dependent on their container's size/position cannot move.

// Cannot move
let centeredContent = new Content(null, {
	width: 10, height: 10
});
let dependentOnContainerContent = new Content(null, {
    top: 0, left: 0, bottom: 100, right: 100,
});

// Can move
let unconstrainedContent = new Content(null, {
    top: 0, left: 0, height: 100, width: 100
});

Measure and Fit

Measured size

All contents have a measured width and measured height, which are the default width and height computed by the content itself. For example, the measured width of the following content object will be 100.

let sampleContent = new Content(null, {
	width: 100
});

The measured width of the following content will be 0, because the content has no default width.

let sampleContent = new Content(null, {
	left: 0, right: 0
});

The coordinates property of a content object reflect the content's measured size. This property can be changed at any time.

sampleContent.coordinates = {
	left: 0,
	width: 100,
	top: 0,
	height: 100
};

Fitted size

All contents also have a fitted width and fitted height, which are the effective width and height of the content computed by its container.

If both left and right coordinates are defined, the content stretches horizontally with its container, and the fitted width of the content depends on the fitted width of its container. Similarly, if both top and bottom coordinates are defined, the content stretches vertically with its container, and the fitted height of the content depends on the fitted height of its container. For example, the fitted width and fitted height of the sampleContent object here will both be 100.

let sampleContent = new Content(null, {
	left: 0, right: 0
});
let sampleContainer = new Container(null, {
	height: 100, width: 100,
	contents: [
		sampleContent
	]
});

If a left or right coordinate (but not both) is defined, or if neither left nor right is defined, the fitted width equals the measured width. Similarly, if a top or bottom coordinate (but not both) is defined, or if neither top nor bottom is defined, the fitted width equals the measured height. For example, the fitted width and fitted height of the sampleContent object here will both be 50.

let sampleContent = new Content(null, {
	left: 0, top: 0, width: 50, height: 50
});
let sampleContainer = new Container(null, {
	height: 100, width: 100,
	contents: [
		sampleContent
	]
});

The width and height properties of a content object reflect the content's fitted size. A content's measured width and height are available immediately after the content is created; the fitted width and height are not available until its onDisplaying event has been triggered.

let sampleContent = new Content(null, {
	left: 0, right: 0, top: 0, height: 50,
	Behavior: class extends Behavior {
		onCreate(content) {
			let measuredHeight = content.coordinates.height; // 50
			let measuredWidth = content.coordinates.width; // undefined
			let fittedWidth = content.width; // undefined
			let fittedHeight = content.height; // 50
		}
		onDisplaying(content) {
			let fittedWidth = content.width; // 320 (assuming the application is 320x240)
			let fittedHeight = content.height; // 50
		}
	}
});
application.add(sampleContent)
Templates

Templates are a tool that reduce the script code needed to instantiate contents and build the containment hierarchy. Templates are often used to create objects that are similar, but have a few slightly different properties.

For example, consider the following screens:

The code for these screens without templates is unnecessarily repetitive. The only difference between screen1 and screen2 here is the header background color and string.

let screen1 = new Column(null, {
	top: 0, bottom: 0, left: 0, right: 0,
	skin: new Skin({ fill: "blue" }), style: sampleStyle,
	contents: [
		Label(null, {
			top: 0, height: 40, left: 0, right: 0,
			string: "Screen 1"
		}),
		Content(null, {
			top: 0, bottom: 0, left: 0, right: 0,
			skin: new Skin({ fill: "white" })
		}),
	]
});

let screen2 = new Column(null, {
	top: 0, bottom: 0, left: 0, right: 0,
	skin: new Skin({ fill: "red" }), style: sampleStyle,
	contents: [
		Label(null, {
			top: 0, height: 40, left: 0, right: 0,
			string: "Screen 2"
		}),
		Content(null, {
			top: 0, bottom: 0, left: 0, right: 0,
			skin: new Skin({ fill: "white" })
		}),
	]
});

Using templates significantly reduces the amount of code needed to define the two screens.

let BasicScreen = Column.template($ => ({
	top: 0, bottom: 0, left: 0, right: 0,
	skin: new Skin({ fill: $.headerColor }), style: sampleStyle,
	contents: [
		Label(null, {
			top: 0, height: 40, left: 0, right: 0,
			string: $.title
		}),
		Content(null, {
			top: 0, bottom: 0, left: 0, right: 0,
			skin: new Skin({ fill: "white" })
		}),
	]
}));

let screen1 = new BasicScreen({ title: "Screen 1", headerColor: "blue" });
let screen2 = new BasicScreen({ title: "Screen 2", headerColor: "red" });

As seen in the example above, the constructor has one parameter, $, which applications use to pass data to the template. The data may have any prototype; it is often a string, number, or JSON object. In their attributes, content and container objects use $ to access data properties. The $ parameter is referred to as “the data” or “the instantiating data.”

The template function for most Piu objects returns a constructor and a template function; the only exceptions are the Skin and Texture objects, which simply return constructors. These template functions allow constructors to be further specialized. In the example below, a HeaderWithBehavior instance would have all the properties of a BasicHeader instance in addition to being active and having a behavior.

let headerStyle = new Style({ font:"600 28px Open Sans", color: "white", horizontal: "left" });
let headerSkin = new Skin({ fill: "blue" });
let BasicHeader = Label.template($ => ({
	top: 0, height: 40, left: 0, right: 0,
	skin: headerSkin, style: headerStyle, string: $
}));

class HeaderBehavior extends Behavior {
	onTouchEnded(header) {
		trace("Header tapped\n");
	}
}
let HeaderWithBehavior = BasicHeader.template($ => ({
	active: true, Behavior: HeaderBehavior
}));

Behavior and Flow

Events

Piu delivers events to the containment hierarchy of applications, and content objects can reference behavior objects, which contain functions that respond to events. Piu uses events extensively.

When a content object receives an event, it checks whether its behavior object has a corresponding function to respond to that event (either directly or indirectly in its prototype chain). If it does, the content object calls the function, passing itself as the first parameter. If it does not, nothing happens.

Low-level events

Piu defines low-level events that are useful on a wide range of target devices. For example, onTouchBegan and onTouchEnded are useful for target devices with touch screens.

Higher-level events

Applications can also define their own higher-level events. To help efficiently implement common event propagation patterns, contents have delegate, distribute, bubble, firstThat, and lastThat properties. See Functions in the section Content Object for descriptions of these properties.

Animations

There are multiple ways to create time-based animation behaviors. One way is to use content objects as clocks, as described in the Duration, Fraction, Interval, Loop, and Time section of this document. This method is commonly used to animate a single content in response to events (to show touch feedback, for example) and to animate a single content for long periods of time.

The simplest way to create complex behaviors that animate several contents or properties is using the timeline object. The timeline object provides a mechanism for sequencing and running a collection of tweens, making it the best method for staggered animations of multiple content objects (to transition graphical elements of a screen in and out, for example). For more information, see the Timeline Object section of this document.

Piu transition objects are best for simple animations to move between screens or swap content objects. They often modify the containment hierarchy by adding or removing contents. They can also modify properties of objects as timeline objects do, but creating a sequence of animations is more complicated. For more information, see the Transition Object section of this document.

Easing equations

Animations that linearly modify the properties of content objects often appear awkward. Using easing equations is a common way to implement animations that feel more natural.

Piu extends the JavaScript Math object with Robert Penner’s open source easing equations (see the Easing section of Robert Penner’s Programming Macromedia Flash MX). The source code is in piuTransition.c.

The Piu implementations of these easing equations all take a single argument: a number in the range [0, 1]. The return value is a number in the range [0, 1] that maps the input to the eased output. These equations are used extensively in all types of animations. They are commonly used to map the fraction property of content objects or the fraction argument of a transition object's onStep function, and as an argument to many timeline object functions.

Global Properties

Properties of the Piu global object can be used anywhere in an application.

Built-in Properties

trace(string)
ArgumentsTypeDescription
stringstringThe string to trace

Traces the specified string in the virtual machine of the hosted application.

Note: Strings will not be traced until a line break ("\n") has also been traced.

trace("Hello world\n");

let sampleVariable = 2;
trace(`sampleVariable value is: ${sampleVariable}\n`);    // "sampleVariable value is 2"

Adding Additional Properties

Additional properties can be added by setting a property of the global object.

global.application = new Application(null, {
	displayListLength: 2048, commandListLength: 2048
});
export default global.application;

Descriptions of Properties

This section provides descriptions of select properties referenced throughout the Piu Object Reference section below.

Anchor

Each content object can have an optional anchor property. When the template is instantiated, a reference to the created content object is assigned to a property of the instantiating data; the identifier of the property is the value of the anchor property.

Anchors allow applications to directly access specific contents and containers in a containment hierarchy instantiated from a template. This can make it easier to access objects to modify while the application is running—for example, to change the label of a string, disable a button, or add lines to a column in a table.

let sampleStyle = new Style({ font:"600 28px Open Sans", color: "white" });
let SampleContent = Label.template($ => ({
	anchor: "ANCHORED_CONTENT", top: 0, bottom: 0, left: 0, right: 0,
	skin: new Skin({ fill: $.color }), style: sampleStyle,
	string: $.title
}));
let SampleContainer = Container.template($ => ({
	active: true, top: 0, bottom: 0, left: 0, right: 0,
	contents: [
		new SampleContent($)
	],
	Behavior: class extends Behavior {
		onCreate(container, data) {
			this.data = data;
		}
		onTouchEnded(container) {
			this.data["ANCHORED_CONTENT"].string = "Hello!"
		}
	}
}));
application.add(new SampleContainer({ title: "Tap to update", color: "blue" }));

Color

A color parameter can be passed into the dictionaries of skin and style constructors.

To specify a color, you can use CSS names (Level 2) or hexadecimal notations ("#RGB", "#RGBA", "#RRGGBB", "#RRGGBBAA"):

const whiteSkin = new Skin({ fill:"white" });
const redSkin = new Skin({ fill:"#F00" });
const halfRedSkin = new Skin({ fill:"#F008" });
const greenSkin = new Skin({ fill:"#00FF00" });
const halfGreenSkin = new Skin({ fill:"#00FF0088" });

To specify a color with an alpha channel, you can also use a mere hexadecimal number 0xRRGGBBAA:

const blueSkin = new Skin({ fill:0x0000FFFF });
const halfBlueSkin = new Skin({ fill:0x0000FF88 });

To build such hexadecimal numbers, Piu exports functions similar to the CSS functional notations:

import { rgb, rgba, hsl, hsla } from "piu/All";
const yellowSkin = new Skin({ fill:rgb(255, 255, 0) });
const halfYellowSkin = new Skin({ fill:rgba(255, 255, 0, 0.5) });
const cyanSkin = new Skin({ fill:hsl(180, 1, 0.5) });
const halfCyanSkin = new Skin({ fill:hsla(180, 1, 0.5, 0.5) });

In dictionaries, colors can be a single color or an array of 2, 3, or 4 colors. The skin and style objects blend a color based on the state of the content object that uses them. See Variant, Variants, State, and States for more information.

Coordinates

All content objects have a coordinates property. The coordinates property is an object with left, width, right, top, height, and bottom properties, all of which can be undefined. The coordinates of contents determine their position and size relative to their container and their previous and next properties (other content objects in the same container).

When a content's container is an application, container, scroller, or layout object:

  • top, bottom, left, and right coordinates are all relative to their container
  • If width, left, and right coordinates are all specified, the left and right coordinates will be overruled
  • If left and right are both unspecified, the content will be centered horizontally in its container with the width specified (or a width of 0, if unspecified)
  • If height, top, and bottom coordinates are all specified, the top and bottom coordinates will be overruled
  • If top and bottom are both unspecified, the content will be centered vertically in its container with the height specified (or a height of 0, if unspecified)

When a content's container is a column object:

  • top and bottom coordinates are relative to their previous and next properties
  • left and right coordinates are relative to their container
  • If width, left, and right coordinates are all specified, the left and right coordinates will be overruled

When a content's container is a row object:

  • left and right coordinates are relative to their previous and next properties
  • top and bottom coordinates are relative to their container
  • If height, top, and bottom coordinates are all specified, the top and bottom coordinates will be overruled

Duration, Fraction, Interval, Loop, and Time

Every content in the containment hierarchy can be used as a clock to control time-based animation behaviors using its duration, fraction, interval, and time properties.

  • The duration property is the duration of the animation, expressed in milliseconds.
  • The time property provides the current time of the content’s clock.
  • The fraction property is the ratio of the clock’s current time to the content’s duration.
  • The interval property is the time between frames (frame rate) of the animation, expressed in milliseconds.

The content’s start and stop functions control when the clock is running. The clock is automatically stopped when its current time reaches its duration. If the content's loop property is set to true, the clock will restart.

When a clock is running, the onTimeChanged function of its content is triggered at the interval specified by the content's interval property. When the content's time is equal to its duration, the onFinished function is triggered.

let animatedContent = new Content(null, {
	height: 100, width: 100, loop: true,
	skin: new Skin({ fill: ["red", "yellow", "blue"] }),
	Behavior: class extends Behavior {
		onCreate(content) {
			this.startAnimation(content);
		}
		startAnimation(content) {
			content.duration = 3000;
			content.time = 0;
			content.start();
		}
		onTimeChanged(content) {
			content.state = content.fraction*2;
		}
	}
});
application.add(animatedContent);

Time-based animation

The interval property sets the desired frame rate for an object's clock, but be aware that it may not be exact if the application is overloaded. It is not safe to assume, for instance, that if a content's interval is 2 and its duration is 100 that it will trigger the onTimeChanged event exactly 50 times before it triggers the onFinished event. Therefore, it is recommended that applications use the fraction or time properties to determine which frame to display for animations.

For example, consider two implementations of a button that expands and contracts 10 pixels in both directions when tapped.

The following implementation is not recommended, as it assumes that onTimeChanged will be triggered exactly 20 times before onFinished. While this may work most of the time, it is possible that the content will trigger its onFinished event before it shrinks down to its original size.

class ExpandingBehavior extends Behavior {
	onTouchEnded(content) {
		this.index = 0;
		content.interval = 5;
		content.duration = 100;
		content.time = 0;
		content.start();
	}
	onTimeChanged(content) {
		this.index++;
		if (this.index < 10) content.sizeBy(1, 1);
		else content.sizeBy(-1, -1);
	}
}

let expandingButton = new Content(null, {
	active: true, height: 50, width: 100,
	skin: new Skin({ fill: "blue" }),
	Behavior: ExpandingBehavior
});

The following implementation is better because it makes no assumptions about the number of frames that will draw and ensures that the content shrinks down to the correct size when onFinished is called.

class ExpandingBehavior extends Behavior {
	onTouchEnded(content) {
		this.startingSize = { h: content.height, w: content.width };
		content.interval = 5;
		content.duration = 100;
		content.time = 0;
		content.start();
	}
	onTimeChanged(content) {
		let startingSize = this.startingSize;
		let fraction = content.fraction;
		if (fraction > 0.5) fraction = 1-fraction;
		fraction *= 20;
		content.height = startingSize.h + fraction;
		content.width = startingSize.w + fraction;
	}
	onFinished(content) {
		let startingSize = this.startingSize;
		content.height = startingSize.h;
		content.width = startingSize.w;
	}
}

let expandingButton = new Content(null, {
	active: true, height: 50, width: 100,
	skin: new Skin({ fill: "blue" }),
	Behavior: ExpandingBehavior
});

Font

A font parameter must be passed into the dictionary of style constructors.

Piu uses bitmap fonts. The metrics are provided by binary FNT files, the glyphs are provided by PNG files.

Fonts are assets and must be defined in the resources of your manifest. Use the default target or the -alpha or -color pseudo targets for fonts.

The binary FNT file format was defined by AngelCode, which also released the BMFont generator on Windows. On Mac you can for instance use Glyph Designer or bmGlyph to generate such files.

One bitmap font corresponds to one style, one weight, one stretch, one size and one family. You will need separate bitmap fonts for each variation.

The Style constructor uses the font property of its dictionary to lookup its font. You can just set the font property to the name of a binary FNT file:

const popStyle = new Style({ font:"popFont" });

The popStyle object will use the popFont.fnt file in your assets.

The lookup happens only when label or text objects that use the style are bound to the displayed containment hierarchy, or when the Style.prototype.measure method is called.

Cascading Styles

In order to cascade styles, you may want to use something similar to the CSS font shortcut. Note that if you use this method of defining fonts in an application, you should not define other fonts in the application using just the font name as described above.

const style = new Style({ font:"italic bold 16px Open Sans" });

In Piu, the font property has five optional parts, in that order:

  1. style: italic | normal | inherit
  2. weight: 100 | ultralight | 200 | thin | 300 | light | 400 | normal | 500 | medium | 600 | semibold | 700 | bold | 800 | heavy | 900 | black | lighter | bolder | inherit
  3. stretch: condensed | normal | inherit
  4. size: xx-small | x-small | small | medium | large | x-large | xx-large | smaller | larger | [1-9][0-9]+px | [1-9][0-9]+% | inherit
  5. family: the rest of the font property if any.

The inherit value is the default value and is useful only to disambiguate a font property. By default the style of a content object inherits the style of its container objects.

All parts are optional and are cascaded separately. So you can for instance define a generic style for the application and specific styles for its contents:

const appStyle = new Style({ font:"16px Fira Sans" });
const menuStyle = new Style({ font:"bold" });

Styles are only cascaded when label or text objects that use them are bound to the displayed containment hierarchy.

For Piu to find the corresponding bitmap font files in your assets, you have to adopt the following convention, based on common practices:

  • the family, without spaces,
  • -,
  • the capitalized name of the stretch, if not normal,
  • the capitalized name of the computed weight, if not normal,
  • the capitalized name of the style, if not normal,
  • Regular, if the stretch, the computed weight and the style are all normal,
  • -,
  • the computed size in pixels without units.

Here above style will look for OpenSans-BoldItalic-16.fnt, appStyle will look for FiraSans-Regular-16.fnt and menuStyle will look for FiraSans-Bold-16.fnt.

Tiles

Applications can tile skins using their tiles property. The size of the tiles is determined by left, right, top, and bottom values, as follows:

  • If the tiles property is undefined or if its left, right, top and bottom values are all undefined, the skin is just an image, for instance an icon.
  • Else if only the left or right values are defined, the skin becomes a horizontal 3-part pattern. The left part is drawn at the left of the content, the right part is drawn at the right of the content, and the center part is repeated to fill the center of the content.
  • Else if only the top or bottom values are defined, the skin becomes a vertical 3-part pattern. The top part is drawn at the top of the content, the bottom part is drawn at the bottom of the content, and the middle part is repeated to fill the middle of the content.
  • Else the skin becomes a 9-part pattern. Corner parts are drawn in the corresponding corners of the content, side parts are repeated in the sides, and the middle part is repeated to fill the middle. The left, right, top and bottom values can all be defined to 0 to fill the content with the skin.

Tiling skins allows content objects of different sizes to share a single asset. Here is an example that uses this 30x30 pixel background to fill arbitrarily sized contents.

let roundedRectangleTexture = new Texture("roundedRectangle.png");
let roundedRectangleSkin = new Skin({
	texture: roundedRectangleTexture,
	x: 0, y: 0, width: 30, height: 30,
	tiles: { left: 5, right: 5, top: 5, bottom: 5 }
});

let sampleStyle = new Style({ font:"600 28px Open Sans", color: "white" });

let smallText = new Label(null, {
	skin: roundedRectangleSkin, top: 20, left: 20, height: 30, width: 30,
	style: sampleStyle, string: "Hi"
});
let bigText = new Text(null, {
	skin: roundedRectangleSkin, top: 70, left: 20, height: 120, width: 100,
	style: sampleStyle, string: "This is a long string"
});

application.add(smallText);
application.add(bigText);

Variant, Variants, State, and States

Applications often use the state and variant properties of content objects to update their appearance. Because they can change dynamically, they can be used to animate content objects and provide visual feedback to touch events, for example.

Colored skins and styles

A common way that the state property is used is to update the color of contents. As described in the Color section of this document, the fill property of a skin or style object can be an array of colors. The state property of a content object using the skin determines the index of the array. If the state is not an integer, colors from surrounding states are blended.

let multiColoredSkin = new Skin({ fill: ["black", "white", "red"] });
let blackContent = new Content(null, {
	top: 20, left: 20, width: 80, height: 80,
	skin: multiColoredSkin, state: 0,
});
let redContent = new Content(null, {
	top: 20, left: 120, width: 80, height: 80,
	skin: multiColoredSkin, state: 2
});
let grayContent = new Content(null, {
	top: 20, left: 220, width: 80, height: 80,
	skin: multiColoredSkin, state: 0.5
});
application.add(blackContent);
application.add(redContent);
application.add(grayContent);

Reusing textures

It is often convenient to store several icons or other user interface elements in a single image. Specifying states and variants properties in the dictionary of skin constructors enables you to reference different sections of the same texture. This prevents an application from having to reference similar images and create multiple skins.

The states and variants properties of a skin are numerical values used to define the size of a single element in the texture. The states property represents the vertical offset between states, and the variants property represents the horizontal offset between variants. Here is an example of an asset that includes ten 28x28 pixel icons in one image, and a skin that will allow applications to reference each icon separately.

const wiFiStripTexture = new Texture({ path:"wifi-strip.png" });
const wiFiSkin = new Skin({
	texture: wiFiStripTexture,
	width: 28, height: 28,
	states: 28, variants: 28
});

The states and variants properties of texture objects should not be confused with the state and variant properties of content objects, although they are related. The state and variant of a content object are used to select which area of their skin to render. Here is a visualization of the state and variant properties a content would use to reference different portions of the skin object from the last example.

The state and variant of a content can be updated at any time. This is often done when an event is triggered.

let WiFiStatusIcon = Content.template($ => ({
    skin: wiFiSkin, state: $.passwordProtected, variant: 0,
    interval: 500, duration: 2500, loop: true,
    active: true,
    Behavior: class extends Behavior {
    	onDisplaying(content) {
    		content.start();
    	}
        onTimeChanged(content) {
        	let variant = content.variant;
        	variant++;
        	if (variant > 4) variant = 0;
        	content.variant = variant;
        }
    }
}));
application.add(new WiFiStatusIcon({ passwordProtected: false }, { top: 20, right: 20 }));
application.add(new WiFiStatusIcon({ passwordProtected: true }, { top: 58, right: 20 }));

Piu Object Reference

This section provides details on the objects that define the Piu API. For each object, the following information is presented if relevant:

  • Source Code: A link to the source code for the object

  • Relevant Examples: Links to example apps that demonstrate how to use the object

  • Constructor Description: A description of the object's constructor(s)

  • Dictionary: Present when additional information is needed regarding the dictionary passed to the object's dictionary-based constructor; describes the properties that the dictionary may contain. Dictionary parameters set properties having the same name (unless noted otherwise) in the created instance.

  • Prototype Description: The prototype from which this object's prototype inherits and descriptions of any properties and functions specific to this object's prototype

  • Events: Descriptions of the events that the object triggers

For the complete JavaScript programming interface, see piuAll.js.

Application Object

All Piu applications must have an application object at the root of their containment hierarchy. All other content objects must be added to the application to appear on screen.

There is no default object, so you have to create one yourself and export it in the main module.

export default new Application();

Alternatively, you can export a function that returns an application object.

export default function() {
	return new Application();
}

Constructor Description

Application([behaviorData, dictionary])
ArgumentsTypeDescription
behaviorData*A parameter that is passed into the onCreate function of this container's behavior. This may be any type of object, including null or a dictionary with arbitrary parameters.
dictionaryobjectAn object with properties to initialize the result. Only parameters specified in the Dictionary section below will have an effect; other parameters will be ignored.

Returns an application instance, an object that inherits from Container.prototype.

export default new Application(null, {
	top: 0, bottom: 0, left: 0, right: 0,
	skin: new Skin({ fill: "blue" }),
});

Application.template(anonymous)
ArgumentsTypeDescription
anonymousfunctionA function that returns an object with properties to initialize the instances that the result creates

Returns a constructor, a function that creates instances of Application.prototype. The prototype property of the result is Application.prototype. The result also provides a template function.

// Taken from the balls example app

...

let BallApplication = Application.template($ => ({
	skin:backgroundSkin,
	contents: [
		Content(6, { left:0, top:0, skin:ballSkin, variant:0, Behavior: BallBehavior } ),
		Content(5, { right:0, top:0, skin:ballSkin, variant:1, Behavior: BallBehavior } ),
		Content(4, { right:0, bottom:0, skin:ballSkin, variant:2, Behavior: BallBehavior } ),
		Content(3, { left:0, bottom:0, skin:ballSkin, variant:3, Behavior: BallBehavior } ),
	]
}));

export default new BallApplication(null, { displayListLength:4096, touchCount:0 });

Dictionary

Same as for container object (see Dictionary in the section Container Object), plus:

ParameterTypeDescription
commandListLength numberThe size of the command list buffer in bytes used for holding Piu drawing operations
displayListLength numberThe size of the display list buffer in bytes for targets using the Poco rendering engine
touchCountnumberThe number of touch events that can trigger at the same time

Prototype Description

Prototype inherits from Container.prototype.

Behavior Object

The behavior object contains functions corresponding to events triggered by a content object. A content object checks whether its behavior owns or inherits a function property with the name of the event, and if so calls that function, passing itself as the first parameter.

Constructor Description

Applications define their own constructors for behavior objects, which inherit from Behavior.prototype and assign them to content objects when they are constructed. When a content object is constructed, it creates an instance of the behavior class assigned to it and triggers the behavior's onCreate event. This function does nothing by default; a behavior can use it to initialize its properties, for example.

class SampleBehavior extends Behavior {
	onCreate(content, data) {
		this.name = data.name;
	}
	onTouchEnded(content) {
		trace(`Name is: ${this.name}\n`);	// "Name is: Moddable"
	}
}

let sampleContent = new Content({ name: "Moddable" }, {
    active: true, height: 100, width: 100,
    skin: new Skin({fill: "blue"}),
    Behavior: SampleBehavior
});
application.add(sampleContent);

Behavior Sample

Prototype Description

Prototype inherits from Object.prototype.

Column Object

The column object is a container object that arranges its contents vertically.

Constructor Description

Column([behaviorData, dictionary])
ArgumentsTypeDescription
behaviorData*A parameter that is passed into the onCreate function of this content's behavior. This may be any type of object, including null or a dictionary with arbitrary parameters.
dictionaryobjectAn object with properties to initialize the result. The dictionary is the same as for the content object. Only parameters specified in the Dictionary section of the Content Object will have an effect; other parameters will be ignored.

Returns a column instance, an object that inherits from Column .prototype

let ColoredSquare = Content.template($ => ({
	left: 0, right: 0, top: 0, bottom: 0,
	skin: new Skin({ fill: $ })
}));

let sampleColumn = new Column(null, {
	top: 0, bottom: 0, left: 0, right: 0,
	contents: [
		new ColoredSquare("red"),
		new ColoredSquare("blue"),
		new ColoredSquare("black"),
	]
});
application.add(sampleColumn);

Column.template(anonymous)
ArgumentsTypeDescription
anonymousfunctionA function that returns an object with properties to initialize the instances that the result creates

Returns a constructor, a function that creates instances of Column.prototype. The prototype property of the result is Column.prototype. The result also provides a template function.

let ColoredSquare = Content.template($ => ({
	left: 0, right: 0, top: 0, bottom: 0,
	skin: new Skin({ fill: $ })
}));

let SampleColumn = Column.template($ => ({
	top: 0, bottom: 0, left: 0, right: 0,
	contents: [
		new ColoredSquare($.firstColor),
		new ColoredSquare($.secondColor),
	],
}));
application.add(new SampleColumn({ firstColor:"red", secondColor:"blue" }));

Prototype Description

Prototype inherits from Container.prototype.

Events

Same as for container object (see Events in the section Container Object)

Container Object

The container object is a content object that can contain other content objects. In a container, content objects are stored in a doubly linked list. The content objects can also be accessed by index or by name using the content property, for instance container.content(0) or container.content("foo").

Constructor Description

Container([behaviorData, dictionary])
ArgumentsTypeDescription
behaviorData*A parameter that is passed into the onCreate function of this container's behavior. This may be any type of object, including null or a dictionary with arbitrary parameters.
dictionaryobjectAn object with properties to initialize the result.Only parameters specified in the Dictionary section below will have an effect; other parameters will be ignored.

Returns a container instance, an object that inherits from Container.prototype.

let ColoredSquare = Content.template($ => ({
	height: 100, width: 100,
	skin: new Skin({ fill: $ })
}));

let sampleContainer = new Container(null, {
	top: 0, bottom: 0, left: 0, right: 0,
	skin: new Skin({fill: "white"}),
	contents: [
		new ColoredSquare("blue", { left: 0, top: 0 }),
		new ColoredSquare("red", { right: 0, top: 50 }),
		new ColoredSquare("black", { left: 100, bottom: 0 }),
	]
})
application.add(sampleContainer);

Container.template(anonymous)
ArgumentsTypeDescription
anonymousfunctionA function that returns an object with properties to initialize the instances that the result creates

Returns a constructor, a function that creates instances of Container.prototype. The prototype property of the result is Container.prototype. The result also provides a template function.

let ColoredSquare = Content.template($ => ({
	height: 100, width: 100,
	skin: new Skin({ fill: $ })
}));

let SampleContainer = Container.template($ => ({
	top: 0, bottom: 0, left: 0, right: 0,
	skin: new Skin({ fill: $.backgroundColor }),
	contents: [
		new ColoredSquare( $.squareColor ),
	]
}));
application.add(new SampleContainer({ backgroundColor: "white", squareColor: "blue" }));

Dictionary

Same as for content object (see Dictionary in the section Content Object), plus:

ParameterTypeDescription
clipbooleanIf true, this container will clip its contents.

Prototype Description

Prototype inherits from Content.prototype.

Properties

Same as for content object (see Properties in the section Content Object), plus:

NameTypeDefault ValueRead OnlyDescription
clipbooleanfalseIf true, this container clips its contents.
firstobjectThe first content object in this container, or null if this container is empty
lastobjectThe last content object in this container, or null if this container is empty
lengthnumberThe number of content objects in this container
transitioningbooleanfalseIf true, this container is running a transition object.

Functions

add(content)

ArgumentTypeDescription
contentcontentThe content object to add. It must be unbound; that is, its container must be null.

Adds the specified content object to this container. The content object becomes the last content object in this container.

let ColoredSquare = Content.template($ => ({
	height: 100, width: 100,
	skin: new Skin({ fill: $ })
}));
let sampleContainer = new Container(null, {
	top: 0, bottom: 0, left: 0, right: 0,
	skin: new Skin({ fill: "white" }),
});

sampleContainer.add(new ColoredSquare("black", {bottom: 10, left: 15}));
sampleContainer.add(new ColoredSquare("blue", {left: 100}));
sampleContainer.add(new ColoredSquare("green", {top: 10, left: 10}));
application.add(sampleContainer);


content(at)

ArgumentTypeDescription
atnumber or stringThe index or name property of the content object you want to access

Returns the specified content object, or undefined if no content with the index or name specified is in this container

let sampleContainer = new Container(null, {
	contents: [
		new Content(null, { name: "Moddable" }),
		new Content(),
	]
});
let namedContent = sampleContainer.content("Moddable");
let unnamedContent = sampleContainer.content(1);
let nonexistentContent = sampleContainer.content("Nonexistent");	// undefined

empty([start, stop])

ArgumentTypeDescription
startnumberThe starting index
stopnumberThe stopping index (this.length by default)

Removes content objects from this container, starting at index start and stopping at index stop. If start or stop is less than 0, it is an offset from this.length.

let ColoredSquare = Content.template($ => ({
	height: 100, width: 100,
	skin: new Skin({ fill: $ })
}));

let sampleContainer = new Container(null, {
	top: 0, bottom: 0, left: 0, right: 0,
	skin: new Skin({ fill: "white" }),
	contents: [
		new ColoredSquare("blue", { top: 0, left:0 }),
		new ColoredSquare("red", { top: 0, right: 0 })
	]
});

sampleContainer.empty();
application.add(sampleContainer);


firstThat(id [, ...])

ArgumentTypeDescription
idstringThe name of the event to trigger
...*Zero or more extra parameters

Causes all content objects in this container to trigger an event named by the value of id. The order of traversal is from the first to the last. Traversal halts when a distributed event returns true. Note that the first parameter of a distributed event is the content object that triggers the event, not this container. Additional parameters, if any, of the event are the extra parameters of the firstThat function.

class SampleBehavior extends Behavior {
	sampleEvent(content) {
		trace(content.name+" triggered\n");
		return true;
	}
}

let sampleContainer = new Container(null, {
	top: 0, bottom: 0, left: 0, right: 0,
	skin: new Skin({ fill: "white" }),
	contents: [
		Content(null, { name: "firstContent" }),
		Content(null, { name: "secondContent", Behavior: SampleBehavior }),
		Content(null, { name: "thirdContent", Behavior: SampleBehavior }),
	],
	Behavior: class extends Behavior {
		onDisplaying(container) {
			container.firstThat("sampleEvent");	// "secondContent triggered" will be traced here
		}
	}
});
application.add(sampleContainer);

insert(content, before)

ArgumentTypeDescription
contentcontentThe content object to insert. Its container must be null.
beforeobjectThe content object before which to insert. Its container must be this container.

Inserts one content object before another in this container as specified by the parameters

let ColoredSquare = Content.template($ => ({
    height: 100, width: 100,
    skin: new Skin({ fill: $ })
}));

let sampleContainer = new Container(null, {
    top: 0, bottom: 0, left: 0, right: 0,
    skin: new Skin({ fill: "white" }),
    contents: [
        new ColoredSquare("blue", { top: 0, left:0 }),
    ]
});
let redSquare = new ColoredSquare("red", { top: 20, left: 20, });
sampleContainer.insert(redSquare, sampleContainer.first);
application.add(sampleContainer);


lastThat(id [, ...])

ArgumentTypeDescription
idstringThe name of the event to trigger
...*Zero or more extra parameters

Causes all content objects in this container to trigger an event named by the value of id. The order of traversal is from the last to the first. Traversal halts when a distributed event returns true. Note that the first parameter of a distributed event is the content object that triggers the event, not this container. Additional parameters, if any, of the event are the extra parameters of the lastThat function.

class SampleBehavior extends Behavior {
	sampleEvent(content) {
		trace(content.name+" triggered\n");
		return true;
	}
}

let sampleContainer = new Container(null, {
	top: 0, bottom: 0, left: 0, right: 0,
	skin: new Skin({ fill: "white" }),
	contents: [
		Content(null, { name: "firstContent" }),
		Content(null, { name: "secondContent", Behavior: SampleBehavior }),
		Content(null, { name: "thirdContent", Behavior: SampleBehavior }),
	],
	Behavior: class extends Behavior {
		onDisplaying(container) {
			container.lastThat("sampleEvent");	// "thirdContent triggered" will be traced here
		}
	}
});
application.add(sampleContainer);

remove(content)

ArgumentTypeDescription
contentcontentThe content object to remove. Its container must be this container.

Removes the specified content object from this container

let ColoredSquare = Content.template($ => ({
	height: 100, width: 100,
	skin: new Skin({ fill: $ })
}));

let redSquare = new ColoredSquare("red");
let blueSquare = new ColoredSquare("blue");

let sampleContainer = new Container(null, {
	top: 0, bottom: 0, left: 0, right: 0,
	skin: new Skin({ fill: "white" }),
	contents: [
		redSquare,
		blueSquare,
	],
});
sampleContainer.remove(redSquare);
application.add(sampleContainer);


replace(content, by)

ArgumentTypeDescription
contentcontentThe content object to replace. Its container must be this container.
bycontentThe replacing content object. It must be unbound; that is, its container must be null.

Replaces one content object with another in this container as specified by the parameters

let ColoredSquare = Content.template($ => ({
	height: 100, width: 100,
	skin: new Skin({ fill: $ })
}));

let redSquare = new ColoredSquare("red");
let blueSquare = new ColoredSquare("blue");

let sampleContainer = new Container(null, {
	top: 0, bottom: 0, left: 0, right: 0,
	skin: new Skin({ fill: "white" }),
	contents: [
		blueSquare,
	],
});
sampleContainer.replace(blueSquare, redSquare);
application.add(sampleContainer);


run(transition [, ...])

ArgumentTypeDescription
transitiontransitionThe transition object to run
...*Zero or more extra parameters

Runs the specified transition object in this container, binding that object to this container for the duration of the transition. The extra parameters are passed to the onBegin and onEnd functions of the transition object. The container triggers the onTransitionBeginning event before the transition starts and the onTransitionEnded event after the transition ends.

import CombTransition from "piu/CombTransition";
class SwitchScreenBehavior extends Behavior {
	onCreate(content, data) {
		this.data = data;
	}
	onTouchEnded(content) {
		let data = this.data;
		let transition = new CombTransition(250, Math.quadEaseOut, "horizontal", 4);
		let nextScreen = new ColoredScreen({ color: data.nextColor, nextColor: data.color })
		application.run(transition, application.first, nextScreen);
	}
}
let ColoredScreen = Container.template($ => ({
	top: 0, bottom: 0, left: 0, right: 0,
	skin: new Skin({ fill: $.color }),
	contents: [
		Content($, {
			active: true, height: 100, width: 100,
			skin: new Skin({ fill: $.nextColor }),
			Behavior: SwitchScreenBehavior
		})
	]
}));
application.add(new ColoredScreen({ color: "red", nextColor: "blue" }));


swap(content0, content1)

ArgumentTypeDescription
content0, content1contentThe content objects to swap. The container of both objects must be this container.

Swaps the specified content objects in this container

let ColoredSquare = Content.template($ => ({
    height: 100, width: 100,
    skin: new Skin({ fill: $ })
}));

let sampleContainer = new Container(null, {
    active: true, top: 0, bottom: 0, left: 0, right: 0,
    skin: new Skin({ fill: "white" }),
    contents: [
        new ColoredSquare("blue", { top: 0, left:0 }),
        new ColoredSquare("red", { top: 50, left:50 }),
    ],
    Behavior: class extends Behavior {
    	onTouchEnded(container) {
    		container.swap(container.first, container.last);
    	}
    }
});
application.add(sampleContainer);


Events

Same as for content object (see Events in the section Content Object), plus:

onTransitionBeginning(container)

ArgumentTypeDescription
containercontainerThe container object that triggered the event

This event is triggered when a transition object starts in the specified container object.


onTransitionEnded(container)

ArgumentTypeDescription
containercontainerThe container object that triggered the event

This event is triggered when a transition object ends in the specified container object.


Content Object

Applications use content objects for graphical parts of their user interface, such as buttons, icons, sliders, switches, and tabs.

Constructor Description

Content([behaviorData, dictionary])
ArgumentTypeDescription
behaviorData*A parameter that is passed into the onCreate function of this content's behavior. This may be any type of object, including null or a dictionary with arbitrary parameters.
dictionaryobjectAn object with properties to initialize the result. Only parameters specified in the Dictionary section below will have an effect; other parameters will be ignored.

Returns a content instance, an object that inherits from Content.prototype

let sampleContent = new Content("Hello", {
	top: 0, right: 50, height: 100, width: 100,
	skin: new Skin({fill: "blue"}),
	Behavior: class extends Behavior {
		onCreate(content, data) {
			trace(`${data}\n`);		// Prints "Hello" to console
		}
	}
})
application.add(sampleContent);

Content.template(anonymous)
ArgumentsTypeDescription
anonymousfunctionA function that returns an object with properties to initialize the instances that the result creates

Returns a constructor, a function that creates instances of Content.prototype. The prototype property of the result is Content.prototype. The result also provides a template function.

let SampleContent = Content.template($ => ({
	height: 100, width: 100,
	skin: new Skin({fill: $.color}),
	Behavior: class extends Behavior {
		onCreate(content, data) {
			trace(`This box is ${data.color}\n`);		// Prints "This box is red" to console
		}
	}
}));
application.add(new SampleContent({color: "red"}, {top: 0, right: 50}));
application.add(new SampleContent({color: "blue"}));

Dictionary

ParameterTypeDescription
activebooleanIf true, this content can be touched; that is, it triggers touch events.
anchorstringCreates an anchor, a reference to the created content object in the instantiating data
backgroundTouch booleanIf true, this container receives any touch events that are received by its contents; that is, it will trigger touch events when one of its contents has been touched.
BehaviorfunctionA function that creates instances of Behavior.prototype; generally a class that extends the Behavior class. This content will create an instance of this behavior, set its behavior parameter to the created instance, and trigger the onCreate method.
bottomnumberThis content's bottom coordinate, in pixels (setting bottom in the created instance's coordinates property)
durationnumberThis content's duration, in milliseconds. This content triggers the onFinished event when its clock is running and its time equals its duration.
exclusiveTouchbooleanIf true, this content always captures touches; that is, captureTouch is implicitly invoked on onTouchDown for this content. Setting exclusiveTouch to true is equivalent to calling captureTouch in response to the onTouchDown event for every touch id.
fractionnumberThis content's fraction--that is, the ratio of its time to its duration
heightnumberThis content's height, in pixels (setting height in the created instance's coordinates property)
intervalnumberThe time between ticks of this content's clock--that is, number of milliseconds between triggering the onTimeChanged events of the content's behavior when its clock is running.
leftnumberThis content's left coordinate, in pixels (setting left in the created instance's coordinates property)
loopbooleanIf true, this content will restart its clock when its time equals its duration
multipleTouchbooleanIf true, this content handles multiple touches.
namestringThis content's name
rightnumberThis content's right coordinate, in pixels (setting right in the created instance's coordinates property)
skinskinThis content's skin
SkinfunctionA function that creates instances of Skin.prototype. This content will create an instance of this skin, and set its skin parameter to the created instance.
statenumberThis content's state. If this content's skin defines states, setting the state changes the appearance of this content.
stylestyleThis content's style
StylefunctionA function that creates instances of Style.prototype. This content will create an instance of this style, and set its style parameter to the created instance.
timenumberThis content's time, in milliseconds. When its time is set, this content triggers the onTimeChanged event.
topnumberThis content's top coordinate, in pixels (setting top in the created instance's coordinates property)
variantnumberThis content's variant. If this content's skin defines variants, setting the variant changes the appearance of this content.
visiblebooleanIf true, this content is visible.
widthnumberThis content's width, in pixels (setting width in the created instance's coordinates property)

Prototype Description

Prototype inherits from Object.prototype.

Properties
NameTypeDefault ValueRead OnlyDescription
activebooleanfalseIf true, this content can be touched; that is, it triggers touch events.
anchorstringThe identifier of the property that references this content object in its instantiating data
backgroundTouch booleanfalseIf true, this container receives any touch events that are received by its contents; that is, it will trigger touch events when one of its contents has been touched.
behaviorobjectnullThis content's behavior object or null. When this content triggers an event, it calls the corresponding function property of its behavior, if any.
boundsobjectThis content's global position and size, as an object with x, y, width, and height number properties, specified in pixels. If this content is unbound, the getter returns undefined and the setter is ignored.
containerobjectThis content's container, or null if this content is unbound--that is, if it has no container
coordinatesobjectThis content's coordinates, as an object with left, width, right, top, height, or bottom number properties (specified in pixels), or an empty object if no coordinates are passed into the constructor
durationnumber0This content's duration, in milliseconds. This content triggers the onFinished event when its clock is running and its time equals its duration.
exclusiveTouchbooleanfalseIf true, this content always captures touches; that is, captureTouch is implicitly invoked on onTouchDown for this content. Setting exclusiveTouch to true is equivalent to calling captureTouch in response to the onTouchDown event for every touch id.
fractionnumberundefinedThis content's fraction--that is, the ratio of its time to its duration. If the duration is 0, the getter returns undefined and the setter is ignored. This content triggers the onTimeChanged event when its fraction is set.
heightnumberThis content's height, in pixels
indexnumberThe index of this content in its container, or –1 if this content is unbound
intervalnumber1The time between ticks of this content's clock--that is, number of milliseconds between triggering the onTimeChanged events of the content's behavior when its clock is running.
loopbooleanfalseIf true, this content will restart its clock when its time equals its duration
multipleTouchbooleanfalseIf true, this content handles multiple touches.
namestringThis content's name
nextobjectThe next content object of this content's container; null if this content is the last content object of this content's container or if this content has no container
offsetobjectThis content's local position, as an object with x and y number properties, specified in pixels. If this content is unbound, the getter returns undefined and the setter is ignored.
positionobjectThis content's global position, as an object with x and y number properties, specified in pixels. If this content is unbound, the getter returns undefined and the setter is ignored.
previousobjectThe previous content object in this content's container; null if this content is the first content object of this content's container or if this content has no container
runningbooleanIf true, this content's clock is running.
sizeobjectThis content's size, as an object with width and height number properties, specified in pixels
skinskinnullThis content's skin or null
statenumber0This content's state. If this content's skin defines states, setting the state changes the appearance of this content.
stylestylenullThis content's style or null
timenumber0This content's time, in milliseconds. When its time is set, this content triggers the onTimeChanged event.
variantnumber0This content's variant. If this content's skin defines variants, setting the variant changes the appearance of this content.
visiblebooleantrueIf true, this content is visible.
widthnumberThis content's width, in pixels
xnumberThis content's global x position. If this content is unbound, the getters return undefined and the setters are ignored.
ynumberThis content's global y position. If this content is unbound, the getters return undefined and the setters are ignored.

Functions

bubble(id [, ...])

ArgumentTypeDescription
idstringThe name of the event to trigger
...*Zero or more extra parameters

Causes this content and all container objects upward in the containment hierarchy to trigger an event named by the value of id. The bubbling halts when a bubbled event returns true. Note that the first parameter of a bubbled event is the container object that triggers the event, not this content. Additional parameters, if any, of a bubbled event are the extra parameters of the bubble function.

let NamedContainer = Container.template($ => ({
	name: $.name, active: true, top: 20, bottom: 20, left: 20, right: 20,
	skin: new Skin({ fill: $.color }),
	Behavior: class extends Behavior {
		printName(container) {
			trace(`${container.name} triggered\n`);
		}
		onTouchEnded(container) {
			trace("\n");
			container.bubble("printName");
		}
	}
}));
let outerContainer = new NamedContainer({ name: "outerContainer", color: "red" });
let middleContainer = new NamedContainer({ name: "middleContainer", color: "blue" });
let innerContainer = new NamedContainer({ name: "innerContainer", color: "black" });
outerContainer.add(middleContainer);
middleContainer.add(innerContainer);
application.add(outerContainer);


captureTouch(id, x, y, ticks)

ArgumentTypeDescription
idnumberThe identifier of the touch
x, ynumberThe global position of the touch, in pixels
ticksnumberThe global time of the touch

Causes this content to capture the touch named id, meaning that only this content will trigger the remaining onTouchMoved and onTouchEnded events related to that touch. Other content objects concerned with the captured touch trigger the onTouchCancelled event when the captureTouch function is called.

class BlueBehavior extends Behavior {
    onTouchBegan(content, id, x, y, ticks) {
    	trace("Blue touch began\n");
        content.captureTouch(id, x, y, ticks);		// With this line, the redContainer behavior's onTouchCancelled method is called; without this line, its onTouchBegan and onTouchEnded methods would be called
    }
    onTouchEnded(content, id, x, y, ticks) {
    	trace("Blue touch ended\n");
    }
}
let blueCapturingContent = new Content(null, {
    active: true, top: 25, left: 25, height: 50, width: 50,
    skin: new Skin({fill: "blue"}),
    Behavior: BlueBehavior
});

class RedBehavior extends Behavior {
    onTouchBegan(content, id, x, y, ticks) {
        trace("Red touch began\n");
    }
    onTouchCancelled(content) {
    	trace("Red touch cancelled\n");
    }
    onTouchEnded(content, id, x, y, ticks) {
    	trace("Red touch ended\n");
    }
}
let redContainer = new Container(null, {
    active: true, backgroundTouch: true,
    top: 0, left: 0, height: 100, width: 100,
    skin: new Skin({fill: "red"}),
    contents: [
    	blueCapturingContent
    ],
    Behavior: RedBehavior
});

application.add(redContainer);


defer(id [, ...])

ArgumentTypeDescription
idstringThe name of the event to trigger
...*Zero or more extra parameters

The defer function is similar to the delegate function; both cause this content to trigger an event named by the value of id. The difference is in their timing. The delegate function sends the event immediately while the defer functions posts the event. The event will be triggered at the following iteration of the main event loop.

The first parameter of the deferred event is this content. Additional parameters, if any, of the deferred event are the extra parameters of the defer function.


delegate(id [, ...])

ArgumentTypeDescription
idstringThe name of the event to trigger
...*Zero or more extra parameters

Causes this content to trigger an event named by the value of id. The first parameter of the delegated event is this content. Additional parameters, if any, of the delegated event are the extra parameters of the delegate function.

let NamedContainer = Container.template($ => ({
	name: $.name, active: true, top: 20, bottom: 20, left: 20, right: 20,
	skin: new Skin({ fill: $.color }),
	Behavior: class extends Behavior {
		printName(container) {
			trace(`${container.name} triggered\n`);
		}
		onTouchEnded(container) {
			trace("\n");
			container.delegate("printName");
		}
	}
}));
let outerContainer = new NamedContainer({ name: "outerContainer", color: "blue" });
let middleContainer = new NamedContainer({ name: "middleContainer", color: "black" });
let innerContainer = new NamedContainer({ name: "innerContainer", color: "red" });
outerContainer.add(middleContainer);
middleContainer.add(innerContainer);
application.add(outerContainer);


focus()

Focuses this content so that it triggers keyboard events. Only one content object at a time is focused.


distribute(id [, ...])

ArgumentTypeDescription
idstringThe name of the event
...*

Causes this container and all content objects downward in the containment hierarchy to trigger an event named by the value of id. The order of traversal is depth first. Traversal halts when one of the triggered event-handling functions returns true. Note that the first parameter of a distributed event is the content object that triggers the event, not this container. Additional parameters, if any, of the event are the extra parameters of the distribute function.

let NamedContainer = Container.template($ => ({
	name: $.name, active: true, top: 20, bottom: 20, left: 20, right: 20,
	skin: new Skin({ fill: $.color }),
	Behavior: class extends Behavior {
		printName(container) {
			trace(`${container.name} triggered\n`);
		}
		onTouchEnded(container) {
			trace("\n");
			container.distribute("printName");
		}
	}
}));
let outerContainer = new NamedContainer({ name: "outerContainer", color: "red" });
let middleContainer = new NamedContainer({ name: "middleContainer", color: "blue" });
let innerContainer = new NamedContainer({ name: "innerContainer", color: "black" });
outerContainer.add(middleContainer);
middleContainer.add(innerContainer);
application.add(outerContainer);


hit(x, y)

ArgumentTypeDescription
x, ynumberThe global position to test, in pixels

Returns this content if this content is active, bound, and contains the position, and undefined otherwise. If this content is a container instance, returns either one of its contents or itself if the content or itself is active, bound, and contains the position, or undefined.

Note that this function should only be used after a content has been measured and fitted; otherwise it will always return undefined.

let sampleContent = new Content(null, {
    active: true, top: 0, left: 0, height: 100, width: 100,
    skin: new Skin({fill: "blue"}),
    Behavior: class extends Behavior {
        onDisplaying(content) {
			let x = content == content.hit(10, 10);		// true
			let y = content.hit(200, 200);			// undefined
        }
    }
});

measure()

Returns the measured size of this content, as an object with width and height parameters.

Example 1:

let sampleContent = new Content(null, {
    top: 0, left: 0, height: 100, width: 100,
    skin: new Skin({fill: "blue"})
});
application.add(sampleContent);

let measuredSize = sampleContent.measure(); 	// {height: 100, width: 100}
let fittedHeight = sampleContent.height;		// 100
let fittedWidth = sampleContent.width;			// 100

Example 2:

let sampleContent = new Content(null, {
    top: 0, bottom: 0, left: 0, right: 0,
    skin: new Skin({fill: "blue"})
});
application.add(sampleContent);

let measuredSize = sampleContent.measure(); 	// {height: 0, width: 0}
let fittedHeight = sampleContent.height;		// 320 (assuming running on 240x320 screen)
let fittedWidth = sampleContent.width;			// 240 (assuming running on 240x320 screen)

moveBy(x, y)

ArgumentTypeDescription
x, ynumberThe deltas by which to move this content, in pixels

Moves this content as specified by the parameters. If the content's coordinates constrain its position, the moveBy function ignores the corresponding horizontal or vertical deltas.

let unconstrainedContent = new Content(null, {
    top: 0, left: 0, height: 100, width: 100,
    skin: new Skin({fill: "blue"}),
});
application.add(unconstrainedContent);
unconstrainedContent.moveBy(100,100);	// Moves unconstrainedContent 100 pixels in the x and y directions

let constrainedContent = new Content(null, {
    top: 0, left: 0, bottom: 140, right: 220,
    skin: new Skin({fill: "red"}),
});
application.add(constrainedContent);
constrainedContent.moveBy(100,100);	// Does nothing


sizeBy(width, height)

ArgumentTypeDescription
width, heightnumberThe deltas by which to size this content, in pixels

Sizes this content as specified by the parameters. If this content's coordinates constrain its size, the sizeBy function ignores the corresponding horizontal or vertical deltas.

let unconstrainedContent = new Content(null, {
    top: 0, left: 0, height: 100, width: 100,
    skin: new Skin({fill: "blue"}),
})
application.add(unconstrainedContent);
unconstrainedContent.sizeBy(100,100);	// Makes unconstrainedContent 100 pixels wider and taller

let constrainedContent = new Content(null, {
    top: 0, left: 0, bottom: 140, right: 220,
    skin: new Skin({fill: "red"}),
})
application.add(constrainedContent);
constrainedContent.sizeBy(100,100);	// Does nothing


start()

Starts this content's clock

class SampleBehavior extends Behavior {
	onDisplaying(content) {
		this.index = 0;
		content.interval = 750;
		content.time = 0;
		content.start();
	}
	onTimeChanged(content) {
		let state = content.state + 1;
		if (state > 3) state = 0;
		content.state = state;
	}
}
let sampleContent = new Content(null, {
	height: 100, width: 100,
	skin: new Skin({fill: ["red", "orange", "yellow", "green"]}),
	Behavior: SampleBehavior
});
application.add(sampleContent);


stop()

Stops this content's clock

class SampleBehavior extends Behavior {
	onDisplaying(content) {
		this.index = 0;
		content.interval = 750;
		content.time = 0;
		content.start();
	}
	onTimeChanged(content) {
		content.state = !content.state;
	}
	onTouchBegan(content) {
		content.stop();
	}
	onTouchEnded(content) {
		content.start();
	}
}
let sampleContent = new Content(null, {
	active: true, height: 100, width: 100,
	skin: new Skin({ fill: ["blue", "white"]}),
	Behavior: SampleBehavior
});
application.add(sampleContent);

Events

The following standard events are triggered by content objects.

onCreate(content, data, context)

ArgumentTypeDescription
contentcontentThe content object that triggered the event
data, context objectThe parameters of the constructor of the content object that references or contains the behavior

This event is triggered when the content is constructed.


onDisplaying(content)

ArgumentTypeDescription
contentcontentThe content object that triggered the event

This event is triggered after the specified content object is added to the containment hierarchy and has been measured and fitted, but before it is visible to the user. This is the first event the object receives after its coordinates have been computed.


onFinished(content)

ArgumentTypeDescription
contentcontentThe content object that triggered the event

This event is triggered when the specified content object is running and its time equals its duration.


onTimeChanged(content)

ArgumentTypeDescription
contentcontentThe content object that triggered the event

This event is triggered when the time of the specified content object changes.


onTouchBegan(content, id, x, y, ticks)

onTouchCancelled(content, id)

onTouchEnded(content, id, x, y, ticks)

onTouchMoved(content, id, x, y, ticks)

ArgumentTypeDescription
contentcontentThe content object that triggered the event
idnumberThe identifier of the touch
x, ynumberThe global coordinates of the event, in pixels
ticksnumberThe global time of the event

These events are triggered when the specified content object is active and touched.

Die Object

The die object is a layout object that allows you to “die cut” its contents with a region, minimizing the areas to invalidate and to update. These are useful for building animations and transitions on constrained devices that cannot update every screen pixel at every frame.

The die object maintains two regions:

  • the work region that the available operations build,
  • the clip region that clips the contents of the die object

Both regions are initially empty.

Constructor Description

Die([behaviorData, dictionary])
ArgumentTypeDescription
behaviorData*A parameter that is passed into the onCreate function of this die's behavior. This may be any type of object, including null or a dictionary with arbitrary parameters.
dictionaryobjectAn object with properties to initialize the result. The dictionary is the same as for the content object. Only parameters specified in the Dictionary section of the Content Object will have an effect; other parameters will be ignored.

Returns a die instance, an object that inherits from Die.prototype.

let sampleDie = new Die(null, {
    left:0, right:0, top:0, bottom:0,
    Behavior: class extends Behavior {
        onDisplaying(die) {
            die.or(40, 40, die.width-80, die.height-80)
                .cut();
        }
    },
    contents: [
        new Content(null, {
            left:0, right:0, top:0, bottom:0,
            skin: new Skin({ fill: "white" }),
        }),
    ]
});

let sampleScreenWithDie = new Container(null, {
    left:0, right:0, top:0, bottom:0,
    contents: [
    	Content(null, {
    		top: 0, bottom: 120, left: 0, right: 0,
    		skin: new Skin({ fill: "blue" }),
    	}),
    	Content(null, {
    		top: 120, bottom: 0, left: 0, right: 0,
    		skin: new Skin({ fill: "black" }),
    	}),
    	sampleDie
    ]
});
application.add(sampleScreenWithDie);

Die.template(anonymous)
ArgumentsTypeDescription
anonymousfunctionA function that returns an object with properties to initialize the instances that the result creates

Returns a constructor, a function that creates instances of Die.prototype. The prototype property of the result is Die.prototype. The result also provides a template function.

let SampleDie = Die.template($ => ({
    left:0, right:0, top:0, bottom:0,
    Behavior: class extends Behavior {
        onDisplaying(die) {
            die.or(40, 40, die.width-80, die.height-80)
                .cut();
        }
    },
    contents: [
        new Content(null, {
            left:0, right:0, top:0, bottom:0,
            skin: new Skin({ fill: "white" }),
        }),
    ]
}));

let sampleScreenWithDie = new Container(null, {
    left:0, right:0, top:0, bottom:0,
    contents: [
    	Content(null, {
    		top: 0, bottom: 0, left: 0, right: 0,
    		skin: new Skin({ fill: "blue" }),
    	}),
    	Row(null, {
    		top: 0, bottom: 0, left: 0, right: 0,
    		contents: [
    			SampleDie(),
    			SampleDie(),
    		]
    	})
    ]
});
application.add(sampleScreenWithDie);

Prototype Description

Prototype inherits from Layout.prototype.

Functions

Same as for layout object (see Functions in the section Layout Object), plus:

and(x, y, width, height)

ArgumentTypeDescription
x, y, width, heightnumberA local rectangle, in pixels

Intersects the rectangle with the work region and returns this.

let sampleContainer = new Container(null, {
    left:0, right:0, top:0, bottom:0, skin: new Skin({ fill: "blue" }),
    contents: [
        Die($, {
            left:0, right:0, top:0, bottom:0,
            Behavior: class extends Behavior {
                onDisplaying(die) {
                    die.fill()
                    	.and(10, 10, 50, 50)
                    	.cut();
                }
            },
            contents: [
                new Content(null, {
                	left:0, right:0, top:0, bottom:0,
                	skin: new Skin({ fill: "white" }),
                }),
            ]
        }),
    ]
});
application.add(sampleContainer);


attach(content)

ArgumentTypeDescription
contentcontentThe content object to attach

Binds the die object to the containment hierarchy by replacing the specified content object in the content's container with this die object and adding the content object to this die object.

let whiteScreen = new Content(null, {
	left:0, right:0, top:0, bottom:0,
	skin: new Skin({ fill: "white" }),
    Behavior: class extends Behavior {
    	onDisplaying(content) {
    		application.insert(blueScreen, content);
    		let die = this.die = new Die();
    		die.attach(content);
    		die.or(0, 0, die.width, die.height/4)
    		die.or(0, die.height/2, die.width, die.height/4)
    			.cut();
    	}
    }
});
let blueScreen = new Content(null, {
	left:0, right:0, top:0, bottom:0,
	skin: new Skin({ fill: "blue" }),
});
application.add(whiteScreen);


cut()

Copies the work region into the current region, and invalidates only the difference between the work and the clip regions.


detach()

Unbind this die object from the content hierarchy by removing the first content object from this die object and replacing this die object in its container with the removed content object.

let whiteScreen = new Content(null, {
	active: true, left:0, right:0, top:0, bottom:0,
	skin: new Skin({ fill: "white" }),
	Behavior: class extends Behavior {
    	onTouchBegan(content) {
    		application.add(blueScreen);
    		let die = this.die = new Die();
    		die.attach(blueScreen);
    		die.or(0, 0, die.width, die.height/4)
    		die.or(0, die.height/2, die.width, die.height/4)
    			.cut();
    	}
    	onTouchEnded(content) {
    		let die = this.die;
    		die.detach();
    		application.remove(blueScreen)
    	}
	}
});
let blueScreen = new Content(null, {
	active: true, left:0, right:0, top:0, bottom:0,
	skin: new Skin({ fill: "blue" }),
});
application.add(whiteScreen);


empty()

Empties the work region and returns this.


fill()

Sets the work region to the bounds of this die object and returns this.


or(x, y, width, height)

ArgumentTypeDescription
x, y, width, heightnumberA local rectangle, in pixels

Inclusively unions the rectangle with the work region and returns this.

let sampleContainer = new Container(null, {
    left:0, right:0, top:0, bottom:0, skin: new Skin({ fill: "red" }),
    contents: [
        Die($, {
            left:0, right:0, top:0, bottom:0,
            Behavior: class extends Behavior {
                onDisplaying(die) {
                    die.or(10, 10, 50, 50)
                    die.or(80, 80, 100, 100)
                    	.cut();
                }
            },
            contents: [
                new Content(null, {
                	left:0, right:0, top:0, bottom:0,
                	skin: new Skin({ fill: "white" }),
                }),
            ]
        }),
    ]
});
application.add(sampleContainer);


set(x, y, width, height)

ArgumentTypeDescription
x, y, width, heightnumberA local rectangle, in pixels

Sets the work region to the rectangle and returns this.

let sampleContainer = new Container(null, {
    left:0, right:0, top:0, bottom:0, skin: new Skin({ fill: "blue" }),
    contents: [
        Die($, {
            left:0, right:0, top:0, bottom:0,
            Behavior: class extends Behavior {
                onDisplaying(die) {
                    die.set(50, 50, 220, 140)
                    	.cut();
                }
            },
            contents: [
                new Content(null, {
                	left:0, right:0, top:0, bottom:0,
                	skin: new Skin({ fill: "white" }),
                }),
            ]
        }),
    ]
});
application.add(sampleContainer);


sub(x, y, width, height)

ArgumentTypeDescription
x, y, width, heightnumberA local rectangle, in pixels

Subtracts the rectangle from the work region and returns this.

let sampleContainer = new Container(null, {
    left:0, right:0, top:0, bottom:0, skin: new Skin({ fill: "blue" }),
    contents: [
        Die($, {
            left:0, right:0, top:0, bottom:0,
            Behavior: class extends Behavior {
                onDisplaying(die) {
                    die.fill()
                    	.sub(0, 0, 50, 50)
                    	.sub(100, 0, 50, 50)
                    	.sub(200, 0, 50, 50)
                    	.cut();
                }
            },
            contents: [
                new Content(null, {
                	left:0, right:0, top:0, bottom:0,
                	skin: new Skin({ fill: "white" }),
                }),
            ]
        }),
    ]
});
application.add(sampleContainer);


xor(x, y, width, height)

ArgumentTypeDescription
x, y, width, heightnumberA local rectangle, in pixels

Exclusively unions the work region with the rectangle and returns this.

let sampleContainer = new Container(null, {
    left:0, right:0, top:0, bottom:0, skin: new Skin({ fill: "blue" }),
    contents: [
        Die($, {
            left:0, right:0, top:0, bottom:0,
            Behavior: class extends Behavior {
                onDisplaying(die) {
                    die.set(0, 0, die.width/2, die.height)
                    	.xor(50, 50, die.width-100, die.height-100)
                    	.cut();
                }
            },
            contents: [
                new Content(null, {
                	left:0, right:0, top:0, bottom:0,
                	skin: new Skin({ fill: "white" }),
                }),
            ]
        }),
    ]
});
application.add(sampleContainer);

Image Object

The image object is a content object that displays images.

Image assets may be a GIF, JPEG, or PNG file, or a folder of JPEG and PNG files. The images example provides an example for every supported type.

Assets must be defined in the resources of your manifest. The quality of JPEG and PNG files can be set to a value between 1 and 100; higher numbers correspond to higher quality.

"resources":{
	"*-image(100)": [
		"$(MODDABLE)/examples/assets/images/screen1",
	],
	"*-image(40)": [
		"$(MODDABLE)/examples/assets/images/screen2",
	]
},

Images in a folder are used as frames of a single animated image. The frame rate is determined by the name of the folder. For example, the fish.15fps folder from the example images folder tells the application to run at 15 frames per second. In the manifest, the .15fps is dropped from the path.

"resources":{
	"*-image": [
		"$(MODDABLE)/examples/assets/images/fish",
	],
}

The frame rate of a GIF is set in the file itself and cannot be changed by the application.

All supported image types are compressed into a single resource with a .cs extension. These are the files that should be referenced in the application's script code. For example, to create image objects using the assets mentioned above, the application would use the paths "screen1.cs", "screen2.cs", and "street.cs".

Constructor Description

Image([behaviorData, dictionary])
ArgumentTypeDescription
behaviorData*A parameter that is passed into the onCreate function of this image's behavior. This may be any type of object, including null or a dictionary with arbitrary parameters.
dictionaryobjectAn object with properties to initialize the result. Only parameters specified in the Dictionary section below will have an effect; other parameters will be ignored.

Returns an image instance, an object that inherits from Image.prototype

let sampleImage = new Image(null, ({
	path: "screen1.cs"
}));
application.add(sampleImage);

This example uses screen1.png from the example images folder

Image.template(anonymous)
ArgumentsTypeDescription
anonymousfunctionA function that returns an object with properties to initialize the instances that the result creates

Returns a constructor, a function that creates instances of Image.prototype. The prototype property of the result is Image.prototype. The result also provides a template function.

class ImageBehavior extends Behavior {
	onDisplaying(image) {
		image.start();
	}
}
let SampleImage = Image.template($ => ({
	path: $, loop: true, Behavior:ImageBehavior,
}));
application.add(new SampleImage("street.cs"));

This example uses street.gif from the example images folder

Dictionary

Same as for content object (see Dictionary in the section Content Object), plus:

ParameterTypeDescription
pathstringThe URL of the image file. It must be a file URL.

Prototype Description

Prototype inherits from Content.prototype.

Properties
NameTypeDefault ValueRead OnlyDescription
frameCount numberThe total number of frames in this image
frameIndex numberThe index of the current frame

Label Object

The label object is a content object that renders a string on a single line with a single style. The string is truncated if it does not fit the bounds of the label object.

Constructor Description

Label([behaviorData, dictionary])
ArgumentTypeDescription
behaviorData*A parameter that is passed into the onCreate function of this label's behavior. This may be any type of object, including null or a dictionary with arbitrary parameters.
dictionaryobjectAn object with properties to initialize the result. Only parameters specified in the Dictionary section below will have an effect; other parameters will be ignored.

Returns a label instance, an object that inherits from Label.prototype

let sampleStyle = new Style({ font:"600 28px Open Sans", color: "blue" });
let sampleLabel = new Label(null, {
	top: 0, bottom: 0, left: 0, right: 0,
	skin: new Skin({ fill: "white" }),
	style: sampleStyle, string: "Hello, World!"
});
application.add(sampleLabel)

Label.template(anonymous)
ArgumentsTypeDescription
anonymousfunctionA function that returns an object with properties to initialize the instances that the result creates

Returns a constructor, a function that creates instances of Label.prototype. The prototype property of the result is Label.prototype. The result also provides a template function.

let blueStyle = new Style({ font:"600 28px Open Sans", color: "blue" });
let redStyle = new Style({ font:"600 28px Open Sans", color: "red" });
let SampleLabel = Label.template($ => ({
	style: $.style, string: $.string,
	skin: new Skin({ fill: "white" }),
}));
application.add(new SampleLabel({ string: "Hello, World!", style: blueStyle }, { top: 0, left: 0 }));
application.add(new SampleLabel({ string: "Hello, World!", style: redStyle }, { bottom: 0, right: 0 }));

Dictionary

Same as for content object (see Dictionary in the section Content Object), plus:

ParameterTypeDescription
stringstringThis label's string

Prototype Description

Prototype inherits from Content.prototype.

Properties
NameTypeDefault ValueRead OnlyDescription
stringstringThis label's string

Layout Object

The layout object is a container object that delegates positioning and sizing of its contents to a script in its behavior.

When its width is measured, the layout object triggers the onMeasureHorizontally event, and the behavior can modify the measured width of the layout object or the coordinates of its contents.

When its height is measured, the layout object triggers the onMeasureVertically event, and the behavior can modify the measured height of the layout object or the coordinates of its contents.

Constructor Description

Layout([behaviorData, dictionary])
ArgumentTypeDescription
behaviorData*A parameter that is passed into the onCreate function of this layout's behavior. This may be any type of object, including null or a dictionary with arbitrary parameters.
dictionaryobjectAn object with properties to initialize the result. The dictionary is the same as for the content object. Only parameters specified in the Dictionary section of the Content Object will have an effect; other parameters will be ignored.

Returns a layout instance, an object that inherits from Layout.prototype/

let ColoredSquare = Content.template($ => ({
	height: 0, width: 0,
	skin: new Skin({ fill: $ }),
}));

let sampleLayout = new Layout(null, {
	height: application.height, width: application.width,
	skin: new Skin({fill: "black"}),
	contents: [
		new ColoredSquare("red", {top: 0, left: 0}),
		new ColoredSquare("yellow", {top: 0, right: 0}),
		new ColoredSquare("green", {bottom: 0, left: 0}),
		new ColoredSquare("blue", {bottom: 0, right: 0}),
	],
	Behavior: class extends Behavior {
		onMeasureHorizontally(layout, width) {
			let squareWidth = width/2;
			let square = layout.first;
			while (square) {
				square.sizeBy(squareWidth, 0);
				square = square.next;
			}
			return width;
		}
		onMeasureVertically(layout, height) {
			let squareHeight = height/2;
			let square = layout.first;
			while (square) {
				square.sizeBy(0, squareHeight);
				square = square.next;
			}
			return height;
		}
	}
});
application.add(sampleLayout);

Layout.template(anonymous)
ArgumentsTypeDescription
anonymousfunctionA function that returns an object with properties to initialize the instances that the result creates

Returns a constructor, a function that creates instances of Layout.prototype. The prototype property of the result is Layout.prototype. The result also provides a template function.

let ColoredSquare = Content.template($ => ({
	height: 0, width: 0,
	skin: new Skin({ fill: $ }),
}));

let SampleLayout = Layout.template($ => ({
	contents: [
		new ColoredSquare("red", {top: 0, left: 0}),
		new ColoredSquare("yellow", {top: 0, right: 0}),
		new ColoredSquare("green", {bottom: 0, left: 0}),
		new ColoredSquare("blue", {bottom: 0, right: 0}),
	],
	Behavior: class extends Behavior {
		onMeasureHorizontally(layout, width) {
			let squareWidth = width/2;
			let square = layout.first;
			while (square) {
				square.sizeBy(squareWidth, 0);
				square = square.next;
			}
			return width;
		}
		onMeasureVertically(layout, height) {
			let squareHeight = height/2;
			let square = layout.first;
			while (square) {
				square.sizeBy(0, squareHeight);
				square = square.next;
			}
			return height;
		}
	}
}));
application.add(new SampleLayout(null, {top: 0, width: 100, left: 0, height: 100}));
application.add(new SampleLayout(null, {bottom: 0, width: 200, right: 0, height: 100}));

Prototype Description

Prototype inherits from Container.prototype.

Events

Same as for container object (see Events in the section Container Object), plus:

onFitHorizontally(layout, width)

ArgumentTypeDescription
layoutobjectThe layout object that triggered the event
widthnumberThe fitted width of the layout object, in pixels

This event is triggered when the fitted width of the layout object is calculated. Once this is triggered, the behavior can modify the coordinates of its contents. Returns the fitted width of the layout object, in pixels.


onFitVertically(layout, height)

ArgumentTypeDescription
layoutobjectThe layout object that triggered the event
heightnumberThe fitted height of the layout object, in pixels

This event is triggered when the fitted height of the layout object is calculated. Once this is triggered, the behavior can modify the coordinates of its contents. Returns the height of the layout object, in pixels.


onMeasureHorizontally(layout, width)

ArgumentTypeDescription
layoutobjectThe layout object that triggered the event
widthnumberThe measured width of the layout object, in pixels

This event is triggered when the measured width of the layout object is calculated. Returns the measured width of the layout object, in pixels.


onMeasureVertically(layout, height)

ArgumentTypeDescription
layoutobjectThe layout object that triggered the event
heightnumberThe measured height of the layout object, in pixels

This event is triggered when the measured height of the layout object is calculated. Returns the measured height of the layout object, in pixels.


Port Object

The port object is a content object that delegates drawing to a script in its behavior that draws using simple Piu graphics commands.

The port object has a clip rectangle (initially the bounds of the port object) that affects all drawing.

Constructor Description

Port([behaviorData, dictionary])
ArgumentTypeDescription
behaviorData*A parameter that is passed into the onCreate function of this content's behavior. This may be any type of object, including null or a dictionary with arbitrary parameters.
dictionaryobjectAn object with properties to initialize the result. The dictionary is the same as for the content object. Only parameters specified in the Dictionary section of the Content Object will have an effect; other parameters will be ignored.

Returns a port instance, an object that inherits from Port.prototype

let samplePort = new Port(null, {
	top: 0, bottom: 0, left: 0, right: 0,
	skin: new Skin({fill: "white"}),
	Behavior: class extends Behavior {
		onDraw(port) {
			port.fillColor("blue", 50, 50, port.width-100, port.height-100);
		}
	}
})
application.add(samplePort);

Port.template(anonymous)
ArgumentsTypeDescription
anonymousfunctionA function that returns an object with properties to initialize the instances that the result creates

Returns a constructor, a function that creates instances of Port.prototype. The prototype property of the result is Port.prototype. The result also provides a template function.

let SamplePort = Port.template($ => ({
	top: 0, bottom: 0, left: 0, right: 0,
	skin: new Skin({fill: "white"}),
	Behavior: class extends Behavior {
		onCreate(port, data) {
			this.colors = data;
		}
		onDraw(port) {
			let colors = this.colors;
			let x = 0, y = 0;
			for (let i = 0; i < colors.length; i++) {
				port.fillColor(colors[i], x, y, 75, 75);
				x += 35;
				y += 35;
			}
		}
	}
}));
application.add(new SamplePort(["blue", "red", "black"]));

Prototype Description

Prototype inherits from Content.prototype.

Functions

drawContent(x, y, width, height)

ArgumentTypeDescription
x, y, width, heightnumberThe local position and size of the area in which to draw, in pixels

Draws this port's skin in the position specified

let heartSkin = new Skin({
	texture: new Texture("heart.png"),
	color: "red",
	x: 0, y: 0, width: 60, height: 60,
});

let sampleStyle = new Style({ font:"600 28px Open Sans", color: ["red", "yellow", "green", "blue"] });
let samplePort = new Port(null, {
	top: 0, bottom: 0, left: 0, right: 0,
	skin: heartSkin,
	Behavior: class extends Behavior {
		onDraw(port) {
			let size = 60;
			port.drawContent(0, 0, size, size);
			port.drawContent(port.width-size, 0, size, size);
			port.drawContent(0, port.height-size, size, size);
			port.drawContent(port.width-size, port.height-size, size, size);
		}
	}
});
application.add(samplePort);


drawLabel(string, x, y, width, height)

ArgumentTypeDescription
string string The string to draw
x, y, width, heightnumberThe local position and size of the area in which to draw, in pixels

Draws the string the way a label instance would, with the style of this port

let sampleStyle = new Style({ font:"600 28px Open Sans", color: "red" });
let samplePort = new Port(null, {
	top: 0, bottom: 0, left: 0, right: 0,
	skin: new Skin({ fill: "white" }), style: sampleStyle,
	Behavior: class extends Behavior {
		onDraw(port) {
			let string = "Hello, World!";
			let size = sampleStyle.measure(string);
			port.drawLabel(string, port.width-size.width, port.height-size.height, size.width, size.height);
		}
	}
})
application.add(samplePort);


drawSkin(skin, x, y, width, height [, variant, state])

ArgumentTypeDescription
skin skin The skin to draw
x, y, width, heightnumberThe local position and size of the area in which to draw, in pixels
variantnumberThe variant of the skin to draw. If the specified skin defines variants, setting the variant changes the appearance.
statenumberThe state of the skin to draw. If the specified skin defines states, setting the state changes the appearance.

Draws the skin the way a content instance would, with the state, variant, and position specified.

let heartSkin = new Skin({
	texture: new Texture("heart.png"),
	color: ["red", "blue"],
	x: 0, y: 0, width: 60, height: 60,
});

let samplePort = new Port(null, {
	top: 0, bottom: 0, left: 0, right: 0,
	skin: new Skin({ fill: "white" }),
	Behavior: class extends Behavior {
		onDraw(port) {
			port.drawSkin(heartSkin, 20, 20, 60, 60, 0, 1);
		}
	}
})
application.add(samplePort);


drawString(string, style, color, x, y, width, height)

ArgumentTypeDescription
stringstringThe string to draw
stylestyleThe style to use to draw the string
colorstringThe color to draw the string, as a string of the form specified in the Color section of this document
x, y, width, heightnumberThe local position and size of the area in which to draw, in pixels

Draws the string the way a label instance would, with the style, color, and position specified.

let sampleStyle = new Style({ font:"600 28px Open Sans"});

let samplePort = new Port(null, {
	top: 0, bottom: 0, left: 0, right: 0,
	skin: new Skin({fill: "white"}),
	Behavior: class extends Behavior {
		onDraw(port) {
			port.drawString("Hello, World!", sampleStyle, "blue", 0, 0, port.width, port.height);
		}
	}
});
application.add(samplePort);


drawStyle(string, style, x, y, w, h [, ellipsis, state])

ArgumentTypeDescription
stringstringThe string to draw
stylestyleThe style to use to draw the string
x, y, width, heightnumberThe local position and size of the area in which to draw, in pixels
ellipsisbooleanIf true, the string is truncated to fit the specified bounds. If false, the entire string is drawn, even if it extends beyond the specified bounds.
statenumberThe state of the style to draw. If the specified style has multiple fill colors, setting the state selects which color to use.

Draws a string with the style, position, and state specified.

let sampleStyle = new Style({ font:"600 28px Open Sans", color: ["red", "yellow", "green", "blue"] });
let samplePort = new Port(null, {
	top: 0, bottom: 0, left: 0, right: 0,
	skin: new Skin({ fill: "white" }),
	Behavior: class extends Behavior {
		onDraw(port) {
			let string = "Hello, World!";
			let size = sampleStyle.measure(string);
			let w = size.width;
			let h = size.height;
			port.drawStyle(string, sampleStyle, 20, 10, w, h, true, 0);
			port.drawStyle(string, sampleStyle, 20, h+10, w, h, true, 1);
			port.drawStyle(string, sampleStyle, 20, h*2+10, w-10, h, false, 2);	// Not truncated
			port.drawStyle(string, sampleStyle, 20, h*3+10, w-10, h, true, 3);	// Truncated
		}
	}
});
application.add(samplePort);


drawTexture(texture, color, x, y, sx, sy, sw, sh)

ArgumentTypeDescription
texturetextureThe texture to draw
colorstringIf the texture has only an alpha bitmap, the value of the color property will be used to colorize the bitmap. Must be a string of the form specified in the Color section of this document.
x, ynumberThe local position and size of the area in which to draw, in pixels
sx, sy, sw, shnumberThe source area--the position and size of the area to copy pixels from, in pixels. The default is the entire image.  

Draws the image referenced by the texture.

let ballTexture = new Texture("balls.png");
let alphaHeartTexture = new Texture("heart.png");

let samplePort = new Port(null, {
	top: 0, bottom: 0, left: 0, right: 0,
	skin: new Skin({fill: "white"}),
	Behavior: class extends Behavior {
		onDraw(port) {
			port.drawTexture(ballTexture, "black", 0, 0, 0, 0, 30, 30);
			port.drawTexture(alphaHeartTexture, "red", 0, 30, 0, 0, 60, 60);
			port.drawTexture(alphaHeartTexture, "blue", 0, 90, 0, 0, 60, 60);
		}
	}
})
application.add(samplePort);


fillColor(color, x, y, width, height)

ArgumentTypeDescription
colorstringThe color to draw the image in, as a string of the form specified in the Color section of this document
x, y, width, heightnumberThe local position and size of the area to fill, in pixels

Fills the area with the color specified.

let samplePort = new Port(null, {
	top: 0, bottom: 0, left: 0, right: 0,
	skin: new Skin({fill: "white"}),
	Behavior: class extends Behavior {
		onDraw(port) {
			port.fillColor("red", 0, 0, port.width/2, port.height);
			port.fillColor("blue", port.width/2, 0, port.width/2, port.height);
		}
	}
})
application.add(samplePort);


fillTexture(texture, color, x, y, width, height, sx, sy, sw, sh)

ArgumentTypeDescription
texture textureThe filling image
x, y, width, heightnumberThe destination area--the local position and size of the area to copy pixels to, in pixels
sx, sy, sw, shnumberThe source area--the position and size of the area to copy pixels from, in pixels.

Fills the area with the image. The source area of the image is repeated to cover the destination area.

let alphaHeartTexture = new Texture("heart.png");

let samplePort = new Port(null, {
	top: 0, bottom: 0, left: 0, right: 0,
	skin: new Skin({fill: "white"}),
	Behavior: class extends Behavior {
		onDraw(port) {
			let w = port.width, h = port.height;
			port.fillTexture(alphaHeartTexture, "red", 0, 0, w, h/2, 0, 0, 60, 60);
			port.fillTexture(alphaHeartTexture, "blue", 0, h/2, w, h/2, 0, 0, 60, 60);
		}
	}
})
application.add(samplePort);


invalidate([x, y, width, height])

ArgumentTypeDescription
x, y, width, heightnumberThe local position and size of the area to invalidate, in pixels

Invalidates the specified area of this port (or the entire port if no area is specified), which triggers the onDraw event.

let samplePort = new Port(null, {
	active: true, top: 0, bottom: 0, left: 0, right: 0,
	skin: new Skin({fill: "white"}),
	Behavior: class extends Behavior {
		onCreate(port) {
			this.color = "blue";
		}
		onDraw(port) {
			port.fillColor(this.color, 0, 0, port.width, port.height);
		}
		onTouchEnded(port) {
			this.color = (this.color == "blue")? "red" : "blue";
			port.invalidate();
		}
	}
})
application.add(samplePort);


measureString(string, style)

ArgumentTypeDescription
stringstringThe string to measure
stylestyleThe style to use when measuring the string

Measures the string the way a label instance would, with the style specified

let sampleStyle = new Style({ font:"600 28px Open Sans"});
let samplePort = new Port(null, {
	active: true, top: 0, bottom: 0, left: 0, right: 0,
	skin: new Skin({fill: "white"}),
	Behavior: class extends Behavior {
		onCreate(port) {
			this.index = 0;
			this.strings = ["H", "He", "Hel", "Hell", "Hello"];
		}
		onDraw(port) {
			let string = this.strings[this.index];
			let stringWidth = port.measureString(string, sampleStyle).width;
			port.drawString(string, sampleStyle, "blue", (port.width-stringWidth)/2, 0, stringWidth, 30);
		}
		onTouchEnded(port) {
			this.index++;
			if (this.index == this.strings.length) this.index = 0;
			port.invalidate();
		}
	}
})
application.add(samplePort);


popClip()

Restores the current clip rectangle from this port's clip rectangles stack


pushClip([x, y, width, height])

ArgumentTypeDescription
x, y, width, heightnumberThe local position and size of the clip rectangle

Saves the specified clip rectangle to this port's clip rectangles stack

let alphaHeartTexture = new Texture("heart.png");
let samplePort = new Port(null, {
	top: 0, bottom: 0, left: 0, right: 0,
	skin: new Skin({fill: "white"}),
	Behavior: class extends Behavior {
		onDraw(port) {
			port.fillTexture(alphaHeartTexture, "blue", 0, 0, port.width, port.height, 0, 0, 60, 60);
			port.pushClip(0, 0, 200, 100);
			port.fillTexture(alphaHeartTexture, "red", 0, 0, port.width, port.height, 0, 0, 60, 60);
			port.popClip();
		}
	}
})
application.add(samplePort);


Events

Same as for content object (see Events in the section Content Object), plus:

onDraw(port, x, y, width, height)

ArgumentTypeDescription
portportThe port object that triggered the event
x, y, width, heightnumberThe local position and size of the area to draw, in pixels

This event is triggered when the specified port object needs to update the area (when it's invalidated).

Row Object

  • Source code: piuRow.c
  • Relevant Examples: N/A

The row object is a container object that arranges its contents horizontally.

Constructor Description

Row([behaviorData, dictionary])
ArgumentTypeDescription
behaviorData*A parameter that is passed into the onCreate function of this content's behavior. This may be any type of object, including null or a dictionary with arbitrary parameters.
dictionaryobjectAn object with properties to initialize the result. The dictionary is the same as for the content object. Only parameters specified in the Dictionary section of the Content Object will have an effect; other parameters will be ignored.

Returns a row instance, an object that inherits from Row.prototype

let sampleRow = new Row(null, {
	top: 0, bottom: 0, left: 0, right: 0,
	contents: [
		new ColoredSquare("red"),
		new ColoredSquare("blue"),
		new ColoredSquare("black"),
	]
});
application.add(sampleRow);

Row.template(anonymous)
ArgumentsTypeDescription
anonymousfunctionA function that returns an object with properties to initialize the instances that the result creates

Returns a constructor, a function that creates instances of Row.prototype. The prototype property of the result is Row.prototype. The result also provides a template function.

let ColoredSquare = Content.template($ => ({
	left: 0, right: 0, top: 0, bottom: 0,
	skin: new Skin({ fill: $ })
}));

let SampleRow = Row.template($ => ({
	top: 0, bottom: 0, left: 0, right: 0,
	contents: [
		new ColoredSquare($.firstColor),
		new ColoredSquare($.secondColor),
	],
}));
application.add(new SampleRow({ firstColor:"red", secondColor:"blue" }));

Prototype Description

Prototype inherits from Container.prototype.

Events

Same as for container object (see Events in the section Container Object)

Scroller Object

The scroller object is a container object that scrolls its first content object horizontally and vertically.

Constructor Description

Scroller([behaviorData, dictionary])
ArgumentTypeDescription
behaviorData*A parameter that is passed into the onCreate function of this content's behavior. This may be any type of object, including null or a dictionary with arbitrary parameters.
dictionaryobjectAn object with properties to initialize the result. Only parameters specified in the Dictionary section below will have an effect; other parameters will be ignored.

Returns a scroller instance, an object that inherits from Scroller.prototype

import { VerticalScrollerBehavior } from "scroller";	// See "scroller.js" from the scroller example

let sampleStyle = new Style({ font:"600 28px Open Sans", color: "white" });
let scrollerSample = new Scroller(null, {
	left: 0, right: 0, top: 0, bottom: 0,
	style: sampleStyle, skin: new Skin({ fill: "blue" }),
	active: true, backgroundTouch: true, clip: true,
	Behavior: VerticalScrollerBehavior,
	contents:[
		Text(null, {
			left: 0, right: 0, top: 0,
			blocks: [
				{spans: [
					"Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
					"Pellentesque a massa et massa rutrum maximus non quis tellus.",
					"Fusce quis eros quis leo sodales vehicula. Praesent pretium massa vel ornare pharetra."
				]}
			]
		}),
	],
});
application.add(scrollerSample);

Scroller.template(anonymous)
ArgumentsTypeDescription
anonymousfunctionA function that returns an object with properties to initialize the instances that the result creates

Returns a constructor, a function that creates instances of Scroller.prototype. The prototype property of the result is Scroller.prototype. The result also provides a template function.

import { VerticalScrollerBehavior } from "scroller";	// See "scroller.js" from the scroller example

let sampleStyle = new Style({ font:"600 28px Open Sans", color: "white" });
let ScrollerSample = Scroller.template($ => ({
	left: 0, right: 0, top: 0, bottom: 0, skin: new Skin({ fill: "black" }),
	active: true, backgroundTouch: true, clip: true,
	Behavior: VerticalScrollerBehavior,
	contents:[
		Text(null, {
			left: 0, top: 0, right: 0,
			string: "The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog.",
		}),
	],
}));
let screenWithScrollerSample = new Column(null, {
	top: 0, bottom: 0, left: 0, right: 0,
	style: sampleStyle,
	contents: [
		Text(null, {
			top: 0, height: 40, left: 0, right: 0,
			skin: new Skin({ fill: "blue" }),
			string: "Scroller Example"
		}),
		new ScrollerSample(),
	]
});
application.add(screenWithScrollerSample);

Dictionary

Same as for container object (see Dictionary in the section Container Object), plus:

ParameterTypeDefinition
loopbooleanIf true, this scroller will loop its first content object

Prototype Description

Prototype inherits from Container.prototype.

Properties
NameTypeDefault ValueRead OnlyDescription
constraintobjectThe constrained scroll offsets of this scroller, as an object with x and y number properties. The scroll offsets when this scroller is tracking may be different from the constrained scroll offsets.
loopbooleanfalseIf true, this content will restart its clock when its time equals its duration
scrollobjectThe scroll offsets of this scroller, as an object with x and y number properties, specified in pixels
trackingbooleanfalseIf true, this scroller is tracking. When tracking, the scroller does not constrain its scroll offsets.
Functions

reveal(bounds)

ArgumentTypeDescription
boundsobjectThe local position and size of the area to reveal, as an object with x, y, width, and height properties, specified in pixels

Scrolls this scroller to reveal the specified area

class SampleScrollerBehavior extends Behavior {
	onDisplaying(scroller) {
		let bounds = scroller.bounds;
		bounds.y = scroller.first.last.y;
		scroller.reveal(bounds);
	}
}
let sampleStyle = new Style({ font:"600 28px Open Sans", color: "white" });
let ScrollerItem = Label.template($ => ({
	left: 20, right: 20, bottom: 90, height: 30,
	style: sampleStyle, string: "Item" + $
}));
let scrollerSample = new Scroller(null, {
	left: 0, right: 0, top: 0, bottom: 0,
	skin: new Skin({ fill: "black" }),
	Behavior: SampleScrollerBehavior,
	contents:[
		Column(null, {
			top: 0, left: 0,
			contents: [
				ScrollerItem(1),
				ScrollerItem(2),
				ScrollerItem(3),
				ScrollerItem(4),
				ScrollerItem(5),
			]
		})
	],
});
application.add(scrollerSample);


scrollBy(dx, dy)

ArgumentTypeDescription
dx, dynumberThe deltas by which to scroll this scroller, in pixels

Adds the deltas to the scroll offsets of this scroller

class SampleScrollerBehavior extends Behavior {
	onDisplaying(scroller) {
		this.halfway = scroller.y + scroller.height/2;
	}
	onTouchEnded(scroller, id, x, y, ticks) {
		scroller.scrollBy(0, y-this.halfway);
	}
}

let ColoredSquare = Content.template($ => ({
	left: 20, right: 20, top: 20, height: 80,
	skin: new Skin({ fill: $ })
}));
let scrollerSample = new Scroller(null, {
	left: 0, right: 0, top: 0, bottom: 0,
	skin: new Skin({ fill: "black" }),
	active: true, backgroundTouch: true, clip: true,
	Behavior: SampleScrollerBehavior,
	contents:[
		Column(null, {
			active: true, top: 0, left: 0, right: 0,
			contents: [
				ColoredSquare("red"),
				ColoredSquare("orange"),
				ColoredSquare("yellow"),
				ColoredSquare("green"),
				ColoredSquare("blue"),
				ColoredSquare("purple"),
			]
		})
	],
});
application.add(scrollerSample);


scrollTo(x, y)

ArgumentTypeDescription
x, ynumberThe offsets to which to scroll this scroller, in pixels

Changes the scroll offsets of this scroller

let ColoredSquare = Content.template($ => ({
	active: true, top: 20, width: 80, height: 80,
	skin: new Skin({ fill: $ }),
	Behavior: class extends Behavior {
		onDisplaying(content) {
			this.x = content.x - 40;
			this.y = content.y - 40;
		}
		onTouchEnded(content) {
			let scroller = content.container.container;
			scroller.scrollTo(this.x, this.y);
		}
	}
}));
let scrollerSample = new Scroller(null, {
	left: 0, right: 0, top: 0, bottom: 0,
	skin: new Skin({ fill: "black" }),
	contents:[
		Column(null, {
			top: 0, left: 0,
			contents: [
				ColoredSquare("red", {left: 0}),
				ColoredSquare("orange", {left: 40}),
				ColoredSquare("yellow", {left: 80}),
				ColoredSquare("green", {left: 120}),
				ColoredSquare("blue", {left: 160}),
				ColoredSquare("purple", {left: 200}),
			]
		})
	],
});
application.add(scrollerSample);


Events

Same as for container object (see Events in the section Container Object), plus:

onScrolled(scroller)
ArgumentTypeDescription
scrollerscrollerThe scroller object that triggered the event

This event is triggered when the specified scroller object scrolls.

When triggered by a scroller, this event is also triggered by all the contents of the scroller. This makes it easier to implement scrollbars, for example.

Skin Object

The skin object defines the appearance of content objects. It can draw or fill content objects with portions of texture objects or fill or stroke content objects with colors.

Constructor Description

Skin([dictionary])
ArgumentTypeDescription
dictionaryobjectAn object with properties to initialize the result. Only parameters specified in the Dictionary section below will have an effect; other parameters will be ignored.

Returns a skin instance, an object that inherits from Skin.prototype

// Texture skin
let ballTexture = new Texture("balls.png");
let ballSkin = new Skin({ texture:ballTexture, x:0, y:0, width:30, height:30, variants:30 });
let ballContent = new Content(null, {
	top: 0, left: 0,
	skin: ballSkin
});
application.add(ballContent);

// Color skin
let borderedSkin = new Skin({ fill: "black", stroke: "blue", borders: { left: 5, right: 5, top: 5, bottom: 5}})
let borderedContent = new Content(null, {
	top: 50, left: 0, height: 50, width: 50,
	skin: borderedSkin
});
application.add(borderedContent);

Skin.template([dictionary])
ArgumentsTypeDescription
dictionaryobjectAn object with properties to initialize the result. Only parameters specified in the Dictionary section below will have an effect; other parameters will be ignored.

Returns a constructor, a function that creates instances of Skin.prototype. The prototype property of the result is Skin.prototype.

// Texture skin
let ballTexture = new Texture("balls.png");
let BallSkin = Skin.template({ texture:ballTexture, x:0, y:0, width:30, height:30, variants:30 });
let ballContent = new Content(null, {
	top: 0, right: 0, variant: 2,
		Skin: BallSkin		// Note the capital "S" in "Skin"
});
application.add(ballContent);

// Color skin
let BorderedSkin = Skin.template({ fill: "black", stroke: "red", borders: { left: 5, right: 5, top: 5, bottom: 5}})
let borderedContent = new Content(null, {
	top: 50, right: 0, height: 50, width: 50,
	skin: new BorderedSkin()	// Note the lowercase "S" in "Skin"
});
application.add(borderedContent);

Dictionary

If there is a texture or Texture property in the dictionary, the constructor returns a texture skin, otherwise the constructor returns a color skin.

Texture skins only

ParameterTypeDescription
bottomnumberThe skin's bottom tile (setting the bottom parameter in the created instance, and bottom in the created instance's tiles property)
colorstring or arrayIf the texture has only an alpha bitmap, the value of the color property will be used to colorize the bitmap. Must be a string or array of strings of the form specified in the Color section of this document.
leftnumberThe skin's left tile (setting the left parameter in the created instance, and left in the created instance's tiles property)
rightnumberThe skin's right tile (setting the right parameter in the created instance, and right in the created instance's tiles property)
statesnumberThis skin's vertical offset between states, in pixels
texturetextureThis skin's texture
TexturefunctionA function that creates instances of Texture.prototype. This skin will create an instance of this texture, and seet its texture parameter to the created instance.
tilesobjectThis skin's tiles, as an object with left, right, top, or bottom number properties, specified in pixels. See Tiles for more information.
topnumberThe skin's top tile (setting the top parameter in the created instance, and top in the created instance's tiles property)
variantsnumberThis skin's horizontal offset between variants, in pixels
x, y, width, heightnumberThe portion of the texture object to extract, in pixels (setting the created instance's bounds, width, and height properties)

Color skins only

ParameterTypeDescription
bordersobjectThe borders to stroke content objects with, as an object with left, right, top, or bottom number properties, specified in pixels. The default is no borders.
fillstring or arrayThe color(s) to fill content objects with, as a string or an array of strings of the form specified in the Color section of this document.
strokestring or arrayThis skin's stroke color(s), as a string or an array of strings of the form specified in the Color section of this document.

Prototype Description

Prototype inherits from Object.prototype.

Properties

All properties of a skin object are read-only, but you can change the style of content objects at any time.

Texture Skins

NameTypeDefault ValueDescription
bottomnumber0The skin's bottom tile
colorstringIf the texture has only an alpha bitmap, the value of the color property will be used to colorize the bitmap. Must be a string or array of strings of the form specified in the Color section of this document.
boundsobjectThe portion of the texture object to extract, as an object with x, y, width, and height number properties, specified in pixels
heightnumberThis skin's height, in pixels
leftnumber0The skin's left tile
rightnumber0The skin's right tile
statesnumberundefinedThis skin's vertical offset between states, in pixels
texturetextureThis skin's texture
tilesobjectundefinedThis skin's tiles, as an object with left, right, top, and bottom number properties, specified in pixels
topnumber0The skin's top tile
variantsnumberundefinedThis skin's horizontal offset between variants, in pixels
widthnumberThis skin's width, in pixels

Color Skins

NameTypeDefault ValueDescription
bordersobject{left: 0, right: 0, top: 0, bottom: 0}This skin's borders, as an object with left, right, top, and bottom number properties, specified in pixels
fillobjectThis skin's fill color(s), as an array of strings of the form specified in the Color section of this document.

The state property of the content object using the skin determines the index of the array; if state is not an integer, colors from surrounding states are blended. If specified as one string instead of an array, it is treated as an array with a single item. The default fill color is transparent.
strokeobjectThis skin's stroke color(s), as an array of strings of the form specified in the Color section of this document.

The state property of the content object using the skin determines the index of the array; if state is not an integer, colors from surrounding states are blended. If specified as one string instead of an array, it is treated as an array with a single item. The default stroke color is transparent.

Sound Object

The Sound object plays audio using the AudioOut class. It may be used to play all or part of an audio resource once or repeatedly. The Sound object is designed to play short sounds to provide audible feedback for user actions. Use the AudioOut class directly for other audio playback needs.

Constructor Description

A separate instance of the Sound class is created for each audio resource to be played.

Sound(dictionary)
ArgumentTypeDescription
dictionaryobjectAn object with properties to initialize the result. Only parameters specified in the Dictionary section below have an effect; other parameters are ignored.

Returns a sound instance, an object that inherits from Sound.prototype

let sampleSound = new Sound({ path: "piano.wav" });

Dictionary

ParameterTypeDescription
pathstringThe name of the resource containing the audio audio.
offsetnumberThe number of samples into the audio to begin playback. If not specified, playback begins with the first sample.
sizenumberThe number of samples to play. If not specified, playback continues to the end of the audio resource.

Prototype Description

Prototype inherits from Object.prototype.

Properties

All properties are static. The default values for the bitsPerSample, numChannels, and sampleRate properties reflect the configuration of the AudioOut module.

NameTypeDefault ValueRead OnlyDescription
bitsPerSamplenumber The number of bits (either 8 or 16) for audio playback.
numChannelsnumber The number of channels for audio playback.
sampleRatenumberThe number of samples per second for audio playback.
volumenumber1The volume of sounds; values range from 0 for silent, to 1 for full volume
Functions

static close()

Stops any sounds that are playing and closes the AudioOut instance used by the Sound object. Instances of the Sound class are not closed or otherwise affected by this call.

Sound.close();

play([stream, repeat, callback])

ArgumentTypeDescription
streamnumberThe stream to play the sound on. Defaults to 0.
repeatnumberThe number of times to repeat the sound. Defaults to 1. Set the repeat property to Infinity to repeat the sound indefinitely.
callbackfunctionAn optional callback function to invoke after the audio resource completes playback.

Plays the audio sample on the specified stream repeat times. If the callback parameter is provided, it is invoked after playback of the audio completes.

// Play sampleSound once
sampleSound.play();

// Play sampleSound 5 times
sampleSound.play(0, 5);

// Play sampleSound once and print to the console when finished
sampleSound.play(0, 1, () => {
	trace("Sound finished\n");
});

Style Object

The style object defines the appearance of strings in label and text objects. Styles can be inherited from those of containing objects. For more information, see the Cascading Styles section below.

Constructor Description

Style(dictionary)
ArgumentTypeDescription
dictionaryobjectAn object with properties to initialize the result. Only parameters specified in the Dictionary section below will have an effect; other parameters will be ignored.

Returns style instance, an object that inherits from Style.prototype

let sampleStyle = new Style({ font:"600 28px Open Sans", color: "blue" });
let sampleLabel = new Label(null, {
	top: 0, bottom: 0, left: 0, right: 0,
	skin: new Skin({ fill: "white" }),
	style: sampleStyle, string: "Hello, World!"
});
application.add(sampleLabel)

Style.template(dictionary)
ArgumentTypeDescription
dictionaryobjectAn object with properties to initialize the result. Only parameters specified in the Dictionary section below will have an effect; other parameters will be ignored.

Returns a constructor, a function that creates instances of Style.prototype. The prototype property of the result is Style. The result also provides a template function.

let RedStyle = Style.template({ font:"600 28px Open Sans", color: "red" });
let BlueStyle = Style.template({ font:"600 28px Open Sans", color: "blue" });
let sampleLabel = new Label(null, {
	top: 0, height:30, left: 0, right: 0,
	skin: new Skin({ fill: "white" }),
	Style: RedStyle, string: "Hello, World!"	// Note the capital "S" in "Style"
});
let sampleLabel2 = new Label(null, {
	top: 30, height: 30, left: 0, right: 0,
	skin: new Skin({ fill: "white" }),
	style: new BlueStyle, string: "Hello, World!"	// Note the lowercase "s" in "style"
});
application.add(sampleLabel);
application.add(sampleLabel2);

Dictionary

Text styles only
ParameterTypeDescription
bottomnumberThis style's bottom margin, in pixels (setting the bottom property of the created instance, and bottom in the created instance's margins property)
leadingnumberThis style's line height, or "leading"--the distance between lines of a block, in pixels. If 0 or unspecified, it is automatically calculated. Use a negative value to force a distance even if lines overlap.
leftnumberThis style's left margin, in pixels (setting the left property of the created instance, and left in the created instance's margins property)
rightnumberThis style's right margin, in pixels (setting the right property of the created instance, and right in the created instance's margins property)
Label styles only
ParameterTypeDescription
verticalstringThis style's vertical alignment, as top, middle (the default), or bottom
Text and Label styles
ParameterTypeDescription
colorstring or arrayThis style's color(s), as a string or an array of strings of the form specified in the Color section of this document
fontstringThis style's font, as a string of the form specified in the Cascading Styles section of this document (setting the style, weight, stretch, size, and family properties of the created instance)
horizontalstringThis style's horizontal alignment, as left, center (the default), right, or justify
topnumberThis style's top margin, in pixels (setting the top property of the created instance, and top in the created instance's margins property)

Prototype Description

Prototype inherits from Object.prototype.

Properties

All properties of a style object are read-only, but you can change the style of content objects at any time.

NameTypeDefault ValueDescription
bottomnumber0The bottom margin of this style
colorobjectundefinedThis style's color(s), as an array of strings, or undefined if no color has been specified. The state property of the content object using the style determines the index of the array; if state is not an integer, colors from surrounding states are blended.
familystringThis style's font family
horizontalstringThis style's horizontal alignment, as left, center (the default), right, or justify
leadingnumberThis style's line height (or "leading")--the distance between lines of a block, in pixels. If 0 or unspecified, it is automatically calculated
leftnumber0The left margin of this style
marginsobjectThis style's margins, as an object with left, right, top, and bottom number properties, specified in pixels
rightnumber0The right margin of this style
sizestringThis style's font size, in pixels.
stretchstringThis style's stretch
topnumber0The top margin of this style
verticalstringThis style's vertical alignment, as top, middle (the default), or bottom, specified in pixels
weightnumberThe weight of this style's font
Functions

measure(string)

ArgumentTypeDescription
stringstringThe string to measure

Calculates the size of the string rendered with this style (and any inherited styles, if this style is attached to a content object), and returns it as an object with width and height properties, specified in pixels

let normalStyle = new Style({ font:"600 28px Open Sans", color: "black" });
let size = normalStyle.measure("Moddable");	// {"width":134,"height":38}

Text Object

The text object is a content object that renders a string on multiple lines with multiple styles. There are two ways to modify the string of a text object. An application typically uses only one of these approaches for a specific text object.

  1. Set the string property. This replaces the full string.
  2. Build the string with blocks and spans, between calls to the begin and end functions. This appends characters to the string. This method provides the most control, since each span can have a different style.

Constructor Description

Text([behaviorData, dictionary])
ArgumentTypeDescription
behaviorData*A parameter that is passed into the onCreate function of this content's behavior. This may be any type of object, including null or a dictionary with arbitrary parameters.
dictionaryobjectAn object with properties to initialize the result. Only parameters specified in the Dictionary section below will have an effect; other parameters will be ignored.

Returns a text instance, an object that inherits from Text.prototype

let sampleStyle = new Style({ font:"600 28px Open Sans"});
let redStyle = new Style({ color: "red" });
let blueStyle = new Style({ color: "blue" });

let sampleText = new Text(null, {
	top: 0, bottom: 0, left: 0, right: 0,
	skin: new Skin({fill: "white"}),
	style: sampleStyle,
	blocks: [
		{ spans: [
			" Lorem ipsum dolor sit amet, ",
			{ style: redStyle, spans: "consectetur adipiscing elit." },
		]},
		{ style: blueStyle, spans: "In dignissim hendrerit ultricies." }
	]
});
application.add(sampleText);

Text.template(anonymous)
ArgumentsTypeDescription
anonymousfunctionA function that returns an object with properties to initialize the instances that the result creates

Returns a constructor, a function that creates instances of Text.prototype. The prototype property of the result is Text.prototype. The result also provides a template function.

let sampleStyle = new Style({ font:"600 28px Open Sans"});
let redStyle = new Style({ color: "red", horizontal: "left" });
let blueStyle = new Style({ color: "blue", horizontal: "right" });

let SampleText = Text.template($ => ({
	top: 50, bottom: 50, left: 50, right: 50,
	skin: new Skin({fill: "white"}),
	style: $.baseStyle,
	blocks: [
		{ style: redStyle, spans: $.redText },
		{ style: blueStyle, spans: $.blueText }
	]
}));
application.add(new SampleText({ baseStyle: sampleStyle, redText: "Red!", blueText: "Blue!" }));

Dictionary

Same as for content object (see Dictionary in the section Content Object), plus:

ParameterTypeDescription
blocksarrayAn array of blocks, where a block is an object with the following properties:
- behavior: An object or null (the default). When this text is active and the block is touched, the block calls the corresponding function properties of its behavior.
- style: A style instance or null (the default).
- spans: A string or an array of spans.

Like a block, a span is an object with behavior, style, and spans properties.
stringstringThis text's string. Setting this string creates one block containing one span that uses this text's style.   

Prototype Description

Prototype inherits from Content.prototype.

Properties
NameTypeRead OnlyDescription
blocksarrayThis text's blocks
stringstringThis text's string. Setting this string creates one block containing one span that uses this text's style.
Functions

For sample code that uses all the functions below, see the text example.

begin()

Starts the process of defining the string and styles of this text using blocks and spans. The string is reset to empty. The begin function must be called before beginBlock or beginSpan. After defining the string and styles, call end.


beginBlock([style, behavior])

ArgumentTypeDescription
stylestyleThe style of the block
behaviorobjectThe behavior of the block

Creates and opens a new block. The begin function must have been already called without a corresponding end. There cannot be another block already open.


beginSpan(style [, behavior])

ArgumentTypeDescription
stylestyleThe style of the span
behaviorobjectThe behavior of the span

Creates and opens a new span. There must be an open block. There cannot be another open span.


concat(string)

ArgumentTypeDescription
stringstringThe string to concatenate

Concatenates the specified string to this text. There must be an open span.


end()

Completes the process of building this text's string and styles using blocks and spans; must be called after begin and before this text can be measured, fit, or rendered


endBlock()

Closes the open block


endSpan()

Closes the open span


Events

Same as for content object (see Events in the section Content Object).

Texture Object

The texture object is an asset that references an image file. Applications use texture objects in defining skin objects.

Constructor Description

Texture(path)
ArgumentTypeDescription
pathstringThe URL of the image file. It must be a file URL.

Returns a texture instance, an object that inherits from Object.prototype

const logoTexture = new Texture("logo.png");
const logoSkin = new Skin({ texture: logoTexture, x: 0, y: 0, width: 100, height: 20 });
Texture(dictionary)
ArgumentTypeDescription
dictionaryobjectAn object with properties to initialize the result. Only parameters specified in the Dictionary section below will have an effect; other parameters will be ignored.

Returns a texture instance, an object that inherits from Object.prototype

const logoTexture = new Texture({ path: "logo.png" });
const logoSkin = new Skin({ texture: logoTexture, x: 0, y: 0, width: 100, height: 20 });
Texture.template(dictionary)
ArgumentTypeDescription
dictionaryobjectAn object with properties to initialize the result. Only parameters specified in the Dictionary section below will have an effect; other parameters will be ignored.

Returns a constructor, a function that creates instances of Texture.prototype. The prototype property of the result is Texture.prototype.

const LogoTexture = Texture.template({ path: "logo.png" });
// Note the capital "T" in "Texture" below
const LogoSkin = Skin.template({ Texture: LogoTexture, x: 0, y: 0, width: 100, height: 20, color: "white" });

const AnotherLogoTexture = Texture.template({ path: "logo.png" });
// Note the lowercase "t" in "texture" below
const AnotherLogoSkin = Skin.template({ texture: new AnotherLogoTexture(), x: 0, y: 0, width: 100, height: 20, color: "white" });

Dictionary

ParameterTypeDescription
pathstringThe URL of the image file. It must be a file URL.

Prototype Description

Prototype inherits from Object.prototype.

Properties
NameTypeRead OnlyDescription
heightnumberThis texture's height, in physical pixels          
widthnumberThis texture's width, in physical pixels

Timeline Object

The timeline object provides a mechanism for sequencing and running a collection of tweens. This is useful for managing transitions between Piu screens and other animations.

Tweens work by taking in a target object and an object that specifies a list of properties and values. When the tween is set to a specific fraction, the appropriate properties of the target object are updated with values between their initial value and the destination value. The specifics of how this works are determined by the type of tween ("on", "from", or "to", as described below) and the easing function used for the tween.

The application manages all of the tweens in a timeline at once by seeking to a particular point in the timeline. This is usually driven by the onTimeChanged function of a content object.

The Piu Timeline implementation is based on the TimelineLite class developed by GreenSock.

Note that the Timeline class must be imported into your application to be used:

import Timeline from "piu/Timeline";`

Constructor Description

Timeline()

Returns a timeline object, an instance of the Timeline class.

let timeline = new Timeline();

Prototype Description

Properties
NameTypeDefault ValueRead OnlyDescription
durationnumberHow long this timeline will take to complete once started, in ms.
fractionnumberThe fraction of this timeline that has completed, as a decimal between 0 and 1. Setting the fraction is equivalent to calling seekTo(fraction * duration).
timenumberThe amount of time the timeline has completed, in ms. This should not be modified directly — use seekTo(time) instead.
Functions

from(target, fromProperties, duration, [easing, delay])

ArgumentTypeDescription
targetobjectThe object that will have its properties tweened by the timeline.
fromPropertiesobjectThe keys of this object are the properties of the target object that will be tweened by the timeline. Their values are the starting values the properties of the target object will have at the beginning of the tween.
durationnumberThe duration of the tween in ms.
easingnumberAn easing function to use for the tween. If null is provided, the tween will use a linear easing function.
delaynumberThe number of ms after the previous tween in the timeline completes that this one should begin. If this number is negative, the tween will begin before the prior tween completes. If no duration is provided, the tween will begin immediately upon completion of the prior tween.

Adds a "from tween" to the timeline. A "from tween" eases the properties of the target object from the values specified in the toProperties object to the original values of the target object over duration ms.

Returns this timeline, useful for chaining together multiple to, from, and on calls.

let sampleStyle = new Style({ font: "600 28px Open Sans", color: ["blue", "white"] });
let sampleColumn = new Column(null, {
	top: 0, bottom: 0, left: 0, right: 0,
	skin: new Skin({ fill: "white" }), style: sampleStyle,
	contents: [
		Label(null, { top: 90, height: 28, left: 80, string: "Hello", state: 0 }),
		Label(null, { top: 2, height: 28, left: 80, string: "Moddable", state: 0 }),
	],
	Behavior: class extends Behavior {
		onDisplaying(column) {
			let timeline = this.timeline = new Timeline();
			timeline.from(column.first, { x: -column.first.width, state: 1 }, 1000, Math.quadEaseOut, 0)
				.from(column.last, { x: application.width, state: 1 }, 800, Math.quadEaseOut, -800);
			column.duration = timeline.duration;
			timeline.seekTo(0);
			column.time = 0;
			column.start();
		}
		onTimeChanged(column) {
			this.timeline.seekTo(column.time);
		}
	}
});
application.add(sampleColumn);

on(target, onProperties, duration, easing, delay, when)

ArgumentTypeDescription
targetobjectThe object that will have its properties tweened by the timeline.
onPropertiesobjectThe keys of this object are the properties of the target object that will be tweened by the timeline. Their values are arrays of values that the tween will ease between over the duration of the timeline.
durationnumberThe duration of the tween in ms.
easingfunctionAn easing function to use for the tween. If null is provided, the tween will use a linear easing function.
delaynumberThe number of ms after the previous tween in the timeline completes that this one should begin. If this number is negative, the tween will begin before the prior tween completes. If no duration is provided, the tween will begin immediately upon completion of the prior tween.

Adds an "on tween" to the timeline. An "on tween" eases the values of the target object through a sequence of steps as specified by arrays in the onProperties object over duration ms.

Returns this timeline, useful for chaining together multiple to, from, and on calls.

let sampleContainer = new Container(null, {
	top: 0, bottom: 0, left: 0, right: 0, skin: new Skin({ fill: "white" }),
	contents: [
		Content(null, { top: 0, height: 50, left: 0, width: 50, skin: new Skin({ fill: ["blue", "red"] }) })
	],
	Behavior: class extends Behavior {
		onDisplaying(container) {
			this.startAnimation(container);
		}
		startAnimation(container) {
			let timeline = this.timeline = new Timeline();
			let l=0, r=150, b=150, t=0;
			timeline.on(container.first, { x: [l, r, r, l, l], y: [t, t, b, b, t], state: [0, 1] }, 1000, Math.quadEaseInOut, 500);
			container.duration = timeline.duration;
			timeline.seekTo(0);
			container.time = 0;
			container.start();
		}
		onTimeChanged(container) {
			let time = container.time;
			if (this.reverse) time = container.duration - time;
			this.timeline.seekTo(time);
		}
		onFinished(container) {
			this.reverse = !this.reverse;
			this.startAnimation(container);
		}
	}
});
application.add(sampleContainer);

seekTo(time)

ArgumentTypeDescription
timenumberThe position in the Timeline to seek to.

Causes this timeline to jump its tweens to the specified time. This sets the properties of the tweens' target objects.

to(target, toProperties, duration, [easing, delay])

ArgumentTypeDescription
targetobjectThe object that will have its properties tweened by the timeline.
toPropertiesobjectThe keys of this object are the properties of the target object that will be tweened by the timeline. Their values are the destination values the properties of the target object will have when the tween is complete.
durationnumberThe duration of the tween in ms.
easingnumberAn easing function to use for the tween. If null is provided, the tween will use a linear easing function.
delaynumberThe number of ms after the previous tween in the timeline completes that this one should begin. If this number is negative, the tween will begin before the prior tween completes. If no duration is provided, the tween will begin immediately upon completion of the prior tween.

Adds a "to tween" to the timeline. A "to tween" eases the properties of the target object from its current values to the desired values specified in the toProperties object over duration ms.

Returns this timeline, useful for chaining together multiple to, from, and on calls.

let sampleStyle = new Style({ font: "600 28px Open Sans", color: ["blue", "white"] });
let sampleColumn = new Column(null, {
	top: 0, bottom: 0, left: 0, right: 0,
	skin: new Skin({ fill: "white" }), style: sampleStyle,
	contents: [
		Label(null, { top: 90, height: 28, left: 80, string: "Hello", state: 0 }),
		Label(null, { top: 2, height: 28, left: 80, string: "Moddable", state: 0 }),
	],
	Behavior: class extends Behavior {
		onDisplaying(column) {
			let timeline = this.timeline = new Timeline();
			timeline.to(column.first, { x: -column.first.width, state: 1 }, 1000, Math.quadEaseOut, 1000)
				.to(column.last, { x: application.width, state: 1 }, 800, Math.quadEaseOut, -800);
			column.duration = timeline.duration;
			timeline.seekTo(0);
			column.time = 0;
			column.start();
		}
		onTimeChanged(column) {
			this.timeline.seekTo(column.time);
		}
	}
});
application.add(sampleColumn);

Transition Object

The transition object is used to animate modifications of the containment hierarchy.

Constructor Description

Applications define their own constructors for transition objects, which inherit from Transition.prototype and override the onBegin, onEnd, and onStep functions.

class BasicLeftToRightTransition extends Transition {
	constructor(duration) {
		super(duration);
	}
	onBegin(container, current, next) {
		container.add(next);
		this.die = new Die();
		this.die.attach(next);
		this.width = container.width;
		this.height = container.height;
	}
	onStep(fraction) {
		fraction = Math.quadEaseOut(fraction);
		let left = 0, right =  Math.round(this.width * fraction);
		this.die.set(left, 0, right - left, this.height);
		this.die.cut();
	}
	onEnd(container, current, next) {
		this.die.detach();
		container.remove(current);
	}
}

Container objects use instances of transition objects as a parameter to their run function.

class SwitchScreenBehavior extends Behavior {
	onCreate(content, data) {
		this.data = data;
	}
	onTouchEnded(content) {
		let data = this.data;
		let transition = new BasicLeftToRightTransition(1000);
		let nextScreen = new ColoredScreen({ color: data.nextColor, nextColor: data.color })
		application.run(transition, application.first, nextScreen);
	}
}
let ColoredScreen = Container.template($ => ({
	top: 0, bottom: 0, left: 0, right: 0,
	skin: new Skin({ fill: $.color }),
	contents: [
		Content($, {
			active: true, height: 100, width: 100,
			skin: new Skin({ fill: $.nextColor }),
			Behavior: SwitchScreenBehavior
		})
	]
}));
application.add(new ColoredScreen({ color: "red", nextColor: "blue" }));

Prototype Description

Prototype inherits from Object.prototype.

Properties
NameTypeDefault ValueRead OnlyDescription
duration number250The duration of the transition, in milliseconds
Functions

onBegin(container [, ...])

ArgumentTypeDescription
containercontainerThe container object that is running the transition
...*Zero or more extra parameters

Invoked when this transition starts. The extra parameters are the extra parameters of the call to the run function that bound this transition to the specified container object.


onEnd(container [, ...])

ArgumentTypeDescription
containercontainerThe container object that is running the transition
...*Zero or more extra parameters

Invoked when this transition ends. The extra parameters are the extra parameters of the call to the run function that bound this transition to the specified container object.


onStep(fraction)

ArgumentTypeDescription
fractionnumberThe ratio of the time elapsed and the duration of this transition, as a number between 0 and 1 (inclusive)

Called while this transition is running; called at least twice (with a fraction parameter of 0 and 1) and at most at the display refresh rate--for example, 60 times a second