Ember 0.9.8.1 Template
by justinbrown
HTML
<script src="https://github.com/downloads/emberjs/ember.js/ember-latest.js"></script>
<script type="text/x-handlebars" data-template-name="theme">
<div>[{{content.occurances.length}}] {{content.text}}</div>
{{#if view.isExpanded}}
<div class="occurances">
{{#each content.occurances}}
{{#if hasPhrases}}
<ul>
{{#each phrases}}
<li>{{string}}</li>
{{/each}}
</ul>
{{/if}}
{{/each}}
</div>
{{/if}}
</script>
<script type="text/x-handlebars" data-template-name="document">
<div class="themes">
<h3>Themes</h3>
Primary:
{{collection contentBinding="view.orderedPrimaryThemes" itemViewClass="App.ThemeView"}}
{{#if view.viewingSecondary}}
Secondary:
{{collection contentBinding="content.secondaryThemes" itemViewClass="App.ThemeView"}}
<a href="#" {{action "toggleSecondary"}}>hide secondary</a>
{{else}}
<a href="#" {{action "toggleSecondary"}}>view {{content.secondaryThemes.length}} more</a>
{{/if}}
</div>
<div class="text">
<h2>Document</h2>
{{#each content.parts}}
{{#view App.PartView partBinding="this"}}
{{part.text}}
{{/view}}
{{/each}}
</div>
</script>
<script type="text/x-handlebars">
{{view Ember.TextArea valueBinding="App.text"}}
<button {{action "add" target="App"}}>Add</button>
<p>Found {{App.documentsController.commonThemes.length}} common themes between {{App.documentsController.length}} documents</p>
<ol>
{{#each App.documentsController.commonThemes}}
<li>{{this}}</li>
{{/each}}
</ol>
{{collection contentBinding="App.documents" itemViewClass="App.DocumentView"}}
</script>
SCSS
body { padding: 1em; }
h2 { font-size: 1.5em; }
h3 { font-size: 1.2em; }
textarea {
display: block;
height: 100px;
width: 100%;
}
.document {
margin: 1em 0;
clear: both;
.themes {
border: 1px solid;
border-bottom-left-radius: 5px;
border-top-left-radius: 5px;
float: left;
padding: 1em;
width: 30%;
}
.text {
border: 1px solid;
border-radius: 5px;
float: left;
padding: 1em;
width: 50%;
}
}
.theme {
cursor: pointer;
margin: 0.3em;
padding: 0.3em;
.occurances {
margin: 0.5em;
}
&.is-expanded {
background-color: #dedede;
border: 1px solid;
}
}
.is-term {
color: blue;
padding: 0;
&:hover {
background-color: blue;
color: white;
}
}
.is-common-word {
color: gray;
}
.highlighted {
color: red;
}
JavaScript
App = Ember.Application.create({
documents: Ember.A([]),
addDocument: function(text) {
this.get('documents').pushObject(App.Document.create({ text: text }));
},
add: function() {
this.addDocument(this.get('text'));
this.set('text', '');
}
});
App.DocumentsController = Ember.ArrayController.extend({
commonThemes: function() {
var themes = [], documents = this.get('content');
// We can only find common themes if we have at least 2 documents.
if(documents.get('length') > 1) {
var getIntersect = function(arr1, arr2) {
var r = [], o = {}, l = arr2.length, i, v;
for (i = 0; i < l; i++) {
o[arr2[i]] = true;
}
l = arr1.length;
for (i = 0; i < l; i++) {
v = arr1[i];
if (v in o) {
r.push(v);
}
}
console.log(r);
return r;
}
var first = documents.slice().shiftObject().get('themes').getEach('text');
themes = documents.reduce(function(previousValue, item, index, enumerable) {
return getIntersect(previousValue, item.get('themes').getEach('text'));
}, first);
}
return themes;
}.property('[email protected][email protected]')
});
App.documentsController = App.DocumentsController.create({
contentBinding: 'App.documents'
});
App.Document = Ember.Object.extend({
parts: function() {
// Create a linked list so parts can traverse forwards to discover phrases.
var previous = null;
return this.get("text").split(/([^\s,\.]+)/).map(function(item, index, self) {
var part = App.Part.create({ text: item });
if(previous) { previous.set('nextPart', part); }
previous = part;
return part;
...