- Move ← ↑ → ↓ or tap on target to navigate
- Double tap to view overflow content or select text
[Mouse]
- Click & drag (← ↑ → ↓)
[Scroll wheel]
- Scroll (↑ ↓)
- Shift key + scroll (← →)
[Keyboard]
- Arrow keys (← ↑ → ↓)
- Spacebar / Shift + Spacebar to skip multiple nodes (↑ ↓)
- PageUp / PageDown to skip multiple nodes (↑ ↓)
- Home / End to skip to first or last node (↑ ↓)
- Shift + [PageUp / PageDown / Home / End] (← →)
[Touch]
- Swipe (← ↑ → ↓)
[Mouse/Touch]
- Tap on target
(to view overflow content or select text)
[Mouse/Touch]
- Double tap
[Keyboard]
- Enter key
Noodel - which stands for node view model - is a beautiful, dynamic user interface for digital content. It offers a way to present content that is modern, intuitive, and adaptable.
Noodel is currently available as Noodel.js, an open source JavaScript library for use in web-based projects.
Noodel requires you to arrange your content into a tree of nodes, where each node contains a distinct chunk of content.
Your content tree will be presented on an infinite canvas that you can navigate by simply moving up, down, left and right.
Blocks of content will show or hide as you move through the tree, keeping only the relevant subtree visible. Think of it like an infinite cascade of drop-down menus - but much more elegant and useful.
As websites and applications grow larger and more complicated, so too will UI features provided for navigation - like table of contents, menus and sidebars. However, these components add clutter to the UI, and are generally hard to use on small screens and touch devices.
Noodel is a system designed from the ground up that aims to present content in a better way. Originally intended as an idea for navigating tree hierarchies, it has evolved to become an incredibly versatile system for displaying content in general. Inspired by the "right = enter, left = exit" paradigm of UI design, as well as 4-way swipe motions that are increasingly utilised by mobile apps, Noodel allows you to integrate navigation with the content organically without requiring any extra UI components.
At the maximum, you can use Noodel to present a full website or app as an interactive content tree. It can be used for virtually anything - from static blogs or wikis, to dynamic apps with complex control flow.
At the minimum, you can use Noodel as a versatile UI plugin for responsive slideshows or hierachical data.
Noodel is simple and intuitive. Most people immediately understand how it works. It aims to leverage the user's spatial memory for navigation, and reduce screen clutter and cognitive load.
Noodel's layout and navigation mechanism remains identical regardless of screen size and input method. By reducing the essential controls to 4-way movements, it can be easily used in contexts where control ability is limited.
Everything about Noodel is designed to be flexible - from its fully customizable styles and layout, to what kind of content you can put in.
Noodel is more than just a static content viewer, although you can certainly use it that way. It provides an extensive API with navigation methods and getters, and allows you to insert, update or delete nodes at any time.
Noodel is built with performance in mind using modern best practices. It uses the powerful Vue.js library under the hood for DOM management and updates.
And finally, who doesn't like an interface that feels like it walked out from a sci-fi movie? Noodel is responsive, interactive and comes with fancy animation effects. It's just cool.
The container for a unit of content in Noodel is called a node - just like the one you're looking at right now. Nodes are the basic building blocks for your content.
Each node can have one or more ordered child nodes that have their own units of sub-content. This can repeat infinitely to form a tree of any size.
Noodel encourages you to break down large blocks of content into smaller chunks, which is generally good for readability.
A node should never exceed the size of the viewport - a precondition for node-based navigation.
A noodel (i.e. node view model) refers to the whole content tree formed by nodes.
If a node has children, it must have exactly 1 child that's active. The descendants of the active child will be shown while the others hidden.
At any given time, only the children of nodes on the lineage of active nodes starting from the root are shown. This tree of visible content is called the active tree.
The container (slider) for a list of sibling nodes is called a branch.
In other words, a branch refers to a node's list of children. Each branch is always uniquely associated with a node - the parent node of the branch.
The axis on which nodes are ordered in branches is called the branch axis. It is vertical (top to bottom) by default.
The container (slider) for the list of branches in the active tree, ordered from ancestors to descendants, is called the trunk.
The axis on which branches are ordered in the trunk is called the trunk axis. It is horizontal (left to right) by default.
The root node is an invisible node that serves as the parent of the topmost branch (i.e. the root of the tree), and always exists.
The level refers to the depth of a node (or branch) in the tree. The root node has level 0, its children (and branch) has level 1, and so on.
The branch that the view is currently focusing on is the focal branch. Moving in the trunk axis changes the focal branch.
The active node inside the focal branch is the focal node. Moving in the branch axis changes the active node of the focal branch.
The focal node is the node the view is centred on, and currently interacting with the user.
You can use Noodel by directly embedding its script and CSS into your HTML:
// You should specify the version number (e.g<EMAIL_ADDRESS>in production

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/noodel/dist/noodel.min.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/noodel/dist/noodel-default.min.css">
Noodel can be obtained via npm-linked CDNs such as jsdelivr and unpkg. It is bundled as a UMD package and available in minimized (production) and non-minimized (development) versions.
There is a separate build of Noodel called noodel-no-vue.umd.js
. This version comes
without Vue.js bundled and is intended to be used in Vue projects where the Vue
script is already included, to prevent including Vue twice. See Usage with Vue for more details.
For more complex projects that use bundlers, install from npm:
npm install noodel
And import into your code:
import Noodel from 'noodel'
// Don't forget to also include the CSS from Noodel's module directory
Noodel comes with a "core" stylesheet, noodel.css
,
and a theming stylesheet, noodel-default.css
.
The core stylesheet contains styles critical for Noodel's functioning and needs to be included in all cases.
The theming stylesheet provides a default grayscale theme with basic transitions for Noodel's visual effects. You can include this stylesheet and tweak it for customization, or replace it altogether with your own custom theme. See Styling for more details.
Creating a noodel is simple. The basic operations are:
// Creates a view model based on the given content tree
const noodel = new Noodel(contentTree);
// Renders the view into an element on the page
noodel.mount(container);
The contentTree is an element selector or array of objects that specifies the content tree, and container is the target container element for placing the noodel.
For sites driven by static HTML templates, you can define the tree via HTML and give the root element to the constructor:

My first node

My second node

First child of my second node

Noodel will traverse the descendants of the container element and convert
all

s with
class="node"
into
Noodel's nodes, keeping the parent-child relationships. Any text or
elements inside a node that are not child nodes will be treated as the
content of that node, concatenated in the order they appear.
This concatenation preserves the markup of the content elements so you have complete freedom in structuring and styling the content of each node.
Note that the actual DOM nodes in the definition will not be placed into Noodel's element tree. This means that side effects such as event listeners attached to them will not be carried over.
Alternatively, for dynamic sites/apps driven by JavaScript, you can specify the content tree as an array of objects corresponding to nodes on the first level:
const contentTree = [
{
content: "
My first node
"
},
{
content: "
My second node
"
children: [
{
content: "
First child of my second node
"
}
]
}
];
const noodel = new Noodel(contentTree);
noodel.mount("#noodel");
⚠ Always use trusted HTML strings as content. Never use unsanitized strings from user input.
Setting options can only be done via JavaScript. If your noodel is defined by an HTML template you still need to set your noodel and node options programmatically.
// setting options for individual nodes
const nodeDefinition = {
options: {
showChildIndicator: false,
focalAnchorTrunk: (size) => size / 3
}
}
// setting global options for the noodel
const noodel = new Noodel([nodeDefinition], {
visibleSubtreeDepth: 5,
focalAnchorTrunk: (size) => size / 4
});
By default, a unique ID will be generated for each node, which will be used for various purposes. You can provide your own ID for nodes using a data attribute:

...

or in JavaScript:
const nodeDefinition = {
id: "myCustomId",
}
Your custom ID must be unique and should not start with "_" as it may conflict with Noodel's default IDs.
By default, the initial active child for each node is at index 0 (the first child). You can specify another child to be initially active by using:

...

or in JavaScript:
const nodeDefinitions = [
{
content: "First child"
},
{
isActive: true, // this node will be active instead
content: "Second child"
},
];
You can assign custom CSS classes/styles to the various DOM elements associated with each node. See here for the list of different elements you can style.

...

or in JavaScript:
const nodeWithCustomStyles = {
classNames: {
node: "myClassA myClassB",
contentBox: "myClassC"
},
style: {
contentBox: "color: green; max-width: 900px;"
}
}
You can optionally define content that will be associated with a node's child branch rather than individual nodes. This branch content will only be displayed if the node has a branch (i.e. has at least 1 child).
For HTML templates this is specified via a div with the class "branch-content":

Some node content...

Any content inside here will be treated as branch content

or in JavaScript:
const nodeDefinition = {
content: "node with branch content",
branchContent: "this is a special branch"
}
You can attach one or more event listeners for each event on both the noodel and its individual nodes. See here for the list of events available.
const noodel = new Noodel([]);
const onFocalNodeChange = () => console.log("focal node has changed");
const anotherListener = () => console.log("another listener triggered");
noodel.on("focalNodeChange", onFocalNodeChange); // attach listener
noodel.on("focalNodeChange", anotherListener); // attach another listener
noodel.off("focalNodeChange", onFocalNodeChange); // detach listener
By default, a noodel responds to four types of user input for navigation: swipe(drag), keyboard, scroll wheel, and tap. Navigation will occur even when such input originates from content elements inside nodes.
This behaviour can be undesirable when you have UI elements that should capture those inputs and prevent them from causing navigation, e.g. a slider or a textbox.
To address this issue, Noodel provides the following "prevention classes" that you can selectively apply to individual elements in your content:
nd-prevent-swipe
nd-prevent-key
nd-prevent-wheel
nd-prevent-tap
Noodel will ignore the input that originates from an element (or its descendants) with the corresponding prevention class and stops it from triggering any Noodel-specific behaviour.

<input type="text" class="nd-prevent-swipe nd-prevent-key"></input>
<button class="nd-prevent-tap">Submit</button>

