Commit e762844c by Tom Giannattasio

new sequence nav functionality - accommodates an infinite number of items

parent 55797545
...@@ -2,21 +2,52 @@ nav.sequence-nav { ...@@ -2,21 +2,52 @@ nav.sequence-nav {
// TODO (cpennington): This doesn't work anymore. XModules aren't able to // TODO (cpennington): This doesn't work anymore. XModules aren't able to
// import from external sources. // import from external sources.
@extend .topbar; @extend .topbar;
border: 1px solid #ccc; margin: -4px 0 30px;
height: 44px;
@include linear-gradient(top, #eee, #ddd);
@include border-radius(25px);
margin: -4px -20px 30px;
position: relative; position: relative;
@include box-shadow(0 1px 0 #fff inset); border-bottom: none;
.left-shadow {
position: absolute;
top: 0;
left: 0;
width: 20px;
height: 46px;
@include linear-gradient(left, rgba(0, 0, 0, .2), rgba(0, 0, 0, 0));
background-color: transparent;
pointer-events: none;
}
.right-shadow {
position: absolute;
top: 0;
right: 0;
width: 20px;
height: 46px;
@include linear-gradient(right, rgba(0, 0, 0, .2), rgba(0, 0, 0, 0));
background-color: transparent;
pointer-events: none;
}
.sequence-list-wrapper {
position: relative;
z-index: 9999;
border: 1px solid #ccc;
height: 44px;
margin: 0 30px;
@include linear-gradient(top, #ddd, #eee);
overflow: hidden;
@include box-shadow(0 1px 3px rgba(0, 0, 0, .1) inset);
}
ol { ol {
position: absolute;
top: 0;
left: 0;
@include box-sizing(border-box); @include box-sizing(border-box);
display: table; display: table;
height: 100%; height: 100%;
margin: 0; margin: 0;
padding-left: 3px; padding: 0 10px;
padding-right: 90px;
width: 100%; width: 100%;
a { a {
...@@ -48,7 +79,6 @@ nav.sequence-nav { ...@@ -48,7 +79,6 @@ nav.sequence-nav {
} }
&.active { &.active {
border-color: $blue;
background-color: #fff; background-color: #fff;
z-index: 9; z-index: 9;
...@@ -177,26 +207,26 @@ nav.sequence-nav { ...@@ -177,26 +207,26 @@ nav.sequence-nav {
} }
ul { ul {
position: absolute;
top: 0;
list-style: none; list-style: none;
height: 100%; height: 100%;
position: absolute;
right: 0; right: 0;
top: 0; top: 0;
width: 81px; width: 100%;
margin: 5px 5px 0 0; margin: 0;
border: none; border: none;
border-bottom: 0;
@include border-radius(3px 3px 0 0);
li { li {
float: left; position: absolute;
margin-bottom: 0; margin-bottom: 0;
height: 34px; height: 44px;
width: 40px; width: 70px;
border: 1px solid #ccc;
@include linear-gradient(top, #eee, #ddd);
@include box-shadow(0 1px 0 rgba(255, 255, 255, .7) inset);
&.prev, &.next { &.prev, &.next {
@include linear-gradient(top, #ccc, #888);
@include box-shadow(0 -1px 0 rgba(0, 0, 0, .2) inset);
a { a {
background-position: center; background-position: center;
...@@ -219,21 +249,23 @@ nav.sequence-nav { ...@@ -219,21 +249,23 @@ nav.sequence-nav {
} }
&.prev { &.prev {
left: -10px;
border-radius: 35px 0 0 35px; border-radius: 35px 0 0 35px;
a { a {
background-image: url('../images/sequence-nav/previous-icon.png'); background-image: url('../images/sequence-nav/previous-icon.png');
background-position: center 10px; background-position: center 15px;
} }
} }
&.next { &.next {
right: -10px;
border-radius: 0 35px 35px 0; border-radius: 0 35px 35px 0;
a { a {
border-left: 1px solid #888; margin-left: 30px;
background-image: url('../images/sequence-nav/next-icon.png'); background-image: url('../images/sequence-nav/next-icon.png');
background-position: center 10px; background-position: center 15px;
} }
} }
} }
......
var SequenceNav = function($element) {
var _this = this;
var $element = $element;
var $wrapper = $element.find('.sequence-list-wrapper');
var $list = $element.find('#sequence-list');
var $arrows = $element.find('.sequence-nav-buttons');
var maxScroll = $list.width() - $wrapper.width() + 20;
var $leftShadow = $('<div class="left-shadow"></div>');
var $rightShadow = $('<div class="right-shadow"></div>');
var $body = $('body');
var listOrigin;
var mouseOrigin;
var startDrag = function(e) {
updateWidths();
mouseOrigin = e.pageX;
listOrigin = $list.position().left;
$body.css('-webkit-user-select', 'none');
$body.bind('mousemove', moveDrag);
$body.bind('mouseup', stopDrag);
};
var moveDrag = function(e) {
var offset = e.pageX - mouseOrigin;
var targetLeft = clamp(listOrigin + offset, -maxScroll, 0);
console.log('---------------');
console.log('offset: ' + offset);
console.log('target left: ' + targetLeft);
console.log('max: ' + maxScroll);
updateHorizontalPosition(targetLeft);
setShadows(targetLeft);
};
var stopDrag = function(e) {
$body.css('-webkit-user-select', 'auto');
$body.unbind('mousemove', moveDrag);
$body.unbind('mouseup', stopDrag);
};
var setShadows = function(left) {
var left = left || $list.position().left;
var padding = 30;
var leftPercent = clamp(-left / padding, 0, 1);
$leftShadow.css('opacity', leftPercent);
var rightPercent = clamp((maxScroll + left) / padding, 0, 1);
$rightShadow.css('opacity', rightPercent);
};
var clamp = function(val, min, max) {
if(val > max) return max;
if(val < min) return min;
return val;
};
var updateWidths = function(e) {
maxScroll = $list.width() - $wrapper.width() + 20;
var targetLeft = clamp($list.position().left, -maxScroll, 0);
updateHorizontalPosition(targetLeft);
setShadows(targetLeft);
};
var updateHorizontalPosition = function(left) {
$list.css({
'left': left + 'px'
});
};
var checkPosition = function(e) {
var $active = $element.find('.active');
if(!$active[0]) {
return;
}
if($active.position().left + $active.width() > $wrapper.width() - $list.position().left) {
$list.animate({
'left': (-$active.position().left + $wrapper.width() - $active.width() - 10) + 'px'
}, {
step: setShadows
});
} else if($active.position().left < -$list.position().left) {
$list.animate({
'left': (-$active.position().left + 10) + 'px'
}, {
step: setShadows
});
}
};
$wrapper.append($leftShadow).append($rightShadow);
setShadows(0);
$wrapper.bind('mousedown', startDrag);
$arrows.bind('click', checkPosition);
$(window).bind('resize', updateWidths);
setTimeout(function() {
checkPosition();
}, 200);
}
\ No newline at end of file
...@@ -29,12 +29,13 @@ a { ...@@ -29,12 +29,13 @@ a {
padding: 1.4em 0 0 0; padding: 1.4em 0 0 0;
> div { > div {
display: table;
width: 100%; width: 100%;
@include box-sizing(border-box); @include box-sizing(border-box);
border-radius: 3px; border-radius: 3px;
border: 1px solid #ccc; border: 1px solid #ccc;
background: #fff; background: #fff;
@include box-shadow(0 1px 10px rgba(0, 0, 0, 0.1)); @include box-shadow(0 1px 2px rgba(0, 0, 0, 0.05));
} }
} }
......
...@@ -58,11 +58,11 @@ nav.course-material { ...@@ -58,11 +58,11 @@ nav.course-material {
header.global { header.global {
border-bottom: 1px solid #bbb; border-bottom: 1px solid #bbb;
@include box-shadow(0 1px 2px rgba(0, 0, 0, .1)); @include box-shadow(0 1px 2px rgba(0, 0, 0, .1));
height: 45px; height: 50px;
@include linear-gradient(top, #fff, #eee); @include linear-gradient(top, #fff, #eee);
nav { nav {
padding-top: 2px; padding-top: 5px;
} }
h1.logo { h1.logo {
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
<%block name="js_extra"> <%block name="js_extra">
<script type="text/javascript" src="${static.url('js/vendor/jquery.scrollTo-1.4.2-min.js')}"></script> <script type="text/javascript" src="${static.url('js/vendor/jquery.scrollTo-1.4.2-min.js')}"></script>
<script type="text/javascript" src="${static.url('js/vendor/flot/jquery.flot.js')}"></script> <script type="text/javascript" src="${static.url('js/vendor/flot/jquery.flot.js')}"></script>
<script type="text/javascript" src="${static.url('js/jquery.sequence.js')}"></script>
## codemirror ## codemirror
<script type="text/javascript" src="${static.url('js/vendor/codemirror-compressed.js')}"></script> <script type="text/javascript" src="${static.url('js/vendor/codemirror-compressed.js')}"></script>
......
<div id="sequence_${element_id}" class="sequence" data-id="${item_id}" data-position="${position}" data-course_modx_root="/course/modx" > <div id="sequence_${element_id}" class="sequence" data-id="${item_id}" data-position="${position}" data-course_modx_root="/course/modx" >
<nav aria-label="Section Navigation" class="sequence-nav"> <nav aria-label="Section Navigation" class="sequence-nav">
<ol id="sequence-list"> <div class="sequence-list-wrapper">
% for idx, item in enumerate(items): <ol id="sequence-list">
## TODO (vshnayder): add item.progress_detail either to the title or somewhere else. % for idx, item in enumerate(items):
## Make sure it gets updated after ajax calls. ## TODO (vshnayder): add item.progress_detail either to the title or somewhere else.
## implementation note: will need to figure out how to handle combining detail ## Make sure it gets updated after ajax calls.
## statuses of multiple modules in js. ## implementation note: will need to figure out how to handle combining detail
<li> ## statuses of multiple modules in js.
<a class="seq_${item['type']} inactive progress-${item['progress_status']}" data-element="${idx+1}"> <li>
<p>${item['title']}</p> <a class="seq_${item['type']} inactive progress-${item['progress_status']}" data-element="${idx+1}">
</a> <p>${item['title']}</p>
</li> </a>
% endfor </li>
</ol> % endfor
</ol>
</div>
<ul class="sequence-nav-buttons"> <ul class="sequence-nav-buttons">
<li class="prev"><a href="#">Previous</a></li> <li class="prev"><a href="#">Previous</a></li>
...@@ -32,3 +34,15 @@ ...@@ -32,3 +34,15 @@
</ul> </ul>
</nav> </nav>
</div> </div>
<script type="text/javascript">
var sequenceNav;
$(document).ready(function() {
// console.log($('.sequence-nav'));
sequenceNav = new SequenceNav($('.sequence-nav'));
console.log(sequenceNav);
});
</script>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment