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;
   ...