Skip to content

Commit

Permalink
Improved DocumentLens implementation.
Browse files Browse the repository at this point in the history
  • Loading branch information
michael committed Mar 18, 2012
1 parent 6879e09 commit a561d68
Show file tree
Hide file tree
Showing 10 changed files with 116 additions and 90 deletions.
2 changes: 1 addition & 1 deletion layouts/app.html
Expand Up @@ -41,7 +41,7 @@
use for everyone. <a href="/substance/contribute">Support</a> us!
</div>
<div class="credits"><a href="http://substance.io/substance/substance">About</a> &middot; <a href="http://twitter.com/_substance" target="_blank">Twitter</a> &middot; <a href="http://github.com/substance/substance" target="_blank">Source Code</a> &middot; <a href="https://groups.google.com/group/substance_" target="_blank">Discuss</a></div>
<div class="version"><a href="http://substance.io/substance/release-notes">Substance 0.4.0</a></div>
<div class="version"><a href="http://substance.io/substance/release-notes">Substance 0.4.1</a></div>
</div>
</body>

Expand Down
47 changes: 2 additions & 45 deletions src/client/views/application.js
Expand Up @@ -50,7 +50,8 @@ s.views.Application = Backbone.View.extend({

scrollTo: function (id) {
var offset = $('#'+id).offset();
offset ? $('html, body').animate({scrollTop: offset.top-90}, 'slow') : null;
// offset ? $('html, body').animate({scrollTop: offset.top-90}, 'fast') : null;
offset ? $('html, body').scrollTop(offset.top-90) : null;
return false;
},

Expand Down Expand Up @@ -142,50 +143,6 @@ s.views.Application = Backbone.View.extend({
loadDocument: function (username, docname, version, nodeid, commentid) {
var render = _.bind(function (options) {
this.replaceMainView("document", new s.views.Document(_.extend(options, {id: 'document_view' })).render());

// TODO: move code to document view
var bounds;
var sections;

// Calculate boundaries
function calcBounds() {
bounds = [];
sections = [];
$('#document .content-node.section').each(function() {
bounds.push($(this).offset().top);
sections.push(graph.get(this.id.replace(/_/g, '/')));
});
}

function getActiveSection() {
var active = 0;
_.each(bounds, function(bound, index) {
if ($(window).scrollTop() >= bound-90) {
active = index;
}
});
return active;
}

var prevSection = null;

function updateToc(e) {
var activeSection = getActiveSection();
if (activeSection !== prevSection) {
prevSection = activeSection;
app.mainView.documentLens.selectedItem = activeSection;
// TODO: no re-render required here
app.mainView.documentLens.render();
}
}

window.calcBounds = calcBounds;
window.getActiveSection = getActiveSection;
window.updateToc = updateToc;

setTimeout(calcBounds, 400);
$(window).scroll(updateToc);

}, this);

var id = '/document/'+username+'/'+docname;
Expand Down
61 changes: 53 additions & 8 deletions src/client/views/document.js
@@ -1,6 +1,4 @@



// Document
// -------------

Expand All @@ -12,21 +10,22 @@ s.views.Document = Backbone.View.extend({
this.authorized = options.authorized;
this.published = options.published;
this.version = options.version;

var sections = [];

var sections;
function collectSections (node, level) {
if (level === 1) sections = [];
node.get('children').each(function (child) {
if (child.type.key !== '/type/section') return;
sections.push({id: child._id, html_id: child.html_id, name: child.get('name'), level: level});
collectSections(child, level+1);
});
return sections;
}

collectSections(this.model, 1);

this.node = s.views.Node.create({ model: this.model, document: this });
this.documentLens = new s.views.DocumentLens({ model: {items: sections}, authorized: this.authorized });
this.documentLens = new s.views.DocumentLens({ model: {items: sections, document: this}, authorized: this.authorized });
this.settings = new s.views.DocumentSettings({ model: this.model, authorized: this.authorized });
this.publish = new s.views.Publish({ model: this.model, docView: this, authorized: this.authorized });
this.invite = new s.views.Invite({ model: this.model, authorized: this.authorized });
Expand All @@ -35,14 +34,26 @@ s.views.Document = Backbone.View.extend({
this.versions = new s.views.Versions({ model: this.model, authorized: this.authorized });

// TODO: Instead listen for a document-changed event
graph.bind('dirty', _.bind(function() {
graph.bind('dirty', _.bind(function(node) {
this.updatePublishState();

// Update TOC
if (node.type._id === "/type/section") {
// Recalc bounds every time content is changed
this.calcBounds();
setTimeout(_.bind(function() {
this.documentLens.model.items = collectSections(this.model, 1);
this.documentLens.render();
}, this), 2);
}
}, this));

this.currentView = null;

_.bindAll(this, 'deselect', 'onKeydown');
$(document.body).keydown(this.onKeydown);
if (!this.bounds) setTimeout(this.calcBounds, 400);
$(window).scroll(this.markActiveSection);
},

render: function () {
Expand Down Expand Up @@ -134,19 +145,53 @@ s.views.Document = Backbone.View.extend({
}
},

// Calculate section bounds
calcBounds: function() {
var that = this;
this.bounds = [];
this.sections = [];
$('#document .content-node.section').each(function() {
that.bounds.push($(this).offset().top);
that.sections.push(graph.get(this.id.replace(/_/g, '/')));
});
},

markActiveSection: function() {
var that = this;
function getActiveSection() {
var active = 0;
_.each(that.bounds, function(bound, index) {
if ($(window).scrollTop() >= bound-90) {
active = index;
}
});
return active;
}

function update(e) {
that.activeSection = getActiveSection();
if (that.activeSection !== that.prevSection) {
that.prevSection = that.activeSection;
that.documentLens.selectSection(that.activeSection);
}
}
update();
},

resizeShelf: function () {
var shelfHeight = this.currentView ? $(this.currentView.el).outerHeight() : 0
, contentMargin = shelfHeight + 100;
this.$('#document_shelf').css({ height: shelfHeight + 'px' });
this.$('#document_content').css({ 'margin-top': contentMargin + 'px' });
this.$('#document_lens').css({ 'top': (contentMargin+40) + 'px' });
},

closeShelf: function() {
if (!this.currentView) return;
this.currentView.unbind('resize', this.resizeShelf);

// It's important to use detach (not remove) to retain the view's event
// handlers
// It's important to use detach (not remove) to retain
// the view's event handlers
$(this.currentView.el).detach();

this.currentView = null;
Expand Down
29 changes: 20 additions & 9 deletions src/client/views/document_lens.js
Expand Up @@ -14,13 +14,20 @@ s.views.DocumentLens = Backbone.View.extend({

this.selectedItem = 0;
this.start = 0;
this.windowSize = 9;
this.height = 270;
this.windowSize = 12;
this.height = this.windowSize * 30;
},

scrollTo: function (e) {
var node = $(e.currentTarget).attr('href').slice(1);
var index = $(e.currentTarget).attr('data-index');
app.scrollTo(node);
setTimeout(_.bind(function() {
this.selectSection(index);
// TODO: view dependency alert
this.model.document.prevSection = index;
}, this), 40);

return false;
},

Expand All @@ -33,6 +40,16 @@ s.views.DocumentLens = Backbone.View.extend({
return [start, start+this.windowSize-1];
},

selectSection: function(item) {
this.selectedItem = item;

this.$('.items .item.selected').removeClass('selected');
this.$($('.items .item')[item]).addClass('selected');
this.$('.outline .outline-item').removeClass('selected');
this.$($('.outline .outline-item')[item]).addClass('selected');
this.$('.items').scrollTop(this.getBounds()[0]*30);
},

render: function () {
var bounds = this.getBounds();
var that = this;
Expand All @@ -42,11 +59,6 @@ s.views.DocumentLens = Backbone.View.extend({
selectedItem: this.selectedItem
}));

// Good?
this.$('.items').mouseleave(function() {
that.render();
});

this.$('.items').scroll(function(e) {
e.preventDefault();
e.stopPropagation();
Expand All @@ -61,8 +73,7 @@ s.views.DocumentLens = Backbone.View.extend({
});

this.$('.items').scrollTop(bounds[0]*30);

var delta = this.height/this.model.items.length;
var delta = Math.min(this.height/this.model.items.length, 30);
this.$('.outline .outline-item').height(delta);

return this;
Expand Down
6 changes: 4 additions & 2 deletions styles/document/document.less
Expand Up @@ -14,7 +14,7 @@
}

#document_identifier {
margin: 9px 80px;
margin: 9px 40px;
margin-right: 20px;
float: left;

Expand Down Expand Up @@ -174,7 +174,9 @@
width: 920px;
color: #000;
position:relative;
margin: 0 auto;
margin: 0;
margin-left: 320px;

padding: 0px 0 0px 0;
-webkit-box-shadow: 0px 1px 4px rgba(0,0,0,0.35), inset 0px 0px 1px rgba(255,255,255,0.15);
-moz-box-shadow: 0px 1px 4px rgba(0,0,0,0.35), inset 0px 0px 1px rgba(255,255,255,0.15);
Expand Down
48 changes: 29 additions & 19 deletions styles/document/lens.less
@@ -1,32 +1,39 @@
#document #document_lens {
-webkit-transition-property: top;
-webkit-transition-duration: 0.6s;
position: fixed;
overflow: hidden;
width: 250px;
left: 10px;
top: 100px;
height: 800px;
left: 40px;
top: 120px;
height: 600px;

.ui-font;
font-weight: bold;
font-size: 12px;


overflow: auto;

.items {
height: 270px;
height: 360px; // 15x30 make dynamic
position: absolute;
top: 0px;
left: 0px;
width: 600px;
overflow-y: auto;
overflow-x: hidden;
margin-left: 30px;

.item {
whitespace: nowrap;
height: 30px;
width: 300px;
width: 230px;

line-height: 30px;

&.level-1 { font-weight: bold; font-size: 16px;}
&.level-1 { font-weight: bold; font-size: 14px; }
&.level-2 { padding-left: 10px; }
&.level-3 { padding-left: 20px; }

a { border: none; color: #939393;}
a { border: none; color: #939393; }
a:hover { color: #444; }

&.selected {
a { color: #2D2D2D;}
Expand All @@ -35,23 +42,26 @@
}

.outline {
float: left;
margin-right: 5px;
float: right;
width: 5px;
height: 270px;
/*height: 270px;*/

.outline-item {
width: 4px;
margin-left: 1px;
background: #8C8C8C;
background: #ccc;
margin-bottom: 1px;

&.selected {
background: #383838;
}
&.active {
background: #8C8C8C;
padding: 0 3px;
margin-left: 0;
}

&.selected {
background: #383838;
}
}
}
}
}
2 changes: 1 addition & 1 deletion styles/document/shelf-content.less
@@ -1,6 +1,6 @@
.shelf-content {
padding: 20px;
padding-left: 80px;
padding-left: 40px;
a { border-bottom: none; }
.settings-title {}
}
2 changes: 1 addition & 1 deletion styles/header.less
Expand Up @@ -20,7 +20,7 @@ body:not(.document) #header {
#header_title {
.document-font;
float: left;
margin: 0 80px;
margin: 0 40px;

a {
text-decoration: none;
Expand Down
7 changes: 4 additions & 3 deletions styles/layout.less
Expand Up @@ -20,13 +20,14 @@ body {
border-top: 1px solid #C1C1C1;
background: #E9EAE5;
color: #7C6E60;
height: 142x; margin-top: -142px;
padding: 30px 80px 30px 80px;
height: 142px; margin-top: -142px;
padding: 30px 40px;
overflow: auto;

z-index: 1000;

.did-you-know {
.document-font;

padding: 20px 0;
font-size: 22px;
font-style: italic;
Expand Down
2 changes: 1 addition & 1 deletion templates/document_lens.ejs
Expand Up @@ -6,6 +6,6 @@

<div class="items">
<% _.each(items, function(item, i) { %>
<div class="item level-<%= item.level %><%= selectedItem === i ? " selected" : ""%>"><a href="#<%= item.html_id %>"><%= item.name %></a></div>
<div class="item level-<%= item.level %><%= selectedItem === i ? " selected" : ""%>"><a data-index="<%= i %>" href="#<%= item.html_id %>"><%= item.name %></a></div>
<% }); %>
</div>

0 comments on commit a561d68

Please sign in to comment.