MDL-46950 gradereport_grader: Consolidate styling of the elements

The grader table has been made entirely standalone from core or
theme styling. The floating divs have to share the exact same
rules, and so it was a lot easier and more maintainable to just
style them both using the same selectors, entirely ignoring the
table default styles.

And because the selectors are unique for both the floating elements
and the table cells, a themer can easily re-use them to style both,
without having to dig around to find all the selectors to overwrite.

Working on this highlighted some issues with the positioning. Those
have been fixed within the same patch. And even though it is still
not 100% correct on IE, the result is pretty decent.

This issue is a part of the MDL-46658 Task.
This issue is a part of the MDL-25544 Epic.
This commit is contained in:
Frederic Massart 2014-08-28 16:49:04 +08:00 committed by Andrew Nicols
parent 7dc48b4629
commit 31819e8961
8 changed files with 454 additions and 496 deletions

View File

@ -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

View File

@ -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;

View File

@ -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('<div aria-hidden="true" role="presentation" id="gradebook-user-container"></div>'),
floatingUserColumn = Y.Node.create('<div aria-hidden="true" role="presentation" class="floater"></div>'),
// 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('<div aria-hidden="true" class="gradebook-user-cell"></div>'),
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('<div></div>');
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('<div aria-hidden="true" role="presentation" id="gradebook-user-header-container"></div>'),
firstUserXY = this._getRelativeXY(this.firstUserCell),
headerXY = this._getRelativeXY(this.headerRow);
// Create the floating row and cell.
var floatingUserHeaderRow = Y.Node.create('<div aria-hidden="true" role="presentation" class="floater heading"></div>'),
floatingUserHeaderCell = Y.Node.create('<div></div>'),
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('<div aria-hidden="true" role="presentation" id="gradebook-header-container"></div>');
var floatingGradeHeaders = Y.Node.create('<div aria-hidden="true" role="presentation" class="floater heading"></div>');
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('<div class="gradebook-header-cell"></div>');
var newnode = Y.Node.create('<div></div>');
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('<div aria-hidden="true" role="presentation" id="gradebook-footer-container"></div>');
var floatingGraderFooter = Y.Node.create('<div aria-hidden="true" role="presentation" class="floater avg"></div>');
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('<div class="gradebook-footer-cell"></div>');
var newnode = Y.Node.create('<div></div>');
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]);

View File

@ -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('<div aria-hidden="true" role="presentation" id="gradebook-user-container"></div>'),
floatingUserColumn = Y.Node.create('<div aria-hidden="true" role="presentation" class="floater"></div>'),
// 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('<div aria-hidden="true" class="gradebook-user-cell"></div>'),
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('<div></div>');
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('<div aria-hidden="true" role="presentation" id="gradebook-user-header-container"></div>'),
firstUserXY = this._getRelativeXY(this.firstUserCell),
headerXY = this._getRelativeXY(this.headerRow);
// Create the floating row and cell.
var floatingUserHeaderRow = Y.Node.create('<div aria-hidden="true" role="presentation" class="floater heading"></div>'),
floatingUserHeaderCell = Y.Node.create('<div></div>'),
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('<div aria-hidden="true" role="presentation" id="gradebook-header-container"></div>');
var floatingGradeHeaders = Y.Node.create('<div aria-hidden="true" role="presentation" class="floater heading"></div>');
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('<div class="gradebook-header-cell"></div>');
var newnode = Y.Node.create('<div></div>');
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('<div aria-hidden="true" role="presentation" id="gradebook-footer-container"></div>');
var floatingGraderFooter = Y.Node.create('<div aria-hidden="true" role="presentation" class="floater avg"></div>');
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('<div class="gradebook-footer-cell"></div>');
var newnode = Y.Node.create('<div></div>');
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]);

View File

@ -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('<div aria-hidden="true" role="presentation" id="gradebook-user-container"></div>'),
floatingUserColumn = Y.Node.create('<div aria-hidden="true" role="presentation" class="floater"></div>'),
// 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('<div aria-hidden="true" class="gradebook-user-cell"></div>'),
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('<div></div>');
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('<div aria-hidden="true" role="presentation" id="gradebook-user-header-container"></div>'),
firstUserXY = this._getRelativeXY(this.firstUserCell),
headerXY = this._getRelativeXY(this.headerRow);
// Create the floating row and cell.
var floatingUserHeaderRow = Y.Node.create('<div aria-hidden="true" role="presentation" class="floater heading"></div>'),
floatingUserHeaderCell = Y.Node.create('<div></div>'),
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('<div aria-hidden="true" role="presentation" id="gradebook-header-container"></div>');
var floatingGradeHeaders = Y.Node.create('<div aria-hidden="true" role="presentation" class="floater heading"></div>');
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('<div class="gradebook-header-cell"></div>');
var newnode = Y.Node.create('<div></div>');
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('<div aria-hidden="true" role="presentation" id="gradebook-footer-container"></div>');
var floatingGraderFooter = Y.Node.create('<div aria-hidden="true" role="presentation" class="floater avg"></div>');
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('<div class="gradebook-footer-cell"></div>');
var newnode = Y.Node.create('<div></div>');
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]);

View File

@ -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',

View File

@ -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 = {
/**