Actualización

This commit is contained in:
Xes
2025-04-10 12:49:05 +02:00
parent 4aff98e77b
commit 1cdd00920f
9151 changed files with 1800913 additions and 0 deletions

View File

@@ -0,0 +1,84 @@
<div id="record-audio-recordrtc-{{ question_id }}" class="row">
<div class="col-sm-4 col-sm-offset-4">
<div class="form-group text-center">
<span class="fa fa-microphone fa-5x fa-fw" aria-hidden="true"></span>
<span class="sr-only">{{ 'RecordAudio'|get_lang }}</span>
</div>
</div>
<div class="col-sm-12">
<div class="form-group text-center">
<div id="timer" style="display: none">
<h2>
<div class="label label-danger">
<span id="hour">00</span>
<span class="divider">:</span>
<span id="minute">00</span>
<span class="divider">:</span>
<span id="second">00</span>
</div>
</h2>
<br />
</div>
<button class="btn btn-primary" type="button" id="btn-start-record-{{ question_id }}">
<span class="fa fa-circle fa-fw" aria-hidden="true"></span> {{ 'StartRecordingAudio'|get_lang }}
</button>
<button class="btn btn-primary hidden" type="button" id="btn-pause-record-{{ question_id }}" disabled>
<span class="fa fa-pause fa-fw" aria-hidden="true"></span> {{ 'PauseRecordingAudio'|get_lang }}
</button>
<button class="btn btn-primary hidden" type="button" id="btn-play-record-{{ question_id }}" disabled>
<span class="fa fa-play fa-fw" aria-hidden="true"></span> {{ 'PlayRecordingAudio'|get_lang }}
</button>
<button class="btn btn-danger hidden" type="button" id="btn-stop-record-{{ question_id }}" disabled>
<span class="fa fa-square fa-fw" aria-hidden="true"></span> {{ 'StopRecordingAudio'|get_lang }}
</button>
<button class="btn btn-success hidden" type="button" id="btn-save-record-{{ question_id }}"
data-loadingtext="{{ 'Uploading'|get_lang }}"
disabled>
<span class="fa fa-send fa-fw" aria-hidden="true"></span> {{ 'SaveRecordedAudio'|get_lang }}
</button>
<button id="hide_description_{{ question_id }}" type="button" class="btn btn-default advanced_options" data-toggle="button" aria-pressed="false" autocomplete="off">
<em class="fa fa-bars"></em> {{ 'AddText' | get_lang }}
</button>
</div>
<div class="form-group text-center">
<audio class="skip hidden center-block" controls id="record-preview-{{ question_id }}"></audio>
</div>
<div class="well">
{{ 'OralExpressionHelpText' | get_lang }}
</div>
<div class="record-message"></div>
</div>
</div>
<div class="row" id="record-audio-wami-{{ question_id }}">
<div class="col-sm-4 col-sm-offset-4 text-center">
<div id="record-audio-wami-container-{{ question_id }}" class="wami-container"></div>
</div>
</div>
<script>
$(document).on('ready', function () {
RecordAudio.init({
blockId: '#record-audio-recordrtc-{{ question_id }}',
btnStartId: '#btn-start-record-{{ question_id }}',
btnPauseId: '#btn-pause-record-{{ question_id }}',
btnPlayId: '#btn-play-record-{{ question_id }}',
btnStopId: '#btn-stop-record-{{ question_id }}',
plyrPreviewId: '#record-preview-{{ question_id }}',
directory: '{{ directory }}',
type: 'document'
}, {
blockId: '#record-audio-wami-{{ question_id }}',
containerId: 'record-audio-wami-container-{{ question_id }}',
directory: '{{ directory }}',
userId: {{ user_id }},
type: 'document'
}, '{{ file_name }}');
if (0 === $('#hide_description_{{ question_id }}_options').length) {
$('#hide_description_{{ question_id }}').remove();
}
});
</script>

View File

@@ -0,0 +1,162 @@
<div class="question-result">
<div class="panel panel-default">
<div class="panel-body">
{% if 'save_titles_as_html'|api_get_configuration_value %}
{{ data.title | remove_xss }}
{% else %}
<h3>{{ data.title | remove_xss }}</h3>
{% endif %}
<div class="row">
<div class="col-md-3">
<div class="user-avatar">
<img src="{{ data.avatar }}">
</div>
<div class="user-info">
<strong>{{ data.name_url }}</strong>
<br />
{% if signature %}
<img src="{{ signature }}" />
{% endif %}
</div>
</div>
<div class="col-md-9">
<div class="group-data">
<div class="list-data username">
<span class="item">{{ 'Username'|get_lang }}</span>
<i class="fa fa-fw fa-user" aria-hidden="true"></i> {{ data.username }}
</div>
{% if data.start_date %}
<div class="list-data start-date">
<span class="item">{{ 'StartDate'|get_lang }}</span>
<i class="fa fa-fw fa-calendar" aria-hidden="true"></i> {{ data.start_date }}
</div>
{% endif %}
{% if data.duration %}
<div class="list-data duration">
<span class="item">{{ 'Duration'|get_lang }}</span>
<i class="fa fa-fw fa-clock-o" aria-hidden="true"></i> {{ data.duration }}
</div>
{% endif %}
{% if data.ip %}
<div class="list-data ip">
<span class="item">{{ 'IP'|get_lang }}</span>
<i class="fa fa-fw fa-laptop" aria-hidden="true"></i> {{ data.ip }}
</div>
{% endif %}
{% if allow_signature %}
<div class="list-data">
<span class="item"></span>
<a id="sign" class="btn btn-primary" href="javascript:void(0)">
<em class="fa fa-pencil"></em> {{ 'Sign'| get_plugin_lang('ExerciseSignaturePlugin') }}
</a>
</div>
{% endif %}
{% if allow_export_pdf %}
<br />
<div class="list-data">
<span class="item"></span>
<a href="{{ export_url }}" class="btn btn-default">
<img src="{{ 'export_pdf.png'|icon(32) }}" /> {{ 'ExportResponseReport'| get_lang }}
</a>
</div>
{% endif %}
</div>
<hr />
<div id="quiz_saved_answers_container">
{% if data.number_of_answers_saved != data.number_of_answers %}
<span class="label label-warning">
<strong>{{ 'XAnswersSavedByUsersFromXTotal'|get_lang|format(data.number_of_answers_saved, data.number_of_answers) }}</strong>
</span>
{% else %}
<span class="label label-success">
<strong>{{ 'XAnswersSavedByUsersFromXTotal'|get_lang|format(data.number_of_answers_saved, data.number_of_answers) }}</strong>
</span>
{% endif %}
{% if 'quiz_confirm_saved_answers'|api_get_configuration_value %}
{% set enable_form = data.track_confirmation.updatedAt is empty and data.track_confirmation.userId == _u.id %}
<form class="form-horizontal" action="#" id="quiz_confirm_saved_answers_form">
<div class="form-group">
<div class="col-sm-12">
<div class="checkbox">
<label>
<input
type="checkbox"
name="quiz_confirm_saved_answers_check"
{% if not enable_form %}disabled{% endif %} {% if data.track_confirmation.confirmed %}checked{% endif %}
>
{{ 'QuizConfirmSavedAnswers'|get_lang }}
</label>
</div>
{% if enable_form %}
<span class="help-block">{{ 'QuizConfirmSavedAnswersHelp'|get_lang }}</span>
{% endif %}
</div>
</div>
{% if enable_form %}
<div class="form-group">
<div class="col-sm-12">
<input type="hidden" name="tc_id" value="{{ data.track_confirmation.id }}">
<button type="submit" class="btn btn-primary" disabled>
<span class="fa fa-save fa-fw" aria-hidden="true"></span> {{ 'Save'|get_lang }}
</button>
</div>
</div>
{% endif %}
</form>
{% endif %}
</div>
</div>
</div>
</div>
</div>
</div>
{% if 'quiz_confirm_saved_answers'|api_get_configuration_value %}
{% set enable_form = data.track_confirmation.updatedAt is empty and data.track_confirmation.userId == _u.id %}
{% if enable_form %}
<script>
$(function () {
var form = $('#quiz_confirm_saved_answers_form');
var checkbox = form.find('[type="checkbox"]');
var button = form.find(':submit');
checkbox.on('change', function () {
button.prop('disabled', !this.checked);
});
form.on('submit', function (e) {
e.preventDefault();
if (!checkbox.is(':checked')) {
return;
}
var xhrData = form.serialize();
button.prop('disabled', true);
checkbox.prop('disabled', true);
$.post(
'{{ _p.web_ajax }}exercise.ajax.php?a=quiz_confirm_saved_answers',
xhrData
).done(function () {
button.parents('.form-group').remove();
$('#quiz_end_message').show();
}).fail(function (response) {
button.replaceWith(response.responseText);
});
})
$('#quiz_end_message').hide();
});
</script>
{% endif %}
{% endif %}

View File

