diff --git a/grade/report/grader/lib.php b/grade/report/grader/lib.php index f08ae20b2ce..4994964b097 100644 --- a/grade/report/grader/lib.php +++ b/grade/report/grader/lib.php @@ -1122,7 +1122,7 @@ class grade_report_grader extends grade_report { $html = ''; $fulltable = new html_table(); - $fulltable->attributes['class'] = 'table table-bordered table-striped table-condensed'; + $fulltable->attributes['class'] = 'gradereport-grader-table'; $fulltable->id = 'user-grades'; // Extract rows from each side (left and right) and collate them into one row each diff --git a/grade/report/grader/styles.css b/grade/report/grader/styles.css index 19ced6af95d..c198d852ef9 100644 --- a/grade/report/grader/styles.css +++ b/grade/report/grader/styles.css @@ -1,159 +1,144 @@ +/** + * Container. + */ .gradeparent { position: relative; } +/** + * Tooltip and overlay. + */ .gradeparent .grader-information-tooltip { min-width: 200px; } - .gradeparent .graderreportoverlay { background-color: white; width: auto; padding: 10px; - border-color: #ddd; font-size: 12px; - box-shadow: #999999 2px 2px 3px; + border: 1px solid #ccc; border-radius: 4px; } -.gradebook-header-cell, -.gradeparent table th { - font-size: 14px; - font-weight: normal; - padding: 4px 5px 4px 5px; - border: 0 solid #ddd; - border-left-width: 1px; - border-top-width: 1px; +/** + * The table. + */ +.gradeparent table { + border: 1px solid #ccc; + border-collapse: separate; + border-spacing: 0; + border-bottom-width: 0; + border-right-width: 0; } -/* General table properties */ -.gradeparent table td, -.gradeparent table th, -.gradeparent .cell, -.gradebook-footer-cell, -.gradebook-user-cell { +/** + * All the cells. + */ +.gradeparent .cell { + border: 1px solid #ccc; + border-top-width: 0; + border-left-width: 0; padding: 4px 5px; vertical-align: middle; } -/* Grade Item titles */ -.gradebook-header-cell, -.gradebook-header-cell, -#gradebook-user-header-container, -.gradeparent tr.heading th.item, -.gradeparent tr.heading th.courseitem, -.gradeparent tr.heading th.userfield, -#studentheader { +/** + * All the floating divs. + */ +.gradeparent .floater { + display: none; +} +.gradeparent .floating { + display: block; +} + +/** + * All the header/floating cells. + */ +.gradeparent .heading .cell, +.gradeparent .avg .cell, +.gradeparent .user.cell { + font-size: 14px; + font-weight: normal; + background-color: #eee; +} + +/** + * The header and footer. + */ +.gradeparent .heading .cell, +.gradeparent .avg .cell { white-space: nowrap; - background-color: #333; } -.gradeparent .gradebook-header-cell.item, -.gradeparent .gradebook-header-cell.item a, -.gradeparent .gradebook-header-cell.courseitem, -.gradeparent .gradebook-header-cell.courseitem a, -.gradeparent .gradebook-header-cell.userfield, -.gradeparent .gradebook-header-cell.userfield a, -.gradeparent #gradebook-user-header-container, -.gradeparent #gradebook-user-header-container a, -.gradeparent .gradebook-user-cell, -.gradeparent .gradebook-user-cell a, -.gradeparent tr.heading th.item, -.gradeparent tr.heading th.item a, -.gradeparent tr.heading th.courseitem, -.gradeparent tr.heading th.courseitem a, -.gradeparent tr.heading th.userfield, -.gradeparent tr.heading th.userfield a, -.gradeparent th a, -.gradeparent #studentheader a { - color: #fff; -} - -/* The username cells */ -.gradebook-user-cell { - border-width: 1px 0 0 1px; - border-style: solid; -} - -.gradebook-user-cell, -.gradeparent th.user { - padding: 4px; +/** + * The user cells. + */ +.gradeparent .user.cell { min-width: 200px; width: 200px; - border-color: #666666; - border-right-width: 1px; - border-left: none; - background-color: #333; - color: #ddd; } - -.gradebook-user-cell:nth-child(odd), -.gradeparent tr:nth-child(odd) th.user { - background-color: #777; -} - -.gradebook-user-cell:nth-child(even), -.gradeparent tr:nth-child(even) th.user { - background-color: #5c5c5c; -} - -.gradebook-user-cell .userpicture, -.gradeparent th.user .userpicture { - margin-right: 4px; - border-radius: 50px; +.gradeparent .user.cell .userpicture { + margin: 0 4px; border: none; vertical-align: top; } -/* The top-left user header cell */ -#gradebook-user-header-container, -#studentheader { - padding: 4px 5px; - border-top: 1px solid #ddd; +/** + * The additional user fields. + */ +.gradeparent .userfield { + font-weight: normal; } -#studentheader { - border-left: none; -} - -/* The footer row */ -.gradebook-footer-cell, -.gradeparent .gradevalue, -.gradeparent .avg .cell { - text-align: center; - width: 100%; -} - -.gradeparent .gradevalue { - display: inline-block; -} - -.gradeparent table#user-grades tr.avg th, -.gradeparent table#user-grades tr.avg td, -.gradebook-footer-cell { - padding: 8px; - background-color: #333; - color: white; +/** + * The footer's header. + */ +.gradeparent .avg .header { font-weight: bold; text-align: center; - border: 1px solid #444; - border-right: 0; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; } -#gradebook-footer-container.gradebook-footer-row-sticky { - background-color: #444; - display: block; - border-bottom: 0px solid #444; +/** + * The footer's cells. + */ +.gradeparent .avg.floating .cell { + border-top-width: 1px; } - -.gradebook-footer-cell:first-child, -.gradeparent table#user-grades tr.avg th.range { +/** + * The footer's range field. + */ +.gradeparent .avg .range { text-align: right; } +/** + * The header and user fields. + */ +.gradeparent .heading .cell, +.gradeparent .user.cell { + text-align: left; +} + +/** + * Content styling. + */ +.gradeparent .heading .cell .iconsmall { + /* Fixes inconsistencies in cell height on IE. */ + padding-top: 0; + padding-bottom: 0; +} +.gradeparent .sorticon { + margin-left: 3px; +} +.dir-rlt .gradeparent .sorticon { + margin-left: 0; + margin-right: 3px; +} +.gradeparent .gradevalue { + display: inline-block; +} + /** MDL-46812 **/ #page-grade-report-grader-index.jsenabled .right_scroller.topscroll { background-color: #ececec; diff --git a/grade/report/grader/yui/build/moodle-gradereport_grader-gradereporttable/moodle-gradereport_grader-gradereporttable-debug.js b/grade/report/grader/yui/build/moodle-gradereport_grader-gradereporttable/moodle-gradereport_grader-gradereporttable-debug.js index 3d609f72b99..bd77568c4c5 100644 --- a/grade/report/grader/yui/build/moodle-gradereport_grader-gradereporttable/moodle-gradereport_grader-gradereporttable-debug.js +++ b/grade/report/grader/yui/build/moodle-gradereport_grader-gradereporttable/moodle-gradereport_grader-gradereporttable-debug.js @@ -30,10 +30,12 @@ YUI.add('moodle-gradereport_grader-gradereporttable', function (Y, NAME) { */ var SELECTORS = { + FOOTERCELLS: '#user-grades .avg .cell', FOOTERROW: '#user-grades .avg', GRADECELL: 'td.grade', GRADERTABLE: '.gradeparent table', GRADEPARENT: '.gradeparent', + HEADERCELLS: '#user-grades .heading .cell', HEADERCELL: '.gradebook-header-cell', HEADERROW: '#user-grades tr.heading', STUDENTHEADER: '#studentheader', @@ -177,8 +179,8 @@ function Highlighter() {} Highlighter.ATTRS= { }; -var ROWFIELDS = 'th.user, th.userreport, th.userfield, .gradebook-user-cell', - COLFIELDS = 'tr[data-itemid] th.item, .gradebook-header-cell'; +var ROWFIELDS = '.user.cell, th.userreport, th.userfield', + COLFIELDS = 'tr[data-itemid] th.item, .heading .cell'; Highlighter.prototype = { /** @@ -280,6 +282,8 @@ var HEIGHT = 'height', OFFSETWIDTH = 'offsetWidth', OFFSETHEIGHT = 'offsetHeight'; +CSS.FLOATING = 'floating'; + function FloatingHeaders() {} FloatingHeaders.ATTRS= { @@ -540,7 +544,7 @@ FloatingHeaders.prototype = { */ _getRelativeXYFromXY: function(x, y) { var parentXY = this.container.getXY(); - return [Math.floor(x - parentXY[0]), Math.floor(y - parentXY[1])]; + return [x - parentXY[0], y - parentXY[1]]; }, /** @@ -612,7 +616,7 @@ FloatingHeaders.prototype = { var userColumn = Y.all(SELECTORS.USERCELL), // Create a floating table. - floatingUserColumn = Y.Node.create(''), + floatingUserColumn = Y.Node.create(''), // Get the XY for the floating element. coordinates = this._getRelativeXY(this.firstUserCell); @@ -620,32 +624,13 @@ FloatingHeaders.prototype = { // Generate the new fields. userColumn.each(function(node) { // Create and configure the new container. - var containerNode = Y.Node.create(''), - height, - width; - - // IE madness... - if (Y.UA.ie) { - var bb = parseInt(node.getComputedStyle('borderBottomWidth'), 10), - bt = parseInt(node.getComputedStyle('borderTopWidth'), 10), - bl = parseInt(node.getComputedStyle('borderLeftWidth'), 10), - br = parseInt(node.getComputedStyle('borderRightWidth'), 10), - pb = parseInt(node.getComputedStyle('paddingBottom'), 10), - pt = parseInt(node.getComputedStyle('paddingTop'), 10), - pl = parseInt(node.getComputedStyle('paddingLeft'), 10), - pr = parseInt(node.getComputedStyle('paddingRight'), 10); - height = node.get(OFFSETHEIGHT) - bb - bt - pb - pt; - width = node.get(OFFSETWIDTH) - bl - br - pl - pr; - } else { - height = node.getComputedStyle(HEIGHT); - width = node.getComputedStyle(WIDTH); - } - + var containerNode = Y.Node.create('
'); containerNode.set('innerHTML', node.get('innerHTML')) + .setAttribute('class', node.getAttribute('class')) .setAttribute('data-uid', node.ancestor('tr').getData('uid')) .setStyles({ - height: height, - width: width + height: node.getComputedStyle(HEIGHT), + width: node.getComputedStyle(WIDTH) }); // Add the new nodes to our floating table. @@ -673,30 +658,41 @@ FloatingHeaders.prototype = { * @protected */ _setupFloatingUserHeader: function() { - // We make various references to the this header cell. Store it for later. + // We make various references to the header cells. Store it for later. this.headerRow = Y.one(SELECTORS.HEADERROW); this.headerCell = Y.one(SELECTORS.STUDENTHEADER); - // Float the 'user name' header cell. - var floatingUserCell = Y.Node.create(''), - firstUserXY = this._getRelativeXY(this.firstUserCell), - headerXY = this._getRelativeXY(this.headerRow); + // Create the floating row and cell. + var floatingUserHeaderRow = Y.Node.create(''), + floatingUserHeaderCell = Y.Node.create('
'), + nodepos = this._getRelativeXY(this.headerCell)[0], + coordinates = this._getRelativeXY(this.headerRow); + gradeHeadersOffset = coordinates[0]; - // Append node contents - floatingUserCell.set('innerHTML', this.headerCell.getHTML()); - floatingUserCell.setStyles({ - height: this.headerCell.getComputedStyle(HEIGHT), - left: firstUserXY[0] + 'px', - position: 'absolute', - top: headerXY[1] + 'px', - width: this.firstUserCell.getComputedStyle(WIDTH) - }); + // Append the content and style to the floating cell. + floatingUserHeaderCell + .set('innerHTML', this.headerCell.getHTML()) + .setAttribute('class', this.headerCell.getAttribute('class')) + .setStyles({ + // The header is larger than the user cells, so we take the user cell. + width: this.firstUserCell.getComputedStyle(WIDTH), + left: (nodepos - gradeHeadersOffset) + 'px' + }); - // Append to the grader region. - this.graderRegion.append(floatingUserCell); + // Style the floating row. + floatingUserHeaderRow + .setStyles({ + left: coordinates[0] + 'px', + position: 'absolute', + top: coordinates[1] + 'px' + }); + + // Append the cell to the row, and finally to the region. + floatingUserHeaderRow.append(floatingUserHeaderCell); + this.graderRegion.append(floatingUserHeaderRow); // Store a reference to this for later - we use it in the event handlers. - this.userColumnHeader = floatingUserCell; + this.userColumnHeader = floatingUserHeaderRow; }, /** @@ -711,7 +707,7 @@ FloatingHeaders.prototype = { var gradeHeaders = Y.all('#user-grades tr.heading .cell'); // Generate a floating headers - var floatingGradeHeaders = Y.Node.create(''); + var floatingGradeHeaders = Y.Node.create(''); var coordinates = this._getRelativeXY(this.headerRow); @@ -722,16 +718,16 @@ FloatingHeaders.prototype = { gradeHeaders.each(function(node) { var nodepos = this._getRelativeXY(node)[0]; - var newnode = Y.Node.create('
'); + var newnode = Y.Node.create('
'); newnode.append(node.getHTML()) - .addClass(node.getAttribute('class')) - .setData('itemid', node.getData('itemid')) - .setStyles({ - height: node.getComputedStyle(HEIGHT), - left: (nodepos - gradeHeadersOffset) + 'px', - position: 'absolute', - width: node.getComputedStyle(WIDTH) - }); + .setAttribute('class', node.getAttribute('class')) + .setData('itemid', node.getData('itemid')) + .setStyles({ + height: node.getComputedStyle(HEIGHT), + left: (nodepos - gradeHeadersOffset) + 'px', + position: 'absolute', + width: node.getComputedStyle(WIDTH) + }); // Sum up total widths - these are used in the container styles. // Use the offsetHeight and Width here as this contains the @@ -776,24 +772,27 @@ FloatingHeaders.prototype = { var footerCells = this.tableFooterRow.all('.cell'); // Create a container. - var floatingGraderFooter = Y.Node.create(''); + var floatingGraderFooter = Y.Node.create(''); var footerWidth = 0; var coordinates = this._getRelativeXY(this.tableFooterRow); var footerRowOffset = coordinates[0]; + var floatingGraderFooterHeight = 0; // Copy cell content. footerCells.each(function(node) { - var newnode = Y.Node.create(''); + var newnode = Y.Node.create('
'); var nodepos = this._getRelativeXY(node)[0]; - newnode.set('innerHTML', node.getHTML()); - newnode.setStyles({ - height: this._getHeight(node), - left: (nodepos - footerRowOffset) + 'px', - position: 'absolute', - width: this._getWidth(node) - }); + newnode.set('innerHTML', node.getHTML()) + .setAttribute('class', node.getAttribute('class')) + .setStyles({ + height: node.getComputedStyle(HEIGHT), + left: (nodepos - footerRowOffset) + 'px', + position: 'absolute', + width: node.getComputedStyle(WIDTH) + }); floatingGraderFooter.append(newnode); + floatingGraderFooterHeight = node.get(OFFSETHEIGHT); footerWidth += parseInt(node.get(OFFSETWIDTH), 10); }, this); @@ -805,16 +804,16 @@ FloatingHeaders.prototype = { button.on('click', function() { updateButton.simulate('click'); }); - floatingGraderFooter.one('.gradebook-footer-cell').append(button); + floatingGraderFooter.one('div').append(button); } // Position the row floatingGraderFooter.setStyles({ position: 'absolute', left: coordinates[0] + 'px', - bottom: 0, - height: this._getHeight(this.tableFooterRow), - width: footerWidth + 'px', + bottom: '1px', + height: floatingGraderFooterHeight + 'px', + width: footerWidth + 'px' }); // Append to the grader region. @@ -841,13 +840,16 @@ FloatingHeaders.prototype = { footerStyles = {}, coord = 0, userCellWidth = 0, - floatUserColumn = false, // Whether or not the user column should float. floatingUserTriggerPoint = 0, // The X position at which the floating should start. - floatingUserRelativePoint = 0; // The point to use when calculating the new position. + floatingUserRelativePoint = 0, // The point to use when calculating the new position. + headerFloats = false, + userFloats = false, + footerFloats = false; // Header position. gradeItemHeadingContainerStyles.left = this._getRelativeXFromX(this.headerRow.getX()); if (Y.config.win.pageYOffset + this.pageHeaderHeight > this.headerRowTop) { + headerFloats = true; if (Y.config.win.pageYOffset + this.pageHeaderHeight < this.lastUserCellTop) { coord = this._getRelativeYFromY(Y.config.win.pageYOffset + this.pageHeaderHeight); gradeItemHeadingContainerStyles.top = coord + 'px'; @@ -858,6 +860,7 @@ FloatingHeaders.prototype = { userColumnHeaderStyles.top = coord + 'px'; } } else { + headerFloats = false; coord = this._getRelativeYFromY(this.headerRowTop); gradeItemHeadingContainerStyles.top = coord + 'px'; userColumnHeaderStyles.top = coord + 'px'; @@ -868,13 +871,13 @@ FloatingHeaders.prototype = { userCellWidth = this.firstUserCell.get(OFFSETWIDTH); floatingUserTriggerPoint = Y.config.win.innerWidth + Y.config.win.pageXOffset; floatingUserRelativePoint = floatingUserTriggerPoint - userCellWidth; - floatUserColumn = floatingUserTriggerPoint < (this.firstUserCellLeft + userCellWidth); + userFloats = floatingUserTriggerPoint < (this.firstUserCellLeft + userCellWidth); } else { floatingUserTriggerPoint = Y.config.win.pageXOffset; floatingUserRelativePoint = floatingUserTriggerPoint; - floatUserColumn = floatingUserTriggerPoint > this.firstUserCellLeft; + userFloats = floatingUserTriggerPoint > this.firstUserCellLeft; } - if (floatUserColumn) { + if (userFloats) { coord = this._getRelativeXFromX(floatingUserRelativePoint); userColumnStyles.left = coord + 'px'; userColumnHeaderStyles.left = coord + 'px'; @@ -898,17 +901,40 @@ FloatingHeaders.prototype = { if (bottomScrollPosition < footerBottomPosition && bottomScrollPosition > this.firstUserCellBottom) { // We have not scrolled below the footer, nor above the first row. footerStyles.bottom = Math.ceil(footerBottomPosition - bottomScrollPosition) + 'px'; + footerFloats = true; } else { // The footer should not float any more. footerStyles.bottom = 0; + footerFloats = false; } } - // Finally, apply the styles. + // Apply the styles. this.gradeItemHeadingContainer.setStyles(gradeItemHeadingContainerStyles); this.userColumnHeader.setStyles(userColumnHeaderStyles); this.userColumn.setStyles(userColumnStyles); this.footerRow.setStyles(footerStyles); + + // Mark the elements as floating, or not. + if (headerFloats) { + this.gradeItemHeadingContainer.addClass(CSS.FLOATING); + } else { + this.gradeItemHeadingContainer.removeClass(CSS.FLOATING); + } + + if (userFloats) { + this.userColumnHeader.addClass(CSS.FLOATING); + this.userColumn.addClass(CSS.FLOATING); + } else { + this.userColumnHeader.removeClass(CSS.FLOATING); + this.userColumn.removeClass(CSS.FLOATING); + } + + if (footerFloats) { + this.footerRow.addClass(CSS.FLOATING); + } else { + this.footerRow.removeClass(CSS.FLOATING); + } }, /** @@ -927,8 +953,8 @@ FloatingHeaders.prototype = { // Resize user cells. var userWidth = this.firstUserCell.getComputedStyle(WIDTH); var userCells = Y.all(SELECTORS.USERCELL); - this.userColumnHeader.setStyle('width', userWidth); - this.userColumn.all('.gradebook-user-cell').each(function(cell, idx) { + this.userColumnHeader.one('.cell').setStyle('width', userWidth); + this.userColumn.all('.cell').each(function(cell, idx) { cell.setStyles({ width: userWidth, height: userCells.item(idx).getComputedStyle(HEIGHT) @@ -937,8 +963,8 @@ FloatingHeaders.prototype = { // Resize headers & footers. // This is an expensive operation, not expected to happen often. - var headers = this.gradeItemHeadingContainer.all(SELECTORS.HEADERCELL); - var resizedcells = Y.all('#user-grades .heading .cell'); + var headers = this.gradeItemHeadingContainer.all('.cell'); + var resizedcells = Y.all(SELECTORS.HEADERCELLS); var headeroffsetleft = this.headerRow.getX(); var newcontainerwidth = 0; @@ -953,60 +979,25 @@ FloatingHeaders.prototype = { headercell.setStyles(styles); }); - var footers = Y.all('#gradebook-footer-container .gradebook-footer-cell'); - if (footers.size() !== 0) { - var resizedavgcells = Y.all('#user-grades .avg .cell'); + if (this.footerRow) { + var footers = this.footerRow.all('.cell'); + if (footers.size() !== 0) { + var resizedavgcells = Y.all(SELECTORS.FOOTERCELLS); - resizedavgcells.each(function(cell, idx) { - var footercell = footers.item(idx); - var styles = { - width: cell.getComputedStyle(WIDTH), - left: cell.getX() - headeroffsetleft + 'px' - }; - footercell.setStyles(styles); - }); + resizedavgcells.each(function(cell, idx) { + var footercell = footers.item(idx); + var styles = { + width: cell.getComputedStyle(WIDTH), + left: cell.getX() - headeroffsetleft + 'px' + }; + footercell.setStyles(styles); + }); + } } this.gradeItemHeadingContainer.setStyle('width', newcontainerwidth); - }, - - /** - * Determine the height of the specified Node. - * - * With IE, the height used when setting a height is the offsetHeight. - * All other browsers set this as this inner height. - * - * @method _getHeight - * @protected - * @param {Node} node - * @return String - */ - _getHeight: function(node) { - if (Y.UA.ie) { - return node.get(OFFSETHEIGHT) + 'px'; - } else { - return node.getComputedStyle(HEIGHT); - } - }, - - /** - * Determine the width of the specified Node. - * - * With IE, the width used when setting a width is the offsetWidth. - * All other browsers set this as this inner width. - * - * @method _getWidth - * @protected - * @param {Node} node - * @return String - */ - _getWidth: function(node) { - if (Y.UA.ie) { - return node.get(OFFSETWIDTH) + 'px'; - } else { - return node.getComputedStyle(WIDTH); - } } + }; Y.Base.mix(Y.M.gradereport_grader.ReportTable, [FloatingHeaders]); diff --git a/grade/report/grader/yui/build/moodle-gradereport_grader-gradereporttable/moodle-gradereport_grader-gradereporttable-min.js b/grade/report/grader/yui/build/moodle-gradereport_grader-gradereporttable/moodle-gradereport_grader-gradereporttable-min.js index 2e44446ef98..3943be15b73 100644 --- a/grade/report/grader/yui/build/moodle-gradereport_grader-gradereporttable/moodle-gradereport_grader-gradereporttable-min.js +++ b/grade/report/grader/yui/build/moodle-gradereport_grader-gradereporttable/moodle-gradereport_grader-gradereporttable-min.js @@ -1,2 +1,2 @@ -YUI.add("moodle-gradereport_grader-gradereporttable",function(e,t){function i(){i.superclass.constructor.apply(this,arguments)}function u(){}function d(){}function v(){}var n={FOOTERROW:"#user-grades .avg",GRADECELL:"td.grade",GRADERTABLE:".gradeparent table",GRADEPARENT:".gradeparent",HEADERCELL:".gradebook-header-cell",HEADERROW:"#user-grades tr.heading",STUDENTHEADER:"#studentheader",USERCELL:"#user-grades .user.cell"},r={OVERRIDDEN:"overridden",TOOLTIPACTIVE:"tooltipactive"};e.extend(i,e.Base,{_eventHandles:[],graderTable:null,initializer:function(){this.graderRegion=e.one(n.GRADEPARENT),this.graderTable=e.one(n.GRADERTABLE),this.setupFloatingHeaders(),this.setupTooltips()},getGradeUserName:function(e){var t=e.ancestor("tr"),n=t.one("th.user .username");return n?n.get("text"):""},getGradeItemName:function(t){var n=e.one("th.item[data-itemid='"+t.getData("itemid")+"']");return n?n.get("text"):""},getGradeFeedback:function(e){return e.getData("feedback")}}),e.namespace("M.gradereport_grader").ReportTable=i,e.namespace("M.gradereport_grader").init=function(t){return new e.M.gradereport_grader.ReportTable(t)};var s="vmarked",o="hmarked";u.ATTRS={};var a="th.user, th.userreport, th.userfield, .gradebook-user-cell",f="tr[data-itemid] th.item, .gradebook-header-cell";u.prototype={setupHighlighter:function(){return this._eventHandles.push(this.graderRegion.delegate("click",this._highlightUser,a,this),this.graderRegion.delegate("click",this._highlightColumn,f,this)),this},_highlightColumn:function(e){var t=e.target.getData("itemid");if(typeof t=="undefined")return;this.graderRegion.all('td.cell[data-itemid="'+t+'"]').toggleClass(s)},_highlightUser:function(e){var t=e.target.ancestor("[data-uid]",!0),n,r;t&&(r=t.getData("uid"));if(typeof r=="undefined")return;n=this.graderRegion.one('tr[data-uid="'+r+'"]'),n&&n.toggleClass(o)}},e.Base.mix(e.M.gradereport_grader.ReportTable,[u]);var l="height",c="width",h="offsetWidth",p="offsetHeight";d.ATTRS={},d.prototype={pageHeaderHeight:0,container:null,headerCell:null,headerRow:null,firstUserCell:null,tableFooterRow:null,footerRow:null,gradeItemHeadingContainer:null,userColumnHeader:null,userColumn:null,firstUserCellBottom:0,firstUserCellLeft:0,lastUserCellTop:0,_eventHandles:[],setupFloatingHeaders:function(){return this.firstUserCell=e.one(n.USERCELL),this.container=e.one(n.GRADEPARENT),this.firstUserCell?(this._setupFloatingUserColumn(),this._setupFloatingUserHeader(),this._setupFloatingAssignmentHeaders(),this._setupFloatingAssignmentFooter(),this._calculateCellPositions(),this._handleScrollEvent(),this._setupEventHandlers(),this):this},_calculateCellPositions:function(){this.headerRowTop=this.headerRow.getY(),this.tableFooterRow&&(this.footerRowPosition=this.tableFooterRow.getY());var t=e.all(n.USERCELL);this.firstUserCellLeft=this.firstUserCell.getX();if(t.size()>1){var r=t.item(1);this.firstUserCellBottom=r.getY()+parseInt(r.getComputedStyle(l),10),this.lastUserCellTop=t.item(t.size()-2).getY()}else{var i=t.item(0);this.lastUserCellTop=i.getY(),this.tableFooterRow?this.firstUserCellBottom=this.footerRowPosition+parseInt(this.tableFooterRow.getComputedStyle(l),10):this.firstUserCellBottom=i.getY()+i.get("offsetHeight")}var s=e.one("header");this.pageHeaderHeight=0,s&&s.getComputedStyle("position")==="fixed"&&(this.pageHeaderHeight=s.get(p))},_getRelativeXY:function(e){return this._getRelativeXYFromXY(e.getX(),e.getY())},_getRelativeXYFromXY:function(e,t){var n=this.container.getXY();return[Math.floor(e-n[0]),Math.floor(t-n[1])]},_getRelativeXFromX:function(e){return this._getRelativeXYFromXY(e,0)[0]},_getRelativeYFromY:function(e){return this._getRelativeXYFromXY(0,e)[1]},_getScrollBarHeight:function(){return e.UA.ie&&e.UA.ie>=10?0:e.config.doc.body.scrollWidth>e.config.doc.body.clientWidth?e.DOM.getScrollbarWidth():0},_setupEventHandlers:function(){this._eventHandles.push(e.one(e.config.win).on("scroll",this._handleScrollEvent,this),e.one(e.config.win).on("resize",this._handleResizeEvent,this),e.one(e.config.win).on("orientationchange",this._handleResizeEvent,this))},_setupFloatingUserColumn:function(){var t=e.all(n.USERCELL),r=e.Node.create(''),i=this._getRelativeXY(this.firstUserCell);t.each(function(t){var n=e.Node.create(''),i,s;if(e.UA.ie){var o=parseInt(t.getComputedStyle("borderBottomWidth"),10),u=parseInt(t.getComputedStyle("borderTopWidth"),10),a=parseInt(t.getComputedStyle("borderLeftWidth"),10),f=parseInt(t.getComputedStyle("borderRightWidth"),10),d=parseInt(t.getComputedStyle("paddingBottom"),10),v=parseInt(t.getComputedStyle("paddingTop"),10),m=parseInt(t.getComputedStyle("paddingLeft"),10),g=parseInt(t.getComputedStyle("paddingRight"),10);i=t.get(p)-o-u-d-v,s=t.get(h)-a-f-m-g}else i=t.getComputedStyle(l),s=t.getComputedStyle(c);n.set("innerHTML",t.get("innerHTML")).setAttribute("data-uid",t.ancestor("tr").getData("uid")).setStyles({height:i,width:s}),r.appendChild(n)},this),r.setStyles({left:i[0]+"px",position:"absolute",top:i[1]+"px"}),this.graderRegion.append(r),this.userColumn=r},_setupFloatingUserHeader:function(){this.headerRow=e.one(n.HEADERROW),this.headerCell=e.one(n.STUDENTHEADER);var t=e.Node.create(''),r=this._getRelativeXY(this.firstUserCell),i=this._getRelativeXY(this.headerRow);t.set("innerHTML",this.headerCell.getHTML()),t.setStyles({height:this.headerCell.getComputedStyle(l),left:r[0]+"px",position:"absolute",top:i[1]+"px",width:this.firstUserCell.getComputedStyle(c)}),this.graderRegion.append(t),this.userColumnHeader=t},_setupFloatingAssignmentHeaders:function(){this.headerRow=e.one("#user-grades tr.heading");var t=e.all("#user-grades tr.heading .cell"),n=e.Node.create(''),r=this._getRelativeXY(this.headerRow),i=0,s=0 -,o=r[0];t.each(function(t){var r=this._getRelativeXY(t)[0],u=e.Node.create('
');u.append(t.getHTML()).addClass(t.getAttribute("class")).setData("itemid",t.getData("itemid")).setStyles({height:t.getComputedStyle(l),left:r-o+"px",position:"absolute",width:t.getComputedStyle(c)}),i+=parseInt(t.get(h),10),s=t.get(p),n.appendChild(u)},this),n.setStyles({height:s+"px",left:r[0]+"px",position:"absolute",top:r[1]+"px",width:i+"px"}),this.userColumnHeader.insert(n,"before"),this.gradeItemHeadingContainer=n},_setupFloatingAssignmentFooter:function(){this.tableFooterRow=e.one("#user-grades .avg");if(!this.tableFooterRow)return;var t=this.tableFooterRow.all(".cell"),n=e.Node.create(''),r=0,i=this._getRelativeXY(this.tableFooterRow),s=i[0];t.each(function(t){var i=e.Node.create(''),o=this._getRelativeXY(t)[0];i.set("innerHTML",t.getHTML()),i.setStyles({height:this._getHeight(t),left:o-s+"px",position:"absolute",width:this._getWidth(t)}),n.append(i),r+=parseInt(t.get(h),10)},this);var o=e.one("#gradersubmit");if(o){var u=e.Node.create('");u.on("click",function(){o.simulate("click")}),n.one(".gradebook-footer-cell").append(u)}n.setStyles({position:"absolute",left:i[0]+"px",bottom:0,height:this._getHeight(this.tableFooterRow),width:r+"px"}),this.graderRegion.append(n),this.footerRow=n},_handleScrollEvent:function(){var t={},n={},r={},i={},s=0,o=0,u=!1,a=0,f=0;t.left=this._getRelativeXFromX(this.headerRow.getX()),e.config.win.pageYOffset+this.pageHeaderHeight>this.headerRowTop?e.config.win.pageYOffset+this.pageHeaderHeightthis.firstUserCellLeft),u?(s=this._getRelativeXFromX(f),r.left=s+"px",n.left=s+"px"):(s=this._getRelativeXFromX(this.firstUserCellLeft),r.left=s+"px",n.left=s+"px");if(this.footerRow){i.left=this._getRelativeXFromX(this.headerRow.getX());var c=e.config.win.innerHeight,p=e.config.win.pageYOffset,d=c-this._getScrollBarHeight()+p,v=parseInt(this.footerRow.getComputedStyle(l),10),m=v+this.footerRowPosition;dthis.firstUserCellBottom?i.bottom=Math.ceil(m-d)+"px":i.bottom=0}this.gradeItemHeadingContainer.setStyles(t),this.userColumnHeader.setStyles(n),this.userColumn.setStyles(r),this.footerRow.setStyles(i)},_handleResizeEvent:function(){this._calculateCellPositions(),this._handleScrollEvent();var t=this.firstUserCell.getComputedStyle(c),r=e.all(n.USERCELL);this.userColumnHeader.setStyle("width",t),this.userColumn.all(".gradebook-user-cell").each(function(e,n){e.setStyles({width:t,height:r.item(n).getComputedStyle(l)})},this);var i=this.gradeItemHeadingContainer.all(n.HEADERCELL),s=e.all("#user-grades .heading .cell"),o=this.headerRow.getX(),u=0;s.each(function(e,t){var n=i.item(t);u+=e.get(h);var r={width:e.getComputedStyle(c),left:e.getX()-o+"px"};n.setStyles(r)});var a=e.all("#gradebook-footer-container .gradebook-footer-cell");if(a.size()!==0){var f=e.all("#user-grades .avg .cell");f.each(function(e,t){var n=a.item(t),r={width:e.getComputedStyle(c),left:e.getX()-o+"px"};n.setStyles(r)})}this.gradeItemHeadingContainer.setStyle("width",u)},_getHeight:function(t){return e.UA.ie?t.get(p)+"px":t.getComputedStyle(l)},_getWidth:function(t){return e.UA.ie?t.get(h)+"px":t.getComputedStyle(c)}},e.Base.mix(e.M.gradereport_grader.ReportTable,[d]),v.ATTRS={};var m='';v.prototype={_tooltip:null,_tooltipBoundingBox:null,_tooltipTemplate:null,setupTooltips:function(){return this._eventHandles.push(this.graderTable.delegate("hover",this._showTooltip,this._hideTooltip,n.GRADECELL,this),this.graderTable.delegate("click",this._toggleTooltip,n.GRADECELL,this)),this},_getTooltip:function(){return this._tooltip||(this._tooltip=new e.Overlay({visible:!1,render:e.one(n.GRADEPARENT)}),this._tooltipBoundingBox=this._tooltip.get("boundingBox"),this._tooltipTemplate=e.Handlebars.compile(m),this._tooltipBoundingBox.addClass("grader-information-tooltip")),this._tooltip},_showTooltip:function(e){var t=e.currentTarget,n=this._getTooltip();n.set("bodyContent",this._tooltipTemplate({cellid:t.get("id"),username:this.getGradeUserName(t),itemname:this.getGradeItemName(t),feedback:this.getGradeFeedback(t),overridden:t.hasClass(r.OVERRIDDEN)?r.OVERRIDDEN:""})).set("xy",[t.getX()+t.get("offsetWidth")/2,t.getY()+t.get("offsetHeight")/2]).show(),e.currentTarget.addClass(r.TOOLTIPACTIVE)},_hideTooltip:function(e){if(e.relatedTarget&&this._tooltipBoundingBox&&this._tooltipBoundingBox.contains(e.relatedTarget))return;this._tooltip&&(e.currentTarget.removeClass(r.TOOLTIPACTIVE),this._tooltip.hide())},_toggleTooltip:function(e){e.currentTarget.hasClass(r.TOOLTIPACTIVE)?this._hideTooltip(e):this._showTooltip(e)}},e.Base.mix(e.M.gradereport_grader.ReportTable,[v])},"@VERSION@",{requires:["base","node","event","handlebars","overlay","event-hover","node-event-simulate"]}); +YUI.add("moodle-gradereport_grader-gradereporttable",function(e,t){function i(){i.superclass.constructor.apply(this,arguments)}function u(){}function d(){}function v(){}var n={FOOTERCELLS:"#user-grades .avg .cell",FOOTERROW:"#user-grades .avg",GRADECELL:"td.grade",GRADERTABLE:".gradeparent table",GRADEPARENT:".gradeparent",HEADERCELLS:"#user-grades .heading .cell",HEADERCELL:".gradebook-header-cell",HEADERROW:"#user-grades tr.heading",STUDENTHEADER:"#studentheader",USERCELL:"#user-grades .user.cell"},r={OVERRIDDEN:"overridden",TOOLTIPACTIVE:"tooltipactive"};e.extend(i,e.Base,{_eventHandles:[],graderTable:null,initializer:function(){this.graderRegion=e.one(n.GRADEPARENT),this.graderTable=e.one(n.GRADERTABLE),this.setupFloatingHeaders(),this.setupTooltips()},getGradeUserName:function(e){var t=e.ancestor("tr"),n=t.one("th.user .username");return n?n.get("text"):""},getGradeItemName:function(t){var n=e.one("th.item[data-itemid='"+t.getData("itemid")+"']");return n?n.get("text"):""},getGradeFeedback:function(e){return e.getData("feedback")}}),e.namespace("M.gradereport_grader").ReportTable=i,e.namespace("M.gradereport_grader").init=function(t){return new e.M.gradereport_grader.ReportTable(t)};var s="vmarked",o="hmarked";u.ATTRS={};var a=".user.cell, th.userreport, th.userfield",f="tr[data-itemid] th.item, .heading .cell";u.prototype={setupHighlighter:function(){return this._eventHandles.push(this.graderRegion.delegate("click",this._highlightUser,a,this),this.graderRegion.delegate("click",this._highlightColumn,f,this)),this},_highlightColumn:function(e){var t=e.target.getData("itemid");if(typeof t=="undefined")return;this.graderRegion.all('td.cell[data-itemid="'+t+'"]').toggleClass(s)},_highlightUser:function(e){var t=e.target.ancestor("[data-uid]",!0),n,r;t&&(r=t.getData("uid"));if(typeof r=="undefined")return;n=this.graderRegion.one('tr[data-uid="'+r+'"]'),n&&n.toggleClass(o)}},e.Base.mix(e.M.gradereport_grader.ReportTable,[u]);var l="height",c="width",h="offsetWidth",p="offsetHeight";r.FLOATING="floating",d.ATTRS={},d.prototype={pageHeaderHeight:0,container:null,headerCell:null,headerRow:null,firstUserCell:null,tableFooterRow:null,footerRow:null,gradeItemHeadingContainer:null,userColumnHeader:null,userColumn:null,firstUserCellBottom:0,firstUserCellLeft:0,lastUserCellTop:0,_eventHandles:[],setupFloatingHeaders:function(){return this.firstUserCell=e.one(n.USERCELL),this.container=e.one(n.GRADEPARENT),this.firstUserCell?(this._setupFloatingUserColumn(),this._setupFloatingUserHeader(),this._setupFloatingAssignmentHeaders(),this._setupFloatingAssignmentFooter(),this._calculateCellPositions(),this._handleScrollEvent(),this._setupEventHandlers(),this):this},_calculateCellPositions:function(){this.headerRowTop=this.headerRow.getY(),this.tableFooterRow&&(this.footerRowPosition=this.tableFooterRow.getY());var t=e.all(n.USERCELL);this.firstUserCellLeft=this.firstUserCell.getX();if(t.size()>1){var r=t.item(1);this.firstUserCellBottom=r.getY()+parseInt(r.getComputedStyle(l),10),this.lastUserCellTop=t.item(t.size()-2).getY()}else{var i=t.item(0);this.lastUserCellTop=i.getY(),this.tableFooterRow?this.firstUserCellBottom=this.footerRowPosition+parseInt(this.tableFooterRow.getComputedStyle(l),10):this.firstUserCellBottom=i.getY()+i.get("offsetHeight")}var s=e.one("header");this.pageHeaderHeight=0,s&&s.getComputedStyle("position")==="fixed"&&(this.pageHeaderHeight=s.get(p))},_getRelativeXY:function(e){return this._getRelativeXYFromXY(e.getX(),e.getY())},_getRelativeXYFromXY:function(e,t){var n=this.container.getXY();return[e-n[0],t-n[1]]},_getRelativeXFromX:function(e){return this._getRelativeXYFromXY(e,0)[0]},_getRelativeYFromY:function(e){return this._getRelativeXYFromXY(0,e)[1]},_getScrollBarHeight:function(){return e.UA.ie&&e.UA.ie>=10?0:e.config.doc.body.scrollWidth>e.config.doc.body.clientWidth?e.DOM.getScrollbarWidth():0},_setupEventHandlers:function(){this._eventHandles.push(e.one(e.config.win).on("scroll",this._handleScrollEvent,this),e.one(e.config.win).on("resize",this._handleResizeEvent,this),e.one(e.config.win).on("orientationchange",this._handleResizeEvent,this))},_setupFloatingUserColumn:function(){var t=e.all(n.USERCELL),r=e.Node.create(''),i=this._getRelativeXY(this.firstUserCell);t.each(function(t){var n=e.Node.create("
");n.set("innerHTML",t.get("innerHTML")).setAttribute("class",t.getAttribute("class")).setAttribute("data-uid",t.ancestor("tr").getData("uid")).setStyles({height:t.getComputedStyle(l),width:t.getComputedStyle(c)}),r.appendChild(n)},this),r.setStyles({left:i[0]+"px",position:"absolute",top:i[1]+"px"}),this.graderRegion.append(r),this.userColumn=r},_setupFloatingUserHeader:function(){this.headerRow=e.one(n.HEADERROW),this.headerCell=e.one(n.STUDENTHEADER);var t=e.Node.create(''),r=e.Node.create("
"),i=this._getRelativeXY(this.headerCell)[0],s=this._getRelativeXY(this.headerRow);gradeHeadersOffset=s[0],r.set("innerHTML",this.headerCell.getHTML()).setAttribute("class",this.headerCell.getAttribute("class")).setStyles({width:this.firstUserCell.getComputedStyle(c),left:i-gradeHeadersOffset+"px"}),t.setStyles({left:s[0]+"px",position:"absolute",top:s[1]+"px"}),t.append(r),this.graderRegion.append(t),this.userColumnHeader=t},_setupFloatingAssignmentHeaders:function(){this.headerRow=e.one("#user-grades tr.heading");var t=e.all("#user-grades tr.heading .cell"),n=e.Node.create(''),r=this._getRelativeXY(this.headerRow),i=0,s=0,o=r[0];t.each(function(t){var r=this._getRelativeXY(t)[0],u=e.Node.create("
");u.append(t.getHTML()).setAttribute("class",t.getAttribute("class")).setData("itemid",t.getData("itemid")).setStyles({height:t.getComputedStyle(l),left:r-o+"px",position:"absolute",width:t.getComputedStyle(c)}),i+=parseInt(t.get(h),10),s=t.get(p),n.appendChild +(u)},this),n.setStyles({height:s+"px",left:r[0]+"px",position:"absolute",top:r[1]+"px",width:i+"px"}),this.userColumnHeader.insert(n,"before"),this.gradeItemHeadingContainer=n},_setupFloatingAssignmentFooter:function(){this.tableFooterRow=e.one("#user-grades .avg");if(!this.tableFooterRow)return;var t=this.tableFooterRow.all(".cell"),n=e.Node.create(''),r=0,i=this._getRelativeXY(this.tableFooterRow),s=i[0],o=0;t.each(function(t){var i=e.Node.create("
"),u=this._getRelativeXY(t)[0];i.set("innerHTML",t.getHTML()).setAttribute("class",t.getAttribute("class")).setStyles({height:t.getComputedStyle(l),left:u-s+"px",position:"absolute",width:t.getComputedStyle(c)}),n.append(i),o=t.get(p),r+=parseInt(t.get(h),10)},this);var u=e.one("#gradersubmit");if(u){var a=e.Node.create('");a.on("click",function(){u.simulate("click")}),n.one("div").append(a)}n.setStyles({position:"absolute",left:i[0]+"px",bottom:"1px",height:o+"px",width:r+"px"}),this.graderRegion.append(n),this.footerRow=n},_handleScrollEvent:function(){var t={},n={},i={},s={},o=0,u=0,a=0,f=0,c=!1,p=!1,d=!1;t.left=this._getRelativeXFromX(this.headerRow.getX()),e.config.win.pageYOffset+this.pageHeaderHeight>this.headerRowTop?(c=!0,e.config.win.pageYOffset+this.pageHeaderHeightthis.firstUserCellLeft),p?(o=this._getRelativeXFromX(f),i.left=o+"px",n.left=o+"px"):(o=this._getRelativeXFromX(this.firstUserCellLeft),i.left=o+"px",n.left=o+"px");if(this.footerRow){s.left=this._getRelativeXFromX(this.headerRow.getX());var v=e.config.win.innerHeight,m=e.config.win.pageYOffset,g=v-this._getScrollBarHeight()+m,y=parseInt(this.footerRow.getComputedStyle(l),10),b=y+this.footerRowPosition;gthis.firstUserCellBottom?(s.bottom=Math.ceil(b-g)+"px",d=!0):(s.bottom=0,d=!1)}this.gradeItemHeadingContainer.setStyles(t),this.userColumnHeader.setStyles(n),this.userColumn.setStyles(i),this.footerRow.setStyles(s),c?this.gradeItemHeadingContainer.addClass(r.FLOATING):this.gradeItemHeadingContainer.removeClass(r.FLOATING),p?(this.userColumnHeader.addClass(r.FLOATING),this.userColumn.addClass(r.FLOATING)):(this.userColumnHeader.removeClass(r.FLOATING),this.userColumn.removeClass(r.FLOATING)),d?this.footerRow.addClass(r.FLOATING):this.footerRow.removeClass(r.FLOATING)},_handleResizeEvent:function(){this._calculateCellPositions(),this._handleScrollEvent();var t=this.firstUserCell.getComputedStyle(c),r=e.all(n.USERCELL);this.userColumnHeader.one(".cell").setStyle("width",t),this.userColumn.all(".cell").each(function(e,n){e.setStyles({width:t,height:r.item(n).getComputedStyle(l)})},this);var i=this.gradeItemHeadingContainer.all(".cell"),s=e.all(n.HEADERCELLS),o=this.headerRow.getX(),u=0;s.each(function(e,t){var n=i.item(t);u+=e.get(h);var r={width:e.getComputedStyle(c),left:e.getX()-o+"px"};n.setStyles(r)});if(this.footerRow){var a=this.footerRow.all(".cell");if(a.size()!==0){var f=e.all(n.FOOTERCELLS);f.each(function(e,t){var n=a.item(t),r={width:e.getComputedStyle(c),left:e.getX()-o+"px"};n.setStyles(r)})}}this.gradeItemHeadingContainer.setStyle("width",u)}},e.Base.mix(e.M.gradereport_grader.ReportTable,[d]),v.ATTRS={};var m='';v.prototype={_tooltip:null,_tooltipBoundingBox:null,_tooltipTemplate:null,setupTooltips:function(){return this._eventHandles.push(this.graderTable.delegate("hover",this._showTooltip,this._hideTooltip,n.GRADECELL,this),this.graderTable.delegate("click",this._toggleTooltip,n.GRADECELL,this)),this},_getTooltip:function(){return this._tooltip||(this._tooltip=new e.Overlay({visible:!1,render:e.one(n.GRADEPARENT)}),this._tooltipBoundingBox=this._tooltip.get("boundingBox"),this._tooltipTemplate=e.Handlebars.compile(m),this._tooltipBoundingBox.addClass("grader-information-tooltip")),this._tooltip},_showTooltip:function(e){var t=e.currentTarget,n=this._getTooltip();n.set("bodyContent",this._tooltipTemplate({cellid:t.get("id"),username:this.getGradeUserName(t),itemname:this.getGradeItemName(t),feedback:this.getGradeFeedback(t),overridden:t.hasClass(r.OVERRIDDEN)?r.OVERRIDDEN:""})).set("xy",[t.getX()+t.get("offsetWidth")/2,t.getY()+t.get("offsetHeight")/2]).show(),e.currentTarget.addClass(r.TOOLTIPACTIVE)},_hideTooltip:function(e){if(e.relatedTarget&&this._tooltipBoundingBox&&this._tooltipBoundingBox.contains(e.relatedTarget))return;this._tooltip&&(e.currentTarget.removeClass(r.TOOLTIPACTIVE),this._tooltip.hide())},_toggleTooltip:function(e){e.currentTarget.hasClass(r.TOOLTIPACTIVE)?this._hideTooltip(e):this._showTooltip(e)}},e.Base.mix(e.M.gradereport_grader.ReportTable,[v])},"@VERSION@",{requires:["base","node","event","handlebars","overlay","event-hover","node-event-simulate"]}); diff --git a/grade/report/grader/yui/build/moodle-gradereport_grader-gradereporttable/moodle-gradereport_grader-gradereporttable.js b/grade/report/grader/yui/build/moodle-gradereport_grader-gradereporttable/moodle-gradereport_grader-gradereporttable.js index f47c3a49aa4..eda07f7cf58 100644 --- a/grade/report/grader/yui/build/moodle-gradereport_grader-gradereporttable/moodle-gradereport_grader-gradereporttable.js +++ b/grade/report/grader/yui/build/moodle-gradereport_grader-gradereporttable/moodle-gradereport_grader-gradereporttable.js @@ -30,10 +30,12 @@ YUI.add('moodle-gradereport_grader-gradereporttable', function (Y, NAME) { */ var SELECTORS = { + FOOTERCELLS: '#user-grades .avg .cell', FOOTERROW: '#user-grades .avg', GRADECELL: 'td.grade', GRADERTABLE: '.gradeparent table', GRADEPARENT: '.gradeparent', + HEADERCELLS: '#user-grades .heading .cell', HEADERCELL: '.gradebook-header-cell', HEADERROW: '#user-grades tr.heading', STUDENTHEADER: '#studentheader', @@ -177,8 +179,8 @@ function Highlighter() {} Highlighter.ATTRS= { }; -var ROWFIELDS = 'th.user, th.userreport, th.userfield, .gradebook-user-cell', - COLFIELDS = 'tr[data-itemid] th.item, .gradebook-header-cell'; +var ROWFIELDS = '.user.cell, th.userreport, th.userfield', + COLFIELDS = 'tr[data-itemid] th.item, .heading .cell'; Highlighter.prototype = { /** @@ -280,6 +282,8 @@ var HEIGHT = 'height', OFFSETWIDTH = 'offsetWidth', OFFSETHEIGHT = 'offsetHeight'; +CSS.FLOATING = 'floating'; + function FloatingHeaders() {} FloatingHeaders.ATTRS= { @@ -540,7 +544,7 @@ FloatingHeaders.prototype = { */ _getRelativeXYFromXY: function(x, y) { var parentXY = this.container.getXY(); - return [Math.floor(x - parentXY[0]), Math.floor(y - parentXY[1])]; + return [x - parentXY[0], y - parentXY[1]]; }, /** @@ -612,7 +616,7 @@ FloatingHeaders.prototype = { var userColumn = Y.all(SELECTORS.USERCELL), // Create a floating table. - floatingUserColumn = Y.Node.create(''), + floatingUserColumn = Y.Node.create(''), // Get the XY for the floating element. coordinates = this._getRelativeXY(this.firstUserCell); @@ -620,32 +624,13 @@ FloatingHeaders.prototype = { // Generate the new fields. userColumn.each(function(node) { // Create and configure the new container. - var containerNode = Y.Node.create(''), - height, - width; - - // IE madness... - if (Y.UA.ie) { - var bb = parseInt(node.getComputedStyle('borderBottomWidth'), 10), - bt = parseInt(node.getComputedStyle('borderTopWidth'), 10), - bl = parseInt(node.getComputedStyle('borderLeftWidth'), 10), - br = parseInt(node.getComputedStyle('borderRightWidth'), 10), - pb = parseInt(node.getComputedStyle('paddingBottom'), 10), - pt = parseInt(node.getComputedStyle('paddingTop'), 10), - pl = parseInt(node.getComputedStyle('paddingLeft'), 10), - pr = parseInt(node.getComputedStyle('paddingRight'), 10); - height = node.get(OFFSETHEIGHT) - bb - bt - pb - pt; - width = node.get(OFFSETWIDTH) - bl - br - pl - pr; - } else { - height = node.getComputedStyle(HEIGHT); - width = node.getComputedStyle(WIDTH); - } - + var containerNode = Y.Node.create('
'); containerNode.set('innerHTML', node.get('innerHTML')) + .setAttribute('class', node.getAttribute('class')) .setAttribute('data-uid', node.ancestor('tr').getData('uid')) .setStyles({ - height: height, - width: width + height: node.getComputedStyle(HEIGHT), + width: node.getComputedStyle(WIDTH) }); // Add the new nodes to our floating table. @@ -673,30 +658,41 @@ FloatingHeaders.prototype = { * @protected */ _setupFloatingUserHeader: function() { - // We make various references to the this header cell. Store it for later. + // We make various references to the header cells. Store it for later. this.headerRow = Y.one(SELECTORS.HEADERROW); this.headerCell = Y.one(SELECTORS.STUDENTHEADER); - // Float the 'user name' header cell. - var floatingUserCell = Y.Node.create(''), - firstUserXY = this._getRelativeXY(this.firstUserCell), - headerXY = this._getRelativeXY(this.headerRow); + // Create the floating row and cell. + var floatingUserHeaderRow = Y.Node.create(''), + floatingUserHeaderCell = Y.Node.create('
'), + nodepos = this._getRelativeXY(this.headerCell)[0], + coordinates = this._getRelativeXY(this.headerRow); + gradeHeadersOffset = coordinates[0]; - // Append node contents - floatingUserCell.set('innerHTML', this.headerCell.getHTML()); - floatingUserCell.setStyles({ - height: this.headerCell.getComputedStyle(HEIGHT), - left: firstUserXY[0] + 'px', - position: 'absolute', - top: headerXY[1] + 'px', - width: this.firstUserCell.getComputedStyle(WIDTH) - }); + // Append the content and style to the floating cell. + floatingUserHeaderCell + .set('innerHTML', this.headerCell.getHTML()) + .setAttribute('class', this.headerCell.getAttribute('class')) + .setStyles({ + // The header is larger than the user cells, so we take the user cell. + width: this.firstUserCell.getComputedStyle(WIDTH), + left: (nodepos - gradeHeadersOffset) + 'px' + }); - // Append to the grader region. - this.graderRegion.append(floatingUserCell); + // Style the floating row. + floatingUserHeaderRow + .setStyles({ + left: coordinates[0] + 'px', + position: 'absolute', + top: coordinates[1] + 'px' + }); + + // Append the cell to the row, and finally to the region. + floatingUserHeaderRow.append(floatingUserHeaderCell); + this.graderRegion.append(floatingUserHeaderRow); // Store a reference to this for later - we use it in the event handlers. - this.userColumnHeader = floatingUserCell; + this.userColumnHeader = floatingUserHeaderRow; }, /** @@ -711,7 +707,7 @@ FloatingHeaders.prototype = { var gradeHeaders = Y.all('#user-grades tr.heading .cell'); // Generate a floating headers - var floatingGradeHeaders = Y.Node.create(''); + var floatingGradeHeaders = Y.Node.create(''); var coordinates = this._getRelativeXY(this.headerRow); @@ -722,16 +718,16 @@ FloatingHeaders.prototype = { gradeHeaders.each(function(node) { var nodepos = this._getRelativeXY(node)[0]; - var newnode = Y.Node.create('
'); + var newnode = Y.Node.create('
'); newnode.append(node.getHTML()) - .addClass(node.getAttribute('class')) - .setData('itemid', node.getData('itemid')) - .setStyles({ - height: node.getComputedStyle(HEIGHT), - left: (nodepos - gradeHeadersOffset) + 'px', - position: 'absolute', - width: node.getComputedStyle(WIDTH) - }); + .setAttribute('class', node.getAttribute('class')) + .setData('itemid', node.getData('itemid')) + .setStyles({ + height: node.getComputedStyle(HEIGHT), + left: (nodepos - gradeHeadersOffset) + 'px', + position: 'absolute', + width: node.getComputedStyle(WIDTH) + }); // Sum up total widths - these are used in the container styles. // Use the offsetHeight and Width here as this contains the @@ -775,24 +771,27 @@ FloatingHeaders.prototype = { var footerCells = this.tableFooterRow.all('.cell'); // Create a container. - var floatingGraderFooter = Y.Node.create(''); + var floatingGraderFooter = Y.Node.create(''); var footerWidth = 0; var coordinates = this._getRelativeXY(this.tableFooterRow); var footerRowOffset = coordinates[0]; + var floatingGraderFooterHeight = 0; // Copy cell content. footerCells.each(function(node) { - var newnode = Y.Node.create(''); + var newnode = Y.Node.create('
'); var nodepos = this._getRelativeXY(node)[0]; - newnode.set('innerHTML', node.getHTML()); - newnode.setStyles({ - height: this._getHeight(node), - left: (nodepos - footerRowOffset) + 'px', - position: 'absolute', - width: this._getWidth(node) - }); + newnode.set('innerHTML', node.getHTML()) + .setAttribute('class', node.getAttribute('class')) + .setStyles({ + height: node.getComputedStyle(HEIGHT), + left: (nodepos - footerRowOffset) + 'px', + position: 'absolute', + width: node.getComputedStyle(WIDTH) + }); floatingGraderFooter.append(newnode); + floatingGraderFooterHeight = node.get(OFFSETHEIGHT); footerWidth += parseInt(node.get(OFFSETWIDTH), 10); }, this); @@ -804,16 +803,16 @@ FloatingHeaders.prototype = { button.on('click', function() { updateButton.simulate('click'); }); - floatingGraderFooter.one('.gradebook-footer-cell').append(button); + floatingGraderFooter.one('div').append(button); } // Position the row floatingGraderFooter.setStyles({ position: 'absolute', left: coordinates[0] + 'px', - bottom: 0, - height: this._getHeight(this.tableFooterRow), - width: footerWidth + 'px', + bottom: '1px', + height: floatingGraderFooterHeight + 'px', + width: footerWidth + 'px' }); // Append to the grader region. @@ -840,13 +839,16 @@ FloatingHeaders.prototype = { footerStyles = {}, coord = 0, userCellWidth = 0, - floatUserColumn = false, // Whether or not the user column should float. floatingUserTriggerPoint = 0, // The X position at which the floating should start. - floatingUserRelativePoint = 0; // The point to use when calculating the new position. + floatingUserRelativePoint = 0, // The point to use when calculating the new position. + headerFloats = false, + userFloats = false, + footerFloats = false; // Header position. gradeItemHeadingContainerStyles.left = this._getRelativeXFromX(this.headerRow.getX()); if (Y.config.win.pageYOffset + this.pageHeaderHeight > this.headerRowTop) { + headerFloats = true; if (Y.config.win.pageYOffset + this.pageHeaderHeight < this.lastUserCellTop) { coord = this._getRelativeYFromY(Y.config.win.pageYOffset + this.pageHeaderHeight); gradeItemHeadingContainerStyles.top = coord + 'px'; @@ -857,6 +859,7 @@ FloatingHeaders.prototype = { userColumnHeaderStyles.top = coord + 'px'; } } else { + headerFloats = false; coord = this._getRelativeYFromY(this.headerRowTop); gradeItemHeadingContainerStyles.top = coord + 'px'; userColumnHeaderStyles.top = coord + 'px'; @@ -867,13 +870,13 @@ FloatingHeaders.prototype = { userCellWidth = this.firstUserCell.get(OFFSETWIDTH); floatingUserTriggerPoint = Y.config.win.innerWidth + Y.config.win.pageXOffset; floatingUserRelativePoint = floatingUserTriggerPoint - userCellWidth; - floatUserColumn = floatingUserTriggerPoint < (this.firstUserCellLeft + userCellWidth); + userFloats = floatingUserTriggerPoint < (this.firstUserCellLeft + userCellWidth); } else { floatingUserTriggerPoint = Y.config.win.pageXOffset; floatingUserRelativePoint = floatingUserTriggerPoint; - floatUserColumn = floatingUserTriggerPoint > this.firstUserCellLeft; + userFloats = floatingUserTriggerPoint > this.firstUserCellLeft; } - if (floatUserColumn) { + if (userFloats) { coord = this._getRelativeXFromX(floatingUserRelativePoint); userColumnStyles.left = coord + 'px'; userColumnHeaderStyles.left = coord + 'px'; @@ -897,17 +900,40 @@ FloatingHeaders.prototype = { if (bottomScrollPosition < footerBottomPosition && bottomScrollPosition > this.firstUserCellBottom) { // We have not scrolled below the footer, nor above the first row. footerStyles.bottom = Math.ceil(footerBottomPosition - bottomScrollPosition) + 'px'; + footerFloats = true; } else { // The footer should not float any more. footerStyles.bottom = 0; + footerFloats = false; } } - // Finally, apply the styles. + // Apply the styles. this.gradeItemHeadingContainer.setStyles(gradeItemHeadingContainerStyles); this.userColumnHeader.setStyles(userColumnHeaderStyles); this.userColumn.setStyles(userColumnStyles); this.footerRow.setStyles(footerStyles); + + // Mark the elements as floating, or not. + if (headerFloats) { + this.gradeItemHeadingContainer.addClass(CSS.FLOATING); + } else { + this.gradeItemHeadingContainer.removeClass(CSS.FLOATING); + } + + if (userFloats) { + this.userColumnHeader.addClass(CSS.FLOATING); + this.userColumn.addClass(CSS.FLOATING); + } else { + this.userColumnHeader.removeClass(CSS.FLOATING); + this.userColumn.removeClass(CSS.FLOATING); + } + + if (footerFloats) { + this.footerRow.addClass(CSS.FLOATING); + } else { + this.footerRow.removeClass(CSS.FLOATING); + } }, /** @@ -926,8 +952,8 @@ FloatingHeaders.prototype = { // Resize user cells. var userWidth = this.firstUserCell.getComputedStyle(WIDTH); var userCells = Y.all(SELECTORS.USERCELL); - this.userColumnHeader.setStyle('width', userWidth); - this.userColumn.all('.gradebook-user-cell').each(function(cell, idx) { + this.userColumnHeader.one('.cell').setStyle('width', userWidth); + this.userColumn.all('.cell').each(function(cell, idx) { cell.setStyles({ width: userWidth, height: userCells.item(idx).getComputedStyle(HEIGHT) @@ -936,8 +962,8 @@ FloatingHeaders.prototype = { // Resize headers & footers. // This is an expensive operation, not expected to happen often. - var headers = this.gradeItemHeadingContainer.all(SELECTORS.HEADERCELL); - var resizedcells = Y.all('#user-grades .heading .cell'); + var headers = this.gradeItemHeadingContainer.all('.cell'); + var resizedcells = Y.all(SELECTORS.HEADERCELLS); var headeroffsetleft = this.headerRow.getX(); var newcontainerwidth = 0; @@ -952,60 +978,25 @@ FloatingHeaders.prototype = { headercell.setStyles(styles); }); - var footers = Y.all('#gradebook-footer-container .gradebook-footer-cell'); - if (footers.size() !== 0) { - var resizedavgcells = Y.all('#user-grades .avg .cell'); + if (this.footerRow) { + var footers = this.footerRow.all('.cell'); + if (footers.size() !== 0) { + var resizedavgcells = Y.all(SELECTORS.FOOTERCELLS); - resizedavgcells.each(function(cell, idx) { - var footercell = footers.item(idx); - var styles = { - width: cell.getComputedStyle(WIDTH), - left: cell.getX() - headeroffsetleft + 'px' - }; - footercell.setStyles(styles); - }); + resizedavgcells.each(function(cell, idx) { + var footercell = footers.item(idx); + var styles = { + width: cell.getComputedStyle(WIDTH), + left: cell.getX() - headeroffsetleft + 'px' + }; + footercell.setStyles(styles); + }); + } } this.gradeItemHeadingContainer.setStyle('width', newcontainerwidth); - }, - - /** - * Determine the height of the specified Node. - * - * With IE, the height used when setting a height is the offsetHeight. - * All other browsers set this as this inner height. - * - * @method _getHeight - * @protected - * @param {Node} node - * @return String - */ - _getHeight: function(node) { - if (Y.UA.ie) { - return node.get(OFFSETHEIGHT) + 'px'; - } else { - return node.getComputedStyle(HEIGHT); - } - }, - - /** - * Determine the width of the specified Node. - * - * With IE, the width used when setting a width is the offsetWidth. - * All other browsers set this as this inner width. - * - * @method _getWidth - * @protected - * @param {Node} node - * @return String - */ - _getWidth: function(node) { - if (Y.UA.ie) { - return node.get(OFFSETWIDTH) + 'px'; - } else { - return node.getComputedStyle(WIDTH); - } } + }; Y.Base.mix(Y.M.gradereport_grader.ReportTable, [FloatingHeaders]); diff --git a/grade/report/grader/yui/src/gradereporttable/js/floatingheaders.js b/grade/report/grader/yui/src/gradereporttable/js/floatingheaders.js index b5791880a56..340053078de 100644 --- a/grade/report/grader/yui/src/gradereporttable/js/floatingheaders.js +++ b/grade/report/grader/yui/src/gradereporttable/js/floatingheaders.js @@ -32,6 +32,8 @@ var HEIGHT = 'height', OFFSETWIDTH = 'offsetWidth', OFFSETHEIGHT = 'offsetHeight'; +CSS.FLOATING = 'floating'; + function FloatingHeaders() {} FloatingHeaders.ATTRS= { @@ -292,7 +294,7 @@ FloatingHeaders.prototype = { */ _getRelativeXYFromXY: function(x, y) { var parentXY = this.container.getXY(); - return [Math.floor(x - parentXY[0]), Math.floor(y - parentXY[1])]; + return [x - parentXY[0], y - parentXY[1]]; }, /** @@ -364,7 +366,7 @@ FloatingHeaders.prototype = { var userColumn = Y.all(SELECTORS.USERCELL), // Create a floating table. - floatingUserColumn = Y.Node.create(''), + floatingUserColumn = Y.Node.create(''), // Get the XY for the floating element. coordinates = this._getRelativeXY(this.firstUserCell); @@ -372,32 +374,13 @@ FloatingHeaders.prototype = { // Generate the new fields. userColumn.each(function(node) { // Create and configure the new container. - var containerNode = Y.Node.create(''), - height, - width; - - // IE madness... - if (Y.UA.ie) { - var bb = parseInt(node.getComputedStyle('borderBottomWidth'), 10), - bt = parseInt(node.getComputedStyle('borderTopWidth'), 10), - bl = parseInt(node.getComputedStyle('borderLeftWidth'), 10), - br = parseInt(node.getComputedStyle('borderRightWidth'), 10), - pb = parseInt(node.getComputedStyle('paddingBottom'), 10), - pt = parseInt(node.getComputedStyle('paddingTop'), 10), - pl = parseInt(node.getComputedStyle('paddingLeft'), 10), - pr = parseInt(node.getComputedStyle('paddingRight'), 10); - height = node.get(OFFSETHEIGHT) - bb - bt - pb - pt; - width = node.get(OFFSETWIDTH) - bl - br - pl - pr; - } else { - height = node.getComputedStyle(HEIGHT); - width = node.getComputedStyle(WIDTH); - } - + var containerNode = Y.Node.create('
'); containerNode.set('innerHTML', node.get('innerHTML')) + .setAttribute('class', node.getAttribute('class')) .setAttribute('data-uid', node.ancestor('tr').getData('uid')) .setStyles({ - height: height, - width: width + height: node.getComputedStyle(HEIGHT), + width: node.getComputedStyle(WIDTH) }); // Add the new nodes to our floating table. @@ -425,30 +408,41 @@ FloatingHeaders.prototype = { * @protected */ _setupFloatingUserHeader: function() { - // We make various references to the this header cell. Store it for later. + // We make various references to the header cells. Store it for later. this.headerRow = Y.one(SELECTORS.HEADERROW); this.headerCell = Y.one(SELECTORS.STUDENTHEADER); - // Float the 'user name' header cell. - var floatingUserCell = Y.Node.create(''), - firstUserXY = this._getRelativeXY(this.firstUserCell), - headerXY = this._getRelativeXY(this.headerRow); + // Create the floating row and cell. + var floatingUserHeaderRow = Y.Node.create(''), + floatingUserHeaderCell = Y.Node.create('
'), + nodepos = this._getRelativeXY(this.headerCell)[0], + coordinates = this._getRelativeXY(this.headerRow); + gradeHeadersOffset = coordinates[0]; - // Append node contents - floatingUserCell.set('innerHTML', this.headerCell.getHTML()); - floatingUserCell.setStyles({ - height: this.headerCell.getComputedStyle(HEIGHT), - left: firstUserXY[0] + 'px', - position: 'absolute', - top: headerXY[1] + 'px', - width: this.firstUserCell.getComputedStyle(WIDTH) - }); + // Append the content and style to the floating cell. + floatingUserHeaderCell + .set('innerHTML', this.headerCell.getHTML()) + .setAttribute('class', this.headerCell.getAttribute('class')) + .setStyles({ + // The header is larger than the user cells, so we take the user cell. + width: this.firstUserCell.getComputedStyle(WIDTH), + left: (nodepos - gradeHeadersOffset) + 'px' + }); - // Append to the grader region. - this.graderRegion.append(floatingUserCell); + // Style the floating row. + floatingUserHeaderRow + .setStyles({ + left: coordinates[0] + 'px', + position: 'absolute', + top: coordinates[1] + 'px' + }); + + // Append the cell to the row, and finally to the region. + floatingUserHeaderRow.append(floatingUserHeaderCell); + this.graderRegion.append(floatingUserHeaderRow); // Store a reference to this for later - we use it in the event handlers. - this.userColumnHeader = floatingUserCell; + this.userColumnHeader = floatingUserHeaderRow; }, /** @@ -463,7 +457,7 @@ FloatingHeaders.prototype = { var gradeHeaders = Y.all('#user-grades tr.heading .cell'); // Generate a floating headers - var floatingGradeHeaders = Y.Node.create(''); + var floatingGradeHeaders = Y.Node.create(''); var coordinates = this._getRelativeXY(this.headerRow); @@ -474,16 +468,16 @@ FloatingHeaders.prototype = { gradeHeaders.each(function(node) { var nodepos = this._getRelativeXY(node)[0]; - var newnode = Y.Node.create('
'); + var newnode = Y.Node.create('
'); newnode.append(node.getHTML()) - .addClass(node.getAttribute('class')) - .setData('itemid', node.getData('itemid')) - .setStyles({ - height: node.getComputedStyle(HEIGHT), - left: (nodepos - gradeHeadersOffset) + 'px', - position: 'absolute', - width: node.getComputedStyle(WIDTH) - }); + .setAttribute('class', node.getAttribute('class')) + .setData('itemid', node.getData('itemid')) + .setStyles({ + height: node.getComputedStyle(HEIGHT), + left: (nodepos - gradeHeadersOffset) + 'px', + position: 'absolute', + width: node.getComputedStyle(WIDTH) + }); // Sum up total widths - these are used in the container styles. // Use the offsetHeight and Width here as this contains the @@ -528,24 +522,27 @@ FloatingHeaders.prototype = { var footerCells = this.tableFooterRow.all('.cell'); // Create a container. - var floatingGraderFooter = Y.Node.create(''); + var floatingGraderFooter = Y.Node.create(''); var footerWidth = 0; var coordinates = this._getRelativeXY(this.tableFooterRow); var footerRowOffset = coordinates[0]; + var floatingGraderFooterHeight = 0; // Copy cell content. footerCells.each(function(node) { - var newnode = Y.Node.create(''); + var newnode = Y.Node.create('
'); var nodepos = this._getRelativeXY(node)[0]; - newnode.set('innerHTML', node.getHTML()); - newnode.setStyles({ - height: this._getHeight(node), - left: (nodepos - footerRowOffset) + 'px', - position: 'absolute', - width: this._getWidth(node) - }); + newnode.set('innerHTML', node.getHTML()) + .setAttribute('class', node.getAttribute('class')) + .setStyles({ + height: node.getComputedStyle(HEIGHT), + left: (nodepos - footerRowOffset) + 'px', + position: 'absolute', + width: node.getComputedStyle(WIDTH) + }); floatingGraderFooter.append(newnode); + floatingGraderFooterHeight = node.get(OFFSETHEIGHT); footerWidth += parseInt(node.get(OFFSETWIDTH), 10); }, this); @@ -557,16 +554,16 @@ FloatingHeaders.prototype = { button.on('click', function() { updateButton.simulate('click'); }); - floatingGraderFooter.one('.gradebook-footer-cell').append(button); + floatingGraderFooter.one('div').append(button); } // Position the row floatingGraderFooter.setStyles({ position: 'absolute', left: coordinates[0] + 'px', - bottom: 0, - height: this._getHeight(this.tableFooterRow), - width: footerWidth + 'px', + bottom: '1px', + height: floatingGraderFooterHeight + 'px', + width: footerWidth + 'px' }); // Append to the grader region. @@ -593,13 +590,16 @@ FloatingHeaders.prototype = { footerStyles = {}, coord = 0, userCellWidth = 0, - floatUserColumn = false, // Whether or not the user column should float. floatingUserTriggerPoint = 0, // The X position at which the floating should start. - floatingUserRelativePoint = 0; // The point to use when calculating the new position. + floatingUserRelativePoint = 0, // The point to use when calculating the new position. + headerFloats = false, + userFloats = false, + footerFloats = false; // Header position. gradeItemHeadingContainerStyles.left = this._getRelativeXFromX(this.headerRow.getX()); if (Y.config.win.pageYOffset + this.pageHeaderHeight > this.headerRowTop) { + headerFloats = true; if (Y.config.win.pageYOffset + this.pageHeaderHeight < this.lastUserCellTop) { coord = this._getRelativeYFromY(Y.config.win.pageYOffset + this.pageHeaderHeight); gradeItemHeadingContainerStyles.top = coord + 'px'; @@ -610,6 +610,7 @@ FloatingHeaders.prototype = { userColumnHeaderStyles.top = coord + 'px'; } } else { + headerFloats = false; coord = this._getRelativeYFromY(this.headerRowTop); gradeItemHeadingContainerStyles.top = coord + 'px'; userColumnHeaderStyles.top = coord + 'px'; @@ -620,13 +621,13 @@ FloatingHeaders.prototype = { userCellWidth = this.firstUserCell.get(OFFSETWIDTH); floatingUserTriggerPoint = Y.config.win.innerWidth + Y.config.win.pageXOffset; floatingUserRelativePoint = floatingUserTriggerPoint - userCellWidth; - floatUserColumn = floatingUserTriggerPoint < (this.firstUserCellLeft + userCellWidth); + userFloats = floatingUserTriggerPoint < (this.firstUserCellLeft + userCellWidth); } else { floatingUserTriggerPoint = Y.config.win.pageXOffset; floatingUserRelativePoint = floatingUserTriggerPoint; - floatUserColumn = floatingUserTriggerPoint > this.firstUserCellLeft; + userFloats = floatingUserTriggerPoint > this.firstUserCellLeft; } - if (floatUserColumn) { + if (userFloats) { coord = this._getRelativeXFromX(floatingUserRelativePoint); userColumnStyles.left = coord + 'px'; userColumnHeaderStyles.left = coord + 'px'; @@ -650,17 +651,40 @@ FloatingHeaders.prototype = { if (bottomScrollPosition < footerBottomPosition && bottomScrollPosition > this.firstUserCellBottom) { // We have not scrolled below the footer, nor above the first row. footerStyles.bottom = Math.ceil(footerBottomPosition - bottomScrollPosition) + 'px'; + footerFloats = true; } else { // The footer should not float any more. footerStyles.bottom = 0; + footerFloats = false; } } - // Finally, apply the styles. + // Apply the styles. this.gradeItemHeadingContainer.setStyles(gradeItemHeadingContainerStyles); this.userColumnHeader.setStyles(userColumnHeaderStyles); this.userColumn.setStyles(userColumnStyles); this.footerRow.setStyles(footerStyles); + + // Mark the elements as floating, or not. + if (headerFloats) { + this.gradeItemHeadingContainer.addClass(CSS.FLOATING); + } else { + this.gradeItemHeadingContainer.removeClass(CSS.FLOATING); + } + + if (userFloats) { + this.userColumnHeader.addClass(CSS.FLOATING); + this.userColumn.addClass(CSS.FLOATING); + } else { + this.userColumnHeader.removeClass(CSS.FLOATING); + this.userColumn.removeClass(CSS.FLOATING); + } + + if (footerFloats) { + this.footerRow.addClass(CSS.FLOATING); + } else { + this.footerRow.removeClass(CSS.FLOATING); + } }, /** @@ -679,8 +703,8 @@ FloatingHeaders.prototype = { // Resize user cells. var userWidth = this.firstUserCell.getComputedStyle(WIDTH); var userCells = Y.all(SELECTORS.USERCELL); - this.userColumnHeader.setStyle('width', userWidth); - this.userColumn.all('.gradebook-user-cell').each(function(cell, idx) { + this.userColumnHeader.one('.cell').setStyle('width', userWidth); + this.userColumn.all('.cell').each(function(cell, idx) { cell.setStyles({ width: userWidth, height: userCells.item(idx).getComputedStyle(HEIGHT) @@ -689,8 +713,8 @@ FloatingHeaders.prototype = { // Resize headers & footers. // This is an expensive operation, not expected to happen often. - var headers = this.gradeItemHeadingContainer.all(SELECTORS.HEADERCELL); - var resizedcells = Y.all('#user-grades .heading .cell'); + var headers = this.gradeItemHeadingContainer.all('.cell'); + var resizedcells = Y.all(SELECTORS.HEADERCELLS); var headeroffsetleft = this.headerRow.getX(); var newcontainerwidth = 0; @@ -705,60 +729,25 @@ FloatingHeaders.prototype = { headercell.setStyles(styles); }); - var footers = Y.all('#gradebook-footer-container .gradebook-footer-cell'); - if (footers.size() !== 0) { - var resizedavgcells = Y.all('#user-grades .avg .cell'); + if (this.footerRow) { + var footers = this.footerRow.all('.cell'); + if (footers.size() !== 0) { + var resizedavgcells = Y.all(SELECTORS.FOOTERCELLS); - resizedavgcells.each(function(cell, idx) { - var footercell = footers.item(idx); - var styles = { - width: cell.getComputedStyle(WIDTH), - left: cell.getX() - headeroffsetleft + 'px' - }; - footercell.setStyles(styles); - }); + resizedavgcells.each(function(cell, idx) { + var footercell = footers.item(idx); + var styles = { + width: cell.getComputedStyle(WIDTH), + left: cell.getX() - headeroffsetleft + 'px' + }; + footercell.setStyles(styles); + }); + } } this.gradeItemHeadingContainer.setStyle('width', newcontainerwidth); - }, - - /** - * Determine the height of the specified Node. - * - * With IE, the height used when setting a height is the offsetHeight. - * All other browsers set this as this inner height. - * - * @method _getHeight - * @protected - * @param {Node} node - * @return String - */ - _getHeight: function(node) { - if (Y.UA.ie) { - return node.get(OFFSETHEIGHT) + 'px'; - } else { - return node.getComputedStyle(HEIGHT); - } - }, - - /** - * Determine the width of the specified Node. - * - * With IE, the width used when setting a width is the offsetWidth. - * All other browsers set this as this inner width. - * - * @method _getWidth - * @protected - * @param {Node} node - * @return String - */ - _getWidth: function(node) { - if (Y.UA.ie) { - return node.get(OFFSETWIDTH) + 'px'; - } else { - return node.getComputedStyle(WIDTH); - } } + }; Y.Base.mix(Y.M.gradereport_grader.ReportTable, [FloatingHeaders]); diff --git a/grade/report/grader/yui/src/gradereporttable/js/gradereporttable.js b/grade/report/grader/yui/src/gradereporttable/js/gradereporttable.js index 78e7f475dd7..20aff21daec 100644 --- a/grade/report/grader/yui/src/gradereporttable/js/gradereporttable.js +++ b/grade/report/grader/yui/src/gradereporttable/js/gradereporttable.js @@ -28,10 +28,12 @@ */ var SELECTORS = { + FOOTERCELLS: '#user-grades .avg .cell', FOOTERROW: '#user-grades .avg', GRADECELL: 'td.grade', GRADERTABLE: '.gradeparent table', GRADEPARENT: '.gradeparent', + HEADERCELLS: '#user-grades .heading .cell', HEADERCELL: '.gradebook-header-cell', HEADERROW: '#user-grades tr.heading', STUDENTHEADER: '#studentheader', diff --git a/grade/report/grader/yui/src/gradereporttable/js/highlighter.js b/grade/report/grader/yui/src/gradereporttable/js/highlighter.js index 7e9f696e43f..669ccc9cbc4 100644 --- a/grade/report/grader/yui/src/gradereporttable/js/highlighter.js +++ b/grade/report/grader/yui/src/gradereporttable/js/highlighter.js @@ -35,8 +35,8 @@ function Highlighter() {} Highlighter.ATTRS= { }; -var ROWFIELDS = 'th.user, th.userreport, th.userfield, .gradebook-user-cell', - COLFIELDS = 'tr[data-itemid] th.item, .gradebook-header-cell'; +var ROWFIELDS = '.user.cell, th.userreport, th.userfield', + COLFIELDS = 'tr[data-itemid] th.item, .heading .cell'; Highlighter.prototype = { /**