diff --git a/lms/static/js/jquery.gradebook.js b/lms/static/js/jquery.gradebook.js index 7a5ce66081..88674342d3 100644 --- a/lms/static/js/jquery.gradebook.js +++ b/lms/static/js/jquery.gradebook.js @@ -2,106 +2,129 @@ var Gradebook = function($element) { - var _this = this; - var $element = $element; - var $body = $('body'); - var $grades = $element.find('.grades'); - var $studentTable = $element.find('.student-table'); - var $gradeTable = $element.find('.grade-table'); - var $search = $element.find('.student-search-field'); - var $leftShadow = $('
'); - var $rightShadow = $('
'); - var tableHeight = $gradeTable.height(); - var maxScroll = $gradeTable.width() - $grades.width(); - - var mouseOrigin; - var tableOrigin; + "use strict"; + var $body = $('body'); + var $grades = $element.find('.grades'); + var $studentTable = $element.find('.student-table'); + var $gradeTable = $element.find('.grade-table'); + var $search = $element.find('.student-search-field'); + var $leftShadow = $('
'); + var $rightShadow = $('
'); + var tableHeight = $gradeTable.height(); + var maxScroll = $gradeTable.width() - $grades.width(); - var startDrag = function(e) { - mouseOrigin = e.pageX; - tableOrigin = $gradeTable.position().left; - $body.css('-webkit-user-select', 'none'); - $body.bind('mousemove', moveDrag); - $body.bind('mouseup', stopDrag); - }; + var mouseOrigin; + var tableOrigin; - var moveDrag = function(e) { - var offset = e.pageX - mouseOrigin; - var targetLeft = clamp(tableOrigin + offset, -maxScroll, 0); + var startDrag = function(e) { + mouseOrigin = e.pageX; + tableOrigin = $gradeTable.position().left; + $body.addClass('no-select'); + $body.bind('mousemove', onDragTable); + $body.bind('mouseup', stopDrag); + }; - updateHorizontalPosition(targetLeft); + /** + * - Called when the user drags the gradetable + * - Calculates targetLeft, which is the desired position + * of the grade table relative to its leftmost position, using: + * - the new x position of the user's mouse pointer; + * - the gradebook's current x position, and; + * - the value of maxScroll (gradetable width - container width). + * - Updates the position and appearance of the gradetable. + */ + var onDragTable = function(e) { + var offset = e.pageX - mouseOrigin; + var targetLeft = clamp(tableOrigin + offset, maxScroll, 0); + updateHorizontalPosition(targetLeft); + setShadows(targetLeft); + }; - setShadows(targetLeft); - }; + var stopDrag = function() { + $body.removeClass('no-select'); + $body.unbind('mousemove', onDragTable); + $body.unbind('mouseup', stopDrag); + }; - var stopDrag = function(e) { - $body.css('-webkit-user-select', 'auto'); - $body.unbind('mousemove', moveDrag); - $body.unbind('mouseup', stopDrag); - }; + var setShadows = function(left) { + var padding = 30; - var setShadows = function(left) { - var padding = 30; + var leftPercent = clamp(-left / padding, 0, 1); + $leftShadow.css('opacity', leftPercent); - var leftPercent = clamp(-left / padding, 0, 1); - $leftShadow.css('opacity', leftPercent); - - var rightPercent = clamp((maxScroll + left) / padding, 0, 1); - $rightShadow.css('opacity', rightPercent); - }; + 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 clamp = function(val, min, max) { + if(val > max) { return max; } + if(val < min) { return min; } + return val; + }; - var updateWidths = function(e) { - maxScroll = $gradeTable.width() - $grades.width(); - var targetLeft = clamp($gradeTable.position().left, -maxScroll, 0); - updateHorizontalPosition(targetLeft); - setShadows(targetLeft); - }; + /** + * - Called when the browser window is resized. + * - Recalculates maxScroll (gradetable width - container width). + * - Calculates targetLeft, which is the desired position + * of the grade table relative to its leftmost position, using: + * - the gradebook's current x position, and: + * - the new value of maxScroll + * - Updates the position and appearance of the gradetable. + */ + var onResizeTable = function() { + maxScroll = $gradeTable.width() - $grades.width(); + var targetLeft = clamp($gradeTable.position().left, maxScroll, 0); + updateHorizontalPosition(targetLeft); + setShadows(targetLeft); + }; - var updateHorizontalPosition = function(left) { - $gradeTable.css({ - 'left': left + 'px' - }); - }; + /** + * - Called on table drag and on window (table) resize. + * - Takes a integer value for the desired (pixel) offset from the left + * (zero/origin) position of the grade table. + * - Uses that value to position the table relative to its leftmost + * possible position within its container. + * + * @param {Number} left - The desired pixel offset from left of the + * desired position. If the value is 0, the gradebook should be moved + * all the way to the left side relative to its parent container. + */ + var updateHorizontalPosition = function(left) { + $grades.scrollLeft(left); + }; - var highlightRow = function(e) { - $element.find('.highlight').removeClass('highlight'); + var highlightRow = function() { + $element.find('.highlight').removeClass('highlight'); - var index = $(this).index(); - $studentTable.find('tr').eq(index + 1).addClass('highlight'); - $gradeTable.find('tr').eq(index + 1).addClass('highlight'); - }; + var index = $(this).index(); + $studentTable.find('tr').eq(index + 1).addClass('highlight'); + $gradeTable.find('tr').eq(index + 1).addClass('highlight'); + }; - var filter = function(e) { - var term = $(this).val(); - if(term.length > 0) { - $studentTable.find('tbody tr').hide(); - $gradeTable.find('tbody tr').hide(); - $studentTable.find('tbody tr:contains(' + term + ')').each(function(i) { - $(this).show(); - $gradeTable.find('tr').eq($(this).index() + 1).show(); - }); - } else { - $studentTable.find('tbody tr').show(); - $gradeTable.find('tbody tr').show(); - } - } + var filter = function() { + var term = $(this).val(); + if(term.length > 0) { + $studentTable.find('tbody tr').hide(); + $gradeTable.find('tbody tr').hide(); + $studentTable.find('tbody tr:contains(' + term + ')').each(function() { + $(this).show(); + $gradeTable.find('tr').eq($(this).index() + 1).show(); + }); + } else { + $studentTable.find('tbody tr').show(); + $gradeTable.find('tbody tr').show(); + } + }; - $leftShadow.css('height', tableHeight + 'px'); - $rightShadow.css('height', tableHeight + 'px'); - $grades.append($leftShadow).append($rightShadow); - setShadows(0); - $grades.css('height', tableHeight); - $gradeTable.bind('mousedown', startDrag); - $element.find('tr').bind('mouseover', highlightRow); - $search.bind('keyup', filter); - $(window).bind('resize', updateWidths); -} + $leftShadow.css('height', tableHeight + 'px'); + $grades.append($leftShadow).append($rightShadow); + setShadows(0); + $grades.css('height', tableHeight); + $gradeTable.bind('mousedown', startDrag); + $element.find('tr').bind('mouseover', highlightRow); + $search.bind('keyup', filter); + $(window).bind('resize', onResizeTable); +}; diff --git a/lms/static/sass/course/_gradebook.scss b/lms/static/sass/course/_gradebook.scss index 9bd921dd6c..28bb5a87b4 100644 --- a/lms/static/sass/course/_gradebook.scss +++ b/lms/static/sass/course/_gradebook.scss @@ -1,6 +1,15 @@ $cell-border-color: #e1e1e1; $table-border-color: #c8c8c8; +.no-select { + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + div.gradebook-wrapper { section.gradebook-content { @@ -75,7 +84,8 @@ div.gradebook-wrapper { position: relative; float: left; width: 76%; - overflow: hidden; + overflow-x: auto; + overflow-y: hidden; .left-shadow, .right-shadow { diff --git a/lms/templates/courseware/gradebook.html b/lms/templates/courseware/gradebook.html index 562adabf9c..2ec8dee0b4 100644 --- a/lms/templates/courseware/gradebook.html +++ b/lms/templates/courseware/gradebook.html @@ -74,13 +74,24 @@ from django.core.urlresolvers import reverse %for section in templateSummary['section_breakdown']: -
${section['label']}
+ <% + tooltip_str = section['detail'] + # We are making header labels from the first student record. So for tool tip (title), + # I am processing this string ```section['detail']``` from student record and removing + # all student related data i.e marks, percentage etc to get only the title of homework. + if "=" in section['detail']: + tooltip_str = section['detail'][0: section['detail'].rfind('=')] + + if "-" in tooltip_str: + tooltip_str = tooltip_str[0: tooltip_str.rfind('-')] + %> +
${section['label']}
%endfor -
Total
+
${_('Total')}
- <%def name="percent_data(fraction)"> + <%def name="percent_data(fraction, label)"> <% letter_grade = 'None' if fraction > 0: @@ -92,16 +103,16 @@ from django.core.urlresolvers import reverse data_class = "grade_" + letter_grade %> - ${ "{0:.0f}".format( 100 * fraction ) } + ${ "{0:.0f}".format( 100 * fraction ) } %for student in students: %for section in student['grade_summary']['section_breakdown']: - ${percent_data( section['percent'] )} + ${percent_data( section['percent'], section['detail'] )} %endfor - ${percent_data( student['grade_summary']['percent'])} + ${percent_data( student['grade_summary']['percent'], _('Total'))} %endfor