function MarkControl(option) { this.option = option; this.maxPrefetchCount = parseInt(option.prefetchCount); this.maxPrefetchCount = this.maxPrefetchCount != undefined && this.maxPrefetchCount > 2 ? this.maxPrefetchCount : 2; this.container = option.container; this.context = { imageServer: option.imageServer, staticServer: option.staticServer, isFinish: false, prefetching: false, prefetchTask: [] }; //初始化容器结构 this.initContainer(); //初始化事件监听 this.initTriggers(option); //初始化功能模块 this.initModules(option); //初始化评卷配置 this.initSetting(option); //初始化成功回调方法 //console.log('MarkControl init success!'); //if (option.success != undefined && typeof(option.success) == 'function') { // option.success(); //} } MarkControl.prototype.initContainer = function () { var height = this.option.height; if (height == undefined) { height = $(window).height(); } this.container = getDom(this.main_row_dom, this).appendTo(this.container); if (this.option.enableSidear != false) { this.container.sidebar = getDom(this.sidebar_dom, this).appendTo(this.container); this.container.sidebar.css('max-height', height); } this.container.center = getDom(this.center_dom, this).appendTo(this.container); this.container.header = getDom(this.center_header_dom, this).appendTo(this.container.center).find('.header'); if (this.option.switchTrackUrl != undefined && this.option.switchTrackUrl.length > 0) { var switchButton = this.container.header.find('#switch-track-button'); switchButton.attr('href', this.option.switchTrackUrl); switchButton.show(); } this.container.centerContent = getDom(this.center_content_dom, this).appendTo(this.container.center); this.container.imageContent = getDom(this.image_content_dom, this).appendTo(this.container.centerContent); this.container.height(height); this.container.centerContent.css('height', height - this.container.header.parent().height()); this.initHeaderAndAssistant(); this.container.centerList = []; this.navNumber = 0; } MarkControl.prototype.initHeaderAndAssistant = function () { var self = this; this.container.header.find('#mark-user-name').html(this.option.userName); if (this.option.logoutTitle != undefined) { this.container.header.find('#logout-title').html(this.option.logoutTitle); } this.container.header.find('#logout-link').click(function () { self.trigger('logout.link.click'); return true; }) this.container.assistant = getDom(this.assistant_dom, this).appendTo(this.container); this.container.assistant.positionSet = false; this.container.assistantButton = this.container.header.find('#assistant-button'); this.container.assistantButton.click(this, function (event) { if (self.container.assistant.positionSet == false) { self.container.assistant.offset({ top: self.container.assistantButton.position().top + self.container.assistantButton.height() + 5, left: self.container.assistantButton.position().left - 85 }); self.container.assistant.positionSet = true; } self.container.assistant.toggle(); }); } MarkControl.prototype.initMarkFunction = function () { var functionList = this.container.assistant.functionList; if (functionList == undefined) { functionList = getDom(this.mark_function_dom, this).appendTo(this.container.assistant).find('#function-list'); this.container.assistant.functionList = functionList; } } MarkControl.prototype.initSetting = function (option) { this.userId = option.userId; this.settingSyncUrl = option.settingSyncUrl; this.settingSyncing = false; this.localStore = window.localStorage; this.setting = {}; if (option.defaultSetting != undefined) { //读取外部初始化配置 this.setting = JSON.parse(option.defaultSetting); } else if (this.localStore != undefined) { //读取本地存储并判断用户标识 var store = JSON.parse(this.localStore.getItem('mark.setting')); if (store != undefined && store.userId != undefined && store.userId == this.userId) { this.setting = store.setting; } } //强制刷新本地存储 this.localSettingSave(); //广播通知所有模块初始化设置 this.trigger('mark.setting.init', this.setting); } MarkControl.prototype.localSettingSave = function () { if (this.localStore != undefined) { this.localStore.setItem('mark.setting', JSON.stringify({ userId: this.userId, setting: this.setting })); } } MarkControl.prototype.updateSetting = function (item) { if (item == undefined) { return; } for (var key in item) { this.setting[key] = item[key]; } this.localSettingSave(); if (this.settingSyncUrl != undefined && this.settingSyncing == false) { this.settingSyncing = true; var self = this; setTimeout(function () { //同步个性化设置 $.post(self.settingSyncUrl, { setting: JSON.stringify(self.setting) }); self.settingSyncing = false; }, 1000); } } //增加某个事件的监听方法 MarkControl.prototype.on = function (eventName, caller, callback, async) { if (eventName && callback && eventName.length > 0 && typeof (callback) == 'function') { if (async) { this.container.bind(eventName, callback); } else { if (this.triggers[eventName] == undefined) { this.triggers[eventName] = new Array(); } this.triggers[eventName].push({ caller: caller, callback: callback }); } } } //触发某个事件,并传递事件相关内容 MarkControl.prototype.trigger = function (eventName, eventObject) { var result = true; if (eventName && eventName.length > 0) { var array = this.triggers[eventName]; if (array != undefined && array.length > 0) { var event = { name: eventName } for (var i in array) { result = result & array[i].callback.call(array[i].caller, event, this.context, eventObject); } } this.container.trigger(eventName, this.context, eventObject); } return result; } //初始化事件监听 MarkControl.prototype.initTriggers = function (option) { if (this.triggers == undefined) { this.triggers = {}; } if (option != undefined && option.on != undefined) { for (var name in option.on) { this.on(name, option.on[name]); } } var self = this; this.on('view.sidebar.open', this, function (event, context, eventObject) { this.container.assistant.hide(); if (this.container.center.hasClass('span12')) { this.container.center.removeClass('span12'); this.container.center.addClass('span7'); } else if (this.container.center.hasClass('span10')) { this.container.center.removeClass('span10'); this.container.center.addClass('span5'); } this.trigger('center.width.change'); }); this.on('view.sidebar.close', this, function (event, context, eventObject) { this.container.assistant.hide(); if (this.container.center.hasClass('span7')) { this.container.center.removeClass('span7'); this.container.center.addClass('span12'); } else if (this.container.center.hasClass('span5')) { this.container.center.removeClass('span5'); this.container.center.addClass('span10'); } this.trigger('center.width.change'); }); this.on('mark.sidebar.open', this, function (event, context, eventObject) { this.container.assistant.hide(); if (this.container.center.hasClass('span12')) { this.container.center.removeClass('span12'); this.container.center.addClass('span10'); } else if (this.container.center.hasClass('span7')) { this.container.center.removeClass('span7'); this.container.center.addClass('span5'); } this.trigger('center.width.change'); }); this.on('mark.sidebar.close', this, function (event, context, eventObject) { this.container.assistant.hide(); if (this.container.center.hasClass('span10')) { this.container.center.removeClass('span10'); this.container.center.addClass('span12'); } else if (this.container.center.hasClass('span5')) { this.container.center.removeClass('span5'); this.container.center.addClass('span7'); } this.trigger('center.width.change'); }); this.on('task.load.finish', this, function (event, context, eventObject) { if (context.task != undefined) { context.task.spent = new Date().getTime(); } }); this.on('mark.focus.change', this, function (event, context, eventObject) { }); this.on('task.get.finish', this, function (event, context, eventObject) { context.prefetchCallback = undefined; }); this.on('task.get.none', this, function (event, context, eventObject) { self.getStatus(); if (context.task == undefined && self.option.clearUrl != undefined) { $.post(self.option.clearUrl, {}, function () { }); } context.prefetchCallback = function () { context.prefetchCallback = undefined; if (self.context.task == undefined && self.context.prefetchTask.length > 0) { self.getTask(); } } }); this.on('task.prefetch.success', this, function (event, context, eventObject) { if (context.prefetchCallback != undefined) { context.prefetchCallback(); } setTimeout(function () { self.prefetch(); }, 500); }); this.on('task.prefetch.error', this, function (event, context, eventObject) { setTimeout(function () { self.prefetch(); }, 500); }); this.on('task.prefetch.none', this, function (event, context, eventObject) { if (context.prefetchCallback != undefined) { context.prefetchCallback(); } if (context.isFinish != true) { setTimeout(function () { self.prefetch(); }, 1000); } }); this.on('task.prefetch.finish', this, function (event, context, eventObject) { self.getTask(); }); this.on('task.submit.before', this, function (event, context, eventObject) { context.submitting = true; }); this.on('history.submit.success', this, function (event, context, eventObject) { context.submitting = false; }); this.on('task.submit.success', this, function (event, context, eventObject) { context.submitting = false; context.task = undefined; self.getTask(); }); this.on('task.submit.error', this, function (event, context, eventObject) { context.submitting = false; }); this.on('task.pass.success', this, function (event, context, eventObject) { if (context.task != undefined && self.option.clearUrl != undefined) { $.post(self.option.clearUrl, { libraryId: context.task.libraryId }); } context.task = undefined; self.getTask(); }); this.on('mark.setting.change', this, function (event, context, eventObject) { self.updateSetting(eventObject); }); $(document).keypress(this, function (event) { if (self.context.listenKeyboard != false) { return self.trigger('key.press', event); } }); $(document).keydown(this, function (event) { if (self.context.listenKeyboard != false) { return self.trigger('key.down', event); } }); $(document).keyup(this, function (event) { if (self.context.listenKeyboard != false) { return self.trigger('key.up', event); } }); window.onbeforeunload = function (e) { if (self.option.clearUrl != undefined) { $.post(self.option.clearUrl); } } } //初始化功能模块 MarkControl.prototype.initModules = function (option) { if (this.modules == undefined) { this.modules = {}; } var names = []; var options = []; for (var name in this.defaultModules) { names.push(name); options[name] = this.defaultModules[name]; } if (option.modules != undefined) { for (var name in option.modules) { if (options[name] == undefined) { names.push(name); options[name] = {}; } $.extend(options[name], option.modules[name]); } } this.initModule(names, options, this.option.success); //initModule(this, names, 0, options); } //指定初始化某个名称的模块 MarkControl.prototype.initModule = function (names, options, success) { for (var i in names) { var name = names[i]; var option = options[name]; var moduleInit = name.replace(/-/g, '_'); if (option == undefined || typeof (option) != 'object') { option = {}; } option.markControl = this; eval('this.modules[name]=' + moduleInit + '(option, function(){})'); } if (success != undefined && typeof (success) == 'function') { success(); } } function initModuleAsync(markControl, names, index, option) { if (index < names.length) { var name = names[index]; var moduleOption = option[name]; var moduleUrl = 'modules/' + name + '.js'; var moduleInit = name.replace(/-/g, '_'); var modules = markControl.modules; if (modules[name] == undefined) { if (typeof (moduleOption) != 'object') { moduleOption = {}; } moduleOption.markControl = markControl; $.getScript(moduleUrl, function () { var success = function () { initModule(markControl, names, index + 1, option); } eval('modules[name]=' + moduleInit + '(moduleOption, success)'); }); } else { initModule(markControl, names, index + 1, option); } } else { if (markControl.option.success != undefined && typeof (markControl.option.success) == 'function') { markControl.option.success(); } } } MarkControl.prototype.start = function (taskOption) { taskOption.markControl = this; var markControl = this; taskOption.success = function () { markControl.context.prefetchCallback = function () { markControl.context.prefetchCallback = undefined; markControl.getTask(); } markControl.context.statusCallback = function () { markControl.context.statusCallback = undefined; markControl.prefetch(); } markControl.getStatus(); }; taskOption.error = function (message) { alert('初始化失败,请刷新页面重新加载'); }; this.taskControl = new TaskControl(taskOption); this.taskControl.init(); } //task预加载 MarkControl.prototype.prefetch = function () { var taskControl = this.taskControl; var markControl = this; var context = this.context; var jsonLoader = this.modules['json-loader']; if (context.isFinish != true) { if (taskControl.isFinish()) { context.isFinish = true; } else if (context.prefetchTask.length >= markControl.maxPrefetchCount) { markControl.trigger('task.prefetch.success'); } else if (context.prefetching == false) { context.prefetching = true; markControl.trigger('task.prefetch.before'); taskControl.fetch(function (task) { if (jsonLoader != undefined) { jsonLoader.build(task, function (error) { if (error) { context.prefetching = false; markControl.trigger('task.prefetch.error'); } else { context.prefetchTask.push(task); context.prefetchStatus = undefined; context.prefetching = false; markControl.trigger('task.prefetch.success'); } }); } else { context.prefetchTask.push(task); context.prefetchStatus = undefined; context.prefetching = false; markControl.trigger('task.prefetch.success'); } }, function (task) { context.prefetchStatus = task.message; context.prefetching = false; markControl.trigger('task.prefetch.none'); }, function () { context.prefetching = false; markControl.trigger('task.prefetch.none'); }); } } else { markControl.trigger('task.prefetch.finish'); } } MarkControl.prototype.getStatus = function () { if (this.taskControl == undefined) { return; } var self = this; this.taskControl.status(function (status) { self.context.status = status; if (status != undefined) { self.context.isFinish = status.blockTotalCount > 0 && status.blockTotalCount == (status.blockMarkedCount + status.blockExceptionCount); } if (self.context.statusCallback != undefined) { self.context.statusCallback(); } self.trigger('mark.status.change', status); }) } MarkControl.prototype.getTask = function () { if (this.taskControl == undefined) { return; } var markControl = this; var context = this.context; markControl.trigger('task.get.before'); if (context.isFinish == true) { markControl.trigger('task.get.finish'); return; } else if (context.task != undefined) { markControl.trigger('task.get.success'); return; } else if (context.waitTask != undefined) { //优先选择因回评等操作处于等待状态的任务 context.task = context.waitTask; context.waitTask = undefined; markControl.trigger('task.get.success'); } else if (context.prefetchTask.length > 0) { //判断是否有任务已预加载完毕 context.task = context.prefetchTask.shift(); markControl.trigger('task.get.success'); } else if (context.prefetchStatus != undefined) { //判断是否有在无预加载任务的情况下的消息提示 markControl.trigger('task.get.none', context.prefetchStatus); } else { markControl.trigger('task.get.none'); } } MarkControl.prototype.getHistory = function (data) { if (this.taskControl == undefined) { return; } this.taskControl.history(data, function (result) { data.result = result; this.option.markControl.trigger('history.get.success', data); }, function (message) { data.message = message; this.option.markControl.trigger('history.get.error', data); }); } MarkControl.prototype.setTask = function (task) { var jsonLoader = this.modules['json-loader']; var self = this; if (this.context.task != undefined && !this.context.task.previous && this.context.waitTask == undefined) { this.context.waitTask = this.context.task; } this.trigger('task.get.before'); if (jsonLoader != undefined && task != undefined) { jsonLoader.build(task, function (error) { self.context.task = task; self.trigger('task.get.success'); }); } else { self.context.task = task; if (task != undefined) { this.trigger('task.get.success'); } } } MarkControl.prototype.submitTask = function (submitUrl) { var task = this.context.task; var markControl = this; var submitUrl = submitUrl != undefined && submitUrl.length > 0 ? submitUrl : this.option.submitUrl; if (task != undefined && this.context.submitting != true) { //开启强制标记 if (this.option.forceSpecialTag === true) { if (task.tagList == undefined || task.tagList == null || task.tagList.length <= 0) { markControl.trigger('task.submit.forceSpecialTag'); return; } } var submitObj = { statusValue: task.statusValue, studentId: task.studentId, libraryId: task.libraryId, totalScore: task.totalScore, scoreList: task.scoreList, trackList: [], tagList: task.tagList, spent: new Date().getTime() - task.spent } this.trigger('task.submit.before'); if (this.taskControl != undefined) { //已定义任务引擎 this.taskControl.submit(submitObj, function (status) { if (status != undefined && status.valid == true) { markControl.context.status = status; markControl.trigger('mark.status.change', status); } if (task.previous == true) { markControl.trigger('history.submit.success', task); } else { markControl.trigger('task.submit.success'); } }, function (message) { markControl.trigger('task.submit.error', message); }); } else if (submitUrl != undefined && submitUrl.length > 0) { //未定义任务引擎,依赖定义/传入的提交地址 $.ajax({ url: submitUrl, type: 'POST', data: JSON.stringify(submitObj), dataType: "json", contentType: 'application/json;charset=utf-8', success: function (result) { if (result.success == true) { markControl.trigger('task.submit.success'); } else { markControl.trigger('task.submit.error', result.message); } }, error: function (message) { markControl.trigger('task.submit.error', message); } }); } else { markControl.trigger('task.submit.success'); } } } MarkControl.prototype.addNavGroup = function (title, content) { var self = this; self.navNumber++; var nav = $('' + title + '').appendTo(self.container.centerNavbar); nav.attr('data-number', self.navNumber); content.attr('data-number', self.navNumber); nav.click(function () { self.container.centerNavbar.find('a').removeClass('selected'); $(this).addClass('selected'); for (var i in self.container.centerList) { var dom = self.container.centerList[i]; if (dom.attr('data-number') == $(this).attr('data-number')) { dom.show(); } else { dom.hide(); } } }); self.container.centerList.push(content); return nav; } MarkControl.prototype.main_row_dom = '
'; MarkControl.prototype.sidebar_dom = '
'; MarkControl.prototype.center_dom = '
'; MarkControl.prototype.center_header_dom = '

\ \ 小助手\ \ 退出\

'; MarkControl.prototype.center_content_dom = '
'; MarkControl.prototype.image_content_dom = '
'; MarkControl.prototype.assistant_dom = '
'; MarkControl.prototype.mark_function_dom = '

评卷功能

\

\

'; //其他通用方法 String.prototype.startWith = function (prefix) { return this.indexOf(prefix) === 0; } String.prototype.endWith = function (suffix) { return this.match(suffix + "$") == suffix; }; //日期格式化 Date.prototype.format = function (fmt) { //author: meizz var o = { "M+": this.getMonth() + 1, //月份 "d+": this.getDate(), //日 "h+": this.getHours(), //小时 "m+": this.getMinutes(), //分 "s+": this.getSeconds(), //秒 "q+": Math.floor((this.getMonth() + 3) / 3), //季度 "S": this.getMilliseconds() //毫秒 }; if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length)); for (var k in o) { if (new RegExp("(" + k + ")").test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length))); } return fmt; } function parseNumber(number) { return Math.round(parseFloat(number) * 10) / 10; } function numberAdd(n1, n2) { return (n1 * 10 + n2 * 10) / 10; } function getDom(content, markControl) { if (markControl != undefined && markControl.option.staticServer != undefined) { content = content.replace(/{staticServer}/g, markControl.option.staticServer); } if (markControl != undefined && markControl.option.logoutUrl != undefined) { content = content.replace(/{logoutUrl}/g, markControl.option.logoutUrl); } var result = $(content); result.each(function() { if($(this).data("i18n-value")!=undefined){ $(this).val($.i18n.prop($(this).data("i18n-value"))); } if($(this).data("i18n-text")!=undefined){ $(this).text($.i18n.prop($(this).data("i18n-text"))); } if($(this).data("i18n-placeholder")!=undefined){ $(this).attr('placeholder',$.i18n.prop($(this).data("i18n-placeholder"))); } $(this).find("[data-i18n-value]").each(function() { $(this).val($.i18n.prop($(this).data("i18n-value"))); }); $(this).find("[data-i18n-text]").each(function() { $(this).text($.i18n.prop($(this).data("i18n-text"))); }); $(this).find("[data-i18n-placeholder]").each(function() { $(this).attr('placeholder',$.i18n.prop($(this).data("i18n-placeholder"))); }); }); return result; } function isArray(obj) { return obj != undefined && Object.prototype.toString.call(obj) === '[object Array]'; } function getMessage(message) { return $.i18n.prop(message); }