mirror of
https://github.com/moodle/moodle.git
synced 2025-04-13 04:22:07 +02:00
Merge branch 'MDL-42504' of git://github.com/timhunt/moodle
This commit is contained in:
commit
2a0a33a6ee
@ -60,3 +60,4 @@ if ($attemptobj->is_finished()) {
|
||||
|
||||
$attemptobj->process_auto_save($timenow);
|
||||
$transaction->allow_commit();
|
||||
echo 'OK';
|
||||
|
@ -185,6 +185,12 @@ $string['confirmserverdelete'] = 'Are you sure you want to remove the server <b>
|
||||
$string['confirmstartattemptlimit'] = 'Number of attempts allowed: {$a}. You are about to start a new attempt. Do you wish to proceed?';
|
||||
$string['confirmstartattempttimelimit'] = 'This quiz has a time limit and is limited to {$a} attempt(s). You are about to start a new attempt. Do you wish to proceed?';
|
||||
$string['confirmstarttimelimit'] = 'The quiz has a time limit. Are you sure that you wish to start?';
|
||||
$string['connectionok'] = 'Network connection restored. You may continue safely.';
|
||||
$string['connectionerror'] = 'Network connection lost. (Autosave failed).
|
||||
|
||||
Make a note of any responses entered on this page in the last few minutes, then try to re-connect.
|
||||
|
||||
Once connection has been re-established, your responses should be saved and this message will disappear.';
|
||||
$string['containercategorycreated'] = 'This category has been created to store all the original categories moved to site level due to the causes specified below.';
|
||||
$string['continueattemptquiz'] = 'Continue the last attempt';
|
||||
$string['continuepreview'] = 'Continue the last preview';
|
||||
|
@ -493,6 +493,8 @@ class mod_quiz_renderer extends plugin_renderer_base {
|
||||
$output .= html_writer::end_tag('div');
|
||||
$output .= html_writer::end_tag('form');
|
||||
|
||||
$output .= $this->connection_warning();
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
@ -1163,6 +1165,18 @@ class mod_quiz_renderer extends plugin_renderer_base {
|
||||
|
||||
return $this->heading($title, 3) . html_writer::tag('div', $graph, array('class' => 'graph'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Output the connection warning messages, which are initially hidden, and
|
||||
* only revealed by JavaScript if necessary.
|
||||
*/
|
||||
public function connection_warning() {
|
||||
$options = array('filter' => false, 'newlines' => false);
|
||||
$warning = format_text(get_string('connectionerror', 'quiz'), FORMAT_MARKDOWN, $options);
|
||||
$ok = format_text(get_string('connectionok', 'quiz'), FORMAT_MARKDOWN, $options);
|
||||
return html_writer::tag('div', $warning, array('id' => 'connection-error', 'style' => 'display: none;', 'role' => 'alert')) .
|
||||
html_writer::tag('div', $ok, array('id' => 'connection-ok', 'style' => 'display: none;', 'role' => 'alert'));
|
||||
}
|
||||
}
|
||||
|
||||
class mod_quiz_links_to_other_attempts implements renderable {
|
||||
|
@ -28,6 +28,28 @@ body.jsenabled .questionflagcheckbox {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#page-mod-quiz-attempt #connection-ok,
|
||||
#page-mod-quiz-attempt #connection-error {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
width: 80%;
|
||||
left: 10%;
|
||||
color: #555;
|
||||
border-radius: 0 0 10px 10px;
|
||||
box-shadow: 5px 5px 20px 0 #666666;
|
||||
padding: 1em 1em 0;
|
||||
z-index: 10000;
|
||||
}
|
||||
|
||||
#page-mod-quiz-attempt #connection-error {
|
||||
background-color: #fcc;
|
||||
}
|
||||
#page-mod-quiz-attempt #connection-ok {
|
||||
background-color: #cfb;
|
||||
width: 60%;
|
||||
left: 20%;
|
||||
}
|
||||
|
||||
/** Mod quiz attempt **/
|
||||
.generalbox#passwordbox {
|
||||
/* Should probably match .generalbox#intro above */
|
||||
|
@ -30,13 +30,17 @@ M.mod_quiz.autosave = {
|
||||
TINYMCE_DETECTION_DELAY: 500,
|
||||
TINYMCE_DETECTION_REPEATS: 20,
|
||||
WATCH_HIDDEN_DELAY: 1000,
|
||||
FAILURES_BEFORE_NOTIFY: 1,
|
||||
FIRST_SUCCESSFUL_SAVE: -1,
|
||||
|
||||
/** Selectors. */
|
||||
SELECTORS: {
|
||||
QUIZ_FORM: '#responseform',
|
||||
VALUE_CHANGE_ELEMENTS: 'input, textarea',
|
||||
CHANGE_ELEMENTS: 'input, select',
|
||||
HIDDEN_INPUTS: 'input[type=hidden]'
|
||||
HIDDEN_INPUTS: 'input[type=hidden]',
|
||||
CONNECTION_ERROR: '#connection-error',
|
||||
CONNECTION_OK: '#connection-ok'
|
||||
},
|
||||
|
||||
/** Script that handles the auto-saves. */
|
||||
@ -57,9 +61,13 @@ M.mod_quiz.autosave = {
|
||||
/** Y.io transaction for the save ajax request. */
|
||||
save_transaction: null,
|
||||
|
||||
/** @property Failed saves count. */
|
||||
savefailures: 0,
|
||||
|
||||
/** Properly bound key change handler. */
|
||||
editor_change_handler: null,
|
||||
|
||||
/** Record of the value of all the hidden fields, last time they were checked. */
|
||||
hidden_field_values: {},
|
||||
|
||||
/**
|
||||
@ -202,7 +210,10 @@ M.mod_quiz.autosave = {
|
||||
this.save_transaction = Y.io(this.AUTOSAVE_HANDLER, {
|
||||
method: 'POST',
|
||||
form: {id: this.form},
|
||||
on: {complete: this.save_done},
|
||||
on: {
|
||||
success: this.save_done,
|
||||
failure: this.save_failed
|
||||
},
|
||||
context: this
|
||||
});
|
||||
},
|
||||
@ -215,6 +226,29 @@ M.mod_quiz.autosave = {
|
||||
Y.log('Dirty after save.');
|
||||
this.start_save_timer();
|
||||
}
|
||||
|
||||
if (this.savefailures > 0) {
|
||||
Y.one(this.SELECTORS.CONNECTION_ERROR).hide();
|
||||
Y.one(this.SELECTORS.CONNECTION_OK).show();
|
||||
this.savefailures = this.FIRST_SUCCESSFUL_SAVE;
|
||||
} else if (this.savefailures === this.FIRST_SUCCESSFUL_SAVE) {
|
||||
Y.one(this.SELECTORS.CONNECTION_OK).hide();
|
||||
this.savefailures = 0;
|
||||
}
|
||||
},
|
||||
|
||||
save_failed: function() {
|
||||
Y.log('Save failed.');
|
||||
this.save_transaction = null;
|
||||
|
||||
// We want to retry soon.
|
||||
this.start_save_timer();
|
||||
|
||||
this.savefailures = Math.max(1, this.savefailures + 1);
|
||||
if (this.savefailures === this.FAILURES_BEFORE_NOTIFY) {
|
||||
Y.one(this.SELECTORS.CONNECTION_ERROR).show();
|
||||
Y.one(this.SELECTORS.CONNECTION_OK).hide();
|
||||
}
|
||||
},
|
||||
|
||||
is_time_nearly_over: function() {
|
||||
|
@ -1 +1 @@
|
||||
YUI.add("moodle-mod_quiz-autosave",function(e,t){M.mod_quiz=M.mod_quiz||{},M.mod_quiz.autosave={TINYMCE_DETECTION_DELAY:500,TINYMCE_DETECTION_REPEATS:20,WATCH_HIDDEN_DELAY:1e3,SELECTORS:{QUIZ_FORM:"#responseform",VALUE_CHANGE_ELEMENTS:"input, textarea",CHANGE_ELEMENTS:"input, select",HIDDEN_INPUTS:"input[type=hidden]"},AUTOSAVE_HANDLER:M.cfg.wwwroot+"/mod/quiz/autosave.ajax.php",delay:12e4,form:null,dirty:!1,delay_timer:null,save_transaction:null,editor_change_handler:null,hidden_field_values:{},init:function(t){this.form=e.one(this.SELECTORS.QUIZ_FORM);if(!this.form)return;this.delay=t*1e3,this.form.delegate("valuechange",this.value_changed,this.SELECTORS.VALUE_CHANGE_ELEMENTS,this),this.form.delegate("change",this.value_changed,this.SELECTORS.CHANGE_ELEMENTS,this),this.form.on("submit",this.stop_autosaving,this),this.init_tinymce(this.TINYMCE_DETECTION_REPEATS),this.save_hidden_field_values(),this.watch_hidden_fields()},save_hidden_field_values:function(){this.form.all(this.SELECTORS.HIDDEN_INPUTS).each(function(e){var t=e.get("name");if(!t)return;this.hidden_field_values[t]=e.get("value")},this)},watch_hidden_fields:function(){this.detect_hidden_field_changes(),e.later(this.WATCH_HIDDEN_DELAY,this,this.watch_hidden_fields)},detect_hidden_field_changes:function(){this.form.all(this.SELECTORS.HIDDEN_INPUTS).each(function(e){var t=e.get("name"),n=e.get("value");if(!t)return;if(!(t in this.hidden_field_values)||n!==this.hidden_field_values[t])this.hidden_field_values[t]=n,this.value_changed({target:e})},this)},init_tinymce:function(t){if(typeof tinyMCE=="undefined"){t>0&&e.later(this.TINYMCE_DETECTION_DELAY,this,this.init_tinymce,[t-1]);return}this.editor_change_handler=e.bind(this.editor_changed,this),tinyMCE.onAddEditor.add(e.bind(this.init_tinymce_editor,this))},init_tinymce_editor:function(e,t){t.onChange.add(this.editor_change_handler),t.onRedo.add(this.editor_change_handler),t.onUndo.add(this.editor_change_handler),t.onKeyDown.add(this.editor_change_handler)},value_changed:function(e){if(e.target.get("name")==="thispage"||e.target.get("name")==="scrollpos"||e.target.get("name").match(/_:flagged$/))return;this.start_save_timer_if_necessary()},editor_changed:function(e){this.start_save_timer_if_necessary()},start_save_timer_if_necessary:function(){this.dirty=!0;if(this.delay_timer||this.save_transaction)return;this.start_save_timer()},start_save_timer:function(){this.cancel_delay(),this.delay_timer=e.later(this.delay,this,this.save_changes)},cancel_delay:function(){this.delay_timer&&this.delay_timer!==!0&&this.delay_timer.cancel(),this.delay_timer=null},save_changes:function(){this.cancel_delay(),this.dirty=!1;if(this.is_time_nearly_over()){this.stop_autosaving();return}typeof tinyMCE!="undefined"&&tinyMCE.triggerSave(),this.save_transaction=e.io(this.AUTOSAVE_HANDLER,{method:"POST",form:{id:this.form},on:{complete:this.save_done},context:this})},save_done:function(){this.save_transaction=null,this.dirty&&this.start_save_timer()},is_time_nearly_over:function(){return M.mod_quiz.timer&&M.mod_quiz.timer.endtime&&(new Date).getTime()+2*this.delay>M.mod_quiz.timer.endtime},stop_autosaving:function(){this.cancel_delay(),this.delay_timer=!0,this.save_transaction&&this.save_transaction.abort()}}},"@VERSION@",{requires:["base","node","event","event-valuechange","node-event-delegate","io-form"]});
|
||||
YUI.add("moodle-mod_quiz-autosave",function(e,t){M.mod_quiz=M.mod_quiz||{},M.mod_quiz.autosave={TINYMCE_DETECTION_DELAY:500,TINYMCE_DETECTION_REPEATS:20,WATCH_HIDDEN_DELAY:1e3,FAILURES_BEFORE_NOTIFY:1,FIRST_SUCCESSFUL_SAVE:-1,SELECTORS:{QUIZ_FORM:"#responseform",VALUE_CHANGE_ELEMENTS:"input, textarea",CHANGE_ELEMENTS:"input, select",HIDDEN_INPUTS:"input[type=hidden]",CONNECTION_ERROR:"#connection-error",CONNECTION_OK:"#connection-ok"},AUTOSAVE_HANDLER:M.cfg.wwwroot+"/mod/quiz/autosave.ajax.php",delay:12e4,form:null,dirty:!1,delay_timer:null,save_transaction:null,savefailures:0,editor_change_handler:null,hidden_field_values:{},init:function(t){this.form=e.one(this.SELECTORS.QUIZ_FORM);if(!this.form)return;this.delay=t*1e3,this.form.delegate("valuechange",this.value_changed,this.SELECTORS.VALUE_CHANGE_ELEMENTS,this),this.form.delegate("change",this.value_changed,this.SELECTORS.CHANGE_ELEMENTS,this),this.form.on("submit",this.stop_autosaving,this),this.init_tinymce(this.TINYMCE_DETECTION_REPEATS),this.save_hidden_field_values(),this.watch_hidden_fields()},save_hidden_field_values:function(){this.form.all(this.SELECTORS.HIDDEN_INPUTS).each(function(e){var t=e.get("name");if(!t)return;this.hidden_field_values[t]=e.get("value")},this)},watch_hidden_fields:function(){this.detect_hidden_field_changes(),e.later(this.WATCH_HIDDEN_DELAY,this,this.watch_hidden_fields)},detect_hidden_field_changes:function(){this.form.all(this.SELECTORS.HIDDEN_INPUTS).each(function(e){var t=e.get("name"),n=e.get("value");if(!t)return;if(!(t in this.hidden_field_values)||n!==this.hidden_field_values[t])this.hidden_field_values[t]=n,this.value_changed({target:e})},this)},init_tinymce:function(t){if(typeof tinyMCE=="undefined"){t>0&&e.later(this.TINYMCE_DETECTION_DELAY,this,this.init_tinymce,[t-1]);return}this.editor_change_handler=e.bind(this.editor_changed,this),tinyMCE.onAddEditor.add(e.bind(this.init_tinymce_editor,this))},init_tinymce_editor:function(e,t){t.onChange.add(this.editor_change_handler),t.onRedo.add(this.editor_change_handler),t.onUndo.add(this.editor_change_handler),t.onKeyDown.add(this.editor_change_handler)},value_changed:function(e){if(e.target.get("name")==="thispage"||e.target.get("name")==="scrollpos"||e.target.get("name").match(/_:flagged$/))return;this.start_save_timer_if_necessary()},editor_changed:function(e){this.start_save_timer_if_necessary()},start_save_timer_if_necessary:function(){this.dirty=!0;if(this.delay_timer||this.save_transaction)return;this.start_save_timer()},start_save_timer:function(){this.cancel_delay(),this.delay_timer=e.later(this.delay,this,this.save_changes)},cancel_delay:function(){this.delay_timer&&this.delay_timer!==!0&&this.delay_timer.cancel(),this.delay_timer=null},save_changes:function(){this.cancel_delay(),this.dirty=!1;if(this.is_time_nearly_over()){this.stop_autosaving();return}typeof tinyMCE!="undefined"&&tinyMCE.triggerSave(),this.save_transaction=e.io(this.AUTOSAVE_HANDLER,{method:"POST",form:{id:this.form},on:{success:this.save_done,failure:this.save_failed},context:this})},save_done:function(){this.save_transaction=null,this.dirty&&this.start_save_timer(),this.savefailures>0?(e.one(this.SELECTORS.CONNECTION_ERROR).hide(),e.one(this.SELECTORS.CONNECTION_OK).show(),this.savefailures=this.FIRST_SUCCESSFUL_SAVE):this.savefailures===this.FIRST_SUCCESSFUL_SAVE&&(e.one(this.SELECTORS.CONNECTION_OK).hide(),this.savefailures=0)},save_failed:function(){this.save_transaction=null,this.start_save_timer(),this.savefailures=Math.max(1,this.savefailures+1),this.savefailures===this.FAILURES_BEFORE_NOTIFY&&(e.one(this.SELECTORS.CONNECTION_ERROR).show(),e.one(this.SELECTORS.CONNECTION_OK).hide())},is_time_nearly_over:function(){return M.mod_quiz.timer&&M.mod_quiz.timer.endtime&&(new Date).getTime()+2*this.delay>M.mod_quiz.timer.endtime},stop_autosaving:function(){this.cancel_delay(),this.delay_timer=!0,this.save_transaction&&this.save_transaction.abort()}}},"@VERSION@",{requires:["base","node","event","event-valuechange","node-event-delegate","io-form"]});
|
||||
|
@ -30,13 +30,17 @@ M.mod_quiz.autosave = {
|
||||
TINYMCE_DETECTION_DELAY: 500,
|
||||
TINYMCE_DETECTION_REPEATS: 20,
|
||||
WATCH_HIDDEN_DELAY: 1000,
|
||||
FAILURES_BEFORE_NOTIFY: 1,
|
||||
FIRST_SUCCESSFUL_SAVE: -1,
|
||||
|
||||
/** Selectors. */
|
||||
SELECTORS: {
|
||||
QUIZ_FORM: '#responseform',
|
||||
VALUE_CHANGE_ELEMENTS: 'input, textarea',
|
||||
CHANGE_ELEMENTS: 'input, select',
|
||||
HIDDEN_INPUTS: 'input[type=hidden]'
|
||||
HIDDEN_INPUTS: 'input[type=hidden]',
|
||||
CONNECTION_ERROR: '#connection-error',
|
||||
CONNECTION_OK: '#connection-ok'
|
||||
},
|
||||
|
||||
/** Script that handles the auto-saves. */
|
||||
@ -57,9 +61,13 @@ M.mod_quiz.autosave = {
|
||||
/** Y.io transaction for the save ajax request. */
|
||||
save_transaction: null,
|
||||
|
||||
/** @property Failed saves count. */
|
||||
savefailures: 0,
|
||||
|
||||
/** Properly bound key change handler. */
|
||||
editor_change_handler: null,
|
||||
|
||||
/** Record of the value of all the hidden fields, last time they were checked. */
|
||||
hidden_field_values: {},
|
||||
|
||||
/**
|
||||
@ -194,7 +202,10 @@ M.mod_quiz.autosave = {
|
||||
this.save_transaction = Y.io(this.AUTOSAVE_HANDLER, {
|
||||
method: 'POST',
|
||||
form: {id: this.form},
|
||||
on: {complete: this.save_done},
|
||||
on: {
|
||||
success: this.save_done,
|
||||
failure: this.save_failed
|
||||
},
|
||||
context: this
|
||||
});
|
||||
},
|
||||
@ -205,6 +216,28 @@ M.mod_quiz.autosave = {
|
||||
if (this.dirty) {
|
||||
this.start_save_timer();
|
||||
}
|
||||
|
||||
if (this.savefailures > 0) {
|
||||
Y.one(this.SELECTORS.CONNECTION_ERROR).hide();
|
||||
Y.one(this.SELECTORS.CONNECTION_OK).show();
|
||||
this.savefailures = this.FIRST_SUCCESSFUL_SAVE;
|
||||
} else if (this.savefailures === this.FIRST_SUCCESSFUL_SAVE) {
|
||||
Y.one(this.SELECTORS.CONNECTION_OK).hide();
|
||||
this.savefailures = 0;
|
||||
}
|
||||
},
|
||||
|
||||
save_failed: function() {
|
||||
this.save_transaction = null;
|
||||
|
||||
// We want to retry soon.
|
||||
this.start_save_timer();
|
||||
|
||||
this.savefailures = Math.max(1, this.savefailures + 1);
|
||||
if (this.savefailures === this.FAILURES_BEFORE_NOTIFY) {
|
||||
Y.one(this.SELECTORS.CONNECTION_ERROR).show();
|
||||
Y.one(this.SELECTORS.CONNECTION_OK).hide();
|
||||
}
|
||||
},
|
||||
|
||||
is_time_nearly_over: function() {
|
||||
|
38
mod/quiz/yui/src/autosave/js/autosave.js
vendored
38
mod/quiz/yui/src/autosave/js/autosave.js
vendored
@ -28,13 +28,17 @@ M.mod_quiz.autosave = {
|
||||
TINYMCE_DETECTION_DELAY: 500,
|
||||
TINYMCE_DETECTION_REPEATS: 20,
|
||||
WATCH_HIDDEN_DELAY: 1000,
|
||||
FAILURES_BEFORE_NOTIFY: 1,
|
||||
FIRST_SUCCESSFUL_SAVE: -1,
|
||||
|
||||
/** Selectors. */
|
||||
SELECTORS: {
|
||||
QUIZ_FORM: '#responseform',
|
||||
VALUE_CHANGE_ELEMENTS: 'input, textarea',
|
||||
CHANGE_ELEMENTS: 'input, select',
|
||||
HIDDEN_INPUTS: 'input[type=hidden]'
|
||||
HIDDEN_INPUTS: 'input[type=hidden]',
|
||||
CONNECTION_ERROR: '#connection-error',
|
||||
CONNECTION_OK: '#connection-ok'
|
||||
},
|
||||
|
||||
/** Script that handles the auto-saves. */
|
||||
@ -55,9 +59,13 @@ M.mod_quiz.autosave = {
|
||||
/** Y.io transaction for the save ajax request. */
|
||||
save_transaction: null,
|
||||
|
||||
/** @property Failed saves count. */
|
||||
savefailures: 0,
|
||||
|
||||
/** Properly bound key change handler. */
|
||||
editor_change_handler: null,
|
||||
|
||||
/** Record of the value of all the hidden fields, last time they were checked. */
|
||||
hidden_field_values: {},
|
||||
|
||||
/**
|
||||
@ -200,7 +208,10 @@ M.mod_quiz.autosave = {
|
||||
this.save_transaction = Y.io(this.AUTOSAVE_HANDLER, {
|
||||
method: 'POST',
|
||||
form: {id: this.form},
|
||||
on: {complete: this.save_done},
|
||||
on: {
|
||||
success: this.save_done,
|
||||
failure: this.save_failed
|
||||
},
|
||||
context: this
|
||||
});
|
||||
},
|
||||
@ -213,6 +224,29 @@ M.mod_quiz.autosave = {
|
||||
Y.log('Dirty after save.');
|
||||
this.start_save_timer();
|
||||
}
|
||||
|
||||
if (this.savefailures > 0) {
|
||||
Y.one(this.SELECTORS.CONNECTION_ERROR).hide();
|
||||
Y.one(this.SELECTORS.CONNECTION_OK).show();
|
||||
this.savefailures = this.FIRST_SUCCESSFUL_SAVE;
|
||||
} else if (this.savefailures === this.FIRST_SUCCESSFUL_SAVE) {
|
||||
Y.one(this.SELECTORS.CONNECTION_OK).hide();
|
||||
this.savefailures = 0;
|
||||
}
|
||||
},
|
||||
|
||||
save_failed: function() {
|
||||
Y.log('Save failed.');
|
||||
this.save_transaction = null;
|
||||
|
||||
// We want to retry soon.
|
||||
this.start_save_timer();
|
||||
|
||||
this.savefailures = Math.max(1, this.savefailures + 1);
|
||||
if (this.savefailures === this.FAILURES_BEFORE_NOTIFY) {
|
||||
Y.one(this.SELECTORS.CONNECTION_ERROR).show();
|
||||
Y.one(this.SELECTORS.CONNECTION_OK).hide();
|
||||
}
|
||||
},
|
||||
|
||||
is_time_nearly_over: function() {
|
||||
|
Loading…
x
Reference in New Issue
Block a user