You should use prevention classes sparingly, on elements that really need them. Having large blocks of content with navigation prevention may impact usability, especially on smaller screens.
For situations that require extensive navigation prevention, you should rely on the inspect mode instead. Alternatively, you can disable the corresponding input in Noodel's options and provide your own means of navigation via Noodel's API.
For swipe-based interfaces such as Noodel, there is always an unavoidable conflict between the swipe mechanism and native mechanisms that depend on the same motion, such as text selection.
The inspect mode is the solution Noodel offers to address this issue. By default, text selection is disabled on a noodel and all input directed towards navigation. Once inspect mode is on, all navigation methods will be suspended and the user is free to select text or perform other conflicting interactions e.g. drag-and-drop in the focal node.
It is recommended that you rely on inspect mode, in addition to prevention classes, to deal with situations where UI elements in your content conflict with Noodel's mechanism.
The default trigger for inspect mode is the double tap (on any area of the noodel), or the Enter key on a keyboard.
This trigger is chosen for maximum convenience and compatibility, but like anything else it does end up conflicting with interactions such as multiple clicks to select a word/line. If you wish to prevent the default trigger you can always disable it through Noodel's options and provide your own means of toggling inspect mode (e.g a custom button) via Noodel's API.
The inspect mode is also used for viewing overflow content in nodes. Scrolling inside nodes is disabled normally but enabled during inspect mode.
Noodel is based on the principle of content chunking. Because each node has a limited space, as a general rule, you should try to break down large blocks of content into bite-sized pieces that can fit into individual nodes.
However, this can be impractical in many situations, so inspect mode is provided as a fallback for viewing overflow content.
The object instance you get when you create a noodel is its "view model". You can also obtain the view model of individual nodes via methods on the noodel instance.
These view models have 2-way sync with the view, and provide extensive API methods for you to dynamically query and update almost every aspect of the content tree.
// view model of whole noodel
const noodel = new Noodel(...);
// view model of an individual node
const currentFocalNode = noodel.getFocalNode();
Each view model of a node is uniquely associated with a node in the tree. This means you can do things such as compare the equality of two nodes by simply comparing the reference of their view model objects.
const noodel = new Noodel(...);
const node = noodel.findNodeById("someNode");
// move to the next node
noodel.moveForward();
// move 2 steps back towards ancestors
noodel.moveOut(2);
// move to the 3rd branch in the active tree
noodel.setFocalLevel(3);
// jump to a specific node
node.jumpToFocus();
const node = noodel.findNodeById("someNode");
// update node content
node.setContent("new content");
// update node styles
node.setStyles({
contentBox: "color: green"
});
// update node options
node.setOptions({
focalAnchorTrunk: () => 100
})
Note that updating content replaces the original content by replacing the innerHTML of the container. The original content elements will be removed.
const rootNode = new Noodel([{}]).getRoot();
// insert nodes and their descendants at index 0
rootNode.insertChildren([
{
content: "Fruits!",
children: [
{
content: "Tomatoes!"
}
]
},
{
content: "Vegetables!"
}
], 0);
// you can also insert new nodes from an HTML template
rootNode.insertChildren("#nodeDefinition");
// delete nodes
rootNode.deleteChildren(1, 2);
Noodel will always try to preserve the current focal node during insertion and deletion, if possible. This means that if the current focal node is at index 3, and you insert a node at index 1, the focal node becomes the node at index 4, and no navigation will occur.
Navigation only happens when a deletion includes the focal node. In that case the focus will go to an adjacent node or branch, as necessary.
The noodel's view state is independent of whether it's mounted or not. You can mutate it while the noodel is not mounted and the change will persist.
const noodel = new Noodel(...);
// make jump before view is mounted
noodel.jumpTo(noodel.findNodeById("firstFocus"));
// the view will focus on the "firstFocus" node initially
noodel.mount("#container");
// the view model is still focused on the same node after unmount
noodel.unmount();
noodel.getFocalNode().getId(); // ==> "firstFocus"
When using Noodel's API, all changes to Noodel's view model are synchronous, while any DOM updates triggered by these changes will be asynchronous. This means that, if you need to do operations that depends on the updated DOM state, you must wait for the updates to settle before doing so.
The nextTick()
function is Noodel's preferred
way to wait for DOM updates to fully complete and settle.
One common use case is to wait for the view to mount before querying a DOM element:
noodel.mount("#noodel");
noodel.nextTick(() => {
// gets the canvas element after the view is actually mounted
const canvasEl = noodel.getEl();
});
Another use for nextTick()
is to properly sequence
certain visual effects:
// this operation inserts a node, then jumps to it
const newNode = someNode.insertChildren([{}], 1)[0];
// Because it takes one DOM update cycle to capture the size of new nodes, the movement may glitch if you do this synchronously. Using nextTick will make the animation smooth.
noodel.nextTick(() => {
newNode.jumpToFocus();
});
If you find the visual effects of some compound operations not going as expected, often
nextTick()
will do the trick.
Noodel has a variety of layout options that, when used in combination, can customize the layout in almost every way you can think of.
To use these options properly, you need to understand the concepts of the branch axis and the trunk axis, which are used in place of the horizontal and vertical axes depending on the noodel's orientation.
The orientation
option specifies the direction of the
trunk axis, and can be either ltr (default), rtl, ttb (top-to-bottom) and btt
(bottom-to-top).
The branch direction
option specifies how a branch layout
its nodes, and can be either "normal" (default) or "reverse". When
the trunk axis is the horizontal axis (i.e. ltr or rtl), "normal" puts nodes from top to
bottom, and "reverse" the opposite. When the trunk axis is the vertical axis,
"normal" puts nodes from left to right, and "reverse" the opposite.
The focal offsets specify the "snap-to lines" on the canvas where the focal branch and active nodes align to, on their respective axis. These are calculated as a function of the canvas length, and defaults to 1/2 of the canvas length (i.e. the center).
The anchor offsets specify the "snap-to lines" on each branch/node that should be aligned to the focal offset, on their respective axis, when they become focal or active. These are calculated as a function of the length of the branch/node, and defaults to 1/2 of their length (i.e. the center).
These offsets can be specified globally and/or customized on each individual node. When used in combination, you can decide how and where the branches and nodes align in a highly flexible way.
Note that you can return just a constant in these functions for a fixed offset.
Also note that the "origins" referenced by these offsets are different depending on the orientation and branch direction. E.g. For an ltr layout with normal branch direction, the origin for the trunk axis is the left edge and the origin for the branch axis is the top edge. For an rtl layout with reverse branch direction, the origin for the trunk axis is the right edge and the origin for the branch axis is the bottom edge.
In Noodel v3, automatic resize detection has been removed in favor of a manual approach, to address some limitations and improve performance.
If the noodel is
mounted,
and something happens that causes the size of nodes/branches/canvas to change,
you should immediately call one of Noodel's various realign()
methods to register the size change and reposition elements as necessary.
// this operation will cause the size of someNode to change on both axes
someNode.setStyle({
contentBox: "width: 200px; height: 300px"
});
// immediately call realign to capture node resize on the branch-axis
someNode.realign();
// parent need to realign branch since the change also caused branch resize on the trunk-axis
someNode.getParent().realignBranch();
The realignAll()
method is a convenience method for realigning everything at once. This
is useful
in situations such as when everything is styled based on viewport units, and the
viewport size changed.
Since this is a more expensive operation it should be used carefully.
// if everything is dependent on viewport units...
window.addEventListener("resize", () => {
noodel.realignAll();
});
// ideally, you should debounce the function above for better performance
Noodel has a routing capability which is enabled by default. This allows Noodel to control the hash of your URL to sync with the location of the current focal node. It will use the ID of the focal node as the fragment identifier.
This allows you to use the browser's history navigation to jump between nodes, as well as create URL links that target specific nodes in a noodel.
If routing is enabled at a noodel's creation, it will check the URL to jump to an initial focal node if its ID is equal to the hash. The sync between the focal node and the URL hash happens regardless whether the noodel is mounted.
Only explicit changes to the URL (e.g. by clicking on a link) will cause a new entry to be pushed to the browser history. Noodel uses history.replaceState() to replace the URL hash as you navigate around the noodel to prevent creating too many unnecessary entries. This includes when you use Noodel's API to navigate.
If you need to do a programmatic navigation that pushes to the history stack, you should change the URL hash to point to the target node instead of using Noodel's API.
You should use routing on one noodel per page only (ideally, when you use a single noodel to control a site). Routing behaviour for multiple noodels on the same page is not well defined.
Due to the fact that Noodel does not use native scrolling for its navigation, basic Ctrl+F search in browsers will not be able to jump to individual occurrences. You may need to implement your own search function for your noodel.
For a simple DOM based text search plugin for Noodel, see noodel-search.
You can control most aspects of Noodel's appearance using plain CSS, by extending/overriding Noodel's CSS classes, or by setting custom class/styles on individual nodes.
In addition, you have complete freedom in structuring and styling the content inside your nodes.
Noodel comes with a "core" stylesheet that determines the layout, and a theming stylesheet with a default theme. While you must keep the core stylesheet, you can override or replace the CSS rules in the theming stylesheet as you see fit.
All of Noodel's DOM elements have various built-in CSS classes attached dynamically. See CSS classes for the list of classes you can work with.
You can specify custom class/styles for each node that will be applied to the
nd-node
element. This is useful when you need
to have different types of nodes (e.g large vs small) in the same tree.
See specifying custom class/styles for example.
The size of nodes are completely flexible - they are simply placed in a flex container, and will grow or shrink to fit their content while respecting any CSS rules applied.
This means you can control the size of nodes by specifying their various height, width and flex properties. In addition, you can style your content and let them influence the size of their node containers.
As an example, it's very easy to use Noodel to create a full-page carousel site, with some simple CSS overrides:
.nd-canvas {
height: 100vh;
width: 100vw;
}
.nd-node {
height: 100vh;
width: 100vw;
}
All animations in Noodel are done via CSS transitions. This means you can control the duration and timing functions of all animations via CSS overrides of the corresponding classes.
Enter/leave animations make use of the transition classes of Vue.js. You can apply any combination of them according to your needs.
Movement animations use transitions of the CSS transform property. These should be specified on the nd-xxx-move classes for the corresponding element, and should only be specified on these classes. The move classes are always attached on their elements and temporarily removed when necessary to disable transform transitions.
Noodel uses Vue.js internally and hence provides integration with Vue out of the box. Noodel is available as a Vue component, and also allows you to use Vue components as the content for individual nodes.
If you are including Noodel and Vue's scripts directly in your HTML, it is recommended that you use Noodel's Vue-less build, alongside the Vue script used in your main project (Noodel requires Vue V3). This prevents Vue from being included twice.
If you are using Noodel via a bundler, the default entry is the Vue-less build and the bundler should be able to take care of bundling Vue as a dependency.
Noodel only needs Vue's runtime script. If you need to compile templates in runtime you need to include Vue's compiler script separately.
Noodel's Vue component is exposed as a static variable on the Noodel class, which can be used like any other Vue components. The way to use it is as follows:
import Noodel from 'noodel';
import { createApp } from 'vue';
const NoodelComponent = Noodel.VueComponent;
const app = createApp({
component: {
NoodelComponent
},
template: '<NoodelComponent :noodel="noodel.getState()"/>',
data: {
noodel: new Noodel([])
}
});
app.mount("#el");
Noodel's Vue component takes a single prop, noodel, which must be the internal
state tree of a Noodel instance that you can obtain via getState()
.
It is important that you do not modify this state tree yourself, but instead use the API methods provided on the Noodel instance to do so.
You are not required to register the Noodel instance as reactive data. However, there is no harm in doing so (like in the example) if it suits how you manage your state in your Vue project.
⚠ You should NOT call Noodel's
mount()
or unmount()
when using Noodel
as a Vue component. It is simply a component that gets mounted and unmounted with your
Vue instance.
You can pass Vue components as node content and they will be rendered via Vue's dynamic
component feature, i.e.
<component :is="yourComponent"></component>
.
To do so, you need to provide an object as node content:
const noodel = new Noodel([
{
content: {
component: YourVueComponent, // your Vue component reference
props: { // name-value pairs of props to pass to this component
"propA": "abc",
"propB": 20
},
eventListeners: { // name-value pairs of event listeners to attach onto the component
"onButtonClick": () => console.log("button click")
}
}
}
]);
Noodel is completely written in TypeScript, fully typed and documented.
You don't need to install any additional type declarations - they come bundled out of the box when you install via npm.
Noodel is targeted to work on all major modern browsers.
Support for IE 10 and 11 is best-effort only - Noodel should work on these browsers, but there may be quirks and bugs in some features.
IE 9 and below are not supported.
The view model of a noodel. Has 2-way binding with the view.
constructor(contentTree: NodeDefinition[] | Element | string, options?: NoodelOptions)
Creates the view model of a noodel based on the given content tree.
contentTree
Initial content tree for the noodel.
Can be
an array of NodeDefinition
objects that specify nodes on the first level, an HTMLElement that contain templates
for nodes on
the first level, or a selector string for such an element. If nothing is provided,
will
create an empty
noodel with just the root.
options
Global options for the noodelmount(el: string | Element)
Mounts the noodel's view into the target container element.
unmount()
Destroys the noodel's view and removes it from the DOM, but keeps the current state of the view model.
nextTick(callback: () => any)
Schedules a callback function to be called after Noodel's current processing cycle. Use this to wait for an operation to be fully processed and reflected in the DOM before the next operation.
getState(): object
Get the internal reactive state tree of this noodel. Only intended to be used as props to the Vue component in a Vue app. Should not be modified directly.
getOptions(): NoodelOptions
Gets the options applied to this node. Returns a cloned object.
getEl(): HTMLDivElement
Gets the container element of this noodel (i.e. nd-canvas), if mounted.
getFocalLevel(): number
Gets the level of the current focal branch. The first branch has level 1.
getActiveTreeHeight(): number
Gets the height (total number of levels) in the current active tree, excluding the root.
getNodeCount(): number
Gets the number of nodes in this noodel (excluding the root).
getRoot(): NoodelNode
Gets the root node.
getFocalParent(): NoodelNode
Gets the parent node of the current focal branch. Returns the root if there's no focal branch (i.e. noodel is empty).
getFocalNode(): NoodelNode
Gets the current focal node. Returns null if noodel is empty.
findNodeByPath(path: number[]): NoodelNode
Gets the node at the given path, an array of 0-based indices starting from the root. Returns null if no such node exist.
findNodeById(id: string): NoodelNode
Gets the node with the given ID. Returns null if no such node exist.
isInInspectMode(): boolean
Check if this noodel is in inspect mode.
setOptions(options: NoodelOptions)
Updates the options of the noodel. Properties of the given object will be merged into the current options.
setFocalLevel(level: number)
Navigates the noodel to focus on the branch at the given level of the current active tree. If the level is greater or smaller than the possible limits, will navigate to the furthest level in that direction.
moveIn(levelCount?: number)
Navigates toward the child branches of the current focal node.
levelCount
number of levels to move, defaults to 1
moveOut(levelCount?: number)
Navigates toward the parent branches of the current focal node.
levelCount
number of levels to move, defaults to 1
moveForward(nodeCount?: number)
Navigates toward the next siblings of the current focal node.
nodeCount
number of nodes to move, defaults to 1
moveBack(nodeCount?: number)
Navigates toward the previous siblings of the current focal node.
nodeCount
number of nodes to move, defaults to 1
toggleInspectMode(on: boolean)
Turns inspect mode on/off.
realignCanvas()
Recapture the size of the canvas and adjust the noodel's position if necessary. Use immediately after an operation that changes the size of the canvas. Does nothing if the noodel is not mounted.
realignAll()
Recapture the size of the canvas, ALL nodes and ALL branches, and realign positions if necessary. Use this if you need to align everything after a size change. Does nothing if the noodel is not mounted.
on(ev: string, listener: Function)
Attach a listener for the given event.
off(ev: string, listener: Function)
Remove a listener for the given event.
focalNodeChange
Event triggered every time the focal node has changed.
(current: Node, prev: Node) => any
current
the current focal nodeprev
the previous focal nodefocalParentChange
Event triggered every time the focal parent has changed.
(current: Node, prev: Node) => any
current
the current focal nodeprev
the previous focal nodeenterInspectMode
Event triggered after entering inspect mode.
() => any
exitInspectMode
Event triggered after exiting inspect mode.
() => any
The view model of a node. Has 2-way binding with the view.
getEl(): HTMLDivElement
Gets the nd-node element associated with this node. Returns null if noodel is not mounted.
getBranchEl(): HTMLDivElement
Gets the nd-branch element associated with this node's child branch. Returns null if noodel is not mounted or branch does not exist.
getParent(): NoodelNode
Gets the parent of this node. Return null if this is the root or has been detached from its parent by a delete operation.
getPath(): number[]
Gets the path (an array of zero-based indices counting from the root) of this node.
getDefinition(deep?: boolean): NodeDefinition
Extracts the definition of this node, returning a NodeDefinition object containing this node's base properties. Useful for serialization or cloning.
deep
whether to extract a deep definition tree
including descendants, defaults to falsegetChild(index: number): NoodelNode
Gets the child of this node at the given index. Return null if does not exist.
getChildren(): NoodelNode[]
Gets a copied array of this node's list of children.
getChildCount(): number
Gets the number of children of this node.
getActiveChildIndex(): number
Gets the index of the active child. Returns null if there's no active child.
getActiveChild(): NoodelNode
Gets the active child of this node. Return null if there's no active child.
getId(): string
Gets the ID of this node.
getContent(): string | ComponentContent
Gets the content of this node. If content is a ComponentContent object, will return a deeply cloned object except the 'component' property which is shallowly copied.
getBranchContent(): string | ComponentContent
Gets the branch content of this node. If content is a ComponentContent object, will return a deeply cloned object except the 'component' property which is shallowly copied.
getClassNames(): NodeCSS
Gets a cloned object containing the custom CSS classes applied to this node.
getStyle(): NodeCSS
Gets a cloned object containing the custom styles applied to this node.
getOptions(): NodeOptions
Gets a cloned object containing the options applied to this node.
getIndex(): number
Gets the 0-based index (position among siblings) of this node. Returns 0 if this node has been detached from its parent by a delete operation.
getLevel(): number
Gets the level of this node. Returns null if this node has been deleted.
isRoot(): boolean
Check whether this node is the root.
isActive(): boolean
Check whether this node is active.
isFocalParent(): boolean
Check whether this node is the parent of the focal branch.
isInFocalBranch(): boolean
Check whether this node is inside the focal branch.
isFocalNode(): boolean
Check whether this node is the focal node.
isVisible(): boolean
Check whether this node is visible (i.e is part of the active tree in display).
isBranchVisible(): boolean
Check whether this node's child branch is visible (i.e is part of the active tree in display).
isDeleted(): boolean
Check whether this node has been deleted from its noodel.
setId(id: string)
Sets the ID of this node.
id
new ID for this node, should not start with '_'
setContent(content: string | ComponentContent)
Sets the content of this node.
setClassNames(className: NodeCss)
Sets the custom class names for this node. Properties of the provided object will be merged into the existing object.
setStyles(styles: NodeCSS)
Sets the custom inline styles for this node. Properties of the provided object will be merged into the existing object.
setOptions(options: NodeOptions)
Sets the options for this node. Properties of the provided object will be merged into the existing object.
setActiveChild(index: number)
Changes the active child of this node. If doing so will toggle the visibility of the focal branch (i.e this node is an ancestor of the focal branch), the view will jump to focus on the new active child.
jumpToFocus()
Performs a navigational jump to focus on this node. Cannot jump to the root.
insertChildren(defs: NodeDefinition[] | string | Element, index?: number): NoodelNode[]
Inserts one or more new nodes (and their descendants) as children of this node. Will always preserve the current active child if possible. Returns the list of inserted nodes.
defs
array or HTML template that specifies the
definitions of the new node(s)index
index to insert at, will append to existing
children if omittedinsertBefore(defs: NodeDefinition[] | string | Element): NoodelNode[]
Convenience method for inserting sibling node(s) before this node.
insertAfter(defs: NodeDefinition[] | string | Element): NoodelNode[]
Convenience method for inserting sibling node(s) after this node.
deleteChildren(index: number, count: number): NoodelNode[]
Deletes one or more children (and their descendants) of this node. If the active child is removed, will set the next child active, unless the child is the last in the list, where the previous child will be set active. If the focal branch is deleted, will move focus to the nearest ancestor branch. Returns the list of deleted nodes.
index
index to delete fromcount
number of children to delete, will limit to
maximum if greater than possible rangedeleteBefore(count: number): NoodelNode[]
Convenience method for deleting sibling node(s) before this node.
count
number of nodes to remove, will limit to
maximum if greater than possible rangedeleteAfter(count: number): NoodelNode[]
Convenience method for deleting sibling node(s) after this node.
count
number of nodes to remove, will limit to
maximum if greater than possible rangedeleteSelf()
Convenience method for deleting this node itself.
reorderChildren(func: (children: NoodelNode[]) => NoodelNode[])
Reorders the children of this node without using insert/delete operations, and triggers FLIP animation (if enabled). Will always preserve the current active child.
func
The reorder function. Takes the array of
children of this node as parameter,
and must return an array containing the exact same set of nodes, possibly in a
different ordertraverseSubtree(func: (node: NoodelNode) => any, includeSelf: boolean)
Do a preorder traversal of this node's subtree and perform the specified action on each descendant.
func
the action to performincludeSelf
whether to include this node in the
traversalrealign()
Recapture the size of this node (on the branch axis) and adjust the branch's position if necessary. Use immediately after an operation that changes the size of this node (on the branch axis). Does nothing if this is the root or noodel is not mounted.
realignBranch()
Recapture the size of this node's child branch (on the trunk axis) and adjust the trunk's position if necessary. Use immediately after an operation that changes the size of this node's child branch (on the trunk axis). Does nothing if this has no children or noodel is not mounted.
on(ev: string, listener: Function)
Attach an event listener on this node.
off(ev: string, listener: Function)
Remove an event listener from this node.
enterFocus
Event triggered after this node entered focus.
(prev: NoodelNode) => any
prev
the previous focal nodeexitFocus
Event triggered after this node exited focus.
(current: NoodelNode) => any
current
the current focal nodechildrenEnterFocus
Event triggered after this node's child branch entered focus.
(prev: NoodelNode) => any
prev
the previous focal parentchildrenExitFocus
Event triggered after this node's child branch exited focus.
(current: NoodelNode) => any
current
the current focal parentObject template used for node creation and insertion.
id?: string
ID of this node. If provided, must be unique and should NOT start with "_" .
children?: NodeDefinition[]
Children nodes of this node. Defaults to an empty array.
isActive?: boolean
If provided, will mark this node as active, overriding the default (first child). If multiple siblings are marked as active, only the first one will take effect.
content?: string | ComponentContent
Content of this node. If is a string, will be inserted as innerHTML of the nd-content-box element. Can also be a ComponentContent object that wraps a Vue component.
branchContent?: string | ComponentContent
Content for this node's child branch. If is a string, will be inserted as innerHTML of the nd-branch-content-box element. Can also be a ComponentContent object that wraps a Vue component. Only rendered if this node has a child branch (i.e. has at least 1 child).
classNames?: NodeCss
An object specifying custom CSS class(es) to apply to various elements associated with a node. Each property should be a string of one or more classes delimited by spaces.
styles?: NodeCss
An object specifying custom CSS styles to apply to various elements associated with a node. Each property should be a string in inline style format.
options?: NodeOptions
Options for this node.
Global options for a noodel.
visibleSubtreeDepth?: number
The number of levels of descendant branches to show after the current focal branch. Defaults to 1.
retainDepthOnTapNavigation?: boolean
If true, will keep the current branch depth (if possible) when tapping on the sibling of an ancestor. Useful to create an effect similar to conventional navigation menus. Defaults to false.
useKeyNavigation?: boolean
Whether to apply the default keyboard navigation. Defaults to true.
useWheelNavigation?: boolean
Whether to apply the default wheel navigation. Defaults to true.
useSwipeNavigation?: boolean
Whether to apply the default swipe navigation. Defaults to true.
useTapNavigation?: boolean
Whether to apply the default tap navigation. Defaults to true.
useInspectModeKey?: boolean
Whether to allow toggling inspect mode via the Enter key. Defaults to true.
useInspectModeDoubleTap?: boolean
Whether to allow toggling inspect mode via the double tap. Defaults to true.
useRouting?: boolean
Whether routing should be enabled for this noodel. Defaults to true.
swipeMultiplierBranch?: number
Number of pixels to move for every pixel swiped in the branch axis. Defaults to 1.
swipeMultiplierTrunk?: number
Number of pixels to move for every pixel swiped in the trunk axis. Defaults to 1.
snapMultiplierBranch?: number
Number of nodes (per unit of velocity) to snap across after a swipe is released. Defaults to 1.
snapMultiplierTrunk?: number
Number of levels (per unit of velocity) to snap across after a swipe is released. Defaults to 1.
showLimitIndicators?: boolean
Whether to render the limit indicators of the canvas. Defaults to true.
showChildIndicators?: boolean
Whether to render the child indicators of nodes. Defaults to true.
orientation?: 'ltr' | 'rtl' | 'ttb' | 'btt'
Determines the direction of the trunk axis. Defaults to 'ltr' (left to right).
branchDirection?: 'normal' | 'reverse'
Determines the direction of the branch axis under the current trunk orientation. Defaults to 'normal'.
focalOffsetTrunk?: (canvasLengthTrunk: number) => number
A function that determines the trunk-axis offset on the canvas where each branch should align to if they become focal, given the trunk-axis length of the canvas as reference. Should return a number of pixels counting from the trunk-axis origin of the canvas. If the number is greater than the canvas length, will use the canvas length. Defaults to 1/2 of the canvas length.
focalOffsetBranch?: (canvasLengthBranch: number) => number
A function that determines the branch-axis offset on the canvas where each node should align to if they become active, given the branch-axis length of the canvas as reference. Should return a number of pixels counting from the branch-axis origin of the canvas. If the number is greater than the canvas length, will use the canvas length. Defaults to 1/2 of the canvas length.
anchorOffsetTrunk?: (branchLength: number) => number
A function that determines the trunk-axis offset on each branch that should align to the focal offset if they become focal, given their length on the trunk axis. Should return a number of pixels counting from the trunk-axis origin of the branch. If the number exceeds the branch length, will use the branch length. Defaults to 1/2 of the branch length.
anchorOffsetBranch?: (nodeLength: number) => number
A function that determines the branch-axis offset on each node that should align to the focal position if they become active, given their length on the branch axis. Should return a number of pixels counting from the branch-axis origin of the node. If the number exceeds the node length, will use the node length. Defaults to 1/2 of the node length.
useFlipAnimation?: boolean
Whether to apply FLIP animations when inserting, deleting or reordering nodes. If true, you must also specify CSS transition of the transform property for nodes via the nd-node-move class. Defaults to false.
Options for an individual node.
showChildIndicator?: boolean | null
If set to a boolean, will override the global showChildIndicators option for this specific node. Defaults to null.
focalOffsetTrunk?: (canvasLengthTrunk: number) => number
If set to a function, will override the global focalOffsetTrunk option for this specific node's child branch. Defaults to null.
focalOffsetBranch?: (canvasLengthBranch: number) => number
If set to a function, will override the global focalOffsetBranch option for this specific node. Defaults to null.
anchorOffsetTrunk?: (branchLength: number) => number
If set to a function, will override the global anchorOffsetTrunk option for this specific node's child branch. Defaults to null.
anchorOffsetBranch?: (nodeLength: number) => number
If set to a function, will override the global anchorOffsetBranch option for this specific node. Defaults to null.
useFlipAnimation?: boolean
If set to a boolean, will override the global useFlipAnimation option for this specific node's child branch. Defaults to null.
Object template used for passing a Vue component as node content.
component: string | object | Function
Vue component to be rendered using Vue's <component> tag. Can be name or component reference.
props?: object
Name-value pairs of props to pass to this component.
eventListeners?: object
Name-value pairs of event listeners to pass to this component.
Object template used for specifying custom CSS classes and styles on nodes.
node: string
CSS applied to the nd-node element.
contentBox: string
CSS applied to the nd-content-box element.
childIndicator: string
CSS applied to the nd-child-indicator element.
branch: string
CSS applied to the nd-branch element.
branchContentBox: string
CSS applied to the nd-branch-content-box element.
branchSlider: string
CSS applied to the nd-branch-slider element.
Lists of CSS classes provided and their associated elements.
nd-canvas
Outermost container of the noodel that processes all inputs.
nd-canvas-ltr, nd-canvas-rtl, nd-canvas-ttb, nd-canvas-btt, nd-canvas-normal, nd-canvas-reverse
Classes applied to the nd-canvas element depending on the current orientation and branch direction.
nd-canvas-inspect
Class applied to the nd-canvas element when in inspect mode.
nd-limit
The limit indicators (i.e. the bars that appear when you try to go beyond the view limits).
nd-limit, nd-limit-left, nd-limit-right, nd-limit-top
Classes applied to the nd-limit elements based on their absolute locations.
nd-limit-trunk-start, nd-limit-trunk-end, nd-limit-branch-start, nd-limit-branch-end
Classes applied to the nd-limit elements based on their locations relative to the trunk and branch axes.
nd-limit-[transition class]
Transition classes for enter/leave transitions of limit indicators.
nd-trunk
The trunk element. You should not need to style this element directly in most cases.
nd-trunk-move
Class applied to the nd-trunk element for specifying the transition effects of snap movements in the trunk axis.
nd-branch
Outermost container of a branch that occupies 100% length of the canvas on the branch axis.
nd-branch-focal
Applied to the nd-branch element of the focal branch.
nd-branch-level-[x]
Applied to every nd-branch element where x is the level of the branch.
nd-branch-[transition class]
Transition classes for enter/leave transitions of branches.
nd-branch-content-box
The container element for branch content specified for the branch.
nd-branch-slider
Direct container of nodes in a branch, and responsible for its movement in the branch axis.
nd-branch-slider-move
Applied to the focal nd-branch element.
nd-branch-move
Class applied to nd-branch elements for specifying the transition effects of snap movements in the branch axis.
nd-node
Outermost container of a node.
nd-node-active
Applied to nd-node elements that are active.
nd-node-[transition class]
Transition classes for enter/leave of nodes during node insertion and deletion.
nd-node-move
Class applied to nd-node elements for specifying the transition effects of FLIP animations during node insertion, deletion and reordering.
nd-content-box
Direct container of the content in a node.
nd-inspect-backdrop
The backdrop element that appears during inspect mode. Note that this element is a child of the nd-node element.
nd-inspect-backdrop-[transition class]
Transition classes for enter/leave of the backdrop.
nd-child-indicator
The child indicator element in a node that is rendered when the node has children.
nd-child-indicator-expanded
Applied to the nd-child-indicator element of a node that has visible children.
nd-child-indicator-[transition class]
Transition classes for enter/leave of child indicators during node insert/delete.
Contributions are most welcome! Please see here for details.
If you find Noodel useful or inspiring, please consider supporting the author 🙂
Or via GitHub Sponsors
MIT License
© 2019-present Zuohao (Jonny) Lu


