MDL-47045 gradereport_grader: Improve Grader report user interface
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:
committed by
Andrew Nicols
parent
6597413d41
commit
2c4a3f7525
@@ -52,7 +52,8 @@ if (isset($graderreportsilast)) {
|
||||
}
|
||||
|
||||
$PAGE->set_url(new moodle_url('/grade/report/grader/index.php', array('id'=>$courseid)));
|
||||
$PAGE->requires->yui_module('moodle-gradereport_grader-scrollview', 'M.gradereport_grader.scrollview.init');
|
||||
//$PAGE->requires->yui_module('moodle-gradereport_grader-scrollview', 'M.gradereport_grader.scrollview.init');
|
||||
$PAGE->requires->yui_module('moodle-gradereport_grader-gradereporttable', 'M.gradereport_grader.gradereporttable.init', array());
|
||||
|
||||
// basic access checks
|
||||
if (!$course = $DB->get_record('course', array('id' => $courseid))) {
|
||||
@@ -193,6 +194,15 @@ if ($USER->gradeediting[$course->id] && ($report->get_pref('showquickfeedback')
|
||||
echo $reporthtml;
|
||||
}
|
||||
|
||||
// Render a loading screen.
|
||||
$loading = html_writer::div(
|
||||
html_writer::div(
|
||||
'<i></i><i></i><i></i><i></i>', 'gradebook-loading'
|
||||
), 'gradebook-loading-screen', array('aria-hidden' => 'true')
|
||||
);
|
||||
|
||||
echo $loading;
|
||||
|
||||
// prints paging bar at bottom for large pages
|
||||
if (!empty($studentsperpage) && $studentsperpage >= 20) {
|
||||
echo $OUTPUT->paging_bar($numusers, $report->page, $studentsperpage, $report->pbarurl);
|
||||
|
||||
@@ -1137,7 +1137,7 @@ class grade_report_grader extends grade_report {
|
||||
$html .= $OUTPUT->container(html_writer::table($righttable), 'right_scroller');
|
||||
} else {
|
||||
$fulltable = new html_table();
|
||||
$fulltable->attributes['class'] = 'gradestable flexible boxaligncenter generaltable';
|
||||
$fulltable->attributes['class'] = 'table table-bordered table-striped table-condensed';
|
||||
$fulltable->id = 'user-grades';
|
||||
|
||||
// Extract rows from each side (left and right) and collate them into one row each
|
||||
|
||||
@@ -56,7 +56,8 @@ M.gradereport_grader = {
|
||||
return;
|
||||
}
|
||||
|
||||
var content = '<div class="graderreportoverlay" role="tooltip" aria-describedby="' + properties.id + '">';
|
||||
var overriden = /.*overridden.*/g.test(properties.cell.getAttribute('class')) ? 'overriden' : '';
|
||||
var content = '<div class="graderreportoverlay ' + overriden + '" role="tooltip" aria-describedby="' + properties.id + '">';
|
||||
content += '<div class="fullname">'+properties.username+'</div><div class="itemname">'+properties.itemname+'</div>';
|
||||
if (properties.feedback) {
|
||||
content += '<div class="feedback">'+properties.feedback+'</div>';
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 320 B |
+370
-204
@@ -1,75 +1,142 @@
|
||||
.path-grade-report-grader .flexible th {
|
||||
white-space: normal;
|
||||
.path-grade-report-grader .yui3-overlay {
|
||||
border: 0;
|
||||
background: none;
|
||||
background-color: 'initial';
|
||||
min-width: 200px;
|
||||
}
|
||||
.gradestable {
|
||||
margin-bottom: 0;
|
||||
.path-grade-report-grader .graderreportoverlay {
|
||||
background-color: white;
|
||||
width: auto;
|
||||
padding: 10px;
|
||||
border-color: #ddd;
|
||||
font-size: 12px;
|
||||
-webkit-box-shadow: #999999 2px 2px 3px;
|
||||
-moz-box-shadow: #999999 2px 2px 3px;
|
||||
box-shadow: #999999 2px 2px 3px;
|
||||
-webkit-border-radius: 4px;
|
||||
-moz-border-radius: 4px;
|
||||
-ms-border-radius: 4px;
|
||||
-o-border-radius: 4px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.gradestable th.user img {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
.path-grade-report-grader .graderreportoverlay.overriden {
|
||||
border-top: 22px solid #f1c32a;
|
||||
}
|
||||
.gradestable th img {
|
||||
vertical-align: text-bottom;
|
||||
padding-bottom: 0;
|
||||
.path-grade-report-grader .graderreportoverlay.overriden:before {
|
||||
font-size: 12px;
|
||||
content: "Overridden grade";
|
||||
color: black;
|
||||
height: 0px;
|
||||
width: 100%;
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
top: -32px;
|
||||
float: left;
|
||||
position: relative;
|
||||
}
|
||||
.gradestable th .grade_icons {
|
||||
margin-top: .3em;
|
||||
.path-grade-report-grader .graderreportoverlay .overriden {
|
||||
background-color: #f1c32a;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
.gradestable th img.sorticon {
|
||||
margin-left: .3em;
|
||||
.path-grade-report-grader .graderreportoverlay .fullname {
|
||||
color: #444;
|
||||
}
|
||||
.dir-rtl .gradestable th img.sorticon {
|
||||
margin-left: 0;
|
||||
margin-right: .3em;
|
||||
.path-grade-report-grader .graderreportoverlay .itemname {
|
||||
padding-top: 4px;
|
||||
color: #666;
|
||||
}
|
||||
table#user-grades .catlevel2 {
|
||||
background-color: #f9f9f9;
|
||||
.path-grade-report-grader .gradeparent {
|
||||
overflow: inherit;
|
||||
}
|
||||
table#user-grades tr.range td.cell {
|
||||
font-weight: 700;
|
||||
|
||||
table#user-grades {
|
||||
font-size: 14px;
|
||||
}
|
||||
table#user-grades tr.avg td.cell {
|
||||
background-color: #efefff;
|
||||
font-weight: 700;
|
||||
color: #00008B;
|
||||
table#user-grades .avg th,
|
||||
table#user-grades .avg td,
|
||||
table#user-grades .heading th {
|
||||
font-weight: bold;
|
||||
background-color: #333;
|
||||
color: #ddd;
|
||||
border-color: #444;
|
||||
}
|
||||
table#user-grades tr.odd td.cell {
|
||||
background-color: #efefef;
|
||||
white-space: nowrap;
|
||||
table#user-grades .avg th a,
|
||||
table#user-grades .avg td a,
|
||||
table#user-grades .heading th a {
|
||||
color: white;
|
||||
font-weight: normal;
|
||||
}
|
||||
table#user-grades tr td.overridden {
|
||||
background-color: #F3E4C0;
|
||||
table#user-grades .avg .cell {
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
}
|
||||
table#user-grades tr.odd td.overridden {
|
||||
background-color: #EFD9A4;
|
||||
table#user-grades .avg .cell.header {
|
||||
text-align: right;
|
||||
}
|
||||
table#user-grades tr td.ajaxoverridden {
|
||||
background-color: #FFE3A0;
|
||||
table#user-grades th {
|
||||
font-weight: normal;
|
||||
}
|
||||
table#user-grades tr.odd td.ajaxoverridden {
|
||||
background-color: #FFDA83;
|
||||
table#user-grades th.cell {
|
||||
height: 20px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
table#user-grades tr.even td.excluded {
|
||||
background-color: #EABFFF;
|
||||
.path-grade-report-history table#user-grades th.cell {
|
||||
white-space: normal;
|
||||
}
|
||||
table#user-grades tr.odd td.excluded {
|
||||
background-color: #E5AFFF;
|
||||
table#user-grades .controls {
|
||||
text-align: right;
|
||||
background-color: #eee;
|
||||
height: 20px;
|
||||
}
|
||||
table#user-grades tr.odd th.header {
|
||||
background-color: #efefef;
|
||||
background-image: none;
|
||||
table#user-grades tr {
|
||||
height: 40px;
|
||||
}
|
||||
table#user-grades tr.even th.header {
|
||||
background-image: none;
|
||||
table#user-grades tr .gradevalue {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
display: inline-block;
|
||||
}
|
||||
table#user-grades tr.groupavg td.cell {
|
||||
background-color: #efffef;
|
||||
font-weight: 700;
|
||||
color: #006400;
|
||||
table#user-grades tr .user {
|
||||
min-width: 200px;
|
||||
max-width: 200px;
|
||||
width: 200px;
|
||||
background-color: #777777;
|
||||
border-color: #666666;
|
||||
}
|
||||
table#user-grades td.cat,
|
||||
table#user-grades td.course {
|
||||
font-weight: 700;
|
||||
table#user-grades tr .user a {
|
||||
color: white;
|
||||
}
|
||||
table#user-grades tr .user .userpicture {
|
||||
display: none;
|
||||
}
|
||||
table#user-grades tr.odd td.grade.vmarked {
|
||||
background-color: #f39a00;
|
||||
border-bottom-color: #f39a00;
|
||||
}
|
||||
table#user-grades tr.odd td.grade.vmarked.overridden {
|
||||
background-color: #f39a00;
|
||||
}
|
||||
table#user-grades tr.odd td.grade.hmarked {
|
||||
background-color: #f5cd00;
|
||||
border-bottom-color: #f5cd00;
|
||||
}
|
||||
table#user-grades tr.odd td.grade.hmarked.overridden {
|
||||
background-color: #f5cd00;
|
||||
}
|
||||
table#user-grades tr.odd td.grade.vmarked.hmarked {
|
||||
background-color: #f1b900;
|
||||
border-bottom-color: #f1b900;
|
||||
}
|
||||
table#user-grades tr.odd td.grade.vmarked.hmarked.overridden {
|
||||
background-color: #f1b900;
|
||||
}
|
||||
table#user-grades tr.odd td.grade.overridden {
|
||||
background-color: #fff;
|
||||
background: url([[pix:gradereport_grader|corner-fold]]) no-repeat;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
background-color: #efefef;
|
||||
}
|
||||
table#user-grades {
|
||||
font-size: 10px;
|
||||
@@ -411,110 +478,36 @@ tr.groupavg th.header {
|
||||
.path-grade-report-grader .heading_name_row th {
|
||||
white-space: nowrap;
|
||||
width: 2000px;
|
||||
table#user-grades tr.even td.grade.vmarked {
|
||||
background-color: #f4a400;
|
||||
border-bottom-color: #f4a400;
|
||||
}
|
||||
|
||||
/*MDL-21088 - IE 7 ignores nowraps on tds or ths so we put a span within it with a nowrap on it*/
|
||||
.path-grade-report-grader heading_name_row th span {
|
||||
white-space: nowrap;
|
||||
table#user-grades tr.even td.grade.vmarked.overridden {
|
||||
background-color: #f4a400;
|
||||
}
|
||||
.path-grade-report-grader .grade_icons img.ajax {
|
||||
float: right;
|
||||
table#user-grades tr.even td.grade.hmarked {
|
||||
background-color: #f5cf2c;
|
||||
border-bottom-color: #f5cf2c;
|
||||
}
|
||||
.path-grade-report-grader .gradestable th.user,
|
||||
.path-grade-report-grader .gradestable th.range,
|
||||
.path-grade-report-grader .flexible th,
|
||||
.path-grade-report-grader .flexible td,
|
||||
.path-grade-report-grader .flexible th a,
|
||||
.path-grade-report-grader .flexible td a,
|
||||
.path-grade-report-grader .gradestable th.range,
|
||||
.path-grade-report-grader td {
|
||||
white-space: nowrap;
|
||||
table#user-grades tr.even td.grade.hmarked.overridden {
|
||||
background-color: #f5cf2c;
|
||||
}
|
||||
table#user-grades .catlevel1,
|
||||
table#user-grades .r1,
|
||||
.path-grade-report-grader table tr.even td.cell,
|
||||
.path-grade-report-grader table tr.even th {
|
||||
background-color: #fff;
|
||||
table#user-grades tr.even td.grade.vmarked.hmarked {
|
||||
background-color: #f1be00;
|
||||
border-bottom-color: #f1be00;
|
||||
}
|
||||
table#user-grades .catlevel3,
|
||||
.path-grade-report-grader table tr.odd td.cell {
|
||||
background-color: #efefef;
|
||||
table#user-grades tr.even td.grade.vmarked.hmarked.overridden {
|
||||
background-color: #f1be00;
|
||||
}
|
||||
table#fixed_column tr.odd th ,
|
||||
table#user-grades tr.odd th {
|
||||
background-color: #efefef;
|
||||
table#user-grades tr.even td.grade.overridden {
|
||||
background-color: #efefef;
|
||||
background: url([[pix:gradereport_grader|corner-fold]]) no-repeat;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
background-color: #efefef;
|
||||
}
|
||||
table#user-grades td.vmarked,
|
||||
table#user-grades tr.odd td.vmarked,
|
||||
table#user-grades tr.avg td.vmarked,
|
||||
table#user-grades tr.controls td.vmarked,
|
||||
table#user-grades .catlevel1.vmarked,
|
||||
table#user-grades .catlevel2.vmarked,
|
||||
table#user-grades .catlevel3.vmarked,
|
||||
table#user-grades tr.range td.vmarked,
|
||||
table#user-grades tr.groupavg td.vmarked {
|
||||
background-color: #fc3;
|
||||
}
|
||||
table#user-grades td.hmarked,
|
||||
table#user-grades tr.odd td.hmarked,
|
||||
table#user-grades tr.even td.hmarked,
|
||||
table#user-grades tr.odd th.hmarked,
|
||||
table#user-grades tr.even th.hmarked {
|
||||
background-color: #ff9;
|
||||
}
|
||||
table#user-grades td.hmarked.vmarked,
|
||||
table#user-grades tr.odd td.hmarked.vmarked,
|
||||
table#user-grades tr.even td.hmarked.vmarked {
|
||||
background-color: #fc9;
|
||||
}
|
||||
table#user-grades tr.heading,
|
||||
table#user-grades .heading td {
|
||||
border-style: solid;
|
||||
border-width: 0;
|
||||
}
|
||||
table#user-grades td.userfield,
|
||||
table#user-grades th,
|
||||
.path-grade-report-grader div.gradeparent,
|
||||
.path-grade-report-grader .ie6 form,
|
||||
table#user-grades td.ajax {
|
||||
text-align: left;
|
||||
}
|
||||
.dir-rtl table#user-grades td.userfield,
|
||||
.dir-rtl table#user-grades th,
|
||||
.path-grade-report-grader.dir-rtl div.gradeparent,
|
||||
.path-grade-report-grader.dir-rtl .ie6 form,
|
||||
.dir-rtl table#user-grades td.ajax {
|
||||
text-align: right;
|
||||
}
|
||||
.path-grade-report-grader .gradeparent {
|
||||
overflow: auto;
|
||||
}
|
||||
table#user-grades td.controls,
|
||||
.path-grade-report-grader table tr.avg .cell,
|
||||
.path-grade-report-grader table tr.range .cell {
|
||||
background-color: #f3ead8;
|
||||
}
|
||||
.path-grade-report-grader div.left_scroller tr,
|
||||
.path-grade-report-grader div.right_scroller tr,
|
||||
.path-grade-report-grader div.left_scroller td,
|
||||
.path-grade-report-grader div.right_scroller td,
|
||||
.path-grade-report-grader div.left_scroller th,
|
||||
.path-grade-report-grader div.right_scroller th {
|
||||
height: 4.5em;
|
||||
font-size: 10px;
|
||||
}
|
||||
.path-grade-report-grader table th.user,
|
||||
.path-grade-report-grader table td.userfield {
|
||||
text-align: left;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.path-grade-report-grader .usersuspended a:link,
|
||||
.path-grade-report-grader .usersuspended a:visited {
|
||||
color: #666;
|
||||
}
|
||||
.path-grade-report-grader table th.usersuspended img.usersuspendedicon {
|
||||
vertical-align: text-bottom;
|
||||
margin-left: .45em;
|
||||
table#user-grades .overridden .grade_icons {
|
||||
padding-left: 10px;
|
||||
}
|
||||
.path-grade-report-grader .yui3-overlay {
|
||||
background-color: #FFEE69;
|
||||
@@ -524,69 +517,234 @@ table#user-grades td.controls,
|
||||
left: 0;
|
||||
padding: 2px 5px;
|
||||
font-size: 0.7em;
|
||||
table#user-grades .catlevel1 .action-icon img {
|
||||
opacity: 0.5;
|
||||
}
|
||||
.path-grade-report-grader .yui3-overlay .fullname {
|
||||
color: #5F3E00;
|
||||
font-weight: bold;
|
||||
}
|
||||
.path-grade-report-grader .yui3-overlay .itemname {
|
||||
color: #194F3E;
|
||||
font-weight: bold;
|
||||
}
|
||||
.path-grade-report-grader .yui3-overlay .feedback {
|
||||
color: #5F595E;
|
||||
}
|
||||
/* table#user-grades td */
|
||||
/* .grader-report-grader table#user-grades td .yui-panel div.hd { */
|
||||
.path-grade-report-grader #tooltipPanel {
|
||||
text-align: left;
|
||||
}
|
||||
.path-grade-report-grader .yui3-overlay a.container-close {
|
||||
margin-top: -3px;
|
||||
}
|
||||
.path-grade-report-grader #hiddentooltiproot,
|
||||
.tooltipDiv {
|
||||
display: none;
|
||||
}
|
||||
.path-grade-report-grader.ie .right_scroller {
|
||||
overflow-y: hidden;
|
||||
}
|
||||
.path-grade-report-grader.ie table#fixed_column th {
|
||||
height: 4.5em;
|
||||
}
|
||||
.path-grade-report-grader.ie table#fixed_column tr.avg th {
|
||||
height: 2.1em;
|
||||
}
|
||||
.path-grade-report-grader.ie div.left_scroller td {
|
||||
height: 4.5em;
|
||||
}
|
||||
.path-grade-report-grader.ie6 div.right_scroller {
|
||||
margin-top: 4em;
|
||||
width: auto;
|
||||
position: absolute;
|
||||
}
|
||||
.path-grade-report-grader.ie6 .excludedfloater {
|
||||
font-size: 7px;
|
||||
table#user-grades .catlevel1 .action-icon.selected img {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
/** MDL-40071 **/
|
||||
.path-grade-report-grader.dir-rtl table th.user,
|
||||
.path-grade-report-grader.dir-rtl table td.userfield {
|
||||
text-align: right;
|
||||
#gradebook-header-container {
|
||||
font-size: 14px;
|
||||
background-color: #444;
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
#gradebook-header-container .gradebook-header-cell {
|
||||
background-color: #444;
|
||||
color: white;
|
||||
padding: 4px;
|
||||
white-space: nowrap;
|
||||
border: 1px solid #444;
|
||||
border-top: 0;
|
||||
border-right: 0;
|
||||
overflow: hidden;
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
#gradebook-header-container .gradebook-header-cell.catlevel1 {
|
||||
background-color: #333;
|
||||
}
|
||||
#gradebook-header-container .gradebook-header-cell.catlevel2 {
|
||||
background-color: #222;
|
||||
}
|
||||
#gradebook-header-container .gradebook-header-cell a {
|
||||
color: white;
|
||||
}
|
||||
#gradebook-header-container .gradebook-header-cell:hover {
|
||||
background-color: #111;
|
||||
}
|
||||
#gradebook-header-container .gradebook-header-cell .icon {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
vertical-align: middle;
|
||||
border: 0;
|
||||
padding-right: 6px;
|
||||
}
|
||||
|
||||
/** MDL-40180 **/
|
||||
.dir-rtl table#user-grades th.category,
|
||||
.dir-rtl table#user-grades th#studentheader,
|
||||
.dir-rtl table#user-grades th.user {
|
||||
text-align: right;
|
||||
#gradebook-user-container {
|
||||
background-color: #777;
|
||||
}
|
||||
.path-grade-report-grader.dir-rtl th.user img.userpicture {
|
||||
margin-left: 0.5em;
|
||||
#gradebook-user-container .gradebook-user-cell {
|
||||
background-color: #666;
|
||||
font-size: 14px;
|
||||
border: 1px solid #666;
|
||||
border-top: 0;
|
||||
padding: 4px;
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
#gradebook-user-container .gradebook-user-cell .userpicture {
|
||||
display: none;
|
||||
}
|
||||
#gradebook-user-container .gradebook-user-cell a {
|
||||
font-weight: normal;
|
||||
color: #fff;
|
||||
}
|
||||
#gradebook-user-container .gradebook-user-cell:nth-child(2n+1) {
|
||||
background-color: #777;
|
||||
border-bottom: 1px solid #777;
|
||||
}
|
||||
#gradebook-user-container .gradebook-user-cell:nth-child(2n):hover {
|
||||
background-color: #5c5c5c;
|
||||
}
|
||||
#gradebook-user-container .gradebook-user-cell:hover {
|
||||
background-color: #6d6d6d;
|
||||
}
|
||||
#gradebook-user-container .gradebook-user-cell:first-child {
|
||||
/*border-top: 1px solid #666;*/
|
||||
}
|
||||
|
||||
.path-grade-report-grader .yui3-scrollview-scrollbar {
|
||||
opacity: 1 !important;
|
||||
#gradebook-footer-container {
|
||||
display: none;
|
||||
font-size: 14px;
|
||||
background-color: #444;
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
#gradebook-footer-container.gradebook-footer-row-sticky {
|
||||
display: block;
|
||||
}
|
||||
#gradebook-footer-container.gradebook-footer-row-sticky .cell {
|
||||
border-top: 2px solid gray;
|
||||
}
|
||||
#gradebook-footer-container .gradebook-footer-cell {
|
||||
padding: 8px;
|
||||
font-size: 14px;
|
||||
background-color: #333;
|
||||
color: white;
|
||||
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-cell:nth-of-type(1) {
|
||||
text-align: right;
|
||||
}
|
||||
#gradebook-footer-container .gradebook-footer-cell .btn {
|
||||
float: left;
|
||||
}
|
||||
|
||||
#gradebook-user-header-container {
|
||||
background-color: #333;
|
||||
font-size: 14px;
|
||||
text-align: left;
|
||||
padding: 8px;
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
#gradebook-user-header-container a {
|
||||
color: white;
|
||||
}
|
||||
|
||||
.gradebook-loading-screen {
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
position: fixed;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
background-color: black;
|
||||
z-index: 99999;
|
||||
opacity: 0.8;
|
||||
padding: 10px;
|
||||
text-align: center;
|
||||
}
|
||||
.gradebook-loading-screen .gradebook-loading {
|
||||
padding-right: 40px;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.gradebook-loading i {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
display: inline-block;
|
||||
border-radius: 50%;
|
||||
background: #00b3d5;
|
||||
}
|
||||
|
||||
.gradebook-loading i:first-child {
|
||||
-webkit-animation: gradebook-loading-ani2 0.5s linear infinite;
|
||||
animation: gradebook-loading-ani2 0.5s linear infinite;
|
||||
opacity: 0;
|
||||
-webkit-transform: translate(-20px);
|
||||
-moz-transform: translate(-20px);
|
||||
-ms-transform: translate(-20px);
|
||||
-o-transform: translate(-20px);
|
||||
transform: translate(-20px);
|
||||
}
|
||||
|
||||
.gradebook-loading i:nth-child(2),
|
||||
.gradebook-loading i:nth-child(3) {
|
||||
-webkit-animation: gradebook-loading-ani3 0.5s linear infinite;
|
||||
animation: gradebook-loading-ani3 0.5s linear infinite;
|
||||
}
|
||||
|
||||
.gradebook-loading i:last-child {
|
||||
-webkit-animation: gradebook-loading-ani1 0.5s linear infinite;
|
||||
animation: gradebook-loading-ani1 0.5s linear infinite;
|
||||
}
|
||||
|
||||
@-webkit-keyframes gradebook-loading-ani1 {
|
||||
100% {
|
||||
-webkit-transform: translate(40px);
|
||||
-moz-transform: translate(40px);
|
||||
-ms-transform: translate(40px);
|
||||
-o-transform: translate(40px);
|
||||
transform: translate(40px);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes gradebook-loading-ani1 {
|
||||
100% {
|
||||
-webkit-transform: translate(40px);
|
||||
-moz-transform: translate(40px);
|
||||
-ms-transform: translate(40px);
|
||||
-o-transform: translate(40px);
|
||||
transform: translate(40px);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@-webkit-keyframes gradebook-loading-ani2 {
|
||||
100% {
|
||||
-webkit-transform: translate(20px);
|
||||
-moz-transform: translate(20px);
|
||||
-ms-transform: translate(20px);
|
||||
-o-transform: translate(20px);
|
||||
transform: translate(20px);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes gradebook-loading-ani2 {
|
||||
100% {
|
||||
-webkit-transform: translate(20px);
|
||||
-moz-transform: translate(20px);
|
||||
-ms-transform: translate(20px);
|
||||
-o-transform: translate(20px);
|
||||
transform: translate(20px);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@-webkit-keyframes gradebook-loading-ani3 {
|
||||
100% {
|
||||
-webkit-transform: translate(20px);
|
||||
-moz-transform: translate(20px);
|
||||
-ms-transform: translate(20px);
|
||||
-o-transform: translate(20px);
|
||||
transform: translate(20px);
|
||||
}
|
||||
}
|
||||
|
||||
.path-grade-report-grader .yui3-scrollview-scrollbar-horiz {
|
||||
@@ -627,6 +785,14 @@ table#user-grades th.category {
|
||||
}
|
||||
.path-grade-report-grader td.grade.overridden {
|
||||
line-height: 20px;
|
||||
@keyframes gradebook-loading-ani3 {
|
||||
100% {
|
||||
-webkit-transform: translate(20px);
|
||||
-moz-transform: translate(20px);
|
||||
-ms-transform: translate(20px);
|
||||
-o-transform: translate(20px);
|
||||
transform: translate(20px);
|
||||
}
|
||||
}
|
||||
|
||||
/** MDL-46812 **/
|
||||
|
||||
+397
@@ -0,0 +1,397 @@
|
||||
YUI.add('moodle-gradereport_grader-gradereporttable', function (Y, NAME) {
|
||||
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
/**
|
||||
* Static header and student column for grader table.
|
||||
*
|
||||
* @package gradereport_grader
|
||||
* @copyright 2014 UC Regents
|
||||
* @author Alfonso Roman <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
var LOGNS = 'moodle-gradereport_grader-gradereporttable';
|
||||
|
||||
M.gradereport_grader = M.gradereport_grader || {};
|
||||
|
||||
// Create a gradebook module
|
||||
M.gradereport_grader.gradereporttable = {
|
||||
// Resuable nodes
|
||||
node_student_header_cell: {},
|
||||
node_student_cell: {},
|
||||
node_footer_row: {},
|
||||
scrollevent: function() {
|
||||
console.log('scrolll event');
|
||||
},
|
||||
// Init module
|
||||
init: function() {
|
||||
Y.log('Loading grader report floating headers and columns.', 'debug', LOGNS);
|
||||
|
||||
// Set up some reusable nodes.
|
||||
this.node_student_header_cell = Y.one('#studentheader');
|
||||
// First student cell.
|
||||
this.node_student_cell = Y.one('#user-grades .user.cell');
|
||||
// Averages row.
|
||||
this.node_footer_row = Y.one('#user-grades .avg');
|
||||
|
||||
// Check if there are any students -- otherwise no need to do anything.
|
||||
if (this.node_student_cell) {
|
||||
// Generate floating elements.
|
||||
this.float_user_column();
|
||||
this.float_assignment_header();
|
||||
this.float_user_header();
|
||||
|
||||
// Onscroll event updates all the floating header/column positions.
|
||||
var onscroll = function() {
|
||||
|
||||
// Get better performance by preventing layout thrashing. This occurs
|
||||
// when the DOM is repeatedly updated and queried for updated values.
|
||||
//
|
||||
// To fix this, group reads and writes
|
||||
|
||||
//
|
||||
// First get all the readable values needed.
|
||||
|
||||
// Header row
|
||||
var headercontainer = document.getElementById('gradebook-header-container');
|
||||
var userheadercell = document.getElementById('studentheader');
|
||||
|
||||
var usercolumnheader = document.getElementById('gradebook-user-header-container');
|
||||
|
||||
var headercelltop = userheadercell.offsetTop + userheadercell.offsetParent.offsetTop;
|
||||
|
||||
// User column
|
||||
var pageleftcutoff = window.pageXOffset;
|
||||
var firstusercell = document.querySelectorAll("#user-grades .user.cell")[0];
|
||||
var firstusercellpos = firstusercell.offsetLeft + firstusercell.offsetParent.offsetLeft;
|
||||
|
||||
var usercolumn = document.getElementById('gradebook-user-container');
|
||||
|
||||
// Footer row
|
||||
var lastrow = document.querySelectorAll('#user-grades .avg')[0];
|
||||
var footer, lastrowpos;
|
||||
|
||||
// Check that Average footer is available.
|
||||
if (lastrow !== undefined) {
|
||||
footer = document.getElementById('gradebook-footer-container');
|
||||
lastrowpos = lastrow.offsetTop + lastrow.offsetParent.offsetTop;
|
||||
}
|
||||
|
||||
// Viewport values
|
||||
var pageYOffset = window.pageYOffset;
|
||||
var windowInnerHeight = window.innerHeight;
|
||||
|
||||
//
|
||||
// Next do all the writing.
|
||||
|
||||
// Header position
|
||||
headercontainer.style.left = userheadercell.offsetLeft + userheadercell.offsetParent.offsetLeft + 'px';
|
||||
if (pageYOffset > headercelltop) {
|
||||
headercontainer.style.top = pageYOffset + 40 + 'px';
|
||||
usercolumnheader.style.top = pageYOffset + 40 + 'px';
|
||||
} else {
|
||||
headercontainer.style.top = headercelltop + 'px';
|
||||
usercolumnheader.style.top = headercelltop + 'px';
|
||||
}
|
||||
|
||||
// User column position
|
||||
if (pageleftcutoff > firstusercellpos) {
|
||||
usercolumn.style.left = pageleftcutoff + 'px';
|
||||
usercolumnheader.style.left = pageleftcutoff + 'px';
|
||||
} else {
|
||||
usercolumn.style.left = firstusercellpos + 'px';
|
||||
usercolumnheader.style.left = firstusercellpos + 'px';
|
||||
}
|
||||
|
||||
// Update footer
|
||||
if (lastrow !== undefined) {
|
||||
footer.style.left = userheadercell.offsetLeft + userheadercell.offsetParent.offsetLeft + 'px';
|
||||
|
||||
if (pageYOffset + windowInnerHeight < lastrowpos) {
|
||||
footer.style.top = (pageYOffset + windowInnerHeight - 50) + 'px';
|
||||
footer.classList.add('gradebook-footer-row-sticky');
|
||||
} else {
|
||||
footer.style.top = lastrowpos + 'px';
|
||||
footer.classList.remove('gradebook-footer-row-sticky');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Add the floating 'average' footer if available.
|
||||
if (this.node_footer_row) {
|
||||
this.float_assignment_footer();
|
||||
}
|
||||
|
||||
// Set floating element initial positions by simulating scroll.
|
||||
onscroll();
|
||||
|
||||
// Generate events.
|
||||
//
|
||||
// Use native DOM scroll & resize events instead of YUI synthetic event.
|
||||
window.onscroll = onscroll;
|
||||
window.onresize = function() {
|
||||
|
||||
onscroll();
|
||||
|
||||
// Resize headers & footers.
|
||||
// This is an expensive operation, not expected to happen often.
|
||||
var headers = Y.all('#gradebook-header-container .gradebook-header-cell');
|
||||
var resizedcells = Y.all('#user-grades .heading .cell');
|
||||
|
||||
var headeroffsetleft = Y.one('#studentheader').getX();
|
||||
var newcontainerwidth = 0;
|
||||
resizedcells.each(function(cell, idx) {
|
||||
var headercell = headers.item(idx);
|
||||
|
||||
newcontainerwidth += cell.get('offsetWidth');
|
||||
var styles = {
|
||||
width: cell.get('offsetWidth'),
|
||||
left: cell.getX() - headeroffsetleft + 'px'
|
||||
};
|
||||
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');
|
||||
|
||||
resizedavgcells.each(function(cell, idx) {
|
||||
var footercell = footers.item(idx);
|
||||
var styles = {
|
||||
width: cell.get('offsetWidth'),
|
||||
left: cell.getX() - headeroffsetleft + 'px'
|
||||
};
|
||||
footercell.setStyles(styles);
|
||||
});
|
||||
Y.one('#gradebook-footer-container').setStyle('width', newcontainerwidth);
|
||||
}
|
||||
|
||||
Y.one('#gradebook-header-container').setStyle('width', newcontainerwidth);
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
// Remove loading screen. Need to do YUI synthetic event to trigger
|
||||
// on all browsers.
|
||||
Y.on('domready', function() {
|
||||
Y.one('.gradebook-loading-screen').remove(true);
|
||||
Y.all('#user-grades .overridden').setAttribute('aria-label', 'Overriden grade');
|
||||
});
|
||||
},
|
||||
float_user_column: function() {
|
||||
Y.log('Floating the user column.', 'debug', LOGNS);
|
||||
|
||||
// Grab the user names column
|
||||
var user_column = Y.all('#user-grades .user.cell');
|
||||
|
||||
// Generate a floating table
|
||||
var floating_user_column = Y.Node.create('<div aria-hidden="true" id="gradebook-user-container"></div>');
|
||||
var floating_user_column_height = 0;
|
||||
var user_column_offset = this.node_student_cell.getY();
|
||||
|
||||
user_column.each(function(node) {
|
||||
|
||||
// Create cloned node and container.
|
||||
// We'll absolutely position the container to each cell position,
|
||||
// this will guarantee that student cells are always aligned.
|
||||
var container_node = Y.Node.create('<div class="gradebook-user-cell"></div>');
|
||||
|
||||
// Grab the username
|
||||
var usernamenode = node.cloneNode(true);
|
||||
container_node.append(usernamenode.getHTML());
|
||||
usernamenode = null;
|
||||
|
||||
container_node.setStyles({
|
||||
'height': node.get('offsetHeight') + 'px',
|
||||
'width': node.get('offsetWidth') + 'px',
|
||||
'position': 'absolute',
|
||||
'top': (node.getY() - user_column_offset) + 'px'
|
||||
});
|
||||
|
||||
floating_user_column_height += node.get('offsetHeight');
|
||||
// Retrieve the corresponding row
|
||||
var classes = node.ancestor().getAttribute('class').split(' ').join('.');
|
||||
// Attach highlight event
|
||||
container_node.on('click', function() {
|
||||
Y.one('.' + classes).all('.grade').toggleClass('hmarked');
|
||||
});
|
||||
// Add the cloned nodes to our floating table
|
||||
floating_user_column.appendChild(container_node);
|
||||
|
||||
}, this);
|
||||
|
||||
// Style the table
|
||||
floating_user_column.setStyles({
|
||||
'position': 'absolute',
|
||||
'left': this.node_student_cell.getX() + 'px',
|
||||
'top': this.node_student_cell.getY() + 'px',
|
||||
'width': this.node_student_cell.get('offsetWidth'),
|
||||
'height': floating_user_column_height + 'px',
|
||||
'background-color': '#f9f9f9'
|
||||
});
|
||||
|
||||
Y.one('body').append(floating_user_column);
|
||||
},
|
||||
float_user_header: function() {
|
||||
Y.log('Floating the user column header.', 'debug', LOGNS);
|
||||
|
||||
// Float the 'user name' header cell.
|
||||
var floating_user_header_cell = Y.Node.create('<div aria-hidden="true" id="gradebook-user-header-container"></div>');
|
||||
|
||||
// Clone the node
|
||||
var cellnode = this.node_student_header_cell.cloneNode(true);
|
||||
// Append node contents
|
||||
floating_user_header_cell.append(cellnode.getHTML());
|
||||
floating_user_header_cell.setStyles({
|
||||
'position': 'absolute',
|
||||
'left': this.node_student_cell.getX() + 'px',
|
||||
'top': this.node_student_header_cell.getY() + 'px',
|
||||
'width': '200px',
|
||||
'height': this.node_student_header_cell.get('offsetHeight') + 'px'
|
||||
});
|
||||
|
||||
// Safe for collection
|
||||
cellnode = null;
|
||||
|
||||
Y.one('body').append(floating_user_header_cell);
|
||||
},
|
||||
float_assignment_header: function() {
|
||||
Y.log('Floating the assignment header.', 'debug', LOGNS);
|
||||
|
||||
var grade_headers = Y.all('#user-grades tr.heading .cell');
|
||||
|
||||
// Generate a floating headers
|
||||
var floating_grade_headers = Y.Node.create('<div aria-hidden="true" id="gradebook-header-container"></div>');
|
||||
|
||||
var floating_grade_headers_width = 0;
|
||||
var floating_grade_headers_height = 0;
|
||||
var grade_headers_offset = this.node_student_header_cell.getX();
|
||||
|
||||
grade_headers.each(function(node) {
|
||||
|
||||
// Get the target column to highlight. This is embedded in
|
||||
// the column cell #, but it's off by one, so need to adjust for that.
|
||||
var col = node.getAttribute('class');
|
||||
|
||||
// Extract the column #
|
||||
var search = /c[0-9]+/g;
|
||||
var match = search.exec(col);
|
||||
match = match[0].replace('c', '');
|
||||
|
||||
// Offset
|
||||
var target_col = parseInt(match, 10);
|
||||
++target_col;
|
||||
|
||||
var nodepos = node.getX();
|
||||
|
||||
// We need to clone the node, otherwise we mutate original obj
|
||||
var nodeclone = node.cloneNode(true);
|
||||
|
||||
var newnode = Y.Node.create('<div class="gradebook-header-cell"></div>');
|
||||
newnode.append(nodeclone.getHTML());
|
||||
newnode.addClass(nodeclone.getAttribute('class'));
|
||||
nodeclone = null;
|
||||
|
||||
newnode.setStyles({
|
||||
'width': node.get('offsetWidth') + 'px',
|
||||
'height': node.get('offsetHeight') + 'px',
|
||||
'position': 'absolute',
|
||||
'left': (nodepos - grade_headers_offset) + 'px'
|
||||
});
|
||||
|
||||
// Sum up total width
|
||||
floating_grade_headers_width += parseInt(node.get('offsetWidth'), 10);
|
||||
floating_grade_headers_height = node.get('offsetHeight');
|
||||
|
||||
// Attach 'highlight column' event to new node
|
||||
newnode.on('click', function() {
|
||||
Y.all('.cell.c' + target_col).toggleClass('vmarked');
|
||||
});
|
||||
|
||||
// Append to floating table.
|
||||
floating_grade_headers.appendChild(newnode);
|
||||
}, this);
|
||||
|
||||
// Position header table.
|
||||
floating_grade_headers.setStyles({
|
||||
'position': 'absolute',
|
||||
'top': this.node_student_header_cell.getY() + 'px',
|
||||
'left': this.node_student_header_cell.getX() + 'px',
|
||||
'width': floating_grade_headers_width + 'px',
|
||||
'height': floating_grade_headers_height + 'px'
|
||||
});
|
||||
|
||||
Y.one('body').append(floating_grade_headers);
|
||||
},
|
||||
float_assignment_footer: function() {
|
||||
Y.log('Floating the averages footer.', 'debug', LOGNS);
|
||||
|
||||
// Generate the sticky footer row.
|
||||
// Grab the row.
|
||||
var footer_row = Y.all('#user-grades .lastrow .cell');
|
||||
// Create a container.
|
||||
var floating_grade_footers = Y.Node.create('<div aria-hidden="true" id="gradebook-footer-container"></div>');
|
||||
var floating_grade_footer_width = 0;
|
||||
var footer_row_offset = this.node_footer_row.getX();
|
||||
// Copy nodes
|
||||
footer_row.each(function(node) {
|
||||
|
||||
var nodepos = node.getX();
|
||||
var cellnodeclone = node.cloneNode(true);
|
||||
|
||||
var newnode = Y.Node.create('<div class="gradebook-footer-cell"></div>');
|
||||
newnode.append(cellnodeclone.getHTML());
|
||||
newnode.setStyles({
|
||||
'width': node.get('offsetWidth') + 'px',
|
||||
'height': '50px',
|
||||
'position': 'absolute',
|
||||
'left': (nodepos - footer_row_offset) + 'px'
|
||||
});
|
||||
|
||||
floating_grade_footers.append(newnode);
|
||||
floating_grade_footer_width += parseInt(node.get('offsetWidth'), 10);
|
||||
}, this);
|
||||
|
||||
// Attach 'Update' button.
|
||||
var update_button = Y.one('#gradersubmit');
|
||||
if (update_button) {
|
||||
var button = Y.Node.create('<button class="btn btn-sm btn-default">' + update_button.getAttribute('value') + '</button>');
|
||||
button.on('click', function() {
|
||||
YUI().use('node-event-simulate', function(Y) {
|
||||
Y.one('#gradersubmit').simulate('click');
|
||||
});
|
||||
});
|
||||
floating_grade_footers.one('.gradebook-footer-cell').append(button);
|
||||
}
|
||||
|
||||
// Position the row
|
||||
floating_grade_footers.setStyles({
|
||||
'position': 'absolute',
|
||||
'left': this.node_footer_row.getX() + 'px',
|
||||
'bottom': '0',
|
||||
'height': '50px',
|
||||
'width': floating_grade_footer_width + 'px'
|
||||
});
|
||||
|
||||
Y.one('body').append(floating_grade_footers);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}, '@VERSION@');
|
||||
+1
File diff suppressed because one or more lines are too long
+392
@@ -0,0 +1,392 @@
|
||||
YUI.add('moodle-gradereport_grader-gradereporttable', function (Y, NAME) {
|
||||
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
/**
|
||||
* Static header and student column for grader table.
|
||||
*
|
||||
* @package gradereport_grader
|
||||
* @copyright 2014 UC Regents
|
||||
* @author Alfonso Roman <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
var LOGNS = 'moodle-gradereport_grader-gradereporttable';
|
||||
|
||||
M.gradereport_grader = M.gradereport_grader || {};
|
||||
|
||||
// Create a gradebook module
|
||||
M.gradereport_grader.gradereporttable = {
|
||||
// Resuable nodes
|
||||
node_student_header_cell: {},
|
||||
node_student_cell: {},
|
||||
node_footer_row: {},
|
||||
scrollevent: function() {
|
||||
console.log('scrolll event');
|
||||
},
|
||||
// Init module
|
||||
init: function() {
|
||||
|
||||
// Set up some reusable nodes.
|
||||
this.node_student_header_cell = Y.one('#studentheader');
|
||||
// First student cell.
|
||||
this.node_student_cell = Y.one('#user-grades .user.cell');
|
||||
// Averages row.
|
||||
this.node_footer_row = Y.one('#user-grades .avg');
|
||||
|
||||
// Check if there are any students -- otherwise no need to do anything.
|
||||
if (this.node_student_cell) {
|
||||
// Generate floating elements.
|
||||
this.float_user_column();
|
||||
this.float_assignment_header();
|
||||
this.float_user_header();
|
||||
|
||||
// Onscroll event updates all the floating header/column positions.
|
||||
var onscroll = function() {
|
||||
|
||||
// Get better performance by preventing layout thrashing. This occurs
|
||||
// when the DOM is repeatedly updated and queried for updated values.
|
||||
//
|
||||
// To fix this, group reads and writes
|
||||
|
||||
//
|
||||
// First get all the readable values needed.
|
||||
|
||||
// Header row
|
||||
var headercontainer = document.getElementById('gradebook-header-container');
|
||||
var userheadercell = document.getElementById('studentheader');
|
||||
|
||||
var usercolumnheader = document.getElementById('gradebook-user-header-container');
|
||||
|
||||
var headercelltop = userheadercell.offsetTop + userheadercell.offsetParent.offsetTop;
|
||||
|
||||
// User column
|
||||
var pageleftcutoff = window.pageXOffset;
|
||||
var firstusercell = document.querySelectorAll("#user-grades .user.cell")[0];
|
||||
var firstusercellpos = firstusercell.offsetLeft + firstusercell.offsetParent.offsetLeft;
|
||||
|
||||
var usercolumn = document.getElementById('gradebook-user-container');
|
||||
|
||||
// Footer row
|
||||
var lastrow = document.querySelectorAll('#user-grades .avg')[0];
|
||||
var footer, lastrowpos;
|
||||
|
||||
// Check that Average footer is available.
|
||||
if (lastrow !== undefined) {
|
||||
footer = document.getElementById('gradebook-footer-container');
|
||||
lastrowpos = lastrow.offsetTop + lastrow.offsetParent.offsetTop;
|
||||
}
|
||||
|
||||
// Viewport values
|
||||
var pageYOffset = window.pageYOffset;
|
||||
var windowInnerHeight = window.innerHeight;
|
||||
|
||||
//
|
||||
// Next do all the writing.
|
||||
|
||||
// Header position
|
||||
headercontainer.style.left = userheadercell.offsetLeft + userheadercell.offsetParent.offsetLeft + 'px';
|
||||
if (pageYOffset > headercelltop) {
|
||||
headercontainer.style.top = pageYOffset + 40 + 'px';
|
||||
usercolumnheader.style.top = pageYOffset + 40 + 'px';
|
||||
} else {
|
||||
headercontainer.style.top = headercelltop + 'px';
|
||||
usercolumnheader.style.top = headercelltop + 'px';
|
||||
}
|
||||
|
||||
// User column position
|
||||
if (pageleftcutoff > firstusercellpos) {
|
||||
usercolumn.style.left = pageleftcutoff + 'px';
|
||||
usercolumnheader.style.left = pageleftcutoff + 'px';
|
||||
} else {
|
||||
usercolumn.style.left = firstusercellpos + 'px';
|
||||
usercolumnheader.style.left = firstusercellpos + 'px';
|
||||
}
|
||||
|
||||
// Update footer
|
||||
if (lastrow !== undefined) {
|
||||
footer.style.left = userheadercell.offsetLeft + userheadercell.offsetParent.offsetLeft + 'px';
|
||||
|
||||
if (pageYOffset + windowInnerHeight < lastrowpos) {
|
||||
footer.style.top = (pageYOffset + windowInnerHeight - 50) + 'px';
|
||||
footer.classList.add('gradebook-footer-row-sticky');
|
||||
} else {
|
||||
footer.style.top = lastrowpos + 'px';
|
||||
footer.classList.remove('gradebook-footer-row-sticky');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Add the floating 'average' footer if available.
|
||||
if (this.node_footer_row) {
|
||||
this.float_assignment_footer();
|
||||
}
|
||||
|
||||
// Set floating element initial positions by simulating scroll.
|
||||
onscroll();
|
||||
|
||||
// Generate events.
|
||||
//
|
||||
// Use native DOM scroll & resize events instead of YUI synthetic event.
|
||||
window.onscroll = onscroll;
|
||||
window.onresize = function() {
|
||||
|
||||
onscroll();
|
||||
|
||||
// Resize headers & footers.
|
||||
// This is an expensive operation, not expected to happen often.
|
||||
var headers = Y.all('#gradebook-header-container .gradebook-header-cell');
|
||||
var resizedcells = Y.all('#user-grades .heading .cell');
|
||||
|
||||
var headeroffsetleft = Y.one('#studentheader').getX();
|
||||
var newcontainerwidth = 0;
|
||||
resizedcells.each(function(cell, idx) {
|
||||
var headercell = headers.item(idx);
|
||||
|
||||
newcontainerwidth += cell.get('offsetWidth');
|
||||
var styles = {
|
||||
width: cell.get('offsetWidth'),
|
||||
left: cell.getX() - headeroffsetleft + 'px'
|
||||
};
|
||||
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');
|
||||
|
||||
resizedavgcells.each(function(cell, idx) {
|
||||
var footercell = footers.item(idx);
|
||||
var styles = {
|
||||
width: cell.get('offsetWidth'),
|
||||
left: cell.getX() - headeroffsetleft + 'px'
|
||||
};
|
||||
footercell.setStyles(styles);
|
||||
});
|
||||
Y.one('#gradebook-footer-container').setStyle('width', newcontainerwidth);
|
||||
}
|
||||
|
||||
Y.one('#gradebook-header-container').setStyle('width', newcontainerwidth);
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
// Remove loading screen. Need to do YUI synthetic event to trigger
|
||||
// on all browsers.
|
||||
Y.on('domready', function() {
|
||||
Y.one('.gradebook-loading-screen').remove(true);
|
||||
Y.all('#user-grades .overridden').setAttribute('aria-label', 'Overriden grade');
|
||||
});
|
||||
},
|
||||
float_user_column: function() {
|
||||
|
||||
// Grab the user names column
|
||||
var user_column = Y.all('#user-grades .user.cell');
|
||||
|
||||
// Generate a floating table
|
||||
var floating_user_column = Y.Node.create('<div aria-hidden="true" id="gradebook-user-container"></div>');
|
||||
var floating_user_column_height = 0;
|
||||
var user_column_offset = this.node_student_cell.getY();
|
||||
|
||||
user_column.each(function(node) {
|
||||
|
||||
// Create cloned node and container.
|
||||
// We'll absolutely position the container to each cell position,
|
||||
// this will guarantee that student cells are always aligned.
|
||||
var container_node = Y.Node.create('<div class="gradebook-user-cell"></div>');
|
||||
|
||||
// Grab the username
|
||||
var usernamenode = node.cloneNode(true);
|
||||
container_node.append(usernamenode.getHTML());
|
||||
usernamenode = null;
|
||||
|
||||
container_node.setStyles({
|
||||
'height': node.get('offsetHeight') + 'px',
|
||||
'width': node.get('offsetWidth') + 'px',
|
||||
'position': 'absolute',
|
||||
'top': (node.getY() - user_column_offset) + 'px'
|
||||
});
|
||||
|
||||
floating_user_column_height += node.get('offsetHeight');
|
||||
// Retrieve the corresponding row
|
||||
var classes = node.ancestor().getAttribute('class').split(' ').join('.');
|
||||
// Attach highlight event
|
||||
container_node.on('click', function() {
|
||||
Y.one('.' + classes).all('.grade').toggleClass('hmarked');
|
||||
});
|
||||
// Add the cloned nodes to our floating table
|
||||
floating_user_column.appendChild(container_node);
|
||||
|
||||
}, this);
|
||||
|
||||
// Style the table
|
||||
floating_user_column.setStyles({
|
||||
'position': 'absolute',
|
||||
'left': this.node_student_cell.getX() + 'px',
|
||||
'top': this.node_student_cell.getY() + 'px',
|
||||
'width': this.node_student_cell.get('offsetWidth'),
|
||||
'height': floating_user_column_height + 'px',
|
||||
'background-color': '#f9f9f9'
|
||||
});
|
||||
|
||||
Y.one('body').append(floating_user_column);
|
||||
},
|
||||
float_user_header: function() {
|
||||
|
||||
// Float the 'user name' header cell.
|
||||
var floating_user_header_cell = Y.Node.create('<div aria-hidden="true" id="gradebook-user-header-container"></div>');
|
||||
|
||||
// Clone the node
|
||||
var cellnode = this.node_student_header_cell.cloneNode(true);
|
||||
// Append node contents
|
||||
floating_user_header_cell.append(cellnode.getHTML());
|
||||
floating_user_header_cell.setStyles({
|
||||
'position': 'absolute',
|
||||
'left': this.node_student_cell.getX() + 'px',
|
||||
'top': this.node_student_header_cell.getY() + 'px',
|
||||
'width': '200px',
|
||||
'height': this.node_student_header_cell.get('offsetHeight') + 'px'
|
||||
});
|
||||
|
||||
// Safe for collection
|
||||
cellnode = null;
|
||||
|
||||
Y.one('body').append(floating_user_header_cell);
|
||||
},
|
||||
float_assignment_header: function() {
|
||||
|
||||
var grade_headers = Y.all('#user-grades tr.heading .cell');
|
||||
|
||||
// Generate a floating headers
|
||||
var floating_grade_headers = Y.Node.create('<div aria-hidden="true" id="gradebook-header-container"></div>');
|
||||
|
||||
var floating_grade_headers_width = 0;
|
||||
var floating_grade_headers_height = 0;
|
||||
var grade_headers_offset = this.node_student_header_cell.getX();
|
||||
|
||||
grade_headers.each(function(node) {
|
||||
|
||||
// Get the target column to highlight. This is embedded in
|
||||
// the column cell #, but it's off by one, so need to adjust for that.
|
||||
var col = node.getAttribute('class');
|
||||
|
||||
// Extract the column #
|
||||
var search = /c[0-9]+/g;
|
||||
var match = search.exec(col);
|
||||
match = match[0].replace('c', '');
|
||||
|
||||
// Offset
|
||||
var target_col = parseInt(match, 10);
|
||||
++target_col;
|
||||
|
||||
var nodepos = node.getX();
|
||||
|
||||
// We need to clone the node, otherwise we mutate original obj
|
||||
var nodeclone = node.cloneNode(true);
|
||||
|
||||
var newnode = Y.Node.create('<div class="gradebook-header-cell"></div>');
|
||||
newnode.append(nodeclone.getHTML());
|
||||
newnode.addClass(nodeclone.getAttribute('class'));
|
||||
nodeclone = null;
|
||||
|
||||
newnode.setStyles({
|
||||
'width': node.get('offsetWidth') + 'px',
|
||||
'height': node.get('offsetHeight') + 'px',
|
||||
'position': 'absolute',
|
||||
'left': (nodepos - grade_headers_offset) + 'px'
|
||||
});
|
||||
|
||||
// Sum up total width
|
||||
floating_grade_headers_width += parseInt(node.get('offsetWidth'), 10);
|
||||
floating_grade_headers_height = node.get('offsetHeight');
|
||||
|
||||
// Attach 'highlight column' event to new node
|
||||
newnode.on('click', function() {
|
||||
Y.all('.cell.c' + target_col).toggleClass('vmarked');
|
||||
});
|
||||
|
||||
// Append to floating table.
|
||||
floating_grade_headers.appendChild(newnode);
|
||||
}, this);
|
||||
|
||||
// Position header table.
|
||||
floating_grade_headers.setStyles({
|
||||
'position': 'absolute',
|
||||
'top': this.node_student_header_cell.getY() + 'px',
|
||||
'left': this.node_student_header_cell.getX() + 'px',
|
||||
'width': floating_grade_headers_width + 'px',
|
||||
'height': floating_grade_headers_height + 'px'
|
||||
});
|
||||
|
||||
Y.one('body').append(floating_grade_headers);
|
||||
},
|
||||
float_assignment_footer: function() {
|
||||
|
||||
// Generate the sticky footer row.
|
||||
// Grab the row.
|
||||
var footer_row = Y.all('#user-grades .lastrow .cell');
|
||||
// Create a container.
|
||||
var floating_grade_footers = Y.Node.create('<div aria-hidden="true" id="gradebook-footer-container"></div>');
|
||||
var floating_grade_footer_width = 0;
|
||||
var footer_row_offset = this.node_footer_row.getX();
|
||||
// Copy nodes
|
||||
footer_row.each(function(node) {
|
||||
|
||||
var nodepos = node.getX();
|
||||
var cellnodeclone = node.cloneNode(true);
|
||||
|
||||
var newnode = Y.Node.create('<div class="gradebook-footer-cell"></div>');
|
||||
newnode.append(cellnodeclone.getHTML());
|
||||
newnode.setStyles({
|
||||
'width': node.get('offsetWidth') + 'px',
|
||||
'height': '50px',
|
||||
'position': 'absolute',
|
||||
'left': (nodepos - footer_row_offset) + 'px'
|
||||
});
|
||||
|
||||
floating_grade_footers.append(newnode);
|
||||
floating_grade_footer_width += parseInt(node.get('offsetWidth'), 10);
|
||||
}, this);
|
||||
|
||||
// Attach 'Update' button.
|
||||
var update_button = Y.one('#gradersubmit');
|
||||
if (update_button) {
|
||||
var button = Y.Node.create('<button class="btn btn-sm btn-default">' + update_button.getAttribute('value') + '</button>');
|
||||
button.on('click', function() {
|
||||
YUI().use('node-event-simulate', function(Y) {
|
||||
Y.one('#gradersubmit').simulate('click');
|
||||
});
|
||||
});
|
||||
floating_grade_footers.one('.gradebook-footer-cell').append(button);
|
||||
}
|
||||
|
||||
// Position the row
|
||||
floating_grade_footers.setStyles({
|
||||
'position': 'absolute',
|
||||
'left': this.node_footer_row.getX() + 'px',
|
||||
'bottom': '0',
|
||||
'height': '50px',
|
||||
'width': floating_grade_footer_width + 'px'
|
||||
});
|
||||
|
||||
Y.one('body').append(floating_grade_footers);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}, '@VERSION@');
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"name": "moodle-gradereport_grader-gradereporttable",
|
||||
"builds": {
|
||||
"moodle-gradereport_grader-gradereporttable": {
|
||||
"jsfiles": [
|
||||
"gradereporttable.js"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,392 @@
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
/**
|
||||
* Static header and student column for grader table.
|
||||
*
|
||||
* @package gradereport_grader
|
||||
* @copyright 2014 UC Regents
|
||||
* @author Alfonso Roman <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
var LOGNS = 'moodle-gradereport_grader-gradereporttable';
|
||||
|
||||
M.gradereport_grader = M.gradereport_grader || {};
|
||||
|
||||
// Create a gradebook module
|
||||
M.gradereport_grader.gradereporttable = {
|
||||
// Resuable nodes
|
||||
node_student_header_cell: {},
|
||||
node_student_cell: {},
|
||||
node_footer_row: {},
|
||||
scrollevent: function() {
|
||||
console.log('scrolll event');
|
||||
},
|
||||
// Init module
|
||||
init: function() {
|
||||
Y.log('Loading grader report floating headers and columns.', 'debug', LOGNS);
|
||||
|
||||
// Set up some reusable nodes.
|
||||
this.node_student_header_cell = Y.one('#studentheader');
|
||||
// First student cell.
|
||||
this.node_student_cell = Y.one('#user-grades .user.cell');
|
||||
// Averages row.
|
||||
this.node_footer_row = Y.one('#user-grades .avg');
|
||||
|
||||
// Check if there are any students -- otherwise no need to do anything.
|
||||
if (this.node_student_cell) {
|
||||
// Generate floating elements.
|
||||
this.float_user_column();
|
||||
this.float_assignment_header();
|
||||
this.float_user_header();
|
||||
|
||||
// Onscroll event updates all the floating header/column positions.
|
||||
var onscroll = function() {
|
||||
|
||||
// Get better performance by preventing layout thrashing. This occurs
|
||||
// when the DOM is repeatedly updated and queried for updated values.
|
||||
//
|
||||
// To fix this, group reads and writes
|
||||
|
||||
//
|
||||
// First get all the readable values needed.
|
||||
|
||||
// Header row
|
||||
var headercontainer = document.getElementById('gradebook-header-container');
|
||||
var userheadercell = document.getElementById('studentheader');
|
||||
|
||||
var usercolumnheader = document.getElementById('gradebook-user-header-container');
|
||||
|
||||
var headercelltop = userheadercell.offsetTop + userheadercell.offsetParent.offsetTop;
|
||||
|
||||
// User column
|
||||
var pageleftcutoff = window.pageXOffset;
|
||||
var firstusercell = document.querySelectorAll("#user-grades .user.cell")[0];
|
||||
var firstusercellpos = firstusercell.offsetLeft + firstusercell.offsetParent.offsetLeft;
|
||||
|
||||
var usercolumn = document.getElementById('gradebook-user-container');
|
||||
|
||||
// Footer row
|
||||
var lastrow = document.querySelectorAll('#user-grades .avg')[0];
|
||||
var footer, lastrowpos;
|
||||
|
||||
// Check that Average footer is available.
|
||||
if (lastrow !== undefined) {
|
||||
footer = document.getElementById('gradebook-footer-container');
|
||||
lastrowpos = lastrow.offsetTop + lastrow.offsetParent.offsetTop;
|
||||
}
|
||||
|
||||
// Viewport values
|
||||
var pageYOffset = window.pageYOffset;
|
||||
var windowInnerHeight = window.innerHeight;
|
||||
|
||||
//
|
||||
// Next do all the writing.
|
||||
|
||||
// Header position
|
||||
headercontainer.style.left = userheadercell.offsetLeft + userheadercell.offsetParent.offsetLeft + 'px';
|
||||
if (pageYOffset > headercelltop) {
|
||||
headercontainer.style.top = pageYOffset + 40 + 'px';
|
||||
usercolumnheader.style.top = pageYOffset + 40 + 'px';
|
||||
} else {
|
||||
headercontainer.style.top = headercelltop + 'px';
|
||||
usercolumnheader.style.top = headercelltop + 'px';
|
||||
}
|
||||
|
||||
// User column position
|
||||
if (pageleftcutoff > firstusercellpos) {
|
||||
usercolumn.style.left = pageleftcutoff + 'px';
|
||||
usercolumnheader.style.left = pageleftcutoff + 'px';
|
||||
} else {
|
||||
usercolumn.style.left = firstusercellpos + 'px';
|
||||
usercolumnheader.style.left = firstusercellpos + 'px';
|
||||
}
|
||||
|
||||
// Update footer
|
||||
if (lastrow !== undefined) {
|
||||
footer.style.left = userheadercell.offsetLeft + userheadercell.offsetParent.offsetLeft + 'px';
|
||||
|
||||
if (pageYOffset + windowInnerHeight < lastrowpos) {
|
||||
footer.style.top = (pageYOffset + windowInnerHeight - 50) + 'px';
|
||||
footer.classList.add('gradebook-footer-row-sticky');
|
||||
} else {
|
||||
footer.style.top = lastrowpos + 'px';
|
||||
footer.classList.remove('gradebook-footer-row-sticky');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Add the floating 'average' footer if available.
|
||||
if (this.node_footer_row) {
|
||||
this.float_assignment_footer();
|
||||
}
|
||||
|
||||
// Set floating element initial positions by simulating scroll.
|
||||
onscroll();
|
||||
|
||||
// Generate events.
|
||||
//
|
||||
// Use native DOM scroll & resize events instead of YUI synthetic event.
|
||||
window.onscroll = onscroll;
|
||||
window.onresize = function() {
|
||||
|
||||
onscroll();
|
||||
|
||||
// Resize headers & footers.
|
||||
// This is an expensive operation, not expected to happen often.
|
||||
var headers = Y.all('#gradebook-header-container .gradebook-header-cell');
|
||||
var resizedcells = Y.all('#user-grades .heading .cell');
|
||||
|
||||
var headeroffsetleft = Y.one('#studentheader').getX();
|
||||
var newcontainerwidth = 0;
|
||||
resizedcells.each(function(cell, idx) {
|
||||
var headercell = headers.item(idx);
|
||||
|
||||
newcontainerwidth += cell.get('offsetWidth');
|
||||
var styles = {
|
||||
width: cell.get('offsetWidth'),
|
||||
left: cell.getX() - headeroffsetleft + 'px'
|
||||
};
|
||||
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');
|
||||
|
||||
resizedavgcells.each(function(cell, idx) {
|
||||
var footercell = footers.item(idx);
|
||||
var styles = {
|
||||
width: cell.get('offsetWidth'),
|
||||
left: cell.getX() - headeroffsetleft + 'px'
|
||||
};
|
||||
footercell.setStyles(styles);
|
||||
});
|
||||
Y.one('#gradebook-footer-container').setStyle('width', newcontainerwidth);
|
||||
}
|
||||
|
||||
Y.one('#gradebook-header-container').setStyle('width', newcontainerwidth);
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
// Remove loading screen. Need to do YUI synthetic event to trigger
|
||||
// on all browsers.
|
||||
Y.on('domready', function() {
|
||||
Y.one('.gradebook-loading-screen').remove(true);
|
||||
Y.all('#user-grades .overridden').setAttribute('aria-label', 'Overriden grade');
|
||||
});
|
||||
},
|
||||
float_user_column: function() {
|
||||
Y.log('Floating the user column.', 'debug', LOGNS);
|
||||
|
||||
// Grab the user names column
|
||||
var user_column = Y.all('#user-grades .user.cell');
|
||||
|
||||
// Generate a floating table
|
||||
var floating_user_column = Y.Node.create('<div aria-hidden="true" id="gradebook-user-container"></div>');
|
||||
var floating_user_column_height = 0;
|
||||
var user_column_offset = this.node_student_cell.getY();
|
||||
|
||||
user_column.each(function(node) {
|
||||
|
||||
// Create cloned node and container.
|
||||
// We'll absolutely position the container to each cell position,
|
||||
// this will guarantee that student cells are always aligned.
|
||||
var container_node = Y.Node.create('<div class="gradebook-user-cell"></div>');
|
||||
|
||||
// Grab the username
|
||||
var usernamenode = node.cloneNode(true);
|
||||
container_node.append(usernamenode.getHTML());
|
||||
usernamenode = null;
|
||||
|
||||
container_node.setStyles({
|
||||
'height': node.get('offsetHeight') + 'px',
|
||||
'width': node.get('offsetWidth') + 'px',
|
||||
'position': 'absolute',
|
||||
'top': (node.getY() - user_column_offset) + 'px'
|
||||
});
|
||||
|
||||
floating_user_column_height += node.get('offsetHeight');
|
||||
// Retrieve the corresponding row
|
||||
var classes = node.ancestor().getAttribute('class').split(' ').join('.');
|
||||
// Attach highlight event
|
||||
container_node.on('click', function() {
|
||||
Y.one('.' + classes).all('.grade').toggleClass('hmarked');
|
||||
});
|
||||
// Add the cloned nodes to our floating table
|
||||
floating_user_column.appendChild(container_node);
|
||||
|
||||
}, this);
|
||||
|
||||
// Style the table
|
||||
floating_user_column.setStyles({
|
||||
'position': 'absolute',
|
||||
'left': this.node_student_cell.getX() + 'px',
|
||||
'top': this.node_student_cell.getY() + 'px',
|
||||
'width': this.node_student_cell.get('offsetWidth'),
|
||||
'height': floating_user_column_height + 'px',
|
||||
'background-color': '#f9f9f9'
|
||||
});
|
||||
|
||||
Y.one('body').append(floating_user_column);
|
||||
},
|
||||
float_user_header: function() {
|
||||
Y.log('Floating the user column header.', 'debug', LOGNS);
|
||||
|
||||
// Float the 'user name' header cell.
|
||||
var floating_user_header_cell = Y.Node.create('<div aria-hidden="true" id="gradebook-user-header-container"></div>');
|
||||
|
||||
// Clone the node
|
||||
var cellnode = this.node_student_header_cell.cloneNode(true);
|
||||
// Append node contents
|
||||
floating_user_header_cell.append(cellnode.getHTML());
|
||||
floating_user_header_cell.setStyles({
|
||||
'position': 'absolute',
|
||||
'left': this.node_student_cell.getX() + 'px',
|
||||
'top': this.node_student_header_cell.getY() + 'px',
|
||||
'width': '200px',
|
||||
'height': this.node_student_header_cell.get('offsetHeight') + 'px'
|
||||
});
|
||||
|
||||
// Safe for collection
|
||||
cellnode = null;
|
||||
|
||||
Y.one('body').append(floating_user_header_cell);
|
||||
},
|
||||
float_assignment_header: function() {
|
||||
Y.log('Floating the assignment header.', 'debug', LOGNS);
|
||||
|
||||
var grade_headers = Y.all('#user-grades tr.heading .cell');
|
||||
|
||||
// Generate a floating headers
|
||||
var floating_grade_headers = Y.Node.create('<div aria-hidden="true" id="gradebook-header-container"></div>');
|
||||
|
||||
var floating_grade_headers_width = 0;
|
||||
var floating_grade_headers_height = 0;
|
||||
var grade_headers_offset = this.node_student_header_cell.getX();
|
||||
|
||||
grade_headers.each(function(node) {
|
||||
|
||||
// Get the target column to highlight. This is embedded in
|
||||
// the column cell #, but it's off by one, so need to adjust for that.
|
||||
var col = node.getAttribute('class');
|
||||
|
||||
// Extract the column #
|
||||
var search = /c[0-9]+/g;
|
||||
var match = search.exec(col);
|
||||
match = match[0].replace('c', '');
|
||||
|
||||
// Offset
|
||||
var target_col = parseInt(match, 10);
|
||||
++target_col;
|
||||
|
||||
var nodepos = node.getX();
|
||||
|
||||
// We need to clone the node, otherwise we mutate original obj
|
||||
var nodeclone = node.cloneNode(true);
|
||||
|
||||
var newnode = Y.Node.create('<div class="gradebook-header-cell"></div>');
|
||||
newnode.append(nodeclone.getHTML());
|
||||
newnode.addClass(nodeclone.getAttribute('class'));
|
||||
nodeclone = null;
|
||||
|
||||
newnode.setStyles({
|
||||
'width': node.get('offsetWidth') + 'px',
|
||||
'height': node.get('offsetHeight') + 'px',
|
||||
'position': 'absolute',
|
||||
'left': (nodepos - grade_headers_offset) + 'px'
|
||||
});
|
||||
|
||||
// Sum up total width
|
||||
floating_grade_headers_width += parseInt(node.get('offsetWidth'), 10);
|
||||
floating_grade_headers_height = node.get('offsetHeight');
|
||||
|
||||
// Attach 'highlight column' event to new node
|
||||
newnode.on('click', function() {
|
||||
Y.all('.cell.c' + target_col).toggleClass('vmarked');
|
||||
});
|
||||
|
||||
// Append to floating table.
|
||||
floating_grade_headers.appendChild(newnode);
|
||||
}, this);
|
||||
|
||||
// Position header table.
|
||||
floating_grade_headers.setStyles({
|
||||
'position': 'absolute',
|
||||
'top': this.node_student_header_cell.getY() + 'px',
|
||||
'left': this.node_student_header_cell.getX() + 'px',
|
||||
'width': floating_grade_headers_width + 'px',
|
||||
'height': floating_grade_headers_height + 'px'
|
||||
});
|
||||
|
||||
Y.one('body').append(floating_grade_headers);
|
||||
},
|
||||
float_assignment_footer: function() {
|
||||
Y.log('Floating the averages footer.', 'debug', LOGNS);
|
||||
|
||||
// Generate the sticky footer row.
|
||||
// Grab the row.
|
||||
var footer_row = Y.all('#user-grades .lastrow .cell');
|
||||
// Create a container.
|
||||
var floating_grade_footers = Y.Node.create('<div aria-hidden="true" id="gradebook-footer-container"></div>');
|
||||
var floating_grade_footer_width = 0;
|
||||
var footer_row_offset = this.node_footer_row.getX();
|
||||
// Copy nodes
|
||||
footer_row.each(function(node) {
|
||||
|
||||
var nodepos = node.getX();
|
||||
var cellnodeclone = node.cloneNode(true);
|
||||
|
||||
var newnode = Y.Node.create('<div class="gradebook-footer-cell"></div>');
|
||||
newnode.append(cellnodeclone.getHTML());
|
||||
newnode.setStyles({
|
||||
'width': node.get('offsetWidth') + 'px',
|
||||
'height': '50px',
|
||||
'position': 'absolute',
|
||||
'left': (nodepos - footer_row_offset) + 'px'
|
||||
});
|
||||
|
||||
floating_grade_footers.append(newnode);
|
||||
floating_grade_footer_width += parseInt(node.get('offsetWidth'), 10);
|
||||
}, this);
|
||||
|
||||
// Attach 'Update' button.
|
||||
var update_button = Y.one('#gradersubmit');
|
||||
if (update_button) {
|
||||
var button = Y.Node.create('<button class="btn btn-sm btn-default">' + update_button.getAttribute('value') + '</button>');
|
||||
button.on('click', function() {
|
||||
YUI().use('node-event-simulate', function(Y) {
|
||||
Y.one('#gradersubmit').simulate('click');
|
||||
});
|
||||
});
|
||||
floating_grade_footers.one('.gradebook-footer-cell').append(button);
|
||||
}
|
||||
|
||||
// Position the row
|
||||
floating_grade_footers.setStyles({
|
||||
'position': 'absolute',
|
||||
'left': this.node_footer_row.getX() + 'px',
|
||||
'bottom': '0',
|
||||
'height': '50px',
|
||||
'width': floating_grade_footer_width + 'px'
|
||||
});
|
||||
|
||||
Y.one('body').append(floating_grade_footers);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"moodle-local_ucla-gradebooktable": {
|
||||
"requires": [
|
||||
"node",
|
||||
"event",
|
||||
"node-event-simulate"
|
||||
]
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user