Skip to content
Matthew Phillips edited this page Sep 25, 2015 · 43 revisions

Setup

Install donejs

npm install donejs -g

Create a new project

donejs init donejs-chat

Then go into the application folder

cd donejs-chat

Start the donejs server

donejs develop

Add bootstrap and checkout live-reload

Install bootstrap

npm install bootstrap --save

Add it to your page

Change index.stache to:

<html><head><title>{{title}}</title>
{{asset "css"}}
</head><body><can-importfrom="bootstrap/less/bootstrap.less!" /><can-importfrom="donejs-chat/styles.less!" /><can-importfrom="donejs-chat/app" as="viewModel" />
{{asset "inline-cache"}}
{{#switch @env.NODE_ENV}}
{{#case "production"}}
<scriptsrc="http://donejs-chat.divshot.io/node_modules/steal/steal.production.js" main="donejs-chat/index.stache!done-autorender"></script>
{{/case}}
{{#default}}
<scriptsrc="/node_modules/steal/steal.js"></script>
{{/default}}
{{/switch}}
</body></html>

Add some HTML that uses it

<divclass="container"><divclass="row"><divclass="col-sm-8 col-sm-offset-2"><h1>Hello world</h1></div></div></div>

Show live-reload awesomeness

Make some changes and see stuff updates. Talk about how live-reload even works on the server!!!

Setup Basic Routing

Generate Home Component

donejs generate component home.component chat-home

Generate chat-messages component

donejs generate component messages chat-messages

Set up navigation between components.

  1. Add link to chat-home
<can-componenttag="chat-home"><styletype="less">display: block;
h1.page-header { margin-top:0; }
</style><template><can-importfrom="can/view/href/" /><h1class="page-header text-center"><imgsrc="http://donejs.com/static/img/donejs-logo-white.svg" alt="DoneJS logo" /><br>Chat
</h1><acan-href="{ page='chat' }" class="btn btn-primary btn-block btn-lg">Start chat</a></template></can-component>
  1. Add link on chat page (messages/messages.stache)
<can-importfrom="can/view/href/" /><h5><acan-href="{ page='home' }">Home</a></h5><p>{{message}}</p>
  1. Add route in app.js
route('/:page',{page: 'home'});
  1. Load dynamically in index.stache
<divclass="container"><divclass="row"><divclass="col-sm-8 col-sm-offset-2">
{{#eq page 'chat'}}
<can-importfrom="donejs-chat/messages/">
{{#if isPending}}
Loading...
{{else}}
<chat-messages/>
{{/if}}
</can-import>
{{else}}
<can-importfrom="donejs-chat/home.component!">
{{#if isPending}}
Loading...
{{else}}
<chat-home/>
{{/if}}
</can-import>
{{/eq}}
</div></div></div>

Complete the messages page

Generate Message model

donejs generate supermodel message

Set URL to http://donejs-chat.herokuapp.com/api/messages.

Use Message model

In src/messages/messages.stache:

<message-modelget-list="{}"><h5><acan-href="{ page='home' }">Home</a></h5><divclass="list-group">
{{#each ./value}}
<aclass="list-group-item"><h4class="list-group-item-heading">{{name}}</h4><pclass="list-group-item-text">{{message}}</p></a>
{{/each}}
{{^if ./value.length}}
<aclass="list-group-item"><h4class="list-group-item-heading">No messages</h4></a>
{{/if}}
</div></message-model>

alternate:

<can-importfrom="donejs-chat/models/message" /><h5><acan-href="{ page='home' }">Home</a></h5><message-modelget-list="{}" class="list-group">
{{#each ./value}}
<aclass="list-group-item"><h4class="list-group-item-heading">{{name}}</h4><pclass="list-group-item-text">{{message}}</p></a>
{{else}}
<aclass="list-group-item"><h4class="list-group-item-heading">No messages</h4></a>
{{/each}}
</message-model>

Create messages

  1. add html, and (enter) event handler
<divclass="row"><divclass="col-sm-3"><inputtype="text" class="form-control" id="name" placeholder="Your name" can-value="{name}"></div><divclass="col-sm-9"><inputtype="text" class="form-control" id="message" placeholder="Your message" can-value="{message}" (enter)="{send}"></div></div>
  1. import Message model in messages.js
<can-importfrom="donejs-chat/models/message" />
  1. Add send method in src/messages/messages.js
importComponentfrom'can/component/';importMapfrom'can/map/';import'can/map/define/';import'./messages.less!';importtemplatefrom'./messages.stache!';importMessagefrom'../models/message';exportconstViewModel=Map.extend({send(){newMessage({name: this.attr('name'),message: this.attr('message')}).save().then(msg=>this.attr('message',''));}});exportdefaultComponent.extend({tag: 'chat-messages',viewModel: ViewModel,
template
});
  1. Talk about set logic

Make it work real-time

> npm install steal-socket.io --save

Add to src/models/message.js

importiofrom'steal-socket.io';constsocket=io('http://donejs-chat.herokuapp.com');socket.on('messages created',order=>messageConnection.createInstance(order));socket.on('messages updated',order=>messageConnection.updateInstance(order));socket.on('messages removed',order=>messageConnection.destroyInstance(order));

Make homepage

Add tabs

npm install bit-tabs --save

Import:

<can-importfrom="bit-tabs/unstyled" />

Add to page:

<bit-tabstabs-class="nav nav-tabs"><bit-paneltitle="CanJS">
CanJS provides the MV*
</bit-panel><bit-paneltitle="StealJS">
StealJS provides the infrastructure.
</bit-panel></bit-tabs>

Add some styles:

bit-panel {
display: block;
padding:10px;
}

Talk about cool stuff

  1. Server Side Rendering
  2. Fall through caching
  3. Inline caching
  4. Request combining

Show off build locally.

Run build

node build

Set to production.

Close the old server and run

NODE_ENV=production donejs start

Show bundles loading progressively

Show off div-shot

  1. Create Divshot application, install the CLI tool and log in
> npm install -g divshot-cli
> divshot login
  1. Paste config in
"donejs": {"deploy": {"root": "dist","services": {"production": {"type": "divshot","config": {"name": "donejs-chat","headers": {"/**": {"Access-Control-Allow-Origin": "*"}}}}}}},
...
"system": {
...
"envs": {"server-production": {"baseURL": "https://donejs-chat.divshot.io/"}}}
  1. Run node build again.
  2. Run donejs deploy
  3. Add http://donejs-chat.divshot.io to <script src and to envs.server-production.baseURL
  4. Show off

Desktop and mobile apps

First create an app.html file that looks like:

<html><head><title>DoneJS chat</title></head><body><scriptload-bundlesenv="cordova-production" src="node_modules/steal/steal.production.js" main="donejs-chat/index.stache!done-autorender"></script></body></html>

Cordova

Make sure all platform SDKs like XCode (for iOS) and the Android SDK are installed.

Update build.js to:

varstealTools=require("steal-tools");varbuildPromise=stealTools.build({config: __dirname+"/package.json!npm"},{bundleAssets: true});varcordovaOptions={buildDir: "./build/cordova",id: "com.donejs.chat",name: "DoneJS chat",platforms: ["ios"],plugins: ["cordova-plugin-transport-security"],index: __dirname+"/app.html",glob: ["node_modules/steal/steal.production.js"]};varstealCordova=require("steal-cordova")(cordovaOptions);// Check if the cordova option is passed.varbuildCordova=process.argv.indexOf("cordova")>0;if(buildCordova){buildPromise.then(stealCordova.build).then(stealCordova.ios.emulate);}

Then run

npm install ios-sim -g

node build cordova

NW.js

Update your package.json:

"main": "app.html",
...
"window": {"width": 1060,"height": 625,"toolbar": false}

Add to build.js:

varnwOptions={buildDir: "./build",platforms: ["osx"],files: ["package.json","app.html","node_modules/steal/steal.production.js"],version: "0.12.3"};varstealNw=require("steal-nw");// Check if the cordova option is passed.varbuildNW=process.argv.indexOf("nw")>0;if(buildNW){buildPromise=buildPromise.then(function(buildResult){stealNw(nwOptions,buildResult);});}

Add to app.js

import platform from "steal-platform"
if(platform.isCordova || platform.isNW) {
route.defaultBinding = "hashchange";
}

Then run

node build nw

cd build/donejs-chat/osx64

open donejs-chat.app

, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Guide · donejs/chat Wiki · GitHub
Skip to content
Matthew Phillips edited this page Sep 25, 2015 · 43 revisions

Setup

Install donejs

npm install donejs -g

Create a new project

donejs init donejs-chat

Then go into the application folder

cd donejs-chat

Start the donejs server

donejs develop

Add bootstrap and checkout live-reload

Install bootstrap

npm install bootstrap --save

Add it to your page

Change index.stache to:

<html><head><title>{{title}}</title>
{{asset "css"}}
</head><body><can-importfrom="bootstrap/less/bootstrap.less!" /><can-importfrom="donejs-chat/styles.less!" /><can-importfrom="donejs-chat/app" as="viewModel" />
{{asset "inline-cache"}}
{{#switch @env.NODE_ENV}}
{{#case "production"}}
<scriptsrc="http://donejs-chat.divshot.io/node_modules/steal/steal.production.js" main="donejs-chat/index.stache!done-autorender"></script>
{{/case}}
{{#default}}
<scriptsrc="/node_modules/steal/steal.js"></script>
{{/default}}
{{/switch}}
</body></html>

Add some HTML that uses it

<divclass="container"><divclass="row"><divclass="col-sm-8 col-sm-offset-2"><h1>Hello world</h1></div></div></div>

Show live-reload awesomeness

Make some changes and see stuff updates. Talk about how live-reload even works on the server!!!

Setup Basic Routing

Generate Home Component

donejs generate component home.component chat-home

Generate chat-messages component

donejs generate component messages chat-messages

Set up navigation between components.

  1. Add link to chat-home
<can-componenttag="chat-home"><styletype="less">display: block;
h1.page-header { margin-top:0; }
</style><template><can-importfrom="can/view/href/" /><h1class="page-header text-center"><imgsrc="http://donejs.com/static/img/donejs-logo-white.svg" alt="DoneJS logo" /><br>Chat
</h1><acan-href="{ page='chat' }" class="btn btn-primary btn-block btn-lg">Start chat</a></template></can-component>
  1. Add link on chat page (messages/messages.stache)
<can-importfrom="can/view/href/" /><h5><acan-href="{ page='home' }">Home</a></h5><p>{{message}}</p>
  1. Add route in app.js
route('/:page',{page: 'home'});
  1. Load dynamically in index.stache
<divclass="container"><divclass="row"><divclass="col-sm-8 col-sm-offset-2">
{{#eq page 'chat'}}
<can-importfrom="donejs-chat/messages/">
{{#if isPending}}
Loading...
{{else}}
<chat-messages/>
{{/if}}
</can-import>
{{else}}
<can-importfrom="donejs-chat/home.component!">
{{#if isPending}}
Loading...
{{else}}
<chat-home/>
{{/if}}
</can-import>
{{/eq}}
</div></div></div>

Complete the messages page

Generate Message model

donejs generate supermodel message

Set URL to http://donejs-chat.herokuapp.com/api/messages.

Use Message model

In src/messages/messages.stache:

<message-modelget-list="{}"><h5><acan-href="{ page='home' }">Home</a></h5><divclass="list-group">
{{#each ./value}}
<aclass="list-group-item"><h4class="list-group-item-heading">{{name}}</h4><pclass="list-group-item-text">{{message}}</p></a>
{{/each}}
{{^if ./value.length}}
<aclass="list-group-item"><h4class="list-group-item-heading">No messages</h4></a>
{{/if}}
</div></message-model>

alternate:

<can-importfrom="donejs-chat/models/message" /><h5><acan-href="{ page='home' }">Home</a></h5><message-modelget-list="{}" class="list-group">
{{#each ./value}}
<aclass="list-group-item"><h4class="list-group-item-heading">{{name}}</h4><pclass="list-group-item-text">{{message}}</p></a>
{{else}}
<aclass="list-group-item"><h4class="list-group-item-heading">No messages</h4></a>
{{/each}}
</message-model>

Create messages

  1. add html, and (enter) event handler
<divclass="row"><divclass="col-sm-3"><inputtype="text" class="form-control" id="name" placeholder="Your name" can-value="{name}"></div><divclass="col-sm-9"><inputtype="text" class="form-control" id="message" placeholder="Your message" can-value="{message}" (enter)="{send}"></div></div>
  1. import Message model in messages.js
<can-importfrom="donejs-chat/models/message" />
  1. Add send method in src/messages/messages.js
importComponentfrom'can/component/';importMapfrom'can/map/';import'can/map/define/';import'./messages.less!';importtemplatefrom'./messages.stache!';importMessagefrom'../models/message';exportconstViewModel=Map.extend({send(){newMessage({name: this.attr('name'),message: this.attr('message')}).save().then(msg=>this.attr('message',''));}});exportdefaultComponent.extend({tag: 'chat-messages',viewModel: ViewModel,
template
});
  1. Talk about set logic

Make it work real-time

> npm install steal-socket.io --save

Add to src/models/message.js

importiofrom'steal-socket.io';constsocket=io('http://donejs-chat.herokuapp.com');socket.on('messages created',order=>messageConnection.createInstance(order));socket.on('messages updated',order=>messageConnection.updateInstance(order));socket.on('messages removed',order=>messageConnection.destroyInstance(order));

Make homepage

Add tabs

npm install bit-tabs --save

Import:

<can-importfrom="bit-tabs/unstyled" />

Add to page:

<bit-tabstabs-class="nav nav-tabs"><bit-paneltitle="CanJS">
CanJS provides the MV*
</bit-panel><bit-paneltitle="StealJS">
StealJS provides the infrastructure.
</bit-panel></bit-tabs>

Add some styles:

bit-panel {
display: block;
padding:10px;
}

Talk about cool stuff

  1. Server Side Rendering
  2. Fall through caching
  3. Inline caching
  4. Request combining

Show off build locally.

Run build

node build

Set to production.

Close the old server and run

NODE_ENV=production donejs start

Show bundles loading progressively

Show off div-shot

  1. Create Divshot application, install the CLI tool and log in
> npm install -g divshot-cli
> divshot login
  1. Paste config in
"donejs": {"deploy": {"root": "dist","services": {"production": {"type": "divshot","config": {"name": "donejs-chat","headers": {"/**": {"Access-Control-Allow-Origin": "*"}}}}}}},
...
"system": {
...
"envs": {"server-production": {"baseURL": "https://donejs-chat.divshot.io/"}}}
  1. Run node build again.
  2. Run donejs deploy
  3. Add http://donejs-chat.divshot.io to <script src and to envs.server-production.baseURL
  4. Show off

Desktop and mobile apps

First create an app.html file that looks like:

<html><head><title>DoneJS chat</title></head><body><scriptload-bundlesenv="cordova-production" src="node_modules/steal/steal.production.js" main="donejs-chat/index.stache!done-autorender"></script></body></html>

Cordova

Make sure all platform SDKs like XCode (for iOS) and the Android SDK are installed.

Update build.js to:

varstealTools=require("steal-tools");varbuildPromise=stealTools.build({config: __dirname+"/package.json!npm"},{bundleAssets: true});varcordovaOptions={buildDir: "./build/cordova",id: "com.donejs.chat",name: "DoneJS chat",platforms: ["ios"],plugins: ["cordova-plugin-transport-security"],index: __dirname+"/app.html",glob: ["node_modules/steal/steal.production.js"]};varstealCordova=require("steal-cordova")(cordovaOptions);// Check if the cordova option is passed.varbuildCordova=process.argv.indexOf("cordova")>0;if(buildCordova){buildPromise.then(stealCordova.build).then(stealCordova.ios.emulate);}

Then run

npm install ios-sim -g

node build cordova

NW.js

Update your package.json:

"main": "app.html",
...
"window": {"width": 1060,"height": 625,"toolbar": false}

Add to build.js:

varnwOptions={buildDir: "./build",platforms: ["osx"],files: ["package.json","app.html","node_modules/steal/steal.production.js"],version: "0.12.3"};varstealNw=require("steal-nw");// Check if the cordova option is passed.varbuildNW=process.argv.indexOf("nw")>0;if(buildNW){buildPromise=buildPromise.then(function(buildResult){stealNw(nwOptions,buildResult);});}

Add to app.js

import platform from "steal-platform"
if(platform.isCordova || platform.isNW) {
route.defaultBinding = "hashchange";
}

Then run

node build nw

cd build/donejs-chat/osx64

open donejs-chat.app

, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Guide · donejs/chat Wiki · GitHub
Skip to content
Matthew Phillips edited this page Sep 25, 2015 · 43 revisions

Setup

Install donejs

npm install donejs -g

Create a new project

donejs init donejs-chat

Then go into the application folder

cd donejs-chat

Start the donejs server

donejs develop

Add bootstrap and checkout live-reload

Install bootstrap

npm install bootstrap --save

Add it to your page

Change index.stache to:

<html><head><title>{{title}}</title>
{{asset "css"}}
</head><body><can-importfrom="bootstrap/less/bootstrap.less!" /><can-importfrom="donejs-chat/styles.less!" /><can-importfrom="donejs-chat/app" as="viewModel" />
{{asset "inline-cache"}}
{{#switch @env.NODE_ENV}}
{{#case "production"}}
<scriptsrc="http://donejs-chat.divshot.io/node_modules/steal/steal.production.js" main="donejs-chat/index.stache!done-autorender"></script>
{{/case}}
{{#default}}
<scriptsrc="/node_modules/steal/steal.js"></script>
{{/default}}
{{/switch}}
</body></html>

Add some HTML that uses it

<divclass="container"><divclass="row"><divclass="col-sm-8 col-sm-offset-2"><h1>Hello world</h1></div></div></div>

Show live-reload awesomeness

Make some changes and see stuff updates. Talk about how live-reload even works on the server!!!

Setup Basic Routing

Generate Home Component

donejs generate component home.component chat-home

Generate chat-messages component

donejs generate component messages chat-messages

Set up navigation between components.

  1. Add link to chat-home
<can-componenttag="chat-home"><styletype="less">display: block;
h1.page-header { margin-top:0; }
</style><template><can-importfrom="can/view/href/" /><h1class="page-header text-center"><imgsrc="http://donejs.com/static/img/donejs-logo-white.svg" alt="DoneJS logo" /><br>Chat
</h1><acan-href="{ page='chat' }" class="btn btn-primary btn-block btn-lg">Start chat</a></template></can-component>
  1. Add link on chat page (messages/messages.stache)
<can-importfrom="can/view/href/" /><h5><acan-href="{ page='home' }">Home</a></h5><p>{{message}}</p>
  1. Add route in app.js
route('/:page',{page: 'home'});
  1. Load dynamically in index.stache
<divclass="container"><divclass="row"><divclass="col-sm-8 col-sm-offset-2">
{{#eq page 'chat'}}
<can-importfrom="donejs-chat/messages/">
{{#if isPending}}
Loading...
{{else}}
<chat-messages/>
{{/if}}
</can-import>
{{else}}
<can-importfrom="donejs-chat/home.component!">
{{#if isPending}}
Loading...
{{else}}
<chat-home/>
{{/if}}
</can-import>
{{/eq}}
</div></div></div>

Complete the messages page

Generate Message model

donejs generate supermodel message

Set URL to http://donejs-chat.herokuapp.com/api/messages.

Use Message model

In src/messages/messages.stache:

<message-modelget-list="{}"><h5><acan-href="{ page='home' }">Home</a></h5><divclass="list-group">
{{#each ./value}}
<aclass="list-group-item"><h4class="list-group-item-heading">{{name}}</h4><pclass="list-group-item-text">{{message}}</p></a>
{{/each}}
{{^if ./value.length}}
<aclass="list-group-item"><h4class="list-group-item-heading">No messages</h4></a>
{{/if}}
</div></message-model>

alternate:

<can-importfrom="donejs-chat/models/message" /><h5><acan-href="{ page='home' }">Home</a></h5><message-modelget-list="{}" class="list-group">
{{#each ./value}}
<aclass="list-group-item"><h4class="list-group-item-heading">{{name}}</h4><pclass="list-group-item-text">{{message}}</p></a>
{{else}}
<aclass="list-group-item"><h4class="list-group-item-heading">No messages</h4></a>
{{/each}}
</message-model>

Create messages

  1. add html, and (enter) event handler
<divclass="row"><divclass="col-sm-3"><inputtype="text" class="form-control" id="name" placeholder="Your name" can-value="{name}"></div><divclass="col-sm-9"><inputtype="text" class="form-control" id="message" placeholder="Your message" can-value="{message}" (enter)="{send}"></div></div>
  1. import Message model in messages.js
<can-importfrom="donejs-chat/models/message" />
  1. Add send method in src/messages/messages.js
importComponentfrom'can/component/';importMapfrom'can/map/';import'can/map/define/';import'./messages.less!';importtemplatefrom'./messages.stache!';importMessagefrom'../models/message';exportconstViewModel=Map.extend({send(){newMessage({name: this.attr('name'),message: this.attr('message')}).save().then(msg=>this.attr('message',''));}});exportdefaultComponent.extend({tag: 'chat-messages',viewModel: ViewModel,
template
});
  1. Talk about set logic

Make it work real-time

> npm install steal-socket.io --save

Add to src/models/message.js

importiofrom'steal-socket.io';constsocket=io('http://donejs-chat.herokuapp.com');socket.on('messages created',order=>messageConnection.createInstance(order));socket.on('messages updated',order=>messageConnection.updateInstance(order));socket.on('messages removed',order=>messageConnection.destroyInstance(order));

Make homepage

Add tabs

npm install bit-tabs --save

Import:

<can-importfrom="bit-tabs/unstyled" />

Add to page:

<bit-tabstabs-class="nav nav-tabs"><bit-paneltitle="CanJS">
CanJS provides the MV*
</bit-panel><bit-paneltitle="StealJS">
StealJS provides the infrastructure.
</bit-panel></bit-tabs>

Add some styles:

bit-panel {
display: block;
padding:10px;
}

Talk about cool stuff

  1. Server Side Rendering
  2. Fall through caching
  3. Inline caching
  4. Request combining

Show off build locally.

Run build

node build

Set to production.

Close the old server and run

NODE_ENV=production donejs start

Show bundles loading progressively

Show off div-shot

  1. Create Divshot application, install the CLI tool and log in
> npm install -g divshot-cli
> divshot login
  1. Paste config in
"donejs": {"deploy": {"root": "dist","services": {"production": {"type": "divshot","config": {"name": "donejs-chat","headers": {"/**": {"Access-Control-Allow-Origin": "*"}}}}}}},
...
"system": {
...
"envs": {"server-production": {"baseURL": "https://donejs-chat.divshot.io/"}}}
  1. Run node build again.
  2. Run donejs deploy
  3. Add http://donejs-chat.divshot.io to <script src and to envs.server-production.baseURL
  4. Show off

Desktop and mobile apps

First create an app.html file that looks like:

<html><head><title>DoneJS chat</title></head><body><scriptload-bundlesenv="cordova-production" src="node_modules/steal/steal.production.js" main="donejs-chat/index.stache!done-autorender"></script></body></html>

Cordova

Make sure all platform SDKs like XCode (for iOS) and the Android SDK are installed.

Update build.js to:

varstealTools=require("steal-tools");varbuildPromise=stealTools.build({config: __dirname+"/package.json!npm"},{bundleAssets: true});varcordovaOptions={buildDir: "./build/cordova",id: "com.donejs.chat",name: "DoneJS chat",platforms: ["ios"],plugins: ["cordova-plugin-transport-security"],index: __dirname+"/app.html",glob: ["node_modules/steal/steal.production.js"]};varstealCordova=require("steal-cordova")(cordovaOptions);// Check if the cordova option is passed.varbuildCordova=process.argv.indexOf("cordova")>0;if(buildCordova){buildPromise.then(stealCordova.build).then(stealCordova.ios.emulate);}

Then run

npm install ios-sim -g

node build cordova

NW.js

Update your package.json:

"main": "app.html",
...
"window": {"width": 1060,"height": 625,"toolbar": false}

Add to build.js:

varnwOptions={buildDir: "./build",platforms: ["osx"],files: ["package.json","app.html","node_modules/steal/steal.production.js"],version: "0.12.3"};varstealNw=require("steal-nw");// Check if the cordova option is passed.varbuildNW=process.argv.indexOf("nw")>0;if(buildNW){buildPromise=buildPromise.then(function(buildResult){stealNw(nwOptions,buildResult);});}

Add to app.js

import platform from "steal-platform"
if(platform.isCordova || platform.isNW) {
route.defaultBinding = "hashchange";
}

Then run

node build nw

cd build/donejs-chat/osx64

open donejs-chat.app

, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Guide · donejs/chat Wiki · GitHub
Skip to content
Matthew Phillips edited this page Sep 25, 2015 · 43 revisions

Setup

Install donejs

npm install donejs -g

Create a new project

donejs init donejs-chat

Then go into the application folder

cd donejs-chat

Start the donejs server

donejs develop

Add bootstrap and checkout live-reload

Install bootstrap

npm install bootstrap --save

Add it to your page

Change index.stache to:

<html><head><title>{{title}}</title>
{{asset "css"}}
</head><body><can-importfrom="bootstrap/less/bootstrap.less!" /><can-importfrom="donejs-chat/styles.less!" /><can-importfrom="donejs-chat/app" as="viewModel" />
{{asset "inline-cache"}}
{{#switch @env.NODE_ENV}}
{{#case "production"}}
<scriptsrc="http://donejs-chat.divshot.io/node_modules/steal/steal.production.js" main="donejs-chat/index.stache!done-autorender"></script>
{{/case}}
{{#default}}
<scriptsrc="/node_modules/steal/steal.js"></script>
{{/default}}
{{/switch}}
</body></html>

Add some HTML that uses it

<divclass="container"><divclass="row"><divclass="col-sm-8 col-sm-offset-2"><h1>Hello world</h1></div></div></div>

Show live-reload awesomeness

Make some changes and see stuff updates. Talk about how live-reload even works on the server!!!

Setup Basic Routing

Generate Home Component

donejs generate component home.component chat-home

Generate chat-messages component

donejs generate component messages chat-messages

Set up navigation between components.

  1. Add link to chat-home
<can-componenttag="chat-home"><styletype="less">display: block;
h1.page-header { margin-top:0; }
</style><template><can-importfrom="can/view/href/" /><h1class="page-header text-center"><imgsrc="http://donejs.com/static/img/donejs-logo-white.svg" alt="DoneJS logo" /><br>Chat
</h1><acan-href="{ page='chat' }" class="btn btn-primary btn-block btn-lg">Start chat</a></template></can-component>
  1. Add link on chat page (messages/messages.stache)
<can-importfrom="can/view/href/" /><h5><acan-href="{ page='home' }">Home</a></h5><p>{{message}}</p>
  1. Add route in app.js
route('/:page',{page: 'home'});
  1. Load dynamically in index.stache
<divclass="container"><divclass="row"><divclass="col-sm-8 col-sm-offset-2">
{{#eq page 'chat'}}
<can-importfrom="donejs-chat/messages/">
{{#if isPending}}
Loading...
{{else}}
<chat-messages/>
{{/if}}
</can-import>
{{else}}
<can-importfrom="donejs-chat/home.component!">
{{#if isPending}}
Loading...
{{else}}
<chat-home/>
{{/if}}
</can-import>
{{/eq}}
</div></div></div>

Complete the messages page

Generate Message model

donejs generate supermodel message

Set URL to http://donejs-chat.herokuapp.com/api/messages.

Use Message model

In src/messages/messages.stache:

<message-modelget-list="{}"><h5><acan-href="{ page='home' }">Home</a></h5><divclass="list-group">
{{#each ./value}}
<aclass="list-group-item"><h4class="list-group-item-heading">{{name}}</h4><pclass="list-group-item-text">{{message}}</p></a>
{{/each}}
{{^if ./value.length}}
<aclass="list-group-item"><h4class="list-group-item-heading">No messages</h4></a>
{{/if}}
</div></message-model>

alternate:

<can-importfrom="donejs-chat/models/message" /><h5><acan-href="{ page='home' }">Home</a></h5><message-modelget-list="{}" class="list-group">
{{#each ./value}}
<aclass="list-group-item"><h4class="list-group-item-heading">{{name}}</h4><pclass="list-group-item-text">{{message}}</p></a>
{{else}}
<aclass="list-group-item"><h4class="list-group-item-heading">No messages</h4></a>
{{/each}}
</message-model>

Create messages

  1. add html, and (enter) event handler
<divclass="row"><divclass="col-sm-3"><inputtype="text" class="form-control" id="name" placeholder="Your name" can-value="{name}"></div><divclass="col-sm-9"><inputtype="text" class="form-control" id="message" placeholder="Your message" can-value="{message}" (enter)="{send}"></div></div>
  1. import Message model in messages.js
<can-importfrom="donejs-chat/models/message" />
  1. Add send method in src/messages/messages.js
importComponentfrom'can/component/';importMapfrom'can/map/';import'can/map/define/';import'./messages.less!';importtemplatefrom'./messages.stache!';importMessagefrom'../models/message';exportconstViewModel=Map.extend({send(){newMessage({name: this.attr('name'),message: this.attr('message')}).save().then(msg=>this.attr('message',''));}});exportdefaultComponent.extend({tag: 'chat-messages',viewModel: ViewModel,
template
});
  1. Talk about set logic

Make it work real-time

> npm install steal-socket.io --save

Add to src/models/message.js

importiofrom'steal-socket.io';constsocket=io('http://donejs-chat.herokuapp.com');socket.on('messages created',order=>messageConnection.createInstance(order));socket.on('messages updated',order=>messageConnection.updateInstance(order));socket.on('messages removed',order=>messageConnection.destroyInstance(order));

Make homepage

Add tabs

npm install bit-tabs --save

Import:

<can-importfrom="bit-tabs/unstyled" />

Add to page:

<bit-tabstabs-class="nav nav-tabs"><bit-paneltitle="CanJS">
CanJS provides the MV*
</bit-panel><bit-paneltitle="StealJS">
StealJS provides the infrastructure.
</bit-panel></bit-tabs>

Add some styles:

bit-panel {
display: block;
padding:10px;
}

Talk about cool stuff

  1. Server Side Rendering
  2. Fall through caching
  3. Inline caching
  4. Request combining

Show off build locally.

Run build

node build

Set to production.

Close the old server and run

NODE_ENV=production donejs start

Show bundles loading progressively

Show off div-shot

  1. Create Divshot application, install the CLI tool and log in
> npm install -g divshot-cli
> divshot login
  1. Paste config in
"donejs": {"deploy": {"root": "dist","services": {"production": {"type": "divshot","config": {"name": "donejs-chat","headers": {"/**": {"Access-Control-Allow-Origin": "*"}}}}}}},
...
"system": {
...
"envs": {"server-production": {"baseURL": "https://donejs-chat.divshot.io/"}}}
  1. Run node build again.
  2. Run donejs deploy
  3. Add http://donejs-chat.divshot.io to <script src and to envs.server-production.baseURL
  4. Show off

Desktop and mobile apps

First create an app.html file that looks like:

<html><head><title>DoneJS chat</title></head><body><scriptload-bundlesenv="cordova-production" src="node_modules/steal/steal.production.js" main="donejs-chat/index.stache!done-autorender"></script></body></html>

Cordova

Make sure all platform SDKs like XCode (for iOS) and the Android SDK are installed.

Update build.js to:

varstealTools=require("steal-tools");varbuildPromise=stealTools.build({config: __dirname+"/package.json!npm"},{bundleAssets: true});varcordovaOptions={buildDir: "./build/cordova",id: "com.donejs.chat",name: "DoneJS chat",platforms: ["ios"],plugins: ["cordova-plugin-transport-security"],index: __dirname+"/app.html",glob: ["node_modules/steal/steal.production.js"]};varstealCordova=require("steal-cordova")(cordovaOptions);// Check if the cordova option is passed.varbuildCordova=process.argv.indexOf("cordova")>0;if(buildCordova){buildPromise.then(stealCordova.build).then(stealCordova.ios.emulate);}

Then run

npm install ios-sim -g

node build cordova

NW.js

Update your package.json:

"main": "app.html",
...
"window": {"width": 1060,"height": 625,"toolbar": false}

Add to build.js:

varnwOptions={buildDir: "./build",platforms: ["osx"],files: ["package.json","app.html","node_modules/steal/steal.production.js"],version: "0.12.3"};varstealNw=require("steal-nw");// Check if the cordova option is passed.varbuildNW=process.argv.indexOf("nw")>0;if(buildNW){buildPromise=buildPromise.then(function(buildResult){stealNw(nwOptions,buildResult);});}

Add to app.js

import platform from "steal-platform"
if(platform.isCordova || platform.isNW) {
route.defaultBinding = "hashchange";
}

Then run

node build nw

cd build/donejs-chat/osx64

open donejs-chat.app

, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' Guide · donejs/chat Wiki · GitHub
Skip to content
Matthew Phillips edited this page Sep 25, 2015 · 43 revisions

Setup

Install donejs

npm install donejs -g

Create a new project

donejs init donejs-chat

Then go into the application folder

cd donejs-chat

Start the donejs server

donejs develop

Add bootstrap and checkout live-reload

Install bootstrap

npm install bootstrap --save

Add it to your page

Change index.stache to:

<html><head><title>{{title}}</title>
{{asset "css"}}
</head><body><can-importfrom="bootstrap/less/bootstrap.less!" /><can-importfrom="donejs-chat/styles.less!" /><can-importfrom="donejs-chat/app" as="viewModel" />
{{asset "inline-cache"}}
{{#switch @env.NODE_ENV}}
{{#case "production"}}
<scriptsrc="http://donejs-chat.divshot.io/node_modules/steal/steal.production.js" main="donejs-chat/index.stache!done-autorender"></script>
{{/case}}
{{#default}}
<scriptsrc="/node_modules/steal/steal.js"></script>
{{/default}}
{{/switch}}
</body></html>

Add some HTML that uses it

<divclass="container"><divclass="row"><divclass="col-sm-8 col-sm-offset-2"><h1>Hello world</h1></div></div></div>

Show live-reload awesomeness

Make some changes and see stuff updates. Talk about how live-reload even works on the server!!!

Setup Basic Routing

Generate Home Component

donejs generate component home.component chat-home

Generate chat-messages component

donejs generate component messages chat-messages

Set up navigation between components.

  1. Add link to chat-home
<can-componenttag="chat-home"><styletype="less">display: block;
h1.page-header { margin-top:0; }
</style><template><can-importfrom="can/view/href/" /><h1class="page-header text-center"><imgsrc="http://donejs.com/static/img/donejs-logo-white.svg" alt="DoneJS logo" /><br>Chat
</h1><acan-href="{ page='chat' }" class="btn btn-primary btn-block btn-lg">Start chat</a></template></can-component>
  1. Add link on chat page (messages/messages.stache)
<can-importfrom="can/view/href/" /><h5><acan-href="{ page='home' }">Home</a></h5><p>{{message}}</p>
  1. Add route in app.js
route('/:page',{page: 'home'});
  1. Load dynamically in index.stache
<divclass="container"><divclass="row"><divclass="col-sm-8 col-sm-offset-2">
{{#eq page 'chat'}}
<can-importfrom="donejs-chat/messages/">
{{#if isPending}}
Loading...
{{else}}
<chat-messages/>
{{/if}}
</can-import>
{{else}}
<can-importfrom="donejs-chat/home.component!">
{{#if isPending}}
Loading...
{{else}}
<chat-home/>
{{/if}}
</can-import>
{{/eq}}
</div></div></div>

Complete the messages page

Generate Message model

donejs generate supermodel message

Set URL to http://donejs-chat.herokuapp.com/api/messages.

Use Message model

In src/messages/messages.stache:

<message-modelget-list="{}"><h5><acan-href="{ page='home' }">Home</a></h5><divclass="list-group">
{{#each ./value}}
<aclass="list-group-item"><h4class="list-group-item-heading">{{name}}</h4><pclass="list-group-item-text">{{message}}</p></a>
{{/each}}
{{^if ./value.length}}
<aclass="list-group-item"><h4class="list-group-item-heading">No messages</h4></a>
{{/if}}
</div></message-model>

alternate:

<can-importfrom="donejs-chat/models/message" /><h5><acan-href="{ page='home' }">Home</a></h5><message-modelget-list="{}" class="list-group">
{{#each ./value}}
<aclass="list-group-item"><h4class="list-group-item-heading">{{name}}</h4><pclass="list-group-item-text">{{message}}</p></a>
{{else}}
<aclass="list-group-item"><h4class="list-group-item-heading">No messages</h4></a>
{{/each}}
</message-model>

Create messages

  1. add html, and (enter) event handler
<divclass="row"><divclass="col-sm-3"><inputtype="text" class="form-control" id="name" placeholder="Your name" can-value="{name}"></div><divclass="col-sm-9"><inputtype="text" class="form-control" id="message" placeholder="Your message" can-value="{message}" (enter)="{send}"></div></div>
  1. import Message model in messages.js
<can-importfrom="donejs-chat/models/message" />
  1. Add send method in src/messages/messages.js
importComponentfrom'can/component/';importMapfrom'can/map/';import'can/map/define/';import'./messages.less!';importtemplatefrom'./messages.stache!';importMessagefrom'../models/message';exportconstViewModel=Map.extend({send(){newMessage({name: this.attr('name'),message: this.attr('message')}).save().then(msg=>this.attr('message',''));}});exportdefaultComponent.extend({tag: 'chat-messages',viewModel: ViewModel,
template
});
  1. Talk about set logic

Make it work real-time

> npm install steal-socket.io --save

Add to src/models/message.js

importiofrom'steal-socket.io';constsocket=io('http://donejs-chat.herokuapp.com');socket.on('messages created',order=>messageConnection.createInstance(order));socket.on('messages updated',order=>messageConnection.updateInstance(order));socket.on('messages removed',order=>messageConnection.destroyInstance(order));

Make homepage

Add tabs

npm install bit-tabs --save

Import:

<can-importfrom="bit-tabs/unstyled" />

Add to page:

<bit-tabstabs-class="nav nav-tabs"><bit-paneltitle="CanJS">
CanJS provides the MV*
</bit-panel><bit-paneltitle="StealJS">
StealJS provides the infrastructure.
</bit-panel></bit-tabs>

Add some styles:

bit-panel {
display: block;
padding:10px;
}

Talk about cool stuff

  1. Server Side Rendering
  2. Fall through caching
  3. Inline caching
  4. Request combining

Show off build locally.

Run build

node build

Set to production.

Close the old server and run

NODE_ENV=production donejs start

Show bundles loading progressively

Show off div-shot

  1. Create Divshot application, install the CLI tool and log in
> npm install -g divshot-cli
> divshot login
  1. Paste config in
"donejs": {"deploy": {"root": "dist","services": {"production": {"type": "divshot","config": {"name": "donejs-chat","headers": {"/**": {"Access-Control-Allow-Origin": "*"}}}}}}},
...
"system": {
...
"envs": {"server-production": {"baseURL": "https://donejs-chat.divshot.io/"}}}
  1. Run node build again.
  2. Run donejs deploy
  3. Add http://donejs-chat.divshot.io to <script src and to envs.server-production.baseURL
  4. Show off

Desktop and mobile apps

First create an app.html file that looks like:

<html><head><title>DoneJS chat</title></head><body><scriptload-bundlesenv="cordova-production" src="node_modules/steal/steal.production.js" main="donejs-chat/index.stache!done-autorender"></script></body></html>

Cordova

Make sure all platform SDKs like XCode (for iOS) and the Android SDK are installed.

Update build.js to:

varstealTools=require("steal-tools");varbuildPromise=stealTools.build({config: __dirname+"/package.json!npm"},{bundleAssets: true});varcordovaOptions={buildDir: "./build/cordova",id: "com.donejs.chat",name: "DoneJS chat",platforms: ["ios"],plugins: ["cordova-plugin-transport-security"],index: __dirname+"/app.html",glob: ["node_modules/steal/steal.production.js"]};varstealCordova=require("steal-cordova")(cordovaOptions);// Check if the cordova option is passed.varbuildCordova=process.argv.indexOf("cordova")>0;if(buildCordova){buildPromise.then(stealCordova.build).then(stealCordova.ios.emulate);}

Then run

npm install ios-sim -g

node build cordova

NW.js

Update your package.json:

"main": "app.html",
...
"window": {"width": 1060,"height": 625,"toolbar": false}

Add to build.js:

varnwOptions={buildDir: "./build",platforms: ["osx"],files: ["package.json","app.html","node_modules/steal/steal.production.js"],version: "0.12.3"};varstealNw=require("steal-nw");// Check if the cordova option is passed.varbuildNW=process.argv.indexOf("nw")>0;if(buildNW){buildPromise=buildPromise.then(function(buildResult){stealNw(nwOptions,buildResult);});}

Add to app.js

import platform from "steal-platform"
if(platform.isCordova || platform.isNW) {
route.defaultBinding = "hashchange";
}

Then run

node build nw

cd build/donejs-chat/osx64

open donejs-chat.app

, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Guide · donejs/chat Wiki · GitHub
Skip to content
Matthew Phillips edited this page Sep 25, 2015 · 43 revisions

Setup

Install donejs

npm install donejs -g

Create a new project

donejs init donejs-chat

Then go into the application folder

cd donejs-chat

Start the donejs server

donejs develop

Add bootstrap and checkout live-reload

Install bootstrap

npm install bootstrap --save

Add it to your page

Change index.stache to:

<html><head><title>{{title}}</title>
{{asset "css"}}
</head><body><can-importfrom="bootstrap/less/bootstrap.less!" /><can-importfrom="donejs-chat/styles.less!" /><can-importfrom="donejs-chat/app" as="viewModel" />
{{asset "inline-cache"}}
{{#switch @env.NODE_ENV}}
{{#case "production"}}
<scriptsrc="http://donejs-chat.divshot.io/node_modules/steal/steal.production.js" main="donejs-chat/index.stache!done-autorender"></script>
{{/case}}
{{#default}}
<scriptsrc="/node_modules/steal/steal.js"></script>
{{/default}}
{{/switch}}
</body></html>

Add some HTML that uses it

<divclass="container"><divclass="row"><divclass="col-sm-8 col-sm-offset-2"><h1>Hello world</h1></div></div></div>

Show live-reload awesomeness

Make some changes and see stuff updates. Talk about how live-reload even works on the server!!!

Setup Basic Routing

Generate Home Component

donejs generate component home.component chat-home

Generate chat-messages component

donejs generate component messages chat-messages

Set up navigation between components.

  1. Add link to chat-home
<can-componenttag="chat-home"><styletype="less">display: block;
h1.page-header { margin-top:0; }
</style><template><can-importfrom="can/view/href/" /><h1class="page-header text-center"><imgsrc="http://donejs.com/static/img/donejs-logo-white.svg" alt="DoneJS logo" /><br>Chat
</h1><acan-href="{ page='chat' }" class="btn btn-primary btn-block btn-lg">Start chat</a></template></can-component>
  1. Add link on chat page (messages/messages.stache)
<can-importfrom="can/view/href/" /><h5><acan-href="{ page='home' }">Home</a></h5><p>{{message}}</p>
  1. Add route in app.js
route('/:page',{page: 'home'});
  1. Load dynamically in index.stache
<divclass="container"><divclass="row"><divclass="col-sm-8 col-sm-offset-2">
{{#eq page 'chat'}}
<can-importfrom="donejs-chat/messages/">
{{#if isPending}}
Loading...
{{else}}
<chat-messages/>
{{/if}}
</can-import>
{{else}}
<can-importfrom="donejs-chat/home.component!">
{{#if isPending}}
Loading...
{{else}}
<chat-home/>
{{/if}}
</can-import>
{{/eq}}
</div></div></div>

Complete the messages page

Generate Message model

donejs generate supermodel message

Set URL to http://donejs-chat.herokuapp.com/api/messages.

Use Message model

In src/messages/messages.stache:

<message-modelget-list="{}"><h5><acan-href="{ page='home' }">Home</a></h5><divclass="list-group">
{{#each ./value}}
<aclass="list-group-item"><h4class="list-group-item-heading">{{name}}</h4><pclass="list-group-item-text">{{message}}</p></a>
{{/each}}
{{^if ./value.length}}
<aclass="list-group-item"><h4class="list-group-item-heading">No messages</h4></a>
{{/if}}
</div></message-model>

alternate:

<can-importfrom="donejs-chat/models/message" /><h5><acan-href="{ page='home' }">Home</a></h5><message-modelget-list="{}" class="list-group">
{{#each ./value}}
<aclass="list-group-item"><h4class="list-group-item-heading">{{name}}</h4><pclass="list-group-item-text">{{message}}</p></a>
{{else}}
<aclass="list-group-item"><h4class="list-group-item-heading">No messages</h4></a>
{{/each}}
</message-model>

Create messages

  1. add html, and (enter) event handler
<divclass="row"><divclass="col-sm-3"><inputtype="text" class="form-control" id="name" placeholder="Your name" can-value="{name}"></div><divclass="col-sm-9"><inputtype="text" class="form-control" id="message" placeholder="Your message" can-value="{message}" (enter)="{send}"></div></div>
  1. import Message model in messages.js
<can-importfrom="donejs-chat/models/message" />
  1. Add send method in src/messages/messages.js
importComponentfrom'can/component/';importMapfrom'can/map/';import'can/map/define/';import'./messages.less!';importtemplatefrom'./messages.stache!';importMessagefrom'../models/message';exportconstViewModel=Map.extend({send(){newMessage({name: this.attr('name'),message: this.attr('message')}).save().then(msg=>this.attr('message',''));}});exportdefaultComponent.extend({tag: 'chat-messages',viewModel: ViewModel,
template
});
  1. Talk about set logic

Make it work real-time

> npm install steal-socket.io --save

Add to src/models/message.js

importiofrom'steal-socket.io';constsocket=io('http://donejs-chat.herokuapp.com');socket.on('messages created',order=>messageConnection.createInstance(order));socket.on('messages updated',order=>messageConnection.updateInstance(order));socket.on('messages removed',order=>messageConnection.destroyInstance(order));

Make homepage

Add tabs

npm install bit-tabs --save

Import:

<can-importfrom="bit-tabs/unstyled" />

Add to page:

<bit-tabstabs-class="nav nav-tabs"><bit-paneltitle="CanJS">
CanJS provides the MV*
</bit-panel><bit-paneltitle="StealJS">
StealJS provides the infrastructure.
</bit-panel></bit-tabs>

Add some styles:

bit-panel {
display: block;
padding:10px;
}

Talk about cool stuff

  1. Server Side Rendering
  2. Fall through caching
  3. Inline caching
  4. Request combining

Show off build locally.

Run build

node build

Set to production.

Close the old server and run

NODE_ENV=production donejs start

Show bundles loading progressively

Show off div-shot

  1. Create Divshot application, install the CLI tool and log in
> npm install -g divshot-cli
> divshot login
  1. Paste config in
"donejs": {"deploy": {"root": "dist","services": {"production": {"type": "divshot","config": {"name": "donejs-chat","headers": {"/**": {"Access-Control-Allow-Origin": "*"}}}}}}},
...
"system": {
...
"envs": {"server-production": {"baseURL": "https://donejs-chat.divshot.io/"}}}
  1. Run node build again.
  2. Run donejs deploy
  3. Add http://donejs-chat.divshot.io to <script src and to envs.server-production.baseURL
  4. Show off

Desktop and mobile apps

First create an app.html file that looks like:

<html><head><title>DoneJS chat</title></head><body><scriptload-bundlesenv="cordova-production" src="node_modules/steal/steal.production.js" main="donejs-chat/index.stache!done-autorender"></script></body></html>

Cordova

Make sure all platform SDKs like XCode (for iOS) and the Android SDK are installed.

Update build.js to:

varstealTools=require("steal-tools");varbuildPromise=stealTools.build({config: __dirname+"/package.json!npm"},{bundleAssets: true});varcordovaOptions={buildDir: "./build/cordova",id: "com.donejs.chat",name: "DoneJS chat",platforms: ["ios"],plugins: ["cordova-plugin-transport-security"],index: __dirname+"/app.html",glob: ["node_modules/steal/steal.production.js"]};varstealCordova=require("steal-cordova")(cordovaOptions);// Check if the cordova option is passed.varbuildCordova=process.argv.indexOf("cordova")>0;if(buildCordova){buildPromise.then(stealCordova.build).then(stealCordova.ios.emulate);}

Then run

npm install ios-sim -g

node build cordova

NW.js

Update your package.json:

"main": "app.html",
...
"window": {"width": 1060,"height": 625,"toolbar": false}

Add to build.js:

varnwOptions={buildDir: "./build",platforms: ["osx"],files: ["package.json","app.html","node_modules/steal/steal.production.js"],version: "0.12.3"};varstealNw=require("steal-nw");// Check if the cordova option is passed.varbuildNW=process.argv.indexOf("nw")>0;if(buildNW){buildPromise=buildPromise.then(function(buildResult){stealNw(nwOptions,buildResult);});}

Add to app.js

import platform from "steal-platform"
if(platform.isCordova || platform.isNW) {
route.defaultBinding = "hashchange";
}

Then run

node build nw

cd build/donejs-chat/osx64

open donejs-chat.app

, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Guide · donejs/chat Wiki · GitHub
Skip to content
Matthew Phillips edited this page Sep 25, 2015 · 43 revisions

Setup

Install donejs

npm install donejs -g

Create a new project

donejs init donejs-chat

Then go into the application folder

cd donejs-chat

Start the donejs server

donejs develop

Add bootstrap and checkout live-reload

Install bootstrap

npm install bootstrap --save

Add it to your page

Change index.stache to:

<html><head><title>{{title}}</title>
{{asset "css"}}
</head><body><can-importfrom="bootstrap/less/bootstrap.less!" /><can-importfrom="donejs-chat/styles.less!" /><can-importfrom="donejs-chat/app" as="viewModel" />
{{asset "inline-cache"}}
{{#switch @env.NODE_ENV}}
{{#case "production"}}
<scriptsrc="http://donejs-chat.divshot.io/node_modules/steal/steal.production.js" main="donejs-chat/index.stache!done-autorender"></script>
{{/case}}
{{#default}}
<scriptsrc="/node_modules/steal/steal.js"></script>
{{/default}}
{{/switch}}
</body></html>

Add some HTML that uses it

<divclass="container"><divclass="row"><divclass="col-sm-8 col-sm-offset-2"><h1>Hello world</h1></div></div></div>

Show live-reload awesomeness

Make some changes and see stuff updates. Talk about how live-reload even works on the server!!!

Setup Basic Routing

Generate Home Component

donejs generate component home.component chat-home

Generate chat-messages component

donejs generate component messages chat-messages

Set up navigation between components.

  1. Add link to chat-home
<can-componenttag="chat-home"><styletype="less">display: block;
h1.page-header { margin-top:0; }
</style><template><can-importfrom="can/view/href/" /><h1class="page-header text-center"><imgsrc="http://donejs.com/static/img/donejs-logo-white.svg" alt="DoneJS logo" /><br>Chat
</h1><acan-href="{ page='chat' }" class="btn btn-primary btn-block btn-lg">Start chat</a></template></can-component>
  1. Add link on chat page (messages/messages.stache)
<can-importfrom="can/view/href/" /><h5><acan-href="{ page='home' }">Home</a></h5><p>{{message}}</p>
  1. Add route in app.js
route('/:page',{page: 'home'});
  1. Load dynamically in index.stache
<divclass="container"><divclass="row"><divclass="col-sm-8 col-sm-offset-2">
{{#eq page 'chat'}}
<can-importfrom="donejs-chat/messages/">
{{#if isPending}}
Loading...
{{else}}
<chat-messages/>
{{/if}}
</can-import>
{{else}}
<can-importfrom="donejs-chat/home.component!">
{{#if isPending}}
Loading...
{{else}}
<chat-home/>
{{/if}}
</can-import>
{{/eq}}
</div></div></div>

Complete the messages page

Generate Message model

donejs generate supermodel message

Set URL to http://donejs-chat.herokuapp.com/api/messages.

Use Message model

In src/messages/messages.stache:

<message-modelget-list="{}"><h5><acan-href="{ page='home' }">Home</a></h5><divclass="list-group">
{{#each ./value}}
<aclass="list-group-item"><h4class="list-group-item-heading">{{name}}</h4><pclass="list-group-item-text">{{message}}</p></a>
{{/each}}
{{^if ./value.length}}
<aclass="list-group-item"><h4class="list-group-item-heading">No messages</h4></a>
{{/if}}
</div></message-model>

alternate:

<can-importfrom="donejs-chat/models/message" /><h5><acan-href="{ page='home' }">Home</a></h5><message-modelget-list="{}" class="list-group">
{{#each ./value}}
<aclass="list-group-item"><h4class="list-group-item-heading">{{name}}</h4><pclass="list-group-item-text">{{message}}</p></a>
{{else}}
<aclass="list-group-item"><h4class="list-group-item-heading">No messages</h4></a>
{{/each}}
</message-model>

Create messages

  1. add html, and (enter) event handler
<divclass="row"><divclass="col-sm-3"><inputtype="text" class="form-control" id="name" placeholder="Your name" can-value="{name}"></div><divclass="col-sm-9"><inputtype="text" class="form-control" id="message" placeholder="Your message" can-value="{message}" (enter)="{send}"></div></div>
  1. import Message model in messages.js
<can-importfrom="donejs-chat/models/message" />
  1. Add send method in src/messages/messages.js
importComponentfrom'can/component/';importMapfrom'can/map/';import'can/map/define/';import'./messages.less!';importtemplatefrom'./messages.stache!';importMessagefrom'../models/message';exportconstViewModel=Map.extend({send(){newMessage({name: this.attr('name'),message: this.attr('message')}).save().then(msg=>this.attr('message',''));}});exportdefaultComponent.extend({tag: 'chat-messages',viewModel: ViewModel,
template
});
  1. Talk about set logic

Make it work real-time

> npm install steal-socket.io --save

Add to src/models/message.js

importiofrom'steal-socket.io';constsocket=io('http://donejs-chat.herokuapp.com');socket.on('messages created',order=>messageConnection.createInstance(order));socket.on('messages updated',order=>messageConnection.updateInstance(order));socket.on('messages removed',order=>messageConnection.destroyInstance(order));

Make homepage

Add tabs

npm install bit-tabs --save

Import:

<can-importfrom="bit-tabs/unstyled" />

Add to page:

<bit-tabstabs-class="nav nav-tabs"><bit-paneltitle="CanJS">
CanJS provides the MV*
</bit-panel><bit-paneltitle="StealJS">
StealJS provides the infrastructure.
</bit-panel></bit-tabs>

Add some styles:

bit-panel {
display: block;
padding:10px;
}

Talk about cool stuff

  1. Server Side Rendering
  2. Fall through caching
  3. Inline caching
  4. Request combining

Show off build locally.

Run build

node build

Set to production.

Close the old server and run

NODE_ENV=production donejs start

Show bundles loading progressively

Show off div-shot

  1. Create Divshot application, install the CLI tool and log in
> npm install -g divshot-cli
> divshot login
  1. Paste config in
"donejs": {"deploy": {"root": "dist","services": {"production": {"type": "divshot","config": {"name": "donejs-chat","headers": {"/**": {"Access-Control-Allow-Origin": "*"}}}}}}},
...
"system": {
...
"envs": {"server-production": {"baseURL": "https://donejs-chat.divshot.io/"}}}
  1. Run node build again.
  2. Run donejs deploy
  3. Add http://donejs-chat.divshot.io to <script src and to envs.server-production.baseURL
  4. Show off

Desktop and mobile apps

First create an app.html file that looks like:

<html><head><title>DoneJS chat</title></head><body><scriptload-bundlesenv="cordova-production" src="node_modules/steal/steal.production.js" main="donejs-chat/index.stache!done-autorender"></script></body></html>

Cordova

Make sure all platform SDKs like XCode (for iOS) and the Android SDK are installed.

Update build.js to:

varstealTools=require("steal-tools");varbuildPromise=stealTools.build({config: __dirname+"/package.json!npm"},{bundleAssets: true});varcordovaOptions={buildDir: "./build/cordova",id: "com.donejs.chat",name: "DoneJS chat",platforms: ["ios"],plugins: ["cordova-plugin-transport-security"],index: __dirname+"/app.html",glob: ["node_modules/steal/steal.production.js"]};varstealCordova=require("steal-cordova")(cordovaOptions);// Check if the cordova option is passed.varbuildCordova=process.argv.indexOf("cordova")>0;if(buildCordova){buildPromise.then(stealCordova.build).then(stealCordova.ios.emulate);}

Then run

npm install ios-sim -g

node build cordova

NW.js

Update your package.json:

"main": "app.html",
...
"window": {"width": 1060,"height": 625,"toolbar": false}

Add to build.js:

varnwOptions={buildDir: "./build",platforms: ["osx"],files: ["package.json","app.html","node_modules/steal/steal.production.js"],version: "0.12.3"};varstealNw=require("steal-nw");// Check if the cordova option is passed.varbuildNW=process.argv.indexOf("nw")>0;if(buildNW){buildPromise=buildPromise.then(function(buildResult){stealNw(nwOptions,buildResult);});}

Add to app.js

import platform from "steal-platform"
if(platform.isCordova || platform.isNW) {
route.defaultBinding = "hashchange";
}

Then run

node build nw

cd build/donejs-chat/osx64

open donejs-chat.app

, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })(); Guide · donejs/chat Wiki · GitHub
Skip to content
Matthew Phillips edited this page Sep 25, 2015 · 43 revisions

Setup

Install donejs

npm install donejs -g

Create a new project

donejs init donejs-chat

Then go into the application folder

cd donejs-chat

Start the donejs server

donejs develop

Add bootstrap and checkout live-reload

Install bootstrap

npm install bootstrap --save

Add it to your page

Change index.stache to:

<html><head><title>{{title}}</title>
{{asset "css"}}
</head><body><can-importfrom="bootstrap/less/bootstrap.less!" /><can-importfrom="donejs-chat/styles.less!" /><can-importfrom="donejs-chat/app" as="viewModel" />
{{asset "inline-cache"}}
{{#switch @env.NODE_ENV}}
{{#case "production"}}
<scriptsrc="http://donejs-chat.divshot.io/node_modules/steal/steal.production.js" main="donejs-chat/index.stache!done-autorender"></script>
{{/case}}
{{#default}}
<scriptsrc="/node_modules/steal/steal.js"></script>
{{/default}}
{{/switch}}
</body></html>

Add some HTML that uses it

<divclass="container"><divclass="row"><divclass="col-sm-8 col-sm-offset-2"><h1>Hello world</h1></div></div></div>

Show live-reload awesomeness

Make some changes and see stuff updates. Talk about how live-reload even works on the server!!!

Setup Basic Routing

Generate Home Component

donejs generate component home.component chat-home

Generate chat-messages component

donejs generate component messages chat-messages

Set up navigation between components.

  1. Add link to chat-home
<can-componenttag="chat-home"><styletype="less">display: block;
h1.page-header { margin-top:0; }
</style><template><can-importfrom="can/view/href/" /><h1class="page-header text-center"><imgsrc="http://donejs.com/static/img/donejs-logo-white.svg" alt="DoneJS logo" /><br>Chat
</h1><acan-href="{ page='chat' }" class="btn btn-primary btn-block btn-lg">Start chat</a></template></can-component>
  1. Add link on chat page (messages/messages.stache)
<can-importfrom="can/view/href/" /><h5><acan-href="{ page='home' }">Home</a></h5><p>{{message}}</p>
  1. Add route in app.js
route('/:page',{page: 'home'});
  1. Load dynamically in index.stache
<divclass="container"><divclass="row"><divclass="col-sm-8 col-sm-offset-2">
{{#eq page 'chat'}}
<can-importfrom="donejs-chat/messages/">
{{#if isPending}}
Loading...
{{else}}
<chat-messages/>
{{/if}}
</can-import>
{{else}}
<can-importfrom="donejs-chat/home.component!">
{{#if isPending}}
Loading...
{{else}}
<chat-home/>
{{/if}}
</can-import>
{{/eq}}
</div></div></div>

Complete the messages page

Generate Message model

donejs generate supermodel message

Set URL to http://donejs-chat.herokuapp.com/api/messages.

Use Message model

In src/messages/messages.stache:

<message-modelget-list="{}"><h5><acan-href="{ page='home' }">Home</a></h5><divclass="list-group">
{{#each ./value}}
<aclass="list-group-item"><h4class="list-group-item-heading">{{name}}</h4><pclass="list-group-item-text">{{message}}</p></a>
{{/each}}
{{^if ./value.length}}
<aclass="list-group-item"><h4class="list-group-item-heading">No messages</h4></a>
{{/if}}
</div></message-model>

alternate:

<can-importfrom="donejs-chat/models/message" /><h5><acan-href="{ page='home' }">Home</a></h5><message-modelget-list="{}" class="list-group">
{{#each ./value}}
<aclass="list-group-item"><h4class="list-group-item-heading">{{name}}</h4><pclass="list-group-item-text">{{message}}</p></a>
{{else}}
<aclass="list-group-item"><h4class="list-group-item-heading">No messages</h4></a>
{{/each}}
</message-model>

Create messages

  1. add html, and (enter) event handler
<divclass="row"><divclass="col-sm-3"><inputtype="text" class="form-control" id="name" placeholder="Your name" can-value="{name}"></div><divclass="col-sm-9"><inputtype="text" class="form-control" id="message" placeholder="Your message" can-value="{message}" (enter)="{send}"></div></div>
  1. import Message model in messages.js
<can-importfrom="donejs-chat/models/message" />
  1. Add send method in src/messages/messages.js
importComponentfrom'can/component/';importMapfrom'can/map/';import'can/map/define/';import'./messages.less!';importtemplatefrom'./messages.stache!';importMessagefrom'../models/message';exportconstViewModel=Map.extend({send(){newMessage({name: this.attr('name'),message: this.attr('message')}).save().then(msg=>this.attr('message',''));}});exportdefaultComponent.extend({tag: 'chat-messages',viewModel: ViewModel,
template
});
  1. Talk about set logic

Make it work real-time

> npm install steal-socket.io --save

Add to src/models/message.js

importiofrom'steal-socket.io';constsocket=io('http://donejs-chat.herokuapp.com');socket.on('messages created',order=>messageConnection.createInstance(order));socket.on('messages updated',order=>messageConnection.updateInstance(order));socket.on('messages removed',order=>messageConnection.destroyInstance(order));

Make homepage

Add tabs

npm install bit-tabs --save

Import:

<can-importfrom="bit-tabs/unstyled" />

Add to page:

<bit-tabstabs-class="nav nav-tabs"><bit-paneltitle="CanJS">
CanJS provides the MV*
</bit-panel><bit-paneltitle="StealJS">
StealJS provides the infrastructure.
</bit-panel></bit-tabs>

Add some styles:

bit-panel {
display: block;
padding:10px;
}

Talk about cool stuff

  1. Server Side Rendering
  2. Fall through caching
  3. Inline caching
  4. Request combining

Show off build locally.

Run build

node build

Set to production.

Close the old server and run

NODE_ENV=production donejs start

Show bundles loading progressively

Show off div-shot

  1. Create Divshot application, install the CLI tool and log in
> npm install -g divshot-cli
> divshot login
  1. Paste config in
"donejs": {"deploy": {"root": "dist","services": {"production": {"type": "divshot","config": {"name": "donejs-chat","headers": {"/**": {"Access-Control-Allow-Origin": "*"}}}}}}},
...
"system": {
...
"envs": {"server-production": {"baseURL": "https://donejs-chat.divshot.io/"}}}
  1. Run node build again.
  2. Run donejs deploy
  3. Add http://donejs-chat.divshot.io to <script src and to envs.server-production.baseURL
  4. Show off

Desktop and mobile apps

First create an app.html file that looks like:

<html><head><title>DoneJS chat</title></head><body><scriptload-bundlesenv="cordova-production" src="node_modules/steal/steal.production.js" main="donejs-chat/index.stache!done-autorender"></script></body></html>

Cordova

Make sure all platform SDKs like XCode (for iOS) and the Android SDK are installed.

Update build.js to:

varstealTools=require("steal-tools");varbuildPromise=stealTools.build({config: __dirname+"/package.json!npm"},{bundleAssets: true});varcordovaOptions={buildDir: "./build/cordova",id: "com.donejs.chat",name: "DoneJS chat",platforms: ["ios"],plugins: ["cordova-plugin-transport-security"],index: __dirname+"/app.html",glob: ["node_modules/steal/steal.production.js"]};varstealCordova=require("steal-cordova")(cordovaOptions);// Check if the cordova option is passed.varbuildCordova=process.argv.indexOf("cordova")>0;if(buildCordova){buildPromise.then(stealCordova.build).then(stealCordova.ios.emulate);}

Then run

npm install ios-sim -g

node build cordova

NW.js

Update your package.json:

"main": "app.html",
...
"window": {"width": 1060,"height": 625,"toolbar": false}

Add to build.js:

varnwOptions={buildDir: "./build",platforms: ["osx"],files: ["package.json","app.html","node_modules/steal/steal.production.js"],version: "0.12.3"};varstealNw=require("steal-nw");// Check if the cordova option is passed.varbuildNW=process.argv.indexOf("nw")>0;if(buildNW){buildPromise=buildPromise.then(function(buildResult){stealNw(nwOptions,buildResult);});}

Add to app.js

import platform from "steal-platform"
if(platform.isCordova || platform.isNW) {
route.defaultBinding = "hashchange";
}

Then run

node build nw

cd build/donejs-chat/osx64

open donejs-chat.app