This a callback function demo. The filter function will be
called using a call back function. any call back function can be passed to filter and it will
be executed on the array.
ArrayofNumber = [1,2,3,4,5,6,7,8,9,10,11,12]
Note: This is a demo of how call back function is called. on filter method. I am passing evencheck and oddcheck function to filter method


A Stacked area chart is the extension of a basic area chart. It displays the evolution of a numerical value for several groups on the same chart, stacked on top of each other. Stacked area chart has pros and cons, read more about it here.
The hardest part in stacked area chart creation is the use of the d3.stack()
function to stack the data. Once this step is done, each group can be added thanks to the d3.area()
function. I strongly advise to understand how to do a basic area chart before trying the examples below.
A stacked area chart showing the evolution of a few baby names in the US. Zoom on a specific time frame through brushing. Highlight a specific group by hovering the legend. Double click to unzoom.
Code hereThe efficiency of stacked area graph is discussed and it must be used with care. They are great to study the evolution of the whole and the relative proportion of each group. However, they are not appropriate to study the evolution of each individual group. (Read more). Using small multiple is often a good alternative to highlight the evolution of each group.


All accumulo properties have a default value in the source code. Properties can also be set in accumulo-site.xml and in zookeeper on per-table or system-wide basis. If properties are set in more than one location, accumulo will choose the property with the highest precedence. This order of precedence is described below (from highest to lowest):
| Location | Description |
|---|---|
| Zookeeper table properties |
Table properties are applied to the entire cluster when set in zookeeper using the accumulo API or shell. While table properties take precedent over system properties, both will override properties set in accumulo-site.xml Table properties consist of all properties with the table.* prefix. Table properties are configured on a per-table basis using the following shell commmand: config -t TABLE -s PROPERTY=VALUE |
| Zookeeper system properties |
System properties are applied to the entire cluster when set in zookeeper using the accumulo API or shell. System properties consist of all properties with a 'yes' in the 'Zookeeper Mutable' column in the table below. They are set with the following shell command:
config -s PROPERTY=VALUEIf a table.* property is set using this method, the value will apply to all tables except those configured on per-table basis (which have higher precedence). While most system properties take effect immediately, some require a restart of the process which is indicated in 'Zookeeper Mutable'. |
| accumulo-site.xml | Accumulo processes (master, tserver, etc) read their local accumulo-site.xml on start up. Therefore, changes made to accumulo-site.xml must rsynced across the cluster and processes must be restarted to apply changes. Certain properties (indicated by a 'no' in 'Zookeeper Mutable') cannot be set in zookeeper and only set in this file. The accumulo-site.xml also allows you to configure tablet servers with different settings. |
| Default | All properties have a default value in the source code. This value has the lowest precedence and is overriden if set in accumulo-site.xml or zookeeper. While the default value is usually optimal, there are cases where a change can increase query and ingest performance. |
The 'config' command in the shell allows you to view the current system configuration. You can also use the '-t' option to view a table's configuration as below:
$ ./bin/accumulo shell -u root Enter current password for 'root'@'ac14': ****** Shell - Accumulo Interactive Shell - - version: 1.4.0-incubating-SNAPSHOT - instance name: ac14 - instance id: 4f48fa03-f692-43ce-ae03-94c9ea8b7181 - - type 'help' for a list of available commands - root@ac13> config -t foo ---------+---------------------------------------------+------------------------------------------------------ SCOPE | NAME | VALUE ---------+---------------------------------------------+------------------------------------------------------ default | table.balancer ............................ | org.apache.accumulo.server.master.balancer.DefaultLoadBalancer default | table.bloom.enabled ....................... | false default | table.bloom.error.rate .................... | 0.5% default | table.bloom.hash.type ..................... | murmur default | table.bloom.key.functor ................... | org.apache.accumulo.core.file.keyfunctor.RowFunctor default | table.bloom.load.threshold ................ | 1 default | table.bloom.size .......................... | 1048576 default | table.cache.block.enable .................. | false default | table.cache.index.enable .................. | false default | table.compaction.major.everything.at ...... |<PHONE_NUMBER>0000GMT default | table.compaction.major.everything.idle .... | 1h default | table.compaction.major.ratio .............. | 1.3 site | @override .............................. | 1.4 system | @override .............................. | 1.5 table | @override .............................. | 1.6 default | table.compaction.minor.idle ............... | 5m default | table.compaction.minor.logs.threshold ..... | 3 default | table.failures.ignore ..................... | false


