Skip to content

Instantly share code, notes, and snippets.

@jamiely
Created September 19, 2011 12:46
Show Gist options
  • Select an option

  • Save jamiely/1226428 to your computer and use it in GitHub Desktop.

Select an option

Save jamiely/1226428 to your computer and use it in GitHub Desktop.
Diff of final changes for intermap
--- a/css/global.css
+++ b/css/global.css
@@ -300,6 +300,10 @@ ul#menu-main-menu li a {
#matrix #interactionMatrixParent {
padding-top: 10px;
}
+ #matrix #interactionMatrixParent h2 .button {
+ font-size: x-small;
+ float: right;
+ }
#matrixContainer {
padding-top: 200px; /* this needs to match {.terms .term} width so that the top terms have enough room */
@@ -682,7 +686,7 @@ is pending or invalid, etc.
}
#reorder div.projectsList ul {
margin: 20px;
- max-width: 400px;
+ max-width: 600px;
}
#reorder li.term {
font-size: x-large;
@@ -737,20 +741,23 @@ is pending or invalid, etc.
padding: 3px;
border: 1px #CCC solid;
}
-#instructions ul {
- font-size: small;
- list-style: disc;
- margin-left: 10px;
+#instructions {
+ display: none;
}
- #instructions > ul > ul {
- margin-top: 10px;
- font-weight: bold;
+ #instructions ul {
+ font-size: small;
+ list-style: disc;
+ margin-left: 10px;
}
- #instructions > ul > ul > li {
- font-weight: normal;
- margin-left: 20px;
- padding: 3px;
+ #instructions > ul > ul {
+ margin-top: 10px;
+ font-weight: bold;
}
+ #instructions > ul > ul > li {
+ font-weight: normal;
+ margin-left: 20px;
+ padding: 3px;
+ }
#bottom > div:nth-child(2) {
text-align: right;
@@ -774,4 +781,8 @@ is pending or invalid, etc.
}
#register fieldset a {
font-size: medium;
- }
\ No newline at end of file
+ }
+
+#linkDeleteActiveTerm {
+ display: none;
+}
\ No newline at end of file
diff --git a/index.dev.html b/index.dev.html
index 417d961..00e21c9 100644
--- a/index.dev.html
+++ b/index.dev.html
@@ -290,7 +290,12 @@
</script>
<div id="interactionMatrixParent">
- <h2>Interaction Matrix</h2>
+ <!-- Add new term handled by IntermapApplicationView -->
+ <h2>
+ Interaction Matrix
+ <a href="javascript:" id="linkDeleteActiveTerm" class="deleteTerm button" title="Either click this button to delete the active term or press the DELETE key.">Delete Term</a>
+ <a href="javascript:" class="addTerm button" title="Either click this button to add a new term or press ENTER in the last term input box.">Add New Term</a>
+ </h2>
<div id="interactionMatrix">
<div class="preview">
@@ -301,7 +306,7 @@
<div id="topTermsContainer">
<div class="terms" id="topTerms">
<script class="template" id="tmplTopTerm" type="text/x-jquery-tmpl">
- &nbsp;<span class="text">${text}</span>
+ &nbsp;<span class="text">${$item.getTerm()}</span>
<span class="tagText" style="color: ${$item.getTagForegroundColor()}; background-color: ${$item.getTagBackgroundColor()}">${$item.getTag()}</span>
</script>
</div>
@@ -405,6 +410,7 @@
<li>Term centrality may be toggled by clicking the <img src="img/star_whartonblue_16x16.png" alt="star" title="Denotes term centrality"> icon.</li>
<li>Terms may be tagged by clicking on the box labeled <em>click to tag</em> and entering a tag.</li>
<li>Please avoid creating duplicate terms.</li>
+ <li>Terms may be deleted by pressing the DELETE key inside a term input box.</li>
</ul>
<ul>
Interactions
diff --git a/index.prod.html b/index.prod.html
index a38be14..205a672 100644
--- a/index.prod.html
+++ b/index.prod.html
@@ -288,7 +288,12 @@
</script>
<div id="interactionMatrixParent">
- <h2>Interaction Matrix</h2>
+ <!-- Add new term handled by IntermapApplicationView -->
+ <h2>
+ Interaction Matrix
+ <a href="javascript:" id="linkDeleteActiveTerm" class="deleteTerm button" title="Either click this button to delete the active term or press the DELETE key.">Delete Term</a>
+ <a href="javascript:" class="addTerm button" title="Either click this button to add a new term or press ENTER in the last term input box.">Add New Term</a>
+ </h2>
<div id="interactionMatrix">
<div class="preview">
@@ -299,7 +304,7 @@
<div id="topTermsContainer">
<div class="terms" id="topTerms">
<script class="template" id="tmplTopTerm" type="text/x-jquery-tmpl">
- &nbsp;<span class="text">${text}</span>
+ &nbsp;<span class="text">${$item.getTerm()}</span>
<span class="tagText" style="color: ${$item.getTagForegroundColor()}; background-color: ${$item.getTagBackgroundColor()}">${$item.getTag()}</span>
</script>
</div>
@@ -403,6 +408,7 @@
<li>Term centrality may be toggled by clicking the <img src="img/star_whartonblue_16x16.png" alt="star" title="Denotes term centrality"> icon.</li>
<li>Terms may be tagged by clicking on the box labeled <em>click to tag</em> and entering a tag.</li>
<li>Please avoid creating duplicate terms.</li>
+ <li>Terms may be deleted by pressing the DELETE key inside a term input box.</li>
</ul>
<ul>
Interactions
diff --git a/index.template.html b/index.template.html
index b1fb391..86b9f96 100755
--- a/index.template.html
+++ b/index.template.html
@@ -287,7 +287,12 @@
</script>
<div id="interactionMatrixParent">
- <h2>Interaction Matrix</h2>
+ <!-- Add new term handled by IntermapApplicationView -->
+ <h2>
+ Interaction Matrix
+ <a href="javascript:" id="linkDeleteActiveTerm" class="deleteTerm button" title="Either click this button to delete the active term or press the DELETE key.">Delete Term</a>
+ <a href="javascript:" class="addTerm button" title="Either click this button to add a new term or press ENTER in the last term input box.">Add New Term</a>
+ </h2>
<div id="interactionMatrix">
<div class="preview">
@@ -298,7 +303,7 @@
<div id="topTermsContainer">
<div class="terms" id="topTerms">
<script class="template" id="tmplTopTerm" type="text/x-jquery-tmpl">
- &nbsp;<span class="text">${text}</span>
+ &nbsp;<span class="text">${$item.getTerm()}</span>
<span class="tagText" style="color: ${$item.getTagForegroundColor()}; background-color: ${$item.getTagBackgroundColor()}">${$item.getTag()}</span>
</script>
</div>
@@ -402,6 +407,7 @@
<li>Term centrality may be toggled by clicking the <img src="img/star_whartonblue_16x16.png" alt="star" title="Denotes term centrality"> icon.</li>
<li>Terms may be tagged by clicking on the box labeled <em>click to tag</em> and entering a tag.</li>
<li>Please avoid creating duplicate terms.</li>
+ <li>Terms may be deleted by pressing the DELETE key inside a term input box.</li>
</ul>
<ul>
Interactions
diff --git a/js/intermap/IntermapRouter.js b/js/intermap/IntermapRouter.js
index 78948d3..0ed5a3d 100644
--- a/js/intermap/IntermapRouter.js
+++ b/js/intermap/IntermapRouter.js
@@ -14,6 +14,8 @@ Intermap.Router = Backbone.Router.extend({
'register': 'register',
'help': 'help' // #help
},
+ // Tracks whether the entire list of projects has ever been loaded
+ _projectsHaveBeenLoaded: false,
_currentProject: 0,
_currentScreen: null,
_newProjectIndex: 1,
@@ -94,13 +96,22 @@ Intermap.Router = Backbone.Router.extend({
* Loads the project with the passed id. Both cid and regular id may be used.
*/
_loadProject: function(id){
- var self = this;
+ var self = this,
+ projects = Intermap.App.get('projects');
try {
- if(this._currentProject != id) {
+ var exists = projects.get(id);
+
+ if(this._currentProject != id && exists) {
Intermap.App.changeProject(id);
this._currentProject = id;
}
+ else if (! exists) {
+ this._loadProjects(function(collection, response) {
+ Intermap.View.getProjectListView().renderProjectsSubmenu();
+ self._loadProject(id);
+ }, {preventScreen: true});
+ }
else {
this._showScreen('#matrix');
}
@@ -113,14 +124,7 @@ Intermap.Router = Backbone.Router.extend({
}
catch(e) { // project doesn't exist most likely. forward to list of projects
- if(Intermap.App.get('projects').length == 0) {
- this._loadProjects(function(collection, response) {
- self._loadProject(id);
- });
- }
- else {
- this.navigate('projects', true);
- }
+ this.navigate('projects', true);
}
},
projects: function(id) {
@@ -154,7 +158,8 @@ Intermap.Router = Backbone.Router.extend({
jQuery('.matrixLink').attr('href', '#projects/' + projectId);
},
- _loadProjects: function(callback) {
+ _loadProjects: function(callback, options) {
+ options = options || {};
this._currentProject = null;
callback = callback || function(){};
@@ -162,7 +167,8 @@ Intermap.Router = Backbone.Router.extend({
var self = this,
result = Intermap.App.get('projects').fetch({
success: function(collection, response) {
- self._showScreen('#projects');
+ if(! options.preventScreen)
+ self._showScreen('#projects');
callback(collection, response);
},
error: function(collection, response) {
diff --git a/js/intermap/models/IntermapApplication.js b/js/intermap/models/IntermapApplication.js
index aa77b00..42a7deb 100755
--- a/js/intermap/models/IntermapApplication.js
+++ b/js/intermap/models/IntermapApplication.js
@@ -70,6 +70,26 @@ Intermap.Application = Backbone.Model.extend({
self.trigger('error', newTerm, 'Term is blank or already exists.');
return null;
},
+
+ /**
+ * Retrieves a term of the active project matching the passed text.
+ */
+ getTermByText: function(text) {
+ var terms = this.get('project').get('terms').getByText(text);
+ return _(terms).first();
+ },
+
+ /**
+ * Deletes the term of the active project corresponding to the passed text
+ */
+ deleteTermFromText: function(text, options) {
+ if(! text) return;
+
+ var term = this.getTermByText(text);
+
+ if(term) term.destroy(options);
+ },
+
/**
* This will create a new interaction, and call the passed callback with the
* newly created interaction model.
diff --git a/js/intermap/views/InteractionMatrixView.js b/js/intermap/views/InteractionMatrixView.js
index 4426537..aeb4bd8 100644
--- a/js/intermap/views/InteractionMatrixView.js
+++ b/js/intermap/views/InteractionMatrixView.js
@@ -146,14 +146,15 @@ Intermap.InteractionMatrixView = Backbone.View.extend({
},
_removeThenDecrementFollowing: function(views, viewToRemove) {
+ // first, remove the view
+ var i = _.indexOf(views, viewToRemove);
+ views.splice(i,1);
+
// wrap in underscore
views = _(views);
- var i = views.indexOf(viewToRemove);
-
// remove 1 item at index i, then decrement row index of the items after
- return views.chain().splice(i, 1).
- slice(i).invoke('decrementRowIndex');
+ return views.chain().slice(i).invoke('decrementRowIndex');
},
onTermCollectionAdd: function(addedTerm) {
diff --git a/js/intermap/views/InteractionView.js b/js/intermap/views/InteractionView.js
index aea9d04..7fff9a2 100755
--- a/js/intermap/views/InteractionView.js
+++ b/js/intermap/views/InteractionView.js
@@ -79,6 +79,8 @@ Intermap.InteractionView = Backbone.View.extend({
else {
el.removeClass('null').removeAttr('title');
}
+
+ this._updateCommentStyle();
},
cycleStatus: function(){
var self = this,
@@ -209,6 +211,15 @@ Intermap.InteractionView = Backbone.View.extend({
this.commentingFlag = false;
this.delayedHover = setTimeout(this.showCommentBox, 1000);
},
+ //
+ // Updates the class name of the element depending on whether the associated
+ // model has a comment or not.
+ //
+ _updateCommentStyle: function() {
+ var fun = this.model.hasComment() ? 'addClass' : 'removeClass';
+
+ jQuery(this.el)[fun]('hasComment');
+ },
updateAttributes: function() {
var title = '',
hasComment = this.model.hasComment();
@@ -223,7 +234,9 @@ Intermap.InteractionView = Backbone.View.extend({
else if(this.model.hasRelationship()) {
title = this.messages.relationship;
}
- jQuery(this.el).attr('title', title)[hasComment ? 'addClass' : 'removeClass']('hasComment');
+
+ jQuery(this.el).attr('title', title);
+ this._updateCommentStyle();
if(title == '') jQuery(this.el).removeAttr('title');
},
diff --git a/js/intermap/views/IntermapApplicationView.js b/js/intermap/views/IntermapApplicationView.js
index b566302..5e3e564 100644
--- a/js/intermap/views/IntermapApplicationView.js
+++ b/js/intermap/views/IntermapApplicationView.js
@@ -1,152 +1,244 @@
// the view for the application model
Intermap.ApplicationView = Backbone.View.extend({
- el: '#application',
- elError: null,
- _router: null,
- initialize: function() {
- _.bindAll(this, 'error', 'updateStatusPosition', 'closeError');
-
- new Intermap.RegisterView();
-
- // displays the graph
- var dotView = new Intermap.IntermapDotView({model: this.model.get('dotModel')});
-
- // routing for the application
- var router = new Intermap.Router();
- this._router = router;
- Backbone.history.start(); // required to perform initial routing
-
- // the main screens
- this._loginView = new Intermap.LoginView({router: router, model: this.model.get('auth')});
- new Intermap.ProjectsListView({model: this.model.get('projects')});
-
-
- var projectView = null;
- if(this.model.get('project')) {
- projectView = new Intermap.ProjectView({model: this.model.get('project')});
- }
-
- var self = this;
- function loadProject() {
- dotView.clear();
- // removes bound events.
- // @todo, reconsider how this works, and instead set a new model
- // and allow the view to re-render.
- if(projectView) projectView.unbind();
-
- projectView = new Intermap.ProjectView({model: self.model.get('project')});
-
- // shows the matrix only after the project has been rendered above
- router._showScreen('#matrix');
- _.delay(self.updateStatusPosition, 500);
- }
- this.model.bind('change:project', loadProject);
-
- // when we sort the terms, we want to reload the entire project.
- // someday, we should just reload the matrix view, but the matrix
- // view is what takes the longest anyway
- this.model.bind('sort:terms', loadProject);
-
- // setup info box
- this.elError = jQuery('<div class="message error"><div class="text"></div><button class="closeError">Close</button></div>');
- this.elError.prependTo('body').hide();
-
- // setup close button
- this.elError.find('button.closeError').click(this.closeError);
-
- this.elError.children('.button').click(function(){
- self.elError.slideUp();
- });
-
- this.model.bind('error', function(model, error) {
- if(error == 'Could not load project') {
- router.navigate('projects', true);
- }
- self.error(error);
- });
-
- this.model.bind('info', function(model, info) {
- self.info(info);
- });
-
- jQuery(window).scroll(this.updateStatusPosition).resize(this.updateStatusPosition);
- jQuery(window).scroll(this.updateMessagePosition).resize(this.updateMessagePosition);
- },
- getRouter: function() { return this._router; },
- getLoginView: function() { return this._loginView; },
-
- _errorBoxDelay: 5000,
- info: function(msg) {
- this.clearMessageClasses('info');
- this.message(msg);
- return this;
- },
- clearMessageClasses: function(newClass){
- var self = this;
- _(['error', 'info', 'warning']).each(function(className) {
- self.elError.removeClass(className);
- });
- if(newClass) {
- this.elError.addClass(newClass);
- }
- },
- error: function(msg) {
- this.clearMessageClasses('error');
- this.message(msg);
- },
- message: function(msg) {
- var elError = this.elError;
- this.updateMessagePosition();
- elError.children('.text').html(msg);
- elError.stop(true, false).slideDown().delay(this._errorBoxDelay).slideUp();
- },
- errorFun: function(msg) {
- var self = this;
- return function() {
- self.error(msg);
- };
- },
- setStatusVisibility: function(isVisible) {
- jQuery('#status')[isVisible?'show':'hide']();
- },
- status: function(msg) {
- var el = jQuery('#status > .statusText');
- el.html(msg);
- if(msg == '') {
- this.setStatusVisibility(false);
- }
- else {
- this.setStatusVisibility(true);
- this.updateStatusPosition();
- }
- },
- closeError: function() {
- this.elError.stop(true).slideUp();
- },
- // sticky footer
- // http://css-tricks.com/snippets/jquery/jquery-sticky-footer/
- updateStatusPosition: function() {
+ el: '#application',
+ elError: null,
+ _router: null,
+ events: {
+ 'click .addTerm': 'onAddTermClick',
+ 'focus input.termText': 'showDeleteButton',
+ 'click #linkDeleteActiveTerm': 'onDeleteTermClick'
+ },
+ // stores the ProjectListView for the application view
+ _projectListView: null,
+ initialize: function() {
+ _.bindAll(this, 'error', 'updateStatusPosition', 'closeError',
+ 'processMessageQueue', 'getProjectListView', 'onAddTermClick',
+ 'showDeleteButton', 'hideDeleteButton');
+
+ new Intermap.RegisterView();
+
+ // displays the graph
+ var dotView = new Intermap.IntermapDotView({model: this.model.get('dotModel')});
+
+ // routing for the application
+ var router = new Intermap.Router();
+ this._router = router;
+ Backbone.history.start(); // required to perform initial routing
+
+ // the main screens
+ this._loginView = new Intermap.LoginView({router: router, model: this.model.get('auth')});
+ this._projectListView = new Intermap.ProjectsListView({model: this.model.get('projects')});
+
+
+ var projectView = null;
+ if(this.model.get('project')) {
+ projectView = new Intermap.ProjectView({model: this.model.get('project')});
+ }
+
+ var self = this;
+ function loadProject() {
+ dotView.clear();
+ // removes bound events.
+ // @todo, reconsider how this works, and instead set a new model
+ // and allow the view to re-render.
+ if(projectView) projectView.unbind();
+
+ projectView = new Intermap.ProjectView({model: self.model.get('project')});
+
+ // shows the matrix only after the project has been rendered above
+ router._showScreen('#matrix');
+ _.delay(self.updateStatusPosition, 500);
+ }
+ this.model.bind('change:project', loadProject);
+
+ // when we sort the terms, we want to reload the entire project.
+ // someday, we should just reload the matrix view, but the matrix
+ // view is what takes the longest anyway
+ this.model.bind('sort:terms', loadProject);
+
+ // setup info box
+ this.elError = jQuery('<div class="message error"><div class="text"></div><button class="closeError">Close</button></div>');
+ this.elError.prependTo('body').hide();
+
+ // setup close button
+ this.elError.find('button.closeError').click(this.closeError);
+
+ this.elError.children('.button').click(function(){
+ self.elError.slideUp();
+ });
+
+ this.model.bind('error', function(model, error) {
+ if(error == 'Could not load project') {
+ router.navigate('projects', true);
+ }
+ self.error(error);
+ });
+
+ this.model.bind('info', function(model, info) {
+ self.info(info);
+ });
+
+ jQuery(window).scroll(this.updateStatusPosition).resize(this.updateStatusPosition);
+ jQuery(window).scroll(this.updateMessagePosition).resize(this.updateMessagePosition);
+
+ // this will hold messages that need to be processed
+ this._messageQueue = [];
+ },
+
+ // retrieves the IntermapRouter for the application
+ getRouter: function() { return this._router; },
+
+ // retrieves the LoginView object for the application
+ getLoginView: function() { return this._loginView; },
+
+ // called when the "Add Term" button is clicked
+ onAddTermClick: function(evt) {
+ Intermap.App.addTermFromText();
+ },
+
+ // called when the "Delete Term" button is clicked to delete the term
+ onDeleteTermClick: function(evt) {
+ var termText = jQuery('#linkDeleteActiveTerm').data('termText');
+ if(termText) {
+ Intermap.App.deleteTermFromText(termText);
+ }
+
+ },
+
+ // Used to show corresponding delete button for the activated TermInputView
+ // input box.
+
+ showDeleteButton: function(evt) {
+ // unbind the hide button from the previous term
+ if(this._showDeleteButtonTerm)
+ this._showDeleteButtonTerm.unbind('destroy', this.hideDeleteButton);
+
+ var el = jQuery(evt.target),
+ termText = el.val(),
+ term = Intermap.App.getTermByText(termText);
+
+ this.$('#linkDeleteActiveTerm')
+ .data('termText', termText)
+ .html('Delete Term "' + _.shorten(termText) + '"')
+ .show();
+
+ // bind the hide delete button so that if the term is destroyed,
+ // the delete button will be hidden
+ term.bind('destroy', this.hideDeleteButton);
+ this._showDeleteButtonTerm = term;
+ },
+
+ // Used to hide the delete button
+ //
+ hideDeleteButton: function() {
+ this.$('#linkDeleteActiveTerm').hide();
+ },
+
+ _errorBoxDelay: 5000,
+ info: function(msg) {
+ this.clearMessageClasses('info');
+ this.message(msg);
+ return this;
+ },
+ clearMessageClasses: function(newClass){
+ var self = this;
+ _(['error', 'info', 'warning']).each(function(className) {
+ self.elError.removeClass(className);
+ });
+ if(newClass) {
+ this.elError.addClass(newClass);
+ }
+ },
+ error: function(msg) {
+ this.clearMessageClasses('error');
+ this.message(msg);
+ },
+ _messageQueue: null,
+ _lastMessageTime: null,
+ message: function(msg) {
+ var self = this;
+
+ var displayMessage = function() {
+ var elError = self.elError;
+ self.updateMessagePosition();
+ elError.children('.text').html(msg);
+ elError.stop(true, false).slideDown().delay(self._errorBoxDelay).slideUp();
+ };
+
+ // queue this function to run when the next opportunity emerges
+ this._messageQueue.push(displayMessage);
+
+ this.processMessageQueue();
+ },
+ // Used to process messages in the queue
+ processMessageQueue: function() {
+ // if we are already processing a message, skip, cuz we don't want to
+ // clobber the other message
+ if(this._messageInProgress || this._messageQueue.length == 0) return;
+
+ // process the first message in the queue
+ this._messageInProgress = true; // a message is being shown
+ this._messageQueue.shift().apply();
+
+ // process the other messages in a few seconds
+ var self = this;
+ _.delay(function(){
+ // message has finished being shown
+ self._messageInProgress = false;
+ // resume processing queue
+ self.processMessageQueue();
+ }, 2000);
+
+ },
+ errorFun: function(msg) {
+ var self = this;
+ return function() {
+ self.error(msg);
+ };
+ },
+ setStatusVisibility: function(isVisible) {
+ jQuery('#status')[isVisible?'show':'hide']();
+ },
+ status: function(msg) {
+ var el = jQuery('#status > .statusText');
+ el.html(msg);
+ if(msg == '') {
+ this.setStatusVisibility(false);
+ }
+ else {
+ this.setStatusVisibility(true);
+ this.updateStatusPosition();
+ }
+ },
+ closeError: function() {
+ this.elError.stop(true).slideUp();
+ },
+ // sticky footer
+ // http://css-tricks.com/snippets/jquery/jquery-sticky-footer/
+ updateStatusPosition: function() {
var $ = jQuery,
- el = $("#status"),
- win = $(window);
-
+ el = $("#status"),
+ win = $(window);
+
if(!el.is(':visible')) return;
-
+
// update height using its child
el.height(el.children('.statusText').height());
var top = win.scrollTop() + win.height() - el.outerHeight() - 150;
el.stop().animate({top: top}, 'fast');
- },
- updateMessagePosition: function() {
- var $ = jQuery,
- el = $(".message"),
- win = $(window);
+ },
+ updateMessagePosition: function() {
+ var $ = jQuery,
+ el = $(".message"),
+ win = $(window);
if(!el.is(':visible')) return;
- var top = win.scrollTop();
+ var top = win.scrollTop();
- el.stop(true, true).animate({top: top}, 'fast').delay(this._errorBoxDelay).slideUp();
- }
+ el.stop(true, true).animate({top: top}, 'fast').delay(this._errorBoxDelay).slideUp();
+ },
+ // Returns the ProjectListView for the application view.
+ getProjectListView: function() { return this._projectListView; }
});
diff --git a/js/intermap/views/IntermapTermTagView.js b/js/intermap/views/IntermapTermTagView.js
index b4c25e4..35fb127 100644
--- a/js/intermap/views/IntermapTermTagView.js
+++ b/js/intermap/views/IntermapTermTagView.js
@@ -31,7 +31,7 @@ Intermap.TermTagView = Backbone.View.extend({
tag = termTag.get('tag');
if (tag){
- jQuery(this.el).html(tag.escape('text'))
+ jQuery(this.el).html(_.shorten(tag.escape('text')))
.css({
backgroundColor: tag.escape('bgcolor'),
color: tag.escape('fgcolor')
diff --git a/js/intermap/views/ProjectsListView.js b/js/intermap/views/ProjectsListView.js
index 7b1272e..666f0dd 100644
--- a/js/intermap/views/ProjectsListView.js
+++ b/js/intermap/views/ProjectsListView.js
@@ -5,7 +5,7 @@ Intermap.ProjectsListView = Backbone.View.extend({
'click .cloneLink': 'cloneProject'
},
initialize: function() {
- _.bindAll(this, 'render');
+ _.bindAll(this, 'render', 'renderProjectsSubmenu');
var self = this;
_.each(['add', 'delete', 'reset'], function(event){
self.model.bind(event, self.render);
@@ -46,8 +46,8 @@ Intermap.ProjectsListView = Backbone.View.extend({
error: Intermap.View.errorFun('Could not copy project.')
});
},
- render: function() {
- var projects = this.model.map(function(model) {
+ getProjectsAttributes: function() {
+ return this.model.map(function(model) {
return _.extend({},
model.attributes,
{
@@ -56,13 +56,21 @@ Intermap.ProjectsListView = Backbone.View.extend({
})
});
});
+ },
+ render: function() {
this.$('.projects-list').html(
- jQuery('#tmplProjectListItem').tmpl(projects)
+ jQuery('#tmplProjectListItem').tmpl(this.getProjectsAttributes())
);
+ this.renderProjectsSubmenu();
+ },
+ // Renders the projects sub menu that is displayed as a menu on the
+ // matrix screen. This should be called whenever the projects list
+ // is updated. Maybe it should be bound to the reset?
+ renderProjectsSubmenu: function() {
// this is the menu that appears on the #matrix screen
jQuery('.projectsSubmenu').html(
- jQuery('#tmplProjectSubmenuItem').tmpl(projects)
+ jQuery('#tmplProjectSubmenuItem').tmpl(this.getProjectsAttributes())
);
}
});
\ No newline at end of file
diff --git a/js/intermap/views/TermReorderView.js b/js/intermap/views/TermReorderView.js
index 37f4cf6..dbd5c2d 100644
--- a/js/intermap/views/TermReorderView.js
+++ b/js/intermap/views/TermReorderView.js
@@ -44,7 +44,7 @@ Intermap.TermReorderView = Backbone.View.extend({
},
render: function(){
var el = jQuery(this.el).empty().append(
- '<a href="javascript:" class="orderAlpha order">Alphabetically</a><a href="javascript:" class="orderTag order">By Tag</a>'
+ '<a href="javascript:" class="orderAlpha order">Alphabetically</a><a href="javascript:" class="orderTag order">By Tag</a><button class="submit">Save</button>'
),
ul = jQuery('<ul></ul>').appendTo(el),
tmpl = jQuery('#tmplReorderTermsListItem'),
diff --git a/js/intermap/views/TermTopView.js b/js/intermap/views/TermTopView.js
index 6f4d6ec..79f9563 100644
--- a/js/intermap/views/TermTopView.js
+++ b/js/intermap/views/TermTopView.js
@@ -37,22 +37,26 @@ Intermap.TermTopView = Backbone.View.extend({
jQuery(this.el).remove();
},
render: function() {
- var newEl = jQuery("#topTerms .template").tmpl(this.model.attributes, {
- // these methods are duplicated in TermReorderView, and should
- // be refactored to be DRY
- getTag: function() {
- var tag = this.data.tag;
- return tag ? tag.escape('text') : '';
- },
- getTagBackgroundColor: function() {
- var tag = this.data.tag;
- return tag ? tag.get('bgcolor') : 'transparent';
- },
- getTagForegroundColor: function() {
- var tag = this.data.tag;
- return tag ? tag.get('fgcolor') : 'black';
- }
- }).unwrap();
+ var self = this,
+ newEl = jQuery("#topTerms .template").tmpl(this.model, {
+ // these methods are duplicated in TermReorderView, and should
+ // be refactored to be DRY
+ getTag: function() {
+ var tag = this.data.get('tag');
+ return tag ? _.shorten(tag.escape('text')) : '';
+ },
+ getTagBackgroundColor: function() {
+ var tag = this.data.get('tag');
+ return tag ? tag.get('bgcolor') : 'transparent';
+ },
+ getTagForegroundColor: function() {
+ var tag = this.data.get('tag');
+ return tag ? tag.get('fgcolor') : 'black';
+ },
+ getTerm: function() {
+ return _.shorten(this.data.escape('text'), 30);
+ }
+ }).unwrap();
jQuery(this.el).html(newEl);
return this;
},
diff --git a/js/underscore-intermap.js b/js/underscore-intermap.js
index 574fe13..b888d38 100644
--- a/js/underscore-intermap.js
+++ b/js/underscore-intermap.js
@@ -17,5 +17,11 @@ _.mixin({
replacement = replacement || '\\"';
return _.quote(str.replace(/"/g, replacement), '"');
+ },
+
+ // shortens the string
+ shorten: function(str, len) {
+ len || (len = 10);
+ return str.length > len ? str.substr(0, len-3) + '...' : str;
}
});
diff --git a/tests/jasmine/dot.js b/tests/jasmine/dot.js
index 1937da8..746d6ba 100644
--- a/tests/jasmine/dot.js
+++ b/tests/jasmine/dot.js
@@ -2,6 +2,13 @@ describe("DOT file", function(){
var
reusableTerms,
project;
+
+ function forceTermsNotNew(terms) {
+ terms.each(function(term) {
+ // force id to be something so that it isn't new
+ term.id = 1;
+ });
+ }
//custom matchers
beforeEach(function() {
@@ -40,11 +47,14 @@ describe("DOT file", function(){
it("can have multiple-word terms", function(){
// the dot file uses ids for the nodes of the form c\d+ ie, c200, c1
var dotRE = /^graph myGraph { label="New Project\\lCentral terms are shown as octagons" labelloc="t" c\d+ \[label="test me"\]; }$/ig,
- localIntermap = new Intermap.Application();
+ localIntermap = new Intermap.Application(),
+ project = localIntermap.get('project');
localIntermap.addTermFromText('test me');
+ forceTermsNotNew (project.get('terms'));
+
var dotModel = new Intermap.DotFile({
- project: localIntermap.get('project')
+ project: project
});
expect(dotModel.getDot()).toMatch(dotRE);
});
@@ -56,6 +66,7 @@ describe("DOT file", function(){
dotModel = new Intermap.DotFile({
project: project
});
+ forceTermsNotNew (project.get('terms'));
expect(interactions.length).not.toEqual(0);
expect(dotModel.getDot()).toMatch(dotFile);
});
@@ -69,7 +80,7 @@ describe("DOT file", function(){
dotModel = new Intermap.DotFile({
project: project
}),
- dotMatcher = /graph myGraph { label="New Project\\lCentral terms are shown as octagons" labelloc="t" c\d+ \[style=filled,fillcolor=([A-Za-z]+),label="A"\];c\d+ \[style=filled,fillcolor=\1,label="B"\];c\d+ \[style=filled,fillcolor=([A-Za-z]+),label="C"\];\s+{ rank=sink; legend \[label="Tag Legend", shape=none, fontsize=14\]; c\d+ \[label=dog,fillcolor=\1,style=filled,shape=box,fontsize=14\];c\d+ \[label=cat,fillcolor=\2,style=filled,shape=box,fontsize=14\]; }}/
+ dotMatcher = /graph myGraph { label="New Project\\lCentral terms are shown as octagons" labelloc="t" c\d+ \[style=filled,fillcolor="([#A-Za-z\d]+)",label="A"\];c\d+ \[style=filled,fillcolor="\1",label="B"\];c\d+ \[style=filled,fillcolor="([#A-Za-z\d]+)",fontcolor="white",label="C"\];\s+{ rank=sink; legend \[label="Tag Legend", shape=none, fontsize=14\]; c\d+ \[label="dog",fillcolor="\1",style=filled,shape=box,fontsize=14\];c\d+ \[label="cat",fillcolor="\2",style=filled,shape=box,fontsize=14,fontcolor="white"\]; }}/;
_.each([
@@ -79,6 +90,7 @@ describe("DOT file", function(){
], function(termProps) {
terms.add(new Intermap.Term(termProps));
});
+ forceTermsNotNew (terms);
expect(dotModel.getDot()).toMatch(dotMatcher);
});
diff --git a/tests/jasmine/index.html b/tests/jasmine/index.html
index 7225cb8..0431c08 100644
--- a/tests/jasmine/index.html
+++ b/tests/jasmine/index.html
@@ -10,6 +10,7 @@
<!-- include source files here... -->
<script type="text/javascript" src="../../js/underscore.js"></script>
+ <script type="text/javascript" src="../../js/underscore-intermap.js"></script>
<script type="text/javascript" src="../../js/backbone.js"></script>
<!-- Intermap.App Source Files -->
diff --git a/tests/selenium/GraphFromSample.html b/tests/selenium/GraphFromSample.html
index 80118eb..c5b802e 100644
--- a/tests/selenium/GraphFromSample.html
+++ b/tests/selenium/GraphFromSample.html
@@ -156,12 +156,12 @@
</tr>
<tr>
<td>click</td>
- <td>//div[@id='leftTerms']/div[2]/span[2]/img</td>
+ <td>//div[@id='leftTerms']/div[2]/span[2]</td>
<td></td>
</tr>
<tr>
<td>click</td>
- <td>//div[@id='leftTerms']/div[1]/span[2]/img</td>
+ <td>//div[@id='leftTerms']/div[1]/span[2]</td>
<td></td>
</tr>
<tr>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment