diff --git a/docMap.json b/docMap.json index a4415d5..c573064 100644 --- a/docMap.json +++ b/docMap.json @@ -15,14 +15,13 @@ }, "comment": " " }, - "contribute": { + "Apis": { "src": { - "path": "docs/contribute.md" + "path": "docs/apis.md" }, - "body": "Thank you for contributing to DoneJS! If you need any help setting up a DoneJS development environment and fixing DoneJS bugs, please reach out to us on [gitter](https://gitter.im/donejs/donejs) or email [contact@bitovi.com](mailto:contact@bitovi.com). We will happily walk you through setting up a the environment, creating a test, and submitting a pull request.\n\n## Reporting Bugs\n\nTo report a bug, please visit [GitHub Issues](https://github.com/donejs/donejs/issues).\n\nWhen filing a bug, it is helpful to include:\n\n- Small examples using tools like [JSFiddle](http://jsfiddle.com/). You can fork the following DoneJS fiddles:\n - [jQuery](http://jsfiddle.net/donejs/qYdwR/)\n - [Zepto](http://jsfiddle.net/donejs/7Yaxk/)\n - [Dojo](http://jsfiddle.net/donejs/9x96n/)\n - [YUI](http://jsfiddle.net/donejs/w6m73/)\n - [Mootools](http://jsfiddle.net/donejs/mnNJX/)\n- Breaking unit tests (optional)\n- Proposed fix solutions (optional)\n\nSearch for previous tickets, if there is one add to that one rather than creating another. You can also post on the [Forums](https://forums.donejs.com) or talk to us in [gitter](https://gitter.im/donejs/donejs).\n\n## Installing \n\n1. Fork DoneJS on GitHub.\n2. Clone it with: `git clone git@github.com:/donejs`\n\n## Structure\n\nTODO: Explain stack or link to api section.\n\n## Contributing\n\nWhen contributing, please include tests with new features or bug fixes in a feature branch until you're ready to submit the code for consideration; then push to the fork, and submit a pull request. More detailed steps are as follows:\n\n1. Navigate to your clone of the DoneJS repository - `cd /path/to/donejs`\n2. Create a new feature branch - `git checkout -b html5-fix`\n3. Make some changes\n4. Update tests to accomodate your changes\n5. Run tests and make sure they pass in all browsers\n6. Update documentation if necessary\n7. Push your changes to your remote branch - `git push origin html5-fix`\n8. Submit a pull request! Navigate to [Pull Requests](https://github.com/donejs/donejs/pulls) and click the 'New Pull Request' button. Fill in some details about your potential patch including a meaningful title. When finished, press \"Send pull request\". The core team will be notified about your submission and let you know of any problems or targeted release date.\n\n## Documentation\n\nIf your changes affect the public API, please make relevant changes to the documentation. Documentation is found either inline or in markdown files in the respective directory. In order to view your changes in documentation you will need to run the DoneJS.com site locally and regenerate the docs.\n\nTo run the docs and watch the files for changes run the command:\n```\n./node_modules/.bin/documentjs -d -f --watch\n```\n\nFinally, serve the site locally using a tool like [http-server](https://www.npmjs.com/package/http-server).\n\n## Making a build\n\nTo make a build (standalone and AMD version) you will also need to have [[NodeJS](http://nodejs.org/), [npm](http://npmjs.org/), [Grunt](http://gruntjs.com/) and all of the DoneJS dev dependencies installed.\n\n### Getting Set Up\n\n1. Install NodeJS & npm - [NodeJS](http://nodejs.org/) or use `brew install nodejs`\n2. Install Grunt - `npm install grunt-cli -g`\n3. Navigate to your local clone of DoneJS - `cd /path/to/canjs`\n4. Install dependencies - `npm install`\n\nAfter you have completed those steps simply run `grunt build` and it will put the built files in the `can/dist` directory, making them ready for download.\n\n## Style Guide\n\n### Linting\nGrunt provides a `quality` task to verify some basic, practical soundness of the codebase. The options are preset.\n\n### Spacing\nIndentation with tabs, not spaces.\n\n`if/else/for/while/try` always have braces, with the first brace on the same line. For example:\n\n if(foo){\n\n }\n \nSpaces after commas. For example:\n\n myfn = function(foo, bar, moo){ ... }\n\n### Assignments\n\nAssignments should always have a semicolon after them.\n\nAssignments in a declaration should always be on their own line. Declarations that don't have an assignment should be listed together at the start of the declaration. For example:\n\n // Bad\n var foo = true;\n var bar = false;\n var a;\n var b;\n\n // Good\n var a, b,\n foo = true,\n bar = false;\n\n### Equality\n\nStrict equality checks `===` should be used in favor of `==`. The only exception is when checking for undefined and null by way of null.\n\n // Bad\n if(bar == \"can\"){ ... }\n\n // Good\n if(bar === \"can\"){ ... }\n\nIf the statement is a truthey or falsey, use implied operators. Falseys are when variables return `false`, `undefined`, `null`, or `0`. Trutheys are when variables return `true`, `1`, or anything defined.\n\nFor example:\n\n // Bad\n if(bar === false){ ... }\n\n // Good \n if(bar){ ... }\n\n // Good\n var foo = [];\n if(!foo.length){ ... }\n\n### Quotes\n\nUse double quotes.\n\n var double = \"I am wrapped in double quotes\";\n\nStrings that require inner quoting must use double outside and single inside.\n\n var html = \"
\";\n\n### Comments\n\nSingle line comments go OVER the line they refer to:\n\n // We need an explicit \"bar\", because later in the code foo is checked.\n var foo = \"bar\";\n\nFor long comments, use:\n \n /* myFn\n * Four score and seven—pause—minutes ago...\n */\n \n### Documentation\n\nThe documentation for the different modules should be clear and consistent. Explanations should be concise, and examples of code should be included where appropriate. In terms of format and style, here are a few suggestions to keep the documentation consistent within a module and across all parts of DoneJS:\n\n#### When referencing another part of DoneJS, make sure to link the first reference in a section.\n\nFor instance, when documenting `can.Component.scope`, the first reference to `can.Component`, `can.route`, or any other part of DoneJS should be enclosed in square brackets, so that links to those docs are generated. Linking each occurrence isn't necessary, but all the other references should at least be surrounded by \"grave accents\" or tickmarks.\n\n\tThis is an example of linking to [can.Component] from another page. If you reference\n\t`can.Component` later in this section, you don't have to link to it. All subsequent\n\treferences to `can.Component` have grave accents or tickmarks surrounding them.\n\t\n\t### New Section\n\t\n\tAnother section referencing [can.Component] starts this trend again...\n\n**Note**: The one exception to this is on the module page. When documenting `can.Component` itself, only use the tickmarks, as linking to `can.Component` would just link to the page you are currently modifying.\n\n#### Enclose string literals in tickmarks as they should appear in code\n\nIf the developer should type `\"@\"`, use the tickmarks to make this clear. This avoids the ambiguity of whether the apostrophes or quote marks are part of the text that should be typed. This also applies to any references to variable/key names (e.g., `scope` versus \"scope\" or **scope**).\n\n#### Include a clear description of your example code\n\nFor a developer that's new to DoneJS, the description of the example is likely more important than the example itself. Make sure there is a clear description of what the code should accomplish. This includes using all the techniques above. A good description should answer the question, \"could you explain what this example code is doing?\"\n\n", - "description": "\n", - "name": "contribute", - "title": "Contribue to DoneJS", + "body": "\n## Application flow overview\n\nLets talk about how the typical behavior of a DoneJS application works. We'll use\nthe chat application as an example in development. We'll cover what happens when:\n\n - A user navigates their browser from a different domain to `http://donejs-chat.com/`\n - A user navigates from `http://donejs-chat.com/` to another `http://donejs-chat.com/chat`.\n\n\n### First page load\n\n1. An http request for `http://donejs-chat.com/` is sent to a node server. The node server is configured,\n in this case with express, to use [done-ssr-middleware](#section=section_done_ssr) to render a DoneJS application:\n\n ```\n var ssr = require('done-ssr-middleware');\n\n app.use('/', ssr({\n config: __dirname + '/public/package.json!npm'\n }));\n ```\n\n2. [done-ssr](#section=section_done_ssr) uses [steal](#section=section_steal) to load the application's main module which results in loading the\n entire application. Loading the application only happens once for all page requests.\n\n A DoneJS's main module is specified where all configuration of a DoneJS application happens, its `package.json`.\n The main module is usually a [can.stache](#section=section_can_stache) template processed with the [done-autorender](#section=section_done_autorender)\n plugin. The module name is specified like: `index.stache!done-autorender`. `index.stache` might look like:\n\n ```\n \n \n My Site\n \n \n \n \n {{#eq page \"home\"}}\n\n \n {{#if isResolved}}\n \n {{/if}}\n \n\n {{/eq}}\n \n \n \n ```\n\n The [done-autorender](#section=section_done_autorender) plugin, in NodeJS, exports this template so it can be rendered. It also exports\n any modules it imports with `` that are labeled with `export-as=\"EXPORT_NAME\"`. Exporting\n the viewModel is important for [done-ssr](#section=section_done_ssr)\n\n3. Once [done-ssr](#section=section_done_ssr) has the [done-autorender](#section=section_done_autorender)'s `template` and `viewModel` export it:\n\n 1. Creates a new instance of the viewModel, setting properties on it\n using [can.route](#section=section_can_route)'s routing rules. \n 2. Creates a new [virtual dom](#section=section_can_simple_dom) instance.\n 3. Renders the [template](#section=section_can_stache) with the `viewModel` into the `virtual dom` instance.\n\n4. [done-autorender](#section=section_done_autorender) templates waits for all promises to complete\n before providing a final result. Once the template is finished rendering, [done-ssr](#section=section_done_ssr) converts it to a\n string and sends it back to the browser.\n\n5. The browser downloads the page's HTML, which includes a `\n\n In development, this loads `steal.js` which then loads `index.stache` and processes it with\n the `done-autorender`. \n\n6. In the browser, `done-autorender`:\n\n 1. Creates a new instance of the [viewModel](#section=section_can_ssr_app_map), setting properties on it\n using [can.route](#section=section_can_route)'s routing rules. \n 2. Renders the [template](#section=section_can_stache) with the `viewModel` into a document fragment.\n 3. Once all asynchronous activity has completed, it replaces the document with the rendered result.\n\n\n\n### Pushstate change\n\n1. A pushstate is triggered by user action, usually by clicking a link. [can.route](#section=section_can_route)'s routing rules determines the properties set on the application [viewModel](#section=section_can_ssr_app_map).\n\n ```\n can.route(':page', { page: 'home' });\n ```\n\n2. [done-autorender](#section=section_done_autorender) previously bound the AppViewModel to [can.route](#section=section_can_route) which causes any change in the route to be reflected in the AppMap instance.\n\n3. Live binding causes the initial template to reflect in the change in route. If the new route is `/chat` it will cause the `page` to be **chat**:\n\n ```\n \n \n My Site\n \n \n \n \n {{#eq page \"home\"}}\n\n \n {{#if isResolved}}\n \n {{/if}}\n \n\n {{/eq}}\n\n {{#eq page \"chat\"}}\n \n {{#if isResolved}}\n \n {{/if}}\n \n\n {{/eq}}\n\n \n \n \n ```\n\n3. [can-import](http://canjs.com/docs/can%7Cview%7Cstache%7Csystem.import.html) will progressively load the component for the new page with a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) as its view model. When the promise resolves the [can.Component](#section=section_can_Component) will be inserted.\n\n## CLI and Generators\n\nAfter installing DoneJS globally with `npm install donejs -g` you will have the `donejs` command available on the command line. It lets you initialize a new application and - when navigating within a DoneJS project - run scripts provided locally by your application. Within your application folder the `donejs` command is a convenience wrapper for the functionality described below and you can also get a list of all commands by running\n\n```\ndonejs help\n```\n\n### NPM scripts\n\n[NPM scripts](https://docs.npmjs.com/misc/scripts) are defined in the `scripts` section of your applications `package.json`. There are some standard scripts that every Node application uses (like `npm start` or `npm test` - both of which are already set up for you) and you can add your own which is what DoneJS does with commands like `npm run develop` or `npm run build`.\nThe `donejs` command makes running those commands easier by allowing you to run them like `donejs start`, `donejs develop` or `donejs build`\n\n### Generators\n\n`donejs add` lets you run the [Yeoman](http://yeoman.io/) generators provided by [generator-donejs](https://github.com/donejs/generator-donejs/). Currently the following generators are available:\n\n- `donejs add app [folder]` which will initialize a new application (optionally within the given folder)\n- `donejs add component ` to create a new can.Component\n- `donejs add supermodel ` to generate a new model\n\n### Third party generators\n\nIf `donejs add` can't find a built-in generator, e.g. when running `donejs add myplugin`, DoneJS will try to install the `donejs-myplugin` package from NPM and run the Yeoman generators it provides. This is how we can enable a desktop application build of the application by simply running\n\n```\ndonejs add nw\n```\n\nWhich will install the [donejs-nw](https://github.com/donejs/donejs-nw) package and then run its generator which initializes everything you need. This also works for adding a mobile application build using [donejs-cordova](https://github.com/donejs/donejs-cordova) like this:\n\n```\ndonejs add cordova\n```\n\nThis way you can use DoneJS's growing list of plugins and generators without having to add anything to your application that you don't use.\n\n## StealJS\n\nThe base of any good JavaScript application is its depenency management system. \nDoneJS uses [StealJS](http://stealjs.com/) which\nitself is split into two sub-projects:\n\n- `steal` - loads CommonJS, ES6, and AMD modules. It can also load styles, templates and more.\n- `steal-tools` - builds your application's modules for production and also provides hot-module-swapping.\n\n### steal\n\nTo use [steal](http://stealjs.com/docs/steal.html), simply add a script tag to `steal.js`\nin an HTML page or in a [done-autorender](#section=section_done_autorender) `template` and\npoint the `main` attribute to a module to load like:\n\n```\n\n```\n\nUsing the default DoneJS [system.directories.lib](http://stealjs.com/docs/npm.html#section_Configuration) configuration, this will load\n`my-app/src/my-module.js`. From there, use CommonJS, ES6, or AMD to load your modules:\n\n```\n// my-app/src/my-module.js\nimport $ from \"jquery\";\nimport \"./styles.css!\";\n\n$('body')\n```\n\nIf an `import`, `require` or `define` module reference ends with `\"/\"`, is a shorthand\nfor importing a module in the modlet format. The moduleName imported is the same\nas the module reference, but with the last folder name added again.\n\nSome examples:\n\n```\n// in components/person module.\nimport \"can/component/\"; //imports \"can/component/component\";\nimport \"./edit/\"; // imports \"components/person/edit/edit\";\n```\n\nConfigure [steal](http://stealjs.com/docs/steal.html)'s behavior in your `package.json` in the `system` object like:\n\n```\n// package.json\n{\n \"main\": \"index.stache!done-autorender\",\n ...\n \"system\": {\n \"meta\": {\n \"ui/core\": {\n \"deps\": [\n \"jquery\",\n \"theme/core.css!\",\n \"theme/theme.css!\"\n ]\n }\n }\n }\n}\n```\n\n### steal-tools\n\nIn DoneJS applications, [steal-tools](http://stealjs.com/docs/steal-tools.html) is primarily used to:\n\n - [build](http://stealjs.com/docs/steal-tools.build.html) and minify your application to production-ready bundles.\n - add [hot module swapping](http://stealjs.com/docs/steal-tools.cmd.live-reload.html)\n\nIt can also be used to [export](http://stealjs.com/docs/steal-tools.export.html) your\nmodules to different formats.\n\nDoneJS comes with a `build.js` script that call's steal-tools' [build](http://stealjs.com/docs/steal-tools.build.html):\n\n```\n//build.js\nvar stealTools = require(\"steal-tools\");\n\nvar buildPromise = stealTools.build({\n config: __dirname + \"/package.json!npm\",\n babelOptions: {\n loose: \"es6.modules\"\n }\n}, {\n bundleAssets: true\n});\n```\n\nThis is already configured to run with:\n\n```\n> donejs build\n```\n\nBut you could also run it with:\n\n```\n> node build.js\n```\n\nHot module swapping is done with [live-reload](http://stealjs.com/docs/steal-tools.cmd.live-reload.html) which\nis bundled within steal-tools. \n\nBy default `donejs develop` starts the live-reload server. However, you could start one\nyourself with:\n\n```\n> steal-tools live-reload\n```\n\n## CanJS\n\nCanJS provides:\n\n- __observables__ with [can.Map](#section=section_can_Map), [can.List](#section=section_can_List), and [can.compute](#section=section_can_compute).\n- __one-way and two-way binding templates__ with [can.stache](#section=section_can_stache) and [can.view.bindings](#section=section_can_view_bindings).\n- __custom elements__ with [can.Component](#section=section_can_Component).\n- __routing__ with [can.route](#section=section_can_route).\n\nObservables act as the `ViewModel` and part of the `Model`.\n\nOne-way and two-way binding templates act as the `View`.\n\n[can.Component](#section=section_can_Component) is used to combine `View` and `ViewModel` into\neasy to instantiate and assemble custom elements.\n\nCheckout the following quick examples of their use:\n\n__observables__:\n\n```\n// Observable objects:\nvar person = new can.Map({first: \"Justin\", last: \"Meyer\"});\n\n// Observable arrays:\nvar hobbies = new can.List([\"basketball\", \"hip-hop dancing\"]);\n\n// Observable single values:\nvar age = can.compute(33);\n\n// Observable computed values:\nvar info = can.compute(function(){\n return person.attr(\"first\")+\" \"+person.attr(\"last\")+\" is \"+\n \tage()+\" and likes \"+ hobbies.join(\",\")+\".\";\n});\n\n// Get the compute's value\ninfo() //-> Justin Meyer is 33 and likes\\\n // basketball, hip-hop dancing.\n\n// Listen to changes in the compute\ninfo.bind(\"change\", function(ev, newValue){\n newValue //-> Justin Meyer is 33 and likes\\\n // basketball, hip-hop dancing.\n});\n\nhobbies.pop(); // causes `change` event above\n```\n\n__one and two-way binding templates__:\n\n```\n// Programatically create a template\n// `{($value)}` cross binds the input's value\n// to `first` in the scope.\nvar template = can.stache(\"

{{first}}

\"+\n\t\"\");\n\n// Create observable data for the template\nvar person = new can.Map({first: \"Payal\"});\n\n// Render the template with data\nvar frag = template(person);\n\n// Add the result to the document\ndocument.body.appendChild(frag);\n\n// Document shows rendered result\ndocument.body //->

Payal

\n\n// ... User changes the input's value to \"Ramiya\" ...\n\n// Document is updated with changes\ndocument.body //->

Ramiya

\n```\n\n__custom elements__:\n\n```\n// Create a custom `can.Map` constructor function\n// with a helper function.\nvar PersonEditViewModel = can.Map.extend({\n fullName: function(){\n return this.attr(\"first\")+\" \"+this.attr(\"last\");\n }\n});\n\n// Create a template that will be rendered within\n// `` elements.\nvar template = can.stache(\"Update {{fullName}}:\"+\n\t\"\"+\n\t\"\");\n\n// Create the `` element with the specified\n// viewModel and template (view).\ncan.Component.extend({\n tag: \"person-edit\",\n viewModel: PersonEditViewModel,\n template: template\n});\n\n// Use that custom element within another template.\n// `{(first)}` cross binds ``'s\n// `first` property to `firstName` in the scope.\nvar parentTemplate = can.stache(\n \"

{{firstName}} {{lastName}}

\"+\n \"\");\n\n// Render the parent template with some data:\nvar frag = parentTemplate(new can.Map({\n firstName: \"Brian\",\n lastName: \"Moschel\"\n}));\n\ndocument.body.appendChild(frag);\n```\n\n### can.Construct\n\n[can.Construct](http://canjs.com/docs/can.Construct.html) allows you to define constructor functions that are easy to inherit\nfrom. It's used by [can.Map](#section=section_can_Map), [can.List](#section=section_can_List), and [can.Component](#section=section_can_Component).\n\nTo create your own constructor function, [extend](http://canjs.com/docs/can.Construct.extend.html) `can.Construct`\nwith prototype methods like:\n\n```\nvar Todo = can.Construct.extend({\n init: function(name){\n this.name = name;\n },\n\n author: function() { ... },\n\n coordinates: function() { ... },\n\n allowedToEdit: function( account ) {\n return true;\n }\n});\n```\n\nThen you can create instances of `Todo` like:\n\n```\nvar todo = new Todo(\"dishes\");\ntodo.name //-> \"dishes\";\ntodo.allowedToEdit() //-> true;\n```\n\nYou can extend `Todo` with [extend](http://canjs.com/docs/can.Construct.extend.html) too:\n\n```\nvar PrivateTodo = Todo.extend({\n allowedToEdit: function( account ) {\n return account.owns( this );\n }\n});\n```\n\n`can.Construct` comes with a [super](http://canjs.com/docs/can.Construct.super.html) plugin that allows you to easily\ncall base behavior like:\n\n```\nvar PrivateTodo = Todo.extend({\n init: function(name, account){\n this._super(name);\n this.account = account;\n }\n allowedToEdit: function() {\n return this.account.owns( this );\n }\n});\n```\n\n### can.Map\n\n[can.Map](http://canjs.com/docs/can.Map.html) is used to create observable\nJavaScript Object-like objects. Create an instance of the\nbase `can.Map` like:\n\n```\nvar person = new can.Map({first: \"Justin\", last: \"Meyer\"});\n```\n\nRead or write a `map`'s properties with [.attr](http://canjs.com/docs/can.Map.prototype.attr.html):\n\n```\nperson.attr(\"first\") //-> Justin\n\nperson.attr(\"first\", \"Ramiya\");\nperson.attr() //-> {first: \"Ramiya\", last: \"Meyer\"}\n\nperson.attr({first: \"Brian\", last: \"Moschel\"});\nperson.attr() //-> {first: \"Brian\", last: \"Moschel\"}\n```\n\nBind to changes in a person's properties with [.bind](http://canjs.com/docs/can.Map.prototype.bind.html):\n\n```\nperson.bind(\"first\", function(ev, newValue, oldValue){\n newValue //-> \"Laura\"\n oldvalue //-> \"Brian\"\n});\n\n// changing `first` causes the function\n// call above.\nperson.attr(\"first\", \"Laura\");\n```\n\nExtend a `can.Map` to create a new constructor function. This is\nvery useful for creating Models and View Models:\n\n```\n// pass extend an object of prototype values\nvar Person = can.Map.extend({\n fullName: function(){\n person.attr(\"first\")+\" \"+person.attr(\"last\");\n }\n})\n\nvar me = new Person({first: \"Kathrine\", last: \"Iannuzzi\"});\nme.fullName() //-> \"Kathrine Iannuzzi\"\n```\n\nThe [define plugin](http://canjs.com/docs/can.Map.prototype.define.html) allows\nyou to control the behavior of attributes. You can define\n[default values](http://canjs.com/docs/can.Map.prototype.define.value.html),\n[getters](http://canjs.com/docs/can.Map.prototype.define.get.html),\n[setters](http://canjs.com/docs/can.Map.prototype.define.set.html), and\n[type](http://canjs.com/docs/can.Map.prototype.define.type.html) converters.\n\n```\nvar Todo = can.Map.extend({\n define: {\n percentComplete: {\n value: 0.1,\n type: \"number\",\n get: function(value){\n return \"\"+value+\"%\"\n },\n set: function(newValue){\n return newValue*100;\n }\n }\n }\n});\n\nvar todo = new Todo();\ntodo.attr(\"percentComplete\") //-> 10%\n```\n\nYou can even describe asynchronous behavior which is critical for working\nwith service data:\n\n```\nvar Todo = can.Map.extend({\n define: {\n owner: {\n get: function(lastSetValue, resolve){\n User.get({id: this.attr(\"ownerId\")}).then(resolve);\n }\n }\n }\n});\n\ntodo = new Todo({ownerId: 5});\n\n// async values only become valid when bound\n// this isn't a problem because templates usually bind for you\ntodo.bind(\"owner\", function(ev, owner){\n owner //-> a User instance\n});\n```\n\n\n### can.List\n\n[can.List](http://canjs.com/docs/can.List.html) is used to create observable\nJavaScript Array-like objects. Create an instance of the\nbase `can.List` like:\n\n```\nvar hobbies = new can.List([\"basketball\",\"dancing\"]);\n```\n\nUse [.attr](http://canjs.com/docs/can.List.prototype.attr.html) to read and write items from the list or to read the length:\n\n```\nfor(var i = 0, len = hobbies.attr(\"length\"); i < len; i++){\n var hobby = hobbies.attr(i);\n}\nhobbies.attr(1, \"hip hop dancing\");\nhobbies.attr() //-> [\"basketball\", \"dancing\"]\n```\n\nUse array methods like [.push](http://canjs.com/docs/can.List.prototype.push.html), [.pop](http://canjs.com/docs/can.List.prototype.pop.html), and [.splice](http://canjs.com/docs/can.List.prototype.splice.html) to modify the array:\n\n```\nhobbies.pop();\n\nhobbies.attr() //-> [\"basketball\"];\n\nhobbies.push(\"football\");\n\nhobbies //-> can.List[\"basketball\",\"football\"]\n```\n\nUse [.forEach](http://canjs.com/docs/can.List.prototype.forEach.html), [.map](http://canjs.com/docs/can.List.prototype.map.html), or [.filter](http://canjs.com/docs/can.List.prototype.filter.html) to loop through the array. All\nthese methods return a `can.List`\n\n```\nvar intramurals = hobbies.map(function(hobby){\n return \"intramural \"+hobby;\n})\nintramurals //-> can.List[\"intramural basketball\",\n \"intramural football\"]\n```\n\nListen to when a list changes by binding on `add` or `remove` or `length`\nevents. \n\n```\nhobbies.bind(\"add\", function(ev, newHobbies, index){\n console.log(\"added\", newHobbies,\"at\", index);\n })\n .bind(\"remove\", function(ev, removedHobbies, index){\n console.log(\"removed\", newHobbies,\"at\", index);\n })\n .bind(\"length\", function(ev, newVal, oldVal){\n console.log(\"length is\", newVal);\n });\n\nhobbies.splice(1,1,\"pumpkin carving\",\"gardening\");\n // console.logs:\n // removed [football] 1\n // added [\"pumpkin carving\",\"gardening\"] 1\n // length is 3\n```\n\n\nBy default, if you initialize a list with plain JavaScript objects,\nthose objects are converted to a `can.Map`:\n\n```\nvar people = new can.List([\n {first: \"Justin\", last: \"Meyer\", age: 72},\n {first: \"David\", last: \"Luecke\", age: 20},\n {first: \"Matthew\", last: \"Phillips\", age: 30}\n]);\n\npeople.attr(0).attr(\"first\") //-> Justin\npeople.attr(\"0.first\") //-> Justin\n```\n\nYou can create your own custom `can.List` constructor functions\nby extending `can.List`:\n\n```\nvar People = can.List.extend({\n seniors: function(){\n return this.filter(function(person){\n return person.attr(\"age\") >= 65\n });\n }\n});\n\nvar people = new People([\n {first: \"Justin\", last: \"Meyer\", age: 72},\n {first: \"David\", last: \"Luecke\", age: 20},\n {first: \"Matthew\", last: \"Phillips\", age: 30}\n]);\n\npeople.seniors() //-> People[{Justin}]\n```\n\nWhen extending `can.List` you can specify the default `Map` type\nthat's created when plain JS objects are added to the list:\n\n```\nvar Person = can.Map.extend({\n fullName: function(){\n person.attr(\"first\")+\" \"+person.attr(\"last\");\n }\n});\n\nvar People = can.List.extend({\n Map: Person\n},{\n seniors: function(){\n return this.filter(function(person){\n return person.attr(\"age\") >= 65\n });\n }\n});\n\nvar people = new People([\n {first: \"Justin\", last: \"Meyer\", age: 72},\n {first: \"David\", last: \"Luecke\", age: 20},\n {first: \"Matthew\", last: \"Phillips\", age: 30}\n]);\n\npeople.attr(0).fullName() //-> \"Justin Meyer\"\n```\n\n### can.compute\n\n[can.compute](http://canjs.com/docs/can.compute.html) isn't used\ndirectly much anymore. However, it's used heavily in [can.Map](#section=section_can_Map)\n[getters](http://canjs.com/docs/can.Map.prototype.define.get.html) and live binding\nso it's worth understanding the basics.\n\n\n`can.compute` allows you to define single observable values like:\n\n```\nvar age = can.compute(33);\n```\n\nor derived values like:\n\n```\nvar person = new can.Map({first: \"Justin\", last: \"Meyer\"}),\n hobbies = new can.List([\"basketball\", \"hip-hop dancing\"]);\n\nvar info = can.compute(function(){\n return person.attr(\"first\")+\" \"+person.attr(\"last\")+\" is \"+\n \tage()+\" and likes \"+ hobbies.join(\",\")+\".\";\n});\n```\n\nRead a compute by calling it like a function:\n\n```\ninfo() //-> \"Justin Meyer is 33 and likes\\\n // basketball, hip-hop dancing.\"\n```\n\nListen to a compute by binding on its `change` event:\n\n```\ninfo.bind(\"change\", function(ev, newVal, oldVal){\n console.log(\"IS:\\n\",newVal,\"\\nWAS:\\n\", oldVal);\n})\n```\n\nInternally, `bind` runs the compute function, identifying what observable\nvalues it reads, and listening to them. It caches the return result so that\nreading the compute again like `info()` just returns the cached result.\n\nWhen any of the read observables change, it updates the cached value,\nand calls back any event handlers:\n\n```\nperson.attr({first: \"Brian\", last: \"Moschel\"});\n\n// console.logs:\n// IS:\n// Brian Moschel is 33 and likes basketball, hip-hop dancing.\n// WAS:\n// Justin Meyer is 33 and likes basketball, hip-hop dancing.\n```\n\n### can.stache\n\n[can.stache](http://canjs.com/docs/can.stache.html) is a Handlebars and\nMustache compliant live-binding templating language.\n\nCreate a template programmatically with `can.stache` like:\n\n```\nvar template = can.stache(\"

{{first}} {{last}}

\");\n```\n\n`template` is a __renderer__ function that, when called with observable data,\nreturns a [DocumentFragment](https://developer.mozilla.org/en-US/docs/Web/API/DocumentFragment) that is updated when the observable data changes.\n\nAdd those fragments to the page to see the result:\n\n```\nvar person = new can.Map({first: \"Brian\", last: \"Moschel\"})\n\nvar frag = template(person);\n\ndocument.body.appendChild(frag);\n\ndocument.body //->

Brian Moschel

\n\nperson.attr({first: \"Ramiya\", last: \"Meyer\"})\n\ndocument.body //->

Ramiya Meyer

\n```\n\nIn a DoneJS application, templates are used primarily as part of\na [can.Component](#section=section_can_Component) or as the [done-autorender](#section=section_done_autorender)ed main template.\n\nWhen used in a [can.Component](#section=section_can_Component), the templates are often put in their own file. For\nexample, a `person_edit.js` component file might have a `person_edit.stache` file like:\n\n```\n// person_edit.stache\nUpdate {{fullName}}:\n\n\n```\n\nThis template's __renderer__ function is imported in `person_edit.js` like:\n\n```\n// person_edit.js\nimport template from \"./person_edit.stache!\";\nimport Component from \"can/component/\";\n\nComponent.extend({\n tag: \"person-edit\",\n template: template\n});\n```\n\n`can.stache` template behavior is controlled by what's\nwithin magic tags like `{{ }}`. There are different tag types, lots of\nhelper functions, and different ways to call methods and functions.\n\nThere's too much to cover so we will highlight the important APIs.\n\nThe different tag types:\n\n - [{{key}}](http://canjs.com/docs/can.stache.tags.escaped.html) -\n inserts an escaped value.\n\n ```\n can.stache(\"{{key}}\")({key: \"Foo\"}) //-> `<b>Foo</b>`\n ```\n\n - [{{{key}}}](http://canjs.com/docs/can.stache.tags.unescaped.html) -\n inserts an unescaped value.\n\n ```\n can.stache(\"{{key}}\")({key: \"Foo\"}) //-> `Foo`\n ```\n\n- [{{#key}} ... {{/key}}](http://canjs.com/docs/can.stache.tags.section.html) -\n renders a subsection depending on the value of the key.\n\n ```\n // boolean values render the subsection or its inverse\n can.stache(\"{{#key}}A{{/key}}\")({key: true}) //-> `A`\n can.stache(\"{{#key}}A{{/key}}\")({key: false}) //-> ``\n can.stache(\"{{#key}}A{{else}}B{{/key}}\")({key: false}) //-> `B`\n\n // iterative values render the subsection for each value\n can.stache(\"{{#key}}A{{/key}}\")({key: [null,0]}) //-> `AA`\n can.stache(\"{{#key}}A{{/key}}\")({key: []}) //-> ``\n\n ```\n\n The subsection is rendered with the `key` value as the top of the [scope](http://canjs.com/docs/can.view.Scope.html):\n\n ```\n can.stache(\"{{#key}}{{child}}{{/key}}\")({key: {child:\"C\"}}) //->`C`\n ```\n\n- [{{^key}} ... {{/key}}](http://canjs.com/docs/can.stache.tags.inverse.html) -\n opposite of `{{#key}}`.\n\n ```\n can.stache(\"{{^key}}A{{/key}}\")({key: true}) //-> ``\n can.stache(\"{{^key}}A{{/key}}\")({key: false}) //-> `A`\n can.stache(\"{{^key}}A{{/key}}\")({key: [null,0]}) //-> ``\n\n can.stache(\"{{^key}}A{{else}}B{{/key}}\")({key: false}) //-> `B`\n ```\n\nThe following are stache's most commonly used helpers:\n\n - [{{#if expr}} .. {{/if}}](http://canjs.com/docs/can.stache.helpers.if.html) - renders the subsection if the expr is truthy.\n\n ```\n can.stache(\"{{#if key}}A{{/if}}\")({key: true}) //-> `A`\n can.stache(\"{{#if key}}A{{/if}}\")({key: false}) //-> ``\n\n can.stache(\"{{#if key}}A{{else}}B{{/if}}\")({key: false}) //-> `B`\n ```\n\n - [{{#is expr1 expr2}} ... {{/is}}](http://canjs.com/docs/can.stache.helpers.is.html) - compares two expressions and renders a subsection depending on the result.\n\n ```\n can.stache(\"{{#is page 'A'}}A{{/is}}\")({page: 'A'}) //-> `A`\n can.stache(\"{{#is page 'A'}}A{{/is}}\")({page: 'B'}) //-> ``\n\n can.stache(\"{{#is page 'A'}}A{{else}}C{{/is}}\")({page: 'C'}) //-> `B`\n ```\n\n - [{{#each key}} ... {{/each}}](http://canjs.com/docs/can.stache.helpers.each.html) - renders a subsection for each item in a key's value.\n\n ```\n can.stache('{{#each hobbies}}

{{.}}

{{/each}}')(['Hockey', 'Hiking']) //-> `

Hockey

Hiking

`\n ```\n\n If the value of a key is a [can.List](#section=section_can_List) only the minimum amount of DOM updates occur when the list changes.\n\n - [{{routeUrl hashes}}](http://canjs.com/docs/can.stache.helpers.routeUrl.html) - generates a url using [can.route](#section=section_can_route) for the provided hashes.\n\n ```\n can.stache(\"{{name}}\")({name: 'Item 23'}) //-> `Item 23`\n ```\n\n[Call methods](http://canjs.com/docs/can.stache.expressions.html#section_Callexpression) in your scope like: `{{method(value)}}`\n\n```\ncan.stache('

10 {{pluralize(\"Baloon\" 10)}}

')({\n pluralize: function(subject, howMany) {\n if(howMany > 1) {\n subject += 's';\n }\n return subject;\n }\n}); //-> \"

10 Baloons

\"\n```\n\n### can.view.bindings\n\n`can.view.bindings` allows you to bind to viewModel or DOM events and create one-way or two-way bindings on element's properties/attributes, can.Component viewModels and `can.stache`'s scope.\n\nCreate a one-way binding from the parent scope to a child's properties/attributes or viewModel:\n\n - [{child-prop}=\"value\"](http://canjs.com/docs/can.view.bindings.toChild.html) - One-way bind `value` in the scope to `childProp` in the viewModel.\n\n ```\n \n ```\n\n - [{$child-prop}=\"value\"](http://canjs.com/docs/can.view.bindings.toChild.html) - One-way bind `value` in the scope to the `childProp` property or attribute of the element.\n\n ```\n \n ```\n\nCreate a one-way binding from the child's properties/attributes or viewModel to the parent scope:\n\n- [{^child-prop}=\"value\"](http://canjs.com/docs/can.view.bindings.toParent.html) - One-way bind the value of `childProp` in the viewModel to the `name` in the parent scope.\n\n ```\n \n ```\n\n - [{^$child-prop}=\"value\"](http://canjs.com/docs/can.view.bindings.toParent.html) - One-way bind `value` in the scope to the `childProp` property or attribute of the element.\n\n ```\n \n ```\n\nCreate two-way bindings between the parent scope and the child's viewModel or property/attributes:\n\n- [{(child-prop)}=\"value\"](http://canjs.com/docs/can.view.bindings.twoWay.html) - Two-way bind the value of `childProp` in the viewModel to the `name` in the parent scope.\n\n ```\n \n ```\n\n - [{^$child-prop}=\"value\"](http://canjs.com/docs/can.view.bindings.twoWay.html) - Two-way bind `value` in the scope to the `childProp` property or attribute of the element.\n\n ```\n \n ```\n\nCreate bindings to viewModel or DOM events:\n\n - [($EVENT)=\"handler()\"](http://canjs.com/docs/can.view.bindings.event.html) - Listen to the DOM event `EVENT` and use `handler` as the event handler.\n\n ```\n
\n ```\n\n- [(EVENT)=\"handler()\"](http://canjs.com/docs/can.view.bindings.event.html) - Listen to the viewModel event `EVENT` and use `handler()` as the event handler.\n\n ```\n \n ```\n\n### can.Component\n\n[can.Component](http://canjs.com/docs/can.Component.html) lets you \ncreate widgets with well-defined View Models and are instantiated with\ncustom elements.\n\nDefine a `can.Component` by extending one with a `tag` name, [can.Map](#section=section_can_Map) `viewModel` and \n[can.stache template](#section=section_can_stache) like:\n\n```\n// Define the view model\nvar HelloViewModel = can.Map.extend({\n excitedMessage: function(){\n return this.attr(\"message\")+\"!\"\n }\n});\n\ncan.Component.extend({\n tag: \"hello-world\",\n viewModel: HelloViewModel,\n template: can.stache(\"

{{excitedMessage}}

\")\n});\n```\n\nTo instantiate this component so it says `Hello World!`, add\na `` element to the page like:\n\n```\n\n```\n\nUse [can.view.bindings](#section=section_can_view_bindings)\nto send a value from the `can.stache` scope like:\n\n```\n// a `can.Map` that will be available in the scope\nvar appViewModel = new can.Map({\n greeting: \"Howdy Planet\"\n});\n\nvar template = can.stache('');\n\nvar frag = template(appViewModel);\n\nfrag //-> \n //

Howdy Planet!

\n //
\n```\n\n`can.Component`s are usually built as [modlets](/Features.html#section_Modlets),\nmeaning their template and styles are another file and imported:\n\n```\n// hello-world.js\nimport Component from 'can/component/';\nimport Map from 'can/map/';\nimport 'can/map/define/';\nimport './hello-world.less!';\nimport template from './hello-world.stache!';\n\nexport const ViewModel = Map.extend({\n excitedMessage: function(){\n return this.attr(\"message\")+\"!\"\n } \n});\n\nexport default Component.extend({\n tag: \"hello-world\",\n viewModel: ViewModel,\n template\n});\n```\n\nSome components are so small, they they don't require three\nseperate files. For these, you can use a `.component` file:\n\n```\n\n\">\n \n \n \n import Map from 'can/map/';\n import 'can/map/define/';\n\n export default Map.extend({\n excitedMessage: function(){\n return this.attr(\"message\")+\"!\"\n }\n });\n \n\n```\n\n### can.route\n\n[can.route](http://canjs.com/docs/can.route.html) provides powerful 2-way, nested, routing to your application, supporting both hash and [pushstate](http://canjs.com/docs/can.route.pushstate.html). \n\nConfigure routing rules to define property values on your application's \nView Model when a url is matched.\n\n\nThe following sets the application ViewModel's `page` property\nto `\"chat\"` when the url looks like `/chat`:\n\n```\ncan.route(\":page\");\n```\n\nYou can define defaults that get set when `:page` is empty. The\nfollowing sets the default `page` property to `\"home\"`.\n\n```\ncan.route(\":page\", { page: \"home\" }); \n```\n\nYou can specify multiple properties to set for a given url: \n\n```\ncan.route(\":page/:slug\");\ncan.route(\":page/:slug/:action\");\n```\n\n\nUpdate the url by changing `can.route`:\n\n```\ncan.route.attr(\"page\", \"restaurants\");\n// location.href -> \"/restaurants\"\n```\n\nOr change `can.route` by modifying the url:\n\n```\nhistory.pushState(null, null, \"/\");\n// can.route.attr(\"page\"); // -> \"home\"\n```\n\nIn a DoneJS application can.route is bound to the [application View Model](#section=section_can_ssr_app_map), but you can connect `can.route` to other\nmaps:\n\n```\nvar Map = require(\"can/map/\");\n\nvar AppViewModel = Map.extend({\n ...\n});\n\nvar viewModel = new AppViewModel();\n\ncan.route.map(viewModel);\n```\n\nWhich will cause any changes in the route to reflect in the View Model instance, and any changes in the View Model instance to reflect in the route.\n\n## Data Layer APIs\n\n\n### can-connect\n\n[can-connect](https://connect.canjs.com) is used to connect typed \ndata to backend services. In a DoneJS application, that typed data is a \n[can.Map](#section=section_can_Map) and [can.Map](#section=section_can_List) type. \n\nTo make a simple connection to a restful interface:\n\n```\n// First, create custom Map and List type \nvar Todo = Map.extend({\n canComplete: function(ownerId) {\n return this.attr(\"ownerId\") === ownerId;\n }\n});\n\nvar TodoList = List.extend({\n Map: Todo\n},{\n incomplete: function(){\n return this.filter(function(todo){\n return !todo.attr(\"complete\")\n });\n }\n});\n\n// Then, make a connection with the right behaviors and options.\nvar todoConnection = connect([\"data-url\",\"constructor\",\"can/map\"],{\n Map: Todo,\n List: TodoList,\n url: \"/services/todos\"\n});\n```\n\nThis adds a [getList](http://connect.canjs.com/doc/can.Map.getList.html), \n[.get](http://connect.canjs.com/doc/can.Map.get.html), \n[.save](http://connect.canjs.com/doc/can.Map.prototype.save.html) and \n[.destroy](http://connect.canjs.com/doc/can.Map.prototype.destroy.html) methods to\n`Todo` allowing you to CRUD `Todo`s and `TodoList`s from the service layer like:\n\n```\n// Get a list of todos\nTodo.getList({due: \"today\"}).then(function(todos){ ... });\n\n// Get a single todo\nTodo.get({id: 5}).then(function(todo){ ... });\n\n// Create a todo\nvar todo = new Todo({name: \"dishes\"})\n\n// Create it on the server \ntodo.save().then(function(todo){\n\n // Update its properties\n todo.attr({\n name: \"Do the dishes\"\n })\n // Update the service layer with changes\n .save().then(function(todo){\n \n // Delete the todo on the service layer\n todo.destroy();\n });\n});\n```\n\n`can-connect` comes with a wide variety of behaviors that\ncan be mixed into a connection. Examples include:\n\n - [real-time](http://connect.canjs.com/doc/can-connect%7Creal-time.html) keeps `can.List`s updated with changes.\n - [fall-through-cache](http://connect.canjs.com/doc/can-connect%7Cfall-through-cache.html)\n\nTo make the process of creating `can.Map` based connections easier,\nDoneJS comes with a [supermodel generator](#section=section_generator_donejs)\ncreates a [super-map](http://connect.canjs.com/doc/can-connect%7Ccan%7Csuper-map.html).\n\nA super-map is just a connection with a bunch of the mostly commonly used\nbehaviors. Create one with the `superMap` function like:\n\n```\nexport const messageConnection = superMap({\n url: \"/services/todos\",\n Map: Todo,\n List: TodoList,\n name: 'todo'\n});\n```\n\n### can-set\n\n[can-set](https://github.com/canjs/can-set) is used to compare\nset objects that are represented by the parameters commonly passed \nto service requests. \n\nFor example, if you want all todos for user `5` that are complete, you\nmight call:\n\n```\nTodo.getList({userId: 5, complete: true})\n```\n\n`{userId: 5, complete: true}` represents a set. Using\n`can-set` we can compare it to other sets. The following\nreturns `true` because `{userId: 5, complete: true}` represents\na subset of `{userId: 5}`.\n\n```\nset.subset({userId: 5, complete: true},{userId: 5}) //-> true\n```\n\n`can-set` can perform more complex logic with custom [set Algebras](https://github.com/canjs/can-set#setalgebra).\n\nThe following creates a set-algebra that is able to combine ranges:\n\n```\n// Create a set Algebra\nvar algebra = new set.Algebra(\n set.comparators.rangeInclusive(\"start\",\"end\"));\n\n// use it\nalgebra.union({start: 1, end: 10},\n {start: 11, end: 20}) //-> {start: 1, end: 20}\n``` \n\nIn a DoneJS application, you create custom algebras to pass\nto [can-connect](#section=section_can_connect) connections. The\nconnection's behaviors use that [algebra](http://connect.canjs.com/doc/connect.base.algebra.html) to their optimizations.\n\nFor example, if the `Todo` type in the [can-connect section](#section=section_can_connect) has the following property behaviors:\n\n - `complete` can be true or false\n - `type` can be one of \"dev\", \"design\", or \"QA\"\n\n... and the service layer supports queries like:\n\n```\n//-> gets all incomplete todos\n/services/todos?complete=false \n\n// -> gets all todos that are for design and dev\n/services/todos?type[]=dev&type[]=design\n```\n\nYou'd want to create an algebra for the `superMap` as follows:\n\n```\nvar algebra = new set.Algebra(\n set.comparators.boolean(\"complete\"),\n set.comparators.enum(\"type\", [\"dev\", \"design\", \"QA\"])\n);\n\nexport const messageConnection = superMap({\n url: \"/services/todos\",\n Map: Todo,\n List: TodoList,\n name: 'todo',\n algebra: algebra\n});\n```\n\nThis allows a `superMap` to combine requests like:\n\n```\n Todo.getList({complete: true})\n+ Todo.getList({complete: true})\n================================\n Todo.getList({})\n```\n\nAnd know that if `Todo.getList({type: [\"dev\",\"design\"]})` has already been \nretrieved, there's no need to make a request for \n`Todo.getList({type: [\"dev\"]})`.\n\n\n## Testing APIs\n\n### QUnit\n\n[QUnit](http://qunitjs.com/) is DoneJS's default JavaScript unit testing framework. It is provided for DoneJS by the [steal-qunit](https://github.com/stealjs/steal-qunit) project. A basic unit test for a can.Component view-model looks like this:\n\n```js\nimport QUnit from 'steal-qunit';\nimport { ViewModel } from 'my/component/';\n\n// ViewModel unit tests\nQUnit.module('my/component');\n\nQUnit.test('Has message', function(){\n var vm = new ViewModel();\n QUnit.equal(vm.attr('message'), 'This is the my-component component');\n});\n```\n\nWhile the generators create QUnit tests by default you can switch your own tests easily to [Jasmine](https://github.com/stealjs/steal-jasmine) or [Mocha](https://github.com/stealjs/steal-mocha).\nTo use Mocha instead for the previous view-model example we just need to install the wrapper with\n\n```\nnpm install steal-mocha --save-dev\nnpm install assert --save-dev\n```\n\nAnd then change the test file to:\n\n```\nimport mocha from 'steal-mocha';\nimport assert from 'assert';\nimport { ViewModel } from 'my/component/';\n\nmocha.setup('bdd');\n\n// ViewModel unit tests\ndescribe('my/component', function() {\n it('Has a message', function() {\n var vm = new ViewModel();\n assert.equal(vm.attr('message'), 'This is the my-component component');\n });\n});\n```\n\n### FuncUnit\n\n[FuncUnit](http://funcunit.com/) enhances QUnit, Mocha or Jasmine and enables them to simulate user actions, easily test asynchronous behavior, and support black box testing. It uses a jQuery-like syntax to write functional or unit tests. When generating an application, DoneJS already includes a basic FuncUnit smoke-test which runs alongside the other tests. It looks like this:\n\n```js\nimport F from 'funcunit';\nimport QUnit from 'steal-qunit';\n\nF.attach(QUnit);\n\nQUnit.module('my-app functional smoke test', {\n beforeEach() {\n F.open('../development.html');\n }\n});\n\nQUnit.test('my-app main page shows up', function() {\n F('title').text('my-app', 'Title is set');\n});\n```\n\nThis will open the main application (`development.html` is the HTML file that loads our DoneJS app without server-side-rendering) and ensures that the `` is set to the name (which is the default in a newly generated application). To learn more about the user interactions and assertions available, follow up in the [FuncUnit API documentation](http://funcunit.com/docs/index.html).\n\n### Testee\n\n[Testee](https://github.com/bitovi/testee) is a JavaScript test runner that can run your QUnit, Mocha and Jasmine tests from the command line. The command executed when running `donejs test` (which is the same as running `npm test`) is located in the `package.json` `scripts` section and already set up to run the main test suite in Firefox like this:\n\n```\ntestee src/test.html --browsers firefox --reporter Spec\n```\n\nTo change the browsers that our tests run on we can update the list of browsers, for example to add Safari and Google Chrome Canary by changing the test script to:\n\n```\ntestee src/test.html --browsers firefox,canary,safari --reporter Spec\n```\n\nTestee supports all [Mocha command line reporters](https://mochajs.org/#reporters). For example, running the tests in the default browser [PhantomJS](http://phantomjs.org/) (DoneJS only works with PhantomJS >= 2.0) on a [Jenkins CI](https://jenkins-ci.org/) server that uses XUnit output from a `testresults.xml` can be accomplished like this:\n\n```\ntestee src/test.html --reporter XUnit > testresults.xml\n```\n\nFor more configuration options follow up in the [Testee documentation](https://github.com/bitovi/testee#testee).\n\n## DocumentJS\n\nWhen working on large applications keeping updated documentation is critical. \n[DocumentJS](http://documentjs.com/) generates API documentation for your\napplication supporting [jsdoc](http://usejsdoc.org/) syntax that can be multi-versioned.\n\n### Configuration\n\nDocumentJS is configured with a [docConfig](http://documentjs.com/docs/DocumentJS.docConfig.html) specified\nin a **documentjs.json** file within your project:\n\n```\n{\n \"sites\": {\n \"docs\": {\n \"dest\": \"docs\",\n \"glob\" : \"**/*.{js,md}\"\n }\n }\n}\n```\n\nThis specifies to look in JavaScript and Markdown files for jsdoc tags. When ran the documentation will be written to the **docs** folder.\n\n### Documenting\n\nDocumentJS includes most [tags](http://documentjs.com/docs/documentjs.tags.html) you need to document a web application and includes an API to create your own.\n\nHere's how you would document a [can.Component](#section=section_can_Component) View Model:\n\n```\n/**\n * @add order/new\n */\nexport const ViewModel = Map.extend({\n define: {\n /**\n * @property {String} slug\n *\n * The restaurants slug (short name). Will\n * be used to request the actual restaurant.\n */\n slug: {\n type: 'string'\n },\n /**\n * @property {place-my-order/models/order} order\n *\n * The order that is being processed. Will\n * be an empty new order inititally.\n */\n order: {\n Value: Order\n },\n /**\n * @property {can.Deferred} saveStatus\n *\n * A deferred that contains the status of the order when\n * it is being saved.\n */\n saveStatus: {\n Value: Object\n },\n /**\n * @property {Boolean} canPlaceOrder\n *\n * A flag to enable / disable the \"Place my order\" button.\n */\n canPlaceOrder: {\n get() {\n let items = this.attr('order.items');\n return items.attr('length');\n }\n }\n },\n\n /**\n * @function placeOrder\n *\n * Save the current order and update the status Deferred.\n *\n * @return {boolean} false to prevent the form submission\n */\n placeOrder() {\n let order = this.attr('order');\n this.attr('saveStatus', order.save());\n return false;\n },\n\n /**\n * @function startNewOrder\n *\n * Resets the order form, so a new order can be placed.\n *\n * @return {boolean} false to prevent the form submission\n */\n startNewOrder: function() {\n this.attr('order', new Order());\n this.attr('saveStatus', null);\n return false;\n }\n});\n```\n\n### Generating\n\nDoneJS preconfigures your app to be documented with:\n\n```\ndonejs document\n```\n\nOr you can run the [documentjs](http://documentjs.com/docs/DocumentJS.apis.generate.documentjs.html) command directly with:\n\n```\nnode_modules/.bin/documentjs\n```\n\n## DOM APIs\n\n### jQuery\n\n[jQuery](http://jquery.com/) is the ubiquitous DOM manipulation \nlibrary. While you don't often need to write jQuery directly,\n[CanJS](#section=section_CanJS) is built making it safe to use jQuery when needed.\n\nFor example, you can make your own custom elements that call jQuery\nplugins:\n\n```\ncan.view.tag(\"tooltip\", function(el){\n $(el).tooltip({\n content: el.getAttribute(\"content\"), \n items: \"tooltip\"\n });\n})\n```\n\n[can.view.bindings](#section=section_can_view_bindings) lets you listen \nto [jQuery special events](http://benalman.com/news/2010/03/jquery-special-events/) like:\n\n```\n<div ($tripleclick)=\"doSomething()\">\n```\n\n[can.Component](#section=section_can_Component)'s events object also supports this: \n\n```\ncan.Component.extend({\n events: {\n \"li tripleclick\": function(li, ev){ ... }\n }\n})\n```\n\n\nCanJS adds special [inserted](http://canjs.com/docs/can.events.inserted.html), [removed](http://canjs.com/docs/can.events.removed.html), and [attributes](http://canjs.com/docs/can.events.attributes.html) events. This allows you to\nteardown any behavior when the DOM is modified:\n\n```\n$(el).bind(\"removed\", function(){\n $(el).tooltip(\"teardown\");\n})\n```\n\nCanJS's live-binding also hooks into these same events. So if you remove\nan element with jQuery, CanJS will also teardown its bindings. This means that if\nyou were to call:\n\n```\n$(\"body\").empty();\n```\n\n### jQuery++\n\n[jQuery++](http://jquerypp.com/) adds a bunch of special events and other DOM\nutilties to jQuery. \n\n - DOM utilities\n - [animate](http://jquerypp.com/#animate) - Overwrites `jQuery.animate` to use CSS3 animations if possible.\n - [compare](http://jquerypp.com/#compare) - Compare the position of two elements in the page.\n - [range](http://jquerypp.com/#range) - Manipulate text ranges.\n - [within](http://jquerypp.com/#within) - Get the elements within a specified area.\n - Special events\n - [drag / drop](http://jquerypp.com/#drag) - drag drop events.\n - [hover](http://jquerypp.com/#hover) - hover events.\n - [key](http://jquerypp.com/#key) - get a string representation of the key pressed.\n - [resize](http://jquerypp.com/#resize) - listen to when an element changes size.\n - [swipe](http://jquerypp.com/#swipe) - mobile swipe events.\n\n\n## Server Side Rendering APIs\n\n### done-ssr\n\n[done-ssr](https://github.com/donejs/done-ssr) enables DoneJS applications to be\nserver-side rendered. Paired with [done-autorender](#section=section_done_autorender) \nit allows you to render the entire document from a single template.\n\n```\nvar http = require(\"http\");\nvar ssr = require(\"done-ssr\");\nvar render = ssr();\n\nvar server = http.createServer(function(request, response){\n render(request).pipe(response);\n});\n\nserver.listen(8080);\n```\n\nThe render function is called with a string url to render and returns a response\nobject that contains the html string that was rendered. Use any Node-based\nhttp framework with done-ssr.\n\nFor convenience we have published an [Express](http://expressjs.com/) middleware:\n\n```\nvar ssr = require(\"done-ssr-middleware\");\nvar app = require(\"express\")();\n\napp.use(ssr(\n config: __dirname + \"/package.json!npm\"\n));\n```\n\nAdditionally DoneJS has [done-serve](https://github.com/donejs/done-serve)\nwhich acts as a rendering front-end for your application. It will host static\ncontent, render your application, and proxy requests to another back-end server.\n\n```\ndone-serve --proxy http://localhost:7070 --port 8080\n```\n\n### done-autorender\n\n[done-autorender](https://github.com/donejs/autorender) is a Steal plugin that\nenables using a [can.stache](#section=section_can_stache) template as your application's entry point. Create a template like:\n\n```handlebars\n<html>\n<head>\n <title>app | {{page}}\n\n\n \n\n
Hello {{name}}
\n\n\n```\n\n**done-autorender** will insert this template on page load. The import specied with\nthe `export-as=\"viewModel\"` attribute is a [can.Map](#section=section_can_Map) that acts as the View Model\nfor the application.\n\nIf you have [live-reload](http://stealjs.com/docs/steal.live-reload.html#section_Use) enabled done-autorender will additionally use those APIs to re-render the\napplication when any modules are reloaded.\n\ndone-autorender handles requests when running in Node for server-side rendering and\nwill wait for all asynchronous events to complete.\n\n### can-simple-dom\n\n[can-simple-dom](https://github.com/canjs/can-simple-dom) is a minimal virtual DOM implementation used\nfor server-side and worker thread rendering. It contains enough of the DOM APIs to get basic\njQuery usage to work, as well as what is typical of CanJS applications.\n\nIf you are working on an advanced plugin you might use can-simple-dom directly,\nin which case you would import it:\n\n```js\nimport simpleDOM from \"can-simple-dom\";\n\nconst document = new simpleDOM.Document();\n```\n\nFrom here document has the normal DOM apis such as `document.createElement`.\n\n", + "description": "DoneJS is comprised of many projects that are documented seperately. This page contains overviews of each project and links to their official APIs. \n### Application Infrastructure\n\nThe blue boxes in the following architecture diagram represent modules provided by DoneJS.\n\n\n\n- [StealJS](#section=section_StealJS) - Module loader and build system. [api](http://stealjs.com/docs/index.html).\n- [CanJS](#section=section_CanJS) - Views, ViewModels, modeling part of Models, custom elements, routing. [api](http://canjs.com/docs/index.html)\n- [can-connect](#section=section_can_connect) - Data connection part of Models, real-time, fall-through cache. [api](https://connect.canjs.com)\n- [can-set](#section=section_can_set) - Create set algebras used to compare AJAX parameters. [api](https://github.com/canjs/can-set#can-set)\n- [jQuery](#section=section_jQuery) - DOM utilities. [api](http://jquery.com/)\n- [jQuery++](#section=section_jQuery__) - Even more DOM utilities. [api](http://jquerypp.com/)\n- [done-ssr](#section=section_done_ssr) - Server-side rendering for NodeJS. [api](https://github.com/donejs/done-ssr)\n- [done-autorender](#section=section_done_autorender) - Processes templates so they can be server-side rendered. [api](https://github.com/donejs/autorender#use)\n- [can-simple-dom](#section=section_can_simple_dom) - A lightweight virtual DOM. [api](https://github.com/canjs/can-simple-dom)\n\n### Tooling\n\nDoneJS provides many aspects of JavaScript application tooling, shown in the diagram below.\n\n\n\n- [donejs-cli](#section_CLIandGenerators) - The commands available to the donejs command line interface. [api](https://github.com/donejs/cli)\n- [generator-donejs](#section_CLIandGenerators) - Default generators are bundled with DoneJS. [api](https://github.com/donejs/generator-donejs/)\n- [QUnit](#section_QUnit) - Default test assertion library. [api](http://qunitjs.com/)\n- [FuncUnit](#section_FuncUnit) - Functional test utilities. [api](http://funcunit.com/)\n- [Testee](#section_Testee) - Browser launcher and test reporter. [api](https://github.com/bitovi/testee)\n- [DocumentJS](#section=section_DocumentJS) - Documentation engine. [api](http://documentjs.com/)\n\n", + "name": "Apis", "type": "page", "parent": "DoneJS", "hideSidebar": true, @@ -32,13 +31,14 @@ }, "comment": " " }, - "Apis": { + "contribute": { "src": { - "path": "docs/apis.md" + "path": "docs/contribute.md" }, - "body": "\n## Application flow overview\n\nLets talk about how the typical behavior of a DoneJS application works. We'll use\nthe chat application as an example in development. We'll cover what happens when:\n\n - A user navigates their browser from a different domain to `http://donejs-chat.com/`\n - A user navigates from `http://donejs-chat.com/` to another `http://donejs-chat.com/chat`.\n\n\n### First page load\n\n1. An http request for `http://donejs-chat.com/` is sent to a node server. The node server is configured,\n in this case with express, to use [done-ssr-middleware](#section=section_done_ssr) to render a DoneJS application:\n\n ```\n var ssr = require('done-ssr-middleware');\n\n app.use('/', ssr({\n config: __dirname + '/public/package.json!npm'\n }));\n ```\n\n2. [done-ssr](#section=section_done_ssr) uses [steal](#section=section_steal) to load the application's main module which results in loading the\n entire application. Loading the application only happens once for all page requests.\n\n A DoneJS's main module is specified where all configuration of a DoneJS application happens, its `package.json`.\n The main module is usually a [can.stache](#section=section_can_stache) template processed with the [done-autorender](#section=section_done_autorender)\n plugin. The module name is specified like: `index.stache!done-autorender`. `index.stache` might look like:\n\n ```\n \n \n My Site\n \n \n \n \n {{#eq page \"home\"}}\n\n \n {{#if isResolved}}\n \n {{/if}}\n \n\n {{/eq}}\n \n \n \n ```\n\n The [done-autorender](#section=section_done_autorender) plugin, in NodeJS, exports this template so it can be rendered. It also exports\n any modules it imports with `` that are labeled with `export-as=\"EXPORT_NAME\"`. Exporting\n the viewModel is important for [done-ssr](#section=section_done_ssr)\n\n3. Once [done-ssr](#section=section_done_ssr) has the [done-autorender](#section=section_done_autorender)'s `template` and `viewModel` export it:\n\n 1. Creates a new instance of the viewModel, setting properties on it\n using [can.route](#section=section_can_route)'s routing rules. \n 2. Creates a new [virtual dom](#section=section_can_simple_dom) instance.\n 3. Renders the [template](#section=section_can_stache) with the `viewModel` into the `virtual dom` instance.\n\n4. [done-autorender](#section=section_done_autorender) templates waits for all promises to complete\n before providing a final result. Once the template is finished rendering, [done-ssr](#section=section_done_ssr) converts it to a\n string and sends it back to the browser.\n\n5. The browser downloads the page's HTML, which includes a `\n\n In development, this loads `steal.js` which then loads `index.stache` and processes it with\n the `done-autorender`. \n\n6. In the browser, `done-autorender`:\n\n 1. Creates a new instance of the [viewModel](#section=section_can_ssr_app_map), setting properties on it\n using [can.route](#section=section_can_route)'s routing rules. \n 2. Renders the [template](#section=section_can_stache) with the `viewModel` into a document fragment.\n 3. Once all asynchronous activity has completed, it replaces the document with the rendered result.\n\n\n\n### Pushstate change\n\n1. A pushstate is triggered by user action, usually by clicking a link. [can.route](#section=section_can_route)'s routing rules determines the properties set on the application [viewModel](#section=section_can_ssr_app_map).\n\n ```\n can.route(':page', { page: 'home' });\n ```\n\n2. [done-autorender](#section=section_done_autorender) previously bound the AppViewModel to [can.route](#section=section_can_route) which causes any change in the route to be reflected in the AppMap instance.\n\n3. Live binding causes the initial template to reflect in the change in route. If the new route is `/chat` it will cause the `page` to be **chat**:\n\n ```\n \n \n My Site\n \n \n \n \n {{#eq page \"home\"}}\n\n \n {{#if isResolved}}\n \n {{/if}}\n \n\n {{/eq}}\n\n {{#eq page \"chat\"}}\n \n {{#if isResolved}}\n \n {{/if}}\n \n\n {{/eq}}\n\n \n \n \n ```\n\n3. [can-import](http://canjs.com/docs/can%7Cview%7Cstache%7Csystem.import.html) will progressively load the component for the new page with a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) as its view model. When the promise resolves the [can.Component](#section=section_can_Component) will be inserted.\n\n## CLI and Generators\n\nAfter installing DoneJS globally with `npm install donejs -g` you will have the `donejs` command available on the command line. It lets you initialize a new application and - when navigating within a DoneJS project - run scripts provided locally by your application. Within your application folder the `donejs` command is a convenience wrapper for the functionality described below and you can also get a list of all commands by running\n\n```\ndonejs help\n```\n\n### NPM scripts\n\n[NPM scripts](https://docs.npmjs.com/misc/scripts) are defined in the `scripts` section of your applications `package.json`. There are some standard scripts that every Node application uses (like `npm start` or `npm test` - both of which are already set up for you) and you can add your own which is what DoneJS does with commands like `npm run develop` or `npm run build`.\nThe `donejs` command makes running those commands easier by allowing you to run them like `donejs start`, `donejs develop` or `donejs build`\n\n### Generators\n\n`donejs add` lets you run the [Yeoman](http://yeoman.io/) generators provided by [generator-donejs](https://github.com/donejs/generator-donejs/). Currently the following generators are available:\n\n- `donejs add app [folder]` which will initialize a new application (optionally within the given folder)\n- `donejs add component ` to create a new can.Component\n- `donejs add supermodel ` to generate a new model\n\n### Third party generators\n\nIf `donejs add` can't find a built-in generator, e.g. when running `donejs add myplugin`, DoneJS will try to install the `donejs-myplugin` package from NPM and run the Yeoman generators it provides. This is how we can enable a desktop application build of the application by simply running\n\n```\ndonejs add nw\n```\n\nWhich will install the [donejs-nw](https://github.com/donejs/donejs-nw) package and then run its generator which initializes everything you need. This also works for adding a mobile application build using [donejs-cordova](https://github.com/donejs/donejs-cordova) like this:\n\n```\ndonejs add cordova\n```\n\nThis way you can use DoneJS's growing list of plugins and generators without having to add anything to your application that you don't use.\n\n## StealJS\n\nThe base of any good JavaScript application is its depenency management system. \nDoneJS uses [StealJS](http://stealjs.com/) which\nitself is split into two sub-projects:\n\n- `steal` - loads CommonJS, ES6, and AMD modules. It can also load styles, templates and more.\n- `steal-tools` - builds your application's modules for production and also provides hot-module-swapping.\n\n### steal\n\nTo use [steal](http://stealjs.com/docs/steal.html), simply add a script tag to `steal.js`\nin an HTML page or in a [done-autorender](#section=section_done_autorender) `template` and\npoint the `main` attribute to a module to load like:\n\n```\n\n```\n\nUsing the default DoneJS [system.directories.lib](http://stealjs.com/docs/npm.html#section_Configuration) configuration, this will load\n`my-app/src/my-module.js`. From there, use CommonJS, ES6, or AMD to load your modules:\n\n```\n// my-app/src/my-module.js\nimport $ from \"jquery\";\nimport \"./styles.css!\";\n\n$('body')\n```\n\nIf an `import`, `require` or `define` module reference ends with `\"/\"`, is a shorthand\nfor importing a module in the modlet format. The moduleName imported is the same\nas the module reference, but with the last folder name added again.\n\nSome examples:\n\n```\n// in components/person module.\nimport \"can/component/\"; //imports \"can/component/component\";\nimport \"./edit/\"; // imports \"components/person/edit/edit\";\n```\n\nConfigure [steal](http://stealjs.com/docs/steal.html)'s behavior in your `package.json` in the `system` object like:\n\n```\n// package.json\n{\n \"main\": \"index.stache!done-autorender\",\n ...\n \"system\": {\n \"meta\": {\n \"ui/core\": {\n \"deps\": [\n \"jquery\",\n \"theme/core.css!\",\n \"theme/theme.css!\"\n ]\n }\n }\n }\n}\n```\n\n### steal-tools\n\nIn DoneJS applications, [steal-tools](http://stealjs.com/docs/steal-tools.html) is primarily used to:\n\n - [build](http://stealjs.com/docs/steal-tools.build.html) and minify your application to production-ready bundles.\n - add [hot module swapping](http://stealjs.com/docs/steal-tools.cmd.live-reload.html)\n\nIt can also be used to [export](http://stealjs.com/docs/steal-tools.export.html) your\nmodules to different formats.\n\nDoneJS comes with a `build.js` script that call's steal-tools' [build](http://stealjs.com/docs/steal-tools.build.html):\n\n```\n//build.js\nvar stealTools = require(\"steal-tools\");\n\nvar buildPromise = stealTools.build({\n config: __dirname + \"/package.json!npm\",\n babelOptions: {\n loose: \"es6.modules\"\n }\n}, {\n bundleAssets: true\n});\n```\n\nThis is already configured to run with:\n\n```\n> donejs build\n```\n\nBut you could also run it with:\n\n```\n> node build.js\n```\n\nHot module swapping is done with [live-reload](http://stealjs.com/docs/steal-tools.cmd.live-reload.html) which\nis bundled within steal-tools. \n\nBy default `donejs develop` starts the live-reload server. However, you could start one\nyourself with:\n\n```\n> steal-tools live-reload\n```\n\n## CanJS\n\nCanJS provides:\n\n- __observables__ with [can.Map](#section=section_can_Map), [can.List](#section=section_can_List), and [can.compute](#section=section_can_compute).\n- __one-way and two-way binding templates__ with [can.stache](#section=section_can_stache) and [can.view.bindings](#section=section_can_view_bindings).\n- __custom elements__ with [can.Component](#section=section_can_Component).\n- __routing__ with [can.route](#section=section_can_route).\n\nObservables act as the `ViewModel` and part of the `Model`.\n\nOne-way and two-way binding templates act as the `View`.\n\n[can.Component](#section=section_can_Component) is used to combine `View` and `ViewModel` into\neasy to instantiate and assemble custom elements.\n\nCheckout the following quick examples of their use:\n\n__observables__:\n\n```\n// Observable objects:\nvar person = new can.Map({first: \"Justin\", last: \"Meyer\"});\n\n// Observable arrays:\nvar hobbies = new can.List([\"basketball\", \"hip-hop dancing\"]);\n\n// Observable single values:\nvar age = can.compute(33);\n\n// Observable computed values:\nvar info = can.compute(function(){\n return person.attr(\"first\")+\" \"+person.attr(\"last\")+\" is \"+\n \tage()+\" and likes \"+ hobbies.join(\",\")+\".\";\n});\n\n// Get the compute's value\ninfo() //-> Justin Meyer is 33 and likes\\\n // basketball, hip-hop dancing.\n\n// Listen to changes in the compute\ninfo.bind(\"change\", function(ev, newValue){\n newValue //-> Justin Meyer is 33 and likes\\\n // basketball, hip-hop dancing.\n});\n\nhobbies.pop(); // causes `change` event above\n```\n\n__one and two-way binding templates__:\n\n```\n// Programatically create a template\n// `{($value)}` cross binds the input's value\n// to `first` in the scope.\nvar template = can.stache(\"

{{first}}

\"+\n\t\"\");\n\n// Create observable data for the template\nvar person = new can.Map({first: \"Payal\"});\n\n// Render the template with data\nvar frag = template(person);\n\n// Add the result to the document\ndocument.body.appendChild(frag);\n\n// Document shows rendered result\ndocument.body //->

Payal

\n\n// ... User changes the input's value to \"Ramiya\" ...\n\n// Document is updated with changes\ndocument.body //->

Ramiya

\n```\n\n__custom elements__:\n\n```\n// Create a custom `can.Map` constructor function\n// with a helper function.\nvar PersonEditViewModel = can.Map.extend({\n fullName: function(){\n return this.attr(\"first\")+\" \"+this.attr(\"last\");\n }\n});\n\n// Create a template that will be rendered within\n// `` elements.\nvar template = can.stache(\"Update {{fullName}}:\"+\n\t\"\"+\n\t\"\");\n\n// Create the `` element with the specified\n// viewModel and template (view).\ncan.Component.extend({\n tag: \"person-edit\",\n viewModel: PersonEditViewModel,\n template: template\n});\n\n// Use that custom element within another template.\n// `{(first)}` cross binds ``'s\n// `first` property to `firstName` in the scope.\nvar parentTemplate = can.stache(\n \"

{{firstName}} {{lastName}}

\"+\n \"\");\n\n// Render the parent template with some data:\nvar frag = parentTemplate(new can.Map({\n firstName: \"Brian\",\n lastName: \"Moschel\"\n}));\n\ndocument.body.appendChild(frag);\n```\n\n### can.Construct\n\n[can.Construct](http://canjs.com/docs/can.Construct.html) allows you to define constructor functions that are easy to inherit\nfrom. It's used by [can.Map](#section=section_can_Map), [can.List](#section=section_can_List), and [can.Component](#section=section_can_Component).\n\nTo create your own constructor function, [extend](http://canjs.com/docs/can.Construct.extend.html) `can.Construct`\nwith prototype methods like:\n\n```\nvar Todo = can.Construct.extend({\n init: function(name){\n this.name = name;\n },\n\n author: function() { ... },\n\n coordinates: function() { ... },\n\n allowedToEdit: function( account ) {\n return true;\n }\n});\n```\n\nThen you can create instances of `Todo` like:\n\n```\nvar todo = new Todo(\"dishes\");\ntodo.name //-> \"dishes\";\ntodo.allowedToEdit() //-> true;\n```\n\nYou can extend `Todo` with [extend](http://canjs.com/docs/can.Construct.extend.html) too:\n\n```\nvar PrivateTodo = Todo.extend({\n allowedToEdit: function( account ) {\n return account.owns( this );\n }\n});\n```\n\n`can.Construct` comes with a [super](http://canjs.com/docs/can.Construct.super.html) plugin that allows you to easily\ncall base behavior like:\n\n```\nvar PrivateTodo = Todo.extend({\n init: function(name, account){\n this._super(name);\n this.account = account;\n }\n allowedToEdit: function() {\n return this.account.owns( this );\n }\n});\n```\n\n### can.Map\n\n[can.Map](http://canjs.com/docs/can.Map.html) is used to create observable\nJavaScript Object-like objects. Create an instance of the\nbase `can.Map` like:\n\n```\nvar person = new can.Map({first: \"Justin\", last: \"Meyer\"});\n```\n\nRead or write a `map`'s properties with [.attr](http://canjs.com/docs/can.Map.prototype.attr.html):\n\n```\nperson.attr(\"first\") //-> Justin\n\nperson.attr(\"first\", \"Ramiya\");\nperson.attr() //-> {first: \"Ramiya\", last: \"Meyer\"}\n\nperson.attr({first: \"Brian\", last: \"Moschel\"});\nperson.attr() //-> {first: \"Brian\", last: \"Moschel\"}\n```\n\nBind to changes in a person's properties with [.bind](http://canjs.com/docs/can.Map.prototype.bind.html):\n\n```\nperson.bind(\"first\", function(ev, newValue, oldValue){\n newValue //-> \"Laura\"\n oldvalue //-> \"Brian\"\n});\n\n// changing `first` causes the function\n// call above.\nperson.attr(\"first\", \"Laura\");\n```\n\nExtend a `can.Map` to create a new constructor function. This is\nvery useful for creating Models and View Models:\n\n```\n// pass extend an object of prototype values\nvar Person = can.Map.extend({\n fullName: function(){\n person.attr(\"first\")+\" \"+person.attr(\"last\");\n }\n})\n\nvar me = new Person({first: \"Kathrine\", last: \"Iannuzzi\"});\nme.fullName() //-> \"Kathrine Iannuzzi\"\n```\n\nThe [define plugin](http://canjs.com/docs/can.Map.prototype.define.html) allows\nyou to control the behavior of attributes. You can define\n[default values](http://canjs.com/docs/can.Map.prototype.define.value.html),\n[getters](http://canjs.com/docs/can.Map.prototype.define.get.html),\n[setters](http://canjs.com/docs/can.Map.prototype.define.set.html), and\n[type](http://canjs.com/docs/can.Map.prototype.define.type.html) converters.\n\n```\nvar Todo = can.Map.extend({\n define: {\n percentComplete: {\n value: 0.1,\n type: \"number\",\n get: function(value){\n return \"\"+value+\"%\"\n },\n set: function(newValue){\n return newValue*100;\n }\n }\n }\n});\n\nvar todo = new Todo();\ntodo.attr(\"percentComplete\") //-> 10%\n```\n\nYou can even describe asynchronous behavior which is critical for working\nwith service data:\n\n```\nvar Todo = can.Map.extend({\n define: {\n owner: {\n get: function(lastSetValue, resolve){\n User.get({id: this.attr(\"ownerId\")}).then(resolve);\n }\n }\n }\n});\n\ntodo = new Todo({ownerId: 5});\n\n// async values only become valid when bound\n// this isn't a problem because templates usually bind for you\ntodo.bind(\"owner\", function(ev, owner){\n owner //-> a User instance\n});\n```\n\n\n### can.List\n\n[can.List](http://canjs.com/docs/can.List.html) is used to create observable\nJavaScript Array-like objects. Create an instance of the\nbase `can.List` like:\n\n```\nvar hobbies = new can.List([\"basketball\",\"dancing\"]);\n```\n\nUse [.attr](http://canjs.com/docs/can.List.prototype.attr.html) to read and write items from the list or to read the length:\n\n```\nfor(var i = 0, len = hobbies.attr(\"length\"); i < len; i++){\n var hobby = hobbies.attr(i);\n}\nhobbies.attr(1, \"hip hop dancing\");\nhobbies.attr() //-> [\"basketball\", \"dancing\"]\n```\n\nUse array methods like [.push](http://canjs.com/docs/can.List.prototype.push.html), [.pop](http://canjs.com/docs/can.List.prototype.pop.html), and [.splice](http://canjs.com/docs/can.List.prototype.splice.html) to modify the array:\n\n```\nhobbies.pop();\n\nhobbies.attr() //-> [\"basketball\"];\n\nhobbies.push(\"football\");\n\nhobbies //-> can.List[\"basketball\",\"football\"]\n```\n\nUse [.forEach](http://canjs.com/docs/can.List.prototype.forEach.html), [.map](http://canjs.com/docs/can.List.prototype.map.html), or [.filter](http://canjs.com/docs/can.List.prototype.filter.html) to loop through the array. All\nthese methods return a `can.List`\n\n```\nvar intramurals = hobbies.map(function(hobby){\n return \"intramural \"+hobby;\n})\nintramurals //-> can.List[\"intramural basketball\",\n \"intramural football\"]\n```\n\nListen to when a list changes by binding on `add` or `remove` or `length`\nevents. \n\n```\nhobbies.bind(\"add\", function(ev, newHobbies, index){\n console.log(\"added\", newHobbies,\"at\", index);\n })\n .bind(\"remove\", function(ev, removedHobbies, index){\n console.log(\"removed\", newHobbies,\"at\", index);\n })\n .bind(\"length\", function(ev, newVal, oldVal){\n console.log(\"length is\", newVal);\n });\n\nhobbies.splice(1,1,\"pumpkin carving\",\"gardening\");\n // console.logs:\n // removed [football] 1\n // added [\"pumpkin carving\",\"gardening\"] 1\n // length is 3\n```\n\n\nBy default, if you initialize a list with plain JavaScript objects,\nthose objects are converted to a `can.Map`:\n\n```\nvar people = new can.List([\n {first: \"Justin\", last: \"Meyer\", age: 72},\n {first: \"David\", last: \"Luecke\", age: 20},\n {first: \"Matthew\", last: \"Phillips\", age: 30}\n]);\n\npeople.attr(0).attr(\"first\") //-> Justin\npeople.attr(\"0.first\") //-> Justin\n```\n\nYou can create your own custom `can.List` constructor functions\nby extending `can.List`:\n\n```\nvar People = can.List.extend({\n seniors: function(){\n return this.filter(function(person){\n return person.attr(\"age\") >= 65\n });\n }\n});\n\nvar people = new People([\n {first: \"Justin\", last: \"Meyer\", age: 72},\n {first: \"David\", last: \"Luecke\", age: 20},\n {first: \"Matthew\", last: \"Phillips\", age: 30}\n]);\n\npeople.seniors() //-> People[{Justin}]\n```\n\nWhen extending `can.List` you can specify the default `Map` type\nthat's created when plain JS objects are added to the list:\n\n```\nvar Person = can.Map.extend({\n fullName: function(){\n person.attr(\"first\")+\" \"+person.attr(\"last\");\n }\n});\n\nvar People = can.List.extend({\n Map: Person\n},{\n seniors: function(){\n return this.filter(function(person){\n return person.attr(\"age\") >= 65\n });\n }\n});\n\nvar people = new People([\n {first: \"Justin\", last: \"Meyer\", age: 72},\n {first: \"David\", last: \"Luecke\", age: 20},\n {first: \"Matthew\", last: \"Phillips\", age: 30}\n]);\n\npeople.attr(0).fullName() //-> \"Justin Meyer\"\n```\n\n### can.compute\n\n[can.compute](http://canjs.com/docs/can.compute.html) isn't used\ndirectly much anymore. However, it's used heavily in [can.Map](#section=section_can_Map)\n[getters](http://canjs.com/docs/can.Map.prototype.define.get.html) and live binding\nso it's worth understanding the basics.\n\n\n`can.compute` allows you to define single observable values like:\n\n```\nvar age = can.compute(33);\n```\n\nor derived values like:\n\n```\nvar person = new can.Map({first: \"Justin\", last: \"Meyer\"}),\n hobbies = new can.List([\"basketball\", \"hip-hop dancing\"]);\n\nvar info = can.compute(function(){\n return person.attr(\"first\")+\" \"+person.attr(\"last\")+\" is \"+\n \tage()+\" and likes \"+ hobbies.join(\",\")+\".\";\n});\n```\n\nRead a compute by calling it like a function:\n\n```\ninfo() //-> \"Justin Meyer is 33 and likes\\\n // basketball, hip-hop dancing.\"\n```\n\nListen to a compute by binding on its `change` event:\n\n```\ninfo.bind(\"change\", function(ev, newVal, oldVal){\n console.log(\"IS:\\n\",newVal,\"\\nWAS:\\n\", oldVal);\n})\n```\n\nInternally, `bind` runs the compute function, identifying what observable\nvalues it reads, and listening to them. It caches the return result so that\nreading the compute again like `info()` just returns the cached result.\n\nWhen any of the read observables change, it updates the cached value,\nand calls back any event handlers:\n\n```\nperson.attr({first: \"Brian\", last: \"Moschel\"});\n\n// console.logs:\n// IS:\n// Brian Moschel is 33 and likes basketball, hip-hop dancing.\n// WAS:\n// Justin Meyer is 33 and likes basketball, hip-hop dancing.\n```\n\n### can.stache\n\n[can.stache](http://canjs.com/docs/can.stache.html) is a Handlebars and\nMustache compliant live-binding templating language.\n\nCreate a template programmatically with `can.stache` like:\n\n```\nvar template = can.stache(\"

{{first}} {{last}}

\");\n```\n\n`template` is a __renderer__ function that, when called with observable data,\nreturns a [DocumentFragment](https://developer.mozilla.org/en-US/docs/Web/API/DocumentFragment) that is updated when the observable data changes.\n\nAdd those fragments to the page to see the result:\n\n```\nvar person = new can.Map({first: \"Brian\", last: \"Moschel\"})\n\nvar frag = template(person);\n\ndocument.body.appendChild(frag);\n\ndocument.body //->

Brian Moschel

\n\nperson.attr({first: \"Ramiya\", last: \"Meyer\"})\n\ndocument.body //->

Ramiya Meyer

\n```\n\nIn a DoneJS application, templates are used primarily as part of\na [can.Component](#section=section_can_Component) or as the [done-autorender](#section=section_done_autorender)ed main template.\n\nWhen used in a [can.Component](#section=section_can_Component), the templates are often put in their own file. For\nexample, a `person_edit.js` component file might have a `person_edit.stache` file like:\n\n```\n// person_edit.stache\nUpdate {{fullName}}:\n\n\n```\n\nThis template's __renderer__ function is imported in `person_edit.js` like:\n\n```\n// person_edit.js\nimport template from \"./person_edit.stache!\";\nimport Component from \"can/component/\";\n\nComponent.extend({\n tag: \"person-edit\",\n template: template\n});\n```\n\n`can.stache` template behavior is controlled by what's\nwithin magic tags like `{{ }}`. There are different tag types, lots of\nhelper functions, and different ways to call methods and functions.\n\nThere's too much to cover so we will highlight the important APIs.\n\nThe different tag types:\n\n - [{{key}}](http://canjs.com/docs/can.stache.tags.escaped.html) -\n inserts an escaped value.\n\n ```\n can.stache(\"{{key}}\")({key: \"Foo\"}) //-> `<b>Foo</b>`\n ```\n\n - [{{{key}}}](http://canjs.com/docs/can.stache.tags.unescaped.html) -\n inserts an unescaped value.\n\n ```\n can.stache(\"{{key}}\")({key: \"Foo\"}) //-> `Foo`\n ```\n\n- [{{#key}} ... {{/key}}](http://canjs.com/docs/can.stache.tags.section.html) -\n renders a subsection depending on the value of the key.\n\n ```\n // boolean values render the subsection or its inverse\n can.stache(\"{{#key}}A{{/key}}\")({key: true}) //-> `A`\n can.stache(\"{{#key}}A{{/key}}\")({key: false}) //-> ``\n can.stache(\"{{#key}}A{{else}}B{{/key}}\")({key: false}) //-> `B`\n\n // iterative values render the subsection for each value\n can.stache(\"{{#key}}A{{/key}}\")({key: [null,0]}) //-> `AA`\n can.stache(\"{{#key}}A{{/key}}\")({key: []}) //-> ``\n\n ```\n\n The subsection is rendered with the `key` value as the top of the [scope](http://canjs.com/docs/can.view.Scope.html):\n\n ```\n can.stache(\"{{#key}}{{child}}{{/key}}\")({key: {child:\"C\"}}) //->`C`\n ```\n\n- [{{^key}} ... {{/key}}](http://canjs.com/docs/can.stache.tags.inverse.html) -\n opposite of `{{#key}}`.\n\n ```\n can.stache(\"{{^key}}A{{/key}}\")({key: true}) //-> ``\n can.stache(\"{{^key}}A{{/key}}\")({key: false}) //-> `A`\n can.stache(\"{{^key}}A{{/key}}\")({key: [null,0]}) //-> ``\n\n can.stache(\"{{^key}}A{{else}}B{{/key}}\")({key: false}) //-> `B`\n ```\n\nThe following are stache's most commonly used helpers:\n\n - [{{#if expr}} .. {{/if}}](http://canjs.com/docs/can.stache.helpers.if.html) - renders the subsection if the expr is truthy.\n\n ```\n can.stache(\"{{#if key}}A{{/if}}\")({key: true}) //-> `A`\n can.stache(\"{{#if key}}A{{/if}}\")({key: false}) //-> ``\n\n can.stache(\"{{#if key}}A{{else}}B{{/if}}\")({key: false}) //-> `B`\n ```\n\n - [{{#is expr1 expr2}} ... {{/is}}](http://canjs.com/docs/can.stache.helpers.is.html) - compares two expressions and renders a subsection depending on the result.\n\n ```\n can.stache(\"{{#is page 'A'}}A{{/is}}\")({page: 'A'}) //-> `A`\n can.stache(\"{{#is page 'A'}}A{{/is}}\")({page: 'B'}) //-> ``\n\n can.stache(\"{{#is page 'A'}}A{{else}}C{{/is}}\")({page: 'C'}) //-> `B`\n ```\n\n - [{{#each key}} ... {{/each}}](http://canjs.com/docs/can.stache.helpers.each.html) - renders a subsection for each item in a key's value.\n\n ```\n can.stache('{{#each hobbies}}

{{.}}

{{/each}}')(['Hockey', 'Hiking']) //-> `

Hockey

Hiking

`\n ```\n\n If the value of a key is a [can.List](#section=section_can_List) only the minimum amount of DOM updates occur when the list changes.\n\n - [{{routeUrl hashes}}](http://canjs.com/docs/can.stache.helpers.routeUrl.html) - generates a url using [can.route](#section=section_can_route) for the provided hashes.\n\n ```\n can.stache(\"{{name}}\")({name: 'Item 23'}) //-> `Item 23`\n ```\n\n[Call methods](http://canjs.com/docs/can.stache.expressions.html#section_Callexpression) in your scope like: `{{method(value)}}`\n\n```\ncan.stache('

10 {{pluralize(\"Baloon\" 10)}}

')({\n pluralize: function(subject, howMany) {\n if(howMany > 1) {\n subject += 's';\n }\n return subject;\n }\n}); //-> \"

10 Baloons

\"\n```\n\n### can.view.bindings\n\n`can.view.bindings` allows you to bind to viewModel or DOM events and create one-way or two-way bindings on element's properties/attributes, can.Component viewModels and `can.stache`'s scope.\n\nCreate a one-way binding from the parent scope to a child's properties/attributes or viewModel:\n\n - [{child-prop}=\"value\"](http://canjs.com/docs/can.view.bindings.toChild.html) - One-way bind `value` in the scope to `childProp` in the viewModel.\n\n ```\n \n ```\n\n - [{$child-prop}=\"value\"](http://canjs.com/docs/can.view.bindings.toChild.html) - One-way bind `value` in the scope to the `childProp` property or attribute of the element.\n\n ```\n \n ```\n\nCreate a one-way binding from the child's properties/attributes or viewModel to the parent scope:\n\n- [{^child-prop}=\"value\"](http://canjs.com/docs/can.view.bindings.toParent.html) - One-way bind the value of `childProp` in the viewModel to the `name` in the parent scope.\n\n ```\n \n ```\n\n - [{^$child-prop}=\"value\"](http://canjs.com/docs/can.view.bindings.toParent.html) - One-way bind `value` in the scope to the `childProp` property or attribute of the element.\n\n ```\n \n ```\n\nCreate two-way bindings between the parent scope and the child's viewModel or property/attributes:\n\n- [{(child-prop)}=\"value\"](http://canjs.com/docs/can.view.bindings.twoWay.html) - Two-way bind the value of `childProp` in the viewModel to the `name` in the parent scope.\n\n ```\n \n ```\n\n - [{^$child-prop}=\"value\"](http://canjs.com/docs/can.view.bindings.twoWay.html) - Two-way bind `value` in the scope to the `childProp` property or attribute of the element.\n\n ```\n \n ```\n\nCreate bindings to viewModel or DOM events:\n\n - [($EVENT)=\"handler()\"](http://canjs.com/docs/can.view.bindings.event.html) - Listen to the DOM event `EVENT` and use `handler` as the event handler.\n\n ```\n
\n ```\n\n- [(EVENT)=\"handler()\"](http://canjs.com/docs/can.view.bindings.event.html) - Listen to the viewModel event `EVENT` and use `handler()` as the event handler.\n\n ```\n \n ```\n\n### can.Component\n\n[can.Component](http://canjs.com/docs/can.Component.html) lets you \ncreate widgets with well-defined View Models and are instantiated with\ncustom elements.\n\nDefine a `can.Component` by extending one with a `tag` name, [can.Map](#section=section_can_Map) `viewModel` and \n[can.stache template](#section=section_can_stache) like:\n\n```\n// Define the view model\nvar HelloViewModel = can.Map.extend({\n excitedMessage: function(){\n return this.attr(\"message\")+\"!\"\n }\n});\n\ncan.Component.extend({\n tag: \"hello-world\",\n viewModel: HelloViewModel,\n template: can.stache(\"

{{excitedMessage}}

\")\n});\n```\n\nTo instantiate this component so it says `Hello World!`, add\na `` element to the page like:\n\n```\n\n```\n\nUse [can.view.bindings](#section=section_can_view_bindings)\nto send a value from the `can.stache` scope like:\n\n```\n// a `can.Map` that will be available in the scope\nvar appViewModel = new can.Map({\n greeting: \"Howdy Planet\"\n});\n\nvar template = can.stache('');\n\nvar frag = template(appViewModel);\n\nfrag //-> \n //

Howdy Planet!

\n //
\n```\n\n`can.Component`s are usually built as [modlets](/Features.html#section_Modlets),\nmeaning their template and styles are another file and imported:\n\n```\n// hello-world.js\nimport Component from 'can/component/';\nimport Map from 'can/map/';\nimport 'can/map/define/';\nimport './hello-world.less!';\nimport template from './hello-world.stache!';\n\nexport const ViewModel = Map.extend({\n excitedMessage: function(){\n return this.attr(\"message\")+\"!\"\n } \n});\n\nexport default Component.extend({\n tag: \"hello-world\",\n viewModel: ViewModel,\n template\n});\n```\n\nSome components are so small, they they don't require three\nseperate files. For these, you can use a `.component` file:\n\n```\n\n\">\n \n \n \n import Map from 'can/map/';\n import 'can/map/define/';\n\n export default Map.extend({\n excitedMessage: function(){\n return this.attr(\"message\")+\"!\"\n }\n });\n \n\n```\n\n### can.route\n\n[can.route](http://canjs.com/docs/can.route.html) provides powerful 2-way, nested, routing to your application, supporting both hash and [pushstate](http://canjs.com/docs/can.route.pushstate.html). \n\nConfigure routing rules to define property values on your application's \nView Model when a url is matched.\n\n\nThe following sets the application ViewModel's `page` property\nto `\"chat\"` when the url looks like `/chat`:\n\n```\ncan.route(\":page\");\n```\n\nYou can define defaults that get set when `:page` is empty. The\nfollowing sets the default `page` property to `\"home\"`.\n\n```\ncan.route(\":page\", { page: \"home\" }); \n```\n\nYou can specify multiple properties to set for a given url: \n\n```\ncan.route(\":page/:slug\");\ncan.route(\":page/:slug/:action\");\n```\n\n\nUpdate the url by changing `can.route`:\n\n```\ncan.route.attr(\"page\", \"restaurants\");\n// location.href -> \"/restaurants\"\n```\n\nOr change `can.route` by modifying the url:\n\n```\nhistory.pushState(null, null, \"/\");\n// can.route.attr(\"page\"); // -> \"home\"\n```\n\nIn a DoneJS application can.route is bound to the [application View Model](#section=section_can_ssr_app_map), but you can connect `can.route` to other\nmaps:\n\n```\nvar Map = require(\"can/map/\");\n\nvar AppViewModel = Map.extend({\n ...\n});\n\nvar viewModel = new AppViewModel();\n\ncan.route.map(viewModel);\n```\n\nWhich will cause any changes in the route to reflect in the View Model instance, and any changes in the View Model instance to reflect in the route.\n\n## Data Layer APIs\n\n\n### can-connect\n\n[can-connect](https://connect.canjs.com) is used to connect typed \ndata to backend services. In a DoneJS application, that typed data is a \n[can.Map](#section=section_can_Map) and [can.Map](#section=section_can_List) type. \n\nTo make a simple connection to a restful interface:\n\n```\n// First, create custom Map and List type \nvar Todo = Map.extend({\n canComplete: function(ownerId) {\n return this.attr(\"ownerId\") === ownerId;\n }\n});\n\nvar TodoList = List.extend({\n Map: Todo\n},{\n incomplete: function(){\n return this.filter(function(todo){\n return !todo.attr(\"complete\")\n });\n }\n});\n\n// Then, make a connection with the right behaviors and options.\nvar todoConnection = connect([\"data-url\",\"constructor\",\"can/map\"],{\n Map: Todo,\n List: TodoList,\n url: \"/services/todos\"\n});\n```\n\nThis adds a [getList](http://connect.canjs.com/doc/can.Map.getList.html), \n[.get](http://connect.canjs.com/doc/can.Map.get.html), \n[.save](http://connect.canjs.com/doc/can.Map.prototype.save.html) and \n[.destroy](http://connect.canjs.com/doc/can.Map.prototype.destroy.html) methods to\n`Todo` allowing you to CRUD `Todo`s and `TodoList`s from the service layer like:\n\n```\n// Get a list of todos\nTodo.getList({due: \"today\"}).then(function(todos){ ... });\n\n// Get a single todo\nTodo.get({id: 5}).then(function(todo){ ... });\n\n// Create a todo\nvar todo = new Todo({name: \"dishes\"})\n\n// Create it on the server \ntodo.save().then(function(todo){\n\n // Update its properties\n todo.attr({\n name: \"Do the dishes\"\n })\n // Update the service layer with changes\n .save().then(function(todo){\n \n // Delete the todo on the service layer\n todo.destroy();\n });\n});\n```\n\n`can-connect` comes with a wide variety of behaviors that\ncan be mixed into a connection. Examples include:\n\n - [real-time](http://connect.canjs.com/doc/can-connect%7Creal-time.html) keeps `can.List`s updated with changes.\n - [fall-through-cache](http://connect.canjs.com/doc/can-connect%7Cfall-through-cache.html)\n\nTo make the process of creating `can.Map` based connections easier,\nDoneJS comes with a [supermodel generator](#section=section_generator_donejs)\ncreates a [super-map](http://connect.canjs.com/doc/can-connect%7Ccan%7Csuper-map.html).\n\nA super-map is just a connection with a bunch of the mostly commonly used\nbehaviors. Create one with the `superMap` function like:\n\n```\nexport const messageConnection = superMap({\n url: \"/services/todos\",\n Map: Todo,\n List: TodoList,\n name: 'todo'\n});\n```\n\n### can-set\n\n[can-set](https://github.com/canjs/can-set) is used to compare\nset objects that are represented by the parameters commonly passed \nto service requests. \n\nFor example, if you want all todos for user `5` that are complete, you\nmight call:\n\n```\nTodo.getList({userId: 5, complete: true})\n```\n\n`{userId: 5, complete: true}` represents a set. Using\n`can-set` we can compare it to other sets. The following\nreturns `true` because `{userId: 5, complete: true}` represents\na subset of `{userId: 5}`.\n\n```\nset.subset({userId: 5, complete: true},{userId: 5}) //-> true\n```\n\n`can-set` can perform more complex logic with custom [set Algebras](https://github.com/canjs/can-set#setalgebra).\n\nThe following creates a set-algebra that is able to combine ranges:\n\n```\n// Create a set Algebra\nvar algebra = new set.Algebra(\n set.comparators.rangeInclusive(\"start\",\"end\"));\n\n// use it\nalgebra.union({start: 1, end: 10},\n {start: 11, end: 20}) //-> {start: 1, end: 20}\n``` \n\nIn a DoneJS application, you create custom algebras to pass\nto [can-connect](#section=section_can_connect) connections. The\nconnection's behaviors use that [algebra](http://connect.canjs.com/doc/connect.base.algebra.html) to their optimizations.\n\nFor example, if the `Todo` type in the [can-connect section](#section=section_can_connect) has the following property behaviors:\n\n - `complete` can be true or false\n - `type` can be one of \"dev\", \"design\", or \"QA\"\n\n... and the service layer supports queries like:\n\n```\n//-> gets all incomplete todos\n/services/todos?complete=false \n\n// -> gets all todos that are for design and dev\n/services/todos?type[]=dev&type[]=design\n```\n\nYou'd want to create an algebra for the `superMap` as follows:\n\n```\nvar algebra = new set.Algebra(\n set.comparators.boolean(\"complete\"),\n set.comparators.enum(\"type\", [\"dev\", \"design\", \"QA\"])\n);\n\nexport const messageConnection = superMap({\n url: \"/services/todos\",\n Map: Todo,\n List: TodoList,\n name: 'todo',\n algebra: algebra\n});\n```\n\nThis allows a `superMap` to combine requests like:\n\n```\n Todo.getList({complete: true})\n+ Todo.getList({complete: true})\n================================\n Todo.getList({})\n```\n\nAnd know that if `Todo.getList({type: [\"dev\",\"design\"]})` has already been \nretrieved, there's no need to make a request for \n`Todo.getList({type: [\"dev\"]})`.\n\n\n## Testing APIs\n\n### QUnit\n\n[QUnit](http://qunitjs.com/) is DoneJS's default JavaScript unit testing framework. It is provided for DoneJS by the [steal-qunit](https://github.com/stealjs/steal-qunit) project. A basic unit test for a can.Component view-model looks like this:\n\n```js\nimport QUnit from 'steal-qunit';\nimport { ViewModel } from 'my/component/';\n\n// ViewModel unit tests\nQUnit.module('my/component');\n\nQUnit.test('Has message', function(){\n var vm = new ViewModel();\n QUnit.equal(vm.attr('message'), 'This is the my-component component');\n});\n```\n\nWhile the generators create QUnit tests by default you can switch your own tests easily to [Jasmine](https://github.com/stealjs/steal-jasmine) or [Mocha](https://github.com/stealjs/steal-mocha).\nTo use Mocha instead for the previous view-model example we just need to install the wrapper with\n\n```\nnpm install steal-mocha --save-dev\nnpm install assert --save-dev\n```\n\nAnd then change the test file to:\n\n```\nimport mocha from 'steal-mocha';\nimport assert from 'assert';\nimport { ViewModel } from 'my/component/';\n\nmocha.setup('bdd');\n\n// ViewModel unit tests\ndescribe('my/component', function() {\n it('Has a message', function() {\n var vm = new ViewModel();\n assert.equal(vm.attr('message'), 'This is the my-component component');\n });\n});\n```\n\n### FuncUnit\n\n[FuncUnit](http://funcunit.com/) enhances QUnit, Mocha or Jasmine and enables them to simulate user actions, easily test asynchronous behavior, and support black box testing. It uses a jQuery-like syntax to write functional or unit tests. When generating an application, DoneJS already includes a basic FuncUnit smoke-test which runs alongside the other tests. It looks like this:\n\n```js\nimport F from 'funcunit';\nimport QUnit from 'steal-qunit';\n\nF.attach(QUnit);\n\nQUnit.module('my-app functional smoke test', {\n beforeEach() {\n F.open('../development.html');\n }\n});\n\nQUnit.test('my-app main page shows up', function() {\n F('title').text('my-app', 'Title is set');\n});\n```\n\nThis will open the main application (`development.html` is the HTML file that loads our DoneJS app without server-side-rendering) and ensures that the `` is set to the name (which is the default in a newly generated application). To learn more about the user interactions and assertions available, follow up in the [FuncUnit API documentation](http://funcunit.com/docs/index.html).\n\n### Testee\n\n[Testee](https://github.com/bitovi/testee) is a JavaScript test runner that can run your QUnit, Mocha and Jasmine tests from the command line. The command executed when running `donejs test` (which is the same as running `npm test`) is located in the `package.json` `scripts` section and already set up to run the main test suite in Firefox like this:\n\n```\ntestee src/test.html --browsers firefox --reporter Spec\n```\n\nTo change the browsers that our tests run on we can update the list of browsers, for example to add Safari and Google Chrome Canary by changing the test script to:\n\n```\ntestee src/test.html --browsers firefox,canary,safari --reporter Spec\n```\n\nTestee supports all [Mocha command line reporters](https://mochajs.org/#reporters). For example, running the tests in the default browser [PhantomJS](http://phantomjs.org/) (DoneJS only works with PhantomJS >= 2.0) on a [Jenkins CI](https://jenkins-ci.org/) server that uses XUnit output from a `testresults.xml` can be accomplished like this:\n\n```\ntestee src/test.html --reporter XUnit > testresults.xml\n```\n\nFor more configuration options follow up in the [Testee documentation](https://github.com/bitovi/testee#testee).\n\n## DocumentJS\n\nWhen working on large applications keeping updated documentation is critical. \n[DocumentJS](http://documentjs.com/) generates API documentation for your\napplication supporting [jsdoc](http://usejsdoc.org/) syntax that can be multi-versioned.\n\n### Configuration\n\nDocumentJS is configured with a [docConfig](http://documentjs.com/docs/DocumentJS.docConfig.html) specified\nin a **documentjs.json** file within your project:\n\n```\n{\n \"sites\": {\n \"docs\": {\n \"dest\": \"docs\",\n \"glob\" : \"**/*.{js,md}\"\n }\n }\n}\n```\n\nThis specifies to look in JavaScript and Markdown files for jsdoc tags. When ran the documentation will be written to the **docs** folder.\n\n### Documenting\n\nDocumentJS includes most [tags](http://documentjs.com/docs/documentjs.tags.html) you need to document a web application and includes an API to create your own.\n\nHere's how you would document a [can.Component](#section=section_can_Component) View Model:\n\n```\n/**\n * @add order/new\n */\nexport const ViewModel = Map.extend({\n define: {\n /**\n * @property {String} slug\n *\n * The restaurants slug (short name). Will\n * be used to request the actual restaurant.\n */\n slug: {\n type: 'string'\n },\n /**\n * @property {place-my-order/models/order} order\n *\n * The order that is being processed. Will\n * be an empty new order inititally.\n */\n order: {\n Value: Order\n },\n /**\n * @property {can.Deferred} saveStatus\n *\n * A deferred that contains the status of the order when\n * it is being saved.\n */\n saveStatus: {\n Value: Object\n },\n /**\n * @property {Boolean} canPlaceOrder\n *\n * A flag to enable / disable the \"Place my order\" button.\n */\n canPlaceOrder: {\n get() {\n let items = this.attr('order.items');\n return items.attr('length');\n }\n }\n },\n\n /**\n * @function placeOrder\n *\n * Save the current order and update the status Deferred.\n *\n * @return {boolean} false to prevent the form submission\n */\n placeOrder() {\n let order = this.attr('order');\n this.attr('saveStatus', order.save());\n return false;\n },\n\n /**\n * @function startNewOrder\n *\n * Resets the order form, so a new order can be placed.\n *\n * @return {boolean} false to prevent the form submission\n */\n startNewOrder: function() {\n this.attr('order', new Order());\n this.attr('saveStatus', null);\n return false;\n }\n});\n```\n\n### Generating\n\nDoneJS preconfigures your app to be documented with:\n\n```\ndonejs document\n```\n\nOr you can run the [documentjs](http://documentjs.com/docs/DocumentJS.apis.generate.documentjs.html) command directly with:\n\n```\nnode_modules/.bin/documentjs\n```\n\n## DOM APIs\n\n### jQuery\n\n[jQuery](http://jquery.com/) is the ubiquitous DOM manipulation \nlibrary. While you don't often need to write jQuery directly,\n[CanJS](#section=section_CanJS) is built making it safe to use jQuery when needed.\n\nFor example, you can make your own custom elements that call jQuery\nplugins:\n\n```\ncan.view.tag(\"tooltip\", function(el){\n $(el).tooltip({\n content: el.getAttribute(\"content\"), \n items: \"tooltip\"\n });\n})\n```\n\n[can.view.bindings](#section=section_can_view_bindings) lets you listen \nto [jQuery special events](http://benalman.com/news/2010/03/jquery-special-events/) like:\n\n```\n<div ($tripleclick)=\"doSomething()\">\n```\n\n[can.Component](#section=section_can_Component)'s events object also supports this: \n\n```\ncan.Component.extend({\n events: {\n \"li tripleclick\": function(li, ev){ ... }\n }\n})\n```\n\n\nCanJS adds special [inserted](http://canjs.com/docs/can.events.inserted.html), [removed](http://canjs.com/docs/can.events.removed.html), and [attributes](http://canjs.com/docs/can.events.attributes.html) events. This allows you to\nteardown any behavior when the DOM is modified:\n\n```\n$(el).bind(\"removed\", function(){\n $(el).tooltip(\"teardown\");\n})\n```\n\nCanJS's live-binding also hooks into these same events. So if you remove\nan element with jQuery, CanJS will also teardown its bindings. This means that if\nyou were to call:\n\n```\n$(\"body\").empty();\n```\n\n### jQuery++\n\n[jQuery++](http://jquerypp.com/) adds a bunch of special events and other DOM\nutilties to jQuery. \n\n - DOM utilities\n - [animate](http://jquerypp.com/#animate) - Overwrites `jQuery.animate` to use CSS3 animations if possible.\n - [compare](http://jquerypp.com/#compare) - Compare the position of two elements in the page.\n - [range](http://jquerypp.com/#range) - Manipulate text ranges.\n - [within](http://jquerypp.com/#within) - Get the elements within a specified area.\n - Special events\n - [drag / drop](http://jquerypp.com/#drag) - drag drop events.\n - [hover](http://jquerypp.com/#hover) - hover events.\n - [key](http://jquerypp.com/#key) - get a string representation of the key pressed.\n - [resize](http://jquerypp.com/#resize) - listen to when an element changes size.\n - [swipe](http://jquerypp.com/#swipe) - mobile swipe events.\n\n\n## Server Side Rendering APIs\n\n### done-ssr\n\n[done-ssr](https://github.com/donejs/done-ssr) enables DoneJS applications to be\nserver-side rendered. Paired with [done-autorender](#section=section_done_autorender) \nit allows you to render the entire document from a single template.\n\n```\nvar http = require(\"http\");\nvar ssr = require(\"done-ssr\");\nvar render = ssr();\n\nvar server = http.createServer(function(request, response){\n render(request).pipe(response);\n});\n\nserver.listen(8080);\n```\n\nThe render function is called with a string url to render and returns a response\nobject that contains the html string that was rendered. Use any Node-based\nhttp framework with done-ssr.\n\nFor convenience we have published an [Express](http://expressjs.com/) middleware:\n\n```\nvar ssr = require(\"done-ssr-middleware\");\nvar app = require(\"express\")();\n\napp.use(ssr(\n config: __dirname + \"/package.json!npm\"\n));\n```\n\nAdditionally DoneJS has [done-serve](https://github.com/donejs/done-serve)\nwhich acts as a rendering front-end for your application. It will host static\ncontent, render your application, and proxy requests to another back-end server.\n\n```\ndone-serve --proxy http://localhost:7070 --port 8080\n```\n\n### done-autorender\n\n[done-autorender](https://github.com/donejs/autorender) is a Steal plugin that\nenables using a [can.stache](#section=section_can_stache) template as your application's entry point. Create a template like:\n\n```handlebars\n<html>\n<head>\n <title>app | {{page}}\n\n\n \n\n
Hello {{name}}
\n\n\n```\n\n**done-autorender** will insert this template on page load. The import specied with\nthe `export-as=\"viewModel\"` attribute is a [can.Map](#section=section_can_Map) that acts as the View Model\nfor the application.\n\nIf you have [live-reload](http://stealjs.com/docs/steal.live-reload.html#section_Use) enabled done-autorender will additionally use those APIs to re-render the\napplication when any modules are reloaded.\n\ndone-autorender handles requests when running in Node for server-side rendering and\nwill wait for all asynchronous events to complete.\n\n### can-simple-dom\n\n[can-simple-dom](https://github.com/canjs/can-simple-dom) is a minimal virtual DOM implementation used\nfor server-side and worker thread rendering. It contains enough of the DOM APIs to get basic\njQuery usage to work, as well as what is typical of CanJS applications.\n\nIf you are working on an advanced plugin you might use can-simple-dom directly,\nin which case you would import it:\n\n```js\nimport simpleDOM from \"can-simple-dom\";\n\nconst document = new simpleDOM.Document();\n```\n\nFrom here document has the normal DOM apis such as `document.createElement`.\n\n", - "description": "DoneJS is comprised of many projects that are documented seperately. This page contains overviews of each project and links to their official APIs. \n### Application Infrastructure\n\nThe blue boxes in the following architecture diagram represent modules provided by DoneJS.\n\n\n\n- [StealJS](#section=section_StealJS) - Module loader and build system. [api](http://stealjs.com/docs/index.html).\n- [CanJS](#section=section_CanJS) - Views, ViewModels, modeling part of Models, custom elements, routing. [api](http://canjs.com/docs/index.html)\n- [can-connect](#section=section_can_connect) - Data connection part of Models, real-time, fall-through cache. [api](https://connect.canjs.com)\n- [can-set](#section=section_can_set) - Create set algebras used to compare AJAX parameters. [api](https://github.com/canjs/can-set#can-set)\n- [jQuery](#section=section_jQuery) - DOM utilities. [api](http://jquery.com/)\n- [jQuery++](#section=section_jQuery__) - Even more DOM utilities. [api](http://jquerypp.com/)\n- [done-ssr](#section=section_done_ssr) - Server-side rendering for NodeJS. [api](https://github.com/donejs/done-ssr)\n- [done-autorender](#section=section_done_autorender) - Processes templates so they can be server-side rendered. [api](https://github.com/donejs/autorender#use)\n- [can-simple-dom](#section=section_can_simple_dom) - A lightweight virtual DOM. [api](https://github.com/canjs/can-simple-dom)\n\n### Tooling\n\nDoneJS provides many aspects of JavaScript application tooling, shown in the diagram below.\n\n\n\n- [donejs-cli](#section_CLIandGenerators) - The commands available to the donejs command line interface. [api](https://github.com/donejs/cli)\n- [generator-donejs](#section_CLIandGenerators) - Default generators are bundled with DoneJS. [api](https://github.com/donejs/generator-donejs/)\n- [QUnit](#section_QUnit) - Default test assertion library. [api](http://qunitjs.com/)\n- [FuncUnit](#section_FuncUnit) - Functional test utilities. [api](http://funcunit.com/)\n- [Testee](#section_Testee) - Browser launcher and test reporter. [api](https://github.com/bitovi/testee)\n- [DocumentJS](#section=section_DocumentJS) - Documentation engine. [api](http://documentjs.com/)\n\n", - "name": "Apis", + "body": "Thank you for contributing to DoneJS! If you need any help setting up a DoneJS development environment and fixing DoneJS bugs, please reach out to us on [gitter](https://gitter.im/donejs/donejs) or email [contact@bitovi.com](mailto:contact@bitovi.com). We will happily walk you through setting up a the environment, creating a test, and submitting a pull request.\n\n## Reporting Bugs\n\nTo report a bug, please visit [GitHub Issues](https://github.com/donejs/donejs/issues).\n\nWhen filing a bug, it is helpful to include:\n\n- Small examples using tools like [JSFiddle](http://jsfiddle.com/). You can fork the following DoneJS fiddles:\n - [jQuery](http://jsfiddle.net/donejs/qYdwR/)\n - [Zepto](http://jsfiddle.net/donejs/7Yaxk/)\n - [Dojo](http://jsfiddle.net/donejs/9x96n/)\n - [YUI](http://jsfiddle.net/donejs/w6m73/)\n - [Mootools](http://jsfiddle.net/donejs/mnNJX/)\n- Breaking unit tests (optional)\n- Proposed fix solutions (optional)\n\nSearch for previous tickets, if there is one add to that one rather than creating another. You can also post on the [Forums](https://forums.donejs.com) or talk to us in [gitter](https://gitter.im/donejs/donejs).\n\n## Installing \n\n1. Fork DoneJS on GitHub.\n2. Clone it with: `git clone git@github.com:/donejs`\n\n## Structure\n\nTODO: Explain stack or link to api section.\n\n## Contributing\n\nWhen contributing, please include tests with new features or bug fixes in a feature branch until you're ready to submit the code for consideration; then push to the fork, and submit a pull request. More detailed steps are as follows:\n\n1. Navigate to your clone of the DoneJS repository - `cd /path/to/donejs`\n2. Create a new feature branch - `git checkout -b html5-fix`\n3. Make some changes\n4. Update tests to accomodate your changes\n5. Run tests and make sure they pass in all browsers\n6. Update documentation if necessary\n7. Push your changes to your remote branch - `git push origin html5-fix`\n8. Submit a pull request! Navigate to [Pull Requests](https://github.com/donejs/donejs/pulls) and click the 'New Pull Request' button. Fill in some details about your potential patch including a meaningful title. When finished, press \"Send pull request\". The core team will be notified about your submission and let you know of any problems or targeted release date.\n\n## Documentation\n\nIf your changes affect the public API, please make relevant changes to the documentation. Documentation is found either inline or in markdown files in the respective directory. In order to view your changes in documentation you will need to run the DoneJS.com site locally and regenerate the docs.\n\nTo run the docs and watch the files for changes run the command:\n```\n./node_modules/.bin/documentjs -d -f --watch\n```\n\nFinally, serve the site locally using a tool like [http-server](https://www.npmjs.com/package/http-server).\n\n## Making a build\n\nTo make a build (standalone and AMD version) you will also need to have [[NodeJS](http://nodejs.org/), [npm](http://npmjs.org/), [Grunt](http://gruntjs.com/) and all of the DoneJS dev dependencies installed.\n\n### Getting Set Up\n\n1. Install NodeJS & npm - [NodeJS](http://nodejs.org/) or use `brew install nodejs`\n2. Install Grunt - `npm install grunt-cli -g`\n3. Navigate to your local clone of DoneJS - `cd /path/to/canjs`\n4. Install dependencies - `npm install`\n\nAfter you have completed those steps simply run `grunt build` and it will put the built files in the `can/dist` directory, making them ready for download.\n\n## Style Guide\n\n### Linting\nGrunt provides a `quality` task to verify some basic, practical soundness of the codebase. The options are preset.\n\n### Spacing\nIndentation with tabs, not spaces.\n\n`if/else/for/while/try` always have braces, with the first brace on the same line. For example:\n\n if(foo){\n\n }\n \nSpaces after commas. For example:\n\n myfn = function(foo, bar, moo){ ... }\n\n### Assignments\n\nAssignments should always have a semicolon after them.\n\nAssignments in a declaration should always be on their own line. Declarations that don't have an assignment should be listed together at the start of the declaration. For example:\n\n // Bad\n var foo = true;\n var bar = false;\n var a;\n var b;\n\n // Good\n var a, b,\n foo = true,\n bar = false;\n\n### Equality\n\nStrict equality checks `===` should be used in favor of `==`. The only exception is when checking for undefined and null by way of null.\n\n // Bad\n if(bar == \"can\"){ ... }\n\n // Good\n if(bar === \"can\"){ ... }\n\nIf the statement is a truthey or falsey, use implied operators. Falseys are when variables return `false`, `undefined`, `null`, or `0`. Trutheys are when variables return `true`, `1`, or anything defined.\n\nFor example:\n\n // Bad\n if(bar === false){ ... }\n\n // Good \n if(bar){ ... }\n\n // Good\n var foo = [];\n if(!foo.length){ ... }\n\n### Quotes\n\nUse double quotes.\n\n var double = \"I am wrapped in double quotes\";\n\nStrings that require inner quoting must use double outside and single inside.\n\n var html = \"
\";\n\n### Comments\n\nSingle line comments go OVER the line they refer to:\n\n // We need an explicit \"bar\", because later in the code foo is checked.\n var foo = \"bar\";\n\nFor long comments, use:\n \n /* myFn\n * Four score and seven—pause—minutes ago...\n */\n \n### Documentation\n\nThe documentation for the different modules should be clear and consistent. Explanations should be concise, and examples of code should be included where appropriate. In terms of format and style, here are a few suggestions to keep the documentation consistent within a module and across all parts of DoneJS:\n\n#### When referencing another part of DoneJS, make sure to link the first reference in a section.\n\nFor instance, when documenting `can.Component.scope`, the first reference to `can.Component`, `can.route`, or any other part of DoneJS should be enclosed in square brackets, so that links to those docs are generated. Linking each occurrence isn't necessary, but all the other references should at least be surrounded by \"grave accents\" or tickmarks.\n\n\tThis is an example of linking to [can.Component] from another page. If you reference\n\t`can.Component` later in this section, you don't have to link to it. All subsequent\n\treferences to `can.Component` have grave accents or tickmarks surrounding them.\n\t\n\t### New Section\n\t\n\tAnother section referencing [can.Component] starts this trend again...\n\n**Note**: The one exception to this is on the module page. When documenting `can.Component` itself, only use the tickmarks, as linking to `can.Component` would just link to the page you are currently modifying.\n\n#### Enclose string literals in tickmarks as they should appear in code\n\nIf the developer should type `\"@\"`, use the tickmarks to make this clear. This avoids the ambiguity of whether the apostrophes or quote marks are part of the text that should be typed. This also applies to any references to variable/key names (e.g., `scope` versus \"scope\" or **scope**).\n\n#### Include a clear description of your example code\n\nFor a developer that's new to DoneJS, the description of the example is likely more important than the example itself. Make sure there is a clear description of what the code should accomplish. This includes using all the techniques above. A good description should answer the question, \"could you explain what this example code is doing?\"\n\n", + "description": "\n", + "name": "contribute", + "title": "Contribue to DoneJS", "type": "page", "parent": "DoneJS", "hideSidebar": true, @@ -49,7 +49,7 @@ "comment": " " }, "community": { - "body": "
\n
\n
\n
\n \n
\n
\n

Help &
Learning Resources

\n
\n
\n

Upcoming
Events & Meetups

\n
\n
\n

Contribute to
DoneJS

\n
\n
\n
\n
\n\n
\n
\n \n \n

Help & Learning Resources

\n
\n
\n
\n

Gitter

\n

\n Get help and chat with our team in realtime! We love to answer questions and help out.\n

\n
\n
\n

Stack Overflow

\n

\n Search questions about DoneJS. We actively watch SO for questions to provide answers to the community.\n

\n
\n
\n
\n

Free Weekly Trainings

\n

\n Join us every Wednesday at Noon, CST for free DoneJS and JavaScript trainings lead by members of our team. We discuss different topics every week from the basics to advanced level techniques to help you step up your game. Also check out all of our past training sessions on youtube.\n

\n
\n
\n \n
\n
\n
\n
\n \n
\n
\n
\n
\n \n
\n
\n
\n \n\n
\n\n
\n \n \n
\n
\n

Upcoming Events

\n
\n
\n
\n
\n \n
\n \n \n
\n\n\n
\n
\n

DoneJS Meetups

\n
\n
\n
\n
\n
\n \n
\n
\n \n
\n
\n \n
\n
\n \n
\n
\n
\n
\n \n
\n\n
\n \n
\n\n
\n
\n
\n

Don’t See Your City? Start a Meetup Today!

\n

\n If you can gather 10 people in your nearest city, we’ll work with you to start a new meetup.\n

\n Get in Touch\n
\n
\n\n
\n
\n \n \n

Contribute to DoneJS

\n

\n Help contribute to the core DoneJS project. Create an issue,
resolve bugs or add new features. We want and need your help!\n

\n \n

\n (contribution guide coming soon)\n

\n
\n
\n
\n
\n", + "body": "
\n
\n
\n
\n \n
\n
\n

Help &
Learning Resources

\n
\n
\n

Upcoming
Events & Meetups

\n
\n
\n

Contribute to
DoneJS

\n
\n
\n
\n
\n\n
\n
\n \n

Help & Learning Resources

\n
\n
\n
\n

Gitter

\n

\n Get help and chat with our team in realtime! We love to answer questions and help out.\n

\n
\n
\n

Stack Overflow

\n

\n Search questions about DoneJS. We actively watch SO for questions to provide answers to the community.\n

\n
\n
\n
\n

Free Weekly Trainings

\n

\n Join us every Wednesday at Noon, CST for free DoneJS and JavaScript trainings lead by members of our team. We discuss different topics every week from the basics to advanced level techniques to help you step up your game. Also check out all of our past training sessions on youtube.\n

\n
\n
\n \n
\n
\n
\n
\n \n
\n
\n
\n
\n \n
\n
\n
\n \n\n
\n\n
\n \n
\n
\n

Upcoming Events

\n
\n
\n
\n
\n \n
\n \n \n
\n\n\n
\n
\n

DoneJS Meetups

\n
\n
\n
\n
\n
\n \n
\n
\n \n
\n
\n \n
\n
\n \n
\n
\n
\n
\n \n
\n\n
\n \n
\n\n
\n
\n
\n

Don’t See Your City? Start a Meetup Today!

\n

\n If you can gather 10 people in your nearest city, we’ll work with you to start a new meetup.\n

\n Get in Touch\n
\n
\n\n
\n
\n \n

Contribute to DoneJS

\n

\n Help contribute to the core DoneJS project. Create an issue,
resolve bugs or add new features. We want and need your help!\n

\n \n

\n (contribution guide coming soon)\n

\n
\n
\n
\n
\n", "type": "template", "name": "community" }, @@ -57,8 +57,8 @@ "src": { "path": "docs/features.md" }, - "body": "\n## Performance Features\n\nDoneJS is configured for maximum performance right out of the box.\n\n### Server-Side Rendered\n\nDoneJS applications are written as [Single Page Applications](http://en.wikipedia.org/wiki/Single-page_application),\nand are able to be rendered on the server by running the same code. This is known as [Isomorphic JavaScript](http://isomorphic.net/javascript), or [Universal JavaScript](https://medium.com/@mjackson/universal-javascript-4761051b7ae9).\n\nServer-side rendering (SSR) provides two large benefits over traditional single page apps: much better page load performance and SEO support.\n\nSSR apps return fully rendered HTML. Traditional single page apps return a page with a spinner. The benefit to your users is a noticeable difference in perceived page load performance:\n\n\"donejs-server-render-diagram.svg\"\n\nCompared to other server-side rendering systems, which require additional code and infrastructure to work correctly, DoneJS is uniquely designed to make turning on SSR quick and easy, and the server it runs is lightweight and fast.\n\n#### Page load performance\n\nServer-side rendered SPAs can load pre-rendered HTML immediately. They can also cache HTML and serve it from a CDN.\n\nTraditional SPAs must load the JS, execute, request data, and render before the user sees content.\n\n#### SEO\n\nSearch engines can't easily index SPAs. Server-side rendering fixes that problem entirely. Even if [Google can understand some JavaScript now](http://googlewebmastercentral.blogspot.ca/2014/05/understanding-web-pages-better.html), many other search engines cannot.\n\nSince search engines see the HTML that your server returns (if you want search engines to find your pages) you'll want Google and other search engines seeing fully rendered content, not the spinners that normally show after initial SPAs load.\n\n#### How it works\n\nDoneJS implements SSR with a single-context virtual DOM.\n\n**Single context** means every request to the server reuses the same context: including memory, modules, and even the same instance of the application.\n\n**Virtual DOM** means a virtual representation of the DOM: the fundamental browser APIs that manipulate the DOM, but stubbed out.\n\nWhen using DoneJS SSR, the same app that runs on the client is loaded in Node. When a request comes in:\n 1. The server handles the incoming request by reusing the application that is already running in memory. It doesn't reload the application (single context is optional, so reload is something you can opt into) which means the initial response is very fast.\n 1. The app renders content the same way it would in the browser, but with a mocked out virtual DOM, which is much faster than a real DOM.\n 1. The server waits for all your asynchronous data requests to finish before signaling that rendering is complete (more on how that works below).\n 1. When rendering is complete, the virtual DOM renders the string representation of the DOM, which is sent back to the client.\n\n\nSince SSR produces fully rendered HTML, it's possible to insert a caching layer, or use a service like Akamai, to serve most requests. Traditional SPAs don't have this option.\n\nRather than a virtual DOM, some other SSR systems use a headless browser on the server, like PhantomJS, which uses a real DOM. These systems are much slower and require much more intensive server resources.\n\nSome systems, even if they do use a virtual DOM, require a new browser instance entirely, or at the very least, reloading the application and its memory for each incoming request, which also is slower and more resource intensive than DoneJS SSR.\n\n##### Prepping your app for SSR\n\nAny app that is rendered on the server needs a way to notify the server that any pending asynchronous data requests are finished, and the app can be rendered.\n\nReact and other frameworks that support SSR don't provide much in the way of solving this problem. You're left to your own devices to check when all asychronous data requests are done, and delay rendering.\n\nDoneJS provides two easy mechanisms for notifying the server when data is finished loading.\n\nThe more common way is to make data requests in the template, which is possible via can-connect's [can-tag feature](http://connect.canjs.com/doc/can-connect%7Ccan%7Ctag.html). It calls a method internally that tells the server to wait for its promise to resolve. You just write your template, turn on SSR, and everything works seamlessly:\n\n```\n\n {{#each ./value}}\n
{{text}}
\n {{/each}}\n
\n```\n\nIf you're making data requests in JavaScript, just add one line to do this manually:\n\n```\nthis.attr( \"%root\" ).waitFor( promise );\n```\n\nThe server will wait for all promises registered via `waitFor` before it renders the page. In a full component that might look like this:\n\n```\ncan.Component.extend({\n tag: \"user-name\",\n template: can.stache( \"{{user.name}}\" ),\n viewModel: {\n init: function () {\n var promise = User.getOne( { id: this.attr( \"id\" ) } );\n this.attr( \"%root\" ).waitFor( promise );\n promise.then( ( user ) => { this.attr( \"user\", user ); } );\n }\n }\n});\n```\n\nView the Documentation\nView the Guide\n\n_Server-side rendering is a feature of [can-ssr](https://github.com/canjs/can-ssr)_\n\n### Progressive Loading\n\nWhen you first load a single page app, you're typically downloading all the JavaScript and CSS for every part of the application. These kilobytes of extra weight slow down page load performance, especially on mobile devices.\n\nDoneJS applications load only the JavaScript and CSS they need, when they need it, in highly optimized and cachable bundles. That means your application will load *fast*.\n\nThere is no configuration needed to enable this feature, and wiring up progressively loaded sections of your app is simple.\n\n#### How it works\n\n
\n\nOther build tools require you to manually configure bundles, which doesn't scale with large applications.\n\nIn a DoneJS application, you simply mark a section to be progressively loaded by wrapping it in your template with ``.\n\n```\n{{#eq page 'home'}}\n\n \n\n{{/eq}}\n{{#eq page 'chat'}}\n\n \n\n{{/eq}}\n```\n\nThen you run the build.\n\n```\ndonejs build\n```\n\nA build time algorithm analyzes the application's dependencies and groups them into bundles, optimizing for minimal download size.\n\nThat's it! No need for additional configuration in your JavaScript.\n\nView the Documentation\nView the Guide\n\n_Progressive Loading is a feature of [StealJS](http://stealjs.com/) with additional support via the [`` tag](http://canjs.com/docs/can%7Cview%7Cstache%7Csystem.import.html) of [CanJS](http://canjs.com/)_\n\n### Caching and Minimal Data Requests\n\nDoneJS improves performance by intelligently managing the data layer, taking advantage of various forms of caching and request reduction techniques.\n\nUndoubtedly, the slowest part of any web application is round trips to the server. Especially now that [more than 50% of web traffic comes from mobile devices](http://searchengineland.com/its-official-google-says-more-searches-now-on-mobile-than-on-desktop-220369), where connections are notoriously slow and unreliable, applications must be smart about reducing network requests.\n\nMaking matters worse, the concerns of maintainable architecture in single page applications are at odds with the concerns of minimizing network requests. This is because independent, isolated UI widgets, while easier to maintain, often make AJAX requests on page load. Without a layer that intelligently manages those requests, this architecture leads to too many AJAX requests before the user sees something useful.\n\nWith DoneJS, you don't have to choose between maintainability and performance.\n\nDoneJS uses the following strategies to improve perceived performance (reduce the amount of time before users see content rendered):\n\n - [Fall through caching](#section=section_CachingandMinimalDataRequests__Howitworks__Fallthroughcaching) - Cache data in localStorage. Automatically show cached data immediately, but look for updates on the server in the background and merge changes.\n - [Combining requests](#section=section_CachingandMinimalDataRequests__Howitworks__Combiningrequests) - Instead of making multiple, independent requests to the same API, combine them into a single request.\n - [Request caching](#section=section_CachingandMinimalDataRequests__Howitworks__Requestcaching) - Reduce the number and size of server requests by intelligently using cached datasets.\n - [Inline cache](#section=section_CachingandMinimalDataRequests__Howitworks__Inlinecache) - Use data embedded in the page response instead of making duplicate requests.\n\n#### How it works\n\n[can-connect](http://connect.canjs.com/) makes up part of the DoneJS model layer. Since all requests flow through this data layer, by making heavy use of set logic and localStorage caching, it's able to identify cache hits, even partial hits, and make the most minimal set of requests possible.\n\nIt acts as a central hub for data requests, making decisions about how to best serve each request, but abstracting this complexity away from the application code. This leaves the UI components themselves able to make requests independently, and with little thought to performance, without actually creating a poorly performing application.\n\n##### Fall through caching\n\nFall through caching serves cached data first, but still makes API requests to check for changes.\n\nThe major benefit of this technique is improved perceived performance. Users will see content faster. Most of the time, when there is a cache hit, that content will still be accurate, or at least mostly accurate.\n\nThis benefits two types of situations. First is page loads after the first page load (the first page load populates the cache). This scenario is less relevant when using server-side rendering. Second is long lived applications that make API requests after the page has loaded. These types of applications will enjoy improved performance.\n\nBy default, this is turned on, but can easily be deactivated for data that should not be cached.\n\nHere's how the caching logic works:\n\n1. When the application loads, it checks for available cache connections.\n1. When a request is made, it checks for a cache hit.\n1. If there is a hit, the request is completed immediately with the cached data.\n1. Regardless of a hit or miss, a request is made in the background to the actual API endpoint.\n1. When that response comes back, if there was a difference between the API response data and the cache hit data, the initial request promise's data is updated with the new data. Template data bindings will cause the UI to update automatically with these changes.\n1. Updated response data is automatically saved in the cache, to be used for future requests - whether that's in the current page session, or when the user comes back in the future.\n\n\n\n##### Combining requests\n\nCombining requests combines multiple incoming requests into one, if possible. This is done with the help of [set algebra](https://en.wikipedia.org/wiki/Algebra_of_sets).\n\nDoneJS collects requests that are made within a few milliseconds of each other, and if they are pointed at the same API, tries to combine them into a single superset request.\n\nFor example, the video below shows an application that shows two filtered lists of data on page load - a list of completed and incomplete todos. Both are subsets of a larger set of data - the entire list of todos.\n\nCombining these into a single request reduces the number of requests. This optimization is abstracted away from the application code that made the original request.\n\n\n\n##### Request caching\n\nRequest caching is a type of caching that is more aggressive than fallthrough caching. It is meant for data that doesn't change very often. Its advantage is it reduces both the number of requests that are made, and the size of those requests.\n\nThere are two differences between request and fallthrough caching:\n\n1. Cached data is not invalidated.\n\nOnce data is in the cache, no more requests to the API for that same set of data are made. You can write code that invalidates the cache at certain times, or after a new build is released.\n\n2. The smallest possible request is made, based on the contents of the cache, and merged into a complete result set.\n\nThe request logic is more aggressive in its attempts to find subsets of the data within the cache, and to only make an API request for the subset NOT found in the cache. In other words, partial cache hits are supported.\n\nThe video below shows two example scenarios. The first shows the cache containing a supserset of the request. The second shows the cache containing a subset of the request.\n\n\n\n\n##### Inline cache\n\nServer-side rendered single page apps (SPAs) have a problem with wasteful duplicate requests. These can cause the browser to slow down, waste bandwidth, and reduce perceived performance.\n\n1. When a page is rendered server-side, it makes data requests on the server to various APIs.\n1. After the page's rendered HTML loads in the client, the SPA is loaded in the client, so that subsequent requests are handled within the SPA.\n1. The SPA will want to re-request for the same data that was already requested on the server.\n\nDoneJS solves this problem with an inline cache - embedded inline JSON data sent back with the server rendered content, which is used to serve the initial SPA data requests.\n\nDoneJS uniquely makes populating and using the inline cache easy. `waitFor` is a method that:\n\n1. Tells the SSR server to wait for a promise to resolve before rendering.\n1. Collects data from each promise and uses it to populate the inline cache.\n\nFor example:\n\n```\ncan.Component.extend({\n tag: \"user-name\",\n template: can.stache( \"{{user.name}}\" ),\n viewModel: {\n init: function () {\n var promise = User.getOne( { id: this.attr( \"id\" ) } );\n this.attr( \"%root\" ).waitFor( promise );\n promise.then( ( user ) => { this.attr( \"user\", user ); } );\n }\n }\n});\n```\n\nThe model layer seamlesslly integrates the inline cache in client side requests, without any special configuration.\n\nWhile this flow would be possible in other SSR systems, it would require manually setting up all of these steps.\n\nThis video illustrates how it works.\n\n\n\n\n\n\nView the Documentation\nView the Guide\n\n_Caching and minimal data requests is a feature of [can-connect](https://github.com/canjs/can-connect)_\n\n### Minimal DOM Updates\n\nThe rise of templates, data binding, and MV* separation, while boosting maintainability, has come at the cost of performance. Many frameworks are not careful or smart with DOM updates, leading to performance problems as apps scale in complexity and data size.\n\nDoneJS' view engine touches the DOM more minimally and specifically than competitor frameworks, providing better performance in large apps and a \"closer to the metal\" feel.\n\nTake the TodoMVC application as an example. If you measure how long it takes DoneJS and React to render the same number of todos you'll see the performance advantage of minimal DOM updates. In fact we did just that and here's the result:\n\n\"Measuring\n_For a small set of todos the difference is negligible but as the number increases the gap widens to the point where React is 6 times slower than DoneJS when rendering 1000 todos._\n\nYou can run this test for yourself at JS Bin.\n\n#### How it works\n\nConsider the following template:\n\n```html\n{{#rows}}\n
{{name}}
\n{{/rows}}\n```\n\nAnd the following change to its data:\n\n```\nrows[0].attr('name', 'changed'); // change the first row's name\n```\n\nIn DoneJS, which uses the [can.stache](http://canjs.com/docs/can.stache.html) view engine, that would:\n\n 1. Trigger an event (because of the [can.Map](http://canjs.com/docs/can.Map.html) object observe API)\n 1. The event invokes a data binding event handler in the template layer\n 1. The handler immediately results in the following code being run:\n```\ntextNode.nodeValue = 'changed';\n```\n\nIn Backbone, you would need to manually re-render the template or roll your own rendering library.\n\nIn Angular, at the end of the current $digest cycle, that would result in an expensive comparison between the old rows array and the new one to see what properties have changed. After the changed property is discovered, the specific DOM node would be updated.\n\nIn React, that would result in the virtual DOM being re-rendered. A diff algorithm comparing the new and old virtual DOM would discover the changed node, and then the specific DOM node would be updated.\n\nOf these four approaches, DoneJS knows about the change the quickest, and updates the DOM the most minimally.\n\nTo see this in action run the test embedded below that shows how DoneJS, React and Angular compare when updating the DOM when a single property changes:\n\"Measuring\n\nYou can run this test yourself at JS Bin\n\nWith synchronously observable objects and data bindings that change mimimal pieces of the DOM, DoneJS aims to provide the best possible mix between powerful, yet performant, templates.\n\ncan.stache Documentation\ncan.Map Documentation\n\n_Minimal DOM updates is a feature of [CanJS](http://canjs.com/)_\n\n### Worker Thread Rendering\n\nWorker thread rendering increases the performance of your application. It essentially allows your application to run entirely within a Web Worker, freeing the main thread to only update the DOM.\n\nSince much of the work is offloaded from the main thread, applications will feel snappy, even while heavy computations are taking place.\n\n#### How it works\n\nTemplates first render in a lightweight Virtual DOM in a [Web Worker](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers). Changes are diffed and sent to the main thread to be applied to the real DOM. The main thread is only notified when there are changes to the DOM.\n\nThe most expensive part of a web application - DOM updates - are separated from application logic, which means your application can continue to run while DOM reflows occur.\n\nBy default, browsers use only a single thread of execution.\n\n\"A\n_With a single thread only one operation can occur at a time_\n\nThis means that performance problems in any area (expensive computations, DOM rendering, processing a large AJAX response, etc) can block the entire application, leaving the browser feeling \"frozen\".\n\nWith worker thread rendering, DOM updates and application logic are run in parallel threads.\n\n\"A\n_Using a worker thread application logic can still occur while the DOM is rendered. This could nearly double the number of operations per second._\n\nDue to this parallelization, performance problems that may have caused noticeable issues in a single thread will likely not cause any noticeable issues while running in separate threads.\n\nAdding worker thread rendering only requires changing one line. Change the main attribute of your page's script tag from:\n```\n\n```\nto\n```\n\n```\n\nAt this time, no other framework besides DoneJS, including Angular or React, supports worker thread rendering out of the box.\n\n
\n
You spend less time worrying about performance micro-optimizations,
\n \n \n
\n\n\nView the Documentation\n\n_Worker Thread Rendering is a feature of the [worker-render](https://github.com/canjs/worker-render) project._\n\n### Deploy to a CDN\n\nDoneJS makes it simple to deploy your static assets to a CDN (content delivery network).\n\nCDNs are distributed networks of servers that serve static assets (CSS, JS, and image files). You only push your files to one service, and the CDN takes care of pushing and updating your assets on different servers across the country and globe. As your app scales CDNs will keep up with the demand, and help support users regardless if they are in New York or Melbourne.\n\n\"User\n_Without a CDN, requests will take longer to fulfill if the user is located further away from your servers._\n
\n\n\n\"User\n_With a CDN, requests can be fulfilled much quicker. Users are served content from the servers located nearest to them._\n\n#### How it works\n\nIt's widely known that CDNs offer the best performance for static assets, but most apps don't use them, mainly because its annoying: annoying to automate, configure, and integrate with your build process.\n\nDoneJS comes with integrations with [S3](https://aws.amazon.com/s3/) and [Firebase](https://www.firebase.com) (popular CDN services) that make configuring and deploying to a CDN dirt simple.\n\n 1. You sign up for S3 or Firebase.\n 2. You paste a few lines of config into your `package.json` that point to the right CDN service.\n\n```\n\"donejs\": {\n \"deploy\": {\n \"root\": \"dist\",\n \"services\": {\n \"production\": {\n \"type\": \"firebase\",\n \"config\": {\n \"firebase\": \"place-my-order\",\n \"public\": \"./dist\",\n \"headers\": [{\n \"source\": \"/**\",\n \"headers\": [{\n \"key\": \"Access-Control-Allow-Origin\",\n \"value\": \"*\"\n }]\n }]\n }\n }\n }\n }\n}\n```\n 3. You paste a few more lines that tell your production server to serve static assets from the CDN.\n\n```\n{\n \"system\": {\n \"envs\": {\n \"production\": {\n \"baseURL\": \"https://place-my-order.firebaseapp.com/\"\n }\n },\n```\n 4. You run `donejs deploy`.\n\nThat's it. Now when you run your server in production mode, all static assets (CSS, JS, images, etc) are served from the CDN.\n\nEven better, you can set up [continuous deployment](./place-my-order.html#section=section_ContinuousDeployment), so that TravisCI or other tools will deploy your code, including pushing out your latest static files to the CDN, automatically.\n\nView the Documentation\nView the Guide\n\n_CDN deployment is a feature of the [donejs/deploy](https://github.com/donejs/deploy) project._\n\n## Usability features\n\nDoneJS is used to make beautiful, real-time user interfaces that can be exported to run on every platform.\n\n### iOS, Android, and Desktop Builds\n\nWrite your application once, then run it natively on every device and operating system. You can make iOS, Android, and desktop builds of your DoneJS application with no extra effort.\n\n\n_Our DoneJS Chat App running as a OS X desktop app and inside an iOS emulator._\n\n#### How it works\n\nFor iOS and Android builds, DoneJS integrates with [Apache Cordova](https://cordova.apache.org/) to generate a mobile app that is ready to be uploaded to Apple's App Store or Google Play.\n\nFor native desktop applications, DoneJS integrates with [NW.js](https://github.com/nwjs/nw.js) to create an native OSX, Windows, or Linux application.\n\nAdding this integration is as simple as running\n\n```\ndonejs add cordova\ndonejs add nw\ndonejs build\n```\n\nWith these simple integrations, you can expand your potential audience without having to build separate applications.\n\nView the Documentation\nView the Guide\n\n_Cordova and nw.js integration are features of the [steal-cordova](https://github.com/stealjs/steal-cordova) and [steal-nw](https://github.com/stealjs/steal-nw) projects._\n\n### Supports All Browsers, Even IE8\n\nDoneJS applications support Internet Explorer 8 minimal additional configuration. You can even write applications using [most ES6 features](http://babeljs.io/docs/advanced/caveats/) that run on IE8, using the built-in babel integration.\n\nMany people won't care about this because IE8 is on its way out, which is a very good thing!\n\nBut it's [not quite dead yet](https://youtu.be/grbSQ6O6kbs?t=61). For many mainstream websites, banks, and ecommerce applications, IE8 continues to hang around the browser stats.\n\nAnd while other frameworks like AngularJS and EmberJS don't support IE8, DoneJS makes it easy to write one app that runs everywhere.\n\nView the Guide\n\n### Real Time Connected\n\nDoneJS is designed to add real-time behavior to applications using any backend technology stack.\n\n[Socket.io](https://socket.io) provides the basics to add real-time capabilities to any JavaScript application, but the challenge of integrating real-time updates into your code remains.\n\nWhen new data arrives, how do you know what data structures to add it to? And where to re-render? Code must be written to send socket.io data across your application, but that code becomes aware of too much, and therefore is brittle and hard to maintain.\n\nDoneJS makes weaving Socket.io backends into your UI simple and automatic.\n\n#### How it works\n\n
\n\nDoneJS' model layer uses set logic to maintain lists of data represented by JSON properties, like a list of todos with `{'ownerId': 2}`. These lists are rendered to the UI via data bound templates.\n\nWhen server-side updates are sent to the client, items are automatically removed or added to any lists they belong to. They also automatically show up in the UI because of the data bindings.\n\nAll of this happens with about 4 lines of code.\n\n```\nconst socket = io('http://chat.donejs.com');\nsocket.on('messages created',\n order => messageConnection.createInstance(order));\nsocket.on('messages updated',\n order => messageConnection.updateInstance(order));\nsocket.on('messages removed',\n order => messageConnection.destroyInstance(order));\n```\n\n[Follow the guide](./Guide.html#section=section_Enableareal_timeconnection) to see an example in action. View the can-connect real-time documentation [here](http://connect.canjs.com/doc/can-connect%7Creal-time.html).\n\nView the Documentation\nView the Guide\n\n_Real time connections is a feature of the [can-connect](http://connect.canjs.com) project._\n\n### Pretty URLs with Pushstate\n\nDoneJS applications use [pushstate](https://developer.mozilla.org/en-US/docs/Web/API/History_API#The_pushState()_method) to provide navigable, bookmarkable pages that support the back and refresh buttons, while still keeping the user in a single page.\n\nThe use of pushstate allows your apps to have \"Pretty URLs\" like `myapp.com/user/1234` instead of uglier hash based URLs like `myapp.com#page=user&userId=1234` or `myapp.com/#!user/1234`.\n\nWiring up these pretty URLs in your code is simple and intuitive.\n\n#### How it works\n\n
\n\nRouting works a bit differently than other libraries. In other libraries, you might declare routes and map those to controller-like actions.\n\nDoneJS application [routes](http://canjs.com/docs/can.route.html) map URL patterns, like `/user/1`, to properties in our application state, like `{'userId': 1}`. In other words, our routes will just be a representation of the application state.\n\nThis architecture simplifies routes so that they can be managed entirely in simple data bound templates, like the following example:\n\n```\n{{#switch page}}\n {{#case \"home\"}}\n \n {{/case}}\n {{#case \"users\"}}\n {{#if slug}}\n \n {{else}}\n \n {{/if}}\n {{/case}}\n{{/switch}}\n```\n\nView the Documentation\nView the Guide\n\n_Pretty URLs and routing are features of the [CanJS](http://canjs.com/) project._\n\n## Maintainability features\n\nDoneJS helps developers get things done quickly with an eye toward maintenance.\n\n### Comprehensive Testing\n\nNothing increases the maintainability of an application more than good automated testing. DoneJS includes a comprehensive test layer that makes writing, running, and maintaining tests intuitive and easy.\n\nDoneJS provides tools for the entire testing lifecycle:\n\n* [Generators](#section=section_ComprehensiveTesting__Howitworks__Generators) - create boilerplate tests to get started quickly\n* [Unit testing](#section=section_ComprehensiveTesting__Howitworks__Unittests) - assertion libraries to test your module interfaces\n* [Functional testing](#section=section_ComprehensiveTesting__Howitworks__Functionaltests) - scripting the browser, simulating user actions, and testing your UI modules\n* [User action event simulation](#section=section_ComprehensiveTesting__Howitworks__Eventsimulationaccuracy) - accurate event simulation for clicks, types, drags, and other user actions\n* [A command line test runner](#section=section_ComprehensiveTesting__Howitworks__Runningtestsfromthecommandline) - invoke the same tests from the CLI\n* [A browser launcher](#section=section_ComprehensiveTesting__Howitworks__Runningtestsfromthecommandline) - launch several browsers and target your tests against them\n* [A reporting tool](#section=section_ComprehensiveTesting__Howitworks__Runningtestsfromthecommandline) - report results, including code coverage, to the CLI, in various formats\n* [Simple integration with continuous integration tools](#section=section_ContinuousIntegration_Deployment) - one step to hook into TravisCI or other CI systems\n* [A mock layer](#section=section_ComprehensiveTesting__Howitworks__MockingserverAPIs) - mock out your server APIs so you can test your app in isolation from a server\n\n
\n
\n \n
\n
\n\n#### How it works\n\nTesting JavaScript apps is complex unto itself. To do it right, you need many tools that have to work together seamlessly. DoneJS provides everything you need - the whole stack.\n\n##### Generators\n\nThe DoneJS app generator command `donejs add app` creates a working project-level test HTML and JS file. Component generators via `donejs add component cart` create a test script and individual test page for each test.\n\n##### Unit tests\n\nUnit tests are used to test the interface for modules like models and view models. You can choose between BDD style unit tests with Jasmine or Mocha, or a more traditional TDD assertion style with QUnit.\n\n##### Functional tests\n\nFunctional tests are used to test UI components by simulating user behavior. The syntax for writing functional tests is jQuery-like, chainable, and asynchronous, simulating user actions and waiting for page elements to change asynchronously.\n\n```js\ntest('destroying todos', function() {\n F('#new-todo').type('Sweet. [enter]');\n\n F('.todo label:contains(\"Sweet.\")').visible('basic assert');\n F('.destroy').click();\n\n F('.todo label:contains(\"Sweet.\")').missing('destroyed todo');\n});\n```\n\n##### Event simulation accuracy\n\nUser action methods, like click, type, and drag, simulate exactly the sequence of events generated by a browser when a user performs that action. For example this:\n```\nF( \".menu\" ).click();\n```\n\nis not just a click event. It triggers a mousedown, then blur, then focus, then mouseup, then click. The result is more accurate tests that catch bugs early.\n\nEven further, there are differences between how IE and Safari handle a click. DoneJS tests take browser differences into account when running functional tests.\n\n##### Running tests from the command line\n\nDoneJS comes with a command line test runner, browser launcher, and reporting tool that integrates with any [continuous integration](#section=section_ContinuousIntegration_Deployment) environment.\n\nNo setup required, running a DoneJS project's test is as simple as running:\n\n```\ndonejs test\n```\n\nYou can run launch your unit and functional tests from the cli, either in headless browser mode, or via multiple real browsers. You can even launch browserstack virtual machines to test against any version of Android, Windows, etc.\n\nThe reporting tool gives detailed information about coverage statistics, and lets you choose from many different output formats, including XML or JSON files.\n\n##### Mocking server APIs\n\nAutomated frontend testing is most useful when it has no external dependencies on API servers or specific sets of data. Thus a good mock layer is critical to write resilient tests.\n\nDoneJS apps use fixtures to emulate REST APIs. A default set of fixtures are created by generators when a new model is created. Fixtures are very flexible, and can be used to simulate error states and slow performing APIs.\n\n```js\nimport fixture from 'can-fixture';\n\nconst store = fixture.store([\n { name: 'Calisota', short: 'CA' },\n { name: 'New Troy', short: 'NT'}\n],{});\n\nfixture({\n 'GET /api/states': store.findAll,\n 'GET /api/states/{short}': store.findOne,\n 'POST /api/states': store.create,\n 'PUT /api/states/{short}': store.update,\n 'DELETE /api/states/{short}': store.destroy\n});\n\nexport default store;\n```\n\n##### Simple authoring\n\nSeveral DoneJS features converge to make authoring tests extremely simple.\n\nBecause of [ES6 Module](#section=section_ES6Modules) support, everything in a DoneJS app is a module, so a test can simply import the modules it needs - such as fixtues and module under test:\n\n```\nimport restaurantStore from 'place-my-order/models/fixtures/restaurant';\nimport { ViewModel } from './list';\n```\n\nThis means the test is small, isolated, and simple. Tests themselves are modules too, so they can be collected easily into sets of tests.\n\nBecause of the [modlet](#section=section_Modlets) pattern, each component contains its own working test script and test file, which can be worked on in isolation.\n\nBecause of [hot module swapping](#section=section_HotModuleSwapping), you can write, debug, and run tests without constantly reloading your page.\n\nOther frameworks require a build step before tests can be run. These builds concatenate dependencies and depend on specific order of tests running, which is a brittle and inefficient workflow.\n\nBecause DoneJS uses a client side loader that makes it simple to start a new page that loads its own dependencies, there is no build script needed to compile and run tests.\n\nYou just run the generator, load your modules, write your test, and run it - from the browser or CLI.\n\n
\n
You spend less time messing with test infrastructure,
\n
...and more time mud ridin'.
\n \n
\n\n##### More information\n\nThe DoneJS testing layer involves many pieces, so if you want to learn more:\n\n * follow along in the [Unit testing view model and fixtures](./place-my-order.html#section=section_Creatingaunit_testedviewmodel) section of the guide\n * see how to run tests and set up CI automation in the [CI section](./place-my-order.html#section=section_Automatedtestsandcontinuousintegration) of the guide\n * read about [FuncUnit](http://funcunit.com/), the functional testing and asynchronous user action simulating library\n * read about [syn](https://github.com/bitovi/syn) - the synthetic event library\n * read about the [Testee.js](https://github.com/bitovi/testee) browser launcher, test runner, and reporting tool\n * read the [can.fixture](http://canjs.com/docs/can.fixture.html) docs\n\n### Documentation\n\nDocumentation is critical for maintainability of any complex application. When your team adds developers, docs ensure minimal ramp up time and knowledge transfer.\n\nYet most teams either don't write docs, or they'll do it \"later\" - a utoptian future period that is always just out of reach. Why? Because it's extra work to set up a tool, configure it, create and maintain separate documentation files.\n\nDoneJS comes with a documentation tool built in, and it generates multi-versioned documentation from inline code comments. It eliminates the barrier to producing docs, since all you have to do is comment your code (which most people already do) and run `donejs document`.\n\n
\n
\n \n
\n
\n\n#### How it works\n\nYou write comments above the module, method, or object that you want to document:\n\n```js\n/**\n * @module {function} utils/add\n * @parent utils\n *\n * The module's description is the first paragraph.\n *\n * The body of the module's documentation.\n *\n * @param {Number} first This param's description.\n * @param {Number} second This param's description.\n * @return {Number} This return value's description.\n */\nexport default function(){ ... };\n```\n\nThen run `donejs document`. A browsable documentation website will be generated.\n\n\"A\n\nDoneJS applications use [DocumentJS](http://documentjs.com) to produce multi-versioned documentation. It lets you:\n\n- Write docs inline or in markdown files.\n- Specify your code's behavior precisely with JSDoc and [Google Closure Compiler annotations](https://developers.google.com/closure/compiler/docs/js-for-compiler?hl=en) - a well known documentation syntax.\n- Customize your site's theme and layout.\n- Generate multi-versioned documentation.\n- Document CSS alongside JavaScript. You can even make a [live style guide](http://documentjs.com/examples/styles/index.html).\n\nYou can keep it simple like the example above, or you can customize your docs with many powerful features. In fact, this entire site and the [CanJS](http://canjs.com/docs/index.html) site are generated using DocumentJS.\n\n
\n
You spend less time messing with Documentation generators,
\n
...and more time perfecting your moonwalk.
\n \n
\n\nView the Documentation\nView the Guide\n\n_DoneJS Documentation is a feature of [DocumentJS](http://documentjs.com/)_\n\n### Continuous Integration & Deployment\n\nContinuous Integration (CI) and Continuous Deployment (CD) are must have tools for any modern development team.\n\nCI is a practice whereby all active development (i.e. a pull request) is checked against automated tests and builds, allowing problems to be detected early (before merging the code into the release branch).\n\n\"A\n_Example of a GitHub pull request with Travis CI integrated. Warns users in advance of merges if their changes will break builds or fail tests._\n\nCD means that any release or merges to your release branch will trigger tests, builds and deployment.\n\nPaired together, CI and CD enable automatic, frequent releases. CD isn't possible without CI. Good automated testing is a must to provide the confidence to release without introducing bugs.\n\nDoneJS provides support for simple integration into popular CI and CD tools, like TravisCI and Jenkins.\n\n
\n
\n \n
\n
\n\n#### How it works\n\nSetting up continuous integration and deployment involves several steps:\n 1. Writing tests\n 1. Setting up a test harness that runs tests from the command line\n 1. Creating simple scripts for running a build, test, and deploy\n 1. Integrating with a service that runs the scripts at the proper times\n\nSteps 1, 2, and 3 are the hard parts. Step 4 is simple. DoneJS supports in two main ways: proper test support and simple CLI commands.\n\n##### Proper test support\n\nDoneJS comes with comprehensive support for testing. The [Testing](#section=section_ComprehensiveTesting) section contains much more detail about testing support.\n\n[Generators](#section=section_Generators) create working test scripts right off the bat, and the plumbing for test automation is built into each project. Each [modlet](#section=section_Modlets) contains a skeleton for unit tests. All that is left for the developer to do is write tests.\n\n##### Simple CLI commands\n\nAnother hurdle is creating automated build, test, and deployment scripts. Every DoneJS app comes with a build, test, and deployment one-liner: `donejs build`, `donejs test`, and `donejs deploy`.\n\n##### Tool integration\n\nOnce the tests are written and the scripts are automated, integrating with the tools that automatically runs these scripts is quite simple. For instance, setting up Travis CI involves signing up and adding a `.travis.yml` file to the project:\n\n```\nlanguage: node_js\nnode_js: node\nscript: npm start & npm test\nbefore_install:\n - \"export DISPLAY=:99.0\"\n - \"sh -e /etc/init.d/xvfb start\"\n```\n\nView the CI Guide\nView the CD Guide\n\n### Modlets\n\nThe secret to building large apps is to never build large apps. Break up your application into small pieces. Then, assemble.\n\nDoneJS encourages use of the modlet file organization pattern. Modlets are small, decoupled, reusable, testable mini applications.\n\n#### How it works\n\nLarge apps have a lot of files. There are two ways to organize them: by type or by module.\n\n\"DoneJS\n\nOrganization by module - or modlets - make large applications easier to maintain by encouraging good architecture patterns. The benefits include:\n\n * Each modlet contains its own demo page and its own test page. Getting a demo page running forces separation of concerns and isolated modules - hallmarks of good design. A standalone demo and test page makes it easy to work on pieces of your application in isolation.\n * Developers are more likely to update tests and documentation if they are sitting right next to the module they are editing. The test is not hidden in a `tests` folder that is more easily ignored.\n * You can develop the application without having to load the entire application and all of its tests on every change.\n\nAn example modlet from the [in depth guide](/place-my-order.html) is the [order/new](https://github.com/donejs/place-my-order/tree/master/src/restaurant/list) component. It has its own [demo page](http://www.place-my-order.com/src/order/new/demo.html) and [test page](http://www.place-my-order.com/src/order/new/test.html).\n\nDoneJS generators create modlets to get you started quickly. To learn more about the modlet pattern, read this [blog post](http://blog.bitovi.com/modlet-workflows/).\n\nView the Video\nView the Guide\n\n_Modlets are a feature of DoneJS [generators](#section=section_Generators)._\n\n### NPM Packages\n\nDoneJS makes it easy to share and consume modules via package managers like NPM and Bower.\n\nYou can import modules from any package manager in any format - CommonJS, AMD, or ES6 - without any configuration. And you can convert modules to any other format.\n\nThe goal of these features is to transform project workflows, making it easier to share and reuse ideas and modules of functionality across applications, with less hassle.\n\n\n
\n
\n \n
\n
\n\n#### How it works\n\nDoneJS apps use [StealJS](http://stealjs.com/) to load modules and install packages. This video introduces NPM import and export in StealJS:\n\n
\n\n##### Zero config package installation\n\nUnlike Browserify or Webpack, StealJS is a client side loader, so you don't have to run a build to load pages.\n\nInstalling a package in a DoneJS app via npm or bower involves no configuration. Install your package from the command line:\n\n```\nnpm install jquery --save\n```\n\nThen immediately consume that package (and its dependencies) in your app:\n\n```\nimport $ from \"jquery\";\n```\n\nUsing require.js or other client side loaders, you'd have to add pathing and other information to your configuration file before being able to use your package. In DoneJS, this step is bypassed because of scripts that add config to your package.json file as the package is installed.\n\nYou can import that package in any format: CommonJS, AMD, or ES6 module format.\n\n##### Convert to any format\n\nDoneJS supports converting a module to any other format: CommonJS, AMD, or ES6 module format, or script and link tags.\n\nThe advantage is that you can publish your module to a wider audience of users. Anyone writing JavaScript can use your module, regardless of which script loader they are using (or if they aren't using a script loader).\n\nJust create an [export script](http://stealjs.com/docs/steal-tools.export.html) that points to the output formats you want, along with some options:\n```js\nvar stealTools = require(\"steal-tools\");\nstealTools.export({\n system: {\n config: __dirname+\"/package.json!npm\"\n },\n outputs: {\n amd: {\n format: \"amd\",\n graphs: true,\n dest: __dirname+\"/dist/amd\"\n }\n});\n```\n\nand run it from your command line:\n```\nnode myexport.js\n```\n\n##### Modular workflow\n\nIn combination with other DoneJS features, NPM module import and export make it possible for teams to design and share components easily.\n\n[Generators](#section=section_Generators) make it easy to bootstrap new modules of functionality quickly, and the [modlet pattern](#section_Modlets) makes it easy to organize small, self-contained modules. Its even easy to create tests and documentation for each module.\n\nDoneJS enables a modular workflow, where pieces of small, reusable functionality can be easily created, shared, and consumed.\n\n 1. Use generators to create a modlet\n 1. Develop rich functionality\n 1. Write tests and docs\n 1. Export and publish it - internally or externally\n 1. Consume it across applications\n\nSimilar to the way that the [microservices](http://microservices.io/patterns/microservices.html) architecture encourages reuse of APIs across applications, the modular workflow encourages reuse of self-contained modules of JavaScript across applications.\n\nImagine an organization where every app is broken into many reusable pieces, each of which are independently tested, developed, and shared. Over time, developers would be able to quickly spin up new applications, reusing previous functionality. DoneJS makes this a real possibility.\n\nView the Documentation\nView the Guide\n\n_NPM package support is a feature of [StealJS](http://stealjs.com/)_\n\n### ES6 Modules\n\nDoneJS supports the compact and powerful [ES6 module](http://www.2ality.com/2014/09/es6-modules-final.html) syntax, even for browsers that don't support it yet. Besides future proofing your application, writing ES6 modules makes it easier to write modular, maintainable code.\n\n````\nimport { add, subtract } from \"math\";\n\nexport function subtract(a, b) {\n return a - b;\n}\n````\n\n#### How it works\n\nDoneJS applications are actually able to import or export any module type: ES6, AMD and CommonJS. This means you can slowly phase in ES6, while still using your old code. You can also use any of the many exciting [ES6 language features](https://github.com/lukehoban/es6features).\n\nA compiler is used to convert ES6 syntax to ES5 in browsers that don't yet support ES6. During development, the compiler runs in the browser, so changes are happening live without a build step. During the build, your code is compiled to ES5, so your production code will run native in every browser. You can even run your [ES6 application in IE8](#section=section_SupportsAllBrowsers_EvenIE8)!\n\nView the Documentation\nView the Guide\n\n_Pretty URLs and routing are features of the [stealjs/transpile](https://github.com/stealjs/transpile) project._\n\n### Custom HTML Elements\n\nOne of the most important concepts in DoneJS is splitting up your application functionality into independent, isolated, reusable custom HTML elements.\n\nThe major advantages of building applications based on custom HTML elements are:\n\n 1. **Ease of page composition** - Designers can do it! Non-developers can express complex behavior with little to no JavaScript required. All you need to build a new page or feature is HTML.\n 1. **Forced modularity** - Because the nature of HTML elements are isolated modules, custom HTML elements must be designed as small, isolated components. This makes them easier to test, debug, and understand.\n 1. **Reuse** - Custom elements are designed to be reusable across pages and applications.\n\nConsider the following example:\n\n```html\n\n\n\n\n \n \n \n \n\n```\nThis code demonstrates:\n\n 1. An element that can load data\n 1. Composable widget elements (a graph with a line-series)\n\nIf our designer wanted to add another period, all they would need to do is add another `` and `` element.\n\nHere’s a working version of the same example in a JSBin.\n\nCustom HTML Elements on jsbin.com\n\nJust like HTML’s natural advantages, composing entire applications from HTML building blocks allows for powerful and easy expression of dynamic behavior.\n\n#### How it works\n\nFirst, it's important to understand the background of custom elements and their advantages. Then, we'll discuss the details of creating powerful custom elements in specifically DoneJS, and why they're special.\n\n##### Benefits of custom elements\n\nBefore custom HTML elements existed, to add a datepicker to your page, you would:\n\n 1. Load a datepicker script\n 1. Add a placeholder HTML element\n\n```\n
\n```\n 3. Add JavaScript code to instantiate your datepicker\n\n```\n$('.datepicker').datepicker()\n```\n 4. Gather your stone tipped spears and forage for small animals to feed your family for the night.\n\nWith custom HTML elements, to add the same datepicker, you would:\n\n 1. Load a datepicker script\n 1. Add the datepicker to your HTML or template:\n\n```\n\n```\n\nThat might seem like a subtle difference, but it is actually a major step forward. The custom HTML element syntax allows for instantiation, configuration, and location, all happening at the same time.\n\nCustom HTML elements are another name for [Web Components](http://webcomponents.org/), a browser spec that has [yet to be implemented](http://caniuse.com/#search=components) across browsers.\n\n##### Benefits of DoneJS custom elements\n\nDoneJS uses CanJS' [can.Component](http://canjs.com/docs/can.Component.html) to provide a modern take on web components.\n\nComponents in DoneJS have three basic building blocks:\n\n * a template\n * a viewModel object\n * event handlers\n\nThere are several unique benefits to DoneJS custom elements:\n\n * [Easily construct custom elements](#section=section_CustomHTMLElements__Howitworks__Definingacustomelement) - you can define them within a single `.component` file, or a modlet\n * [Load data from custom elements](#section=section_CustomHTMLElements__Howitworks__Dataelementsvisualelementsexpressivetemplates)\n * [Simple progressive loading with can-import](#section=section_CustomHTMLElements__Howitworks__Intemplatedependencydeclarations)\n\n##### Defining a custom element\n\nOne way to define a component is with a [web component](https://github.com/donejs/done-component) style declaration, using a single file with a `.component` extension:\n\n```html\n\n \n \n \n \n\n```\n\nThis simple form of custom elements is great for quick, small widgets, since everything is contained in one place.\n\nAnother way to organize a custom element is a [modlet](#section_Modlets) style file structure: a folder with the element broken into several independent pieces. In this pattern, the custom element's ViewModel, styles, template, event handlers, demo page, tests, and test page are all located in separate files. This type of custom element is well suited for [export and reuse](#section=section_NPMPackages__Howitworks__Modularworkflow).\n\nDoneJS [Generators](#section_Generators) will create both of these types of custom elements so you can get started quickly.\n\n##### Data elements + visual elements = expressive templates\n\nThe beauty and power of custom HTML elements is most apparent when visual widgets (like graphing) is combined with elements that express data.\n\nBack to our original example:\n\n```html\n\n\n\n\n \n \n\n```\n\nThis template combines a request for data with an element that expresses it. It's immediately obvious how you would add or remove features from this, allowing for quick changes and easy prototyping. Without custom elements, the same changes would require more difficult code changes and wiring those changes up with widget elements that display the data.\n\nData custom elements are part of DoneJS via can-connect's [can-tag feature](http://connect.canjs.com/doc/can-connect%7Ccan%7Ctag.html).\n\n##### Custom element libraries\n\nCustom elements are designed to be easily shareable across your organization. DoneJS provides support for simple [NPM import and export](#section_NPMPackages) and creating [documentation](#section=section_Documentation) for elements. Together with custom element support, these features make it easier than ever to create reusable bits of functionality and share them.\n\nSome open source examples of DoneJS custom elements:\n\nbit-c3\nbit-tabs\nbit-autocomplete\n\nCheck out [their source](https://github.com/bitovi-components/bit-tabs) for good examples of shareable, documented, and tested custom elements.\n\n##### In-template dependency declarations\n\n[can-import](http://canjs.com/docs/can%7Cview%7Cstache%7Csystem.import.html) is a powerful feature that allows templates to be entirely self-sufficient. You can load custom elements, helpers, and other modules straight from a template file like:\n\n```\n\n\n\n ...\n ...\n\n```\n\nThe `` element also plays a key role in [Progressive Loading](#section=section_ProgressiveLoading). Simply by wrapping a section in a closed can-import, it signals to the build that the enclosed section's dependencies should be progressively loaded.\n\n```\n{{#eq location 'home'}}\n\n \n\n{{/eq}}\n{{#eq location 'away'}}\n\n \n\n{{/eq}}\n```\n\nView the Documentation\nView the Guide\n\n_Custom HTML elements are a feature of [CanJS](http://canjs.com/)_\n\n### MVVM Architecture\n\nDoneJS applications employ a [Model-View-ViewModel](https://en.wikipedia.org/wiki/Model_View_ViewModel) architecture pattern, provided by [CanJS](http://canjs.com/).\n\n\"MVVM\n\nThe introduction of a strong ViewModel has some key advantages for maintaining large applications:\n\n * **Decouples the presentation from its business logic** - A ViewModel is essentially an object and methods representing the state of a View. This separation of concerns enables simple, dumb HTML-based Views containing minimal logic, while the ViewModel manages the complexities of application logic.\n * **Enables designer/developer cooperation** - Because the view is stripped of code and application logic, designers can safely and comfortably change the View without fear of breaking things.\n * **Enables easier [testing](#section=section_ComprehensiveTesting)** - ViewModels can be unit tested easily. Because they represent the view's state without any knowledge of the DOM, they provide a simple interface for testing.\n\n#### How it works\n\nThe following video introduces MVVM in DoneJS, focusing on the strength of the ViewModel with an example.\n\n
\n\nDoneJS has a uniquely strong ViewModel layer compared to other frameworks. We'll discuss how it works and compare it to other frameworks.\n\n\n##### MVVM overview\n\n**Models** in DoneJS are responsible for loading data from the server. They can be reused across ViewModels. They often perform data validation and sanitization logic. Their main function is to represent data sent back from a server. Models use intelligent set logic that enables [real time](#section=section_RealTimeConnected) integration and [caching](#section=section_CachingandMinimalDataRequests) techniques.\n\n**Views** in DoneJS are templates. Specifically, templates that use handlebars syntax, but with data bindings and rewritten for better performance. Handlebars templates are designed to be logic-less.\n\n**ViewModels** will be covered in detail below.\n\n##### Independent ViewModels\n\nThe first reason DoneJS ViewModels are unique is their independence. ViewModels and Views are completely decoupled, and can be developed completely isolated from a template.\n\nFor example, here's a typical ViewModel, which is often defined in its own separate file like `viewmodel.js` and exported as its own module:\n\n```\nexport const ViewModel = Map.extend({\n define: {\n fullName: {\n get () {\n return this.attr(\"first\") + \" \" + this.attr(\"last\");\n }\n }\n }\n})\n```\n\nThe template (view) lives in its own file, so a designer could easily modify it without touching any JavaScript. This template renders the ViewModel property from above:\n\n```\n
{{fullName}}
\n```\n\nA [custom HTML element](#section=section_CustomHTMLElements), also known as a component, would be used to tie these layers together:\n\n```\nimport Component from 'can/component/';\nimport ViewModel from \"./viewmodel\";\nimport template from './template.stache!';\n\nComponent.extend({\n tag: 'my-component',\n viewModel: ViewModel,\n template\n});\n```\n\nThe ViewModel is defined as its own module and exported as an ES6 module, so it can be imported into a unit test, instantiated, and tested in isolation from the DOM:\n\n```\nimport ViewModel from \"./viewmodel\";\n\nQUnit.test('fullName works', function() {\n var vm = new ViewModel();\n vm.attr('first', 'John');\n vm.attr('last', 'Doe');\n QUnit.equal(vm.attr('fullName'), 'John Doe');\n});\n```\n\nIn other frameworks, ViewModels don't enjoy this level of independence. Every React class has a render function, which is essentially a template, so the View, ViewModel, and component definition are typically part of the same module. Every Angular directive is a ViewModel. In DoneJS, separating the ViewModel, template, and custom element is encouraged, making each module more decoupled and easier to unit test.\n\n##### Powerful observable data layer\n\nA powerful observable data layer binds the layers together with very minimal code.\n\nDoneJS supports the following features:\n\n1. **Direct observable objects** - changes to a property in an object or array immediately and synchronously notify any event listeners.\n\n1. **Computed properties** - ViewModels can define properties that depend on other properties, and they'll automatically recompute only when their dependent properties change.\n\n1. **Data bound templates** - templates bind to property changes and update the DOM as needed.\n\nIn the simple ViewModel example above, `fullName`'s value depends on `first` and `last`. If something in the application changes `first`, `fullName` will recompute.\n\n```\nexport const ViewModel = Map.extend({\n define: {\n fullName: {\n get () {\n return this.attr(\"first\") + \" \" + this.attr(\"last\");\n }\n }\n }\n})\n```\n\n`fullName` is data bound to the view that renders it:\n\n```\n
{{fullName}}
\n```\n\nIf `first` is changed:\n\n```\nviewModel.attr('first', 'Jane');\n```\n\n`fullName` recomputes, then the DOM automatically changes to reflect the new value.\n\nThe interplay of these layers provides amazing power to developers. ViewModels express complex relationships between data, without regard to its display. Views express properties from the ViewModel, without regard to how the properties are computed. The app then comes alive with rich functionality.\n\nWithout automatic ties connecting these layers, achieving the same `fullName` functionality would require more code explicitly performing these steps. There would need to be communication between layers, removing the isolation achieved above. Any change to `first` would need to notify ViewModel's `fullName` of a change. Any change to `fullName` would need to tell the view to re-render itself. These dependencies grow and quickly lead to unmaintainable code.\n\nIn Angular, there are no direct observables. It uses dirty checking with regular JavaScript objects, which means at the end of the current $digest cycle, it will run an algorithm that determines what data has changed. This has performance drawbacks, as well as making it harder to write simple unit tests.\n\nIn React, there is no observable data layer. You could define a `fullName` like we showed above, but it would be recomputed every time `render` is called, whether or not it has changed. Though it's possible to isolate and unit test its ViewModel, its not quite set up to make this easy.\n\n##### More information\n\nTo learn more:\n\n * Models - read about [can.connect](http://connect.canjs.com/) and [can.Map](http://canjs.com/docs/can.Map.html)\n * Computed properties - read about [can.compute](http://canjs.com/docs/can.compute.html)\n * Observable data layer - read about [can.Map](http://canjs.com/docs/can.Map.html) and [can.List](http://canjs.com/docs/can.List.html)\n * ViewModels - read about [can.component](http://canjs.com/docs/can.Component.html), [can.Component.viewModel](http://canjs.com/docs/can.Component.prototype.viewModel.html), and [can.Map.define](http://canjs.com/docs/can.Map.prototype.define.html)\n * Views - read about [can.stache](http://canjs.com/docs/can.stache.html)\n * [Create a unit tested ViewModel](./place-my-order.html#section=section_Creatingaunit_testedviewmodel) in the in depth guide\n\n_The MVVM architecture in DoneJS is provided by [CanJS](http://canjs.com/)._\n\n### Hot Module Swapping\n\nGetting and staying in [flow](https://en.wikipedia.org/wiki/Flow_(psychology)) is critical while writing complex apps. In DoneJS, whenever you change JavaScript, CSS, or a template file, the change is automatically reflected in your browser, without a browser refresh.\n\n
\n
\n \n
\n
\n\n#### How it works\n\nLive reload servers generally watch for file changes and force your browser window to refresh. DoneJS doesn’t refresh the page, it re-imports modules that are marked as dirty, in real-time.\n\nThe correct terminology is actually [hot swapping](https://en.wikipedia.org/wiki/Hot_swapping), not live reload. Regardless of what it's called, the result is a blazing fast development experience.\n\nThere is no configuration needed to enable this feature. Just start the dev server and begin:\n\n```\ndonejs develop\n```\n\n
\n
You spend less time waiting for refreshes and builds,
\n \n \n
\n\nView the Documentation\n\n_Live reload is a feature of [StealJS](http://stealjs.com/)._\n\n\n### Generators\n\nDoneJS generators help you kickstart new projects and components. They'll save you time, eliminating boilerplate by scaffolding a working project, component, or module.\n\nGenerator templates set up many of the best practices and features discussed in the rest of this page, without you even realizing it.\n\n#### How it works\n\nThe DoneJS generator uses Yeoman to bootstrap your application, component, or model.\n\nThere are four generators by default (and you can easily create your own).\n\n##### Project generator\n\nFrom the command line, run:\n\n```\ndonejs add app\n```\n\nYou'll be prompted for a project name, source folder, and other setup information. DoneJS' project dependencies will be installed, like StealJS and CanJS. In the folder that was created, you'll see:\n\n```\n├── .yo-rc.json\n├── build.js\n├── development.html\n├── documentjs.json\n├── package.json\n├── production.html\n├── readme.md\n├── src/\n| ├── app.js\n| ├── index.stache\n| ├── models/\n| | ├── fixtures\n| | | ├── fixtures.js\n| | ├── test.js\n| ├── styles.less\n| ├── test.html\n| ├── test/\n| | ├── test.js\n| | ├── functional.js\n├── node_modules/\n```\n\nYou're now a command away from running application wide tests, generating documentation, and running a build. Start your server with `donejs develop`, open your browser, and you'll see a functioning, server-side rendered hello world page.\n\n##### Modlet component generator\n\nTo create a [component](http://canjs.com/docs/can.Component.html) organized with the [modlet](#section_Modlets) file organization pattern:\n\n```\ndonejs add component \n```\n\nIt will create the following files:\n\n\n```\nrestaurant/\n├── list/\n| ├── list.html\n| ├── list.js\n| ├── list.less\n| ├── list.md\n| ├── list.stache\n| ├── list_test.js\n| ├── test.html\n```\n\nThis folder contains everything a properly maintained component needs: a working demo page, a basic test, and documentation placeholder markdown file.\n\n##### Simple component generator\n\nFor simple, standalone components:\n\n```\ndonejs add component .component \n```\n\nWhich will generate a working component in a single file.\n\n##### Model generator\n\nTo create a new [model](http://connect.canjs.com/doc/can-connect%7Ccan%7Csuper-map.html):\n\n```\ndonejs add supermodel \n```\n\nThis will create:\n\n - a working model in the application's `models` folder\n - a working fixture file for that model\n - a working test, and add the test as a dependency for the application's model test\n\n
\n
You spend less time setting up your app,
\n
...and more time searching for carrots.
\n \n
\n\nView the Documentation\nView the Guide\n\n_Generators are provided by the [Generator DoneJS](https://github.com/donejs/generator-donejs) project with additional support via the [donejs-cli](https://github.com/donejs/cli) project_\n\n", - "description": " \nLearn about the features that will help you get your app done.\n\n### All-in-one stack\n\nDoneJS offers everything you need to build a modern web app. It comes with a module loader, build system, MVVM utilities, full testing layer, documentation generator, server side rendering utilities, a data layer, and more. Its completeness is itself a feature.\n\nThere's no mixing and matching pieces of your stack. Just `npm install` and get started.\n\nChoosing a modern stack is not at all simple or straightforward.\n\n1. *What types of tools do you want?* Server-side rendering? What is a virtual DOM? Do I need one? MVVM or Flux? Should I set up testing infrastructure? Documentation?\n\n2. *Choose all your pieces.* The good news is, you have [many choices](http://microjs.com/#). The bad news is, you have many choices. React, Angular, or Backbone? Require.js, browserify, or jspm? Jasmine or QUnit? What tool will run my tests?\n\n3. *Finally, you have to make sure your chosen tools work together effectively.* Does require.js work well with Angular? Does Karma work with Browserify? What about React and Babel?\n\nDoneJS gives you a full solution. It's our mission to eliminate any ambiguity around choosing technology for building an app, so you spend less time tinkering with your stack, and more time actually building your app.\n\nAnd as we've proven [over the last 8 years](/About.html#section=section_Evolve), we'll keep updating the stack as the state of the art evolves over time.\n\n### Integrated layers\n\nJust like Apple integrates the hardware and software for its devices, DoneJS integrates different technologies in a way that creates unique advantages that you can only get from using an integrated solution.\n\n#### Cross-layer features\n\nDoneJS makes it easier to do things that are not possible, or at best DIY, with competitor frameworks, by spanning technology layers. Here are a couple examples:\n\n##### 1. [Server-side rendering](#section=section_ServerSideRendered__Howitworks__PreppingyourappforSSR)\n\nServer-side rendering (SSR), which you can read about in more detail in its [section](#section_Server_SideRendered) below, spans many layers to make setup and integration simple.\n\nIt uses hooks in data components to automatically notify the server to delay rendering, [hot module swapping](#section=section_HotModuleSwapping) automatically integrates (no need to restart the server while developing), data is collected in an [inline cache](#section=section_CachingandMinimalDataRequests__Howitworks__Inlinecache) automatically and used to prevent duplicate AJAX requests. Support for these features is only possible because of code that spans layers, including can-connect, can-ssr, CanJS, and StealJS.\n\nBy contrast, React supports SSR, but you're left to your own devices to support delaying rendering, hot module swapping, and inline caching.\n\n##### 2. [Progressive enhancement](#section=section_ProgressiveLoading__Howitworks)\n\nYou can mark a section of your template to be progressively loaded by wrapping it with ``, like:\n\n```\n\n \n\n```\n\nand then running `donejs build`.\n\n`` has hooks that notify the build time algorithm to create a bundle for this template fragment and its dependencies. This feature spans StealJS, steal-build, CanJS, and done-cli.\n\n#### Story-level solutions\n\nAnother advantage of the integration between DoneJS' parts is the ability to solve development problems on the level of [**stories**](http://searchsoftwarequality.techtarget.com/definition/user-story) rather than just features.\n\nSolving a story means a packaged solution to a development problem, where several features across layers converge to solve the problem from start to finish. Here are several examples of stories that DoneJS solves:\n\n1. [Modular workflow](section=section_NPMPackages__Howitworks__Modularworkflow) - DoneJS makes it possible for teams to design and share components easily. Starting with [generators](#section=section_Generators), users can create [modlets](#section=section_Modlets) that encapsulate everything a [custom elements](#section=section_CustomHTMLElements) needs, easily add [documentation](#section=section_Documentation) and [testing](#section=section_ComprehensiveTesting), then use [NPM import and export](#section=section_NPMPackages) to easily share the modules with other developers, no matter what module format they're using.\n\n2. [Performance](#section=section_PerformanceFeatures) - DoneJS was designed from the start to solve the performance story, packaging [server-side rendering](#section=section_ServerSideRendered), [progressive loading](#section=section_ProgressiveLoading), [worker thread rendering](#section=section_WorkerThreadRendering), [data layer caching](#section=section_CachingandMinimalDataRequests), and more, all under one roof.\n\n3. [Maintainability](#section=section_Maintainabilityfeatures) - [testing](#section=section_ComprehensiveTesting), [docs](#section=section_Documentation), [MVVM](#section=section_MVVMArchitecture)\n\n4. Developer efficiency - [zero-config NPM imports](#section=section_NPMPackages), [hot module swapping](#section=section_HotModuleSwapping), [ES6 support](#section=section_ES6Modules)\n\n### Feature comparison\n\n
\n
\n
SOLUTION LEGEND
\n
    \n
  • \n \n
    EASY
    \n
  • \n
  • \n \n
    GOOD
    \n
  • \n
  • \n \n
    DIFFICULT
    \n
  • \n
  • \n \n
    THIRD-PARTY
    \n
  • \n
  • \n \n
    NO
    \n
  • \n \n
\n
\n
\n
\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
FEATURES
\n \n \n \n \n
\n \n
\n
\n
manual setup and lacks most of the features/support DoneJS has.\" title=\"Requires some manual setup and lacks most of the features/support DoneJS has.\">\n \n
\n
\n \n \n \n \n \n \n \n
\n \n \n \n \n \n \n \n
\n \n \n \n \n
\n \n
\n
\n \n
\n \n \n \n \n \n \n
\n \n
\n
\n \n \n \n \n \n \n \n
\n \n \n \n \n
\n \n
\n
\n
\n \n
\n
\n \n \n \n \n
\n \n
\n
\n \n
\n \n \n \n \n
\n \n
\n
\n
\n \n
\n
\n \n \n \n \n
\n \n
\n
\n
\n \n
\n
\n \n \n
\n \n
\n
\n
\n \n
\n
\n
\n \n \n
\n
\n \n \n \n \n \n \n \n
\n \n \n \n \n \n \n \n
\n \n \n \n \n \n \n \n
\n \n \n \n \n
\n \n
\n
\n
\n \n
\n
\n \n \n \n \n \n \n \n
\n \n \n \n \n
\n \n
\n
\n
\n \n
\n
\n \n \n \n \n \n \n
\n \n
\n
\n \n \n \n \n \n \n \n
\n
\n
\n
\n\n", + "body": "\n## Performance Features\n\nDoneJS is configured for maximum performance right out of the box.\n\n### Server-Side Rendered\n\nDoneJS applications are written as [Single Page Applications](http://en.wikipedia.org/wiki/Single-page_application),\nand are able to be rendered on the server by running the same code. This is known as [Isomorphic JavaScript](http://isomorphic.net/javascript), or [Universal JavaScript](https://medium.com/@mjackson/universal-javascript-4761051b7ae9).\n\nServer-side rendering (SSR) provides two large benefits over traditional single page apps: much better page load performance and SEO support.\n\nSSR apps return fully rendered HTML. Traditional single page apps return a page with a spinner. The benefit to your users is a noticeable difference in perceived page load performance:\n\n\"donejs-server-render-diagram.svg\"\n\nCompared to other server-side rendering systems, which require additional code and infrastructure to work correctly, DoneJS is uniquely designed to make turning on SSR quick and easy, and the server it runs is lightweight and fast.\n\n#### Page load performance\n\nServer-side rendered SPAs can load pre-rendered HTML immediately. They can also cache HTML and serve it from a CDN.\n\nTraditional SPAs must load the JS, execute, request data, and render before the user sees content.\n\n#### SEO\n\nSearch engines can't easily index SPAs. Server-side rendering fixes that problem entirely. Even if [Google can understand some JavaScript now](http://googlewebmastercentral.blogspot.ca/2014/05/understanding-web-pages-better.html), many other search engines cannot.\n\nSince search engines see the HTML that your server returns (if you want search engines to find your pages) you'll want Google and other search engines seeing fully rendered content, not the spinners that normally show after initial SPAs load.\n\n#### How it works\n\nDoneJS implements SSR with a single-context virtual DOM.\n\n**Single context** means every request to the server reuses the same context: including memory, modules, and even the same instance of the application.\n\n**Virtual DOM** means a virtual representation of the DOM: the fundamental browser APIs that manipulate the DOM, but stubbed out.\n\nWhen using DoneJS SSR, the same app that runs on the client is loaded in Node. When a request comes in:\n 1. The server handles the incoming request by reusing the application that is already running in memory. It doesn't reload the application (single context is optional, so reload is something you can opt into) which means the initial response is very fast.\n 1. The app renders content the same way it would in the browser, but with a mocked out virtual DOM, which is much faster than a real DOM.\n 1. The server waits for all your asynchronous data requests to finish before signaling that rendering is complete (more on how that works below).\n 1. When rendering is complete, the virtual DOM renders the string representation of the DOM, which is sent back to the client.\n\n\nSince SSR produces fully rendered HTML, it's possible to insert a caching layer, or use a service like Akamai, to serve most requests. Traditional SPAs don't have this option.\n\nRather than a virtual DOM, some other SSR systems use a headless browser on the server, like PhantomJS, which uses a real DOM. These systems are much slower and require much more intensive server resources.\n\nSome systems, even if they do use a virtual DOM, require a new browser instance entirely, or at the very least, reloading the application and its memory for each incoming request, which also is slower and more resource intensive than DoneJS SSR.\n\n##### Prepping your app for SSR\n\nAny app that is rendered on the server needs a way to notify the server that any pending asynchronous data requests are finished, and the app can be rendered.\n\nReact and other frameworks that support SSR don't provide much in the way of solving this problem. You're left to your own devices to check when all asychronous data requests are done, and delay rendering.\n\nDoneJS provides two easy mechanisms for notifying the server when data is finished loading.\n\nThe more common way is to make data requests in the template, which is possible via can-connect's [can-tag feature](http://connect.canjs.com/doc/can-connect%7Ccan%7Ctag.html). It calls a method internally that tells the server to wait for its promise to resolve. You just write your template, turn on SSR, and everything works seamlessly:\n\n```\n\n {{#each ./value}}\n
{{text}}
\n {{/each}}\n
\n```\n\nIf you're making data requests in JavaScript, just add one line to do this manually:\n\n```\nthis.attr( \"%root\" ).waitFor( promise );\n```\n\nThe server will wait for all promises registered via `waitFor` before it renders the page. In a full component that might look like this:\n\n```\ncan.Component.extend({\n tag: \"user-name\",\n template: can.stache( \"{{user.name}}\" ),\n viewModel: {\n init: function () {\n var promise = User.getOne( { id: this.attr( \"id\" ) } );\n this.attr( \"%root\" ).waitFor( promise );\n promise.then( ( user ) => { this.attr( \"user\", user ); } );\n }\n }\n});\n```\n\nView the Documentation\nView the Guide\n\n_Server-side rendering is a feature of [can-ssr](https://github.com/canjs/can-ssr)_\n\n### Progressive Loading\n\nWhen you first load a single page app, you're typically downloading all the JavaScript and CSS for every part of the application. These kilobytes of extra weight slow down page load performance, especially on mobile devices.\n\nDoneJS applications load only the JavaScript and CSS they need, when they need it, in highly optimized and cachable bundles. That means your application will load *fast*.\n\nThere is no configuration needed to enable this feature, and wiring up progressively loaded sections of your app is simple.\n\n#### How it works\n\n
\n\nOther build tools require you to manually configure bundles, which doesn't scale with large applications.\n\nIn a DoneJS application, you simply mark a section to be progressively loaded by wrapping it in your template with ``.\n\n```\n{{#eq page 'home'}}\n\n \n\n{{/eq}}\n{{#eq page 'chat'}}\n\n \n\n{{/eq}}\n```\n\nThen you run the build.\n\n```\ndonejs build\n```\n\nA build time algorithm analyzes the application's dependencies and groups them into bundles, optimizing for minimal download size.\n\nThat's it! No need for additional configuration in your JavaScript.\n\nView the Documentation\nView the Guide\n\n_Progressive Loading is a feature of [StealJS](http://stealjs.com/) with additional support via the [`` tag](http://canjs.com/docs/can%7Cview%7Cstache%7Csystem.import.html) of [CanJS](http://canjs.com/)_\n\n### Caching and Minimal Data Requests\n\nDoneJS improves performance by intelligently managing the data layer, taking advantage of various forms of caching and request reduction techniques.\n\nUndoubtedly, the slowest part of any web application is round trips to the server. Especially now that [more than 50% of web traffic comes from mobile devices](http://searchengineland.com/its-official-google-says-more-searches-now-on-mobile-than-on-desktop-220369), where connections are notoriously slow and unreliable, applications must be smart about reducing network requests.\n\nMaking matters worse, the concerns of maintainable architecture in single page applications are at odds with the concerns of minimizing network requests. This is because independent, isolated UI widgets, while easier to maintain, often make AJAX requests on page load. Without a layer that intelligently manages those requests, this architecture leads to too many AJAX requests before the user sees something useful.\n\nWith DoneJS, you don't have to choose between maintainability and performance.\n\nDoneJS uses the following strategies to improve perceived performance (reduce the amount of time before users see content rendered):\n\n - [Fall through caching](#section=section_CachingandMinimalDataRequests__Howitworks__Fallthroughcaching) - Cache data in localStorage. Automatically show cached data immediately, but look for updates on the server in the background and merge changes.\n - [Combining requests](#section=section_CachingandMinimalDataRequests__Howitworks__Combiningrequests) - Instead of making multiple, independent requests to the same API, combine them into a single request.\n - [Request caching](#section=section_CachingandMinimalDataRequests__Howitworks__Requestcaching) - Reduce the number and size of server requests by intelligently using cached datasets.\n - [Inline cache](#section=section_CachingandMinimalDataRequests__Howitworks__Inlinecache) - Use data embedded in the page response instead of making duplicate requests.\n\n#### How it works\n\n[can-connect](http://connect.canjs.com/) makes up part of the DoneJS model layer. Since all requests flow through this data layer, by making heavy use of set logic and localStorage caching, it's able to identify cache hits, even partial hits, and make the most minimal set of requests possible.\n\nIt acts as a central hub for data requests, making decisions about how to best serve each request, but abstracting this complexity away from the application code. This leaves the UI components themselves able to make requests independently, and with little thought to performance, without actually creating a poorly performing application.\n\n##### Fall through caching\n\nFall through caching serves cached data first, but still makes API requests to check for changes.\n\nThe major benefit of this technique is improved perceived performance. Users will see content faster. Most of the time, when there is a cache hit, that content will still be accurate, or at least mostly accurate.\n\nThis benefits two types of situations. First is page loads after the first page load (the first page load populates the cache). This scenario is less relevant when using server-side rendering. Second is long lived applications that make API requests after the page has loaded. These types of applications will enjoy improved performance.\n\nBy default, this is turned on, but can easily be deactivated for data that should not be cached.\n\nHere's how the caching logic works:\n\n1. When the application loads, it checks for available cache connections.\n1. When a request is made, it checks for a cache hit.\n1. If there is a hit, the request is completed immediately with the cached data.\n1. Regardless of a hit or miss, a request is made in the background to the actual API endpoint.\n1. When that response comes back, if there was a difference between the API response data and the cache hit data, the initial request promise's data is updated with the new data. Template data bindings will cause the UI to update automatically with these changes.\n1. Updated response data is automatically saved in the cache, to be used for future requests - whether that's in the current page session, or when the user comes back in the future.\n\n\n\n##### Combining requests\n\nCombining requests combines multiple incoming requests into one, if possible. This is done with the help of [set algebra](https://en.wikipedia.org/wiki/Algebra_of_sets).\n\nDoneJS collects requests that are made within a few milliseconds of each other, and if they are pointed at the same API, tries to combine them into a single superset request.\n\nFor example, the video below shows an application that shows two filtered lists of data on page load - a list of completed and incomplete todos. Both are subsets of a larger set of data - the entire list of todos.\n\nCombining these into a single request reduces the number of requests. This optimization is abstracted away from the application code that made the original request.\n\n\n\n##### Request caching\n\nRequest caching is a type of caching that is more aggressive than fallthrough caching. It is meant for data that doesn't change very often. Its advantage is it reduces both the number of requests that are made, and the size of those requests.\n\nThere are two differences between request and fallthrough caching:\n\n1. Cached data is not invalidated.\n\nOnce data is in the cache, no more requests to the API for that same set of data are made. You can write code that invalidates the cache at certain times, or after a new build is released.\n\n2. The smallest possible request is made, based on the contents of the cache, and merged into a complete result set.\n\nThe request logic is more aggressive in its attempts to find subsets of the data within the cache, and to only make an API request for the subset NOT found in the cache. In other words, partial cache hits are supported.\n\nThe video below shows two example scenarios. The first shows the cache containing a supserset of the request. The second shows the cache containing a subset of the request.\n\n\n\n\n##### Inline cache\n\nServer-side rendered single page apps (SPAs) have a problem with wasteful duplicate requests. These can cause the browser to slow down, waste bandwidth, and reduce perceived performance.\n\n1. When a page is rendered server-side, it makes data requests on the server to various APIs.\n1. After the page's rendered HTML loads in the client, the SPA is loaded in the client, so that subsequent requests are handled within the SPA.\n1. The SPA will want to re-request for the same data that was already requested on the server.\n\nDoneJS solves this problem with an inline cache - embedded inline JSON data sent back with the server rendered content, which is used to serve the initial SPA data requests.\n\nDoneJS uniquely makes populating and using the inline cache easy. `waitFor` is a method that:\n\n1. Tells the SSR server to wait for a promise to resolve before rendering.\n1. Collects data from each promise and uses it to populate the inline cache.\n\nFor example:\n\n```\ncan.Component.extend({\n tag: \"user-name\",\n template: can.stache( \"{{user.name}}\" ),\n viewModel: {\n init: function () {\n var promise = User.getOne( { id: this.attr( \"id\" ) } );\n this.attr( \"%root\" ).waitFor( promise );\n promise.then( ( user ) => { this.attr( \"user\", user ); } );\n }\n }\n});\n```\n\nThe model layer seamlesslly integrates the inline cache in client side requests, without any special configuration.\n\nWhile this flow would be possible in other SSR systems, it would require manually setting up all of these steps.\n\nThis video illustrates how it works.\n\n\n\n\n\n\nView the Documentation\nView the Guide\n\n_Caching and minimal data requests is a feature of [can-connect](https://github.com/canjs/can-connect)_\n\n### Minimal DOM Updates\n\nThe rise of templates, data binding, and MV* separation, while boosting maintainability, has come at the cost of performance. Many frameworks are not careful or smart with DOM updates, leading to performance problems as apps scale in complexity and data size.\n\nDoneJS' view engine touches the DOM more minimally and specifically than competitor frameworks, providing better performance in large apps and a \"closer to the metal\" feel.\n\nTake the TodoMVC application as an example. If you measure how long it takes DoneJS and React to render the same number of todos you'll see the performance advantage of minimal DOM updates. In fact we did just that and here's the result:\n\n\"Measuring\n_For a small set of todos the difference is negligible but as the number increases the gap widens to the point where React is 6 times slower than DoneJS when rendering 1000 todos._\n\nYou can run this test for yourself at JS Bin.\n\n#### How it works\n\nConsider the following template:\n\n```html\n{{#rows}}\n
{{name}}
\n{{/rows}}\n```\n\nAnd the following change to its data:\n\n```\nrows[0].attr('name', 'changed'); // change the first row's name\n```\n\nIn DoneJS, which uses the [can.stache](http://canjs.com/docs/can.stache.html) view engine, that would:\n\n 1. Trigger an event (because of the [can.Map](http://canjs.com/docs/can.Map.html) object observe API)\n 1. The event invokes a data binding event handler in the template layer\n 1. The handler immediately results in the following code being run:\n```\ntextNode.nodeValue = 'changed';\n```\n\nIn Backbone, you would need to manually re-render the template or roll your own rendering library.\n\nIn Angular, at the end of the current $digest cycle, that would result in an expensive comparison between the old rows array and the new one to see what properties have changed. After the changed property is discovered, the specific DOM node would be updated.\n\nIn React, that would result in the virtual DOM being re-rendered. A diff algorithm comparing the new and old virtual DOM would discover the changed node, and then the specific DOM node would be updated.\n\nOf these four approaches, DoneJS knows about the change the quickest, and updates the DOM the most minimally.\n\nTo see this in action run the test embedded below that shows how DoneJS, React and Angular compare when updating the DOM when a single property changes:\n\"Measuring\n\nYou can run this test yourself at JS Bin\n\nWith synchronously observable objects and data bindings that change mimimal pieces of the DOM, DoneJS aims to provide the best possible mix between powerful, yet performant, templates.\n\ncan.stache Documentation\ncan.Map Documentation\n\n_Minimal DOM updates is a feature of [CanJS](http://canjs.com/)_\n\n### Worker Thread Rendering\n\nWorker thread rendering increases the performance of your application. It essentially allows your application to run entirely within a Web Worker, freeing the main thread to only update the DOM.\n\nSince much of the work is offloaded from the main thread, applications will feel snappy, even while heavy computations are taking place.\n\n#### How it works\n\nTemplates first render in a lightweight Virtual DOM in a [Web Worker](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers). Changes are diffed and sent to the main thread to be applied to the real DOM. The main thread is only notified when there are changes to the DOM.\n\nThe most expensive part of a web application - DOM updates - are separated from application logic, which means your application can continue to run while DOM reflows occur.\n\nBy default, browsers use only a single thread of execution.\n\n\"A\n_With a single thread only one operation can occur at a time_\n\nThis means that performance problems in any area (expensive computations, DOM rendering, processing a large AJAX response, etc) can block the entire application, leaving the browser feeling \"frozen\".\n\nWith worker thread rendering, DOM updates and application logic are run in parallel threads.\n\n\"A\n_Using a worker thread application logic can still occur while the DOM is rendered. This could nearly double the number of operations per second._\n\nDue to this parallelization, performance problems that may have caused noticeable issues in a single thread will likely not cause any noticeable issues while running in separate threads.\n\nAdding worker thread rendering only requires changing one line. Change the main attribute of your page's script tag from:\n```\n\n```\nto\n```\n\n```\n\nAt this time, no other framework besides DoneJS, including Angular or React, supports worker thread rendering out of the box.\n\n
\n
You spend less time worrying about performance micro-optimizations,
\n \n \n
\n\n\nView the Documentation\n\n_Worker Thread Rendering is a feature of the [worker-render](https://github.com/canjs/worker-render) project._\n\n### Deploy to a CDN\n\nDoneJS makes it simple to deploy your static assets to a CDN (content delivery network).\n\nCDNs are distributed networks of servers that serve static assets (CSS, JS, and image files). You only push your files to one service, and the CDN takes care of pushing and updating your assets on different servers across the country and globe. As your app scales CDNs will keep up with the demand, and help support users regardless if they are in New York or Melbourne.\n\n\"User\n_Without a CDN, requests will take longer to fulfill if the user is located further away from your servers._\n
\n\n\n\"User\n_With a CDN, requests can be fulfilled much quicker. Users are served content from the servers located nearest to them._\n\n#### How it works\n\nIt's widely known that CDNs offer the best performance for static assets, but most apps don't use them, mainly because its annoying: annoying to automate, configure, and integrate with your build process.\n\nDoneJS comes with integrations with [S3](https://aws.amazon.com/s3/) and [Firebase](https://www.firebase.com) (popular CDN services) that make configuring and deploying to a CDN dirt simple.\n\n 1. You sign up for S3 or Firebase.\n 2. You paste a few lines of config into your `package.json` that point to the right CDN service.\n\n```\n\"donejs\": {\n \"deploy\": {\n \"root\": \"dist\",\n \"services\": {\n \"production\": {\n \"type\": \"firebase\",\n \"config\": {\n \"firebase\": \"place-my-order\",\n \"public\": \"./dist\",\n \"headers\": [{\n \"source\": \"/**\",\n \"headers\": [{\n \"key\": \"Access-Control-Allow-Origin\",\n \"value\": \"*\"\n }]\n }]\n }\n }\n }\n }\n}\n```\n 3. You paste a few more lines that tell your production server to serve static assets from the CDN.\n\n```\n{\n \"system\": {\n \"envs\": {\n \"production\": {\n \"baseURL\": \"https://place-my-order.firebaseapp.com/\"\n }\n },\n```\n 4. You run `donejs deploy`.\n\nThat's it. Now when you run your server in production mode, all static assets (CSS, JS, images, etc) are served from the CDN.\n\nEven better, you can set up [continuous deployment](./place-my-order.html#section=section_ContinuousDeployment), so that TravisCI or other tools will deploy your code, including pushing out your latest static files to the CDN, automatically.\n\nView the Documentation\nView the Guide\n\n_CDN deployment is a feature of the [donejs/deploy](https://github.com/donejs/deploy) project._\n\n## Usability features\n\nDoneJS is used to make beautiful, real-time user interfaces that can be exported to run on every platform.\n\n### iOS, Android, and Desktop Builds\n\nWrite your application once, then run it natively on every device and operating system. You can make iOS, Android, and desktop builds of your DoneJS application with no extra effort.\n\n\n_Our DoneJS Chat App running as a OS X desktop app and inside an iOS emulator._\n\n#### How it works\n\nFor iOS and Android builds, DoneJS integrates with [Apache Cordova](https://cordova.apache.org/) to generate a mobile app that is ready to be uploaded to Apple's App Store or Google Play.\n\nFor native desktop applications, DoneJS integrates with [NW.js](https://github.com/nwjs/nw.js) to create an native OSX, Windows, or Linux application.\n\nAdding this integration is as simple as running\n\n```\ndonejs add cordova\ndonejs add nw\ndonejs build\n```\n\nWith these simple integrations, you can expand your potential audience without having to build separate applications.\n\nView the Documentation\nView the Guide\n\n_Cordova and nw.js integration are features of the [steal-cordova](https://github.com/stealjs/steal-cordova) and [steal-nw](https://github.com/stealjs/steal-nw) projects._\n\n### Supports All Browsers, Even IE8\n\nDoneJS applications support Internet Explorer 8 minimal additional configuration. You can even write applications using [most ES6 features](http://babeljs.io/docs/advanced/caveats/) that run on IE8, using the built-in babel integration.\n\nMany people won't care about this because IE8 is on its way out, which is a very good thing!\n\nBut it's [not quite dead yet](https://youtu.be/grbSQ6O6kbs?t=61). For many mainstream websites, banks, and ecommerce applications, IE8 continues to hang around the browser stats.\n\nAnd while other frameworks like AngularJS and EmberJS don't support IE8, DoneJS makes it easy to write one app that runs everywhere.\n\nView the Guide\n\n### Real Time Connected\n\nDoneJS is designed to add real-time behavior to applications using any backend technology stack.\n\n[Socket.io](https://socket.io) provides the basics to add real-time capabilities to any JavaScript application, but the challenge of integrating real-time updates into your code remains.\n\nWhen new data arrives, how do you know what data structures to add it to? And where to re-render? Code must be written to send socket.io data across your application, but that code becomes aware of too much, and therefore is brittle and hard to maintain.\n\nDoneJS makes weaving Socket.io backends into your UI simple and automatic.\n\n#### How it works\n\n
\n\nDoneJS' model layer uses set logic to maintain lists of data represented by JSON properties, like a list of todos with `{'ownerId': 2}`. These lists are rendered to the UI via data bound templates.\n\nWhen server-side updates are sent to the client, items are automatically removed or added to any lists they belong to. They also automatically show up in the UI because of the data bindings.\n\nAll of this happens with about 4 lines of code.\n\n```\nconst socket = io('http://chat.donejs.com');\nsocket.on('messages created',\n order => messageConnection.createInstance(order));\nsocket.on('messages updated',\n order => messageConnection.updateInstance(order));\nsocket.on('messages removed',\n order => messageConnection.destroyInstance(order));\n```\n\n[Follow the guide](./Guide.html#section=section_Enableareal_timeconnection) to see an example in action. View the can-connect real-time documentation [here](http://connect.canjs.com/doc/can-connect%7Creal-time.html).\n\nView the Documentation\nView the Guide\n\n_Real time connections is a feature of the [can-connect](http://connect.canjs.com) project._\n\n### Pretty URLs with Pushstate\n\nDoneJS applications use [pushstate](https://developer.mozilla.org/en-US/docs/Web/API/History_API#The_pushState()_method) to provide navigable, bookmarkable pages that support the back and refresh buttons, while still keeping the user in a single page.\n\nThe use of pushstate allows your apps to have \"Pretty URLs\" like `myapp.com/user/1234` instead of uglier hash based URLs like `myapp.com#page=user&userId=1234` or `myapp.com/#!user/1234`.\n\nWiring up these pretty URLs in your code is simple and intuitive.\n\n#### How it works\n\n
\n\nRouting works a bit differently than other libraries. In other libraries, you might declare routes and map those to controller-like actions.\n\nDoneJS application [routes](http://canjs.com/docs/can.route.html) map URL patterns, like `/user/1`, to properties in our application state, like `{'userId': 1}`. In other words, our routes will just be a representation of the application state.\n\nThis architecture simplifies routes so that they can be managed entirely in simple data bound templates, like the following example:\n\n```\n{{#switch page}}\n {{#case \"home\"}}\n \n {{/case}}\n {{#case \"users\"}}\n {{#if slug}}\n \n {{else}}\n \n {{/if}}\n {{/case}}\n{{/switch}}\n```\n\nView the Documentation\nView the Guide\n\n_Pretty URLs and routing are features of the [CanJS](http://canjs.com/) project._\n\n## Maintainability features\n\nDoneJS helps developers get things done quickly with an eye toward maintenance.\n\n### Comprehensive Testing\n\nNothing increases the maintainability of an application more than good automated testing. DoneJS includes a comprehensive test layer that makes writing, running, and maintaining tests intuitive and easy.\n\nDoneJS provides tools for the entire testing lifecycle:\n\n* [Generators](#section=section_ComprehensiveTesting__Howitworks__Generators) - create boilerplate tests to get started quickly\n* [Unit testing](#section=section_ComprehensiveTesting__Howitworks__Unittests) - assertion libraries to test your module interfaces\n* [Functional testing](#section=section_ComprehensiveTesting__Howitworks__Functionaltests) - scripting the browser, simulating user actions, and testing your UI modules\n* [User action event simulation](#section=section_ComprehensiveTesting__Howitworks__Eventsimulationaccuracy) - accurate event simulation for clicks, types, drags, and other user actions\n* [A command line test runner](#section=section_ComprehensiveTesting__Howitworks__Runningtestsfromthecommandline) - invoke the same tests from the CLI\n* [A browser launcher](#section=section_ComprehensiveTesting__Howitworks__Runningtestsfromthecommandline) - launch several browsers and target your tests against them\n* [A reporting tool](#section=section_ComprehensiveTesting__Howitworks__Runningtestsfromthecommandline) - report results, including code coverage, to the CLI, in various formats\n* [Simple integration with continuous integration tools](#section=section_ContinuousIntegration_Deployment) - one step to hook into TravisCI or other CI systems\n* [A mock layer](#section=section_ComprehensiveTesting__Howitworks__MockingserverAPIs) - mock out your server APIs so you can test your app in isolation from a server\n\n
\n
\n \n
\n
\n\n#### How it works\n\nTesting JavaScript apps is complex unto itself. To do it right, you need many tools that have to work together seamlessly. DoneJS provides everything you need - the whole stack.\n\n##### Generators\n\nThe DoneJS app generator command `donejs add app` creates a working project-level test HTML and JS file. Component generators via `donejs add component cart` create a test script and individual test page for each test.\n\n##### Unit tests\n\nUnit tests are used to test the interface for modules like models and view models. You can choose between BDD style unit tests with Jasmine or Mocha, or a more traditional TDD assertion style with QUnit.\n\n##### Functional tests\n\nFunctional tests are used to test UI components by simulating user behavior. The syntax for writing functional tests is jQuery-like, chainable, and asynchronous, simulating user actions and waiting for page elements to change asynchronously.\n\n```js\ntest('destroying todos', function() {\n F('#new-todo').type('Sweet. [enter]');\n\n F('.todo label:contains(\"Sweet.\")').visible('basic assert');\n F('.destroy').click();\n\n F('.todo label:contains(\"Sweet.\")').missing('destroyed todo');\n});\n```\n\n##### Event simulation accuracy\n\nUser action methods, like click, type, and drag, simulate exactly the sequence of events generated by a browser when a user performs that action. For example this:\n```\nF( \".menu\" ).click();\n```\n\nis not just a click event. It triggers a mousedown, then blur, then focus, then mouseup, then click. The result is more accurate tests that catch bugs early.\n\nEven further, there are differences between how IE and Safari handle a click. DoneJS tests take browser differences into account when running functional tests.\n\n##### Running tests from the command line\n\nDoneJS comes with a command line test runner, browser launcher, and reporting tool that integrates with any [continuous integration](#section=section_ContinuousIntegration_Deployment) environment.\n\nNo setup required, running a DoneJS project's test is as simple as running:\n\n```\ndonejs test\n```\n\nYou can run launch your unit and functional tests from the cli, either in headless browser mode, or via multiple real browsers. You can even launch browserstack virtual machines to test against any version of Android, Windows, etc.\n\nThe reporting tool gives detailed information about coverage statistics, and lets you choose from many different output formats, including XML or JSON files.\n\n##### Mocking server APIs\n\nAutomated frontend testing is most useful when it has no external dependencies on API servers or specific sets of data. Thus a good mock layer is critical to write resilient tests.\n\nDoneJS apps use fixtures to emulate REST APIs. A default set of fixtures are created by generators when a new model is created. Fixtures are very flexible, and can be used to simulate error states and slow performing APIs.\n\n```js\nimport fixture from 'can-fixture';\n\nconst store = fixture.store([\n { name: 'Calisota', short: 'CA' },\n { name: 'New Troy', short: 'NT'}\n],{});\n\nfixture({\n 'GET /api/states': store.findAll,\n 'GET /api/states/{short}': store.findOne,\n 'POST /api/states': store.create,\n 'PUT /api/states/{short}': store.update,\n 'DELETE /api/states/{short}': store.destroy\n});\n\nexport default store;\n```\n\n##### Simple authoring\n\nSeveral DoneJS features converge to make authoring tests extremely simple.\n\nBecause of [ES6 Module](#section=section_ES6Modules) support, everything in a DoneJS app is a module, so a test can simply import the modules it needs - such as fixtues and module under test:\n\n```\nimport restaurantStore from 'place-my-order/models/fixtures/restaurant';\nimport { ViewModel } from './list';\n```\n\nThis means the test is small, isolated, and simple. Tests themselves are modules too, so they can be collected easily into sets of tests.\n\nBecause of the [modlet](#section=section_Modlets) pattern, each component contains its own working test script and test file, which can be worked on in isolation.\n\nBecause of [hot module swapping](#section=section_HotModuleSwapping), you can write, debug, and run tests without constantly reloading your page.\n\nOther frameworks require a build step before tests can be run. These builds concatenate dependencies and depend on specific order of tests running, which is a brittle and inefficient workflow.\n\nBecause DoneJS uses a client side loader that makes it simple to start a new page that loads its own dependencies, there is no build script needed to compile and run tests.\n\nYou just run the generator, load your modules, write your test, and run it - from the browser or CLI.\n\n
\n
You spend less time messing with test infrastructure,
\n
...and more time mud ridin'.
\n \n
\n\n##### More information\n\nThe DoneJS testing layer involves many pieces, so if you want to learn more:\n\n * follow along in the [Unit testing view model and fixtures](./place-my-order.html#section=section_Creatingaunit_testedviewmodel) section of the guide\n * see how to run tests and set up CI automation in the [CI section](./place-my-order.html#section=section_Automatedtestsandcontinuousintegration) of the guide\n * read about [FuncUnit](http://funcunit.com/), the functional testing and asynchronous user action simulating library\n * read about [syn](https://github.com/bitovi/syn) - the synthetic event library\n * read about the [Testee.js](https://github.com/bitovi/testee) browser launcher, test runner, and reporting tool\n * read the [can.fixture](http://canjs.com/docs/can.fixture.html) docs\n\n### Documentation\n\nDocumentation is critical for maintainability of any complex application. When your team adds developers, docs ensure minimal ramp up time and knowledge transfer.\n\nYet most teams either don't write docs, or they'll do it \"later\" - a utoptian future period that is always just out of reach. Why? Because it's extra work to set up a tool, configure it, create and maintain separate documentation files.\n\nDoneJS comes with a documentation tool built in, and it generates multi-versioned documentation from inline code comments. It eliminates the barrier to producing docs, since all you have to do is comment your code (which most people already do) and run `donejs document`.\n\n
\n
\n \n
\n
\n\n#### How it works\n\nYou write comments above the module, method, or object that you want to document:\n\n```js\n/**\n * @module {function} utils/add\n * @parent utils\n *\n * The module's description is the first paragraph.\n *\n * The body of the module's documentation.\n *\n * @param {Number} first This param's description.\n * @param {Number} second This param's description.\n * @return {Number} This return value's description.\n */\nexport default function(){ ... };\n```\n\nThen run `donejs document`. A browsable documentation website will be generated.\n\n\"A\n\nDoneJS applications use [DocumentJS](http://documentjs.com) to produce multi-versioned documentation. It lets you:\n\n- Write docs inline or in markdown files.\n- Specify your code's behavior precisely with JSDoc and [Google Closure Compiler annotations](https://developers.google.com/closure/compiler/docs/js-for-compiler?hl=en) - a well known documentation syntax.\n- Customize your site's theme and layout.\n- Generate multi-versioned documentation.\n- Document CSS alongside JavaScript. You can even make a [live style guide](http://documentjs.com/examples/styles/index.html).\n\nYou can keep it simple like the example above, or you can customize your docs with many powerful features. In fact, this entire site and the [CanJS](http://canjs.com/docs/index.html) site are generated using DocumentJS.\n\n
\n
You spend less time messing with Documentation generators,
\n
...and more time perfecting your moonwalk.
\n \n
\n\nView the Documentation\nView the Guide\n\n_DoneJS Documentation is a feature of [DocumentJS](http://documentjs.com/)_\n\n### Continuous Integration & Deployment\n\nContinuous Integration (CI) and Continuous Deployment (CD) are must have tools for any modern development team.\n\nCI is a practice whereby all active development (i.e. a pull request) is checked against automated tests and builds, allowing problems to be detected early (before merging the code into the release branch).\n\n\"A\n_Example of a GitHub pull request with Travis CI integrated. Warns users in advance of merges if their changes will break builds or fail tests._\n\nCD means that any release or merges to your release branch will trigger tests, builds and deployment.\n\nPaired together, CI and CD enable automatic, frequent releases. CD isn't possible without CI. Good automated testing is a must to provide the confidence to release without introducing bugs.\n\nDoneJS provides support for simple integration into popular CI and CD tools, like TravisCI and Jenkins.\n\n
\n
\n \n
\n
\n\n#### How it works\n\nSetting up continuous integration and deployment involves several steps:\n 1. Writing tests\n 1. Setting up a test harness that runs tests from the command line\n 1. Creating simple scripts for running a build, test, and deploy\n 1. Integrating with a service that runs the scripts at the proper times\n\nSteps 1, 2, and 3 are the hard parts. Step 4 is simple. DoneJS supports in two main ways: proper test support and simple CLI commands.\n\n##### Proper test support\n\nDoneJS comes with comprehensive support for testing. The [Testing](#section=section_ComprehensiveTesting) section contains much more detail about testing support.\n\n[Generators](#section=section_Generators) create working test scripts right off the bat, and the plumbing for test automation is built into each project. Each [modlet](#section=section_Modlets) contains a skeleton for unit tests. All that is left for the developer to do is write tests.\n\n##### Simple CLI commands\n\nAnother hurdle is creating automated build, test, and deployment scripts. Every DoneJS app comes with a build, test, and deployment one-liner: `donejs build`, `donejs test`, and `donejs deploy`.\n\n##### Tool integration\n\nOnce the tests are written and the scripts are automated, integrating with the tools that automatically runs these scripts is quite simple. For instance, setting up Travis CI involves signing up and adding a `.travis.yml` file to the project:\n\n```\nlanguage: node_js\nnode_js: node\nscript: npm start & npm test\nbefore_install:\n - \"export DISPLAY=:99.0\"\n - \"sh -e /etc/init.d/xvfb start\"\n```\n\nView the CI Guide\nView the CD Guide\n\n### Modlets\n\nThe secret to building large apps is to never build large apps. Break up your application into small pieces. Then, assemble.\n\nDoneJS encourages use of the modlet file organization pattern. Modlets are small, decoupled, reusable, testable mini applications.\n\n#### How it works\n\nLarge apps have a lot of files. There are two ways to organize them: by type or by module.\n\n\"DoneJS\n\nOrganization by module - or modlets - make large applications easier to maintain by encouraging good architecture patterns. The benefits include:\n\n * Each modlet contains its own demo page and its own test page. Getting a demo page running forces separation of concerns and isolated modules - hallmarks of good design. A standalone demo and test page makes it easy to work on pieces of your application in isolation.\n * Developers are more likely to update tests and documentation if they are sitting right next to the module they are editing. The test is not hidden in a `tests` folder that is more easily ignored.\n * You can develop the application without having to load the entire application and all of its tests on every change.\n\nAn example modlet from the [in depth guide](/place-my-order.html) is the [order/new](https://github.com/donejs/place-my-order/tree/master/src/restaurant/list) component. It has its own [demo page](http://www.place-my-order.com/src/order/new/demo.html) and [test page](http://www.place-my-order.com/src/order/new/test.html).\n\nDoneJS generators create modlets to get you started quickly. To learn more about the modlet pattern, read this [blog post](http://blog.bitovi.com/modlet-workflows/).\n\nView the Video\nView the Guide\n\n_Modlets are a feature of DoneJS [generators](#section=section_Generators)._\n\n### NPM Packages\n\nDoneJS makes it easy to share and consume modules via package managers like NPM and Bower.\n\nYou can import modules from any package manager in any format - CommonJS, AMD, or ES6 - without any configuration. And you can convert modules to any other format.\n\nThe goal of these features is to transform project workflows, making it easier to share and reuse ideas and modules of functionality across applications, with less hassle.\n\n\n
\n
\n \n
\n
\n\n#### How it works\n\nDoneJS apps use [StealJS](http://stealjs.com/) to load modules and install packages. This video introduces NPM import and export in StealJS:\n\n
\n\n##### Zero config package installation\n\nUnlike Browserify or Webpack, StealJS is a client side loader, so you don't have to run a build to load pages.\n\nInstalling a package in a DoneJS app via npm or bower involves no configuration. Install your package from the command line:\n\n```\nnpm install jquery --save\n```\n\nThen immediately consume that package (and its dependencies) in your app:\n\n```\nimport $ from \"jquery\";\n```\n\nUsing require.js or other client side loaders, you'd have to add pathing and other information to your configuration file before being able to use your package. In DoneJS, this step is bypassed because of scripts that add config to your package.json file as the package is installed.\n\nYou can import that package in any format: CommonJS, AMD, or ES6 module format.\n\n##### Convert to any format\n\nDoneJS supports converting a module to any other format: CommonJS, AMD, or ES6 module format, or script and link tags.\n\nThe advantage is that you can publish your module to a wider audience of users. Anyone writing JavaScript can use your module, regardless of which script loader they are using (or if they aren't using a script loader).\n\nJust create an [export script](http://stealjs.com/docs/steal-tools.export.html) that points to the output formats you want, along with some options:\n```js\nvar stealTools = require(\"steal-tools\");\nstealTools.export({\n system: {\n config: __dirname+\"/package.json!npm\"\n },\n outputs: {\n amd: {\n format: \"amd\",\n graphs: true,\n dest: __dirname+\"/dist/amd\"\n }\n});\n```\n\nand run it from your command line:\n```\nnode myexport.js\n```\n\n##### Modular workflow\n\nIn combination with other DoneJS features, NPM module import and export make it possible for teams to design and share components easily.\n\n[Generators](#section=section_Generators) make it easy to bootstrap new modules of functionality quickly, and the [modlet pattern](#section_Modlets) makes it easy to organize small, self-contained modules. Its even easy to create tests and documentation for each module.\n\nDoneJS enables a modular workflow, where pieces of small, reusable functionality can be easily created, shared, and consumed.\n\n 1. Use generators to create a modlet\n 1. Develop rich functionality\n 1. Write tests and docs\n 1. Export and publish it - internally or externally\n 1. Consume it across applications\n\nSimilar to the way that the [microservices](http://microservices.io/patterns/microservices.html) architecture encourages reuse of APIs across applications, the modular workflow encourages reuse of self-contained modules of JavaScript across applications.\n\nImagine an organization where every app is broken into many reusable pieces, each of which are independently tested, developed, and shared. Over time, developers would be able to quickly spin up new applications, reusing previous functionality. DoneJS makes this a real possibility.\n\nView the Documentation\nView the Guide\n\n_NPM package support is a feature of [StealJS](http://stealjs.com/)_\n\n### ES6 Modules\n\nDoneJS supports the compact and powerful [ES6 module](http://www.2ality.com/2014/09/es6-modules-final.html) syntax, even for browsers that don't support it yet. Besides future proofing your application, writing ES6 modules makes it easier to write modular, maintainable code.\n\n````\nimport { add, subtract } from \"math\";\n\nexport function subtract(a, b) {\n return a - b;\n}\n````\n\n#### How it works\n\nDoneJS applications are actually able to import or export any module type: ES6, AMD and CommonJS. This means you can slowly phase in ES6, while still using your old code. You can also use any of the many exciting [ES6 language features](https://github.com/lukehoban/es6features).\n\nA compiler is used to convert ES6 syntax to ES5 in browsers that don't yet support ES6. During development, the compiler runs in the browser, so changes are happening live without a build step. During the build, your code is compiled to ES5, so your production code will run native in every browser. You can even run your [ES6 application in IE8](#section=section_SupportsAllBrowsers_EvenIE8)!\n\nView the Documentation\nView the Guide\n\n_Pretty URLs and routing are features of the [stealjs/transpile](https://github.com/stealjs/transpile) project._\n\n### Custom HTML Elements\n\nOne of the most important concepts in DoneJS is splitting up your application functionality into independent, isolated, reusable custom HTML elements.\n\nThe major advantages of building applications based on custom HTML elements are:\n\n 1. **Ease of page composition** - Designers can do it! Non-developers can express complex behavior with little to no JavaScript required. All you need to build a new page or feature is HTML.\n 1. **Forced modularity** - Because the nature of HTML elements are isolated modules, custom HTML elements must be designed as small, isolated components. This makes them easier to test, debug, and understand.\n 1. **Reuse** - Custom elements are designed to be reusable across pages and applications.\n\nConsider the following example:\n\n```html\n\n\n\n\n \n \n \n \n\n```\nThis code demonstrates:\n\n 1. An element that can load data\n 1. Composable widget elements (a graph with a line-series)\n\nIf our designer wanted to add another period, all they would need to do is add another `` and `` element.\n\nHere’s a working version of the same example in a JSBin.\n\nCustom HTML Elements on jsbin.com\n\nJust like HTML’s natural advantages, composing entire applications from HTML building blocks allows for powerful and easy expression of dynamic behavior.\n\n#### How it works\n\nFirst, it's important to understand the background of custom elements and their advantages. Then, we'll discuss the details of creating powerful custom elements in specifically DoneJS, and why they're special.\n\n##### Benefits of custom elements\n\nBefore custom HTML elements existed, to add a datepicker to your page, you would:\n\n 1. Load a datepicker script\n 1. Add a placeholder HTML element\n\n```\n
\n```\n 3. Add JavaScript code to instantiate your datepicker\n\n```\n$('.datepicker').datepicker()\n```\n 4. Gather your stone tipped spears and forage for small animals to feed your family for the night.\n\nWith custom HTML elements, to add the same datepicker, you would:\n\n 1. Load a datepicker script\n 1. Add the datepicker to your HTML or template:\n\n```\n\n```\n\nThat might seem like a subtle difference, but it is actually a major step forward. The custom HTML element syntax allows for instantiation, configuration, and location, all happening at the same time.\n\nCustom HTML elements are another name for [Web Components](http://webcomponents.org/), a browser spec that has [yet to be implemented](http://caniuse.com/#search=components) across browsers.\n\n##### Benefits of DoneJS custom elements\n\nDoneJS uses CanJS' [can.Component](http://canjs.com/docs/can.Component.html) to provide a modern take on web components.\n\nComponents in DoneJS have three basic building blocks:\n\n * a template\n * a viewModel object\n * event handlers\n\nThere are several unique benefits to DoneJS custom elements:\n\n * [Easily construct custom elements](#section=section_CustomHTMLElements__Howitworks__Definingacustomelement) - you can define them within a single `.component` file, or a modlet\n * [Load data from custom elements](#section=section_CustomHTMLElements__Howitworks__Dataelementsvisualelementsexpressivetemplates)\n * [Simple progressive loading with can-import](#section=section_CustomHTMLElements__Howitworks__Intemplatedependencydeclarations)\n\n##### Defining a custom element\n\nOne way to define a component is with a [web component](https://github.com/donejs/done-component) style declaration, using a single file with a `.component` extension:\n\n```html\n\n \n \n \n \n\n```\n\nThis simple form of custom elements is great for quick, small widgets, since everything is contained in one place.\n\nAnother way to organize a custom element is a [modlet](#section_Modlets) style file structure: a folder with the element broken into several independent pieces. In this pattern, the custom element's ViewModel, styles, template, event handlers, demo page, tests, and test page are all located in separate files. This type of custom element is well suited for [export and reuse](#section=section_NPMPackages__Howitworks__Modularworkflow).\n\nDoneJS [Generators](#section_Generators) will create both of these types of custom elements so you can get started quickly.\n\n##### Data elements + visual elements = expressive templates\n\nThe beauty and power of custom HTML elements is most apparent when visual widgets (like graphing) is combined with elements that express data.\n\nBack to our original example:\n\n```html\n\n\n\n\n \n \n\n```\n\nThis template combines a request for data with an element that expresses it. It's immediately obvious how you would add or remove features from this, allowing for quick changes and easy prototyping. Without custom elements, the same changes would require more difficult code changes and wiring those changes up with widget elements that display the data.\n\nData custom elements are part of DoneJS via can-connect's [can-tag feature](http://connect.canjs.com/doc/can-connect%7Ccan%7Ctag.html).\n\n##### Custom element libraries\n\nCustom elements are designed to be easily shareable across your organization. DoneJS provides support for simple [NPM import and export](#section_NPMPackages) and creating [documentation](#section=section_Documentation) for elements. Together with custom element support, these features make it easier than ever to create reusable bits of functionality and share them.\n\nSome open source examples of DoneJS custom elements:\n\nbit-c3\nbit-tabs\nbit-autocomplete\n\nCheck out [their source](https://github.com/bitovi-components/bit-tabs) for good examples of shareable, documented, and tested custom elements.\n\n##### In-template dependency declarations\n\n[can-import](http://canjs.com/docs/can%7Cview%7Cstache%7Csystem.import.html) is a powerful feature that allows templates to be entirely self-sufficient. You can load custom elements, helpers, and other modules straight from a template file like:\n\n```\n\n\n\n ...\n ...\n\n```\n\nThe `` element also plays a key role in [Progressive Loading](#section=section_ProgressiveLoading). Simply by wrapping a section in a closed can-import, it signals to the build that the enclosed section's dependencies should be progressively loaded.\n\n```\n{{#eq location 'home'}}\n\n \n\n{{/eq}}\n{{#eq location 'away'}}\n\n \n\n{{/eq}}\n```\n\nView the Documentation\nView the Guide\n\n_Custom HTML elements are a feature of [CanJS](http://canjs.com/)_\n\n### MVVM Architecture\n\nDoneJS applications employ a [Model-View-ViewModel](https://en.wikipedia.org/wiki/Model_View_ViewModel) architecture pattern, provided by [CanJS](http://canjs.com/).\n\n\"MVVM\n\nThe introduction of a strong ViewModel has some key advantages for maintaining large applications:\n\n * **Decouples the presentation from its business logic** - A ViewModel is essentially an object and methods representing the state of a View. This separation of concerns enables simple, dumb HTML-based Views containing minimal logic, while the ViewModel manages the complexities of application logic.\n * **Enables designer/developer cooperation** - Because the view is stripped of code and application logic, designers can safely and comfortably change the View without fear of breaking things.\n * **Enables easier [testing](#section=section_ComprehensiveTesting)** - ViewModels can be unit tested easily. Because they represent the view's state without any knowledge of the DOM, they provide a simple interface for testing.\n\n#### How it works\n\nThe following video introduces MVVM in DoneJS, focusing on the strength of the ViewModel with an example.\n\n
\n\nDoneJS has a uniquely strong ViewModel layer compared to other frameworks. We'll discuss how it works and compare it to other frameworks.\n\n\n##### MVVM overview\n\n**Models** in DoneJS are responsible for loading data from the server. They can be reused across ViewModels. They often perform data validation and sanitization logic. Their main function is to represent data sent back from a server. Models use intelligent set logic that enables [real time](#section=section_RealTimeConnected) integration and [caching](#section=section_CachingandMinimalDataRequests) techniques.\n\n**Views** in DoneJS are templates. Specifically, templates that use handlebars syntax, but with data bindings and rewritten for better performance. Handlebars templates are designed to be logic-less.\n\n**ViewModels** will be covered in detail below.\n\n##### Independent ViewModels\n\nThe first reason DoneJS ViewModels are unique is their independence. ViewModels and Views are completely decoupled, and can be developed completely isolated from a template.\n\nFor example, here's a typical ViewModel, which is often defined in its own separate file like `viewmodel.js` and exported as its own module:\n\n```\nexport const ViewModel = Map.extend({\n define: {\n fullName: {\n get () {\n return this.attr(\"first\") + \" \" + this.attr(\"last\");\n }\n }\n }\n})\n```\n\nThe template (view) lives in its own file, so a designer could easily modify it without touching any JavaScript. This template renders the ViewModel property from above:\n\n```\n
{{fullName}}
\n```\n\nA [custom HTML element](#section=section_CustomHTMLElements), also known as a component, would be used to tie these layers together:\n\n```\nimport Component from 'can/component/';\nimport ViewModel from \"./viewmodel\";\nimport template from './template.stache!';\n\nComponent.extend({\n tag: 'my-component',\n viewModel: ViewModel,\n template\n});\n```\n\nThe ViewModel is defined as its own module and exported as an ES6 module, so it can be imported into a unit test, instantiated, and tested in isolation from the DOM:\n\n```\nimport ViewModel from \"./viewmodel\";\n\nQUnit.test('fullName works', function() {\n var vm = new ViewModel();\n vm.attr('first', 'John');\n vm.attr('last', 'Doe');\n QUnit.equal(vm.attr('fullName'), 'John Doe');\n});\n```\n\nIn other frameworks, ViewModels don't enjoy this level of independence. Every React class has a render function, which is essentially a template, so the View, ViewModel, and component definition are typically part of the same module. Every Angular directive is a ViewModel. In DoneJS, separating the ViewModel, template, and custom element is encouraged, making each module more decoupled and easier to unit test.\n\n##### Powerful observable data layer\n\nA powerful observable data layer binds the layers together with very minimal code.\n\nDoneJS supports the following features:\n\n1. **Direct observable objects** - changes to a property in an object or array immediately and synchronously notify any event listeners.\n\n1. **Computed properties** - ViewModels can define properties that depend on other properties, and they'll automatically recompute only when their dependent properties change.\n\n1. **Data bound templates** - templates bind to property changes and update the DOM as needed.\n\nIn the simple ViewModel example above, `fullName`'s value depends on `first` and `last`. If something in the application changes `first`, `fullName` will recompute.\n\n```\nexport const ViewModel = Map.extend({\n define: {\n fullName: {\n get () {\n return this.attr(\"first\") + \" \" + this.attr(\"last\");\n }\n }\n }\n})\n```\n\n`fullName` is data bound to the view that renders it:\n\n```\n
{{fullName}}
\n```\n\nIf `first` is changed:\n\n```\nviewModel.attr('first', 'Jane');\n```\n\n`fullName` recomputes, then the DOM automatically changes to reflect the new value.\n\nThe interplay of these layers provides amazing power to developers. ViewModels express complex relationships between data, without regard to its display. Views express properties from the ViewModel, without regard to how the properties are computed. The app then comes alive with rich functionality.\n\nWithout automatic ties connecting these layers, achieving the same `fullName` functionality would require more code explicitly performing these steps. There would need to be communication between layers, removing the isolation achieved above. Any change to `first` would need to notify ViewModel's `fullName` of a change. Any change to `fullName` would need to tell the view to re-render itself. These dependencies grow and quickly lead to unmaintainable code.\n\nIn Angular, there are no direct observables. It uses dirty checking with regular JavaScript objects, which means at the end of the current $digest cycle, it will run an algorithm that determines what data has changed. This has performance drawbacks, as well as making it harder to write simple unit tests.\n\nIn React, there is no observable data layer. You could define a `fullName` like we showed above, but it would be recomputed every time `render` is called, whether or not it has changed. Though it's possible to isolate and unit test its ViewModel, its not quite set up to make this easy.\n\n##### More information\n\nTo learn more:\n\n * Models - read about [can.connect](http://connect.canjs.com/) and [can.Map](http://canjs.com/docs/can.Map.html)\n * Computed properties - read about [can.compute](http://canjs.com/docs/can.compute.html)\n * Observable data layer - read about [can.Map](http://canjs.com/docs/can.Map.html) and [can.List](http://canjs.com/docs/can.List.html)\n * ViewModels - read about [can.component](http://canjs.com/docs/can.Component.html), [can.Component.viewModel](http://canjs.com/docs/can.Component.prototype.viewModel.html), and [can.Map.define](http://canjs.com/docs/can.Map.prototype.define.html)\n * Views - read about [can.stache](http://canjs.com/docs/can.stache.html)\n * [Create a unit tested ViewModel](./place-my-order.html#section=section_Creatingaunit_testedviewmodel) in the in depth guide\n\n_The MVVM architecture in DoneJS is provided by [CanJS](http://canjs.com/)._\n\n### Hot Module Swapping\n\nGetting and staying in [flow](https://en.wikipedia.org/wiki/Flow_(psychology)) is critical while writing complex apps. In DoneJS, whenever you change JavaScript, CSS, or a template file, the change is automatically reflected in your browser, without a browser refresh.\n\n
\n
\n \n
\n
\n\n#### How it works\n\nLive reload servers generally watch for file changes and force your browser window to refresh. DoneJS doesn’t refresh the page, it re-imports modules that are marked as dirty, in real-time.\n\nThe correct terminology is actually [hot swapping](https://en.wikipedia.org/wiki/Hot_swapping), not live reload. Regardless of what it's called, the result is a blazing fast development experience.\n\nThere is no configuration needed to enable this feature. Just start the dev server and begin:\n\n```\ndonejs develop\n```\n\n
\n
You spend less time waiting for refreshes and builds,
\n \n \n
\n\nView the Documentation\n\n_Live reload is a feature of [StealJS](http://stealjs.com/)._\n\n\n### Generators\n\nDoneJS generators help you kickstart new projects and components. They'll save you time, eliminating boilerplate by scaffolding a working project, component, or module.\n\nGenerator templates set up many of the best practices and features discussed in the rest of this page, without you even realizing it.\n\n#### How it works\n\nThe DoneJS generator uses Yeoman to bootstrap your application, component, or model.\n\nThere are four generators by default (and you can easily create your own).\n\n##### Project generator\n\nFrom the command line, run:\n\n```\ndonejs add app\n```\n\nYou'll be prompted for a project name, source folder, and other setup information. DoneJS' project dependencies will be installed, like StealJS and CanJS. In the folder that was created, you'll see:\n\n```\n├── .yo-rc.json\n├── build.js\n├── development.html\n├── documentjs.json\n├── package.json\n├── production.html\n├── readme.md\n├── src/\n| ├── app.js\n| ├── index.stache\n| ├── models/\n| | ├── fixtures\n| | | ├── fixtures.js\n| | ├── test.js\n| ├── styles.less\n| ├── test.html\n| ├── test/\n| | ├── test.js\n| | ├── functional.js\n├── node_modules/\n```\n\nYou're now a command away from running application wide tests, generating documentation, and running a build. Start your server with `donejs develop`, open your browser, and you'll see a functioning, server-side rendered hello world page.\n\n##### Modlet component generator\n\nTo create a [component](http://canjs.com/docs/can.Component.html) organized with the [modlet](#section_Modlets) file organization pattern:\n\n```\ndonejs add component \n```\n\nIt will create the following files:\n\n\n```\nrestaurant/\n├── list/\n| ├── list.html\n| ├── list.js\n| ├── list.less\n| ├── list.md\n| ├── list.stache\n| ├── list_test.js\n| ├── test.html\n```\n\nThis folder contains everything a properly maintained component needs: a working demo page, a basic test, and documentation placeholder markdown file.\n\n##### Simple component generator\n\nFor simple, standalone components:\n\n```\ndonejs add component .component \n```\n\nWhich will generate a working component in a single file.\n\n##### Model generator\n\nTo create a new [model](http://connect.canjs.com/doc/can-connect%7Ccan%7Csuper-map.html):\n\n```\ndonejs add supermodel \n```\n\nThis will create:\n\n - a working model in the application's `models` folder\n - a working fixture file for that model\n - a working test, and add the test as a dependency for the application's model test\n\n
\n
You spend less time setting up your app,
\n
...and more time searching for carrots.
\n \n
\n\nView the Documentation\nView the Guide\n\n_Generators are provided by the [Generator DoneJS](https://github.com/donejs/generator-donejs) project with additional support via the [donejs-cli](https://github.com/donejs/cli) project_\n\n", + "description": " \nLearn about the features that will help you get your app done.\n\n### All-in-one stack\n\nDoneJS offers everything you need to build a modern web app. It comes with a module loader, build system, MVVM utilities, full testing layer, documentation generator, server side rendering utilities, a data layer, and more. Its completeness is itself a feature.\n\nThere's no mixing and matching pieces of your stack. Just `npm install` and get started.\n\nChoosing a modern stack is not at all simple or straightforward.\n\n1. *What types of tools do you want?* Server-side rendering? What is a virtual DOM? Do I need one? MVVM or Flux? Should I set up testing infrastructure? Documentation?\n\n2. *Choose all your pieces.* The good news is, you have [many choices](http://microjs.com/#). The bad news is, you have many choices. React, Angular, or Backbone? Require.js, browserify, or jspm? Jasmine or QUnit? What tool will run my tests?\n\n3. *Finally, you have to make sure your chosen tools work together effectively.* Does require.js work well with Angular? Does Karma work with Browserify? What about React and Babel?\n\nDoneJS gives you a full solution. It's our mission to eliminate any ambiguity around choosing technology for building an app, so you spend less time tinkering with your stack, and more time actually building your app.\n\nAnd as we've proven [over the last 8 years](/About.html#section=section_Evolve), we'll keep updating the stack as the state of the art evolves over time.\n\n### Integrated layers\n\nJust like Apple integrates the hardware and software for its devices, DoneJS integrates different technologies in a way that creates unique advantages that you can only get from using an integrated solution.\n\n#### Cross-layer features\n\nDoneJS makes it easier to do things that are not possible, or at best DIY, with competitor frameworks, by spanning technology layers. Here are a couple examples:\n\n##### 1. [Server-side rendering](#section=section_ServerSideRendered__Howitworks__PreppingyourappforSSR)\n\nServer-side rendering (SSR), which you can read about in more detail in its [section](#section_Server_SideRendered) below, spans many layers to make setup and integration simple.\n\nIt uses hooks in data components to automatically notify the server to delay rendering, [hot module swapping](#section=section_HotModuleSwapping) automatically integrates (no need to restart the server while developing), data is collected in an [inline cache](#section=section_CachingandMinimalDataRequests__Howitworks__Inlinecache) automatically and used to prevent duplicate AJAX requests. Support for these features is only possible because of code that spans layers, including can-connect, can-ssr, CanJS, and StealJS.\n\nBy contrast, React supports SSR, but you're left to your own devices to support delaying rendering, hot module swapping, and inline caching.\n\n##### 2. [Progressive enhancement](#section=section_ProgressiveLoading__Howitworks)\n\nYou can mark a section of your template to be progressively loaded by wrapping it with ``, like:\n\n```\n\n \n\n```\n\nand then running `donejs build`.\n\n`` has hooks that notify the build time algorithm to create a bundle for this template fragment and its dependencies. This feature spans StealJS, steal-build, CanJS, and done-cli.\n\n#### Story-level solutions\n\nAnother advantage of the integration between DoneJS' parts is the ability to solve development problems on the level of [**stories**](http://searchsoftwarequality.techtarget.com/definition/user-story) rather than just features.\n\nSolving a story means a packaged solution to a development problem, where several features across layers converge to solve the problem from start to finish. Here are several examples of stories that DoneJS solves:\n\n1. [Modular workflow](section=section_NPMPackages__Howitworks__Modularworkflow) - DoneJS makes it possible for teams to design and share components easily. Starting with [generators](#section=section_Generators), users can create [modlets](#section=section_Modlets) that encapsulate everything a [custom elements](#section=section_CustomHTMLElements) needs, easily add [documentation](#section=section_Documentation) and [testing](#section=section_ComprehensiveTesting), then use [NPM import and export](#section=section_NPMPackages) to easily share the modules with other developers, no matter what module format they're using.\n\n2. [Performance](#section=section_PerformanceFeatures) - DoneJS was designed from the start to solve the performance story, packaging [server-side rendering](#section=section_ServerSideRendered), [progressive loading](#section=section_ProgressiveLoading), [worker thread rendering](#section=section_WorkerThreadRendering), [data layer caching](#section=section_CachingandMinimalDataRequests), and more, all under one roof.\n\n3. [Maintainability](#section=section_Maintainabilityfeatures) - [testing](#section=section_ComprehensiveTesting), [docs](#section=section_Documentation), [MVVM](#section=section_MVVMArchitecture)\n\n4. Developer efficiency - [zero-config NPM imports](#section=section_NPMPackages), [hot module swapping](#section=section_HotModuleSwapping), [ES6 support](#section=section_ES6Modules)\n\n### Feature comparison\n\n
\n
\n
SOLUTION LEGEND
\n
    \n
  • \n \n
    EASY
    \n
  • \n
  • \n \n
    GOOD
    \n
  • \n
  • \n \n
    DIFFICULT
    \n
  • \n
  • \n \n
    THIRD-PARTY
    \n
  • \n
  • \n \n
    NO
    \n
  • \n
\n
\n
\n
\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
FEATURES
\n \n \n \n \n
\n \n
\n
\n
manual setup and lacks most of the features/support DoneJS has.\" title=\"Requires some manual setup and lacks most of the features/support DoneJS has.\">\n \n
\n
\n \n \n \n \n \n \n \n
\n \n \n \n \n \n \n \n
\n \n \n \n \n
\n \n
\n
\n \n
\n \n \n \n \n \n \n
\n \n
\n
\n \n \n \n \n \n \n \n
\n \n \n \n \n
\n \n
\n
\n
\n \n
\n
\n \n \n \n \n
\n \n
\n
\n \n
\n \n \n \n \n
\n \n
\n
\n
\n \n
\n
\n \n \n \n \n
\n \n
\n
\n
\n \n
\n
\n \n \n
\n \n
\n
\n
\n \n
\n
\n
\n \n \n
\n
\n \n \n \n \n \n \n \n
\n \n \n \n \n \n \n \n
\n \n \n \n \n \n \n \n
\n \n \n \n \n
\n \n
\n
\n
\n \n
\n
\n \n \n \n \n \n \n \n
\n \n \n \n \n
\n \n
\n
\n
\n \n
\n
\n \n \n \n \n \n \n
\n \n
\n
\n \n \n \n \n \n \n \n
\n
\n
\n
\n\n", "name": "Features", "type": "page", "parent": "DoneJS", @@ -70,7 +70,7 @@ "comment": " " }, "donejs": { - "body": "
\n
\n
\n
\n
\n \n \"Est.\n \n

Your App. Done.

\n

DoneJS is an open source JavaScript framework that makes it easy to build high performance, real-time web and mobile applications.

\n \n
\n
\n \n
\n
\n

Ready to install DoneJS?

\n \n

Get Started

\n\n
\n
\n
\n
\n

Ready to install DoneJS?

\n \n
\n
\n

Get Started

\n \n
\n
\n
\n \n
\n
\n\n
\n
\n \n

Improved App Usability

\n

DoneJS is used to make beautiful, real-time user interfaces that can be exported to run on every platform.

\n

Take our example app for a spin:

\n
\n
\n
\n \n
\n
\n \n
\n \n \n
\n

Learn how to build this in our in-depth guide!

\n

More ways DoneJS is better for users:

\n

\n iOS, Android, and Desktop Builds | \n Supports All Browsers, even IE8 | \n Real Time Connected | \n Pretty URL’s with Pushstate\n

\n
\n
\n\n
\n \n
\n
\n

Better Performance

\n

DoneJS is configured for maximum performance right out of the box.

\n

Scroll the graph to see how it works:

\n
\n
\n
\n
\n
\n \n
\n
\n
\n \n
\n
\n
\n
\n

More ways DoneJS improves app performance:

\n

\n Server Side Rendered (Isomorphic) | \n Progressive Loading | \n Minimal Data Requests | \n Minimal DOM Updates | \n Worker Thread Rendering | \n Deploy to a CDN\n

\n
\n
\n
\n
\n

Better Performance

\n

DoneJS is configured for maximum performance right out of the box.

\n

Hover over the graph to see how it works:

\n
\n
\n
\n
\n
\n
\n
\n \n \n \n \n
\n \n \n
\n
\n \n \n
\n
\n
\n

More ways DoneJS improves app performance:

\n

\n Server Side Rendered (Isomorphic) | \n Progressive Loading | \n Minimal Data Requests | \n Minimal DOM Updates | \n Worker Thread Rendering | \n Deploy to a CDN\n

\n
\n
\n\n
\n
\n \n

More Maintainable

\n

DoneJS helps developers get things done quickly with an eye toward maintenance.

\n
\n
\n \n
\n

MVVM Architecture

\n

DoneJS applications are architecturally Model-View-ViewModel, with a uniquely powerful and isolated ViewModel.

\n Learn More\n
\n
\n
\n \n
\n

Comprehensive Testing

\n

Comprehensive tools for the entire testing lifecycle that make writing, running, and maintaining tests intuitive and easy.

\n Learn More\n
\n
\n
\n
\n
\n \n
\n

NPM Packages and Custom HTML Elements

\n

Split your app into reusable custom HTML elements, and easily share and consume them as NPM modules.

\n NPM Packages\n Custom Elements\n
\n
\n
\n \n
\n

Continuous Integration and Deployment

\n

Run tests on every commit to detect problems early. Automate deployment to release early and often.

\n Learn More\n
\n
\n
\n
\n
\n \n
\n

Hot Module Swapping

\n

Changes to JavaScript, CSS, or template files are automatically reflected in your browser, without a refresh.

\n Learn More\n
\n
\n
\n \n
\n

Documentation

\n

Generate a multi-versioned, browsable documentation website from inline code comments.

\n Learn More\n
\n
\n
\n

More ways DoneJS helps developers do their jobs

\n

\n Comprehensive Testing | \n Hot Module Swapping | \n Documentation | \n NPM Packages | \n Continuous Integration and Deployment | \n ES6 Modules | \n Modlets | \n Custom HTML Elements | \n MVVM Architecture | \n Generators\n

\n\n
\n
\n\n
\n
\n

Community

\n

We’re always here to help, and we’d love to hear from you.
Here are some links to help you out.

\n

\n If you’re looking for help the best place to start is the forums or our Gitter chatroom.\n

\n
\n
\n
\n

Help

\n

Gitter

\n

Forum

\n

Stack Overflow

\n
\n
\n

Keep in Touch

\n

Twitter

\n

Youtube

\n

Blog

\n\n
\n
\n

Contribute

\n

Github

\n

Submit Issues

\n
\n
\n
\n
\n
\n", + "body": "
\n
\n
\n
\n
\n \n \"Est.\n \n

Your App. Done.

\n

DoneJS is an open source JavaScript framework that makes it easy to build high performance, real-time web and mobile applications.

\n \n
\n
\n \n
\n
\n

Ready to install DoneJS?

\n \n

Get Started

\n\n
\n
\n
\n
\n

Ready to install DoneJS?

\n \n
\n
\n

Get Started

\n \n
\n
\n
\n \n
\n
\n\n
\n
\n \n

Improved App Usability

\n

DoneJS is used to make beautiful, real-time user interfaces that can be exported to run on every platform.

\n

Take our example app for a spin:

\n
\n
\n
\n \n
\n
\n \n
\n \n \n
\n

Learn how to build this in our in-depth guide!

\n

More ways DoneJS is better for users:

\n

\n iOS, Android, and Desktop Builds | \n Supports All Browsers, even IE8 | \n Real Time Connected | \n Pretty URL’s with Pushstate\n

\n
\n
\n\n
\n \n
\n
\n

Better Performance

\n

DoneJS is configured for maximum performance right out of the box.

\n

Scroll the graph to see how it works:

\n
\n
\n
\n
\n
\n \n
\n
\n
\n \n
\n
\n
\n
\n

More ways DoneJS improves app performance:

\n

\n Server Side Rendered (Isomorphic) | \n Progressive Loading | \n Minimal Data Requests | \n Minimal DOM Updates | \n Worker Thread Rendering | \n Deploy to a CDN\n

\n
\n
\n
\n
\n

Better Performance

\n

DoneJS is configured for maximum performance right out of the box.

\n

Hover over the graph to see how it works:

\n
\n
\n
\n
\n
\n
\n
\n \n \n \n \n
\n \n \n
\n
\n \n \n
\n
\n
\n

More ways DoneJS improves app performance:

\n

\n Server Side Rendered (Isomorphic) | \n Progressive Loading | \n Minimal Data Requests | \n Minimal DOM Updates | \n Worker Thread Rendering | \n Deploy to a CDN\n

\n
\n
\n\n
\n
\n \n

More Maintainable

\n

DoneJS helps developers get things done quickly with an eye toward maintenance.

\n
\n
\n \n
\n

MVVM Architecture

\n

DoneJS applications are architecturally Model-View-ViewModel, with a uniquely powerful and isolated ViewModel.

\n Learn More\n
\n
\n
\n \n
\n

Comprehensive Testing

\n

Comprehensive tools for the entire testing lifecycle that make writing, running, and maintaining tests intuitive and easy.

\n Learn More\n
\n
\n
\n
\n
\n \n
\n

NPM Packages and Custom HTML Elements

\n

Split your app into reusable custom HTML elements, and easily share and consume them as NPM modules.

\n NPM Packages\n Custom Elements\n
\n
\n
\n \n
\n

Continuous Integration and Deployment

\n

Run tests on every commit to detect problems early. Automate deployment to release early and often.

\n Learn More\n
\n
\n
\n
\n
\n \n
\n

Hot Module Swapping

\n

Changes to JavaScript, CSS, or template files are automatically reflected in your browser, without a refresh.

\n Learn More\n
\n
\n
\n \n
\n

Documentation

\n

Generate a multi-versioned, browsable documentation website from inline code comments.

\n Learn More\n
\n
\n
\n

More ways DoneJS helps developers do their jobs

\n

\n Comprehensive Testing | \n Hot Module Swapping | \n Documentation | \n NPM Packages | \n Continuous Integration and Deployment | \n ES6 Modules | \n Modlets | \n Custom HTML Elements | \n MVVM Architecture | \n Generators\n

\n\n
\n
\n\n
\n
\n

Community

\n

We’re always here to help, and we’d love to hear from you.
Here are some links to help you out.

\n

\n If you’re looking for help the best place to start is the forums or our Gitter chatroom.\n

\n
\n
\n
\n

Help

\n

Gitter

\n

Forum

\n

Stack Overflow

\n
\n
\n

Keep in Touch

\n

Twitter

\n

Youtube

\n

Blog

\n\n
\n
\n

Contribute

\n

Github

\n

Submit Issues

\n
\n
\n
\n
\n
\n", "type": "template", "name": "donejs" }, @@ -91,30 +91,14 @@ }, "comment": " " }, - "Guides": { - "src": { - "path": "docs/guides/guides.md" - }, - "body": "\n## [Quick start: donejs-chat](/Guide.html)\n\n\nIn the [quick start guide](/Guide.html), we will build a small chat application - [http://chat.donejs.com/](http://chat.donejs.com/). You'll learn about:\n\n- Hot Module Swapping\n- Server-side rendering\n- Progressive loading\n- Real time connections\n- Building and deploying to a CDN.\n- Builds to Codova (mobile) and NW.js (desktop).\n\n## [In-depth: place-my-order](/place-my-order.html)\n\n\n\nIn the [place-my-order guide](/place-my-order.html), we will go into detail, creating [http://place-my-order.com](http://place-my-order.com), a restaurant menu order application. You'll learn everything covered in the \"Quick start\", plus more:\n\n- MVVM architecture\n- Testing\n- Nested routing\n- Continuous integration and continuous deployment\n- Documentation\n\n## [Creating a plugin](/plugin.html)\n\n\n\nIn the [plugin guide](/plugin.html), we will create a reusable number input widget using [Bootstrap](http://getbootstrap.com) styles. We will cover:\n\n- Create the project on GitHub\n- Initialize the repository as a new DoneJS plugin\n- Set up continuous integration with Travis CI\n- Start development mode\n- Implement the component functionality and tests\n- Make a pull request to the repository\n- Make a build\n- Publish to NPM\n- Use the plugin in other projects\n\n## [Example App: Bitballs](/bitballs.html)\n\n\n\nIn this guide, you'll learn how [Bitballs](http://bitballs.herokuapp.com) - a charity basketball tournament management application - works.\nSpecifically, this guide will walk through the implementation of the following behaviors or functionality:\n\n - Registration, login, user sessions, and access rights.\n - Handling relationships between model types.\n - Setup node services and server-side rendering on the same process.\n - How to turn off parts of the app that should not be server-side rendered.\n\n", - "description": "DoneJS is about getting your application ... __done__ ... so you can spend time with your friends and family. To demonstrate how easy it is to make something amazing with all the bells and\nwhistles a modern developer needs, we created the following guides.\n\n\n", - "name": "Guides", - "type": "page", - "parent": "DoneJS", - "hideSidebar": true, - "outline": { - "depth": 2, - "tag": "ol" - }, - "comment": " " - }, - "Guide": { + "generator": { "src": { - "path": "docs/guides/guide.md" + "path": "docs/guides/generator.md" }, - "body": "\n## Setup\n\nIn this section, we will install DoneJS and generate a new application.\n\n### Install DoneJS\n\nTo get started, let's install the DoneJS command line utility globally:\n\n```\nnpm install -g donejs\n```\n\n### Generate the application\n\nThen we'll create a new DoneJS application called `donejs-chat`:\n\n```\ndonejs add app donejs-chat\n```\n\nThis will create a new folder called `donejs-chat` and in it generate our application.\n\nThe initialization process will ask questions like the name of your application, the source folder, etc. We'll answer these with the default settings by hitting enter.\n\n\"donejs\n\nThis will install all of DoneJS's dependencies, including the following:\n\n- [StealJS](http://stealjs.com) - ES6, CJS, and AMD module loader and builder\n- [CanJS](http://canjs.com) - Custom elements and Model-View-ViewModel utilities\n- [jQuery](http://jquery.com) - DOM helpers\n- [jQuery++](http://jquerypp.com) - Extended DOM helpers\n- [QUnit](https://qunitjs.com/) - Assertion library (optionally: [Mocha] or [Jasmine])\n- [FuncUnit](http://funcunit.com) - Functional tests\n- [Testee](https://github.com/bitovi/testee) - JavaScript Test runner\n- [DocumentJS](http://documentjs.com) - Documentation\n\n### Turn on development mode\n\nDoneJS comes with its own development server, which hosts your development files and automatically [renders the application on the server](Features.html#section=section_ServerSideRendered). Development mode enables [hot module swapping](Features.html#section=section_HotModuleSwapping), which automatically reloads files in the browser and on the server as they change.\n\nTo start it let's go into the `donejs-chat` application directory:\n\n```\ncd donejs-chat\n```\n\nWe can start development mode by running:\n\n```\ndonejs develop\n```\n\nThe default port is `8080`.\n\nGo to [http://localhost:8080/](localhost:8080) to see our application showing a default homepage.\n\n\"hello\n\n## Adding Bootstrap\n\nDoneJS makes it easy to import other projects that are published on [NPM](https://npmjs.org). In this section we will install and add [Bootstrap](http://getbootstrap.com/) to the page and see DoneJS's [hot module swapping](Features.html#section=section_HotModuleSwapping) in action.\n\n### Install the NPM package\n\nOpen a new terminal window so we can keep the DoneJS development server running. Then, install the [Bootstrap NPM package](https://www.npmjs.com/package/bootstrap) and save it as a dependency of our application like this:\n\n```\nnpm install bootstrap --save\n```\n\n### Add it to the page\n\nTo see hot module swapping in action, let's update the main template to import Bootstrap's LESS file and also add some HTML that uses its styles.\n\nUpdate `src/index.stache` to look like this:\n\n> The highlighted lines have been added or changed.\n\n\n```html\n\n \n {{title}}\n \n \n \n \n \n\n
\n
\n
\n

\n \"DoneJS\n
Chat\n

\n
\n
\n
\n\n {{#switch env.NODE_ENV}}\n {{#case \"production\"}}\n \n {{/case}}\n {{#default}}\n \n {{/default}}\n {{/switch}}\n \n\n\n```\n\nIf you kept your browser window open at [http://localhost:8080/](localhost:8080) you should see the updated styles and content as soon as you save the file.\n\n\"donejs\n\nFeel free to edit the HTML or `src/styles.less` to see how hot module swapping updates the page automatically.\n\n## Routing and components\n\nIn this part we will create our own custom HTML elements - one for the homepage and another to display the chat messages. Then we will create routes to navigate between these two pages.\n\n### Generate custom elements\n\nWe'll use a DoneJS [generator](/Features.html#section=section_Generators) to create custom components. The component generator is run by typing `donejs add component `.\n\nThe homepage custom element (with the HTML tag name `chat-home`) won't be very big or complex, so we'll put everything into a single `.component` file.\n\nTo generate it, run:\n\n```\ndonejs add component home.component chat-home\n```\n\nThe messages component (with the tag `chat-messages`) will be a little more complex, so we'll generate it using the [modlet file pattern](Features.html#section=section_Modlets).\n\n\nNow run:\n\n```\ndonejs add component messages chat-messages\n```\n\n\"chat.donejs.com\"\n\nLater we will update the generated files with the chat messages functionality.\n\n### Navigate between pages\n\n> Routing works a bit differently than other libraries. In other libraries, you might declare routes and map those to controller-like actions. DoneJS application [routes](http://canjs.com/docs/can.route.html) map URL strings (like /user/1) to properties on our application's view-model. In other words, our routes will just be a representation of the application state. To learn more about routing visit the CanJS guide on [Application State and Routing](http://canjs.com/guides/AppStateAndRouting.html).\n\nFirst, let's update `src/home.component` with the original content from the homepage and a link to the chat messages page:\n\n\n```html\n\n \n \n\n\n```\n\n> [`routeUrl`](http://canjs.com/docs/can.stache.helpers.routeUrl.html) is a helper that populates the anchor's href with a URL that sets the application ViewModel's `page` property to `\"chat\"`. The AppViewModel is shown below.\n\nNext, add a link to go back to the homepage from the chat page by updating `src/messages/messages.stache` to:\n\n\n```html\n
Home
\n

{{message}}

\n\n```\n\nThen, add a routing rule for the `page` property in `src/app.js`:\n\n\n```js\nimport Map from \"can/map/\";\nimport route from \"can/route/\";\nimport 'can/map/define/';\nimport 'can/route/pushstate/';\n\nconst AppViewModel = Map.extend({\n define: {\n title: {\n value: 'donejs-chat',\n serialize: false\n }\n }\n});\n\nroute('/:page', { page: 'home' });\n\nexport default AppViewModel;\n\n```\n\n### Switch between pages\n\nFinally, we'll glue both components together as separate pages in `src/index.stache`. This is done by adding dynamic imports for the `home.component` and `messages/` components and showing each import based on the `page` property.\n\nUpdate `src/index.stache` to:\n\n\n```html\n\n \n {{title}}\n \n \n \n \n \n\n
\n
\n
\n {{#eq page 'chat'}}\n \n {{#if isPending}}\n Loading...\n {{else}}\n \n {{/if}}\n \n {{else}}\n \n {{#if isPending}}\n Loading...\n {{else}}\n \n {{/if}}\n \n {{/eq}}\n
\n
\n
\n\n {{#switch env.NODE_ENV}}\n {{#case \"production\"}}\n \n {{/case}}\n {{#default}}\n \n {{/default}}\n {{/switch}}\n \n\n\n```\n\nNow each component is being dynamically loaded while navigating between the home and messages page. You should see the changes already in your browser.\n\n\"chat.donejs.com\"\n\nAlso, everything is [rendered on the server](Features.html#section=section_ServerSideRendered). If you reload the homepage at [localhost:8080](http://localhost:8080) you'll see the page's content right away, while the JavaScript is loading in the background. Viewing the source will show the dynamically inserted styles and the corresponding HTML.\n\n\"chat.donejs.com\"\n\n\n## Homepage\n\nNow that we can navigate between pages, we will finish implementing their functionality, starting with the homepage.\n\n\n### Install bit-tabs\n\nOn the homepage, let's install and add [bit-tabs](https://github.com/bitovi-components/bit-tabs), a simple declarative tabs widget.\n\nRun:\n\n```\nnpm install bit-tabs --save\n```\n\n### Update the page\n\nThen, import the unstyled custom elements from `bit-tabs/unstyled` (unstyled because we will use Bootstrap's styles) and add `` and `` elements to the template.\n\nUpdate `src/home.component` to:\n\n\n```html\n\n \n \n\n\n```\n\nYou'll notice tabs appear in the browser:\n\n\"chat.donejs.com\"\n\n## Messages page\n\nIn this section we add live chat functionality to the messages page. We'll need to:\n\n * Create a messages model that connects to a RESTful API.\n * Add the ability to retrieve and list messages and create new messages.\n * Make the message list receive real-time updates from other clients.\n\n### Generate Message model\n\nTo load messages from the server, we will use [can-connect's supermodel](http://connect.canjs.com/doc/can-connect%7Ccan%7Csuper-map.html).\n\nGenerate a `message` supermodel like this:\n\n```\ndonejs add supermodel message\n```\n\nWhen asked for the URL endpoint, set it to our remote RESTful API at `http://chat.donejs.com/api/messages`. The other questions can be answered with the default by hitting enter.\n\n\"model\n\n### Use the connection\n\nThe generated file is all that is needed to connect to our RESTful API. Use it by importing it and requesting a list of all messages with the `` custom element.\n\nUpdate `src/messages/messages.stache` to:\n\n\n```html\n\n
Home
\n\n\n {{#each ./value}}\n
\n

{{name}}

\n

{{body}}

\n
\n {{else}}\n
\n

No messages

\n
\n {{/each}}\n
\n\n```\n\nIf you open [localhost:8080/chat](http://localhost:8080/chat), you will see a list of messages from the server or the \"No message\" text.\n\n\"chat.donejs.com\"\n\n### Create messages\n\nNow let's add the form to create new messages. The form two-way binds the `name` and `body` properties to the component's view-model and calls `send()` when hitting the enter key in the message input.\n\nUpdate `src/messages/messages.stache` to look like this:\n\n\n```html\n\n
Home
\n\n\n {{#each ./value}}\n
\n

{{name}}

\n

{{body}}

\n
\n {{else}}\n
\n

No messages

\n
\n {{/each}}\n
\n\n
\n
\n \n
\n
\n \n
\n
\n \n
\n
\n\n```\n\nNext we have to implement the `send()` method. Update `src/messages/messages.js` to this:\n\n\n```js\nimport Component from 'can/component/';\nimport Map from 'can/map/';\nimport 'can/map/define/';\nimport './messages.less!';\nimport template from './messages.stache!';\nimport Message from '../models/message';\n\nexport const ViewModel = Map.extend({\n send(event) {\n event.preventDefault();\n\n new Message({\n name: this.attr('name'),\n body: this.attr('body')\n }).save().then(msg => this.attr('body', ''));\n }\n});\n\nexport default Component.extend({\n tag: 'chat-messages',\n viewModel: ViewModel,\n template\n});\n\n```\n\nThe `send()` method takes the `name` and `message` properties from the view-model and creates a `Message` instance, saving it to the server. Once saved successfully, it sets the message to an empty string to reset the input field.\n\nYou can now enter your name and a message! It will automatically appear in our messages list.\n\n\"chat.donejs.com\"\n\nIn fact, all lists that are related to that model will be updated automatically whenever there is new, modified, or deleted data. [can-connect](http://connect.canjs.com/) automatically manages the lists, while also providing [caching and minimized data requests](Features.html#section=section_Cachingandminimaldatarequests).\n\nYou can see from your console that the localStorage cache is already populated with data:\n\n\"chat.donejs.com\"\n\n### Enable a real-time connection\n\nRight now our chat's messages update automatically with our own messages, but not with messages from other clients. The API server ([chat.donejs.com/api/messages](http://chat.donejs.com/api/messages)) provides a [Socket.io](http://socket.io/) server that sends out real-time updates for new, updated and deleted chat messages.\n\nTo connect to it, first we'll install a socket.io connector, by running:\n\n```\nnpm install steal-socket.io@2 --save\n```\n\nUpdate `src/models/message.js` to:\n\n\n```js\nimport can from 'can';\nimport superMap from 'can-connect/can/super-map/';\nimport tag from 'can-connect/can/tag/';\nimport 'can/map/define/define';\nimport io from 'steal-socket.io';\n\nexport const Message = can.Map.extend({\n define: {}\n});\n\nMessage.List = can.List.extend({\n Map: Message\n}, {});\n\nexport const messageConnection = superMap({\n url: 'http://chat.donejs.com/api/messages',\n idProp: 'id',\n Map: Message,\n List: Message.List,\n name: 'message'\n});\n\ntag('message-model', messageConnection);\n\nconst socket = io('http://chat.donejs.com');\n\nsocket.on('messages created',\n message => messageConnection.createInstance(message));\nsocket.on('messages updated',\n message => messageConnection.updateInstance(message));\nsocket.on('messages removed',\n message => messageConnection.destroyInstance(message));\n\nexport default Message;\n\n```\n\nThis will listen to `messages ` events sent by the server and tell the connection to update all active lists of messages accordingly. Try opening another browser window to see receiving messages in real-time.\n\n\"two\n\n## Production build\n\nNow that we implemented the complete chat functionality we can get our application ready for production.\n\n### Run build\n\nWe can find the build configuration in `build.js` in the application folder.\n\nEverything is already set up, so we can simply make a build by running:\n\n```\ndonejs build\n```\n\nThe optimized bundles that load your JavaScript and CSS as fast as possible are sent to the `dist/` folder.\n\n### Turn on production\n\nTo test the production build, close the current server (with `CTRL + C`) and start it with the environment (`NODE_ENV`) set to `production`:\n\n```\nNODE_ENV=production donejs start\n```\n\nIf you're using Windows, you must first set the environmental variable:\n\n1. For Windows **command prompt** you set with `set NODE_ENV=production`\n1. For Windows **Powershell** you set it with `$env:NODE_ENV=\"production\"`\n\nThen run your application with `donejs start`.\n\nIf we now open [localhost:8080](http://localhost:8080/) again we can see the production bundles being loaded in the network tab of the developer tools.\n\n\"two\n\nAll DoneJS projects are extremely modular, which is why in development mode, you see 200 or more requests when loading the page (thanks to hot module swapping we only have to make those requests once). In production mode, we can only see about 10 requests and a significantly reduced file-size.\n\n## Deploy\n\nNow that we verified that our application works in production, we can deploy it to the web. In this section, we will use [Firebase](https://www.firebase.com/), a service that provides static file hosting and [Content Delivery Network](https://en.wikipedia.org/wiki/Content_delivery_network) (CDN) support, to automatically deploy and serve our application's static assets from a CDN.\n\n### Set up Firebase\n\nSign up for free at [Firebase](https://firebase.google.com/). After you have an account go to [Firebase console](https://console.firebase.google.com/) and create an app called `donejs-chat-` where `` is your GitHub username. Write down the name of your app because you'll need it in the next section.\n\n> You'll get an error if your app name is too long, so pick something on the shorter side.\n\nWhen you deploy for the first time it will ask you to authorize, but first we need to configure the project.\n\n### Configure DoneJS\n\nNow we can add the Firebase deployment configuration to our `package.json` like this:\n\n```\ndonejs add firebase\n```\n\nWhen prompted, enter the name of the application created when you set up the Firebase app. Before you can deploy your app you need to login and authorize the Firebase tools, which you can do with:\n\n```\nnode_modules/.bin/firebase login\n```\n\nThen we can deploy the application by running:\n\n```\ndonejs build\ndonejs deploy\n```\n\nStatic files are deployed to Firebase.\n\n\"two\n\nAnd verify that the application is loading from the CDN by loading it after running:\n\n```\nNODE_ENV=production donejs start\n```\n\n> If you're using Windows, set the NODE_ENV variable as you did previously in the Production section.\n\nWe should now see our assets being loaded from the Firebase CDN.\n\n\"two\n\n## Desktop and mobile apps\n\nIn the last part of this guide we will make mobile and desktop builds of our chat application, using [Cordova](https://cordova.apache.org/) and [nw.js](http://nwjs.io/).\n\n### Cordova\n\nTo build the application as a Cordova based mobile application, you need to have each platform's SDK installed.\nWe'll be building an iOS app if you are a Mac user, and an Android app if you're a Windows user.\n\nMac users should download XCode from the AppStore and install the `ios-sim` package globally with:\n\n```\nnpm install -g ios-sim\n```\n\nWe will use these tools to create an iOS application that can be tested in the iOS simulator.\n\nWindows users should install the [Android Studio](https://developer.android.com/sdk/index.html), which gives all of the tools we need.\n\nNow we can install the DoneJS Cordova tools with:\n\n```\ndonejs add cordova\n```\n\nDepending on your operating system you can accept most of the defaults, unless you would like to build for Android, which needs to be selected from the list of platforms.\n\nTo run the Cordova build and launch the simulator we can now run:\n\n```\ndonejs build cordova\n```\n\nIf everything went well, we should see the emulator running our application.\n\n\"ios\n\nWindows users will get instructions to download the latest version of the platform and to create a Virtual Device. Follow the instructions and then re-do the build. This will only happen the first time you build for Cordova.\n\n### NW.js\n\nTo set up the desktop build, we have to add it to our application like this:\n\n```\ndonejs add nw\n```\n\nWe can answer most prompts with the default except for the version which needs to be set to the latest **stable version**. Set the version prompt to `0.12.3`.\n\n\"nw\n\nThen we can run the build like this:\n\n```\ndonejs build nw\n```\n\nThe OS X application can be opened with\n\n```\ncd build/donejs-chat/osx64\nopen donejs-chat.app\n```\n\nThe Windows application can be opened with\n\n```\n.\\build\\donejs-chat\\win64\\donejs-chat.exe\n```\n\n\"nw\n\n## What's next?\n\nIn this guide we created a small chat application that connects to a remote API with DoneJS. It has routing between two pages and can send and receive messages in real-time. We built an optimized bundle for production and deployed it to a static file host and CDN. Last, we made builds of the application as a mobile and desktop application.\n\nIf you want to learn more about DoneJS - like how to create more complex custom elements and routes, write and automatically run tests, Continuous Integration and Continuous Deployment - head over to the [place-my-order Guide](./place-my-order.html).\n\n## IE8 Support\n\nThis section is optional. Follow it only if you're interested in making applications that are compatible with IE8.\n\n### Support CORS\n\nSince our application uses cross domain requests we need to make a couple of changes to make it work in IE8 which doesn't support CORS. The first is to create a [jQuery prefilter](http://api.jquery.com/jquery.ajaxprefilter/) so all HTTP requests are marked as being cross domain. Create `src/prefilter.js`:\n\n```js\nimport $ from \"jquery\";\n\n$.ajaxPrefilter(function(options){\n options.crossDomain = true;\n});\n```\n\nNext we need to install [jQuery transport](http://api.jquery.com/jquery.ajaxtransport/) that will perform our cross domain requests in IE8:\n\n```\nnpm install jquery-transport-xdr --save\n```\n\nFinally import both of these modules in your messages model. Change `src/models/message.js` to:\n\n```js\nimport can from 'can';\nimport superMap from 'can-connect/can/super-map/';\nimport tag from 'can-connect/can/tag/';\nimport 'can/map/define/define';\nimport io from 'steal-socket.io';\nimport 'jquery-transport-xdr';\nimport 'donejs-chat/prefilter';\n\nexport const Message = can.Map.extend({\n define: {}\n});\n\nMessage.List = can.List.extend({\n Map: Message\n}, {});\n\nexport const messageConnection = superMap({\n url: 'http://chat.donejs.com/api/messages',\n idProp: 'id',\n Map: Message,\n List: Message.List,\n name: 'message'\n});\n\ntag('message-model', messageConnection);\n\nconst socket = io('http://chat.donejs.com');\n\nsocket.on('messages created',\n order => messageConnection.createInstance(order));\nsocket.on('messages updated',\n order => messageConnection.updateInstance(order));\nsocket.on('messages removed',\n order => messageConnection.destroyInstance(order));\n\nexport default Message;\n```\n\n### Install jQuery 1.x\n\nDoneJS comes with jQuery 2.x by default, but if you need to support IE8 the 1.x branch is necessary. You can switch by installing the right version:\n\n```\nnpm install jquery@1.11.0 --save\n```\n\nUpdate your `build.js` file to make the compiled output work in IE:\n\n```js\nvar buildPromise = stealTools.build({\n config: __dirname + \"/package.json!npm\",\n babelOptions: {\n loose: \"es6.modules\"\n }\n}, {\n bundleAssets: true\n});\n...\n```\n\nAnd rebuild:\n\n```\ndonejs build\n```\n\nThe application will now work in IE8.\n\n", - "description": "In this guide, we will create [chat.donejs.com](http://chat.donejs.com), a small real-time chat application with a homepage showing a tabs widget and a messages page that lets us send and receive messages in real-time: \n\"chat.donejs.com\"\n\nIn the first part of this guide we will install DoneJS, [generate a new application](Features.html#section=section_Generators) and start a server that provides [hot module swapping](Features.html#section=section_HotModuleSwapping) and [server-side rendering](Features.html#section=section_ServerSideRendered). We will then [import Bootstrap from NPM](Features.html#section=section_NPMPackages), create our [own custom HTML elements](Features.html#section=section_CustomHTMLElements) and [set up routing](Features.html#section=section_PrettyURL_swithPushstate) between the homepage and the chat messages page. After that, we will complete both pages by adding a tabs widget to the homepage and the ability to send messages and [receive real-time updates](Features.html#section=section_RealTimeConnected).\n\nIn the final parts of the guide we will make an [optimized, progressively loaded production build](Features.html#section=section_Progressiveloading) and [deploy it to a CDN](Features.html#section=section_DeploytoaCDN). We will conclude with creating a [mobile and desktop](Features.html#section=section_iOS_Android_andDesktopBuilds) version of the application.\n\nIf you run into any problems, let us know [on Gitter](https://gitter.im/donejs/donejs), we're happy to help out.\n\n", - "name": "Guide", - "title": "Quick start guide", + "body": "\nIf you have used `donejs add nw` or `donejs add cordova` to create a [desktop- or mobile version](https://donejs.com/Features.html#section=section_iOS_Android_andDesktopBuilds) of your application you already used a DoneJS generator. Generators are [npm](https://www.npmjs.com/) modules that provide a [Yeoman](http://yeoman.io/) generator that adds functionality to your application.\n\nIn this guide you will create your own version of [donejs-jshint](https://www.npmjs.com/package/donejs-jshint), a DoneJS generator that adds:\n\n- [JSHint](http://jshint.com/), a JavaScript code quality tool\n- An [.editorconfig](http://editorconfig.org/) file which helps text editors and IDEs to define and maintain a consistent coding style.\n\nIt will also update the `npm test` script to run JSHint with our tests. You can find the code in the [donejs-jshint](https://github.com/donejs/donejs-jshint) repository. We can run the generator with:\n\n\n $ donejs add jshint\n\n\nCurrently it will only ask if we want to use spaces or tabs and to overwrite the `package.json` to add the npm scripts for JSHint:\n\n\"DoneJS\n\n> __Note:__ Since `donejs-jshint` already exists we will use `donejs--jshint` with `` being your GitHub username for the remainder of this article. Once published it can then be used as `donejs add -jshint`.\n\n\n## Setting up\n\n### Creating the project on GitHub\n\nWe will use [GitHub](https://github.com) to host the code for the project which makes it easy for others to contribute and to automatically run the tests in [continuous integration](https://en.wikipedia.org/wiki/Continuous_integration) which we will enable later.\n\nIf you don't have an account yet, go to [GitHub](https://github.com/join) to sign up and follow [the help](https://help.github.com/articles/set-up-git/) on how to set it up for the command-line `git`. Once completed, create a new repository from your dashboard.\n\nCalling the repository `donejs--jshint` and initializing it empty (without any of the default files) looks like this:\n\n\"generator-repository\"\n\nAfter creating the repository, clone it into a new folder:\n\n\n $ git clone git@github.com:/donejs--jshint.git\n $ cd donejs--jshint\n\n\n### Initializing the project\n\nTo initialize a new generator you will need DoneJS version 0.9.0+ installed globally. To check your DoneJS version run\n\n\n $ donejs --version\n\n\nTo install DoneJS or to get the latest version run:\n\n\n $ npm install donejs -g \n\n\nIn the `donejs--jshint` folder we can now initialize a new generator, very similar to a new DoneJS application, like this:\n\n\n $ donejs add generator\n\n\nThe generator will ask several question that should be answered as follows:\n\n* For the project name you can just confirm the default by pressing enter\n* For the GitHub username or organization enter the GitHub username where the repository has been created\n* All other fields can also be answered with the default or the information you would like to use\n\nOnce all done, the final prompt looks similar to this:\n\n\"generator-init\"\n\nNow the generator will initialize the default layout and install all its dependencies.\n\n### Setting up Travis CI\n\nWhen the installation has completed, make sure everything got set up properly by running:\n\n\n $ npm test\n\n\nThis will run some basic generator tests and output the result on the console.\n\nThis command can also be used to automatically run the tests on a [continuous integration](https://en.wikipedia.org/wiki/Continuous_integration) server. There are many open source CI servers, the most popular being [Jenkins](https://jenkins-ci.org/), and many hosted solutions like [Travis CI](https://travis-ci.org/).\n\nWe will use Travis CI as our hosted solution because it is free for open source projects. It works with your GitHub account which it will use to sign up. Once signed in, go to `Accounts` (in the dropdown under you name) to enable the `donejs--jshint` repository:\n\n\"generator-travis\"\n\nYou may have to click the *\"Sync account\"* button for the repository to show up. Now, every time we push to GitHub the tests will run automatically. We can do so with our initial commit:\n\n\n $ git add . --all\n $ git commit -am \"Initial commit\"\n $ git push origin master\n\n\nIf you now go `https://travis-ci.org//donejs--jshint/builds` you will see the build running and eventually turn green (which will update the badge that got added in the `readme.md` file).\n\n\n## Adding the configuration files\n\nNow we can add the files that our generator should produce. All file templates will be put in the `default/templates/` folder.\n\n### .jshintrc\n\nFirst, add a `default/templates/.jshintrc` file which contains [options for JSHint](http://jshint.com/docs/options/):\n\n\n {\n \"node\": true,\n \"esnext\": true,\n \"bitwise\": true,\n \"camelcase\": true,\n \"curly\": true,\n \"eqeqeq\": true,\n \"immed\": true,\n \"indent\": 2,\n \"latedef\": \"nofunc\",\n \"newcap\": false,\n \"noarg\": true,\n \"regexp\": true,\n \"undef\": true,\n \"unused\": true,\n \"strict\": false,\n \"trailing\": true,\n \"smarttabs\": true,\n \"white\": false\n }\n\n\n### .editorconfig\n\nNext add a `default/templates/.editorconfig` file like this:\n\n\n ; Unix-style newlines\n [*]\n end_of_line = LF\n indent_style = <%= indent_style %>\n trim_trailing_whitespace = true\n\n\nAll files support [EJS](http://www.embeddedjs.com/) placeholders. Here, `<%= indent_style %>` will be used for the user choice of using whitespaces or tabs. Finally, remove `defaults/templates/file.js` since we won't be using it.\n\n\n## Implementing the generator\n\nFor the most part, DoneJS generators are simply [Yeoman](http://yeoman.io/) generators so everything documented for [writing your own Yeoman generator](http://yeoman.io/authoring/) also applies here. For the user choice of tabs vs. spaces also refer to the chapter about [interacting with the user](http://yeoman.io/authoring/user-interactions.html).\n\n### Adding the generator functionality\n\nOur generator needs to ask if we want to use spaces or tabs and then copy the `.jshintrc` and `.editorconfig` files over to their final destination. We also want to add an `npm run jshint` script to the `package.json` and make sure that JSHint runs during `npm test`. The complete generator at `default/index.js` looks like this:\n\n\n\n var generator = require('yeoman-generator');\n var _ = require('lodash');\n\n module.exports = generator.Base.extend({\n initializing: function () {\n // Read the original package.json\n this.pkg = this.fs.readJSON(\n this.destinationPath('package.json'), {}\n );\n \n // Maintain a list of all files we want to copy over\n this.files = [\n '.editorconfig',\n '.jshintrc'\n ];\n },\n \n prompting: function () {\n var done = this.async();\n\n // Create a prompt setting the `indent_style` property\n // to `tab` or `space`\n this.prompt([{\n type: 'list',\n name: 'indent_style',\n message: 'What indentation style do you want to use?',\n default: 'tab',\n choices: [\n {\n name: 'Tabs',\n value: 'tab'\n },\n {\n name: 'Spaces',\n value: 'space'\n }\n ]\n }], function (answers) {\n this.props = answers;\n done();\n }.bind(this));\n },\n \n writing: function () {\n var pkg = this.pkg;\n \n // Update `package.json` with the `jshint` command\n // and update the `test` script\n pkg.scripts = _.extend(pkg.scripts, {\n test: 'npm run jshint && ' + \n _.get(pkg, 'scripts.test',\n 'echo \"No tests specified\"'),\n jshint: 'jshint ' + \n _.get(pkg, 'system.directories.lib',\n 'src') + \n '/. --config'\n });\n \n // Write to `package.json` and format accordingly\n // This will prompt you to overwrite\n var indent = this.props.index === 'tab' ? '\\t' : ' ';\n this.fs.writeJSON('package.json', pkg, null, indent);\n\n // Install jshint as a development dependency\n this.npmInstall([ 'jshint' ], { saveDev: true});\n \n // Got through every file and copy it\n this.files.forEach(function(file) {\n this.fs.copyTpl(\n this.templatePath(file),\n this.destinationPath(file),\n this.props\n );\n }.bind(this));\n }\n });\n\n\nThat's it. Now we have a fully functional generator and can give it a try in a DoneJS application.\n\n### Manual testing\n\nWhen running `donejs add ` DoneJS will\n\n- Check if `donejs-` is installed locally\n- If not install it from NPM\n- Then run the generator at `default/index.js`\n\nIf we want to test our generator without publishing it to npm first we can link it instead. In the generator folder run:\n\n\n $ npm link\n\n\nThen go into your test DoneJS application directory:\n\n\n $ cd ../place-my-order\n $ npm link donejs--jshint\n\n\nNow we can run\n\n\n $ donejs add -jshint\n\n\n### Writing a unit test\n\nYeoman also comes with some tools for [testing generators](http://yeoman.io/authoring/testing.html). The test we initially ran with `npm test` makes sure that `default/templates/file.js` gets written. Since we deleted that file, update the test at `test/index.js` to verify that it wrote the files we want with the content we expect:\n\n\n var path = require('path');\n var helpers = require('yeoman-test');\n var assert = require('yeoman-assert');\n\n describe('donejs--jshint', function() {\n before(function(done) {\n // Run the generator in a temprorary directory\n helpers.run(path.join(__dirname, '../default'))\n .inTmpDir()\n // Mock the user input by setting\n // `indent_style` to `tab`\n .withPrompts({\n 'indent_style': 'tab'\n }).on('end', done);\n });\n\n // Verify that `.jshintrc` got written\n // and has some content\n it('created .jshintrc', function() {\n assert.file(['.jshintrc']);\n assert.fileContent('.jshintrc',\n /\"latedef\": \"nofunc\"/);\n });\n \n // Verify that `.editorconfig` got written\n // with `indent_style` set to our selection\n it('.editorconfig with indent_style', function() {\n assert.file(['.editorconfig']);\n assert.fileContent('.editorconfig',\n /indent_style = tab/);\n });\n \n // Make sure that `package.json` got updated\n // with the `jshint` npm script\n it('update package.json', function() {\n assert.jsonFileContent('package.json', {\n scripts: {\n jshint: 'jshint src/. --config'\n }\n });\n });\n });\n\n\nNow we can see all tests passing when running:\n\n\n $ npm test\n\n\n\n## Publishing the plugin\n\n### Making a pull request\n\nAlthough we are working on the generator by ourselves for now, [GitHub pull requests](https://help.github.com/articles/using-pull-requests/) are a great way to keep track of our progress and to make sure that all tests are passing. In the plugin folder run:\n\n\n $ git checkout -b generator-functionality\n $ git add . --all\n $ git commit -m \"Implementing JSHint and editorconfig generator\"\n $ git push origin generator-functionality\n\n\nAnd then create a new pull request by going to `https://github.com//donejs--jshint` which will now show an option like this:\n\n\"generator-pr\"\n\nOnce you created the pull request, you will see a `Some checks haven’t completed yet` message that will eventually turn green:\n\n\"generator-pull-request\"\n\nNow you can click the \"Merge pull request\" button. Then in the console, checkout the *master* branch and pull down the latest changes with:\n\n\n $ git checkout master\n $ git pull origin master\n\n\n\n### Publishing to npm\n\nFor others to be able to use your generator via `donejs add ` have to pulish it to [npm](http://npmjs.org). [Create a new account](https://www.npmjs.com/signup) and then log in via\n\n\n $ npm login\n\n\n[Semantic versioning](http://semver.org/) is a great way to communicate new features and breaking changes. The generated plugin already comes with the release scripts to publish new versions according to the `major.minor.patch` schema. In our case to publish an initial version `0.1.0` we can run\n\n\n $ donejs release:minor\n\n\nNow version `0.1.0` of the generator is available and everybody can use it through\n\n\n donejs add -jshint\n\n\n## Show it off\n\nOnce you published your generator, let the world know about it. [Tweet @donejs](https://twitter.com/donejs) and post it in the [DoneJS forums](http://forums.donejs.com/) and the [DoneJS chat](https://gitter.im/donejs/donejs). Those are also great places to get quick help with any questions.\n\n", + "description": "Generators add additional functionality to DoneJS applications. In this guide will create a generator that adds JSHint and an `.editorconfig` file to a DoneJS application. \n", + "name": "generator", + "title": "Creating a generator", "type": "page", "parent": "DoneJS", "hideSidebar": true, @@ -124,14 +108,13 @@ }, "comment": " " }, - "generator": { + "Guides": { "src": { - "path": "docs/guides/generator.md" + "path": "docs/guides/guides.md" }, - "body": "\nIf you have used `donejs add nw` or `donejs add cordova` to create a [desktop- or mobile version](https://donejs.com/Features.html#section=section_iOS_Android_andDesktopBuilds) of your application you already used a DoneJS generator. Generators are [npm](https://www.npmjs.com/) modules that provide a [Yeoman](http://yeoman.io/) generator that adds functionality to your application.\n\nIn this guide you will create your own version of [donejs-jshint](https://www.npmjs.com/package/donejs-jshint), a DoneJS generator that adds:\n\n- [JSHint](http://jshint.com/), a JavaScript code quality tool\n- An [.editorconfig](http://editorconfig.org/) file which helps text editors and IDEs to define and maintain a consistent coding style.\n\nIt will also update the `npm test` script to run JSHint with our tests. You can find the code in the [donejs-jshint](https://github.com/donejs/donejs-jshint) repository. We can run the generator with:\n\n\n $ donejs add jshint\n\n\nCurrently it will only ask if we want to use spaces or tabs and to overwrite the `package.json` to add the npm scripts for JSHint:\n\n\"DoneJS\n\n> __Note:__ Since `donejs-jshint` already exists we will use `donejs--jshint` with `` being your GitHub username for the remainder of this article. Once published it can then be used as `donejs add -jshint`.\n\n\n## Setting up\n\n### Creating the project on GitHub\n\nWe will use [GitHub](https://github.com) to host the code for the project which makes it easy for others to contribute and to automatically run the tests in [continuous integration](https://en.wikipedia.org/wiki/Continuous_integration) which we will enable later.\n\nIf you don't have an account yet, go to [GitHub](https://github.com/join) to sign up and follow [the help](https://help.github.com/articles/set-up-git/) on how to set it up for the command-line `git`. Once completed, create a new repository from your dashboard.\n\nCalling the repository `donejs--jshint` and initializing it empty (without any of the default files) looks like this:\n\n\"generator-repository\"\n\nAfter creating the repository, clone it into a new folder:\n\n\n $ git clone git@github.com:/donejs--jshint.git\n $ cd donejs--jshint\n\n\n### Initializing the project\n\nTo initialize a new generator you will need DoneJS version 0.9.0+ installed globally. To check your DoneJS version run\n\n\n $ donejs --version\n\n\nTo install DoneJS or to get the latest version run:\n\n\n $ npm install donejs -g \n\n\nIn the `donejs--jshint` folder we can now initialize a new generator, very similar to a new DoneJS application, like this:\n\n\n $ donejs add generator\n\n\nThe generator will ask several question that should be answered as follows:\n\n* For the project name you can just confirm the default by pressing enter\n* For the GitHub username or organization enter the GitHub username where the repository has been created\n* All other fields can also be answered with the default or the information you would like to use\n\nOnce all done, the final prompt looks similar to this:\n\n\"generator-init\"\n\nNow the generator will initialize the default layout and install all its dependencies.\n\n### Setting up Travis CI\n\nWhen the installation has completed, make sure everything got set up properly by running:\n\n\n $ npm test\n\n\nThis will run some basic generator tests and output the result on the console.\n\nThis command can also be used to automatically run the tests on a [continuous integration](https://en.wikipedia.org/wiki/Continuous_integration) server. There are many open source CI servers, the most popular being [Jenkins](https://jenkins-ci.org/), and many hosted solutions like [Travis CI](https://travis-ci.org/).\n\nWe will use Travis CI as our hosted solution because it is free for open source projects. It works with your GitHub account which it will use to sign up. Once signed in, go to `Accounts` (in the dropdown under you name) to enable the `donejs--jshint` repository:\n\n\"generator-travis\"\n\nYou may have to click the *\"Sync account\"* button for the repository to show up. Now, every time we push to GitHub the tests will run automatically. We can do so with our initial commit:\n\n\n $ git add . --all\n $ git commit -am \"Initial commit\"\n $ git push origin master\n\n\nIf you now go `https://travis-ci.org//donejs--jshint/builds` you will see the build running and eventually turn green (which will update the badge that got added in the `readme.md` file).\n\n\n## Adding the configuration files\n\nNow we can add the files that our generator should produce. All file templates will be put in the `default/templates/` folder.\n\n### .jshintrc\n\nFirst, add a `default/templates/.jshintrc` file which contains [options for JSHint](http://jshint.com/docs/options/):\n\n\n {\n \"node\": true,\n \"esnext\": true,\n \"bitwise\": true,\n \"camelcase\": true,\n \"curly\": true,\n \"eqeqeq\": true,\n \"immed\": true,\n \"indent\": 2,\n \"latedef\": \"nofunc\",\n \"newcap\": false,\n \"noarg\": true,\n \"regexp\": true,\n \"undef\": true,\n \"unused\": true,\n \"strict\": false,\n \"trailing\": true,\n \"smarttabs\": true,\n \"white\": false\n }\n\n\n### .editorconfig\n\nNext add a `default/templates/.editorconfig` file like this:\n\n\n ; Unix-style newlines\n [*]\n end_of_line = LF\n indent_style = <%= indent_style %>\n trim_trailing_whitespace = true\n\n\nAll files support [EJS](http://www.embeddedjs.com/) placeholders. Here, `<%= indent_style %>` will be used for the user choice of using whitespaces or tabs. Finally, remove `defaults/templates/file.js` since we won't be using it.\n\n\n## Implementing the generator\n\nFor the most part, DoneJS generators are simply [Yeoman](http://yeoman.io/) generators so everything documented for [writing your own Yeoman generator](http://yeoman.io/authoring/) also applies here. For the user choice of tabs vs. spaces also refer to the chapter about [interacting with the user](http://yeoman.io/authoring/user-interactions.html).\n\n### Adding the generator functionality\n\nOur generator needs to ask if we want to use spaces or tabs and then copy the `.jshintrc` and `.editorconfig` files over to their final destination. We also want to add an `npm run jshint` script to the `package.json` and make sure that JSHint runs during `npm test`. The complete generator at `default/index.js` looks like this:\n\n\n\n var generator = require('yeoman-generator');\n var _ = require('lodash');\n\n module.exports = generator.Base.extend({\n initializing: function () {\n // Read the original package.json\n this.pkg = this.fs.readJSON(\n this.destinationPath('package.json'), {}\n );\n \n // Maintain a list of all files we want to copy over\n this.files = [\n '.editorconfig',\n '.jshintrc'\n ];\n },\n \n prompting: function () {\n var done = this.async();\n\n // Create a prompt setting the `indent_style` property\n // to `tab` or `space`\n this.prompt([{\n type: 'list',\n name: 'indent_style',\n message: 'What indentation style do you want to use?',\n default: 'tab',\n choices: [\n {\n name: 'Tabs',\n value: 'tab'\n },\n {\n name: 'Spaces',\n value: 'space'\n }\n ]\n }], function (answers) {\n this.props = answers;\n done();\n }.bind(this));\n },\n \n writing: function () {\n var pkg = this.pkg;\n \n // Update `package.json` with the `jshint` command\n // and update the `test` script\n pkg.scripts = _.extend(pkg.scripts, {\n test: 'npm run jshint && ' + \n _.get(pkg, 'scripts.test',\n 'echo \"No tests specified\"'),\n jshint: 'jshint ' + \n _.get(pkg, 'system.directories.lib',\n 'src') + \n '/. --config'\n });\n \n // Write to `package.json` and format accordingly\n // This will prompt you to overwrite\n var indent = this.props.index === 'tab' ? '\\t' : ' ';\n this.fs.writeJSON('package.json', pkg, null, indent);\n\n // Install jshint as a development dependency\n this.npmInstall([ 'jshint' ], { saveDev: true});\n \n // Got through every file and copy it\n this.files.forEach(function(file) {\n this.fs.copyTpl(\n this.templatePath(file),\n this.destinationPath(file),\n this.props\n );\n }.bind(this));\n }\n });\n\n\nThat's it. Now we have a fully functional generator and can give it a try in a DoneJS application.\n\n### Manual testing\n\nWhen running `donejs add ` DoneJS will\n\n- Check if `donejs-` is installed locally\n- If not install it from NPM\n- Then run the generator at `default/index.js`\n\nIf we want to test our generator without publishing it to npm first we can link it instead. In the generator folder run:\n\n\n $ npm link\n\n\nThen go into your test DoneJS application directory:\n\n\n $ cd ../place-my-order\n $ npm link donejs--jshint\n\n\nNow we can run\n\n\n $ donejs add -jshint\n\n\n### Writing a unit test\n\nYeoman also comes with some tools for [testing generators](http://yeoman.io/authoring/testing.html). The test we initially ran with `npm test` makes sure that `default/templates/file.js` gets written. Since we deleted that file, update the test at `test/index.js` to verify that it wrote the files we want with the content we expect:\n\n\n var path = require('path');\n var helpers = require('yeoman-test');\n var assert = require('yeoman-assert');\n\n describe('donejs--jshint', function() {\n before(function(done) {\n // Run the generator in a temprorary directory\n helpers.run(path.join(__dirname, '../default'))\n .inTmpDir()\n // Mock the user input by setting\n // `indent_style` to `tab`\n .withPrompts({\n 'indent_style': 'tab'\n }).on('end', done);\n });\n\n // Verify that `.jshintrc` got written\n // and has some content\n it('created .jshintrc', function() {\n assert.file(['.jshintrc']);\n assert.fileContent('.jshintrc',\n /\"latedef\": \"nofunc\"/);\n });\n \n // Verify that `.editorconfig` got written\n // with `indent_style` set to our selection\n it('.editorconfig with indent_style', function() {\n assert.file(['.editorconfig']);\n assert.fileContent('.editorconfig',\n /indent_style = tab/);\n });\n \n // Make sure that `package.json` got updated\n // with the `jshint` npm script\n it('update package.json', function() {\n assert.jsonFileContent('package.json', {\n scripts: {\n jshint: 'jshint src/. --config'\n }\n });\n });\n });\n\n\nNow we can see all tests passing when running:\n\n\n $ npm test\n\n\n\n## Publishing the plugin\n\n### Making a pull request\n\nAlthough we are working on the generator by ourselves for now, [GitHub pull requests](https://help.github.com/articles/using-pull-requests/) are a great way to keep track of our progress and to make sure that all tests are passing. In the plugin folder run:\n\n\n $ git checkout -b generator-functionality\n $ git add . --all\n $ git commit -m \"Implementing JSHint and editorconfig generator\"\n $ git push origin generator-functionality\n\n\nAnd then create a new pull request by going to `https://github.com//donejs--jshint` which will now show an option like this:\n\n\"generator-pr\"\n\nOnce you created the pull request, you will see a `Some checks haven’t completed yet` message that will eventually turn green:\n\n\"generator-pull-request\"\n\nNow you can click the \"Merge pull request\" button. Then in the console, checkout the *master* branch and pull down the latest changes with:\n\n\n $ git checkout master\n $ git pull origin master\n\n\n\n### Publishing to npm\n\nFor others to be able to use your generator via `donejs add ` have to pulish it to [npm](http://npmjs.org). [Create a new account](https://www.npmjs.com/signup) and then log in via\n\n\n $ npm login\n\n\n[Semantic versioning](http://semver.org/) is a great way to communicate new features and breaking changes. The generated plugin already comes with the release scripts to publish new versions according to the `major.minor.patch` schema. In our case to publish an initial version `0.1.0` we can run\n\n\n $ donejs release:minor\n\n\nNow version `0.1.0` of the generator is available and everybody can use it through\n\n\n donejs add -jshint\n\n\n## Show it off\n\nOnce you published your generator, let the world know about it. [Tweet @donejs](https://twitter.com/donejs) and post it in the [DoneJS forums](http://forums.donejs.com/) and the [DoneJS chat](https://gitter.im/donejs/donejs). Those are also great places to get quick help with any questions.\n\n", - "description": "Generators add additional functionality to DoneJS applications. In this guide will create a generator that adds JSHint and an `.editorconfig` file to a DoneJS application. \n", - "name": "generator", - "title": "Creating a generator", + "body": "\n## [Quick start: donejs-chat](/Guide.html)\n\n\nIn the [quick start guide](/Guide.html), we will build a small chat application - [http://chat.donejs.com/](http://chat.donejs.com/). You'll learn about:\n\n- Hot Module Swapping\n- Server-side rendering\n- Progressive loading\n- Real time connections\n- Building and deploying to a CDN.\n- Builds to Codova (mobile) and NW.js (desktop).\n\n## [In-depth: place-my-order](/place-my-order.html)\n\n\n\nIn the [place-my-order guide](/place-my-order.html), we will go into detail, creating [http://place-my-order.com](http://place-my-order.com), a restaurant menu order application. You'll learn everything covered in the \"Quick start\", plus more:\n\n- MVVM architecture\n- Testing\n- Nested routing\n- Continuous integration and continuous deployment\n- Documentation\n\n## [Creating a plugin](/plugin.html)\n\n\n\nIn the [plugin guide](/plugin.html), we will create a reusable number input widget using [Bootstrap](http://getbootstrap.com) styles. We will cover:\n\n- Create the project on GitHub\n- Initialize the repository as a new DoneJS plugin\n- Set up continuous integration with Travis CI\n- Start development mode\n- Implement the component functionality and tests\n- Make a pull request to the repository\n- Make a build\n- Publish to NPM\n- Use the plugin in other projects\n\n## [Example App: Bitballs](/bitballs.html)\n\n\n\nIn this guide, you'll learn how [Bitballs](http://bitballs.herokuapp.com) - a charity basketball tournament management application - works.\nSpecifically, this guide will walk through the implementation of the following behaviors or functionality:\n\n - Registration, login, user sessions, and access rights.\n - Handling relationships between model types.\n - Setup node services and server-side rendering on the same process.\n - How to turn off parts of the app that should not be server-side rendered.\n\n", + "description": "DoneJS is about getting your application ... __done__ ... so you can spend time with your friends and family. To demonstrate how easy it is to make something amazing with all the bells and\nwhistles a modern developer needs, we created the following guides.\n\n\n", + "name": "Guides", "type": "page", "parent": "DoneJS", "hideSidebar": true, @@ -141,14 +124,14 @@ }, "comment": " " }, - "place-my-order": { + "Guide": { "src": { - "path": "docs/guides/place-my-order.md" + "path": "docs/guides/guide.md" }, - "body": "\n## Set up the project\n\nIn this section we will create our DoneJS project and set up a RESTful API for the application to use.\nYou will need [NodeJS](http://nodejs.org) or [io.js](https://iojs.org/en/index.html) installed and your code editor of choice.\n\n### Create the project\n\nTo get started, let's install the DoneJS command line utility globally:\n\n```\nnpm install -g donejs\n```\n\nThen we can create a new DoneJS application:\n\n```\ndonejs add app place-my-order\n```\n\nThe initialization process will ask you questions like the name of your application (set to `place-my-order`) and the source folder (set to `src`). The other questions can be skipped by hitting enter. This will install all of DoneJS' dependencies. The main project dependencies include:\n\n- [StealJS](http://stealjs.com) - ES6, CJS, and AMD module loader and builder\n- [CanJS](http://canjs.com) - Custom elements and Model-View-ViewModel utilities\n- [jQuery](http://jquery.com) - DOM helpers\n- [jQuery++](http://jquerypp.com) - Extended DOM helpers\n- [QUnit](https://qunitjs.com/) or Mocha - Assertion library\n- [FuncUnit](http://funcunit.com) - Functional tests\n- [Testee](https://github.com/bitovi/testee) - Test runner\n- [DocumentJS](http://documentjs.com) - Documentation\n\nIf we now go into the `place-my-order` folder with\n\n```\ncd place-my-order\n```\n\nWe can see the following files:\n\n```\n├── build.js\n├── development.html\n├── documentjs.json\n├── package.json\n├── production.html\n├── readme.md\n├── src/\n| ├── app.js\n| ├── index.stache\n| ├── models/\n| | ├── fixtures\n| | | ├── fixtures.js\n| | ├── test.js\n| ├── styles.less\n| ├── test.html\n| ├── test/\n| | ├── test.js\n| | ├── functional.js\n├── node_modules/\n```\n\nLet's have a quick look at the purpose of each:\n\n- `development.html`, `production.html` those pages can run the DoneJS application in development or production mode without a server\n- `package.json` is the main configuration file that defines all our application dependencies and other settings.\n- `test.html` is used to run all our tests.\n- `documentjs.json` is the configuration file for generating documentation.\n- `readme.md` is the readme file for your repository.\n- `src` is the folder where all our development assets live in their own modlets (more about that later).\n- `src/app.js` is the main application file, which exports the main application state.\n- `src/index.stache` is the main client template that includes server-side rendering.\n- `src/models/` is the folder where models for the API connection will be put. It currently contains `fixtures/fixtures.js` which will reference all the specific models fixtures files (so that we can run model tests without the need for a running API server) and `test.js` which will later gather all the individual model test files.\n- `src/styles.less` is the main application styles.\n- `src/test/test.js` collects all individual component and model tests we will create throughout this guide and is loaded by `test.html`.\n- `src/test/functional.js` will contain functional smoke tests for our application.\n\n### Development mode\n\nDoneJS comes with its own server, which hosts your development files and takes care of server-side rendering. DoneJS' development mode will also enable [hot module swapping](http://blog.bitovi.com/hot-module-replacement-comes-to-stealjs/) which automatically reloads files in the browser as they change. You can start it by running:\n\n```\ndonejs develop\n```\n\nThe default port is 8080, so if we now go to [http://localhost:8080/](localhost:8080) we can see our application with a default homepage. If we change `src/index.stache` or `src/app.js` all changes will show up right away in the browser. Try it by changing the `message` property in `src/app.js`.\n\n### Setup a service API\n\nSingle page applications usually communicate with a RESTful API and a websocket connection for real-time updates. This guide will not cover how to create a REST API. Instead, we'll just install and start an existing service API created specifically for use with this tutorial:\n\n**Note**: Kill the server for now while we install a few dependencies (ctrl+c on Windows and Mac).\n\n```\nnpm install place-my-order-api --save\n```\n\nNow we can add an API server start script into the `scripts` section of our `package.json` like this:\n\n```js\n \"scripts\": {\n \"api\": \"place-my-order-api --port 7070\",\n \"test\": \"testee src/test.html --browsers firefox --reporter Spec\",\n \"start\": \"done-serve --port 8080\",\n \"develop\": \"done-serve --develop --port 8080\",\n \"document\": \"documentjs\",\n \"build\": \"node build\"\n },\n```\n\n\nWhich allows us to start the server like:\n\n```\ndonejs api\n```\n\nThe first time it starts, the server will initialize some default data (restaurants and orders). Once started, you can verify that the data has been created and the service is running by going to [http://localhost:7070/restaurants](http://localhost:7070/restaurants), where we can see a JSON list of restaurant data.\n\n### Starting the application\n\nNow our application is good to go and we can start the server. We need to proxy the `place-my-order-api` server to `/api` on our server in order to avoid violating the same origin policy. This means that we need to modify the `start` and `develop` script in our `package.json` to:\n\n```js\n\"scripts\": {\n \"api\": \"place-my-order-api --port 7070\",\n \"test\": \"testee src/test.html --browsers firefox --reporter Spec\",\n \"start\": \"done-serve --proxy http://localhost:7070 --port 8080\",\n \"develop\": \"done-serve --develop --proxy http://localhost:7070 --port 8080\",\n \"document\": \"documentjs\",\n \"build\": \"node build\"\n},\n```\n\n\nNow we can start the application with:\n\n```\ndonejs develop\n```\n\nGo to [http://localhost:8080](http://localhost:8080) to see the \"hello world\" message again.\n\n### Loading assets\n\nBefore we get to the code, we also need to install the `place-my-order-assets` package which contains the images and styles specifically for this tutorial's application:\n\n```\nnpm install place-my-order-assets --save\n```\n\nEvery DoneJS application consists of at least two files:\n\n 1. **A main template** (in this case `src/index.stache`) which contains the main template and links to the development or production assets.\n 1. **A main application view-model** (`src/app.js`) that initializes the application state and routes.\n\n`src/index.stache` was already created for us when we ran `donejs add app`, so update it to\nload the static assets and set a `` tag to support a responsive design:\n\n\n```html\n\n \n {{title}}\n \n \n \n \n \n \n\n

{{message}}

\n\n {{#switch env.NODE_ENV}}\n {{#case \"production\"}}\n \n \n {{/case}}\n {{#default}}\n \n {{/default}}\n {{/switch}}\n \n\n\n```\n\nThis is an HTML5 template that uses [can.stache](http://canjs.com/docs/can.stache.html) - a [Handlebars syntax](http://handlebarsjs.com/)-compatible view engine. It renders a `message` property from the application state.\n\n`can-import` loads the template's dependencies:\n 1. The `place-my-order-assets` package, which loads the LESS styles for the application\n 1. `place-my-order/app`, which is the main application file\n\nThe main application file at `src/app.js` looks like this:\n\n```\n// src/app.js\nimport Map from \"can/map/\";\nimport route from \"can/route/\";\nimport 'can/map/define/';\nimport 'can/route/pushstate/';\n\nconst AppViewModel = Map.extend({\n define: {\n message: {\n value: 'Hello World!',\n serialize: false\n },\n title: {\n value: 'place-my-order',\n serialize: false\n }\n }\n});\n\nexport default AppViewModel;\n```\n\nThis initializes a [can.Map](https://canjs.com/docs/can.Map.html): a special object that acts as the application global state (with a default `message` property) and also plays a key role in enabling server side rendering.\n\n## Creating custom elements\n\nOne of the most important concepts in DoneJS is splitting up your application functionality into individual, self-contained modules. In the following section we will create separate components for the homepage, the restaurant list, and the order history page. After that, we will glue them all together using routes and the global application state.\n\nThere are two ways of creating components. For smaller components we can define all templates, styles and functionality in a single `.component` file (to learn more see [done-component](https://github.com/donejs/done-component)). Larger components can be split up into several separate files.\n\n### Creating a homepage element\n\nTo generate a new component run:\n\n```\ndonejs add component home.component pmo-home\n```\n\nThis will create a file at `src/home.component` containing the basic ingredients of a component. We will update it to reflect the below content:\n\n\n```html\n\n \n\n\n```\n\nHere we created a [can.Component](http://canjs.com/docs/can.Component.html) named `pmo-home` using a [web-component](http://webcomponents.org/) style declaration. This particular component is just a basic template, it does not have much in the way of styles or functionality.\n\n### Create the order history element\n\nWe'll create an initial version of order history that is very similar.\n\n```\ndonejs add component order/history.component pmo-order-history\n```\n\nAnd update `src/order/history.component`:\n\n\n```html\n\n \n\n\n```\n\n### Creating a restaurant list element\n\nThe restaurant list will contain more functionality, which is why we will split its template and component logic into separate files.\n\nWe can create a basic component like that by running:\n\n```\ndonejs add component restaurant/list pmo-restaurant-list\n```\n\nThe component's files are collected in a single folder so that components can be easily tested, moved, and re-used. The folder structure looks like this:\n\n```\n├── node_modules\n├── package.json\n├── src/\n| ├── app.js\n| └── index.stache\n| ├── models\n| ├── order/\n| | ├── history.component\n| ├── restaurant/\n| | ├── list/\n| | | ├── list.html\n| | | ├── list.js\n| | | ├── list.less\n| | | ├── list.md\n| | | ├── list.stache\n| | | ├── list_test.js\n| | | ├── test.html\n```\n\nWe will learn more about those files and add more functionality to this element later, but it already contains a fully functional component with a demo page (see [localhost:8080/src/restaurant/list/list.html](http://localhost:8080/src/restaurant/list/list.html)), a basic test (at [localhost:8080/src/restaurant/list/test.html](http://localhost:8080/src/restaurant/list/test.html)) and documentation placeholders.\n\n## Setting up routing\n\nIn this part, we will create routes - URL patterns that load specific parts of our single page app. We'll also dynamically load the custom elements we created and integrate them in the application's main page.\n\n### Create Routes\n\nRouting works a bit differently than other libraries. In other libraries, you might declare routes and map those to controller-like actions.\n\nDoneJS application [routes](http://canjs.com/docs/can.route.html) map URL strings (like /user/1) to properties in our application state. In other words, our routes will just be a representation of the application state.\n\nTo learn more about routing visit the CanJS guide on [Application State and Routing](http://canjs.com/guides/AppStateAndRouting.html).\n\nTo add our routes, change `src/app.js` to:\n\n\n```js\nimport Map from 'can/map/';\nimport route from 'can/route/';\nimport 'can/route/pushstate/';\nimport 'can/map/define/';\n\nconst AppViewModel = Map.extend({\n define: {\n title: {\n serialize: false,\n value: 'place-my-order'\n }\n }\n});\n\nroute(':page', { page: 'home' });\nroute(':page/:slug', { slug: null });\nroute(':page/:slug/:action', { slug: null, action: null });\n\nexport default AppViewModel;\n\n```\n\n> Notice: We also removed the `message` property in `AppViewModel`. This is because\n> it is not needed.\n\nNow we have three routes available:\n\n- `:page` captures urls like [http://localhost:8080/home](http://localhost:8080/home) and sets the `page` property on `AppViewModel` to `home` (which is also the default when visiting [http://localhost:8080/](http://localhost:8080/))\n- `:page/:slug` matches restaurant links like [http://localhost:8080/restaurants/spago](http://localhost:8080/restaurants/spago) and sets `page` and `slug` (a URL friendly restaurant short name)\n- `:page/:slug/:action` will be used to show the order page for a specific restaurant e.g. [http://localhost:8080/restaurants/spago/order](http://localhost:8080/restaurants/spago/order)\n\nIts important to note that if any of these URLs are matched, AppViewModel, which is the application's global state, will contain these properties, even though they aren't present in the AppViewModel definition directly. Properties can be set on AppViewModel that aren't explicitly defined.\n\n### Adding a header element\n\nNow is also a good time to add a header element that links to the different routes we just defined. We can run\n\n```\ndonejs add component header.component pmo-header\n```\n\nand update `src/header.component` to:\n\n\n```html\n\n \n\n\n```\n\nHere we use [routeUrl](http://canjs.com/docs/can.stache.helpers.routeUrl.html) to create links that will set values in the application state. For example, the first usage of routeUrl above will create a link based on the current routing rules ([http://localhost:8080/home](http://localhost:8080/home) in this case) that sets the `page` property to `home` when clicked.\n\nWe also use the Stache `eq` helper to make the appropriate link active.\n\n### Create a loading indicator\n\nTo show that something is currently loading, let's create a `pmo-loading` component:\n\n```\ndonejs add component loading.component pmo-loading\n```\n\nChange `src/loading.component` to:\n\n\n```html\n\n \n\n\n```\n\n### Switch between components\n\nNow we can glue all those individual components together in `src/index.stache`. What we want to do is - based on the current page (`home`, `restaurants` or `order-history`) - load the correct component and then initialize it.\n\nUpdate `src/index.stache` to:\n\n\n```html\n\n \n {{title}}\n \n \n \n \n \n \n\n \n \n \n\n {{#switch page}}\n {{#case \"home\"}}\n \n \n \n {{/case}}\n {{#case \"restaurants\"}}\n \n \n \n {{/case}}\n {{#case \"order-history\"}}\n \n \n \n {{/case}}\n {{/switch}}\n\n {{#switch env.NODE_ENV}}\n {{#case \"production\"}}\n \n \n {{/case}}\n {{#default}}\n \n {{/default}}\n {{/switch}}\n \n\n\n```\n\nHere we make a `switch` statement that checks for the current `page` property (part of the AppViewModel that makes up the scope object of this template) then progressively loads the component with [can-import](http://canjs.com/docs/can%7Cview%7Cstache%7Csystem.import.html) and initializes it.\n\nSetting `can-tag=\"pmo-loading\"` inserts a `` loading indicator while the import is in progress. A can-import's view model is a promise object, so once it is done loading, it sets its `state` property to `resolved`.\n\nNow we can see the header and the home component and be able to navigate to the different pages through the header.\n\n## Getting Data from the Server\n\nIn this next part, we'll connect to the RESTful API that we set up with `place-my-order-api`, using the powerful data layer provided by [can-connect](http://connect.canjs.com/).\n\n### Creating a restaurants connection\n\nAt the beginning of this guide we set up a REST API at [http://localhost:7070](http://localhost:7070) and told `done-serve` to proxy it to [http://localhost:8080/api](http://localhost:8080/api).\n\nTo manage the restaurant data located at [http://localhost:8080/api/restaurants](http://localhost:8080/api/restaurants), we'll create a restaurant supermodel:\n\n```js\ndonejs add supermodel restaurant\n```\n\nAnswer the question about the URL endpoint with `/api/restaurants` and the name of the id property with `_id`.\n\nWe have now created a model and fixtures (for testing without an API) with a folder structure like this:\n\n```\n├── node_modules\n├── package.json\n├── src/\n| ├── app.js\n| └── index.stache\n| ├── models/\n| | ├── fixtures/\n| | | ├── restaurant.js\n| | ├── fixtures.js\n| | ├── restaurant.js\n| | ├── restaurant_test.js\n| | ├── test.js\n```\n\n### Test the connection\n\nTo test the connection you can run the following in the console:\n\n```js\nSystem.import(\"place-my-order/models/restaurant\").then(function(module){\n var Restaurant = module[\"default\"];\n return Restaurant.getList({});\n}).then(function(restaurants){\n console.log( restaurants.attr() );\n})\n```\n\nThis programmatically imports the `Restaurant` model and uses it to get a list\nof all restaurants on the server and log them to the console.\n\n### Add data to the page\n\nNow, update the `ViewModel` in `src/restaurant/list/list.js` to use [can.Map.define](http://canjs.com/docs/can.Map.prototype.define.html) to load all restaurants from the restaurant connection:\n\n\n```js\nimport Component from 'can/component/';\nimport Map from 'can/map/';\nimport 'can/map/define/';\nimport template from './list.stache';\nimport Restaurant from 'place-my-order/models/restaurant';\n\nexport var ViewModel = Map.extend({\n define: {\n restaurants: {\n value() {\n return Restaurant.getList({});\n }\n }\n }\n});\n\nexport default Component.extend({\n tag: 'pmo-restaurant-list',\n viewModel: ViewModel,\n template: template\n});\n\n```\n\nAnd update the template at `src/restaurant/list/list.stache` to use the [Promise](http://canjs.com/docs/can.Deferred.html) returned for the `restaurants` property to render the template:\n\n```html\n
\n

Restaurants

\n {{#if restaurants.isPending}}\n
\n {{/if}}\n {{#if restaurants.isResolved}}\n {{#each restaurants.value}}\n
\n \n

{{name}}

\n {{#address}}\n
\n {{street}}
{{city}}, {{state}} {{zip}}\n
\n {{/address}}\n\n
\n $$$
\n Hours: M-F 10am-11pm\n Open Now\n
\n\n \n Details\n \n
\n
\n {{/each}}\n {{/if}}\n
\n```\n\nBy checking for `restaurants.isPending` and `restaurants.isResolved` we are able to show a loading indicator while the data are being retrieved. Once resolved, the actual restaurant list is available at `restaurants.value`. When navigating to the restaurants page now we can see a list of all restaurants.\n\nNote the usage of `routeUrl` to set up a link that points to each restaurant. `slug=slug` is not wrapped in quotes because the helper will populate each restaurant's individual `slug` property in the URL created.\n\n## Creating a unit-tested view model\n\nIn this section we will create a view model for the restaurant list functionality.\n\nWe'll show a dropdown of all available US states. When the user selects a state, we'll show a list of cities. Once a city is selected, we'll load a list of all restaurants for that city. The end result will look like this:\n\n![Restaurant list](static/img/restaurant-list.png)\n\n### Identify view model state\n\nFirst we need to identify the properties that our view model needs to provide. We want to load a list of states from the server and let the user select a single state. Then we do the same for cities and finally load the restaurant list for that selection.\n\nAll asynchronous requests return a Promise, so the data structure will look like this:\n\n```js\n{\n states: Promise<[State]>\n state: String \"IL\",\n cities: Promise<[City]>,\n city: String \"Chicago\",\n restaurants: Promise<[Restaurant]>\n}\n```\n\n### Create dependent models\n\nThe API already provides a list of available [states](http://localhost:8080/api/states) and [cities](http://localhost:8080/api/cities). To load them we can create the corresponding models like we already did for Restaurants.\n\nRun:\n\n```\ndonejs add supermodel state\n```\n\nWhen prompted, set the URL to `/api/states` and the id property to `short`.\n\nRun:\n\n```\ndonejs add supermodel city\n```\n\nWhen prompted, set the URL to `/api/cities` and the id property to `name`.\n\nNow we can load a list of states and cities.\n\n### Implement view model behavior\n\nNow that we have identified the view model properties needed and have created the models necessary to load them, we can [define](http://canjs.com/docs/can.Map.prototype.define.html) the `states`, `state`, `cities` and `city` properties in the view model at `src/restaurant/list/list.js`:\n\n\n```js\nimport Component from 'can/component/';\nimport Map from 'can/map/';\nimport 'can/map/define/';\nimport template from './list.stache';\nimport Restaurant from 'place-my-order/models/restaurant';\nimport State from 'place-my-order/models/state';\nimport City from 'place-my-order/models/city';\n\nexport var ViewModel = Map.extend({\n define: {\n states: {\n get() {\n return State.getList({});\n }\n },\n state: {\n type: 'string',\n value: null,\n set() {\n // Remove the city when the state changes\n this.attr('city', null);\n }\n },\n cities: {\n get() {\n let state = this.attr('state');\n\n if(!state) {\n return null;\n }\n\n return City.getList({ state });\n }\n },\n city: {\n type: 'string',\n value: null\n },\n restaurants: {\n get() {\n let state = this.attr('state');\n let city = this.attr('city');\n\n if(state && city) {\n return Restaurant.getList({\n 'address.state': state,\n 'address.city': city\n });\n }\n\n return null;\n }\n }\n }\n});\n\nexport default Component.extend({\n tag: 'pmo-restaurant-list',\n viewModel: ViewModel,\n template: template\n});\n\n```\n\nLet's take a closer look at those properties:\n\n- `states` will return a list of all available states by calling `State.getList({})`\n- `state` is a string property set to `null` by default (no selection). Additionally, when `state` is changed we will remove the dependent `city` selection.\n- `cities` will return `null` if no state has been selected. Otherwise, it will load all the cities for a given state by sending `state` as a query paramater (which will make a request like [http://localhost:8080/api/cities?state=IL](ttp://localhost:8080/api/cities?state=IL))\n- `city` is a simple string, set to `null` by default\n- `restaurants` will always be `null` unless both a `city` and a `state` are selected. If both are selected, it will set the `address.state` and `address.city` query parameters which will return a list of all restaurants whose address matches those parameters.\n\n### Create a test\n\nView models that are decoupled from the presentation layer are easy to test. We will use [QUnit](http://qunitjs.com/) as the testing framework by loading a StealJS-friendly wrapper (`steal-qunit`). The component generator created a fully working test page for the component, which can be opened at [http://localhost:8080/pmo/restaurant/list/test.html](http://localhost:8080/src/restaurant/list/test.html). Currently, the tests will fail because we changed the view model, but in this section we will create some unit tests for the new functionality.\n\n#### Fixtures: Create fake data\n\nUnit tests should be able to run by themselves without the need for an API server. This is where [fixtures](http://canjs.com/docs/can.fixture.html) come in. Fixtures allow us to mock requests to the REST API with data that we can use tests or demo pages. Default fixtures will be provided for every generated model. Now we'll add more realistic fake data by updating `src/models/fixtures/state.js` to:\n\n\n```js\nimport fixture from 'can-fixture';\n\nconst store = fixture.store([\n { name: 'Calisota', short: 'CA' },\n { name: 'New Troy', short: 'NT'}\n],{});\n\nfixture({\n 'GET /api/states': store.findAll,\n 'GET /api/states/{short}': store.findOne,\n 'POST /api/states': store.create,\n 'PUT /api/states/{short}': store.update,\n 'DELETE /api/states/{short}': store.destroy\n});\n\nexport default store;\n\n```\n\nUpdate `src/models/fixtures/city.js` to look like:\n\n\n```js\nimport fixture from 'can-fixture';\n\nconst store = fixture.store([\n { state: 'CA', name: 'Casadina' },\n { state: 'NT', name: 'Alberny' }\n],{});\n\nfixture({\n 'GET /api/cities': store.findAll,\n 'GET /api/cities/{name}': store.findOne,\n 'POST /api/cities': store.create,\n 'PUT /api/cities/{name}': store.update,\n 'DELETE /api/cities/{name}': store.destroy\n});\n\nexport default store;\n\n```\n\nAnd we also need to provide a restaurant list according to the selected city and state in `src/models/fixtures/restaurant.js`:\n\n\n```js\nimport fixture from 'can-fixture';\n\nconst store = fixture.store([{\n _id: 1,\n name: 'Cheese City',\n slug:'cheese-city',\n address: {\n city: 'Casadina',\n state: 'CA'\n },\n images: {\n banner: \"node_modules/place-my-order-assets/images/1-banner.jpg\",\n owner: \"node_modules/place-my-order-assets/images/2-owner.jpg\",\n thumbnail: \"node_modules/place-my-order-assets/images/3-thumbnail.jpg\"\n }\n}, {\n _id: 2,\n name: 'Crab Barn',\n slug:'crab-barn',\n address: {\n city: 'Alberny',\n state: 'NT'\n },\n images: {\n banner: \"node_modules/place-my-order-assets/images/2-banner.jpg\",\n owner: \"node_modules/place-my-order-assets/images/3-owner.jpg\",\n thumbnail: \"node_modules/place-my-order-assets/images/2-thumbnail.jpg\"\n }\n}],{\n \"address.city\": function(restaurantValue, paramValue, restaurant){\n return restaurant.address.city === paramValue;\n },\n \"address.state\": function(restaurantValue, paramValue, restaurant){\n return restaurant.address.state === paramValue;\n }\n});\n\nfixture({\n 'GET /api/restaurants': store.findAll,\n 'GET /api/restaurants/{id}': store.findOne,\n 'POST /api/restaurants': store.create,\n 'PUT /api/restaurants/{id}': store.update,\n 'DELETE /api/restaurants/{id}': store.destroy\n});\n\nexport default store;\n\n```\n\n#### Test the view model\n\nWith fake data in place, we can test our view model by changing `src/restaurant/list/list_test.js` to:\n\n\n```js\nimport QUnit from 'steal-qunit';\nimport cityStore from 'place-my-order/models/fixtures/city';\nimport stateStore from 'place-my-order/models/fixtures/state';\nimport restaurantStore from 'place-my-order/models/fixtures/restaurant';\nimport { ViewModel } from './list';\n\nQUnit.module('place-my-order/restaurant/list', {\n beforeEach() {\n localStorage.clear();\n }\n});\n\nQUnit.asyncTest('loads all states', function() {\n var vm = new ViewModel();\n var expectedStates = stateStore.findAll({});\n\n vm.attr('states').then(states => {\n QUnit.deepEqual(states.attr(), expectedStates.data, 'Got all states');\n QUnit.start();\n });\n});\n\nQUnit.asyncTest('setting a state loads its cities', function() {\n var vm = new ViewModel();\n var expectedCities = cityStore.findAll({data: {state: \"CA\"}}).data;\n\n QUnit.equal(vm.attr('cities'), null, '');\n vm.attr('state', 'CA');\n vm.attr('cities').then(cities => {\n QUnit.deepEqual(cities.attr(), expectedCities);\n QUnit.start();\n });\n});\n\nQUnit.asyncTest('changing a state resets city', function() {\n var vm = new ViewModel();\n var expectedCities = cityStore.findAll({data: {state: \"CA\"}}).data;\n\n QUnit.equal(vm.attr('cities'), null, '');\n vm.attr('state', 'CA');\n vm.attr('cities').then(cities => {\n QUnit.deepEqual(cities.attr(), expectedCities);\n vm.attr('state', 'NT');\n QUnit.equal(vm.attr('city'), null);\n QUnit.start();\n });\n});\n\nQUnit.asyncTest('setting state and city loads a list of its restaurants', function() {\n var vm = new ViewModel();\n var expectedRestaurants = restaurantStore.findAll({\n data: {\"address.city\": \"Alberny\"}\n }).data;\n\n vm.attr('state', 'NT');\n vm.attr('city', 'Alberny');\n\n vm.attr('restaurants').then(restaurants => {\n QUnit.deepEqual(restaurants.attr(), expectedRestaurants);\n QUnit.start();\n });\n});\n\n```\n\nThese unit tests are comparing expected data (what we we defined in the fixtures) with actual data (how the view model methods are behaving). Visit [http://localhost:8080/src/restaurant/list/test.html](http://localhost:8080/src/restaurant/list/test.html) to see all tests passing.\n\n### Write the template\n\nNow that our view model is implemented and tested, we'll update the restaurant list template to support the city/state selection functionality.\n\nUpdate `src/restaurant/list/list.stache` to:\n\n\n```html\n
\n

Restaurants

\n
\n
\n \n \n
\n
\n \n \n
\n
\n\n {{#if restaurants.isPending}}\n
\n {{/if}}\n\n {{#if restaurants.isResolved}}\n {{#each restaurants.value}}\n
\n \n

{{name}}

\n {{#address}}\n
\n {{street}}
{{city}}, {{state}} {{zip}}\n
\n {{/address}}\n\n
\n $$$
\n Hours: M-F 10am-11pm\n Open Now\n
\n\n \n Place My Order\n \n
\n
\n {{/each}}\n {{/if}}\n
\n\n```\n\n\nSome things worth pointing out:\n\n- Since `states` and `cities` return a promise, we can check the promise's status via `isResolved` and `isPending` and once resolved get the actual value with `states.value` and `cities.value`. This also allows us to easily show loading indicators and disable the select fields while loading data.\n- The `state` and `city` properties are two-way bound to their select fields via [{($value)}](http://canjs.com/docs/can.view.bindings.can-value.html)\n\nNow we have a component that lets us select state and city and displays the appropriate restaurant list.\n\n### Update the demo page\n\nWe already have an existing demo page at [src/restaurant/list/list.html](http://localhost:8080/src/restaurant/list/list.html). We'll update it to load fixtures so it can demonstrate the use of the pmo-restaurnt-list component:\n\n\n```html\n\n\n\n```\n\nView the demo page at [http://localhost:8080/src/restaurant/list/list.html](http://localhost:8080/src/restaurant/list/list.html) .\n\n## Automated tests\n\nIn this chapter we will automate running the tests so that they can be run from from the command line.\n\n### Using the global test page\n\nWe already worked with an individual component test page in [src/restaurant/list/test.html](http://localhost:8080/src/restaurant/list/test.html) but we also have a global test page available at [src/test.html](http://localhost:8080/src/test.html). All tests are being loaded in `src/test/test.js`. Since we do not tests our models at the moment, let's remove the `import 'place-my-order/models/test';` part so that `src/test/test.js` looks like this:\n\n\n```js\nimport 'place-my-order/test/functional';\n\nimport 'place-my-order/restaurant/list/list_test';\n\n```\n\nIf you now go to [http://localhost:8080/src/test.html](http://localhost:8080/src/test.html) we still see all restaurant list tests passing but we will add more here later on.\n\n### Using a test runner\n\nThe tests can be automated with any test runner that supports running QUnit tests. We will use [Testee](https://github.com/bitovi/testee) which makes it easy to run those tests in any browser from the command line without much configuration. In fact, everything needed to automatically run the `src/test.html` page in Firefox is already set up and we can launch the tests by running:\n\n```\ndonejs test\n```\n\nTo see the tests passing on the command line.\n\n## Continuous integration\n\nNow that the tests can be run from the command line we can automate it in a [continuous integration](https://en.wikipedia.org/wiki/Continuous_integration) (CI) environment to run all tests whenever a code change is made. We will use [GitHub](https://github.com) to host our code and [TravisCI](https://travis-ci.org/) as the CI server.\n\n### Creating a GitHub account and repository\n\nIf you don't have an account yet, go to [GitHub](https://github.com) to sign up and follow [the help](https://help.github.com/articles/set-up-git/) on how to set it up for use with the command-line `git`. Once completed, you can create a new repository from your dashboard. Calling the repository `place-my-order` and initializing it empty (without any of the default files) looks like this:\n\n![Creating a new repository on GitHub](static/img/guide-create-repo.png)\n\nNow we have to initialize Git in our project folder and add the GitHub repository we created as the origin remote (replace `` with your GitHub username):\n\n```\ngit init\ngit remote add origin git@github.com:/place-my-order.git\n```\n\nThen we can add all files and push to origin like this:\n\n```\ngit add . --all\ngit commit -am \"Initial commit\"\ngit push origin master\n```\n\nIf you now go to [github.com//place-my-order](https://github.com//place-my-order) you will see the project files in the repository.\n\n### Setting up Travis CI\n\nThe way our application is set up, now all a continuous integration server has to do is clone the application repository, run `npm install`, and then run `npm test`. There are many open source CI servers, the most popular one probably [Jenkins](https://jenkins-ci.org/), and many hosted solutions like [Travis CI](https://travis-ci.org/).\n\nWe will use Travis as our hosted solution because it is free for open source projects. It works with your GitHub account which it will use to sign up. First, [sign up](https://travis-ci.org/), then go to `Accounts` (in the dropdown under you name) to enable the `place-my-order` repository:\n\n![Enabling the repository on Travis CI](static/img/guide-travis-ci.png)\n\nContinuous integration on GitHub is most useful when using [branches and pull requests](https://help.github.com/categories/collaborating-on-projects-using-pull-requests/). That way your main branch (master) will only get new code changes if all tests pass. Let's create a new branch with\n\n```\ngit checkout -b travis-ci\n```\n\nAnd add a `.travis.yml` file to our project root:\n\n```\nlanguage: node_js\nnode_js: node\nbefore_install:\n - \"export DISPLAY=:99.0\"\n - \"sh -e /etc/init.d/xvfb start\"\n```\n\nBy default Travis CI runs `npm test` for NodeJS projects which is what we want. `before_install` sets up a window system to run Firefox.\n\nWe can also add a *Build Passing* badge to the top `readme.md`:\n\n```\n[![Build Status](https://travis-ci.org//place-my-order.png?branch=master)](https://travis-ci.org//place-my-order)\n\n# place-my-order\n```\n\nTo see Travis run, let's add all changes and push to the branch:\n\n```\ngit add readme.md .travis.yml\ngit commit -am \"Enabling Travis CI\"\ngit push origin travis-ci\n```\n\nAnd then create a new pull request by going to [github.com//place-my-order](https://github.com//place-my-order) which will now show an option for it:\n\n![Creating a new pull request on GitHub](static/img/guide-github-pr.png)\n\nOnce you created the pull request, you will see a `Some checks haven’t completed yet` message that will eventually turn green like this:\n\n![Merging a pull request with all tests passed](static/img/guide-merge-pr.png)\n\nOnce everything turns green, click the \"Merge pull request\" button. Then in your console, checkout the _master_ branch and pull down it's latest with:\n\n```\ngit checkout master\ngit pull origin master\n```\n\n\n## Nested routes\n\nIn this section, we will add additional pages that are show under nested urls such as `restaurants/cheese-curd-city/order`.\n\n
\n\nUntil now we've used three top level routes: `home`, `restaurants` and `order-history`. We did however also define two additional routes in `src/app.js` which looked like:\n\n```js\nroute(':page/:slug', { slug: null });\nroute(':page/:slug/:action', { slug: null, action: null });\n```\n\nWe want to use those routes when we are in the `restaurants` page. The relevant section in `src/index.stache` currently looks like this:\n\n```html\n{{#case \"restaurants\"}}\n \n \n \n{{/case}}\n```\n\nWe want to support two additional routes:\n\n- `restaurants/:slug`, which shows a details page for the restaurant with `slug` being a URL friendly short name for the restaurant\n- `restaurants/:slug/order`, which shows the menu of the current restaurant and allows us to make a selection and then send our order.\n\n### Create additional components\n\nTo make this happen, we need two more components. First, the `pmo-restaurant-details` component which loads the restaurant (based on the `slug`) and displays its information.\n\n```\ndonejs add component restaurant/details.component pmo-restaurant-details\n```\n\nAnd change `src/restaurant/details.component` to:\n\n\n```html\n\n \n\n\n```\n\nThe order component will be a little more complex, which is why we will put it into its own folder:\n\n```\ndonejs add component order/new pmo-order-new\n```\n\nFor now, we will just use placeholder content and implement the functionality in\nthe following chapters.\n\n### Add to the main template\n\nNow we can add those components to the main template (at `src/index.stache`) with conditions based on the routes that we want to match. Change the section which contains:\n\n```html\n{{#case \"restaurants\"}}\n \n \n \n{{/case}}\n```\n\nTo:\n\n\n```html\n{{#case \"restaurants\"}}\n {{#if slug}}\n {{#switch action}}\n {{#case 'order'}}\n \n \n \n {{/case}}\n\n {{#default}}\n \n \n \n {{/default}}\n {{/switch}}\n {{else}}\n \n \n \n {{/if}}\n{{/case}}\n\n```\n\nHere we are adding some more conditions if `page` is set to `restaurants`:\n\n- When there is no `slug` set, show the original restaurant list\n- When `slug` is set but no `action`, show the restaurant details\n- When `slug` is set and `action` is `order`, show the order component for that restaurant\n\n## Importing other projects\n\nThe NPM integration of StealJS makes it very easy to share and import other components. One thing we want to do when showing the `pmo-order-new` component is have a tab to choose between the lunch and dinner menu. The good news is that there is already a [bit-tabs](https://github.com/bitovi-components/bit-tabs) component which does exactly that. Let's add it as a project dependency with:\n\n```\nnpm install bit-tabs --save\n```\n\nAnd then integrate it into `src/order/new/new.stache`:\n\n\n```html\n\n
\n

Order here

\n\n \n \n This is the lunch menu\n \n \n This is the dinner menu\n \n \n
\n\n```\n\nHere we just import the `unstyled` module from the `bit-tabs` package using `can-import` which will then provide the `bit-tabs` and `bit-panel` custom elements.\n\n## Creating data\n\nIn this section, we will update the order component to be able to select restaurant menu items and submit a new order for a restaurant.\n\n### Creating the order model\n\nFirst, let's look at the restaurant data we get back from the server. It looks like this:\n\n```js\n{\n \"_id\": \"5571e03daf2cdb6205000001\",\n \"name\": \"Cheese Curd City\",\n \"slug\": \"cheese-curd-city\",\n \"images\": {\n \"thumbnail\": \"images/1-thumbnail.jpg\",\n \"owner\": \"images/1-owner.jpg\",\n \"banner\": \"images/2-banner.jpg\"\n },\n \"menu\": {\n \"lunch\": [\n {\n \"name\": \"Spinach Fennel Watercress Ravioli\",\n \"price\": 35.99\n },\n {\n \"name\": \"Chicken with Tomato Carrot Chutney Sauce\",\n \"price\": 45.99\n },\n {\n \"name\": \"Onion fries\",\n \"price\": 15.99\n }\n ],\n \"dinner\": [\n {\n \"name\": \"Gunthorp Chicken\",\n \"price\": 21.99\n },\n {\n \"name\": \"Herring in Lavender Dill Reduction\",\n \"price\": 45.99\n },\n {\n \"name\": \"Roasted Salmon\",\n \"price\": 23.99\n }\n ]\n },\n \"address\": {\n \"street\": \"1601-1625 N Campbell Ave\",\n \"city\": \"Green Bay\",\n \"state\": \"WI\",\n \"zip\": \"60045\"\n }\n}\n```\n\nWe have a `menu` property which provides a `lunch` and `dinner` option (which will show later inside the tabs we set up in the previous chapter later). We want to be able to add and remove items from the order, check if an item is in the order already, set a default order status (`new`), and be able to calculate the order total. For that to happen, we need to create a new `order` model:\n\n```\ndonejs add supermodel order\n```\n\nLike the restaurant model, the URL is `/api/orders` and the id property is `_id`. To select menu items, we need to add some additional functionality to `src/models/order.js`:\n\n\n```js\nimport superMap from 'can-connect/can/super-map/';\nimport tag from 'can-connect/can/tag/';\nimport List from 'can/list/';\nimport Map from 'can/map/';\nimport 'can/map/define/';\n\nconst ItemsList = List.extend({}, {\n has: function(item) {\n return this.indexOf(item) !== -1;\n },\n\n toggle: function(item) {\n var index = this.indexOf(item);\n\n if (index !== -1) {\n this.splice(index, 1);\n } else {\n this.push(item);\n }\n }\n});\n\nlet Order = Map.extend({\n define: {\n status: {\n value: 'new'\n },\n items: {\n Value: ItemsList\n },\n total: {\n get() {\n let total = 0.0;\n this.attr('items').forEach(item =>\n total += parseFloat(item.attr('price')));\n return total.toFixed(2);\n }\n }\n },\n\n markAs(status) {\n this.attr('status', status);\n this.save();\n }\n});\n\nexport const connection = superMap({\n url: '/api/orders',\n idProp: '_id',\n Map: Order,\n List: Order.List,\n name: 'orders'\n});\n\ntag('order-model', connection);\n\nexport default Order;\n\n```\n\nHere we define an `ItemsList` which allows us to toggle menu items and check if they are already in the order. We set up ItemsList as the Value of the items property of an order so we can use its has function and toggle directly in the template. We also set a default value for status and a getter for calculating the order total which adds up all the item prices. We also create another `` tag to load orders in the order history template later.\n\n### Implement the view model\n\nNow we can update the view model in `src/order/new/new.js`:\n\n\n```js\nimport Component from 'can/component/component';\nimport Map from 'can/map/';\nimport 'can/map/define/';\nimport template from './new.stache';\nimport Restaurant from 'place-my-order/models/restaurant';\nimport Order from 'place-my-order/models/order';\n\nexport const ViewModel = Map.extend({\n define: {\n slug: {\n type: 'string'\n },\n order: {\n Value: Order\n },\n saveStatus: {\n Value: Object\n },\n canPlaceOrder: {\n get() {\n let items = this.attr('order.items');\n return items.attr('length');\n }\n }\n },\n\n placeOrder() {\n let order = this.attr('order');\n order.attr('restaurant', this.attr('restaurant._id'));\n this.attr('saveStatus', order.save());\n return false;\n },\n\n startNewOrder() {\n this.attr('order', new Order());\n this.attr('saveStatus', null);\n return false;\n }\n});\n\nexport default Component.extend({\n tag: 'pmo-order-new',\n viewModel: ViewModel,\n template\n});\n\n```\n\nHere we just define the properties that we need: `slug`, `order`, `canPlaceOrder` - which we will use to enable/disable the submit button - and `saveStatus`, which will become a Deferred once the order is submitted. `placeOrder` updates the order with the restaurant information and saves the current order. `startNewOrder` allows us to submit another order.\n\nWhile we're here we can also update our test to get it passing again, replace `src/order/new/new_test.js` with:\n\n\n```js\nimport QUnit from 'steal-qunit';\nimport { ViewModel } from './new';\n\n// ViewModel unit tests\nQUnit.module('place-my-order/order/new');\n\nQUnit.test('canPlaceOrder', function(){\n var vm = new ViewModel({\n order: { items: [1] }\n });\n QUnit.equal(vm.attr('canPlaceOrder'), true, 'can place an order');\n});\n\n```\n\n### Write the template\n\nFirst, let's implement a small order confirmation component with\n\n```\ndonejs add component order/details.component pmo-order-details\n```\n\nand changing `src/order/details.component` to:\n\n\n```html\n\n \n\n\n```\n\nNow we can import that component and update `src/order/new/new.stache` to:\n\n\n```html\n\n\n\n
\n \n {{#if isPending}}\n
\n {{else}}\n {{#value}}\n {{#if saveStatus.isResolved}}\n \n

\n Place another order\n

\n {{else}}\n

Order from {{name}}

\n\n
\n \n

\n {{^if order.items.length}}\n Please choose an item\n {{else}}\n {{order.items.length}} selected\n {{/if}}\n

\n \n
    \n {{#each menu.lunch}}\n
  • \n \n
  • \n {{/each}}\n
\n
\n \n
    \n {{#each menu.dinner}}\n
  • \n \n
  • \n {{/each}}\n
\n
\n
\n\n
\n \n \n

Please enter your name.

\n
\n
\n \n \n

Please enter your address.

\n
\n
\n \n \n

Please enter your phone number.

\n
\n
\n

Total: ${{order.total}}

\n {{#if saveStatus.isPending}}\n
\n {{else}}\n \n {{/if}}\n
\n
\n {{/if}}\n {{/value}}\n {{/if}}\n
\n
\n\n```\n\nThis is a longer template so lets walk through it:\n\n- `` loads the order details component we previously created\n- `` loads a restaurant based on the slug value passed to the component\n- If the `saveStatus` deferred is resolved we show the `pmo-order-details` component with that order\n- Otherwise we will show the order form with the `bit-tabs` panels we implemented in the previous chapter and iterate over each menu item]\n- `(submit)=\"{placeOrder}\"` will call `placeOrder` from our view model when the form is submitted\n- The interesting part for showing a menu item is the checkbox ``\n - `(change)` binds to the checkbox change event and runs `order.items.toggle` which toggles the item from `ItemList`, which we created in the model\n - `order.item.has` sets the checked status to whether or not this item is in the order\n- Then we show form elements for name, address, and phone number, which are bound to the order model using [can-value](http://canjs.com/docs/can.view.bindings.can-value.html)\n- Finally we disable the button with `{{^if canPlaceOrder}}disabled{{/if}}` which calls `canPlaceOrder` from the view model and returns false if no menu items are selected.\n\n## Set up a real-time connection\n\ncan-connect makes it very easy to implement real-time functionality. It is capable of listening to notifications from the server when server data has been created, updated, or removed. This is usually accomplished via [websockets](https://en.wikipedia.org/wiki/WebSocket), which allow sending push notifications to a client.\n\n### Adding real-time events to a model\n\nThe `place-my-order-api` module uses the [Feathers](http://feathersjs.com/) NodeJS framework, which in addition to providing a REST API, sends those events in the form of a websocket event like `orders created`. To make the order page update in real-time, all we need to do is add listeners for those events to `src/models/order.js` and in the handler notify the order connection.\n\n```\nnpm install steal-socket.io --save\n```\n\nIn `src/models/order.js` replace with:\n\n\n```js\nimport superMap from 'can-connect/can/super-map/';\nimport tag from 'can-connect/can/tag/';\nimport List from 'can/list/';\nimport Map from 'can/map/';\nimport 'can/map/define/';\nimport io from 'steal-socket.io';\n\nconst ItemsList = List.extend({}, {\n has: function(item) {\n return this.indexOf(item) !== -1;\n },\n\n toggle: function(item) {\n var index = this.indexOf(item);\n\n if (index !== -1) {\n this.splice(index, 1);\n } else {\n this.push(item);\n }\n }\n});\n\nlet Order = Map.extend({\n define: {\n status: {\n value: 'new'\n },\n items: {\n Value: ItemsList\n },\n total: {\n get() {\n let total = 0.0;\n this.attr('items').forEach(item =>\n total += parseFloat(item.attr('price')));\n return total.toFixed(2);\n }\n }\n },\n\n markAs(status) {\n this.attr('status', status);\n this.save();\n }\n});\n\nexport const connection = superMap({\n url: '/api/orders',\n idProp: '_id',\n Map: Order,\n List: Order.List,\n name: 'orders'\n});\n\nconst socket = io();\n\nsocket.on('orders created', order => connection.createInstance(order));\nsocket.on('orders updated', order => connection.updateInstance(order));\nsocket.on('orders removed', order => connection.destroyInstance(order));\n\ntag('order-model', connection);\n\nexport default Order;\n\n```\n\n### Update the template\n\nThat's all the JavaScript we need to implement real-time functionality. All the rest can be done by creating the `pmo-order-list` component with:\n\n```\ndonejs add component order/list.component pmo-order-list\n```\n\nChanging `src/order/list.component` to:\n\n\n```html\n\n \n\n\n```\n\nAnd in the order history template by updating `src/order/history.component` to:\n\n\n```html\n\n \n\n\n```\n\nFirst we import the order model and then just call `'}\">` for each order status. That's it. If we now open the order page we see some already completed default orders. Keeping the page open and placing a new order from another browser or device will update our order page automatically.\n\n## Create documentation\n\nDocumenting our code is very important to quickly get other developers up to speed. [DocumentJS](http://documentjs.com/) makes documenting code easier. It will generate a full documentation page from Markdown files and code comments in our project.\n\n### Configuring DocumentJS\n\nWhen we initialized the application all the infrastructure necessary to generate the documentation has already been set up. New modlet components will be added automatically. We can generate the documentation with:\n\n```\ndonejs document\n```\n\nThis produces documentation at [http://localhost:8080/docs/](http://localhost:8080/docs/).\n\n### Documenting a module\n\nLet's add the documentation for a module. Let's use `src/order/new/new.js` and update it with some inline comments that describe what our view model properties are supposed to do:\n\n\n```js\nimport Component from 'can/component/component';\nimport Map from 'can/map/';\nimport 'can/map/define/';\nimport template from './new.stache';\nimport Restaurant from 'place-my-order/models/restaurant';\nimport Order from 'place-my-order/models/order';\n\n/**\n * @add place-my-order/order/new\n */\nexport const ViewModel = Map.extend({\n define: {\n /**\n * @property {String} slug\n *\n * The restaurants slug (short name). Will\n * be used to request the actual restaurant.\n */\n slug: {\n type: 'string'\n },\n /**\n * @property {place-my-order/models/order} order\n *\n * The order that is being processed. Will\n * be an empty new order inititally.\n */\n order: {\n Value: Order\n },\n /**\n * @property {can.Deferred} saveStatus\n *\n * A deferred that contains the status of the order when\n * it is being saved.\n */\n saveStatus: {\n Value: Object\n },\n /**\n * @property {Boolean} canPlaceOrder\n *\n * A flag to enable / disable the \"Place my order\" button.\n */\n canPlaceOrder: {\n get() {\n let items = this.attr('order.items');\n return items.attr('length');\n }\n }\n },\n\n /**\n * @function placeOrder\n *\n * Save the current order and update the status Deferred.\n *\n * @return {boolean} false to prevent the form submission\n */\n placeOrder() {\n let order = this.attr('order');\n this.attr('saveStatus', order.save());\n return false;\n },\n\n /**\n * @function startNewOrder\n *\n * Resets the order form, so a new order can be placed.\n *\n * @return {boolean} false to prevent the form submission\n */\n startNewOrder: function() {\n this.attr('order', new Order());\n this.attr('saveStatus', null);\n return false;\n }\n});\n\nexport default Component.extend({\n tag: 'pmo-order-new',\n viewModel: ViewModel,\n template\n});\n\n```\n\nIf we now run `donejs document` again, we will see the module show up in the menu bar and will be able to navigate through the different properties.\n\n## Production builds\n\nNow we're ready to create a production build; go ahead and kill your development server, we won't need it from here on.\n\n### Progressive loading\n\nOur `index.stache` contains a can-import tag for each of the pages we have implemented. These can-imports which have nested html will be progressively loaded; the restaurant list page's JavaScript and CSS will only be loaded when the user visits that page.\n\n### Bundling your app\n\nTo bundle our application for production we use the build script in `build.js`. We could also use [Grunt](http://gruntjs.com/) or [Gulp](http://gulpjs.com/), but in this example we just run it directly with Node. Everything is set up already so we run:\n\n```\ndonejs build\n```\n\nThis will build the application to a `dist/` folder in the project's base directory.\n\nFrom here your application is ready to be used in production. Enable production mode by setting the `NODE_ENV` variable:\n\n```\nNODE_ENV=production donejs start\n```\n\nIf you're using Windows omit the NODE_ENV=production in the command, and instead see the [setting up guide](SettingUp.html#section=section_EnvironmentalVariables) on how to set environment variables.\n\nRefresh your browser to see the application load in production.\n\n## Desktop and mobile apps\n\n### Building to iOS and Android\n\nTo build the application as a Cordova based mobile application, you need to have each platform's SDK installed.\nWe'll be building an iOS app if you are a Mac user, and an Android app if you're a Windows user.\n\nMac users should download XCode from the AppStore and install the `ios-sim` package globally with:\n\n```\nnpm install -g ios-sim\n```\n\nWe will use these tools to create an iOS application that can be tested in the iOS simulator.\n\nWindows users should install the [Android Studio](https://developer.android.com/sdk/index.html), which gives all of the tools we need. See the [setting up guide](SettingUp.html#section=section_AndroidDevelopment) for full instructions on setting up your Android emulator.\n\nNow we can install the DoneJS Cordova tools with:\n\n```\ndonejs add cordova\n```\n\nDepending on your operating system you can accept most of the defaults, unless you would like to build for Android, which needs to be selected from the list of platforms.\n\nThis will change your `build.js` script with the options needed to build iOS/Android apps. Open this file and add the place-my-order-asset images to the **glob** property:\n\n```\nvar cordovaOptions = {\n buildDir: \"./build/cordova\",\n id: \"com.donejs.placemyorder\",\n name: \"place my order\",\n platforms: [\"ios\"],\n plugins: [\"cordova-plugin-transport-security\"],\n index: __dirname + \"/production.html\",\n glob: [\n \"node_modules/steal/steal.production.js\",\n \"node_modules/place-my-order-assets/images/**/*\"\n ]\n};\n```\n\n\n#### AJAX\n\nWhen not running in a traditional browser environment, AJAX requests need to be made\nto an external URL. The module `steal-platform` aids in detecting environments like Cordova\nso special behavior can be added. Install the module:\n\n```\nnpm install steal-platform --save\n```\n\nCreate a file: `src/service-base-url.js` and place this code:\n\n```js\nimport platform from \"steal-platform\";\n\nlet baseUrl = '';\n\nif(platform.isCordova || platform.isNW) {\n baseUrl = 'http://www.place-my-order.com';\n}\n\nexport default baseUrl;\n```\n\nThis detects if the environment running your app is either Cordova or NW.js and if so sets the baseUrl to place-my-order.com so that all AJAX requests will be made there.\n\nOur models will also need to be updated to use the baseUrl. For example in `src/models/state` do:\n\n```js\nimport can from 'can';\nimport superMap from 'can-connect/can/super-map/';\nimport tag from 'can-connect/can/tag/';\nimport 'can/map/define/define';\nimport baseUrl from '../service-base-url';\n\nexport const State = can.Map.extend({\n define: {}\n});\n\nState.List = can.List.extend({\n Map: State\n}, {});\n\nexport const stateConnection = superMap({\n url: baseUrl + '/api/states',\n idProp: 'short',\n Map: State,\n List: State.List,\n name: 'state'\n});\n\ntag('state-model', stateConnection);\n\nexport default State;\n```\n\nMake this same change in `src/models/city.js` and `src/models/restaurant.js`.\n\nFor `src/models/order`, you must also update the socket connection:\n\n```js\nimport superMap from 'can-connect/can/super-map/';\nimport tag from 'can-connect/can/tag/';\nimport List from 'can/list/';\nimport Map from 'can/map/';\nimport 'can/map/define/';\nimport io from 'steal-socket.io';\nimport baseUrl from '../service-base-url';\n\nconst ItemsList = List.extend({}, {\n has: function(item) {\n return this.indexOf(item) !== -1;\n },\n\n toggle: function(item) {\n var index = this.indexOf(item);\n\n if (index !== -1) {\n this.splice(index, 1);\n } else {\n this.push(item);\n }\n }\n});\n\nlet Order = Map.extend({\n define: {\n status: {\n value: 'new'\n },\n items: {\n Value: ItemsList\n },\n total: {\n get() {\n let total = 0.0;\n this.attr('items').forEach(item =>\n total += parseFloat(item.attr('price')));\n return total.toFixed(2);\n }\n }\n },\n\n markAs(status) {\n this.attr('status', status);\n this.save();\n }\n});\n\nexport const connection = superMap({\n url: baseUrl + '/api/orders',\n idProp: '_id',\n Map: Order,\n List: Order.List,\n name: 'orders'\n});\n\nconst socket = io(baseUrl);\n\nsocket.on('orders created', order => connection.createInstance(order));\nsocket.on('orders updated', order => connection.updateInstance(order));\nsocket.on('orders removed', order => connection.destroyInstance(order));\n\ntag('order-model', connection);\nwindow.orderConnection = connection;\nexport default Order;\n```\n\n\nTo run the Cordova build and launch the simulator we can now run:\n\n```\ndonejs build cordova\n```\n\nIf everything went well, we should see the emulator running our application.\n\n### Building to NW.js\n\nTo set up the desktop build, we have to add it to our application like this:\n\n```\ndonejs add nw\n```\n\nWe can answer most prompts with the default except for the version which needs to be set to the latest **stable version**. Set the version prompt to `0.12.3`.\n\nLike with Cordova, we need to add the place-my-order-assets images to the build, open your `build.js` script and update the **glob** property to reflect:\n\n```js\nvar nwOptions = {\n buildDir: \"./build\",\n version: \"0.12.3\",\n platforms: [\"osx32\",\"osx64\"],\n glob: [\n \"package.json\",\n \"production.html\",\n \"node_modules/steal/steal.production.js\",\n \"node_modules/place-my-order-assets/images/**/*\"\n ]\n};\n```\n\nThen we can run the build like this:\n\n```\ndonejs build nw\n```\n\nThe OS X application can be opened with\n\n```\nopen build/place-my-order/osx64/place-my-order.app\n```\n\nThe Windows application can be opened with\n\n```\n.\\build\\place-my-order\\win64\\place-my-order.exe\n```\n\n## Deploy\n\nNow that we verified that our application works in production, we can deploy it to the web. In this section, we will use [Firebase](https://www.firebase.com/), a service that provides static file hosting and [Content Delivery Network](https://en.wikipedia.org/wiki/Content_delivery_network) (CDN) support, to automatically deploy and serve our application's static assets from a CDN and [Heroku](https://heroku.com) to provide server-side rendering.\n\n### Bundling assets\n\nLikely you have assets in your project other than your JavaScript and CSS that you will need to deploy to production. Place My Order has these assets saved to another project, you can view them at `node_modules/place-my-order-assets/images`.\n\nStealTools comes with the ability to bundle all of your static assets into a folder that can be deployed to production by itself. Think if it as a zip file that contains everything your app needs to run in production.\n\nTo use this capability add an option to your build script to enable it. Change:\n\n```js\nvar buildPromise = stealTools.build({\n config: __dirname + \"/package.json!npm\"\n}, {\n bundleAssets: true\n});\n```\n\nto:\n\n```js\nvar buildPromise = stealTools.build({\n config: __dirname + \"/package.json!npm\"\n}, {\n bundleAssets: {\n infer: false,\n glob: \"node_modules/place-my-order-assets/images/**/*\"\n }\n});\n```\n\n\nStealTools will find all of the assets you reference in your CSS and copy them to the dist folder. By default StealTools will set your [bundlesPath](http://stealjs.com/docs/System.bundlesPath.html) to `dist/bundles`, and will place the place-my-order-assets images in `dist/node_modules/place-my-order/assets/images`. bundleAssets preserves the path of your assets so that their locations are the same relative to the base url in both development and production.\n\n### Static hosting on Firebase\n\nSign up for free at [Firebase](https://firebase.google.com/). After you have an account go to [Firebase console](https://console.firebase.google.com/) and create an app called `place-my-order-` where `` is your GitHub username:\n\n\"two\n\nWrite down the name of your app because you'll need it in the next section.\n\n> You will get an error if your app name is too long, so pick something on the shorter side, for example `pmo-`.\n\nWhen you deploy for the first time it will ask you to authorize with your login information, but first we need to configure the project.\n\n#### Configuring DoneJS\n\nWith the Firebase account and application in place we can add the deployment configuration to our project like this:\n\n```\ndonejs add firebase\n```\n\nWhen prompted, enter the name of the application created when you set up the Firebase app. Next, login to the firebase app for the first time by running:\n\n```\nnode_modules/.bin/firebase login\n```\n\nAnd authorize your application.\n\n#### Run deploy\n\nWe can now deploy the application by running:\n\n```\ndonejs build\ndonejs deploy\n```\n\nStatic files are deployed to Firebase and we can verify that the application is loading from the CDN by loading it running:\n\n```\nNODE_ENV=production donejs start\n```\n\n> If you're using Windows, set the NODE_ENV variable as you did previously in the Production section.\n\nWe should now see our assets being loaded from the Firebase CDN like this:\n\n![A network tab when using the CDN](static/img/guide-firebase-network.png)\n\n### Deploy your Node code\n\nAt this point your application has been deployed to a CDN. This contains StealJS, your production bundles and CSS, and any images or other static files. You still need to deploy your server code in order to get the benefit of server-side rendering.\n\nIf you do not have an account yet, sign up for Heroku at [signup.heroku.com](https://signup.heroku.com/). Then download the [Heroku CLI](https://devcenter.heroku.com/articles/heroku-command) which will be used to deploy.\n\nAfter installing we can initialize the application via\n\n```\nheroku login\nheroku create\n```\n\nThis will return the url where your app can be viewed. Before you open it you'll need to update the NODE_ENV variable:\n\n```\nheroku config:set NODE_ENV=production\n```\n\nAdd a new `Procfile` that tells Heroku what to launch as the app's server. Since we are using done-serve our Procfile just looks like this:\n\n```\nweb: node_modules/.bin/done-serve --proxy http://www.place-my-order.com/api\n```\n\nFirst let's save our current status:\n\n```\ngit add -A\ngit commit -m \"Finishing place-my-order\"\ngit push origin master\n```\n\nSince Heroku needs the build artifacts we need to commit those before pushing to Heroku. We recommend doing this in a separate branch.\n\n```\ngit checkout -b deploy\ngit add -f dist\ngit commit -m \"Deploying to Heroku\"\n```\n\nAnd finally do an initial deploy.\n\n```\ngit push heroku deploy:master\n```\n\nAny time in the future you want to deploy simply push to the Heroku remote. Once the deploy is finished you can open the link provided in your browser. If successful we can checkout the _master_ branch:\n\n```\ngit checkout master\n```\n\n### Continuous Deployment\n\nPreviously we set up Travis CI [for automated testing](#section=section_Continuousintegration) of our application code as we developed, but Travis (and other CI solutions) can also be used to deploy our code to production once tests have passed.\n\nOpen your `.travis.yml` file and add `before_deploy` and `deploy` keys that look like this:\n\n```yaml\nlanguage: node_js\nnode_js: node\nbefore_install:\n - \"export DISPLAY=:99.0\"\n - \"sh -e /etc/init.d/xvfb start\"\nbefore_deploy:\n - \"git config --global user.email \\\"me@example.com\\\"\"\n - \"git config --global user.name \\\"PMO deploy bot\\\"\"\n - \"node build\"\n - \"git add dist/ --force\"\n - \"git commit -m \\\"Updating build.\\\"\"\n - \"node_modules/.bin/firebase deploy --token \\\"$FIREBASE_TOKEN\\\"\"\ndeploy:\n skip_cleanup: true\n provider: \"heroku\"\n app: \n```\n\n\nYou can find the name of the app by running `heroku apps:info`.\n\nIn order to deploy to Heroku you need to provide Travis with your Heroku API key. Sensitive information in our `.travis.yml` should always be encrypted for which we install the [travis-encrypt](https://www.npmjs.com/package/travis-encrypt) module:\n\n*Note: if using Windows, first install the OpenSSL package as described in the [Setting Up](https://donejs.com/SettingUp.html) guide.*\n\n```\nnpm install travis-encrypt -g\n```\n\nNow we can get the Heroku authentication token with:\n\n```\nheroku auth:token\n```\n\nCopy the token printed and paste it as `` in the following command:\n\n```\ntravis-encrypt --add deploy.api_key -r /place-my-order \n```\n\nReplace `` with the name of your GitHub account.\n\nTo automate the deploy to Firebase you need to provide the Firebase CI token. You can get the token by running:\n\n```\nnode_modules/.bin/firebase login:ci\n```\n\nIn the application folder. It will open a browser window and ask you to authorize the application. Once successful, copy the token and use it as the `` in the following command:\n\n```\ntravis-encrypt --add -r /place-my-order 'FIREBASE_TOKEN=\"\"'\n```\n\nNow any time a build succeeds when pushing to `master` the application will be deployed to Heroku and static assets to Firebase's CDN.\n\nTo test this out checkout a new branch:\n\n```\ngit checkout -b continuous\ngit add -A\ngit commit -m \"Trying out continuous deployment\"\ngit push origin continuous\n```\n\nVisit your GitHub page, create a pull-request, wait for tests to pass and then merge. Visit your Travis CI build page at [https://travis-ci.org//place-my-order](https://travis-ci.org//place-my-order) to see the deployment happening in real time like this:\n\n![The Travis CI deploy](static/img/guide-travis-deploy.png)\n\n## What's next?\n\nIn this final short chapter, let's quickly look at what we did in this guide and where to follow up for any questions.\n\n### Recap\n\nIn this in-depth guide we created and deployed a fully tested restaurant menu ordering application called [place-my-order](http://www.place-my-order.com/) with DoneJS. We learned how to set up a DoneJS project, create custom elements and retrieve data from the server. Then we implemented a unit-tested view-model, ran those tests automatically from the command line and on a continuous integration server.\n\nWe went into more detail on how to create nested routes and importing other projects from NPM. Then we created new orders and made it real-time, added and built documentation and made a production build. Finally we turned that same application into a desktop- and mobile application and deployed it to a CDN and the web.\n\n### Following up\n\nYou can learn more about each of the individual projects that DoneJS includes at:\n\n- [StealJS](http://stealjs.com) - ES6, CJS, and AMD module loader and builder\n- [CanJS](http://canjs.com) - Custom elements and Model-View-ViewModel utilities\n- [jQuery](http://jquery.com) - DOM helpers\n- [jQuery++](http://jquerypp.com) - Extended DOM helpers\n- [QUnit](https://qunitjs.com/) or Mocha - Assertion library\n- [FuncUnit](http://funcunit.com) - Functional tests\n- [Testee](https://github.com/bitovi/testee) - Test runner\n- [DocumentJS](http://documentjs.com) - Documentation\n\nIf you have any questions, do not hesitate to ask us on [Gitter](https://gitter.im/donejs/donejs) or the [forums](http://forums.donejs.com)!\n\n", - "description": "In this guide you will learn about all of [DoneJS' features]() by creating, testing, documenting, building and deploying [place-my-order.com](http://place-my-order.com), a restaurant menu and ordering application. The final result will look like this: \n\n\n\n\nAfter the initial application setup, which includes a server that hosts and pre-renders the application, we will create several custom elements and bring them together using the application state and routes. Then we will learn how to retrieve data from the server using a RESTful API.\n\nAfter that we will talk about what a view model is and how to identify, implement and test its functionality. Once we have unit tests running in the browser, we will automate running them locally from the command line and also on a continuous integration server. In the subsequent chapters, we will show how to easily import other modules into our application and how to set up a real-time connection.\n\nFinally, we will describe how to build and deploy our application to the web, as a desktop application with nw.js, and as a mobile app with Cordova.\n\n\n", - "name": "place-my-order", - "title": "In depth guide", + "body": "\n## Setup\n\nIn this section, we will install DoneJS and generate a new application.\n\n### Install DoneJS\n\nTo get started, let's install the DoneJS command line utility globally:\n\n```\nnpm install -g donejs\n```\n\n### Generate the application\n\nThen we'll create a new DoneJS application called `donejs-chat`:\n\n```\ndonejs add app donejs-chat\n```\n\nThis will create a new folder called `donejs-chat` and in it generate our application.\n\nThe initialization process will ask questions like the name of your application, the source folder, etc. We'll answer these with the default settings by hitting enter.\n\n\"donejs\n\nThis will install all of DoneJS's dependencies, including the following:\n\n- [StealJS](http://stealjs.com) - ES6, CJS, and AMD module loader and builder\n- [CanJS](http://canjs.com) - Custom elements and Model-View-ViewModel utilities\n- [jQuery](http://jquery.com) - DOM helpers\n- [jQuery++](http://jquerypp.com) - Extended DOM helpers\n- [QUnit](https://qunitjs.com/) - Assertion library (optionally: [Mocha] or [Jasmine])\n- [FuncUnit](http://funcunit.com) - Functional tests\n- [Testee](https://github.com/bitovi/testee) - JavaScript Test runner\n\n### Turn on development mode\n\nDoneJS comes with its own development server, which hosts your development files and automatically [renders the application on the server](Features.html#section=section_ServerSideRendered). Development mode enables [hot module swapping](Features.html#section=section_HotModuleSwapping), which automatically reloads files in the browser and on the server as they change.\n\nTo start it let's go into the `donejs-chat` application directory:\n\n```\ncd donejs-chat\n```\n\nWe can start development mode by running:\n\n```\ndonejs develop\n```\n\nThe default port is `8080`.\n\nGo to [http://localhost:8080/](localhost:8080) to see our application showing a default homepage.\n\n\"hello\n\n## Adding Bootstrap\n\nDoneJS makes it easy to import other projects that are published on [NPM](https://npmjs.org). In this section we will install and add [Bootstrap](http://getbootstrap.com/) to the page and see DoneJS's [hot module swapping](Features.html#section=section_HotModuleSwapping) in action.\n\n### Install the NPM package\n\nOpen a new terminal window so we can keep the DoneJS development server running. Then, install the [Bootstrap NPM package](https://www.npmjs.com/package/bootstrap) and save it as a dependency of our application like this:\n\n```\nnpm install bootstrap --save\n```\n\n### Add it to the page\n\nTo see hot module swapping in action, let's update the main template to import Bootstrap's LESS file and also add some HTML that uses its styles.\n\nUpdate `src/index.stache` to look like this:\n\n> The highlighted lines have been added or changed.\n\n\n```html\n\n \n {{title}}\n \n \n \n \n \n\n
\n
\n
\n

\n \"DoneJS\n
Chat\n

\n
\n
\n
\n\n {{#switch env.NODE_ENV}}\n {{#case \"production\"}}\n \n {{/case}}\n {{#default}}\n \n {{/default}}\n {{/switch}}\n \n\n\n```\n\nIf you kept your browser window open at [http://localhost:8080/](localhost:8080) you should see the updated styles and content as soon as you save the file.\n\n\"donejs\n\nFeel free to edit the HTML or `src/styles.less` to see how hot module swapping updates the page automatically.\n\n## Routing and components\n\nIn this part we will create our own custom HTML elements - one for the homepage and another to display the chat messages. Then we will create routes to navigate between these two pages.\n\n### Generate custom elements\n\nWe'll use a DoneJS [generator](/Features.html#section=section_Generators) to create custom components. The component generator is run by typing `donejs add component `.\n\nThe homepage custom element (with the HTML tag name `chat-home`) won't be very big or complex, so we'll put everything into a single `.component` file.\n\nTo generate it, run:\n\n```\ndonejs add component home.component chat-home\n```\n\nThe messages component (with the tag `chat-messages`) will be a little more complex, so we'll generate it using the [modlet file pattern](Features.html#section=section_Modlets).\n\n\nNow run:\n\n```\ndonejs add component messages chat-messages\n```\n\n\"chat.donejs.com\"\n\nLater we will update the generated files with the chat messages functionality.\n\n### Navigate between pages\n\n> Routing works a bit differently than other libraries. In other libraries, you might declare routes and map those to controller-like actions. DoneJS application [routes](http://canjs.com/docs/can.route.html) map URL strings (like /user/1) to properties on our application's view-model. In other words, our routes will just be a representation of the application state. To learn more about routing visit the CanJS guide on [Application State and Routing](http://canjs.com/guides/AppStateAndRouting.html).\n\nFirst, let's update `src/home.component` with the original content from the homepage and a link to the chat messages page:\n\n\n```html\n\n \n \n \n

\n \"DoneJS\n
Chat\n

\n\n \n Start chat\n \n
\n
\n\n```\n\n> [`routeUrl`](http://canjs.com/docs/can.stache.helpers.routeUrl.html) is a helper that populates the anchor's href with a URL that sets the application ViewModel's `page` property to `\"chat\"`. The AppViewModel is shown below.\n\nNext, add a link to go back to the homepage from the chat page by updating `src/messages/messages.stache` to:\n\n\n```html\n\n
Home
\n

{{message}}

\n\n```\n\nThen, add a routing rule for the `page` property in `src/app.js`:\n\n\n```js\nimport DefineMap from 'can-define/map/';\nimport route from 'can-route';\nimport 'can-route-pushstate';\n\nconst AppViewModel = DefineMap.extend({\n page: 'string',\n title: {\n value: 'donejs-chat',\n serialize: false\n }\n});\n\nroute('/{page}', { page: 'home' });\n\nexport default AppViewModel;\n\n```\n\n### Switch between pages\n\nFinally, we'll glue both components together as separate pages in `src/index.stache`. This is done by adding dynamic imports for the `home.component` and `messages/` components and showing each import based on the `page` property.\n\nUpdate `src/index.stache` to:\n\n\n```html\n\n \n {{title}}\n \n \n \n \n \n\n
\n
\n
\n {{#eq page 'chat'}}\n \n {{#if isPending}}\n Loading...\n {{else}}\n \n {{/if}}\n \n {{else}}\n \n {{#if isPending}}\n Loading...\n {{else}}\n \n {{/if}}\n \n {{/eq}}\n
\n
\n
\n\n {{#switch env.NODE_ENV}}\n {{#case \"production\"}}\n \n {{/case}}\n {{#default}}\n \n {{/default}}\n {{/switch}}\n \n\n\n```\n\nNow each component is being dynamically loaded while navigating between the home and messages page. You should see the changes already in your browser.\n\n\"chat.donejs.com\"\n\nAlso, everything is [rendered on the server](Features.html#section=section_ServerSideRendered). If you reload the homepage at [localhost:8080](http://localhost:8080) you'll see the page's content right away, while the JavaScript is loading in the background. Viewing the source will show the dynamically inserted styles and the corresponding HTML.\n\n\"chat.donejs.com\"\n\n\n## Homepage\n\nNow that we can navigate between pages, we will finish implementing their functionality, starting with the homepage.\n\n\n### Install bit-tabs\n\nOn the homepage, let's install and add [bit-tabs](https://github.com/bitovi-components/bit-tabs), a simple declarative tabs widget.\n\nRun:\n\n```\nnpm install bit-tabs --save\n```\n\n### Update the page\n\nThen, import the unstyled custom elements from `bit-tabs/unstyled` (unstyled because we will use Bootstrap's styles) and add `` and `` elements to the template.\n\nUpdate `src/home.component` to:\n\n\n```html\n\n \n \n \n \n

\n \"DoneJS\n
Chat\n

\n\n \n \n

CanJS provides the MV*

\n
\n \n

StealJS provides the infrastructure.

\n
\n
\n\n \n Start chat\n \n
\n
\n\n```\n\nYou'll notice tabs appear in the browser:\n\n\"chat.donejs.com\"\n\n## Messages page\n\nIn this section we add live chat functionality to the messages page. We'll need to:\n\n * Create a messages model that connects to a RESTful API.\n * Add the ability to retrieve and list messages and create new messages.\n * Make the message list receive real-time updates from other clients.\n\n### Generate Message model\n\nTo load messages from the server, we will use [can-connect's supermodel](http://connect.canjs.com/doc/can-connect%7Ccan%7Csuper-map.html).\n\nGenerate a `message` supermodel like this:\n\n```\ndonejs add supermodel message\n```\n\nWhen asked for the URL endpoint, set it to our remote RESTful API at `http://chat.donejs.com/api/messages`. The other questions can be answered with the default by hitting enter.\n\n\"model\n\nUpdate `src/models/message.js` to:\n\n\n```js\nimport DefineMap from 'can-define/map/';\nimport DefineList from 'can-define/list/';\nimport superMap from 'can-connect/can/super-map/';\nimport tag from 'can-connect/can/tag/';\n\nexport const Message = DefineMap.extend({\n seal: false\n}, {\n id: '*',\n name: 'string',\n body: 'string'\n});\n\nMessage.List = DefineList.extend({\n '*': Message\n});\n\nexport const messageConnection = superMap({\n url: 'http://chat.donejs.com/api/messages',\n idProp: 'id',\n Map: Message,\n List: Message.List,\n name: 'message'\n});\n\ntag('message-model', messageConnection);\n\nexport default Message;\n\n```\n\n### Use the connection\n\nThe generated file is all that is needed to connect to our RESTful API. Use it by importing it and requesting a list of all messages with the `` custom element.\n\nUpdate `src/messages/messages.stache` to:\n\n\n```html\n\n\n
Home
\n\n\n {{#each ./value}}\n
\n

{{name}}

\n

{{body}}

\n
\n {{else}}\n
\n

No messages

\n
\n {{/each}}\n
\n\n```\n\nIf you open [localhost:8080/chat](http://localhost:8080/chat), you will see a list of messages from the server or the \"No message\" text.\n\n\"chat.donejs.com\"\n\n### Create messages\n\nNow let's add the form to create new messages. The form two-way binds the `name` and `body` properties to the component's view-model and calls `send()` when hitting the enter key in the message input.\n\nUpdate `src/messages/messages.stache` to look like this:\n\n\n```html\n\n\n
Home
\n\n\n {{#each ./value}}\n
\n

{{name}}

\n

{{body}}

\n
\n {{else}}\n
\n

No messages

\n
\n {{/each}}\n
\n\n
\n
\n \n
\n
\n \n
\n
\n \n
\n
\n\n```\n\nNext we have to implement the `send()` method. Update `src/messages/messages.js` to this:\n\n\n```js\nimport Component from 'can-component';\nimport DefineMap from 'can-define/map/';\nimport './messages.less';\nimport view from './messages.stache';\nimport Message from '../models/message';\n\nexport const ViewModel = DefineMap.extend({\n name: 'string',\n body: 'string',\n\n send(event) {\n event.preventDefault();\n\n new Message({\n name: this.name,\n body: this.body\n }).save().then(msg => this.body = '');\n }\n});\n\nexport default Component.extend({\n tag: 'chat-messages',\n ViewModel: ViewModel,\n view\n});\n\n```\n\nThe `send()` method takes the `name` and `message` properties from the view-model and creates a `Message` instance, saving it to the server. Once saved successfully, it sets the message to an empty string to reset the input field.\n\nYou can now enter your name and a message! It will automatically appear in our messages list.\n\n\"chat.donejs.com\"\n\nIn fact, all lists that are related to that model will be updated automatically whenever there is new, modified, or deleted data. [can-connect](http://connect.canjs.com/) automatically manages the lists, while also providing [caching and minimized data requests](Features.html#section=section_Cachingandminimaldatarequests).\n\nYou can see from your console that the localStorage cache is already populated with data:\n\n\"chat.donejs.com\"\n\n### Enable a real-time connection\n\nRight now our chat's messages update automatically with our own messages, but not with messages from other clients. The API server ([chat.donejs.com/api/messages](http://chat.donejs.com/api/messages)) provides a [Socket.io](http://socket.io/) server that sends out real-time updates for new, updated and deleted chat messages.\n\nTo connect to it, first we'll install a socket.io connector, by running:\n\n```\nnpm install steal-socket.io@2 --save\n```\n\nUpdate `src/models/message.js` to:\n\n\n```js\nimport DefineMap from 'can-define/map/';\nimport DefineList from 'can-define/list/';\nimport superMap from 'can-connect/can/super-map/';\nimport tag from 'can-connect/can/tag/';\nimport io from 'steal-socket.io';\n\nexport const Message = DefineMap.extend({\n seal: false\n}, {\n id: '*',\n name: 'string',\n body: 'string'\n});\n\nMessage.List = DefineList.extend({\n '*': Message\n});\n\nexport const messageConnection = superMap({\n url: 'http://chat.donejs.com/api/messages',\n idProp: 'id',\n Map: Message,\n List: Message.List,\n name: 'message'\n});\n\ntag('message-model', messageConnection);\n\nconst socket = io('http://chat.donejs.com');\n\nsocket.on('messages created',\n message => messageConnection.createInstance(message));\nsocket.on('messages updated',\n message => messageConnection.updateInstance(message));\nsocket.on('messages removed',\n message => messageConnection.destroyInstance(message));\n\nexport default Message;\n\n```\n\nThis will listen to `messages ` events sent by the server and tell the connection to update all active lists of messages accordingly. Try opening another browser window to see receiving messages in real-time.\n\n\"two\n\n## Production build\n\nNow that we implemented the complete chat functionality we can get our application ready for production.\n\n### Run build\n\nWe can find the build configuration in `build.js` in the application folder.\n\nEverything is already set up, so we can simply make a build by running:\n\n```\ndonejs build\n```\n\nThe optimized bundles that load your JavaScript and CSS as fast as possible are sent to the `dist/` folder.\n\n### Turn on production\n\nTo test the production build, close the current server (with `CTRL + C`) and start it with the environment (`NODE_ENV`) set to `production`:\n\n```\nNODE_ENV=production donejs start\n```\n\nIf you're using Windows, you must first set the environmental variable:\n\n1. For Windows **command prompt** you set with `set NODE_ENV=production`\n1. For Windows **Powershell** you set it with `$env:NODE_ENV=\"production\"`\n\nThen run your application with `donejs start`.\n\nIf we now open [localhost:8080](http://localhost:8080/) again we can see the production bundles being loaded in the network tab of the developer tools.\n\n\"two\n\nAll DoneJS projects are extremely modular, which is why in development mode, you see 200 or more requests when loading the page (thanks to hot module swapping we only have to make those requests once). In production mode, we can only see about 10 requests and a significantly reduced file-size.\n\n## Deploy\n\nNow that we verified that our application works in production, we can deploy it to the web. In this section, we will use [Firebase](https://www.firebase.com/), a service that provides static file hosting and [Content Delivery Network](https://en.wikipedia.org/wiki/Content_delivery_network) (CDN) support, to automatically deploy and serve our application's static assets from a CDN.\n\n### Set up Firebase\n\nSign up for free at [Firebase](https://firebase.google.com/). After you have an account go to [Firebase console](https://console.firebase.google.com/) and create an app called `donejs-chat-` where `` is your GitHub username. Write down the name of your app because you'll need it in the next section.\n\n> You'll get an error if your app name is too long, so pick something on the shorter side.\n\nWhen you deploy for the first time it will ask you to authorize, but first we need to configure the project.\n\n### Configure DoneJS\n\nNow we can add the Firebase deployment configuration to our `package.json` like this:\n\n```\ndonejs add firebase\n```\n\nWhen prompted, enter the name of the application created when you set up the Firebase app. Before you can deploy your app you need to login and authorize the Firebase tools, which you can do with:\n\n```\nnode_modules/.bin/firebase login\n```\n\nThen we can deploy the application by running:\n\n```\ndonejs build\ndonejs deploy\n```\n\nStatic files are deployed to Firebase.\n\n\"two\n\nAnd verify that the application is loading from the CDN by loading it after running:\n\n```\nNODE_ENV=production donejs start\n```\n\n> If you're using Windows, set the NODE_ENV variable as you did previously in the Production section.\n\nWe should now see our assets being loaded from the Firebase CDN.\n\n\"two\n\n## Desktop and mobile apps\n\nIn the last part of this guide we will make mobile and desktop builds of our chat application, using [Cordova](https://cordova.apache.org/) and [nw.js](http://nwjs.io/).\n\n### Cordova\n\nTo build the application as a Cordova based mobile application, you need to have each platform's SDK installed.\nWe'll be building an iOS app if you are a Mac user, and an Android app if you're a Windows user.\n\nMac users should download XCode from the AppStore and install the `ios-sim` package globally with:\n\n```\nnpm install -g ios-sim\n```\n\nWe will use these tools to create an iOS application that can be tested in the iOS simulator.\n\nWindows users should install the [Android Studio](https://developer.android.com/sdk/index.html), which gives all of the tools we need.\n\nNow we can install the DoneJS Cordova tools with:\n\n```\ndonejs add cordova\n```\n\nDepending on your operating system you can accept most of the defaults, unless you would like to build for Android, which needs to be selected from the list of platforms.\n\nTo run the Cordova build and launch the simulator we can now run:\n\n```\ndonejs build cordova\n```\n\nIf everything went well, we should see the emulator running our application.\n\n\"ios\n\nWindows users will get instructions to download the latest version of the platform and to create a Virtual Device. Follow the instructions and then re-do the build. This will only happen the first time you build for Cordova.\n\n### NW.js\n\nTo set up the desktop build, we have to add it to our application like this:\n\n```\ndonejs add nw\n```\n\nWe can answer most prompts with the default except for the version which needs to be set to the latest **stable version**. Set the version prompt to `0.12.3`.\n\n\"nw\n\nThen we can run the build like this:\n\n```\ndonejs build nw\n```\n\nThe OS X application can be opened with\n\n```\ncd build/donejs-chat/osx64\nopen donejs-chat.app\n```\n\nThe Windows application can be opened with\n\n```\n.\\build\\donejs-chat\\win64\\donejs-chat.exe\n```\n\n\"nw\n\n## What's next?\n\nIn this guide we created a small chat application that connects to a remote API with DoneJS. It has routing between two pages and can send and receive messages in real-time. We built an optimized bundle for production and deployed it to a static file host and CDN. Last, we made builds of the application as a mobile and desktop application.\n\nIf you want to learn more about DoneJS - like how to create more complex custom elements and routes, write and automatically run tests, Continuous Integration and Continuous Deployment - head over to the [place-my-order Guide](./place-my-order.html).\n\n", + "description": "In this guide, we will create [chat.donejs.com](http://chat.donejs.com), a small real-time chat application with a homepage showing a tabs widget and a messages page that lets us send and receive messages in real-time: \n\"chat.donejs.com\"\n\nIn the first part of this guide we will install DoneJS, [generate a new application](Features.html#section=section_Generators) and start a server that provides [hot module swapping](Features.html#section=section_HotModuleSwapping) and [server-side rendering](Features.html#section=section_ServerSideRendered). We will then [import Bootstrap from NPM](Features.html#section=section_NPMPackages), create our [own custom HTML elements](Features.html#section=section_CustomHTMLElements) and [set up routing](Features.html#section=section_PrettyURL_swithPushstate) between the homepage and the chat messages page. After that, we will complete both pages by adding a tabs widget to the homepage and the ability to send messages and [receive real-time updates](Features.html#section=section_RealTimeConnected).\n\nIn the final parts of the guide we will make an [optimized, progressively loaded production build](Features.html#section=section_Progressiveloading) and [deploy it to a CDN](Features.html#section=section_DeploytoaCDN). We will conclude with creating a [mobile and desktop](Features.html#section=section_iOS_Android_andDesktopBuilds) version of the application.\n\nIf you run into any problems, let us know [on Gitter](https://gitter.im/donejs/donejs), we're happy to help out.\n\n", + "name": "Guide", + "title": "Quick start guide", "type": "page", "parent": "DoneJS", "hideSidebar": true, @@ -192,6 +175,23 @@ }, "comment": " " }, + "place-my-order": { + "src": { + "path": "docs/guides/place-my-order.md" + }, + "body": "\n## Set up the project\n\nIn this section we will create our DoneJS project and set up a RESTful API for the application to use.\nYou will need [NodeJS](http://nodejs.org) or [io.js](https://iojs.org/en/index.html) installed and your code editor of choice.\n\n### Create the project\n\nTo get started, let's install the DoneJS command line utility globally:\n\n```\nnpm install -g donejs\n```\n\nThen we can create a new DoneJS application:\n\n```\ndonejs add app place-my-order\n```\n\nThe initialization process will ask you questions like the name of your application (set to `place-my-order`) and the source folder (set to `src`). The other questions can be skipped by hitting enter. This will install all of DoneJS' dependencies. The main project dependencies include:\n\n- [StealJS](http://stealjs.com) - ES6, CJS, and AMD module loader and builder\n- [CanJS](http://canjs.com) - Custom elements and Model-View-ViewModel utilities\n- [jQuery](http://jquery.com) - DOM helpers\n- [jQuery++](http://jquerypp.com) - Extended DOM helpers\n- [QUnit](https://qunitjs.com/) or Mocha - Assertion library\n- [FuncUnit](http://funcunit.com) - Functional tests\n- [Testee](https://github.com/bitovi/testee) - Test runner\n\nIf we now go into the `place-my-order` folder with\n\n```\ncd place-my-order\n```\n\nWe can see the following files:\n\n```\n├── build.js\n├── development.html\n├── package.json\n├── production.html\n├── readme.md\n├── src/\n| ├── app.js\n| ├── index.stache\n| ├── models/\n| | ├── fixtures\n| | | ├── fixtures.js\n| | ├── test.js\n| ├── styles.less\n| ├── test.html\n| ├── test/\n| | ├── test.js\n| | ├── functional.js\n├── node_modules/\n```\n\nLet's have a quick look at the purpose of each:\n\n- `development.html`, `production.html` those pages can run the DoneJS application in development or production mode without a server\n- `package.json` is the main configuration file that defines all our application dependencies and other settings.\n- `test.html` is used to run all our tests.\n- `readme.md` is the readme file for your repository.\n- `src` is the folder where all our development assets live in their own modlets (more about that later).\n- `src/app.js` is the main application file, which exports the main application state.\n- `src/index.stache` is the main client template that includes server-side rendering.\n- `src/models/` is the folder where models for the API connection will be put. It currently contains `fixtures/fixtures.js` which will reference all the specific models fixtures files (so that we can run model tests without the need for a running API server) and `test.js` which will later gather all the individual model test files.\n- `src/styles.less` is the main application styles.\n- `src/test/test.js` collects all individual component and model tests we will create throughout this guide and is loaded by `test.html`.\n- `src/test/functional.js` will contain functional smoke tests for our application.\n\n### Development mode\n\nDoneJS comes with its own server, which hosts your development files and takes care of server-side rendering. DoneJS' development mode will also enable [hot module swapping](http://blog.bitovi.com/hot-module-replacement-comes-to-stealjs/) which automatically reloads files in the browser as they change. You can start it by running:\n\n```\ndonejs develop\n```\n\nThe default port is 8080, so if we now go to [http://localhost:8080/](localhost:8080) we can see our application with a default homepage. If we change `src/index.stache` or `src/app.js` all changes will show up right away in the browser. Try it by changing the `message` property in `src/app.js`.\n\n### Setup a service API\n\nSingle page applications usually communicate with a RESTful API and a websocket connection for real-time updates. This guide will not cover how to create a REST API. Instead, we'll just install and start an existing service API created specifically for use with this tutorial:\n\n**Note**: Kill the server for now while we install a few dependencies (ctrl+c on Windows and Mac).\n\n```\nnpm install place-my-order-api --save\n```\n\nNow we can add an API server start script into the `scripts` section of our `package.json` like this:\n\n```js\n \"scripts\": {\n \"api\": \"place-my-order-api --port 7070\",\n \"test\": \"testee src/test.html --browsers firefox --reporter Spec\",\n \"start\": \"done-serve --port 8080\",\n \"develop\": \"done-serve --develop --port 8080\",\n \"build\": \"node build\"\n },\n```\n\n\nWhich allows us to start the server like:\n\n```\ndonejs api\n```\n\nThe first time it starts, the server will initialize some default data (restaurants and orders). Once started, you can verify that the data has been created and the service is running by going to [http://localhost:7070/restaurants](http://localhost:7070/restaurants), where we can see a JSON list of restaurant data.\n\n### Starting the application\n\nNow our application is good to go and we can start the server. We need to proxy the `place-my-order-api` server to `/api` on our server in order to avoid violating the same origin policy. This means that we need to modify the `start` and `develop` script in our `package.json` to:\n\n```js\n\"scripts\": {\n \"api\": \"place-my-order-api --port 7070\",\n \"test\": \"testee src/test.html --browsers firefox --reporter Spec\",\n \"start\": \"done-serve --proxy http://localhost:7070 --port 8080\",\n \"develop\": \"done-serve --develop --proxy http://localhost:7070 --port 8080\",\n \"build\": \"node build\"\n},\n```\n\n\nNow we can start the application with:\n\n```\ndonejs develop\n```\n\nGo to [http://localhost:8080](http://localhost:8080) to see the \"hello world\" message again.\n\n### Loading assets\n\nBefore we get to the code, we also need to install the `place-my-order-assets` package which contains the images and styles specifically for this tutorial's application:\n\n```\nnpm install place-my-order-assets --save\n```\n\nEvery DoneJS application consists of at least two files:\n\n 1. **A main template** (in this case `src/index.stache`) which contains the main template and links to the development or production assets.\n 1. **A main application view-model** (`src/app.js`) that initializes the application state and routes.\n\n`src/index.stache` was already created for us when we ran `donejs add app`, so update it to\nload the static assets and set a `` tag to support a responsive design:\n\n\n```html\n\n \n {{title}}\n \n \n \n \n \n \n\n

{{message}}

\n\n {{#switch env.NODE_ENV}}\n {{#case \"production\"}}\n \n {{/case}}\n {{#default}}\n \n {{/default}}\n {{/switch}}\n \n\n\n```\n\nThis is an HTML5 template that uses [can.stache](http://canjs.com/docs/can.stache.html) - a [Handlebars syntax](http://handlebarsjs.com/)-compatible view engine. It renders a `message` property from the application state.\n\n`can-import` loads the template's dependencies:\n 1. The `place-my-order-assets` package, which loads the LESS styles for the application\n 1. `place-my-order/app`, which is the main application file\n\nThe main application file at `src/app.js` looks like this:\n\n```\n// src/app.js\nimport DefineMap from 'can-define/map/';\nimport route from 'can-route';\nimport 'can-route-pushstate';\n\nconst AppViewModel = DefineMap.extend({\n message: {\n value: 'Hello World!',\n serialize: false\n },\n title: {\n value: 'place-my-order',\n serialize: false\n }\n});\n\nexport default AppViewModel;\n```\n\nThis initializes a [can.DefineMap](http://canjs.com/doc/can-define/map/map.html): a special object that acts as the application global state (with a default `message` property) and also plays a key role in enabling server side rendering.\n\n## Creating custom elements\n\nOne of the most important concepts in DoneJS is splitting up your application functionality into individual, self-contained modules. In the following section we will create separate components for the homepage, the restaurant list, and the order history page. After that, we will glue them all together using routes and the global application state.\n\nThere are two ways of creating components. For smaller components we can define all templates, styles and functionality in a single `.component` file (to learn more see [done-component](https://github.com/donejs/done-component)). Larger components can be split up into several separate files.\n\n### Creating a homepage element\n\nTo generate a new component run:\n\n```\ndonejs add component home.component pmo-home\n```\n\nThis will create a file at `src/home.component` containing the basic ingredients of a component. We will update it to reflect the below content:\n\n\n```html\n\n \n \n
\n \n

Ordering food has never been easier

\n

\n We make it easier than ever to order gourmet food\n from your favorite local restaurants.\n

\n

Choose a Restaurant

\n
\n
\n \n
\n\n```\n\nHere we created a [can.Component](http://canjs.com/docs/can.Component.html) named `pmo-home` using a [web-component](http://webcomponents.org/) style declaration. This particular component is just a basic template, it does not have much in the way of styles or functionality.\n\n### Create the order history element\n\nWe'll create an initial version of order history that is very similar.\n\n```\ndonejs add component order/history.component pmo-order-history\n```\n\nAnd update `src/order/history.component`:\n\n\n```html\n\n \n \n
\n
\n
Name / Address / Phone
\n
Order
\n
Total
\n
Action
\n
\n
\n
\n \n
\n\n```\n\n### Creating a restaurant list element\n\nThe restaurant list will contain more functionality, which is why we will split its template and component logic into separate files.\n\nWe can create a basic component like that by running:\n\n```\ndonejs add component restaurant/list pmo-restaurant-list\n```\n\nThe component's files are collected in a single folder so that components can be easily tested, moved, and re-used. The folder structure looks like this:\n\n```\n├── node_modules\n├── package.json\n├── src/\n| ├── app.js\n| └── index.stache\n| ├── models\n| ├── order/\n| | ├── history.component\n| ├── restaurant/\n| | ├── list/\n| | | ├── list.html\n| | | ├── list.js\n| | | ├── list.less\n| | | ├── list.md\n| | | ├── list.stache\n| | | ├── list_test.js\n| | | ├── test.html\n```\n\nWe will learn more about those files and add more functionality to this element later, but it already contains a fully functional component with a demo page (see [localhost:8080/src/restaurant/list/list.html](http://localhost:8080/src/restaurant/list/list.html)), a basic test (at [localhost:8080/src/restaurant/list/test.html](http://localhost:8080/src/restaurant/list/test.html)) and documentation placeholders.\n\n## Setting up routing\n\nIn this part, we will create routes - URL patterns that load specific parts of our single page app. We'll also dynamically load the custom elements we created and integrate them in the application's main page.\n\n### Create Routes\n\nRouting works a bit differently than other libraries. In other libraries, you might declare routes and map those to controller-like actions.\n\nDoneJS application [routes](http://canjs.com/docs/can.route.html) map URL strings (like /user/1) to properties in our application state. In other words, our routes will just be a representation of the application state.\n\nTo learn more about routing visit the CanJS guide on [Application State and Routing](http://canjs.com/guides/AppStateAndRouting.html).\n\nTo add our routes, change `src/app.js` to:\n\n\n```js\nimport DefineMap from 'can-define/map/';\nimport route from 'can-route';\nimport 'can-route-pushstate';\n\nconst AppViewModel = DefineMap.extend({\n page: \"string\",\n slug: \"string\",\n action: \"string\",\n\n title: {\n value: 'place-my-order',\n serialize: false\n }\n});\n\nroute('{page}', { page: 'home' });\nroute('{page}/{slug}', { slug: null });\nroute('{page}/{slug}/{action}', { slug: null, action: null });\n\nexport default AppViewModel;\n\n```\n\n> Notice: We also removed the `message` property in `AppViewModel`. This is because\n> it is not needed.\n\nNow we have three routes available:\n\n- `{page}` captures urls like [http://localhost:8080/home](http://localhost:8080/home) and sets the `page` property on `AppViewModel` to `home` (which is also the default when visiting [http://localhost:8080/](http://localhost:8080/))\n- `{page}/{slug}` matches restaurant links like [http://localhost:8080/restaurants/spago](http://localhost:8080/restaurants/spago) and sets `page` and `slug` (a URL friendly restaurant short name)\n- `{page}/{slug}/{action}` will be used to show the order page for a specific restaurant e.g. [http://localhost:8080/restaurants/spago/order](http://localhost:8080/restaurants/spago/order)\n\n### Adding a header element\n\nNow is also a good time to add a header element that links to the different routes we just defined. We can run\n\n```\ndonejs add component header.component pmo-header\n```\n\nand update `src/header.component` to:\n\n\n```html\n\n \n \n \n
\n \n
\n
\n \n
\n\n```\n\nHere we use [routeUrl](http://canjs.com/docs/can.stache.helpers.routeUrl.html) to create links that will set values in the application state. For example, the first usage of routeUrl above will create a link based on the current routing rules ([http://localhost:8080/home](http://localhost:8080/home) in this case) that sets the `page` property to `home` when clicked.\n\nWe also use the Stache `eq` helper to make the appropriate link active.\n\n### Create a loading indicator\n\nTo show that something is currently loading, let's create a `pmo-loading` component:\n\n```\ndonejs add component loading.component pmo-loading\n```\n\nChange `src/loading.component` to:\n\n\n```html\n\n \n \n {{#eq state \"resolved\"}}\n \n {{else}}\n
\n {{/eq}}\n
\n \n
\n\n```\n\n\n### Switch between components\n\nNow we can glue all those individual components together in `src/index.stache`. What we want to do is - based on the current page (`home`, `restaurants` or `order-history`) - load the correct component and then initialize it.\n\nUpdate `src/index.stache` to:\n\n\n```html\n\n \n {{title}}\n \n \n \n \n \n \n\n \n \n \n\n {{#switch page}}\n {{#case \"home\"}}\n \n \n \n {{/case}}\n {{#case \"restaurants\"}}\n \n \n \n {{/case}}\n {{#case \"order-history\"}}\n \n \n \n {{/case}}\n {{/switch}}\n\n {{#switch env.NODE_ENV}}\n {{#case \"production\"}}\n \n \n {{/case}}\n {{#default}}\n \n {{/default}}\n {{/switch}}\n \n\n\n```\n\nHere we make a `switch` statement that checks for the current `page` property (part of the AppViewModel that makes up the scope object of this template) then progressively loads the component with [can-import](http://canjs.com/docs/can%7Cview%7Cstache%7Csystem.import.html) and initializes it.\n\nSetting `can-tag=\"pmo-loading\"` inserts a `` loading indicator while the import is in progress. A can-import's view model is a promise object, so once it is done loading, it sets its `state` property to `resolved`.\n\nNow we can see the header and the home component and be able to navigate to the different pages through the header.\n\n## Getting Data from the Server\n\nIn this next part, we'll connect to the RESTful API that we set up with `place-my-order-api`, using the powerful data layer provided by [can-connect](http://connect.canjs.com/).\n\n### Creating a restaurants connection\n\nAt the beginning of this guide we set up a REST API at [http://localhost:7070](http://localhost:7070) and told `done-serve` to proxy it to [http://localhost:8080/api](http://localhost:8080/api).\n\nTo manage the restaurant data located at [http://localhost:8080/api/restaurants](http://localhost:8080/api/restaurants), we'll create a restaurant supermodel:\n\n```js\ndonejs add supermodel restaurant\n```\n\nAnswer the question about the URL endpoint with `/api/restaurants` and the name of the id property with `_id`.\n\nWe have now created a model and fixtures (for testing without an API) with a folder structure like this:\n\n```\n├── node_modules\n├── package.json\n├── src/\n| ├── app.js\n| └── index.stache\n| ├── models/\n| | ├── fixtures/\n| | | ├── restaurant.js\n| | ├── fixtures.js\n| | ├── restaurant.js\n| | ├── restaurant_test.js\n| | ├── test.js\n```\n\n### Test the connection\n\nTo test the connection you can run the following in the console:\n\n```js\nsteal.import(\"place-my-order/models/restaurant\")\n .then(function(module) {\n var Restaurant = module[\"default\"];\n return Restaurant.getList({});\n }).then(function(restaurants) {\n console.log(restaurants);\n });\n```\n\nThis programmatically imports the `Restaurant` model and uses it to get a list\nof all restaurants on the server and log them to the console.\n\n### Add data to the page\n\nNow, update the `ViewModel` in `src/restaurant/list/list.js` to use [can-define](https://github.com/canjs/can-define) to load all restaurants from the restaurant connection:\n\n\n```js\nimport Component from 'can-component';\nimport DefineMap from 'can-define/map/';\nimport './list.less';\nimport view from './list.stache';\nimport Restaurant from 'place-my-order/models/restaurant';\n\nexport const ViewModel = DefineMap.extend({\n restaurants: {\n value() {\n return Restaurant.getList({});\n }\n }\n});\n\nexport default Component.extend({\n tag: 'pmo-restaurant-list',\n ViewModel,\n view\n});\n\n```\n\nAnd update the template at `src/restaurant/list/list.stache` to use the [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) returned for the `restaurants` property to render the template:\n\n\n```html\n\n\n
\n

Restaurants

\n {{#if restaurants.isPending}}\n
\n {{/if}}\n\n {{#if restaurants.isResolved}}\n {{#each restaurants.value}}\n
\n \n

{{name}}

\n {{#address}}\n
\n {{street}}
{{city}}, {{state}} {{zip}}\n
\n {{/address}}\n\n
\n $$$
\n Hours: M-F 10am-11pm\n Open Now\n
\n\n \n Details\n \n
\n
\n {{/each}}\n {{/if}}\n
\n\n```\n\nBy checking for `restaurants.isPending` and `restaurants.isResolved` we are able to show a loading indicator while the data are being retrieved. Once resolved, the actual restaurant list is available at `restaurants.value`. When navigating to the restaurants page now we can see a list of all restaurants.\n\nNote the usage of `routeUrl` to set up a link that points to each restaurant. `slug=slug` is not wrapped in quotes because the helper will populate each restaurant's individual `slug` property in the URL created.\n\n## Creating a unit-tested view model\n\nIn this section we will create a view model for the restaurant list functionality.\n\nWe'll show a dropdown of all available US states. When the user selects a state, we'll show a list of cities. Once a city is selected, we'll load a list of all restaurants for that city. The end result will look like this:\n\n![Restaurant list](static/img/restaurant-list.png)\n\n### Identify view model state\n\nFirst we need to identify the properties that our view model needs to provide. We want to load a list of states from the server and let the user select a single state. Then we do the same for cities and finally load the restaurant list for that selection.\n\nAll asynchronous requests return a Promise, so the data structure will look like this:\n\n```js\n{\n states: Promise<[State]>\n state: String \"IL\",\n cities: Promise<[City]>,\n city: String \"Chicago\",\n restaurants: Promise<[Restaurant]>\n}\n```\n\n### Create dependent models\n\nThe API already provides a list of available [states](http://localhost:8080/api/states) and [cities](http://localhost:8080/api/cities). To load them we can create the corresponding models like we already did for Restaurants.\n\nRun:\n\n```\ndonejs add supermodel state\n```\n\nWhen prompted, set the URL to `/api/states` and the id property to `short`.\n\nRun:\n\n```\ndonejs add supermodel city\n```\n\nWhen prompted, set the URL to `/api/cities` and the id property to `name`.\n\nNow we can load a list of states and cities.\n\n### Implement view model behavior\n\nNow that we have identified the view model properties needed and have created the models necessary to load them, we can [define](http://canjs.com/doc/can-define/map/map.html) the `states`, `state`, `cities` and `city` properties in the view model at `src/restaurant/list/list.js`:\n\n\n```js\nimport Component from 'can-component';\nimport DefineMap from 'can-define/map/';\nimport './list.less';\nimport view from './list.stache';\nimport Restaurant from 'place-my-order/models/restaurant';\nimport State from 'place-my-order/models/state';\nimport City from 'place-my-order/models/city';\n\nexport const ViewModel = DefineMap.extend({\n get states() {\n return State.getList({});\n },\n state: {\n type: 'string',\n value: null,\n set() {\n // Remove the city when the state changes\n this.city = null;\n }\n },\n get cities() {\n let state = this.state;\n\n if(!state) {\n return null;\n }\n\n return City.getList({ state });\n },\n city: {\n type: 'string',\n value: null\n },\n get restaurants() {\n let state = this.state;\n let city = this.city;\n\n if(state && city) {\n return Restaurant.getList({\n 'address.state': state,\n 'address.city': city\n });\n }\n\n return null;\n }\n});\n\nexport default Component.extend({\n tag: 'pmo-restaurant-list',\n ViewModel,\n view\n});\n\n```\n\nLet's take a closer look at those properties:\n\n- `states` will return a list of all available states by calling `State.getList({})`\n- `state` is a string property set to `null` by default (no selection). Additionally, when `state` is changed we will remove the dependent `city` selection.\n- `cities` will return `null` if no state has been selected. Otherwise, it will load all the cities for a given state by sending `state` as a query paramater (which will make a request like [http://localhost:8080/api/cities?state=IL](ttp://localhost:8080/api/cities?state=IL))\n- `city` is a simple string, set to `null` by default\n- `restaurants` will always be `null` unless both a `city` and a `state` are selected. If both are selected, it will set the `address.state` and `address.city` query parameters which will return a list of all restaurants whose address matches those parameters.\n\n### Create a test\n\nView models that are decoupled from the presentation layer are easy to test. We will use [QUnit](http://qunitjs.com/) as the testing framework by loading a StealJS-friendly wrapper (`steal-qunit`). The component generator created a fully working test page for the component, which can be opened at [http://localhost:8080/pmo/restaurant/list/test.html](http://localhost:8080/src/restaurant/list/test.html). Currently, the tests will fail because we changed the view model, but in this section we will create some unit tests for the new functionality.\n\n#### Fixtures: Create fake data\n\nUnit tests should be able to run by themselves without the need for an API server. This is where [fixtures](http://canjs.com/docs/can.fixture.html) come in. Fixtures allow us to mock requests to the REST API with data that we can use for tests or demo pages. Default fixtures will be provided for every generated model. Now we'll add more realistic fake data by updating `src/models/fixtures/states.js` to:\n\n\n```js\nimport fixture from 'can-fixture';\n\nconst store = fixture.store([\n { name: 'Calisota', short: 'CA' },\n { name: 'New Troy', short: 'NT'}\n],{});\n\nfixture({\n 'GET /api/states': store.findAll,\n 'GET /api/states/{short}': store.findOne,\n 'POST /api/states': store.create,\n 'PUT /api/states/{short}': store.update,\n 'DELETE /api/states/{short}': store.destroy\n});\n\nexport default store;\n\n```\n\nUpdate `src/models/fixtures/cities.js` to look like:\n\n\n```js\nimport fixture from 'can-fixture';\n\nconst store = fixture.store([\n { state: 'CA', name: 'Casadina' },\n { state: 'NT', name: 'Alberny' }\n],{});\n\nfixture({\n 'GET /api/cities': store.findAll,\n 'GET /api/cities/{name}': store.findOne,\n 'POST /api/cities': store.create,\n 'PUT /api/cities/{name}': store.update,\n 'DELETE /api/cities/{name}': store.destroy\n});\n\nexport default store;\n\n```\n\nAnd we also need to provide a restaurant list according to the selected city and state in `src/models/fixtures/restaurants.js`:\n\n\n```js\nimport fixture from 'can-fixture';\n\nconst store = fixture.store([{\n _id: 1,\n name: 'Cheese City',\n slug:'cheese-city',\n address: {\n city: 'Casadina',\n state: 'CA'\n },\n images: {\n banner: \"node_modules/place-my-order-assets/images/1-banner.jpg\",\n owner: \"node_modules/place-my-order-assets/images/2-owner.jpg\",\n thumbnail: \"node_modules/place-my-order-assets/images/3-thumbnail.jpg\"\n }\n}, {\n _id: 2,\n name: 'Crab Barn',\n slug:'crab-barn',\n address: {\n city: 'Alberny',\n state: 'NT'\n },\n images: {\n banner: \"node_modules/place-my-order-assets/images/2-banner.jpg\",\n owner: \"node_modules/place-my-order-assets/images/3-owner.jpg\",\n thumbnail: \"node_modules/place-my-order-assets/images/2-thumbnail.jpg\"\n }\n}],{\n \"address.city\": function(restaurantValue, paramValue, restaurant){\n return restaurant.address.city === paramValue;\n },\n \"address.state\": function(restaurantValue, paramValue, restaurant){\n return restaurant.address.state === paramValue;\n }\n});\n\nfixture({\n 'GET /api/restaurants': store.findAll,\n 'GET /api/restaurants/{id}': store.findOne,\n 'POST /api/restaurants': store.create,\n 'PUT /api/restaurants/{id}': store.update,\n 'DELETE /api/restaurants/{id}': store.destroy\n});\n\nexport default store;\n\n```\n\n#### Test the view model\n\nWith fake data in place, we can test our view model by changing `src/restaurant/list/list_test.js` to:\n\n\n```js\nimport QUnit from 'steal-qunit';\nimport cityStore from 'place-my-order/models/fixtures/cities';\nimport stateStore from 'place-my-order/models/fixtures/states';\nimport restaurantStore from 'place-my-order/models/fixtures/restaurants';\nimport { ViewModel } from './list';\n\nQUnit.module('place-my-order/restaurant/list', {\n beforeEach() {\n localStorage.clear();\n }\n});\n\nQUnit.asyncTest('loads all states', function() {\n var vm = new ViewModel();\n var expectedStates = stateStore.getListData({});\n\n vm.states.then(states => {\n QUnit.deepEqual(states.serialize(), expectedStates.data, 'Got all states');\n QUnit.start();\n });\n});\n\nQUnit.asyncTest('setting a state loads its cities', function() {\n var vm = new ViewModel();\n var expectedCities = cityStore.getListData({data: {state: \"CA\"}}).data;\n\n QUnit.equal(vm.cities, null, '');\n vm.state = 'CA';\n vm.cities.then(cities => {\n QUnit.deepEqual(cities.serialize(), expectedCities, 'Got all cities');\n QUnit.start();\n });\n});\n\nQUnit.asyncTest('changing a state resets city', function() {\n var vm = new ViewModel();\n var expectedCities = cityStore.getListData({data: {state: \"CA\"}}).data;\n\n QUnit.equal(vm.cities, null, '');\n vm.state = 'CA';\n vm.cities.then(cities => {\n QUnit.deepEqual(cities.serialize(), expectedCities);\n vm.state = 'NT';\n QUnit.equal(vm.city, null);\n QUnit.start();\n });\n});\n\nQUnit.asyncTest('setting state and city loads a list of its restaurants', function() {\n var vm = new ViewModel();\n var expectedRestaurants = restaurantStore.getListData({\n data: {\"address.city\": \"Alberny\"}\n }).data;\n\n vm.state = 'NT';\n vm.city = 'Alberny';\n\n vm.restaurants.then(restaurants => {\n QUnit.deepEqual(restaurants.serialize(), expectedRestaurants);\n QUnit.start();\n });\n});\n\n```\n\nThese unit tests are comparing expected data (what we we defined in the fixtures) with actual data (how the view model methods are behaving). Visit [http://localhost:8080/src/restaurant/list/test.html](http://localhost:8080/src/restaurant/list/test.html) to see all tests passing.\n\n### Write the template\n\nNow that our view model is implemented and tested, we'll update the restaurant list template to support the city/state selection functionality.\n\nUpdate `src/restaurant/list/list.stache` to:\n\n\n```html\n\n\n
\n

Restaurants

\n
\n
\n \n \n
\n
\n \n \n
\n
\n\n {{#if restaurants.isPending}}\n
\n {{/if}}\n\n {{#if restaurants.isResolved}}\n {{#each restaurants.value}}\n
\n \n

{{name}}

\n {{#address}}\n
\n {{street}}
{{city}}, {{state}} {{zip}}\n
\n {{/address}}\n\n
\n $$$
\n Hours: M-F 10am-11pm\n Open Now\n
\n\n \n Place My Order\n \n
\n
\n {{/each}}\n {{/if}}\n
\n\n```\n\nSome things worth pointing out:\n\n- Since `states` and `cities` return a promise, we can check the promise's status via `isResolved` and `isPending` and once resolved get the actual value with `states.value` and `cities.value`. This also allows us to easily show loading indicators and disable the select fields while loading data.\n- The `state` and `city` properties are two-way bound to their select fields via [{($value)}](http://canjs.com/doc/can-stache-bindings.twoWay.html#___child_prop____key_)\n\nNow we have a component that lets us select state and city and displays the appropriate restaurant list.\n\n### Update the demo page\n\nWe already have an existing demo page at [src/restaurant/list/list.html](http://localhost:8080/src/restaurant/list/list.html). We'll update it to load fixtures so it can demonstrate the use of the pmo-restaurnt-list component:\n\n\n```html\n\n\n\n```\n\nView the demo page at [http://localhost:8080/src/restaurant/list/list.html](http://localhost:8080/src/restaurant/list/list.html) .\n\n## Automated tests\n\nIn this chapter we will automate running the tests so that they can be run from from the command line.\n\n### Using the global test page\n\nWe already worked with an individual component test page in [src/restaurant/list/test.html](http://localhost:8080/src/restaurant/list/test.html) but we also have a global test page available at [src/test.html](http://localhost:8080/src/test.html). All tests are being loaded in `src/test/test.js`. Since we don't have tests for our models at the moment, let's remove the `import 'place-my-order/models/test';` part so that `src/test/test.js` looks like this:\n\n\n```js\nimport 'place-my-order/test/functional';\n\nimport 'place-my-order/restaurant/list/list_test';\n\n```\n\nIf you now go to [http://localhost:8080/src/test.html](http://localhost:8080/src/test.html) we still see all restaurant list tests passing but we will add more here later on.\n\n### Using a test runner\n\nThe tests can be automated with any test runner that supports running QUnit tests. We will use [Testee](https://github.com/bitovi/testee) which makes it easy to run those tests in any browser from the command line without much configuration. In fact, everything needed to automatically run the `src/test.html` page in Firefox is already set up and we can launch the tests by running:\n\n```\ndonejs test\n```\n\nTo see the tests passing on the command line.\n\n## Continuous integration\n\nNow that the tests can be run from the command line we can automate it in a [continuous integration](https://en.wikipedia.org/wiki/Continuous_integration) (CI) environment to run all tests whenever a code change is made. We will use [GitHub](https://github.com) to host our code and [TravisCI](https://travis-ci.org/) as the CI server.\n\n### Creating a GitHub account and repository\n\nIf you don't have an account yet, go to [GitHub](https://github.com) to sign up and follow [the help](https://help.github.com/articles/set-up-git/) on how to set it up for use with the command-line `git`. Once completed, you can create a new repository from your dashboard. Calling the repository `place-my-order` and initializing it empty (without any of the default files) looks like this:\n\n![Creating a new repository on GitHub](static/img/guide-create-repo.png)\n\nNow we have to initialize Git in our project folder and add the GitHub repository we created as the origin remote (replace `` with your GitHub username):\n\n```\ngit init\ngit remote add origin git@github.com:/place-my-order.git\n```\n\nThen we can add all files and push to origin like this:\n\n```\ngit add . --all\ngit commit -am \"Initial commit\"\ngit push origin master\n```\n\nIf you now go to [github.com//place-my-order](https://github.com//place-my-order) you will see the project files in the repository.\n\n### Setting up Travis CI\n\nThe way our application is set up, now all a continuous integration server has to do is clone the application repository, run `npm install`, and then run `npm test`. There are many open source CI servers, the most popular one probably [Jenkins](https://jenkins-ci.org/), and many hosted solutions like [Travis CI](https://travis-ci.org/).\n\nWe will use Travis as our hosted solution because it is free for open source projects. It works with your GitHub account which it will use to sign up. First, [sign up](https://travis-ci.org/), then go to `Accounts` (in the dropdown under you name) to enable the `place-my-order` repository:\n\n![Enabling the repository on Travis CI](static/img/guide-travis-ci.png)\n\nContinuous integration on GitHub is most useful when using [branches and pull requests](https://help.github.com/categories/collaborating-on-projects-using-pull-requests/). That way your main branch (master) will only get new code changes if all tests pass. Let's create a new branch with\n\n```\ngit checkout -b travis-ci\n```\n\nAnd add a `.travis.yml` file to our project root:\n\n```\nlanguage: node_js\nnode_js: node\naddons:\n firefox: \"latest\"\nbefore_install:\n - \"export DISPLAY=:99.0\"\n - \"sh -e /etc/init.d/xvfb start\"\n```\n\nBy default Travis CI runs `npm test` for NodeJS projects which is what we want. `before_install` sets up a window system to run Firefox.\n\nWe can also add a *Build Passing* badge to the top `readme.md`:\n\n```\n[![Build Status](https://travis-ci.org//place-my-order.png?branch=master)](https://travis-ci.org//place-my-order)\n\n# place-my-order\n```\n\nTo see Travis run, let's add all changes and push to the branch:\n\n```\ngit add readme.md .travis.yml\ngit commit -am \"Enabling Travis CI\"\ngit push origin travis-ci\n```\n\nAnd then create a new pull request by going to [github.com//place-my-order](https://github.com//place-my-order) which will now show an option for it:\n\n![Creating a new pull request on GitHub](static/img/guide-github-pr.png)\n\nOnce you created the pull request, you will see a `Some checks haven’t completed yet` message that will eventually turn green like this:\n\n![Merging a pull request with all tests passed](static/img/guide-merge-pr.png)\n\nOnce everything turns green, click the \"Merge pull request\" button. Then in your console, checkout the _master_ branch and pull down it's latest with:\n\n```\ngit checkout master\ngit pull origin master\n```\n\n\n## Nested routes\n\nIn this section, we will add additional pages that are shown under nested urls such as `restaurants/cheese-curd-city/order`.\n\n
\n\nUntil now we've used three top level routes: `home`, `restaurants` and `order-history`. We did however also define two additional routes in `src/app.js` which looked like:\n\n```js\nroute('{page}/{slug}', { slug: null });\nroute('{page}/{slug}/{action}', { slug: null, action: null });\n```\n\nWe want to use those routes when we are in the `restaurants` page. The relevant section in `src/index.stache` currently looks like this:\n\n```html\n{{#case \"restaurants\"}}\n \n \n \n{{/case}}\n```\n\nWe want to support two additional routes:\n\n- `restaurants/{slug}`, which shows a details page for the restaurant with `slug` being a URL friendly short name for the restaurant\n- `restaurants/{slug}/order`, which shows the menu of the current restaurant and allows us to make a selection and then send our order.\n\n### Create additional components\n\nTo make this happen, we need two more components. First, the `pmo-restaurant-details` component which loads the restaurant (based on the `slug`) and displays its information.\n\n```\ndonejs add component restaurant/details.component pmo-restaurant-details\n```\n\nAnd change `src/restaurant/details.component` to:\n\n\n```html\n\n \n \n \n \n {{#if isPending}}\n
\n {{else}}\n {{#value}}\n
\n
\n

{{name}}

\n\n {{#address}}\n
\n {{street}}
{{city}}, {{state}} {{zip}}\n
\n {{/address}}\n\n
\n $$$
\n Hours: M-F 10am-11pm\n Open Now\n
\n\n
\n
\n
\n\n
\n

The best food this side of the Mississippi

\n\n

\n \n Description for {{name}}\n

\n

\n \n Order from {{name}}\n \n

\n
\n {{/value}}\n {{/if}}\n
\n
\n
\n\n```\n\nThe order component will be a little more complex, which is why we will put it into its own folder:\n\n```\ndonejs add component order/new pmo-order-new\n```\n\nFor now, we will just use placeholder content and implement the functionality in\nthe following chapters.\n\n### Add to the main template\n\nNow we can add those components to the main template (at `src/index.stache`) with conditions based on the routes that we want to match. Change the section which contains:\n\n```html\n{{#case \"restaurants\"}}\n \n \n \n{{/case}}\n```\n\nTo:\n\n\n```html\n{{#case \"restaurants\"}}\n {{#if slug}}\n {{#switch action}}\n {{#case 'order'}}\n \n \n \n {{/case}}\n\n {{#default}}\n \n \n \n {{/default}}\n {{/switch}}\n {{else}}\n \n \n \n {{/if}}\n{{/case}}\n\n```\n\nHere we are adding some more conditions if `page` is set to `restaurants`:\n\n- When there is no `slug` set, show the original restaurant list\n- When `slug` is set but no `action`, show the restaurant details\n- When `slug` is set and `action` is `order`, show the order component for that restaurant\n\n## Importing other projects\n\nThe NPM integration of StealJS makes it very easy to share and import other components. One thing we want to do when showing the `pmo-order-new` component is have a tab to choose between the lunch and dinner menu. The good news is that there is already a [bit-tabs](https://github.com/bitovi-components/bit-tabs) component which does exactly that. Let's add it as a project dependency with:\n\n```\nnpm install bit-tabs --save\n```\n\nAnd then integrate it into `src/order/new/new.stache`:\n\n\n```html\n\n
\n

Order here

\n\n \n \n This is the lunch menu\n \n \n This is the dinner menu\n \n \n
\n\n```\n\nHere we just import the `unstyled` module from the `bit-tabs` package using `can-import` which will then provide the `bit-tabs` and `bit-panel` custom elements.\n\n## Creating data\n\nIn this section, we will update the order component to be able to select restaurant menu items and submit a new order for a restaurant.\n\n### Creating the order model\n\nFirst, let's look at the restaurant data we get back from the server. It looks like this:\n\n```\n{\n \"_id\": \"5571e03daf2cdb6205000001\",\n \"name\": \"Cheese Curd City\",\n \"slug\": \"cheese-curd-city\",\n \"images\": {\n \"thumbnail\": \"images/1-thumbnail.jpg\",\n \"owner\": \"images/1-owner.jpg\",\n \"banner\": \"images/2-banner.jpg\"\n },\n \"menu\": {\n \"lunch\": [\n {\n \"name\": \"Spinach Fennel Watercress Ravioli\",\n \"price\": 35.99\n },\n {\n \"name\": \"Chicken with Tomato Carrot Chutney Sauce\",\n \"price\": 45.99\n },\n {\n \"name\": \"Onion fries\",\n \"price\": 15.99\n }\n ],\n \"dinner\": [\n {\n \"name\": \"Gunthorp Chicken\",\n \"price\": 21.99\n },\n {\n \"name\": \"Herring in Lavender Dill Reduction\",\n \"price\": 45.99\n },\n {\n \"name\": \"Roasted Salmon\",\n \"price\": 23.99\n }\n ]\n },\n \"address\": {\n \"street\": \"1601-1625 N Campbell Ave\",\n \"city\": \"Green Bay\",\n \"state\": \"WI\",\n \"zip\": \"60045\"\n }\n}\n```\n\nWe have a `menu` property which provides a `lunch` and `dinner` option (which will show later inside the tabs we set up in the previous chapter). We want to be able to add and remove items from the order, check if an item is in the order already, set a default order status (`new`), and be able to calculate the order total. For that to happen, we need to create a new `order` model:\n\n```\ndonejs add supermodel order\n```\n\nLike the restaurant model, the URL is `/api/orders` and the id property is `_id`. To select menu items, we need to add some additional functionality to `src/models/order.js`:\n\n\n```js\nimport DefineMap from 'can-define/map/';\nimport DefineList from 'can-define/list/';\nimport superMap from 'can-connect/can/super-map/';\nimport tag from 'can-connect/can/tag/';\n\nconst Item = DefineMap.extend({\n price: 'number'\n});\n\nconst ItemsList = DefineList.extend({\n '*': Item\n}, {\n has: function(item) {\n return this.indexOf(item) !== -1;\n },\n\n toggle: function(item) {\n var index = this.indexOf(item);\n\n if (index !== -1) {\n this.splice(index, 1);\n } else {\n this.push(item);\n }\n }\n});\n\nexport const Order = DefineMap.extend({\n seal: false\n}, {\n '_id': '*',\n name: 'string',\n address: 'string',\n phone: 'string',\n restaurant: 'string',\n\n status: {\n value: 'new'\n },\n items: {\n Value: ItemsList\n },\n get total() {\n let total = 0.0;\n this.items.forEach(item =>\n total += parseFloat(item.price));\n return total.toFixed(2);\n },\n markAs(status) {\n this.status = status;\n this.save();\n }\n});\n\nOrder.List = DefineList.extend({\n '*': Order\n});\n\nexport const orderConnection = superMap({\n url: '/api/orders',\n idProp: '_id',\n Map: Order,\n List: Order.List,\n name: 'order'\n});\n\ntag('order-model', orderConnection);\n\nexport default Order;\n\n```\n\nHere we define an `ItemsList` which allows us to toggle menu items and check if they are already in the order. We set up ItemsList as the Value of the items property of an order so we can use its has function and toggle directly in the template. We also set a default value for status and a getter for calculating the order total which adds up all the item prices. We also create another `` tag to load orders in the order history template later.\n\n### Implement the view model\n\nNow we can update the view model in `src/order/new/new.js`:\n\n\n```js\nimport Component from 'can-component';\nimport DefineMap from 'can-define/map/';\nimport './new.less';\nimport view from './new.stache';\nimport Restaurant from 'place-my-order/models/restaurant';\nimport Order from 'place-my-order/models/order';\n\nexport const ViewModel = DefineMap.extend({\n slug: 'string',\n saveStatus: '*',\n order: {\n Value: Order\n },\n get restaurantPromise() {\n return Restaurant.get({ _id: this.slug });\n },\n restaurant: {\n get(lastSetVal, resolve) {\n this.restaurantPromise.then(resolve);\n }\n },\n get canPlaceOrder() {\n return this.order.items.length;\n },\n placeOrder(ev) {\n ev.preventDefault();\n let order = this.order;\n order.restaurant = this.restaurant._id;\n this.saveStatus = order.save();\n },\n startNewOrder() {\n this.order = new Order();\n this.saveStatus = null;\n }\n});\n\nexport default Component.extend({\n tag: 'pmo-order-new',\n ViewModel,\n view\n});\n\n```\n\nHere we just define the properties that we need: `slug`, `order`, `canPlaceOrder` - which we will use to enable/disable the submit button - and `saveStatus`, which will become a promise once the order is submitted. `placeOrder` updates the order with the restaurant information and saves the current order. `startNewOrder` allows us to submit another order.\n\nWhile we're here we can also update our test to get it passing again, replace `src/order/new/new_test.js` with:\n\n\n```js\nimport QUnit from 'steal-qunit';\nimport { ViewModel } from './new';\n\n// ViewModel unit tests\nQUnit.module('place-my-order/order/new');\n\nQUnit.test('canPlaceOrder', function(){\n var vm = new ViewModel({\n order: { items: [1] }\n });\n QUnit.equal(vm.canPlaceOrder, true, 'can place an order');\n});\n\n```\n\n### Write the template\n\nFirst, let's implement a small order confirmation component with\n\n```\ndonejs add component order/details.component pmo-order-details\n```\n\nand changing `src/order/details.component` to:\n\n\n```html\n\n \n {{#order}}\n

Thanks for your order {{name}}!

\n
\n
\n\n

Items ordered:

\n
    \n {{#each items}}\n
  • \n \n
  • \n {{/each}}\n\n
  • \n \n
  • \n
\n\n
\n
\n {{/order}}\n
\n
\n\n```\n\nNow we can import that component and update `src/order/new/new.stache` to:\n\n\n```html\n\n\n\n
\n {{#if restaurantPromise.isPending}}\n
\n {{else}}\n {{#if saveStatus.isResolved}}\n \n

\n Place another order\n

\n {{else}}\n

Order from {{restaurant.name}}

\n\n
\n \n

\n {{^if order.items.length}}\n Please choose an item\n {{else}}\n {{order.items.length}} selected\n {{/if}}\n

\n \n
    \n {{#each restaurant.menu.lunch}}\n
  • \n \n
  • \n {{/each}}\n
\n
\n \n
    \n {{#each restaurant.menu.dinner}}\n
  • \n \n
  • \n {{/each}}\n
\n
\n
\n\n
\n \n \n

Please enter your name.

\n
\n
\n \n \n

Please enter your address.

\n
\n
\n \n \n

Please enter your phone number.

\n
\n
\n

Total: ${{order.total}}

\n {{#if saveStatus.isPending}}\n
\n {{else}}\n \n {{/if}}\n
\n
\n {{/if}}\n {{/if}}\n
\n\n```\n\nThis is a longer template so lets walk through it:\n\n- `` loads the order details component we previously created\n- `` loads a restaurant based on the slug value passed to the component\n- If the `saveStatus` promise is resolved we show the `pmo-order-details` component with that order\n- Otherwise we will show the order form with the `bit-tabs` panels we implemented in the previous chapter and iterate over each menu item\n- `($submit)=\"placeOrder()\"` will call `placeOrder` from our view model when the form is submitted\n- The interesting part for showing a menu item is the checkbox ``\n - `($change)` binds to the checkbox change event and runs `order.items.toggle` which toggles the item from `ItemList`, which we created in the model\n - `order.item.has` sets the checked status to whether or not this item is in the order\n- Then we show form elements for name, address, and phone number, which are bound to the order model using [can-stache-bindings](http://canjs.com/doc/can-stache-bindings.html)\n- Finally we disable the button with `{{^if canPlaceOrder}}disabled{{/if}}` which gets `canPlaceOrder` from the view model and returns false if no menu items are selected.\n\n## Set up a real-time connection\n\ncan-connect makes it very easy to implement real-time functionality. It is capable of listening to notifications from the server when server data has been created, updated, or removed. This is usually accomplished via [websockets](https://en.wikipedia.org/wiki/WebSocket), which allow sending push notifications to a client.\n\n### Adding real-time events to a model\n\nThe `place-my-order-api` module uses the [Feathers](http://feathersjs.com/) NodeJS framework, which in addition to providing a REST API, sends those events in the form of a websocket event like `orders created`. To make the order page update in real-time, all we need to do is add listeners for those events to `src/models/order.js` and in the handler notify the order connection.\n\n```\nnpm install steal-socket.io --save\n```\n\nUpdate `src/models/order.js` to:\n\n\n```js\nimport DefineMap from 'can-define/map/';\nimport DefineList from 'can-define/list/';\nimport superMap from 'can-connect/can/super-map/';\nimport tag from 'can-connect/can/tag/';\nimport io from 'steal-socket.io';\n\nconst Item = DefineMap.extend({\n price: 'number'\n});\n\nconst ItemsList = DefineList.extend({\n '*': Item\n}, {\n has: function(item) {\n return this.indexOf(item) !== -1;\n },\n\n toggle: function(item) {\n var index = this.indexOf(item);\n\n if (index !== -1) {\n this.splice(index, 1);\n } else {\n this.push(item);\n }\n }\n});\n\nexport const Order = DefineMap.extend({\n seal: false\n}, {\n '_id': '*',\n name: 'string',\n address: 'string',\n phone: 'string',\n restaurant: 'string',\n\n status: {\n value: 'new'\n },\n items: {\n Value: ItemsList\n },\n total: {\n get() {\n let total = 0.0;\n this.items.forEach(item =>\n total += parseFloat(item.price));\n return total.toFixed(2);\n }\n },\n\n markAs(status) {\n this.status = status;\n this.save();\n }\n});\n\nOrder.List = DefineList.extend({\n '*': Order\n});\n\nexport const orderConnection = superMap({\n url: '/api/orders',\n idProp: '_id',\n Map: Order,\n List: Order.List,\n name: 'order'\n});\n\nconst socket = io();\n\nsocket.on('orders created', order => orderConnection.createInstance(order));\nsocket.on('orders updated', order => orderConnection.updateInstance(order));\nsocket.on('orders removed', order => orderConnection.destroyInstance(order));\n\ntag('order-model', orderConnection);\n\nexport default Order;\n\n```\n\n### Update the template\n\nThat's all the JavaScript we need to implement real-time functionality. All the rest can be done by creating the `pmo-order-list` component with:\n\n```\ndonejs add component order/list.component pmo-order-list\n```\n\nChanging `src/order/list.component` to:\n\n\n```html\n\n \n

{{listTitle}}

\n\n {{#if orders.isPending}}\n
\n {{else}}\n {{#each orders.value}}\n
\n
\n {{name}}
{{address}}
{{phone}}\n
\n\n
\n
    \n {{#each items}}
  • {{name}}
  • {{/each}}\n
\n
\n\n
${{total}}
\n\n
\n {{statusTitle}}\n {{#if action}}\n

\n Mark as:\n \n {{actionTitle}}\n \n

\n {{/if}}\n\n

\n Delete\n

\n
\n
\n {{else}}\n
{{emptyMessage}}
\n {{/each}}\n {{/if}}\n
\n
\n\n```\n\nAnd in the order history template by updating `src/order/history.component` to:\n\n\n```html\n\n \n \n\n
\n
\n
Name / Address / Phone
\n
Order
\n
Total
\n
Action
\n
\n\n \n \n \n \n\n \n \n \n\n \n \n \n\n \n \n \n
\n
\n
\n\n```\n\nFirst we import the order model and then just call `'}\">` for each order status. That's it. If we now open the [order page](http://localhost:8080/order-history) we see some already completed default orders. Keeping the page open and placing a new order from another browser or device will update our order page automatically.\n\n## Create documentation\n\nDocumenting our code is very important to quickly get other developers up to speed. [DocumentJS](http://documentjs.com/) makes documenting code easier. It will generate a full documentation page from Markdown files and code comments in our project.\n\n### Installing and Configuring DocumentJS\n\nLet's add DocumentJS to our application:\n\n```\ndonejs add documentjs\n```\n\nThis will install DocumentJS and also create a `documentjs.json` configuration file. Now we can generate the documentation with:\n\n```\ndonejs document\n```\n\nThis produces documentation at [http://localhost:8080/docs/](http://localhost:8080/docs/).\n\n### Documenting a module\n\nLet's add the documentation for a module. Let's use `src/order/new/new.js` and update it with some inline comments that describe what our view model properties are supposed to do:\n\n\n```js\nimport Component from 'can-component';\nimport DefineMap from 'can-define/map/';\nimport './new.less';\nimport view from './new.stache';\nimport Restaurant from 'place-my-order/models/restaurant';\nimport Order from 'place-my-order/models/order';\n\n/**\n * @add place-my-order/order/new\n */\nexport const ViewModel = DefineMap.extend({\n /**\n * @property {string} slug\n *\n * the restaurants slug (short name). will\n * be used to request the actual restaurant.\n */\n slug: 'string',\n /**\n * @property {Promise} saveStatus\n *\n * a Promise that contains the status of the order when\n * it is being saved.\n */\n saveStatus: '*',\n /**\n * @property {place-my-order/models/order} order\n *\n * the order that is being processed. will\n * be an empty new order inititally.\n */\n order: {\n Value: Order\n },\n /**\n * @property {Promise} restaurantPromise\n *\n * a Promise that contains the restaurant that is being\n * ordered from.\n */\n get restaurantPromise() {\n return Restaurant.get({ _id: this.slug });\n },\n /**\n * @property {place-my-order/models/restaurant} restaurant\n *\n * the restaurant that is being ordered from.\n */\n restaurant: {\n get(lastSetVal, resolve) {\n this.restaurantPromise.then(resolve);\n }\n },\n /**\n * @property {Boolean} canPlaceOrder\n *\n * boolean indicating whether the order\n * can be placed.\n */\n get canPlaceOrder() {\n return this.order.items.length;\n },\n /**\n * @function placeOrder\n *\n * save the current order and update the status deferred.\n */\n placeOrder(ev) {\n ev.preventDefault();\n let order = this.order;\n order.restaurant = this.restaurant._id;\n this.saveStatus = order.save();\n },\n /**\n * @function startNewOrder\n *\n * resets the order form, so a new order can be placed.\n */\n startNewOrder() {\n this.order = new Order();\n this.saveStatus = null;\n }\n});\n\nexport default Component.extend({\n tag: 'pmo-order-new',\n ViewModel,\n view\n});\n\n```\n\nIf we now run `donejs document` again, we will see the module show up in the menu bar and will be able to navigate through the different properties.\n\n## Production builds\n\nNow we're ready to create a production build; go ahead and kill your development server, we won't need it from here on.\n\n### Progressive loading\n\nOur `index.stache` contains a can-import tag for each of the pages we have implemented. These can-imports which have nested html will be progressively loaded; the restaurant list page's JavaScript and CSS will only be loaded when the user visits that page.\n\n### Bundling assets\n\nLikely you have assets in your project other than your JavaScript and CSS that you will need to deploy to production. Place My Order has these assets saved to another project, you can view them at `node_modules/place-my-order-assets/images`.\n\nStealTools comes with the ability to bundle all of your static assets into a folder that can be deployed to production by itself. Think if it as a zip file that contains everything your app needs to run in production.\n\nTo use this capability add an option to your build script to enable it. Change:\n\n```js\nvar buildPromise = stealTools.build({\n config: __dirname + \"/package.json!npm\"\n}, {\n bundleAssets: true\n});\n```\n\nto:\n\n```js\nvar buildPromise = stealTools.build({\n config: __dirname + \"/package.json!npm\"\n}, {\n bundleAssets: {\n infer: false,\n glob: \"node_modules/place-my-order-assets/images/**/*\"\n }\n});\n```\n\n\nStealTools will find all of the assets you reference in your CSS and copy them to the dist folder. By default StealTools will set your [dest](http://stealjs.com/docs/steal-tools.build.html#dest) to `dist`, and will place the place-my-order-assets images in `dist/node_modules/place-my-order/assets/images`. bundleAssets preserves the path of your assets so that their locations are the same relative to the base url in both development and production.\n\n\n### Bundling your app\n\nTo bundle our application for production we use the build script in `build.js`. We could also use [Grunt](http://gruntjs.com/) or [Gulp](http://gulpjs.com/), but in this example we just run it directly with Node. Everything is set up already so we run:\n\n```\ndonejs build\n```\n\nThis will build the application to a `dist/` folder in the project's base directory.\n\nFrom here your application is ready to be used in production. Enable production mode by setting the `NODE_ENV` variable:\n\n```\nNODE_ENV=production donejs start\n```\n\nIf you're using Windows omit the NODE_ENV=production in the command, and instead see the [setting up guide](SettingUp.html#section=section_EnvironmentalVariables) on how to set environment variables.\n\nRefresh your browser to see the application load in production.\n\n## Desktop and mobile apps\n\n### Building to iOS and Android\n\nTo build the application as a Cordova based mobile application, you need to have each platform's SDK installed.\nWe'll be building an iOS app if you are a Mac user, and an Android app if you're a Windows user.\n\nMac users should download XCode from the AppStore and install the `ios-sim` package globally with:\n\n```\nnpm install -g ios-sim\n```\n\nWe will use these tools to create an iOS application that can be tested in the iOS simulator.\n\nWindows users should install the [Android Studio](https://developer.android.com/sdk/index.html), which gives all of the tools we need. See the [setting up guide](SettingUp.html#section=section_AndroidDevelopment) for full instructions on setting up your Android emulator.\n\nNow we can install the DoneJS Cordova tools with:\n\n```\ndonejs add cordova\n```\n\nDepending on your operating system you can accept most of the defaults, unless you would like to build for Android, which needs to be selected from the list of platforms.\n\nThis will change your `build.js` script with the options needed to build iOS/Android apps. Open this file and add the place-my-order-asset images to the **glob** property:\n\n```\nvar cordovaOptions = {\n buildDir: \"./build/cordova\",\n id: \"com.donejs.placemyorder\",\n name: \"place my order\",\n platforms: [\"ios\"],\n plugins: [\"cordova-plugin-transport-security\"],\n index: __dirname + \"/production.html\",\n glob: [\n \"node_modules/steal/steal.production.js\",\n \"node_modules/place-my-order-assets/images/**/*\"\n ]\n};\n```\n\n\n#### AJAX\n\nWhen not running in a traditional browser environment, AJAX requests need to be made\nto an external URL. The module `steal-platform` aids in detecting environments like Cordova\nso special behavior can be added. Install the module:\n\n```\nnpm install steal-platform --save\n```\n\nCreate a file: `src/service-base-url.js` and place this code:\n\n```js\nimport platform from \"steal-platform\";\n\nlet baseUrl = '';\n\nif(platform.isCordova || platform.isNW) {\n baseUrl = 'http://www.place-my-order.com';\n}\n\nexport default baseUrl;\n```\n\nThis detects if the environment running your app is either Cordova or NW.js and if so sets the baseUrl to place-my-order.com so that all AJAX requests will be made there.\n\nOur models will also need to be updated to use the baseUrl. For example in `src/models/state` do:\n\n```js\nimport can from 'can';\nimport superMap from 'can-connect/can/super-map/';\nimport tag from 'can-connect/can/tag/';\nimport 'can/map/define/define';\nimport baseUrl from '../service-base-url';\n\nexport const State = can.Map.extend({\n define: {}\n});\n\nState.List = can.List.extend({\n Map: State\n}, {});\n\nexport const stateConnection = superMap({\n url: baseUrl + '/api/states',\n idProp: 'short',\n Map: State,\n List: State.List,\n name: 'state'\n});\n\ntag('state-model', stateConnection);\n\nexport default State;\n```\n\nMake this same change in `src/models/city.js` and `src/models/restaurant.js`.\n\nFor `src/models/order`, you must also update the socket connection:\n\n```js\nimport superMap from 'can-connect/can/super-map/';\nimport tag from 'can-connect/can/tag/';\nimport List from 'can/list/';\nimport Map from 'can/map/';\nimport 'can/map/define/';\nimport io from 'steal-socket.io';\nimport baseUrl from '../service-base-url';\n\nconst ItemsList = List.extend({}, {\n has: function(item) {\n return this.indexOf(item) !== -1;\n },\n\n toggle: function(item) {\n var index = this.indexOf(item);\n\n if (index !== -1) {\n this.splice(index, 1);\n } else {\n this.push(item);\n }\n }\n});\n\nlet Order = Map.extend({\n define: {\n status: {\n value: 'new'\n },\n items: {\n Value: ItemsList\n },\n total: {\n get() {\n let total = 0.0;\n this.attr('items').forEach(item =>\n total += parseFloat(item.attr('price')));\n return total.toFixed(2);\n }\n }\n },\n\n markAs(status) {\n this.attr('status', status);\n this.save();\n }\n});\n\nexport const orderConnection = superMap({\n url: baseUrl + '/api/orders',\n idProp: '_id',\n Map: Order,\n List: Order.List,\n name: 'orders'\n});\n\nconst socket = io(baseUrl);\n\nsocket.on('orders created', order => orderConnection.createInstance(order));\nsocket.on('orders updated', order => orderConnection.updateInstance(order));\nsocket.on('orders removed', order => orderConnection.destroyInstance(order));\n\ntag('order-model', orderConnection);\nexport default Order;\n```\n\n\nTo run the Cordova build and launch the simulator we can now run:\n\n```\ndonejs build cordova\n```\n\nIf everything went well, we should see the emulator running our application.\n\n### Building to NW.js\n\nTo set up the desktop build, we have to add it to our application like this:\n\n```\ndonejs add nw\n```\n\nWe can answer most prompts with the default except for the version which needs to be set to the latest **stable version**. Set the version prompt to `0.12.3`.\n\nLike with Cordova, we need to add the place-my-order-assets images to the build, open your `build.js` script and update the **glob** property to reflect:\n\n```js\nvar nwOptions = {\n buildDir: \"./build\",\n version: \"0.12.3\",\n platforms: [\"osx32\",\"osx64\"],\n glob: [\n \"package.json\",\n \"production.html\",\n \"node_modules/steal/steal.production.js\",\n \"node_modules/place-my-order-assets/images/**/*\"\n ]\n};\n```\n\nThen we can run the build like this:\n\n```\ndonejs build nw\n```\n\nThe OS X application can be opened with\n\n```\nopen build/place-my-order/osx64/place-my-order.app\n```\n\nThe Windows application can be opened with\n\n```\n.\\build\\place-my-order\\win64\\place-my-order.exe\n```\n\n## Deploy\n\nNow that we verified that our application works in production, we can deploy it to the web. In this section, we will use [Firebase](https://www.firebase.com/), a service that provides static file hosting and [Content Delivery Network](https://en.wikipedia.org/wiki/Content_delivery_network) (CDN) support, to automatically deploy and serve our application's static assets from a CDN and [Heroku](https://heroku.com) to provide server-side rendering.\n\n### Static hosting on Firebase\n\nSign up for free at [Firebase](https://firebase.google.com/). After you have an account go to [Firebase console](https://console.firebase.google.com/) and create an app called `place-my-order-` where `` is your GitHub username:\n\n\"two\n\nWrite down the name of your app because you'll need it in the next section.\n\n> You will get an error if your app name is too long, so pick something on the shorter side, for example `pmo-`.\n\nWhen you deploy for the first time it will ask you to authorize with your login information, but first we need to configure the project.\n\n#### Configuring DoneJS\n\nWith the Firebase account and application in place we can add the deployment configuration to our project like this:\n\n```\ndonejs add firebase\n```\n\nWhen prompted, enter the name of the application created when you set up the Firebase app. Next, login to the firebase app for the first time by running:\n\n```\nnode_modules/.bin/firebase login\n```\n\nAnd authorize your application.\n\n#### Run deploy\n\nWe can now deploy the application by running:\n\n```\ndonejs build\ndonejs deploy\n```\n\nStatic files are deployed to Firebase and we can verify that the application is loading from the CDN by loading it running:\n\n```\nNODE_ENV=production donejs start\n```\n\n> If you're using Windows, set the NODE_ENV variable as you did previously in the Production section.\n\nWe should now see our assets being loaded from the Firebase CDN like this:\n\n![A network tab when using the CDN](static/img/guide-firebase-network.png)\n\n### Deploy your Node code\n\nAt this point your application has been deployed to a CDN. This contains StealJS, your production bundles and CSS, and any images or other static files. You still need to deploy your server code in order to get the benefit of server-side rendering.\n\nIf you do not have an account yet, sign up for Heroku at [signup.heroku.com](https://signup.heroku.com/). Then download the [Heroku CLI](https://devcenter.heroku.com/articles/heroku-command) which will be used to deploy.\n\nAfter installing we can initialize the application via\n\n```\nheroku login\nheroku create\n```\n\nThis will return the url where your app can be viewed. Before you open it you'll need to update the NODE_ENV variable:\n\n```\nheroku config:set NODE_ENV=production\n```\n\nAdd a new `Procfile` that tells Heroku what to launch as the app's server. Since we are using done-serve our Procfile just looks like this:\n\n```\nweb: node_modules/.bin/done-serve --proxy http://www.place-my-order.com/api\n```\n\nFirst let's save our current status:\n\n```\ngit add -A\ngit commit -m \"Finishing place-my-order\"\ngit push origin master\n```\n\nSince Heroku needs the build artifacts we need to commit those before pushing to Heroku. We recommend doing this in a separate branch.\n\n```\ngit checkout -b deploy\ngit add -f dist\ngit commit -m \"Deploying to Heroku\"\n```\n\nAnd finally do an initial deploy.\n\n```\ngit push heroku deploy:master\n```\n\nAny time in the future you want to deploy simply push to the Heroku remote. Once the deploy is finished you can open the link provided in your browser. If successful we can checkout the _master_ branch:\n\n```\ngit checkout master\n```\n\n### Continuous Deployment\n\nPreviously we set up Travis CI [for automated testing](#section=section_Continuousintegration) of our application code as we developed, but Travis (and other CI solutions) can also be used to deploy our code to production once tests have passed.\n\nOpen your `.travis.yml` file and add `before_deploy` and `deploy` keys that look like this:\n\n```yaml\nlanguage: node_js\nnode_js: node\nbefore_install:\n - \"export DISPLAY=:99.0\"\n - \"sh -e /etc/init.d/xvfb start\"\nbefore_deploy:\n - \"git config --global user.email \\\"me@example.com\\\"\"\n - \"git config --global user.name \\\"PMO deploy bot\\\"\"\n - \"node build\"\n - \"git add dist/ --force\"\n - \"git commit -m \\\"Updating build.\\\"\"\n - \"node_modules/.bin/firebase deploy --token \\\"$FIREBASE_TOKEN\\\"\"\ndeploy:\n skip_cleanup: true\n provider: \"heroku\"\n app: \n```\n\n\nYou can find the name of the app by running `heroku apps:info`.\n\nIn order to deploy to Heroku you need to provide Travis with your Heroku API key. Sensitive information in our `.travis.yml` should always be encrypted for which we install the [travis-encrypt](https://www.npmjs.com/package/travis-encrypt) module:\n\n*Note: if using Windows, first install the OpenSSL package as described in the [Setting Up](https://donejs.com/SettingUp.html) guide.*\n\n```\nnpm install travis-encrypt -g\n```\n\nNow we can get the Heroku authentication token with:\n\n```\nheroku auth:token\n```\n\nCopy the token printed and paste it as `` in the following command:\n\n```\ntravis-encrypt --add deploy.api_key -r /place-my-order \n```\n\nReplace `` with the name of your GitHub account.\n\nTo automate the deploy to Firebase you need to provide the Firebase CI token. You can get the token by running:\n\n```\nnode_modules/.bin/firebase login:ci\n```\n\nIn the application folder. It will open a browser window and ask you to authorize the application. Once successful, copy the token and use it as the `` in the following command:\n\n```\ntravis-encrypt --add -r /place-my-order 'FIREBASE_TOKEN=\"\"'\n```\n\nNow any time a build succeeds when pushing to `master` the application will be deployed to Heroku and static assets to Firebase's CDN.\n\nTo test this out checkout a new branch:\n\n```\ngit checkout -b continuous\ngit add -A\ngit commit -m \"Trying out continuous deployment\"\ngit push origin continuous\n```\n\nVisit your GitHub page, create a pull-request, wait for tests to pass and then merge. Visit your Travis CI build page at [https://travis-ci.org//place-my-order](https://travis-ci.org//place-my-order) to see the deployment happening in real time like this:\n\n![The Travis CI deploy](static/img/guide-travis-deploy.png)\n\n## What's next?\n\nIn this final short chapter, let's quickly look at what we did in this guide and where to follow up for any questions.\n\n### Recap\n\nIn this in-depth guide we created and deployed a fully tested restaurant menu ordering application called [place-my-order](http://www.place-my-order.com/) with DoneJS. We learned how to set up a DoneJS project, create custom elements and retrieve data from the server. Then we implemented a unit-tested view-model, ran those tests automatically from the command line and on a continuous integration server.\n\nWe went into more detail on how to create nested routes and importing other projects from NPM. Then we created new orders and made it real-time, added and built documentation and made a production build. Finally we turned that same application into a desktop and mobile application and deployed it to a CDN and the web.\n\n### Following up\n\nYou can learn more about each of the individual projects that DoneJS includes at:\n\n- [StealJS](http://stealjs.com) - ES6, CJS, and AMD module loader and builder\n- [CanJS](http://canjs.com) - Custom elements and Model-View-ViewModel utilities\n- [jQuery](http://jquery.com) - DOM helpers\n- [jQuery++](http://jquerypp.com) - Extended DOM helpers\n- [QUnit](https://qunitjs.com/) or Mocha - Assertion library\n- [FuncUnit](http://funcunit.com) - Functional tests\n- [Testee](https://github.com/bitovi/testee) - Test runner\n- [DocumentJS](http://documentjs.com) - Documentation\n\nIf you have any questions, do not hesitate to ask us on [Gitter](https://gitter.im/donejs/donejs) or the [forums](http://forums.donejs.com)!\n\n", + "description": "In this guide you will learn about all of [DoneJS' features]() by creating, testing, documenting, building and deploying [place-my-order.com](http://place-my-order.com), a restaurant menu and ordering application. The final result will look like this: \n\n\n\n\nAfter the initial application setup, which includes a server that hosts and pre-renders the application, we will create several custom elements and bring them together using the application state and routes. Then we will learn how to retrieve data from the server using a RESTful API.\n\nAfter that we will talk about what a view model is and how to identify, implement and test its functionality. Once we have unit tests running in the browser, we will automate running them locally from the command line and also on a continuous integration server. In the subsequent chapters, we will show how to easily import other modules into our application and how to set up a real-time connection.\n\nFinally, we will describe how to build and deploy our application to the web, as a desktop application with nw.js, and as a mobile app with Cordova.\n\n\n", + "name": "place-my-order", + "title": "In depth guide", + "type": "page", + "parent": "DoneJS", + "hideSidebar": true, + "outline": { + "depth": 2, + "tag": "ol" + }, + "comment": " " + }, "About-ru": { "src": { "path": "docs/ru/about-ru.md" diff --git a/make-example.js b/make-example.js index ee5c74d..7c9cd8f 100644 --- a/make-example.js +++ b/make-example.js @@ -17,7 +17,8 @@ generate(docMap, { templates: path.join(__dirname, "templates"), dependencies: { "can": "2.3.28", - "bit-docs-donejs-theme": __dirname + "bit-docs-donejs-theme": __dirname, + "bit-docs-html-toc": "^0.5.0" } }, dest: path.join(__dirname, "site"), diff --git a/static/content_list.js b/static/content_list.js deleted file mode 100644 index 32b6bab..0000000 --- a/static/content_list.js +++ /dev/null @@ -1,92 +0,0 @@ -var $ = require("jquery"); -var Control = require("can/control/"); - -require("can/observe/"); - -var contentList = function(sections, tag) { - var element = $("<" + tag + ">"); - $.each(sections, function(i, section) { - $li = $("
  • "); - $a = $("").attr("href", "#" + section.id).text(section.text); - element.append($li.append($a)); - - if (section.sections && section.sections.length) { - $li.append(contentList(section.sections, tag)); - } - }); - return element; -}; - -module.exports = Control.extend({ - init: function() { - var sections = []; - - this.collectSignatures().each(function(ix) { - var h2 = $("h2", this); - this.id = "sig_" + h2.text().replace(/\s/g, "").replace(/[^\w]/g, "_"); - //this.id = encodeURIComponent(h2.text()); - sections.push({ id: this.id, text: h2.text() }); - }); - - var headingStack = [], - last = function() { - return headingStack[headingStack.length - 1]; - }; - - var ch = this.collectHeadings().each(function(ix) { - var el = $(this); - this.id = "section_" + - el.text().replace(/\s/g, "").replace(/[^\w]/g, "_"); - var num = +this.nodeName.substr(1); - var section = { - id: this.id, - text: el.text(), - num: num, - sections: [] - }; - - while (last() && last().num >= num) { - headingStack.pop(); - } - - if (!headingStack.length) { - sections.push(section); - headingStack.push(section); - } else { - last().sections.push(section); - headingStack.push(section); - } - }); - - this.element.html( - contentList( - sections, - (window.docObject.outline && window.docObject.outline.tag || - "ul").toLowerCase() - ) - ); - - if (window.location.hash.length) { - var id = window.location.hash.replace("#", ""), - anchor = document.getElementById(id); - - if (anchor) { - anchor.scrollIntoView(true); - } - } - }, - collectSignatures: function() { - var cloned = $(".content .signature").clone(); - // remove release numbers - cloned.find(".release").remove(); - return cloned; - }, - collectHeadings: function() { - var depth = window.docObject.outline && window.docObject.outline.depth || 1; - var headings = []; - for (var i = 0; i < depth; i++) { - headings.push("h" + (i + 2)); - } - return $(".content .comment").find(headings.join(",")); - } -}); diff --git a/static/content_list.mustache b/static/content_list.mustache deleted file mode 100644 index a057f8c..0000000 --- a/static/content_list.mustache +++ /dev/null @@ -1,5 +0,0 @@ - \ No newline at end of file diff --git a/static/handle-page-anchors.js b/static/handle-page-anchors.js new file mode 100644 index 0000000..6aa3c77 --- /dev/null +++ b/static/handle-page-anchors.js @@ -0,0 +1,86 @@ +module.exports = function() { + var headings = {}; + var collected = collectHeadings(); + + collected.each(function() { + var $el = $(this); + var id = $el.attr("id"); + + if (id) headings[id] = true; + }); + + collected.each(function() { + var $el = $(this); + var id = $el.attr("id"); + + if (!id) { + id = makeAnchorHeadingId($el.text()); + var token = getUniqueToken(id, headings); + + id += token > 0 ? "-" + token : ""; + headings[id] = true; + + $el.attr("id", id); + } + + $el.prepend(anchorTemplate({ id: id })); + }); + + // hijack anchor page jumps, animate scroll + $('a[href*="#"]:not([href="#"])').on("click", function() { + if ( + location.pathname.replace(/^\//, "") == this.pathname.replace(/^\//, "") || + location.hostname == this.hostname + ) { + var offset = -55; + var $jumpTo = $(this.hash); + + var distance = Math.abs( + $("body").scrollTop() - ($jumpTo.offset().top + offset) + ); + var duration = Math.max(500, distance / 6000 * 250); + + $("html, body").animate( + { + scrollTop: $jumpTo.offset().top + offset + }, + duration + ); + } + }); + + // module helpers + + function getUniqueToken(id, headings) { + var token = 0; + var uniq = id; + + while (headings[uniq]) { + token += 1; + uniq = id + "-" + token; + } + + return token; + } + + function collectHeadings() { + return $("body:not(.donejs):not(.community)").find("h2, h3, h4, h5"); + } + + function makeAnchorHeadingId(anchorText) { + return (anchorText || "") + .replace(/\s/g, "-") // replace spaces with dashes + .replace(/[^\w\-]/g, "") // remove punctuation + .toLowerCase(); + } + + function anchorTemplate(ctx) { + var id = encodeURIComponent(ctx.id); + + return '' + + '' + + ""; + } +}; diff --git a/static/static.js b/static/static.js index 24c2641..61672f1 100644 --- a/static/static.js +++ b/static/static.js @@ -1,8 +1,8 @@ var $ = require("jquery"); -var ContentList = require("./content_list"); -var FrameHelper = require("./frame_helper"); var Versions = require("./versions"); +var FrameHelper = require("./frame_helper"); var Highlighter = require("./js/line-highlight"); +var handlePageAnchors = require("./handle-page-anchors"); require("./js/collapse"); require("./js/dropdown"); @@ -26,7 +26,6 @@ for (var i = 0; i < codes.length; i++) { prettyPrint(); -new ContentList(".contents"); new FrameHelper(".docs"); new Versions($("#versions, .sidebar-title:first")); @@ -34,6 +33,9 @@ $("textarea").click(function() { this.select(); }); +// perform a smooth page scroll to anchors on the same page +$(handlePageAnchors); + if ($(".twitter-follow-button").length) { // replace the "Follow @canjs!" link with a little wiget with follower count. $("#twitter-wjs").remove(); @@ -194,20 +196,6 @@ var getNavToHeaderEl = function(hEl) { return $("section.contents a[href*='" + id + "']"); }; -$("section.comment h3").each(function() { - //fix duplicate id problem - var ids = $('[id="' + this.id + '"]'); - if (ids.length > 1 && ids[0] === this) { - var navTo = getNavToHeaderEl(ids); - ids.each(function(x, el) { - var aEl = navTo.get(x); - aEl.href = aEl.href.replace(el.id, el.id + x); - - el.id = el.id + x; - }); - } -}); - var getSpyableElementFromPoint = (function() { var lastElAtPoint, x, y; var fromThese = $("section.comment > *"); @@ -367,76 +355,30 @@ $(window).scroll(function() { } }); -$("body:not(.donejs):not(.community)").find("h3, h4, h5").each(function() { - if (!this.id) { - var tag = this.tagName.toLowerCase(); - var prevTag = "h" + (parseInt(tag.replace(/h(\d)/, "$1")) - 1); - var prevEl = $(this).prevAll(prevTag).get(0); - var prevId = prevEl ? prevEl.id : ""; - - this.id = prevId + "__" + $(this).text().replace(/[^a-z0-9]/gi, ""); - } - var html = ""; - html += ""; - html += ""; - $(this).prepend(html); -}); - -//hijack guide page jumps, animate scroll +// hijack guide page jumps, animate scroll $(function() { - var clickFn = function() { + $("section.contents a").on("click", function(evt) { var thisLi = $(this).closest("li"); + if ($("section.contents").is(".active") && thisLi.is("ol > li > ol > li")) { $(".scroll-spy-title").click(); } - }; - - $("section.contents a").each(function() { - this.href = this.href.replace("#", "#section="); - - $(this).on("click", clickFn); - - return true; }); var hashOnLoad = window.location.hash; - if (hashOnLoad) { - var jumpTo = hashOnLoad.replace(/.*?#section=/, "#"); - if ($(jumpTo).length) { - var offset = -55; - $("html, body").animate( - { - scrollTop: $(jumpTo).offset().top + offset - }, - 500 - ); - } - } -}); + var $jumpTo = $(hashOnLoad); -window.addEventListener( - "hashchange", - function(hashChangeEvent) { + if (hashOnLoad && $jumpTo.length) { var offset = -55; - var newHash = hashChangeEvent.newURL.replace(/.*?(#.*)/g, "$1"); - - if (newHash.indexOf("#section=") === -1) return; - - var jumpTo = newHash.replace(/.*?#section=/, "#"); - var distance = Math.abs( - $("body").scrollTop() - ($(jumpTo).offset().top + offset) - ); - var duration = Math.max(500, distance / 6000 * 250); $("html, body").animate( { - scrollTop: $(jumpTo).offset().top + offset + scrollTop: $jumpTo.offset().top + offset }, - duration + 500 ); - }, - false -); + } +}); $(window).scroll(function() { if (!isMobileSize) return; diff --git a/templates/content.mustache b/templates/content.mustache index 6438271..953b593 100644 --- a/templates/content.mustache +++ b/templates/content.mustache @@ -32,7 +32,7 @@ rendering the "regular" content }} {{/unless}} {{#unless hideArticle}} -
    +
    {{/unless}} diff --git a/templates/layout.mustache b/templates/layout.mustache index 7e7ef4c..2c43051 100644 --- a/templates/layout.mustache +++ b/templates/layout.mustache @@ -143,7 +143,6 @@