public abstract class TableHeaderAdapter
extends java.lang.Object
TableHeaderView
.| Modifier | Constructor and Description |
|---|---|
|
TableHeaderAdapter(Context context)
Creates a new TableHeaderAdapter.
|
protected |
TableHeaderAdapter(Context context,
int columnCount)
Creates a new TableHeaderAdapter.
|
protected |
TableHeaderAdapter(Context context,
TableColumnModel columnModel)
Creates a new TableHeaderAdapter.
|
| Modifier and Type | Method and Description |
|---|---|
protected int |
getColumnCount()
Gives the column count that is currently used to render the table headers.
|
protected TableColumnModel |
getColumnModel()
Gives the
TableColumnModel that is currently used to render the table headers. |
protected int |
getColumnWeight(int columnIndex)
Gives the column weight (the relative width of a column) of the column at the given index.
|
protected int |
getColumnWeightSum()
Gives the overall column weight (sum of all column weights).
|
Context |
getContext()
Gives the
Context of this adapter. |
abstract View |
getHeaderView(int columnIndex,
ViewGroup parentView)
Method that gives the header views for the different columns.
|
LayoutInflater |
getLayoutInflater()
Gives the
LayoutInflater of this adapter. |
Resources |
getResources()
Gives the
Resources of this adapter. |
protected void |
setColumnCount(int columnCount)
Sets the column count which is used to render the table headers.
|
protected void |
setColumnModel(TableColumnModel columnModel)
Sets the
TableColumnModel that will be used to render the table headers. |
protected void |
setColumnWeight(int columnIndex,
int columnWeight)
Sets the column weight (the relative width of a column) of the column at the given index.
|
public TableHeaderAdapter(Context context)
context
- The context that shall be used.protected TableHeaderAdapter(Context context, int columnCount)
context
- The context that shall be used.columnCount
- The number of columns.protected TableHeaderAdapter(Context context, TableColumnModel columnModel)
context
- The context that shall be used.columnModel
- The column model to be used.public Context getContext()
Context
of this adapter. (Hint: use this method in the getHeaderView()
-method
to programmatically initialize new views.)Context
of this adapter.public LayoutInflater getLayoutInflater()
LayoutInflater
of this adapter. (Hint: use this method in the
getHeaderView()
-method to inflate xml-layout-files.)LayoutInflater
of this adapter.public Resources getResources()
Resources
of this adapter. (Hint: use this method in the
getHeaderView()
-method to resolve resources.)Resources
of the context of this adapter.protected void setColumnModel(TableColumnModel columnModel)
TableColumnModel
that will be used to render the table headers.columnModel
- The TableColumnModel
that should be set.protected TableColumnModel getColumnModel()
TableColumnModel
that is currently used to render the table headers.protected void setColumnCount(int columnCount)
columnCount
- The column count that should be set.protected int getColumnCount()
protected void setColumnWeight(int columnIndex, int columnWeight)
columnIndex
- The index of the column to which this weight should be assigned.columnWeight
- The weight that should be set to the column at the given index.protected int getColumnWeight(int columnIndex)
columnIndex
- The index of the column to receive the column weight.protected int getColumnWeightSum()
public abstract View getHeaderView(int columnIndex, ViewGroup parentView)
columnIndex
- The index of the column to return the header view.parentView
- The view to which the returned view will be added.


Relationships are the ability to capture "yes or no" relationship status between arbitrary objects.
Much like Objects, Relationships by themselves are not fairly interesting. They deal with cryptic links between unknown identifiers, that fails to apply much meaning to our everyday lives.


Sorry, your browser doesn't support embedded videos.
Sorry, your browser doesn't support embedded videos.


Examining the code needed to read a file line by line is a a common way to examine the hoops a programming language makes you jump through. While Perl certainly has some one-liners for this, let’s start with Ruby, which presents an elegant and clear way of doing it:
File.open("some_file.txt") do |file|
file.readlines.each do |line|
puts line.upcase
end
end
Here’s the canonical Java way of doing it, complete with plenty of places to introduce bugs:
import java.io.*;
public class ReadFile {
public static void main(String args[]) throws IOException {
File file = new File("some_file.txt");
BufferedReader reader = new BufferedReader(
new FileReader(file));
String line = reader.readLine();
while (line != null) {
System.out.println(line.toUpperCase());
line = reader.readLine();
}
reader.close();
}
}
readLine()
twice kinda sucks. We could use a do-while, but that requires a second line != null
check. Personally, I like to forget the second readLine()
and wonder why my code runs forever :) That being said, this was extremely easy to figure out, even the very first time I did it in 1998. The class names are obvious, and the documentation is excellent.
Scala to the rescue, right?
import scala.io._
object ReadFile extends Application {
val s = Source.fromFile("some_file.txt")
s.getLines.foreach( (line) => {
println(line.trim.toUpperCase)
})
}
scala.io
and, of the few classes that were there (including a curiously named BytePickle
), it appeared as though Source
was the class to use. Of course, there’s no easy way to create one from the constructor, and the scaladoc doesn’t just say “Dude, look at the Source
object”. Once I looked through the Source
object’s scaladoc, the solution presented itself.
Of course, unlike every other line-traversing library in the known universe, Source
leaves the line endings on. This is thankfully fixed in 2.8 (by which I mean 2.8 breaks 2.7’s implementation, which is a strange thing for a point release to do). The real question is: “Is this how I’m supposed to read files in Scala?”. With a class called Source?!
reportError
and reportWarning
. I guess this is only for writing the Scala compiler? If so, scala.io
seems an odd place to put this.
So, my answer is “No, this cannot be how to canonically read files in Scala”. Since the Java way kinda, well, sucks, what alternatives are there? There’s scalax.io
, which seems to implement this as a class called, curiously, FileExtras
. I’m not sure if this code is actively maintained, but it’s documented in classic Scala style: terse and full of loaded terms like “nonstrict”. Nevertheless, there seems to be some code here to easily read a file “the easy way” (despite some distracting names).
This points out a big difference between “Scala the language” and “Scala the library”. Scala the language is very interesting and has a lot of potential. Scala the library is schizophrenic at best; it’s not sure if it wants to be OO, functional, or what. The documentation ranges from sparse to absent, and the overall designs of the classes and package range for sublime to baffling. Years different from Java 1.1.


Class or ResCon
Class
ResCon
Session Name:
Trainer ID:
Faculty
Architecture Design and Planning
Medicine and Health
Multidisciplinary
Non Faculty
Arts and Social Sciences
Health Sciences
Science
Engineering and Information Technologies
Your Link:
Generate Link


