//给分板模块 var mark_board = function(option, success) { var object = new MarkBoard(option); success(); return object; } function MarkBoard(option) { var self = this; this.markControl = option.markControl; this.needConfirm = option.needConfirm === true ? true : false; this.autoSubmit = option.autoSubmit === false ? false : true; this.showScoreBoard = option.showScoreBoard === false ? false : true; this.enableSkip = option.enableSkip === true ? true : false; this.init(); this.markControl.on('task.get.before', this, function(event, context, eventObject) { this.task = undefined; this.stepList = undefined; this.currentStep = undefined; this.stepCount = undefined; this.render(); }); this.markControl.on('task.load.finish', this, function(event, context, eventObject) { this.initByTask(context.task); }); this.markControl.on('history.submit.success', this, function(event, context, eventObject) { this.initByTask(context.task); }); this.markControl.on('mark.focus.change', this, function(event, context, eventObject) { this.onFocusChange(); }); this.markControl.on('mark.step.change', this, this.onStepSelect); this.markControl.on('key.press', this, function(e, context, event) { var code = event.keyCode; //console.log('key press:' + code); if (this.currentStep != undefined && this.task != undefined) { if (code >= 48 && code <= 57) { this.onNumberInput(code - 48); event.preventDefault(); return false; } else if (code >= 96 && code <= 105 && event.numLock) { this.onNumberInput(code - 96); event.preventDefault(); return false; } else if (code == 46 || code == 110 || code == 190) { //小数点 this.onDecimalInput(); event.preventDefault(); return false; } else if (code == 13 || code == 108) { //回车键 if (this.currentStep.markFinish === true && this.task.markFinish === true) { this.onTaskSubmit(); event.preventDefault(); return false; } else { this.onNumberSubmit(); event.preventDefault(); return false; } } } }); this.markControl.on('key.down', this, function(e, context, event) { var code = event.keyCode; //console.log('key down:' + code); if (this.currentStep != undefined && this.task != undefined) { if (code == 8 || code == 46) { //删除键&回退键 this.onNumberDelete(); event.preventDefault(); return false; } else if (code == 32) { //屏蔽空格键按下效果 return false; } else if (code == 80 && this.enableSkip) { //P键,跳过当前任务 this.markControl.trigger('task.pass.success'); } } }); this.markControl.on('key.up', this, function(e, context, event) { var code = event.keyCode; console.log('key up:' + code); if (this.currentStep != undefined && this.task != undefined) { if (code == 32) { //空格键提交步骤分 this.onNumberSubmit(); event.preventDefault(); return false; } else if (code == 37) { //←按键,切换到上一个步骤 if (this.currentStep.number > 1) { this.resetCurrentStep(); this.markControl.trigger('mark.step.change', this.currentStep.number - 1); event.preventDefault(); return false; } } else if (code == 39) { //→按键,切换到下一个步骤 if (this.currentStep.number < this.stepCount) { this.resetCurrentStep(); this.markControl.trigger('mark.step.change', this.currentStep.number + 1); event.preventDefault(); return false; } } } }); this.markControl.on('mark.setting.init', this, function(event, context, setting) { var show = setting['score.board.show']; if (show != undefined && show == true) { self.showScoreBoard = true; } }); } MarkBoard.prototype.init = function() { var self = this; this.stepBoard = getDom(this.step_board_dom, this.markControl).appendTo(this.markControl.container.centerContent); this.stepBoard.height(this.markControl.container.centerContent.height()); this.stepBoard.selectiveHeader = this.stepBoard.find('#step-board-selective-header'); this.stepBoard.stepHolder = this.stepBoard.find('.step-list'); this.stepBoard.stepHolder.height(this.markControl.container.centerContent.height() - 120); this.stepBoard.stepHolder.css('overflow', 'scroll'); //this.stepBoard.stepHolder.perfectScrollbar({ // wheelSpeed: 20, // useKeyboard: false, // minScrollbarLength: 30, // suppressScrollX: true //}); this.scoreBoard = getDom(this.scoreBoard_dom, this.markControl).appendTo(this.markControl.container); this.scoreBoard.header = getDom(this.scoreBoard_header_dom, this.markControl).appendTo(this.scoreBoard).find('#score-board-header'); this.scoreBoard.stepHolder = getDom(this.scoreBoard_stepHolder_dom, this.markControl).appendTo(this.scoreBoard); this.scoreBoard.footer = getDom(this.scoreBoard_footer_dom, this.markControl).appendTo(this.scoreBoard).find('#score-board-total-score'); this.scoreBoard.stepHolder.css('max-height', $(window).height() * 0.75); this.scoreBoard.stepHolder.css('overflow', 'scroll'); this.scoreBoard.draggable({ containment: "window" }); this.scoreBoard.find('#task-submit-button').click(this, function(event) { var markBoard = event.data; if (markBoard.task != undefined && markBoard.currentStep.markFinish === true) { markBoard.onTaskSubmit(); } }); this.scoreBoard.find('#resetBtn').click(this, function(event) { var markBoard = event.data; var selectedBlockId = $(".block-id-list option:selected").val(); if (markBoard.task != undefined) { if (markBoard.task.blockId == selectedBlockId) { alert("不能重新分发到同一题!"); return false; } else if (selectedBlockId == 0) { alert("必须选择一题分发!"); return false; } else { markBoard.task.reset = true; markBoard.task.blockId = selectedBlockId; markBoard.onTaskSubmit(); } } }); $('#resetBtn').click(this, function(event) { var markBoard = event.data; var selectedBlockId = $(".block-id-list option:selected").val(); if (markBoard.task != undefined) { if (markBoard.task.blockId == selectedBlockId) { alert("不能重新分发到同一题!"); return false; } else if (selectedBlockId == 0) { alert("必须选择一题分发!"); return false; } else { markBoard.task.reset = true; markBoard.task.blockId = selectedBlockId; markBoard.onTaskSubmit(); } } }); if (this.enableSkip) { this.scoreBoard.find('#task-pass-button').show(); this.scoreBoard.find('#task-pass-button').click(this, function(event) { var markBoard = event.data; markBoard.markControl.trigger('task.pass.success'); }); } this.scoreBoard.find('#score-board-close-button').click(this, function(event) { event.data.toggleScoreBoard(false); self.markControl.trigger('mark.setting.change', { 'score.board.show': false }); }); this.stepBoard.find('#show-score-board-button').click(this, function(event) { event.data.toggleScoreBoard(true); self.markControl.trigger('mark.setting.change', { 'score.board.show': true }); }); this.scoreBoard.find('.all-zero-button').click(this, function(event) { event.data.allZeroSubmit(); }); this.stepBoard.find('.all-zero-button').click(this, function(event) { event.data.allZeroSubmit(); }); this.popover = getDom(this.popover_dom, this.markControl).appendTo(this.markControl.container); this.popover.css('text-align', 'center'); this.popover.title = this.popover.find('.popover-title'); this.popover.title.css('font-size', '20px'); this.popover.title.css('line-height', '25px'); //this.popover.width('100'); //this.popover.title.width('100'); } MarkBoard.prototype.initByTask = function(task) { this.task = task; this.stepList = task.markStepList; this.currentStep = undefined; this.stepCount = this.stepList != undefined ? this.stepList.length : 0; task.totalScore = parseNumber(task.totalScore); var markFinish = true; var scoreList = task.scoreList != undefined && task.scoreList != '' ? task.scoreList.split(',') : []; for (var j in task.markStepList) { var step = task.markStepList[j]; if (scoreList != undefined && scoreList.length > j) { step.markScore = parseNumber(scoreList[j]); step.score = new String(step.markScore); step.markFinish = true; } else { markFinish = false; } } task.markFinish = task.totalScore != undefined && markFinish == true; this.render(task); if (this.stepCount > 0) { this.markControl.trigger('mark.step.change', 1); } else if (task.markFinish == true) { this.currentStep = { markFinish: true }; } } MarkBoard.prototype.onDecimalInput = function() { var score = this.currentStep.score; if ( !score.endWith('.')) { score = score + '.'; } this.currentStep.score = score; this.currentStep.markFinish = false; this.onScoreChange(); } MarkBoard.prototype.onNumberInput = function(number) { this.currentStep.score = this.currentStep.score + '' + number; this.currentStep.markFinish = false; this.onScoreChange(); } MarkBoard.prototype.onNumberDelete = function(number) { var score = this.currentStep.score; if (score.length > 1) { score = score.substring(0, score.length - 1); } else { score = ''; } this.currentStep.score = score; this.currentStep.markFinish = false; this.onScoreChange(); } MarkBoard.prototype.onNumberSubmit = function() { var score = this.currentStep.score; var interval = this.currentStep.interval; if (score.length > 0) { if (interval < 1 && score.startWith('.')) { score = '0'.concat(score); } else if (interval < 1 && score.endWith('.')) { score = score.concat(interval.toString().substring(2)); } } if (this.validateScore(this.currentStep, score)) { this.onScoreSubmit(true); } else if (this.showScoreBoard == true) { //分值表模式下,自动清除已输入的无效内容,免去删除操作 this.resetCurrentStep(); this.onScoreChange(); } } //切换步骤时,重置当前步骤的状态 //若当前分数未提交,则还原之前已给的分数;若之前还未给分,则清空分数显示 MarkBoard.prototype.resetCurrentStep = function() { var step = this.currentStep; if (step != undefined) { if (step.markScore != undefined) { step.markFinish = true; step.score = new String(step.markScore); } else { step.markFinish = false; step.score = ''; } this.markControl.trigger('mark.score.change'); } } MarkBoard.prototype.onStepSelect = function(event, context, stepNumber) { if (stepNumber <= this.stepCount && stepNumber > 0) { //还是点击当前步骤,不触发任何动作 if (this.currentStep != undefined && this.currentStep.number == stepNumber) { return; } //修改原step状态 if (this.currentStep != undefined) { var dom = this.stepBoard.stepArray[this.currentStep.number - 1]; dom.removeClass('current'); if (this.currentStep.markScore != undefined) { dom.addClass('done'); dom.find('.current-score').html(this.currentStep.markScore); } else { dom.addClass('todo'); dom.find('.current-score').html(''); } } this.togglePopover(false); this.currentStep = this.stepList[stepNumber - 1]; if (this.currentStep.score == undefined || isNaN(this.currentStep.score)) { this.currentStep.score = ''; } dom = this.stepBoard.stepArray[stepNumber - 1]; dom.removeClass('done'); dom.removeClass('todo'); dom.addClass('current'); //step列表自动滚动 //alert(this.stepBoard.stepHolder.height() - dom.height()); var scrollTop = this.stepBoard.stepHolder.scrollTop(); var maxHeight = this.stepBoard.stepHolder.height(); var domTop = dom.position().top; var domHeight = dom.height(); if (domTop < 0 && scrollTop > 0) { scrollTop = Math.max(scrollTop - domHeight, 0); } else if ((domTop + domHeight) > maxHeight) { scrollTop += (domTop + domHeight - maxHeight + 5); } this.stepBoard.stepHolder.scrollTop(scrollTop); } } MarkBoard.prototype.onScoreChange = function() { if (this.currentStep != undefined) { var dom = this.stepBoard.stepArray[this.currentStep.number - 1]; dom.find('.current-score').html(this.currentStep.score); this.togglePopover(false); } } MarkBoard.prototype.onScoreSubmit = function(autoNext) { if (this.currentStep != undefined) { this.currentStep.markScore = parseFloat(this.currentStep.score); this.currentStep.markFinish = true; this.onScoreChange(); this.updateTotalScore(); this.stepBoard.find('#total-score').html(this.task.totalScore); this.scoreBoard.footer.html(this.task.totalScore); var currentScore = this.currentStep.score; this.scoreBoard.stepArray[this.currentStep.number - 1].find('.score-select').each(function(index, obj) { if ($(obj).attr('data-score') == currentScore) { $(obj).addClass('active'); } else { $(obj).removeClass('active'); } }); this.markControl.trigger('mark.score.change'); if (autoNext === true && this.currentStep.number < this.stepCount) { this.markControl.trigger('mark.step.change', this.currentStep.number + 1); } else if (this.task.markFinish === true && this.showScoreBoard == false && this.autoSubmit === true) { this.onTaskSubmit(); } } } MarkBoard.prototype.updateTotalScore = function() { if (this.task != undefined) { var totalScore = 0; var finish = true; for (var i in this.stepList) { if (this.stepList[i].markScore != undefined) { totalScore = numberAdd(totalScore, this.stepList[i].markScore); } else { finish = false; } } this.task.totalScore = totalScore; this.task.markFinish = finish; } } MarkBoard.prototype.allZeroSubmit = function() { if (this.task != undefined && this.stepList != undefined && this.stepList.length > 0) { for (var i in this.stepList) { this.stepList[i].markScore = 0; } for (var i in this.task.markStepList) { this.task.markStepList[i].markScore = 0; } this.onTaskSubmit(); } } MarkBoard.prototype.onTaskSubmit = function() { var totalScore = 0; var scoreList = []; var finish = true; for (var i in this.stepList) { var score = this.stepList[i].markScore; if (score != undefined) { totalScore = numberAdd(totalScore, score); scoreList.push(score); } else { finish = false; } } if (this.task.reset) { finish = true; } if (!finish) { alert('当前任务还有未给分的步骤,请继续给分'); } else if (!this.needConfirm || confirm('总分为' + totalScore + ', 确认要提交吗?')) { this.task.totalScore = totalScore; this.task.scoreList = scoreList.join(','); this.markControl.submitTask(); } } MarkBoard.prototype.validateScore = function(step, scoreString) { var stepDom = this.stepBoard.stepArray[this.currentStep.number - 1].find('.current-score'); if (!$.isNumeric(scoreString)) { this.togglePopover(true, '不是合法数字', stepDom); //alert('当前分数不是合法数字'); return false; } var score = new Number(scoreString); if (score < step.min) { this.togglePopover(true, '不能小于' + step.min, stepDom); //alert('当前分数不应小于' + step.min); return false; } if (score > step.max) { this.togglePopover(true, '不能大于' + step.max, stepDom); //alert('当前分数不应大于' + step.max); return false; } var find = false; if (step.scoreList.length > 0) { for (var i in step.scoreList) { if (score == step.scoreList[i]) { find = true; } } } if (!find) { this.togglePopover(true, '不符合分值间隔要求', stepDom); //alert('当前分数不符合分值间隔要求'); return false; } step.score = scoreString; return true; } MarkBoard.prototype.render = function(task) { if (task != undefined) { var self = this; var title = task.blockTitle; this.initMarkBoardHeader(); this.stepBoard.stepHolder.empty(); this.stepBoard.stepArray = []; if (task.markFinish === true) { this.stepBoard.find('#total-score').html(task.totalScore); this.scoreBoard.footer.html(task.totalScore); } else { this.stepBoard.find('#total-score').html(''); this.scoreBoard.footer.html(''); } this.scoreBoard.stepHolder.empty(); this.scoreBoard.stepArray = []; for (var i in task.markStepList) { var step = task.markStepList[i]; step.max = parseNumber(step.max); step.min = parseNumber(step.min); step.score = parseNumber(step.score); step.interval = parseNumber(step.interval); //初始化步骤列表 var dom = getDom(this.step_dom, this.markControl); dom.attr('data-number', step.number); dom.find('.step-title').html(step.title); dom.find('.interval-score').html($.i18n.prop("mark.interval") + step.interval + $.i18n.prop("mark.score")); dom.find('.max-score').html(step.max); dom.find('.min-score').html(step.min); if (step.markFinish === true) { dom.addClass('done'); dom.find('.current-score').html(step.score); } else { dom.addClass('todo'); } dom.click(function() { self.onStepSelect(undefined, undefined, $(this).attr('data-number')); }) this.stepBoard.stepArray.push(dom.appendTo(this.stepBoard.stepHolder)); //初始化分值表 var dom2 = getDom(this.scoreBoard_step_dom, this.markControl); dom2.attr('data-number', step.number); dom2.find('.number').html(step.title); var scoreHolder = dom2.find('.fraction'); for (var j in step.scoreList) { step.scoreList[j] = parseNumber(step.scoreList[j]); var dom3 = getDom(this.scoreBoard_score_dom, this.markControl); var score = step.scoreList[j]; dom3.attr('data-step-number', step.number); dom3.attr('data-score', score); dom3.html(score); dom3.appendTo(scoreHolder); if (step.markFinish === true && step.markScore == score) { dom3.addClass('active'); } } this.scoreBoard.stepArray.push(dom2.appendTo(this.scoreBoard.stepHolder)); } this.toggleScoreBoard(this.showScoreBoard); this.scoreBoard.find('.score-select').click(this, function(event) { var markBoard = event.data; if (markBoard.task != undefined) { var object = $(event.target); markBoard.markControl.trigger('mark.step.change', object.attr('data-step-number')); markBoard.currentStep.score = object.attr('data-score'); markBoard.onScoreSubmit(); } }); this.stepBoard.stepHolder.scrollTop(0); } else { this.initMarkBoardHeader(); this.stepBoard.stepHolder.empty(); this.stepBoard.stepArray = []; this.stepBoard.find('#total-score').html(''); this.stepBoard.hide(); this.scoreBoard.stepHolder.empty(); this.scoreBoard.stepArray = []; this.scoreBoard.hide(); } } MarkBoard.prototype.initMarkBoardHeader = function() { var self = this; if (this.task == undefined) { this.stepBoard.selectiveHeader.hide(); this.scoreBoard.header.html(''); } else { var group = this.task.selectiveGroup; if (group != undefined) { this.scoreBoard.header.empty(); var blockSelect = (this.scoreBoard.header).append(this.scoreBoard_selective_dom).find('select'); blockSelect.append(''); if (group.blockList != undefined) { for (var i = 0; i < group.blockList.length; i++) { var block = group.blockList[i]; var selected = this.task.blockId == block.id ? 'selected' : ''; blockSelect.append(''); } } blockSelect.change(function() { self.onBlockChange($(this).val()); }); blockSelect = this.stepBoard.selectiveHeader.find('select'); blockSelect.empty(); blockSelect.append(''); if (group.blockList != undefined) { for (var i = 0; i < group.blockList.length; i++) { var block = group.blockList[i]; var selected = this.task.blockId == block.id ? 'selected' : ''; blockSelect.append(''); } } blockSelect.unbind(); blockSelect.change(function() { self.onBlockChange($(this).val()); }); this.stepBoard.selectiveHeader.show(); } else { this.stepBoard.selectiveHeader.hide(); this.scoreBoard.header.html(this.task.blockTitle); } } } MarkBoard.prototype.toggleScoreBoard = function(show) { this.resetCurrentStep(); if (show) { this.markControl.trigger('step.board.hide'); this.showScoreBoard = true; this.scoreBoard.show(); this.stepBoard.hide(); } else { this.markControl.trigger('step.board.show'); this.showScoreBoard = false; this.scoreBoard.hide(); this.stepBoard.show(); } } MarkBoard.prototype.onBlockChange = function(blockId) { if (this.task != undefined && this.task.selectiveGroup != undefined) { this.task.blockId = parseInt(blockId); this.task.totalScore = 0; this.task.scoreList = ''; var block = undefined; for (var i = 0; i < this.task.selectiveGroup.blockList.length; i++) { if (this.task.blockId == this.task.selectiveGroup.blockList[i].id) { block = this.task.selectiveGroup.blockList[i]; break; } } if (block != undefined) { this.task.markStepList = block.markStepList; } else { this.task.markStepList = []; } this.initByTask(this.task); } } MarkBoard.prototype.togglePopover = function(show, text, baseDom) { var popover = this.popover; if (show == true && baseDom != undefined) { //console.log(baseDom.offset().top + ',' + baseDom.offset().left); popover.offset({ top: baseDom.offset().top + 20, left: baseDom.offset().left - popover.width() }); popover.title.html(text); popover.show(); //console.log(popover.offset().top + ',' + popover.offset().left); } else { popover.offset({ top: 0, left: 0 }) popover.title.html(''); popover.hide(); } } MarkBoard.prototype.onFocusChange = function() { this.currentStep = null; } MarkBoard.prototype.step_board_dom = '