@@ -0,0 +1,150 @@
<div id="question-{{ id }}" class="question-reading-comprehension-container">
<div class="question-reading-comprehension-overlay"></div>
{% if exercise_type == 1 %} {# all in one page #}
<button type="button" class="btn btn-default btn-lg" id="question-{{ id }}-start">
{{ 'StartTimeWindow'|get_lang }}
<span class="fa fa-play" aria-hidden="true"></span>
</button>
{% endif %}
<div id="question-{{ id }}-text" class="center-block question-reading-comprehension-text" onselectstart="return false">
{{ text }}
</div>
</div>
<style>
.question-reading-comprehension-container {
position: relative;
}
.question-reading-comprehension-container button {
left: 50%;
margin-left: -60px;
margin-top: -23px;
position: absolute;
top: 50%;
width: 120px;
}
.question-reading-comprehension-container .question-reading-comprehension-overlay {
bottom: 0;
left: 0;
position: absolute;
right: 0;
top: 0;
}
.question-reading-comprehension-text {
text-align: justify;
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.question-reading-comprehension-text .text-highlight {
color: transparent;
-webkit-text-shadow: 0 0 12px rgba(0, 0, 0, 0.5);
-khtml-text-shadow: 0 0 12px rgba(0, 0, 0, 0.5);
-moz-text-shadow: 0 0 12px rgba(0, 0, 0, 0.5);
-ms-text-shadow: 0 0 12px rgba(0, 0, 0, 0.5);
text-shadow: 0 0 12px rgba(0, 0, 0, 0.5);
-webkit-transition: color .12s linear, text-shadow .12s linear;
-khtml-transition: color .12s linear, text-shadow .12s linear;
-moz-transition: color .12s linear, text-shadow .12s linear;
-ms-transition: color .12s linear, text-shadow .12s linear;
transition: color .12s linear, text-shadow .12s linear;
}
.question-reading-comprehension-text .text-highlight.active {
color: #000;
-webkit-text-shadow: none;
-khtml-text-shadow: none;
-moz-text-shadow: none;
-ms-text-shadow: none;
text-shadow: none;
-webkit-transition: color .12s linear, text-shadow .12s linear;
-khtml-transition: color .12s linear, text-shadow .12s linear;
-moz-transition: color .12s linear, text-shadow .12s linear;
-ms-transition: color .12s linear, text-shadow .12s linear;
transition: color .12s linear, text-shadow .12s linear;
}
.question-reading-comprehension-text .text-highlight.border {
color: #bbb;
-webkit-text-shadow: none;
-khtml-text-shadow: none;
-moz-text-shadow: none;
-ms-text-shadow: none;
text-shadow: none;
-webkit-transition: color .12s linear, text-shadow .12s linear;
-khtml-transition: color .12s linear, text-shadow .12s linear;
-moz-transition: color .12s linear, text-shadow .12s linear;
-ms-transition: color .12s linear, text-shadow .12s linear;
transition: color .12s linear, text-shadow .12s linear;
}
.question-reading-comprehension-text br {
margin-bottom: 1em;
}
.radio.hide-reading-answers, .question_title.hide-reading-answers {
display: none;
}
</style>
<script>
$(document).on('ready', function () {
var index = 0,
$questionTexts = $('#question-{{ id }}-text .text-highlight'),
$btnFinish = $('#question_div_{{ id }} .form-actions button.question-validate-btn'),
total = $questionTexts.length,
timeOuId = null;
function updateView()
{
$questionTexts.removeClass('active border');
if (index == total - 1) {
$('#question_div_{{ id }} .radio, #question_div_{{ id }} .question_title').removeClass('hide-reading-answers');
$btnFinish.show();
}
if (index >= total) {
window.clearInterval(timeOuId);
return;
}
var prev = index > 0 ? $('#question-{{ id }}-text .text-highlight').get(index - 1) : null,
current = $questionTexts.get(index),
next = index < total ? $('#question-{{ id }}-text .text-highlight').get(index + 1) : null;
$(current).addClass('active');
if (prev) {
$(prev).addClass('border');
}
if (next) {
$(next).addClass('border');
}
index++;
}
function startQuestion() {
updateView();
timeOuId = window.setInterval(updateView, {{ refresh_time }} * 1000);
}
$btnFinish.hide();
{% if exercise_type == 1 %}
$('#question-{{ id }}-start').on('click', function (e) {
e.preventDefault();
startQuestion();
$(this).remove();
});
{% else %}
startQuestion();
{% endif %}
});
</script>

View File

@@ -0,0 +1,100 @@
{# Displayed from exercise_result.php #}
{{ page_top }}
{{ page_content }}
{{ page_bottom }}
{% if allow_signature %}
<div id="sign_popup" style="display: none">
<div id="signature_area" class="well">
<canvas width="400px"></canvas>
</div>
<span class="loading" style="display: none"><i class="fas fa-spinner"></i></span>
<span id="save_controls">
<button id="sign_popup_save" class="btn btn-primary" type="submit">
<em class="fa fa-save"></em> {{ 'Save'|get_lang }}
</button>
<button id="sign_popup_clean" class="btn btn-default" type="submit">
<em class="fa fa-eraser"></em> {{ 'Clean'|get_lang }}
</button>
</span>
<span id="close_controls" style="display: none">
<span id="sign_results"></span>
<hr />
<button id="sign_popup_close" class="btn btn-default" type="submit">
{{ 'Close'|get_lang }}
</button>
</span>
</div>
<script>
var imageFormat = 'image/png';
var canvas = document.querySelector("canvas");
var signaturePad = new SignaturePad(canvas);
var dataURL = signaturePad.toDataURL(imageFormat);
var url = "{{ _p.web_ajax }}exercise.ajax.php?{{ _p.web_cid_query }}";
var exeId = "{{ exe_id }}";
$(function() {
$("#sign_popup_close").on("click", function() {
$("#sign_popup").dialog("close");
$('#loading').hide();
$('#save_controls').show();
$('#close_controls').hide();
$('#signature_area').show();
});
$("#sign_popup_clean").on("click", function() {
signaturePad.clear();
});
$("#sign_popup_save").on("click", function() {
if (signaturePad.isEmpty()) {
alert('{{ 'ProvideASignatureFirst'| get_plugin_lang('ExerciseSignaturePlugin') | e('js') }}');
return false;
}
var dataURL = signaturePad.toDataURL(imageFormat);
$.ajax({
beforeSend: function(result) {
$('#loading').show();
},
type: "POST",
url: url,
data: "a=sign_attempt&exe_id="+exeId+"&file="+dataURL,
success: function(data) {
$('#loading').hide();
$('#save_controls').hide();
$('#close_controls').show();
$('#signature_area').hide();
signaturePad.clear();
if (1 == data) {
$('#sign_results').html('{{ 'Saved' | get_lang }}');
$('#sign').hide();
//$('#sign').html('{{ 'SignatureSaved' | get_lang }}');
} else {
$('#sign_results').html('{{ 'Error' | get_lang }}');
}
$('#close_controls').show();
},
});
});
$("#sign").on("click", function() {
$("#sign_popup").dialog({
autoOpen: false,
width: 500,
height: 'auto',
//position: { my: 'left top', at: 'right top'}, //of: $target
close: function(){
//$("div#"+div_show_id).remove();
//$("div#"+div_content_id).remove();
}
});
$("#sign_popup").dialog("open");
});
});
</script>
{% endif %}

View File

@@ -0,0 +1,255 @@
<script>
var DraggableAnswer = {
gallery: null,
trash: null,
deleteItem: function (item, insertHere) {
if (insertHere.find(".exercise-draggable-answer-option").length > 0) {
return false;
}
item.fadeOut(function () {
var $list = $('ul', insertHere).length
? $('ul', insertHere)
: $('<ul>').addClass('gallery list-unstyled').appendTo(insertHere);
var droppedId = item.attr('id'),
dropedOnId = insertHere.attr('id'),
originSelectId = 'window_' + droppedId + '_select',
value = dropedOnId.split('_')[2];
$('#' + originSelectId + ' option')
.filter(function (index) {
var position = insertHere.prop('id').split('_')[2];
return index === parseInt(position);
})
.prop("selected", true);
item.appendTo($list).fadeIn();
});
},
recycleItem: function (item) {
var droppedId = item.attr('id'),
originSelectId = 'window_' + droppedId + '_select',
idParts = droppedId.split('_'),
questionId = parseInt(idParts[0]) || 0;
if (!questionId) {
return;
}
item.fadeOut(function () {
item
.appendTo(DraggableAnswer.gallery.filter('[data-question="' + questionId + '"]'))
.fadeIn();
});
$('#' + originSelectId + ' option').prop('selected', false);
$('#' + originSelectId + ' option:first').prop('selected', true);
},
init: function (gallery, trash) {
this.gallery = gallery;
this.trash = trash;
$("li.touch-items", DraggableAnswer.gallery).draggable({
revert: "invalid",
containment: "document",
helper: "clone",
cursor: "move"
});
DraggableAnswer.trash.droppable({
accept: ".exercise-draggable-answer > li.touch-items",
drop: function (e, ui) {
DraggableAnswer.deleteItem(ui.draggable, $(this));
}
});
DraggableAnswer.gallery.droppable({
drop: function (e, ui) {
DraggableAnswer.recycleItem(ui.draggable, $(this));
}
});
}
};
var MatchingDraggable = {
colorDestination: '#316B31',
curviness: 0,
connectorType: 'Straight',
initialized: false,
init: function (questionId) {
var windowQuestionSelector = '.window' + questionId + '_question',
countConnections = $(windowQuestionSelector).length,
colorArray = [],
colorArrayDestination = [];
if (countConnections > 0) {
colorArray = $.xcolor.analogous("#da0", countConnections);
colorArrayDestination = $.xcolor.analogous("#51a351", countConnections);
} else {
colorArray = $.xcolor.analogous("#da0", 10);
colorArrayDestination = $.xcolor.analogous("#51a351", 10);
}
jsPlumb.importDefaults({
DragOptions: {cursor: 'pointer', zIndex: 2000},
PaintStyle: {strokeStyle: '#000'},
EndpointStyle: {strokeStyle: '#316b31'},
Endpoint: 'Rectangle',
Anchors: ['TopCenter', 'TopCenter']
});
var exampleDropOptions = {
tolerance: 'touch',
hoverClass: 'dropHover',
activeClass: 'dragActive'
};
var destinationEndPoint = {
endpoint: ["Dot", {radius: 15}],
paintStyle: {fillStyle: MatchingDraggable.colorDestination},
isSource: false,
connectorStyle: {strokeStyle: MatchingDraggable.colorDestination, lineWidth: 8},
connector: [
MatchingDraggable.connectorType,
{curviness: MatchingDraggable.curviness}
],
maxConnections: 1000,
isTarget: true,
dropOptions: exampleDropOptions,
beforeDrop: function (params) {
jsPlumb.select({source: params.sourceId}).each(function (connection) {
jsPlumb.detach(connection);
});
var selectId = params.sourceId + "_select";
var value = params.targetId.split("_")[2];
$("#" + selectId + " option")
.removeAttr('selected')
.filter(function (index) {
return index === parseInt(value);
})
.attr("selected", true);
return true;
}
};
var count = 0;
var sourceDestinationArray = [];
$(windowQuestionSelector).each(function (index) {
var windowId = $(this).attr("id");
var scope = windowId + "scope";
var destinationColor = colorArray[count].getHex();
var sourceEndPoint = {
endpoint: [
"Dot",
{radius: 15}
],
paintStyle: {
fillStyle: destinationColor
},
isSource: true,
connectorStyle: {
strokeStyle: "#8a8888",
lineWidth: 8
},
connector: [
MatchingDraggable.connectorType,
{curviness: MatchingDraggable.curviness}
],
maxConnections: 1,
isTarget: false,
dropOptions: exampleDropOptions,
scope: scope
};
sourceDestinationArray[count + 1] = sourceEndPoint;
count++;
jsPlumb.addEndpoint(
windowId,
{
anchor: ['RightMiddle', 'RightMiddle', 'RightMiddle', 'RightMiddle']
},
sourceEndPoint
);
var destinationCount = 0;
$(windowQuestionSelector).each(function (index) {
var windowDestinationId = $(this).attr("id");
destinationEndPoint.scope = scope;
destinationEndPoint.paintStyle.fillStyle = colorArrayDestination[destinationCount].getHex();
destinationCount++;
jsPlumb.addEndpoint(
windowDestinationId + "_answer",
{
anchors: ['LeftMiddle', 'LeftMiddle', 'LeftMiddle', 'LeftMiddle']
},
destinationEndPoint
);
});
});
MatchingDraggable.attachBehaviour();
},
attachBehaviour: function () {
if (!MatchingDraggable.initialized) {
MatchingDraggable.initialized = true;
}
}
};
jsPlumb.ready(function () {
if ($(".drag_question").length > 0) {
MatchingDraggable.init();
$(document).scroll(function () {
jsPlumb.repaintEverything();
});
$(window).resize(function () {
jsPlumb.repaintEverything();
});
}
});
function shuffleArray(array) {
for (var i = array.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
$(function () {
// if shuffle answers
if ('{{ shuffle_answers }}' == '1') {
$('.exercise-draggable-answer').each(function(){
// get current ul
var $ul = $(this);
var li = $ul.find('.touch-items');
var liContents = [];
li.each(function() {
liContents.push($(this));
});
shuffleArray(liContents);
$ul.empty().html(liContents);
});
}
DraggableAnswer.init(
$(".exercise-draggable-answer"),
$(".droppable")
);
});
</script>