The Iliad
by Homer
Concluding Note
Additional Information
- Year Published: 1899
- Language: English
- Country of Origin: Greece
- Source: Homer. (1899). The Iliad. Boston, MA; B.H. Stanton.
-
Readability:
- Flesch–Kincaid Level: 6.4
- Word Count: 529
- Genre: Epic
- Keywords: destiny, fate, glory, honor
- ✎ Cite This
Downloads
We have now passed through the Iliad, and seen the anger of Achilles, and the terrible effects of it, at an end, as that only was the subject of the poem, and the nature of epic poetry would not permit our author to proceed to the event of the war, it perhaps may be acceptable to the common reader to give a short account of what happened to Troy and the chief actors in this poem after the conclusion of it.
I need not mention that Troy was taken soon after the death of Hector by the stratagem of the wooden horse, the particulars of which are described by Virgil in the second book of the Æneid.
Achilles fell before Troy, by the hand of Paris, by the shot of an arrow in his heel, as Hector had prophesied at his death, lib. xxii.
The unfortunate Priam was killed by Pyrrhus, the son of Achilles.
Ajax, after the death of Achilles, had a contest with Ulysses for the armour of Vulcan, but being defeated in his aim, he slew himself through indignation.
Helen, after the death of Paris, married Deiphobus his brother, and at the taking of Troy betrayed him, in order to reconcile herself to Menelaus her first husband, who received her again into favour.
Agamemnon at his return was barbarously murdered by Ægysthus, at the instigation of Clytemnestra his wife, who in his absence had dishonoured his bed with Ægysthus.
Diomed, after the fall of Troy, was expelled his own country, and scarce escaped with his life from his adulterous wife Ægiale; but at last was received by Daunus in Apulia, and shared his kingdom; it is uncertain how he died.
Nestor lived in peace with his children, in Pylos, his native country.
Ulysses also, after innumerable troubles by sea and land, at last returned in safety to Ithaca, which is the subject of Homer's Odyssey.
For what remains, I beg to be excused from the ceremonies of taking leave at the end of my work, and from embarrassing myself, or others, with any defences or apologies about it. But instead of endeavouring to raise a vain monument to myself, of the merits or difficulties of it (which must be left to the world, to truth, and to posterity), let me leave behind me a memorial of my friendship with one of the most valuable of men, as well as finest writers, of my age and country, one who has tried, and knows by his own experience, how hard an undertaking it is to do justice to Homer, and one whom (I am sure) sincerely rejoices with me at the period of my labours. To him, therefore, having brought this long work to a conclusion, I desire to dedicate it, and to have the honour and satisfaction of placing together, in this manner, the names of Mr. CONGREVE, and of
March 25, 1720
A. POPE
Ton theon de eupoiia—to mae epi pleon me procophai en poiaetikn kai allois epitaeoeimasi en ois isos a kateschethaen, ei Æsthomaen emautan euodos proionta.
M. AUREL ANTON de Seipso, lib. i. Section 17.
END OF THE ILIAD


{{- partial "structure/head/base.html" . -}} {{/* - partial "page/install-sw.html" . - */}} {{/* - partial "structured-data/base.html" . - */}}


This example uses the MailChimp API v3 created by Drew McLellan.
It also includes Google reCAPTCHA to ensure there is no spam subscribes.
I have also added a check that the person agrees to join the mailing list.
In order for the example below to work you will need to use your own Google reCAPTCHA site & private keys as well as your MailChimp API key and list ID


First case is selected by default
I am case 1, in switch 1
I am case 2, in switch 1
I am case 3, in switch 1
Switch 1, case 1
Switch 1, case 2
Switch 1, case 3
Second case has @selected="true"
I am case 1, in switch 2
I am case 2, in switch 2
I am case 3, in switch 2
Switch 2, case 1
Switch 2, case 2
Switch 2, case 3
Second and third cases have @selected="true"
, but the second case should be the default
I am case 1, in switch 3
I am case 2, in switch 3
I am case 3, in switch 3
Switch 3, case 1
Switch 3, case 2
Switch 3, case 3


--- description: 'A page showing products' action: 'shop:products' template: main protocol: all published: true name: Products url: /products ---


Sort(columns: Collection<SortColumn>)
Sort allows specification of a set of entity attribute names and their associated directionality and null handling, to be applied upon processing a query specification.


For any Favourama Android App user who can bring new users to our app, we will give commissions to you based on the following:
Disclaimer: The above 4 types of users shall not overlap. All requests and messages mentioned above can only be counted in when they are valid. Favourama has its own measure to determine the validity of messages and requests. Rights to explain are reserved by Favourama. The promotion may end anytime when Favourama sees fit. Failure to learn the end date of this promotion punctually is the participants' own responsibility, Favourama shall not be responsible for paying commissions for users introduced beyond promotion's end date.
By joining the promotion, you accept all rules and terms mentioned in the disclaimer above. If you wish to join as a participant, please fill out the form and click continue below.


/
Instances
Problems
Home
Instances
Upload Instance
No Instances
An instances
Optimize
Download
Remove


Encaustic Group July 2012
July 2012 Encaustic Painters
Fayum Funeral Portrait, Mummy Portrait of a Woman, Antinoopolis, End of the Reign of Trajan, 98-117 A.D., Wax portrait on wood. |
Encaustic painting is one of the oldest painting mediums in our culture. Encaustic painting was practiced by Greek artists as far back as the 5th century B. C.
Wax is an excellent preservative of materials. It was from this use that the art of encaustic painting developed.
The use of encaustic on panels rivaled the use of tempera. Pliny refers to encaustic paintings several hundred years old in the possession of Roman aristocrats of his own time.
The nature of encaustic to both preserve and color gave it wide use on the stone work of both architecture and statuary.
Perhaps the best known of all encaustic work are the Fayum funeral portraits painted in the 1st and 2nd centuries A.D. by Greek painters in Egypt. Many of these pieces have survived to our own time, and their color has remained as fresh as any recently completed work.
In the great period of economic instability that followed the decline of the Roman empire, encaustic fell into disuse, it became a lost art. The process was cumbersome and painstaking, and the cost of producing it was high. It was replaced by tempera.
In the 20th century, encaustic is a far less formidable technique. This factor has created a resurgence of encaustic painting, and it is once again taking its place as a major artists' medium.
— Ralph Mayer, The Artist's Handbook
NKG Boston is pleased to present four artists who are using this ancient medium in their contemporary practices.
Gallery II
NKG June 29 - July 20 2012
Opening Reception Friday July 6, 2012 5-8 pm
NK Gallery
450 Harrison Avenue #61
Boston MA 021118
Gallery hours Wed- Sat 11am – 4pm


Patricia Duffy is an instructor in the UN Language and Communications Programme.
She has an M.A. from Teachers College, Columbia University and is an Acting Officer of the UN
Society of Writers and its liaison to the UN 1% for Development Fund.
Pat is the author of two textbooks on English as a second language:
Variations: Reading/Oral Communication Skills and Focus on Innovations and Innovators, and also
Blue Cats, a book about language and perception.
She is in the process of creating this online course, Action through Words: Learning English through
learning about the United Nations.
Miriam Eisenstein Ebsworth, Ph.D. is director of Doctoral Programs in Multilingual, Multicultural Studies: TESOL (Teaching Enlgish to Speakers of Other Languages) & Bilingual Education. A native English speaker from a Yiddish speaking home in Brooklyn, NY, her language background also includes Spanish, French, and Hebrew. She has worked with second language learners from kindergarten through adult in the Metropolitan area, has mentored second language teachers and researchers, and has held various leadership positions on a local and national level. Many of her research interests center on crosscultural communication, with language as a mediator of individual and group perceptions and values.
B.A. Modern Languages & Early Childhood Ed. (Brooklyn College)
M.A. TESOL (Teachers College)
Ph.D. Linguistics (CUNY Graduate Center)
Teaching Excellence Award, Steinhardt School of Education, 2001.
Special New York State TESOL Leadership Award for work to preserve ESL Teacher certification in NY.
1998.
Distinguished Scholar, Nessa Wolfson Memorial Colloquium University of Pennsylvania, 1998.


--- layout: post title: Knit Hat date: 2010-02-11 16:27:39.000000000 -05:00 type: post published: true status: publish categories: - arts and crafts - knitting tags: - hat - knitting meta: tagazine-media: a:7:{s:7:"primary";s:64:"http://monpetitchoublog.files.wordpress.com/2010/02/img_1418.jpg";s:6:"images";a:1:{s:64:"http://monpetitchoublog.files.wordpress.com/2010/02/img_1418.jpg";a:6:{s:8:"file_url";s:64:"http://monpetitchoublog.files.wordpress.com/2010/02/img_1418.jpg";s:5:"width";s:4:"3072";s:6:"height";s:4:"2304";s:4:"type";s:5:"image";s:4:"area";s:7:"7077888";s:9:"file_path";s:0:"";}}s:6:"videos";a:0:{}s:11:"image_count";s:1:"1";s:6:"author";s:7:"9073083";s:7:"blog_id";s:7:"8808538";s:9:"mod_stamp";s:19:"2010-02-11 20:27:39";} author: login: sophie email<EMAIL_ADDRESS>display_name: Pika first_name: '' last_name: '' ---
Just in time for 2 days of snow. This is the first hat I've ever made for myself and I'm pretty happy with it. It's just 2 by 2 ribbing knit on straight needles with some shaping at the top. I used "Vanna's Choice" yarn from Lion Brand.


VILLAGE OF DREAMS [ENO NAKA NO BOKU NO] A film review by James Berardinelli Copyright 1997 James Berardinelli
RATING (0 TO 10): 7.5 Alternative Scale: *** out of ****
Japan, 1996 Running Length: 1:52 MPAA Classification: No MPAA Rating (Mature themes, brief nudity) Theatrical Aspect Ratio: 1.85:1 Shown at the Philadelphia Festival of World Cinema, 5/6/97 & 5/8/97
Cast: Matsuyama Keigo, Matsuyama Shogo, Harada Mieko, Nagatsuka Kyozo, Komatsu Hosei Director: Higashi Yoichi Producers: Yamagami Tetsujiro, Sho Koshiro Screenplay: Higashi Yoichi and Nakajima Takehiro from the novel THE VILLAGE OF MY PAINTINGS by Tashima Seizo Cinematography: Shimizu Yoshio Music: Caterina Ancient Music Ensemble In Japanese with subtitles
VILLAGE OF DREAMS, the latest feature from respected Japanese director Higashi Yoichi, uses a languorous pace and stunning visuals to tell the simple-yet-effective story of a period in the life of two boys growing up in suburban Kyoto shortly after the conclusion of the second World War. The movie, which transpires in a peaceful, out-of-the-way locale and is told from a child's point-of-view, functions as a reminder of a simpler, less-hurried Japan.
The film is based on the autobiographical account of picture-book artists Tashima Seizo and his twin brother, Yukihiko (who both appear as they are today in a brief prologue).  They also have active imaginations. VILLAGE OF DREAMS features more than a dash of magic realism with its depiction of witches in trees, imps hiding in undergrowth, and talking fish.
The simplicity of the plot allows the characters room to grow and breathe. Seizo and Yukihiko are firmly at the center of the film for its entire duration. We see the world through their eyes -- a strange, wonderful, sometimes-frightening place where simple walks in the woods can turn into great adventures. Then, as Seizo and Yukihiko become aware of the differences between the male and female body, the issue of sexual curiosity comes to the fore. There's even a memorable hypothesis about why a girl doesn't have a penis.
Visually, VILLAGE OF DREAMS is a beautiful, evocative piece of work that achieves much of its effectiveness through its visuals of the twins' rural village and the surrounding woods. The film is all about memories and the past -- a retrospective of a society that no longer exists as it once did and a catalyst for us to remember those long-ago days when we gazed upon the world with the wide-eyed enthusiasm of a child.
- James Berardinelli e-mail<EMAIL_ADDRESS>ReelViews web site: http://www.cybernex.net/~berardin
The review above was posted to the
rec.arts.movies.reviews newsgroup (de.rec.film.kritiken for German reviews).
The Internet Movie Database accepts no responsibility for the contents of the
review and has no editorial control. Unless stated otherwise, the copyright
belongs to the author.
Please direct comments/criticisms of the review to relevant newsgroups.
Broken URLs inthe reviews are the responsibility of the author.
The formatting of the review is likely to differ from the original due
to ASCII to HTML conversion.
Related links: index of all rec.arts.movies.reviews reviews


--- author: brian.leroux categories: app date: '2009-10-07 11:10:55' link: http://blogs.nitobi.com/brian/2009/10/07/phonegap-0-8-0-is-apple-approved/ permalink: /2009/10/07/phonegap-0-8-0-is-apple-approved/ slug: phonegap-0-8-0-is-apple-approved status: publish title: PhoneGap 0.8.0 is Apple Approved type: post format: html ---
Its official: PhoneGap 0.8.0 is approved by Apple.
After an epic amount of blog campaigning, twitter rebuttals, email group frustration and obfuscation hackery we can now say that Apple approves of PhoneGap.
All along we knew that PhoneGap was within the licensing terms of the iPhone SDK and the unwarranted rejections where simply unfair to the development community. We can now get back to the business of building the best device agnostic open web mobile platform.
A huge thanks to iPhone PhoneGap contributor Mike Nauchbar for taking this crusade on!


Note: This is a fake form. Submitting on the edit button will submit to itself
Select an address to edit:
Instart Logic US Headquarters 450 Lambert Avenue Palo Alto, CA 94306
Instart Logic India Office 6th Floor , HM Vibha Towers Hosur Rd, Adugodi Bengaluru — 560029
Instart Logic New York Office 499 Seventh Ave, 7th Floor North New York, NY 10018
Instart Logic Boston Office 400 West Cummings Park, Suite 3650 Woburn, MA 01801
Instart Logic London Office Knyvett House Watermans Business Park The Causeway Staines-Upon-Thames, TW18 3BA, UK


Cacti - T. pachanoi
One Saturday morning, a friend showed up with a large quantity of Peruvian Torch cactus, which was split four ways. We each had 20 grams. Eating Peruvian Torch is an unpleasant way of consuming mescaline, but it was the only method easily available to us, and I found the trip to be well worth it. This was my first experience with any sort of entheogenic drug. None of my compatriots had ever tried mescaline, but they had all done shrooms and salvia. I went in with a positive outlook, quite hopeful, though slightly anxious. I was not disappointed.
Around noon we each ate our allotted portions. We had purchased the cactus in the form of small cubish chunks of inconsistent sizes. I don't know exactly which part of the cactus these came from. The taste was very bitter and unpleasant. I managed to get down about three quarters of what I had bought with the aid of plentiful glasses of water. After about fifteen minutes of slowly eating the cactus, I began to feel quite nauseated. One friend, Mr. B, threw up shortly after eating his dose. The nausea wasn't terrible. It peaked after maybe forty-five minutes, but I managed to hold down what I had eaten by lying on my bed and telling myself, 'I will not throw up. If I can hold this down, I will ultimately have a more rewarding experience. I am sick, but it will pass. It is a sickness I knowingly instigated to see a certain end. I will see what the cactus has to show me.' I lay there for about half an hour.
Once I felt better, my anticipation started to build quite a bit. I was constantly asking myself (and my companions) whether anything was happening yet, but I didn't really feel much until about two hours after eating the cactus. I remember feeling somewhat nervous, realizing that there was no turning back at this point. Still, I did my best to remain positive, and I succeeded.
Once the two-hour mark had been reached, I started feeling different. The drug has a very slow come-up, at least when consumed in this fashion. The most noticable aspects of the coming up for me were a pleasant warmth in my body accompanied by a strong feeling of energy. These sensations commingled and grew stronger until I felt a profound euphoria, which lasted for the duration of the trip.
The experience of the drug was quite clear-headed. I didn't feel 'doped' like after smoking pot. I felt that my thought processes were my own, and I was controlling them. This contrasts with my later experiences with mushrooms, which I always find pushing my mind in certain directions, welcome or not.
At some point, I retired to my room, where I would remain for most of the trip. The setting was quite comfortable for me, because I was able to listen to a good deal of music, which I enjoyed very much. Other participants came and went as it struck their fancy. As the mescaline starting kicking in more and more, Mr. B and I - as well as another friend - Mr. T, who was on a low dose of mushrooms, found ourselves having quite rewarding conversations. We gained insight into all manner of things, facilitated to some degree by the drugs. While I did not have any fantastic revelations, I feel that I did learn something.
Nobody was reporting any visuals, and we were eager to amplify the effects of the drug, so around 6pm we smoked a large joint of marijuana, forgoing the pure experience of mescaline in favor of pot-fueled amplification. I think this was worthwhile. I have since done mescaline alone, and enjoyed it very much, but the pot was quite a boon in this instance.
Soon after smoking the joint, we started experiencing stronger effects. Mr. B reported 'crazy' closed-eye visuals, and I noticed these as well. I find it difficult to describe effects of this nature, but I can definitively state that my senses were quite strongly altered. My vision sort of 'swam,' in a pleasant wavy fashion, similar to mild mushroom effects. I often felt that I could see objects continuously rushing at me, and I saw a beautiful pattern overlaid on everything else is my vision. This could best be described as a more noticable (and aesthetically pleasing) version of the 'floaters' which some people experience in their everyday vision. The entire world and each of its constituent objects held a warm glow, mirroring my own. Occasionally, I would see a wave a distortion slowly pass across my vision, from the top down, blurring everything.
This is the best I can recall the effects. All of them were essentially pleasing, and I was easily able to grasp why I have heard mescaline called 'warm.' This was manifest in the way my body felt: warm and energetic, in a very comfortable way. The warmth was also present in the general state of euphoria and empathy which I experienced.
I also see why mescaline is called 'subtle.' The visual effects were pleasing, if not astonishing. I imagine they could become much stronger with a higher dose, but with this method of intake, I don't know if a much higher dose would be possible, at least for me. While pleased with the trip, I felt no attachment to the remaining portion of the cactus, which I gave away.
I was left with a sense of well-being well into the night. The drug started wearing off around 10pm or so. I stayed awake until probably 1 or 2am. Overall the trip was comfortable, insightful, and fun: a pleasant introduction to entheogens on the whole.
Experience Reports are the writings and opinions of the individual authors who submit them.
Some of the activities described are dangerous and/or illegal and none are recommended by Erowid.


Dancing
Sprint
3:45 PM
100%
Sprint
1:40 PM
100%
Select the month you want to view
Oct
Nov
Dec
There is no activity in this month.