Commit e8cfeae5 authored by Pascal Hartig's avatar Pascal Hartig

Remove emberjs-require example, redirect to README

Close #528
parent 41ef0d4a
/* Mocha */
#mocha h1, h2 {
margin: 0;
}
#mocha h1 {
font-size: 1em;
font-weight: 200;
}
#mocha .suite .suite h1 {
font-size: .8em;
}
#mocha h2 {
font-size: 12px;
font-weight: normal;
cursor: pointer;
}
#mocha .suite {
margin-left: 15px;
}
#mocha .test {
margin-left: 15px;
}
#mocha .test:hover h2::after {
position: relative;
top: 0;
right: -10px;
content: '(view source)';
font-size: 12px;
font-family: arial;
color: #888;
}
#mocha .test.pending:hover h2::after {
content: '(pending)';
font-family: arial;
}
#mocha .test.pass::before {
content: '✓';
font-size: 12px;
display: block;
float: left;
margin-right: 5px;
color: #00c41c;
}
#mocha .test.pending {
color: #0b97c4;
}
#mocha .test.pending::before {
content: '◦';
color: #0b97c4;
}
#mocha .test.fail {
color: #c00;
}
#mocha .test.fail pre {
color: black;
}
#mocha .test.fail::before {
content: '✖';
font-size: 12px;
display: block;
float: left;
margin-right: 5px;
color: #c00;
}
#mocha .test pre.error {
color: #c00;
}
#mocha .test pre {
display: inline-block;
font: 12px/1.5 monaco, monospace;
margin: 5px;
padding: 15px;
border: 1px solid #eee;
border-bottom-color: #ddd;
-webkit-border-radius: 3px;
-webkit-box-shadow: 0 1px 3px #eee;
}
#error {
color: #c00;
font-size: 1.5 em;
font-weight: 100;
letter-spacing: 1px;
}
#stats {
position: fixed;
top: 15px;
right: 10px;
font-size: 12px;
margin: 0;
color: #888;
}
#stats .progress {
float: right;
padding-top: 0;
}
#stats em {
color: black;
}
#stats li {
display: inline-block;
margin: 0 5px;
list-style: none;
padding-top: 11px;
}
code .comment { color: #ddd }
code .init { color: #2F6FAD }
code .string { color: #5890AD }
code .keyword { color: #8A6343 }
code .number { color: #2F6FAD }
<!doctype html> <!doctype html>
<html lang="en"> <title>ember.js + require.js • TodoMVC</title>
<head> <meta http-equiv="refresh" content="0;URL=README.md">
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>ember.js + require.js • TodoMVC</title>
<link rel="stylesheet" href="../../assets/base.css">
<link rel="stylesheet" href="../../assets/jasmine/jasmine.css">
<link rel="stylesheet" href="css/app.css">
<!--[if IE]>
<script src="../../assets/ie.js"></script>
<![endif]-->
</head>
<body>
<section id="todoapp"></section>
<footer id="info">
<p>Double-click to edit a todo</p>
<p>
Created by
<a href="http://github.com/tomdale">Tom Dale</a>,
<a href="http://github.com/stas">Стас Сушков</a>
</p>
<p>Part of <a href="http://todomvc.com">TodoMVC</a></p>
</footer>
<script src="../../assets/base.js"></script>
<script data-main="js/app.js" src="js/lib/require/require.js"></script>
</body>
</html>
// Define libraries
require.config({
baseUrl: 'js/',
paths: {
jquery: '../../../assets/jquery.min',
ember: 'lib/ember-latest.min',
handlebars: '../../../assets/handlebars.min',
text: 'lib/require/text',
jasmine: '../../../assets/jasmine/jasmine',
jasmine_html: '../../../assets/jasmine/jasmine-html'
}
});
// Load our app
define( 'app', [
'app/router',
'app/models/store',
'app/controllers/entries',
'app/views/application',
'jquery',
'handlebars',
'ember'
], function( Router, Store, EntriesController, ApplicationView ) {
var App = Ember.Application.create({
VERSION: '1.0',
rootElement: '#todoapp',
// Load routes
Router: Router,
// Extend to inherit outlet support
ApplicationController: Ember.Controller.extend(),
ApplicationView: ApplicationView,
entriesController: EntriesController.create({
store: new Store('todos-emberjs')
}),
ready: function() {
this.initialize();
}
});
// Expose the application globally
return window.Todos = App;
}
);
define('app/controllers/entries', [ 'ember' ],
/**
* Entries controller
*
* @returns Class
*/
function() {
return Ember.ArrayProxy.extend({
store: null,
content: [],
createNew: function( value ) {
if ( !value.trim() )
return;
var todo = this.get( 'store' ).createFromTitle( value );
this.pushObject( todo );
},
pushObject: function( item, ignoreStorage) {
if ( !ignoreStorage )
this.get( 'store' ).create( item );
return this._super( item );
},
removeObject: function( item ) {
this.get( 'store' ).remove( item );
return this._super( item );
},
clearCompleted: function() {
this.filterProperty(
'completed', true
).forEach( this.removeObject, this );
},
total: function() {
return this.get( 'length' );
}.property( '@each.length' ),
remaining: function() {
return this.filterProperty( 'completed', false ).get( 'length' );
}.property( '@each.completed' ),
completed: function() {
return this.filterProperty( 'completed', true ).get( 'length' );
}.property( '@each.completed' ),
noneLeft: function() {
return this.get( 'total' ) === 0;
}.property( 'total' ),
allAreDone: function( key, value ) {
if ( value !== undefined ) {
this.setEach( 'completed', value );
return value;
} else {
return !!this.get( 'length' ) &&
this.everyProperty( 'completed', true );
}
}.property( '@each.completed' ),
init: function() {
this._super();
// Load items if any upon initialization
var items = this.get( 'store' ).findAll();
if ( items.get( 'length' ) ) {
this.set( '[]', items );
};
}
});
}
);
define('app/controllers/todos', [ 'ember' ],
/**
* Todos controller
*
* @returns Class
*/
function() {
return Ember.Controller.extend({
entries: function() {
var filter = this.getPath( 'content.filterBy' );
if ( Ember.empty( filter ) ) {
return this.get( 'content' );
}
if ( !Ember.compare( filter, 'completed' ) ) {
return this.get( 'content' ).filterProperty( 'completed', true );
}
if ( !Ember.compare( filter, 'active' ) ) {
return this.get( 'content' ).filterProperty( 'completed', false );
}
}.property( 'content.remaining' )
});
}
);
define('app/models/store', [
'app/models/todo',
'ember'
],
/**
* Todo entries storage model
*
* @param Class Todo, the todo entry model
* @returns Class
*/
function( Todo ) {
// Our Store is represented by a single JS object in *localStorage*.
// Create it with a meaningful name, like the name you'd give a table.
return function( name ) {
this.name = name;
var store = localStorage.getItem( this.name );
this.data = ( store && JSON.parse( store ) ) || {};
// Save the current state of the **Store** to *localStorage*.
this.save = function() {
localStorage.setItem( this.name, JSON.stringify( this.data ) );
};
// Wrapper around `this.create`
// Creates a `Todo` model object out of the title
this.createFromTitle = function( title ) {
var todo = Todo.create({
title: title,
store: this
});
this.create( todo );
return todo;
};
// Store the model inside the `Store`
this.create = function ( model ) {
if ( !model.get( 'id' ) )
model.set( 'id', Date.now() );
return this.update( model );
};
// Update a model by replacing its copy in `this.data`.
this.update = function( model ) {
this.data[ model.get( 'id' ) ] = model.getProperties(
'id', 'title', 'completed'
);
this.save();
return model;
};
// Retrieve a model from `this.data` by id.
this.find = function( model ) {
var todo = Todo.create( this.data[ model.get( 'id' ) ] );
todo.set( 'store', this );
return todo;
};
// Return the array of all models currently in storage.
this.findAll = function() {
var result = [],
key;
for ( key in this.data ) {
var todo = Todo.create( this.data[ key ] );
todo.set( 'store', this );
result.push( todo );
}
return result;
};
// Delete a model from `this.data`, returning it.
this.remove = function( model ) {
delete this.data[ model.get( 'id' ) ];
this.save();
return model;
};
};
}
);
define('app/models/todo', ['ember'],
/**
* Todo entry model
*
* @returns Class
*/
function() {
return Ember.Object.extend({
id: null,
title: null,
completed: false,
// set store reference upon creation instead of creating static bindings
store: null,
// Observer that will react on item change and will update the storage
todoChanged: function() {
this.get( 'store' ).update( this );
}.observes( 'title', 'completed' )
});
}
);
define('app/router', [ 'ember' ],
/**
* Todos Router
*
* Defined routes represent filters according to specs
*
* @returns Class
*/
function() {
return Ember.Router.extend({
root: Ember.Route.extend({
showAll: Ember.Route.transitionTo( 'index' ),
showActive: Ember.Route.transitionTo( 'active' ),
showCompleted: Ember.Route.transitionTo( 'completed' ),
index: Ember.Route.extend({
route: '/',
connectOutlets: function( router ) {
var controller = router.get( 'applicationController' );
var context = controller.namespace.entriesController;
context.set( 'filterBy', '' );
// This require was left here exclusively for design purposes
// Loads decoupled controller/view based on current route
require([ 'app/controllers/todos', 'app/views/items' ],
function( TodosController, ItemsView ) {
controller.connectOutlet({
viewClass: ItemsView,
controller: TodosController.create(),
context: context
});
}
);
}
}),
active: Ember.Route.extend({
route: '/active',
connectOutlets: function( router ) {
var controller = router.get( 'applicationController' );
var context = controller.namespace.entriesController;
context.set( 'filterBy', 'active' );
// This require was left here exclusively for design purposes
// Loads decoupled controller/view based on current route
require([ 'app/controllers/todos', 'app/views/items' ],
function( TodosController, ItemsView ) {
controller.connectOutlet({
viewClass: ItemsView,
controller: TodosController.create(),
context: context
});
}
);
}
}),
completed: Ember.Route.extend({
route: '/completed',
connectOutlets: function( router ) {
var controller = router.get( 'applicationController' );
var context = controller.namespace.entriesController;
context.set( 'filterBy', 'completed' );
// This require was left here exclusively for design purposes
// Loads decoupled controller/view based on current route
require([ 'app/controllers/todos', 'app/views/items' ],
function( TodosController, ItemsView ) {
controller.connectOutlet({
viewClass: ItemsView,
controller: TodosController.create(),
context: context
});
}
);
}
}),
specs: Ember.Route.extend({
route: '/specs',
connectOutlets: function() {
require( [ 'app/specs/helper' ] );
}
})
})
});
}
);
/**
* Some smoke tests
*/
describe( 'controllers/todos', function() {
var controller = Todos.get( 'todosController' );
var title = 'Another title...';
it( 'should have an input for entering new entry', function() {
expect( controller.inputView ).to.be.a( 'object' );
expect(
$( controller.inputView.get( 'element' ) ).attr( 'placeholder' )
).to.equal( controller.inputView.get( 'placeholder' ) );
});
it( 'should not create new entry on empty-ish input', function() {
var counted = controller.get( 'remaining' );
controller.inputView.set( 'value', ' ' );
controller.inputView.insertNewline();
expect( controller.get( 'remaining' ) ).to.equal( counted )
});
it( 'should create new entry on newline', function() {
controller.inputView.set( 'value', title );
controller.inputView.insertNewline();
expect( controller.get( 'lastObject' ).title ).to.equal( title );
controller.removeObject( controller.get( 'lastObject' ) );
});
it( 'should delete item if title is empty-ish', function() {
controller.createNew( title );
var counted = controller.get( 'remaining' );
var entry = controller.get( 'lastObject' );
entry.set( 'title', ' ' );
var editor = controller.todoEditor.create({
todo: entry,
storage: controller
});
editor.whenDone();
expect( controller.get( 'remaining' ) ).to.equal( counted - 1 );
});
it( 'should reflect the same number of items as in store', function() {
controller.createNew( 'value', title );
var visibles = controller.todosView.
get( 'childViews' )[ 0 ].get( 'childViews' ).length;
expect( controller.get( 'content' ).length ).to.equal( visibles );
controller.removeObject( controller.get( 'lastObject' ) );
});
it( 'should allow removing entries', function( done ) {
controller.createNew( 'value', title );
setTimeout( function(){
controller.allDoneCheckbox.set( 'value', true );
}, 100 );
setTimeout( function(){
controller.clearCompletedButton.triggerAction();
}, 200 );
setTimeout( function(){
expect( controller.get( 'content' ).length ).to.equal( 0 );
}, 300 );
done();
});
});
define( 'app/specs/helper', [ 'jasmine', 'jasmine_html' ],
/**
* Specs Runner
*/
function() {
// Load testsuite
require([
'app/specs/todoMVC',
], function() {
var jasmineEnv = jasmine.getEnv();
var htmlReporter = new jasmine.HtmlReporter();
jasmineEnv.addReporter( htmlReporter );
jasmineEnv.execute();
});
}
);
/**
* Some integration tests
*/
describe( 'models/store', function() {
var title = 'Testing title...';
var store = Todos.todosController.get( 'store' );
it( 'should allow creating and removing items', function() {
var count = store.findAll().length;
var todo = store.createFromTitle( title );
expect( store.findAll().length ).to.equal( count + 1 );
expect( todo ).to.have.property( 'title', title );
expect( todo ).to.have.property( 'completed', false );
expect( todo ).to.have.property( 'store', store );
store.remove( todo );
expect( store.findAll().length ).to.equal( count );
});
it( 'should allow finding and changing items', function() {
var todo = store.createFromTitle( title );
expect( store.find( todo ).id ).to.equal( todo.id );
expect( store.find( todo ).title ).to.equal( todo.title );
expect( store.find( todo ).completed ).to.equal( false );
todo.set( 'completed', true );
expect( store.find( todo ).id ).to.equal( todo.id );
expect( store.find( todo ).completed ).to.equal( true );
store.remove( todo );
});
});
/**
* TodoMVC Project Specs
*
* Use `runs` and `waits` to make sure results are run synchroneously
*/
describe( 'TodoMVC features.', function(){
var enterEvent = $.Event('keyup', { keyCode: 13 });
var todoTitle = 'Foo Bar Todo';
describe( 'Todo creation:', function() {
beforeEach( function(){
// Make sure we are always on the main screen
window.location.hash = '#/';
});
it( 'should allow creating a new todo' , function() {
runs( function(){
$( '#new-todo' ).val( todoTitle ).trigger( enterEvent );
});
waits( 100 );
runs( function() {
!!$( '#todo-list li' ).text().match( todoTitle );
});
});
it( 'should not allow adding an empty todo' , function() {
var ourTodo,
beforeCount = $( '#todo-list li' ).length;
runs( function(){
$( '#new-todo' ).val( ' ' ).trigger( enterEvent );
});
waits( 100 );
runs( function(){
expect( $( '#todo-list li' ).length ).toEqual( beforeCount );
});
});
});
describe( 'Todo completion:', function() {
it( 'should allow marking a todo complete' , function() {
var ourTodo,
beforeCount = $( '#todo-list li.completed' ).length,
postTitle = ' to be completed';
runs( function(){
$( '#new-todo' ).val( todoTitle + postTitle ).trigger( enterEvent );
});
waits( 100 );
runs( function() {
ourTodo = $( '#todo-list li:last-child' );
expect( ourTodo.text() ).toMatch( postTitle );
ourTodo.find( '.toggle' ).click();
expect( $( '#todo-list li.completed' ).length ).toEqual( beforeCount + 1 );
});
});
it( 'should allow clearing completed todos' , function() {
var ourTodo,
beforeCount = $( '#todo-list li.completed' ).length,
postTitle = ' to be completed';
runs( function(){
$( '#new-todo' ).val( todoTitle + postTitle ).trigger( enterEvent );
});
waits( 100 );
runs( function() {
ourTodo = $( '#todo-list li:last-child' );
expect( ourTodo.text() ).toMatch( postTitle );
ourTodo.find( '.toggle' ).click();
$( '#clear-completed' ).click();
expect( $( '#todo-list li.completed' ).length ).toEqual( 0 );
});
});
});
describe( 'Todo deletion:', function() {
it( 'should allow deleting a todo' , function() {
var ourTodo,
beforeCount = $( '#todo-list li' ).length,
postTitle = ' to be deleted';
runs( function(){
$( '#new-todo' ).val( todoTitle + postTitle ).trigger( enterEvent );
});
waits( 100 );
runs( function() {
ourTodo = $( '#todo-list li:last-child' );
expect( ourTodo.text() ).toMatch( postTitle );
ourTodo.find( '.destroy' ).click();
expect( $( '#todo-list li' ).length ).toEqual( beforeCount );
});
});
});
});
/**
* Some acceptance testing for views
*/
describe( 'views/*', function() {
it( 'should validate clear button view', function( done ) {
require( [ 'text!app/views/clear_button.html' ], function( html ){
expect( html ).to.be.a( 'string' );
expect( html ).to.match( /completedCount/ );
expect( function(){ Em.Handlebars.compile( html ) } ).to.not.throw( Error );
done();
});
});
it( 'should validate items view', function( done ) {
require( [ 'text!app/views/items.html' ], function( html ) {
expect( html ).to.be.a( 'string' );
expect( html ).to.match( /collection/ );
expect( html ).to.match( /id="todo-list"/ );
expect( html ).to.match( /Todos\.todosController/ );
expect( html ).to.match( /Checkbox/ );
expect( html ).to.match( /class="toggle"/ );
expect( function(){ Em.Handlebars.compile( html ) } ).to.not.throw( Error );
done();
});
});
});
{{#with view}}
<button id="clear-completed" {{action "clearCompleted" target="entries"}} >
Clear completed ({{entries.completed}})
</button>
{{/with}}
<ul id="filters">
<li>
<a {{action showAll href=true}} {{bindAttr class="view.isAll:selected"}}>All</a>
</li>
<li>
<a {{action showActive href=true}} {{bindAttr class="view.isActive:selected"}}>Active</a>
</li>
<li>
<a {{action showCompleted href=true}} {{bindAttr class="view.isCompleted:selected"}}>Completed</a>
</li>
</ul>
{{#unless view.content.editing}}
{{view Ember.Checkbox checkedBinding="view.content.completed" class="toggle"}}
<label>{{view.content.title}}</label>
<button {{action removeItem}} class="destroy" ></button>
{{else}}
{{view view.ItemEditorView contentBinding="view.content"}}
{{/unless}}
{{#with view}}
{{#if oneLeft }}
<strong>{{entries.remaining}}</strong> item left
{{else}}
<strong>{{entries.remaining}}</strong> items left
{{/if}}
{{/with}}
define('app/views/application', [
'app/views/stats',
'app/views/filters',
'app/views/clear_button',
'ember'
],
/**
* Main application view
*
* @param Class StatsView, stats view class
* @param Class FiltersView, filters view class
* @param Class ClearBtnView, clear button view class
* @returns Class
*/
function( StatsView, FiltersView, ClearBtnView ) {
return Ember.ContainerView.extend({
childViews: [ 'headerView', 'mainView', 'footerView' ],
headerView: Ember.ContainerView.create({
childViews: [ 'titleView', 'createTodoView' ],
elementId: 'header',
tagName: 'header',
titleView: Ember.View.create({
tagName: 'h1',
template: function() {
return 'todos';
}
}),
createTodoView: Ember.TextField.create({
entriesBinding: 'controller.namespace.entriesController',
placeholder: 'What needs to be done?',
elementId: 'new-todo',
insertNewline: function() {
var value = this.get( 'value' );
if ( value ) {
this.get( 'entries' ).createNew( value );
this.set( 'value', '' );
}
}
}),
}),
mainView: Em.ContainerView.create({
elementId: 'main',
tagName: 'section',
visibilityBinding: 'controller.namespace.entriesController.noneLeft',
classNameBindings: [ 'visibility:hidden' ],
childViews: [ 'outletView', 'markAllChkbox' ],
outletView: Ember.View.create({
template: Ember.Handlebars.compile( '{{outlet}}' ),
}),
markAllChkbox: Ember.Checkbox.create({
entriesBinding: 'controller.namespace.entriesController',
elementId: 'toggle-all',
checkedBinding: 'entries.allAreDone'
})
}),
footerView: Ember.ContainerView.create({
elementId: 'footer',
tagName: 'footer',
visibilityBinding: 'controller.namespace.entriesController.noneLeft',
classNameBindings: [ 'visibility:hidden' ],
childViews: [
StatsView.create(),
FiltersView.create(),
ClearBtnView.create()
]
})
})
}
);
define('app/views/clear_button', [
'text!app/templates/clear_button.html',
'ember'
],
/**
* View to clear completed tasks
*
* @param String button_html, the html for view
* @returns Class
*/
function( button_html ) {
return Ember.View.extend({
entriesBinding: 'controller.namespace.entriesController',
template: Ember.Handlebars.compile( button_html ),
classNameBindings: 'buttonClass',
buttonClass: function () {
if ( !this.getPath( 'entries.completed' ) )
return 'hidden';
}.property( 'entries.completed' )
})
}
);
define('app/views/filters', [
'text!app/templates/filters.html',
'ember'
],
/**
* View to render filter links
*
* @param String filters_html, filter links html view
* @returns Class
*/
function( filters_html ) {
return Ember.View.extend({
template: Ember.Handlebars.compile( filters_html ),
filterBinding: 'controller.namespace.entriesController.filterBy',
isAll: function() {
return Ember.empty( this.get('filter') );
}.property( 'filter' ),
isActive: function() {
return this.get('filter') === 'active';
}.property('filter'),
isCompleted: function() {
return this.get('filter') === 'completed';
}.property('filter')
});
}
);
define('app/views/items', [
'text!app/templates/items.html',
'ember'
],
/**
* View to render todos items
*
* @param String items_html, the html view for the `Todos` items
* @returns Class
*/
function( items_html ) {
return Ember.CollectionView.extend({
contentBinding: 'controller.entries',
tagName: 'ul',
elementId: 'todo-list',
itemViewClass: Ember.View.extend({
template: Ember.Handlebars.compile( items_html ),
classNames: [ 'view' ],
classNameBindings: ['content.completed', 'content.editing'],
doubleClick: function() {
this.get( 'content' ).set( 'editing', true );
},
removeItem: function() {
this.getPath( 'controller.content' ).removeObject( this.get( 'content' ) );
},
ItemEditorView: Ember.TextField.extend({
valueBinding: 'content.title',
classNames: [ 'edit' ],
change: function() {
if ( Ember.empty( this.getPath( 'content.title' ) ) ) {
this.getPath( 'controller.content' ).removeObject( this.get( 'content' ) );
}
},
whenDone: function() {
this.get( 'content' ).set( 'editing', false );
},
focusOut: function() {
this.whenDone();
},
didInsertElement: function() {
this.$().focus();
},
insertNewline: function() {
this.whenDone();
}
})
})
})
}
);
define('app/views/stats', [
'text!app/templates/stats.html',
'ember'
],
/**
* View to render todos stats
*
* @param String stats_html, stats indicator view
* @returns Class
*/
function( stats_html ) {
return Ember.View.extend({
entriesBinding: 'controller.namespace.entriesController',
elementId: 'todo-count',
tagName: 'span',
template: Ember.Handlebars.compile( stats_html ),
oneLeft: function() {
return this.getPath( 'entries.remaining' ) === 1;
}.property( 'entries.remaining' )
})
}
);
This source diff could not be displayed because it is too large. You can view the blob instead.
/*
RequireJS text 0.27.0 Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.
Available via the MIT or new BSD license.
see: http://github.com/jrburke/requirejs for details
*/
(function(){var k=["Msxml2.XMLHTTP","Microsoft.XMLHTTP","Msxml2.XMLHTTP.4.0"],n=/^\s*<\?xml(\s)+version=[\'\"](\d)*.(\d)*[\'\"](\s)*\?>/im,o=/<body[^>]*>\s*([\s\S]+)\s*<\/body>/im,i=typeof location!=="undefined"&&location.href,p=i&&location.protocol&&location.protocol.replace(/\:/,""),q=i&&location.hostname,r=i&&(location.port||void 0),j=[];define(function(){var g,h,l;typeof window!=="undefined"&&window.navigator&&window.document?h=function(a,b){var c=g.createXhr();c.open("GET",a,!0);c.onreadystatechange=
function(){c.readyState===4&&b(c.responseText)};c.send(null)}:typeof process!=="undefined"&&process.versions&&process.versions.node?(l=require.nodeRequire("fs"),h=function(a,b){b(l.readFileSync(a,"utf8"))}):typeof Packages!=="undefined"&&(h=function(a,b){var c=new java.io.File(a),e=java.lang.System.getProperty("line.separator"),c=new java.io.BufferedReader(new java.io.InputStreamReader(new java.io.FileInputStream(c),"utf-8")),d,f,g="";try{d=new java.lang.StringBuffer;(f=c.readLine())&&f.length()&&
f.charAt(0)===65279&&(f=f.substring(1));for(d.append(f);(f=c.readLine())!==null;)d.append(e),d.append(f);g=String(d.toString())}finally{c.close()}b(g)});return g={version:"0.27.0",strip:function(a){if(a){var a=a.replace(n,""),b=a.match(o);b&&(a=b[1])}else a="";return a},jsEscape:function(a){return a.replace(/(['\\])/g,"\\$1").replace(/[\f]/g,"\\f").replace(/[\b]/g,"\\b").replace(/[\n]/g,"\\n").replace(/[\t]/g,"\\t").replace(/[\r]/g,"\\r")},createXhr:function(){var a,b,c;if(typeof XMLHttpRequest!==
"undefined")return new XMLHttpRequest;else for(b=0;b<3;b++){c=k[b];try{a=new ActiveXObject(c)}catch(e){}if(a){k=[c];break}}if(!a)throw Error("createXhr(): XMLHttpRequest not available");return a},get:h,parseName:function(a){var b=!1,c=a.indexOf("."),e=a.substring(0,c),a=a.substring(c+1,a.length),c=a.indexOf("!");c!==-1&&(b=a.substring(c+1,a.length),b=b==="strip",a=a.substring(0,c));return{moduleName:e,ext:a,strip:b}},xdRegExp:/^((\w+)\:)?\/\/([^\/\\]+)/,useXhr:function(a,b,c,e){var d=g.xdRegExp.exec(a),
f;if(!d)return!0;a=d[2];d=d[3];d=d.split(":");f=d[1];d=d[0];return(!a||a===b)&&(!d||d===c)&&(!f&&!d||f===e)},finishLoad:function(a,b,c,e,d){c=b?g.strip(c):c;d.isBuild&&d.inlineText&&(j[a]=c);e(c)},load:function(a,b,c,e){var d=g.parseName(a),f=d.moduleName+"."+d.ext,m=b.toUrl(f),h=e&&e.text&&e.text.useXhr||g.useXhr;!i||h(m,p,q,r)?g.get(m,function(b){g.finishLoad(a,d.strip,b,c,e)}):b([f],function(a){g.finishLoad(d.moduleName+"."+d.ext,d.strip,a,c,e)})},write:function(a,b,c){if(b in j){var e=g.jsEscape(j[b]);
c.asModule(a+"!"+b,"define(function () { return '"+e+"';});\n")}},writeFile:function(a,b,c,e,d){var b=g.parseName(b),f=b.moduleName+"."+b.ext,h=c.toUrl(b.moduleName+"."+b.ext)+".js";g.load(f,c,function(){var b=function(a){return e(h,a)};b.asModule=function(a,b){return e.asModule(a,h,b)};g.write(a,f,b,d)},d)}}})})();
# Ember.js + Require.js • [TodoMVC](http://todomvc.com) # Ember.js + Require.js • [TodoMVC](http://todomvc.com)
This example was removed, because the Ember.js dependency injection architecture
does not provide appropriate hooks for asynchronous module loading yet and thus
the use of Require.js with Ember.js is not advised.
## Running tests For more information, [read the discussion](https://github.com/addyosmani/todomvc/pull/528).
To fire specs runner, append `#specs` to the url in address bar, and reload the webpage.
## Credit
Initial release by @tomdale.
Refactoring and maintenance by @stas.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment