Skip to content

Commit

Permalink
Publish new website with redesign
Browse files Browse the repository at this point in the history
  • Loading branch information
Tom Dale committed Jan 24, 2012
0 parents commit e10866d
Show file tree
Hide file tree
Showing 51 changed files with 32,956 additions and 0 deletions.
1 change: 1 addition & 0 deletions docs/application
@@ -0,0 +1 @@
<html><body><h1>File Not Found</h1><p>/docs/application/index.html</p></body>
38 changes: 38 additions & 0 deletions docs/documentation.not-md
@@ -0,0 +1,38 @@
# Ember.js Guide

## Understanding MVC Architecture
1. What is MVC?
2. The Model Layer
3. The View Layer
4. The Controller Layer
5. Augmenting Controllers with Storyboards

9. Mixins
10. Arrays and Enumerables
11. Understanding the Run Loop
5. Describing Your UI with Handlebars
1. What is Handlebars?
2. Displaying Templates
3. Handlebars In-Depth
4. Ember.View
5. The View Rendering Pipeline
6. Form Helpers
6. Handling User Events
1. Implementing Handlers on Views
2. Event Bubbling
3. Registering Custom Events
4. Customizing Ember.Application
7. Testing
1. What is unit testing?
2. What is integration testing?
3. Using Jasmine
4. Mocking Events and Remote Services
5. Run Loop Considerations
8. Getting Data into Your App
1. Content TBD
9. Managing Assets and Deploying to Production
1. Multiple Files and Dependency Resolution
2. Concatenation
3. Minification
4. Deploying Static Assets: Best Practices
5. Profiling for Performance
1 change: 1 addition & 0 deletions docs/enumerables
@@ -0,0 +1 @@
<html><body><h1>File Not Found</h1><p>/docs/enumerables/index.html</p></body>
1 change: 1 addition & 0 deletions docs/handlebars
@@ -0,0 +1 @@
<html><body><h1>File Not Found</h1><p>/docs/handlebars/index.html</p></body>
1 change: 1 addition & 0 deletions docs/introduction
@@ -0,0 +1 @@
<html><body><h1>File Not Found</h1><p>/docs/introduction/index.html</p></body>
1 change: 1 addition & 0 deletions docs/object_model
@@ -0,0 +1 @@
<html><body><h1>File Not Found</h1><p>/docs/object_model/index.html</p></body>
1 change: 1 addition & 0 deletions docs/views
@@ -0,0 +1 @@
<html><body><h1>File Not Found</h1><p>/docs/views/index.html</p></body>
1,498 changes: 1,498 additions & 0 deletions documentation/index.html

Large diffs are not rendered by default.

189 changes: 189 additions & 0 deletions examples/contacts/app.js
@@ -0,0 +1,189 @@
App = SC.Application.create();

/*
Model
*/

App.Contact = SC.Object.extend({
firstName: '',
lastName: '',

hasName: function() {
var firstName = this.get('firstName'),
lastName = this.get('lastName');

return firstName !== '' || lastName !== '';
}.property('firstName', 'lastName')
});

/*
Controllers
*/

App.contactsController = SC.ArrayController.create({
// The array of Contact objects that backs the array controller.
content: [],

// The content array, sorted by first name, or last
// name if no first name is provided.
sortedContacts: function() {
var content = this.get('content');

return content.slice().sort(function(a, b) {
var firstNameA = a.get('firstName'),
firstNameB = b.get('firstName');

if (!firstNameA) {
firstNameA = a.get('lastName');
}

if (!firstNameB) {
firstNameB = b.get('lastName');
}

if (!firstNameA && firstNameB) { return 1; }
if (!firstNameB && firstNameA) { return -1; }
if (firstNameA < firstNameB) { return -1; }
if (firstNameA > firstNameB) { return 1; }
return 0;
});

// Every time a contact's first name or last name changes,
// recompute the order. Since this is a somewhat expensive
// operation, the cacheable() flag means that the computed
// value will be automatically memoized.
}.property('@each.firstName', '@each.lastName').cacheable(),

// Creates a new, empty Contact object and adds it to the
// array controller.
newContact: function() {
this.pushObject(App.Contact.create({
phoneNumbers: []
}));
},

loadContacts: function() {
var self = this;
$.ajax({
url: '/contacts.json',
dataType: 'json',
success: function(data) {
var contacts = data.contacts;

// Turn JSON objects into bindable Ember
// objects.
contacts = contacts.map(function(item) {
return self.createContactFromJSON(item);
});

self.set('content', contacts);
},

error: function() {
self.pushObject(self.createContactFromJSON({
firstName: 'Peter',
lastName: 'Wagenet',
phoneNumbers: ['(415) 555-2381']
}));

self.set('isFromFixtures', true);
}
});
},

createContactFromJSON: function(json) {
json.phoneNumbers = json.phoneNumbers.map(function(number) {
return { number: number };
});

return App.Contact.create(json);
}
});

App.contactsController.loadContacts();

App.selectedContactController = SC.Object.create({
content: null
});

App.DeleteNumberView = SC.View.extend({
classNames: ['delete-number-view'],
click: function() {
var phoneNumber = this.get('content');
var contact = this.getPath('contentView.content');

contact.get('phoneNumbers').removeObject(phoneNumber);
}
});

App.EditField = SC.View.extend({
tagName: 'span',
templateName: 'edit-field',

doubleClick: function() {
this.set('isEditing', true);
return false;
},

focusOut: function() {
this.set('isEditing', false);
},

keyUp: function(evt) {
if (evt.keyCode === 13) {
this.set('isEditing', false);
}
}
});

App.TextField = SC.TextField.extend({
didInsertElement: function() {
this.$().focus();
}
});

SC.Handlebars.registerHelper('editable', function(path, options) {
options.hash.valueBinding = path;
return SC.Handlebars.helpers.view.call(this, App.EditField, options);
});

SC.Handlebars.registerHelper('button', function(options) {
var hash = options.hash;

if (!hash.target) {
hash.target = "App.contactsController";
}
return SC.Handlebars.helpers.view.call(this, SC.Button, options);
});

App.ContactListView = SC.View.extend({
classNameBindings: ['isSelected'],

click: function() {
var content = this.get('content');

App.selectedContactController.set('content', content);
},

isSelected: function() {
var selectedItem = App.selectedContactController.get('content'),
content = this.get('content');

if (content === selectedItem) { return true; }
}.property('App.selectedContactController.content')
});

App.CardView = SC.View.extend({
contentBinding: 'App.selectedContactController.content',
classNames: ['card'],

addPhoneNumber: function() {
var phoneNumbers = this.getPath('content.phoneNumbers');
phoneNumbers.pushObject({ number: '' });
}
});

Binary file added examples/contacts/images/broken_noise.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added examples/contacts/images/delete.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added examples/contacts/images/ricepaper2.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
73 changes: 73 additions & 0 deletions examples/contacts/index.html
@@ -0,0 +1,73 @@
<!DOCTYPE html>
<html>
<head>
<title>Ember.js Contacts</title>
<link rel="stylesheet" href="style.css" type="text/css" media="screen" charset="utf-8">
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.js"></script>
<script type="text/javascript" src="../lib/ember.min.js"></script>
<script type="text/javascript" src="app.js"></script>
</head>
<body>
<div id="container">
<div id="contact-list">
<script type="text/x-handlebars">
<h2>My Contacts</h2>
<ul>
{{#each App.contactsController.sortedContacts}}
{{#view App.ContactListView contentBinding="this"}}
{{#with content}}
<li>
{{#if hasName}}
<b>{{firstName}}</b> {{#if firstName}}{{lastName}}{{else}}<b>{{lastName}}</b>{{/if}}
{{else}}
<span class="no-name">no name</span>
{{/if}}
{{/with}}
{{/view}}
{{/each}}
</ul>
{{#button action="newContact"}}New Contact{{/button}}
</script>
</div>

<div id="detail">
<script type="text/x-handlebars">
{{#if App.selectedContactController.content}}
{{#view App.CardView}}
<div class="name">
{{editable "content.firstName"}} {{editable "content.lastName"}}
</div>

<table class="phone-numbers">
{{#each content.phoneNumbers}}
<tr>
<td>{{editable number}}</td>
<td>{{view App.DeleteNumberView contentBinding="this"}}</td>
</tr>
{{/each}}
</table>
{{#view SC.Button target="contentView" action="addPhoneNumber"}}
Add Phone Number
{{/view}}
{{/view}}
{{else}}
<div class="no-contact-selected">No contact selected.</div>
{{/if}}

</script>
</div>

<script type="text/x-handlebars" data-template-name="edit-field">
{{#if isEditing}}
{{view App.TextField valueBinding="value" propagatesEvents=true}}
{{else}}
{{#if value}}
{{value}}
{{else}}
<span class="no-name">empty</span>
{{/if}}
{{/if}}
</script>
</body>
</html>

67 changes: 67 additions & 0 deletions examples/contacts/server.js
@@ -0,0 +1,67 @@
var express = require('express'),
connect = require('connect');

var app = express.createServer(
connect.logger(),
connect.static(__dirname),
connect.static('..')
);

var guid = 0;

var contacts = [
{
guid: ++guid,
firstName: 'Peter',
lastName: 'Wagenet',
phoneNumbers: ['(415) 555-2380']
},

{
guid: ++guid,
firstName: 'Yehuda',
lastName: 'Katz',
phoneNumbers: ['(415) 555-6666']
},

{
guid: ++guid,
firstName: 'Erik',
lastName: 'Bryn',
phoneNumbers: ['(415) 555-2380', '(614) 555-8127']
},

{
guid: ++guid,
firstName: 'James',
lastName: 'Rosen',
phoneNumbers: ['(415) 555-2380']
},

{
guid: ++guid,
firstName: 'Kara',
lastName: 'Gates',
phoneNumbers: ['(207) 555-3141']
},

{
guid: ++guid,
firstName: 'Dudley',
lastName: 'Flanders',
phoneNumbers: ['(415) 555-6789']
},

{
guid: ++guid,
firstName: 'Tom',
lastName: 'Dale',
phoneNumbers: ['(808) 800-8135']
}
];

app.get('/contacts.json', function(req, res) {
res.send({contacts: contacts});
});

app.listen(3000);

0 comments on commit e10866d

Please sign in to comment.