Merge branch '1.11.x' of github.com:chamilo/chamilo-lms into 1.11.x

remotes/angel/1.11.x
Yannick Warnier 8 years ago
commit a33c798c87
  1. 103
      main/exercise/Annotation.php
  2. 65
      main/exercise/annotation_user.php
  3. 79
      main/exercise/exercise.class.php
  4. 2
      main/exercise/exercise_report.php
  5. 41
      main/exercise/exercise_show.php
  6. 1
      main/exercise/exercise_submit.php
  7. 3
      main/exercise/question.class.php
  8. 2
      main/forum/forumfunction.inc.php
  9. 4
      main/inc/lib/api.lib.php
  10. 2
      main/inc/lib/blog.lib.php
  11. 67
      main/inc/lib/exercise.lib.php
  12. 18
      main/inc/lib/exercise_show_functions.lib.php
  13. 299
      main/inc/lib/javascript/annotation/js/annotation.js

@ -0,0 +1,103 @@
<?php
/* For licensing terms, see /license.txt */
/**
* Class Annotation
* Allow instanciate an object of type HotSpot extending the class question
* @author Angel Fernando Quiroz Campos <angel.quiroz@beeznest.com>
* @package chamilo.
*/
class Annotation extends Question
{
public static $typePicture = 'annotation.png';
public static $explanationLangVar = 'Annotation';
/**
* Annotation constructor.
*/
public function __construct()
{
parent::__construct();
$this->type = ANNOTATION;
}
public function display()
{
}
/**
* @param FormValidator $form
* @param int $fck_config
*/
public function createForm(&$form, $fck_config = 0)
{
parent::createForm($form, $fck_config);
if (isset($_GET['editQuestion'])) {
$form->addButtonUpdate(get_lang('ModifyExercise'), 'submitQuestion');
return;
}
$form->addElement(
'file',
'imageUpload',
array(
Display::img(
Display::return_icon('annotation.png', null, null, ICON_SIZE_BIG, false, true)
),
get_lang('UploadJpgPicture'),
)
);
$form->addButtonSave(get_lang('GoToQuestion'), 'submitQuestion');
$form->addRule('imageUpload', get_lang('OnlyImagesAllowed'), 'filetype', array('jpg', 'jpeg', 'png', 'gif'));
$form->addRule('imageUpload', get_lang('NoImage'), 'uploadedfile');
}
/**
* @param FormValidator $form
* @param null $objExercise
* @return null|false
*/
public function processCreation($form, $objExercise = null)
{
$fileInfo = $form->getSubmitValue('imageUpload');
$courseInfo = api_get_course_info();
parent::processCreation($form, $objExercise);
if (!empty($fileInfo['tmp_name'])) {
$this->uploadPicture($fileInfo['tmp_name'], $fileInfo['name']);
$documentPath = api_get_path(SYS_COURSE_PATH).$courseInfo['path'].'/document';
$picturePath = $documentPath.'/images';
// fixed width ang height
if (!file_exists($picturePath.'/'.$this->picture)) {
return false;
}
$this->resizePicture('width', 800);
$this->save();
return true;
}
}
/**
* @param FormValidator $form
*/
function createAnswersForm($form)
{
// nothing
}
/**
* @param FormValidator $form
*/
function processAnswersCreation($form)
{
// nothing
}
}

@ -0,0 +1,65 @@
<?php
/* For licensing terms, see /license.txt */
use ChamiloSession as Session;
session_cache_limiter("none");
require_once __DIR__.'/../inc/global.inc.php';
$questionId = isset($_GET['question_id']) ? intval($_GET['question_id']) : 0;
$exerciseId = isset($_GET['exe_id']) ? intval($_GET['exe_id']) : 0;
$objQuestion = Question::read($questionId);
$documentPath = api_get_path(SYS_COURSE_PATH).$_course['path'].'/document';
$picturePath = $documentPath.'/images';
$pictureName = $objQuestion->selectPicture();
$pictureSize = getimagesize($picturePath.'/'.$objQuestion->selectPicture());
$pictureWidth = $pictureSize[0];
$pictureHeight = $pictureSize[1];
$data = [
'use' => 'user',
'image' => [
'path' => $objQuestion->selectPicturePath(),
'width' => $pictureSize[0],
'height' => $pictureSize[1]
],
'answers' => [
'paths' => [],
'texts' => []
]
];
$attemptList = Event::getAllExerciseEventByExeId($exerciseId);
if (!empty($attemptList) && isset($attemptList[$questionId])) {
$questionAttempt = $attemptList[$questionId][0];
if (!empty($questionAttempt['answer'])) {
$answers = explode('|', $questionAttempt['answer']);
foreach ($answers as $answer) {
$parts = explode(')(', $answer);
$type = array_shift($parts);
switch ($type) {
case 'P':
$points = [];
foreach ($parts as $partPoint) {
$points[] = Geometry::decodePoint($partPoint);
}
$data['answers']['paths'][] = $points;
break;
case 'T':
break;
}
}
}
}
header('Content-Type: application/json');
echo json_encode($data);

@ -3176,7 +3176,8 @@ class Exercise
if ($answerType == FREE_ANSWER ||
$answerType == ORAL_EXPRESSION ||
$answerType == CALCULATED_ANSWER
$answerType == CALCULATED_ANSWER ||
$answerType == ANNOTATION
) {
$nbrAnswers = 1;
}
@ -3221,7 +3222,7 @@ class Exercise
$answer_correct_array = array();
$orderedHotspots = [];
if ($answerType == HOT_SPOT) {
if ($answerType == HOT_SPOT || $answerType == ANNOTATION) {
$orderedHotspots = $em
->getRepository('ChamiloCoreBundle:TrackEHotspot')
->findBy([
@ -4156,6 +4157,35 @@ class Exercise
$_SESSION['hotspot_coord'][1] = $delineation_cord;
$_SESSION['hotspot_dest'][1] = $answer_delineation_destination;
break;
case ANNOTATION:
if ($from_database) {
$sql = "SELECT answer, marks FROM $TBL_TRACK_ATTEMPT
WHERE
exe_id = $exeId AND
question_id= ".$questionId;
$resq = Database::query($sql);
$data = Database::fetch_array($resq);
$choice = $data['answer'];
$choice = str_replace('\r\n', '', $choice);
$choice = stripslashes($choice);
$questionScore = empty($data['marks']) ? 0 : $data['marks'];
$totalScore += $questionScore == -1 ? 0 : $questionScore;
$arrques = $questionName;
$arrans = $choice;
break;
}
$studentChoice = $choice;
if ($studentChoice) {
$questionScore = 0;
$totalScore += 0;
}
break;
} // end switch Answertype
if ($show_result) {
@ -4455,6 +4485,15 @@ class Exercise
)
);
echo '</tr>';
} else if ($answerType == ANNOTATION) {
ExerciseShowFunctions::displayAnnotationAnswer(
$feedback_type,
$choice,
$exeId,
$questionId,
$questionScore,
$results_disabled
);
}
}
} else {
@ -4800,6 +4839,16 @@ class Exercise
);
echo '</tr>';
break;
case ANNOTATION:
ExerciseShowFunctions::displayAnnotationAnswer(
$feedback_type,
$choice,
$exeId,
$questionId,
$questionScore,
$results_disabled
);
break;
}
}
@ -5020,11 +5069,13 @@ class Exercise
}
}
$relPath = api_get_path(WEB_CODE_PATH);
if ($answerType == HOT_SPOT || $answerType == HOT_SPOT_ORDER) {
// We made an extra table for the answers
if ($show_result) {
$relPath = api_get_path(WEB_CODE_PATH);
// if ($origin != 'learnpath') {
echo '</table></td></tr>';
echo "
@ -5048,6 +5099,26 @@ class Exercise
";
// }
}
} else if ($answerType == ANNOTATION) {
if ($show_result) {
echo '</table></td></tr>';
echo '
<tr>
<td colspan="2">
<p><em>' . get_lang('Annotation') . '</em></p>
<div id="annotation-canvas-'.$questionId.'"></div>
<script>
AnnotationQuestion({
use: \'solution\',
questionId: parseInt('.$questionId.'),
exerciseId: parseInt('.$exeId.'),
relPath: \''.$relPath.'\'
});
</script>
</td>
</tr>
';
}
}
//if ($origin != 'learnpath') {
@ -5167,7 +5238,7 @@ class Exercise
$answer = $choice;
Event::saveQuestionAttempt($questionScore, $answer, $quesId, $exeId, 0, $this->id);
// } elseif ($answerType == HOT_SPOT || $answerType == HOT_SPOT_DELINEATION) {
} elseif ($answerType == HOT_SPOT) {
} elseif ($answerType == HOT_SPOT || $answerType == ANNOTATION) {
$answer = [];
if (isset($exerciseResultCoordinates[$questionId]) && !empty($exerciseResultCoordinates[$questionId])) {
Database::delete(

@ -149,7 +149,9 @@ if (isset($_REQUEST['comments']) &&
foreach ($_POST as $key_index => $key_value) {
$my_post_info = explode('_', $key_index);
$post_content_id[] = $my_post_info[1];
if ($my_post_info[0] == 'comments') {
$comments_exist = true;
}

@ -145,6 +145,7 @@ $this_section = SECTION_COURSES;
$htmlHeadXtra[] = '<link rel="stylesheet" href="' . api_get_path(WEB_LIBRARY_JS_PATH) . 'hotspot/css/hotspot.css">';
$htmlHeadXtra[] = '<script src="' . api_get_path(WEB_LIBRARY_JS_PATH) . 'hotspot/js/hotspot.js"></script>';
$htmlHeadXtra[] = '<script src="' . api_get_path(WEB_LIBRARY_JS_PATH) . 'annotation/js/annotation.js"></script>';
if ($origin != 'learnpath') {
Display::display_header('');
@ -362,6 +363,8 @@ foreach ($questionList as $questionId) {
$choice = array();
}
$relPath = api_get_path(WEB_CODE_PATH);
switch ($answerType) {
case MULTIPLE_ANSWER_COMBINATION:
//no break
@ -431,7 +434,6 @@ foreach ($questionList as $questionId) {
$totalScore += $question_result['score'];
if ($show_results) {
$relPath = api_get_path(WEB_CODE_PATH);
echo '</table></td></tr>';
echo "
<tr>
@ -612,6 +614,39 @@ foreach ($questionList as $questionId) {
";
}
break;
case ANNOTATION:
$question_result = $objExercise->manage_answer(
$id,
$questionId,
$choice,
'exercise_show',
array(),
false,
true,
$show_results,
$objExercise->selectPropagateNeg(),
[],
$showTotalScoreAndUserChoicesInLastAttempt
);
$questionScore = $question_result['score'];
$totalScore += $question_result['score'];
if ($show_results) {
echo '
<div id="annotation-canvas-'.$questionId.'"></div>
<script>
$(document).on(\'ready\', function () {
AnnotationQuestion({
questionId: '.(int) $questionId.',
exerciseId: '.(int) $id.',
use: \'solution\',
relPath: \''.$relPath.'\'
});
});
</script>
';
}
break;
}
if ($answerType == MULTIPLE_ANSWER_TRUE_FALSE) {
@ -642,7 +677,7 @@ foreach ($questionList as $questionId) {
if ($isFeedbackAllowed) {
$name = "fckdiv" . $questionId;
$marksname = "marksName" . $questionId;
if (in_array($answerType, array(FREE_ANSWER, ORAL_EXPRESSION))) {
if (in_array($answerType, array(FREE_ANSWER, ORAL_EXPRESSION, ANNOTATION))) {
$url_name = get_lang('EditCommentsAndMarks');
} else {
if ($action == 'edit') {
@ -704,7 +739,7 @@ foreach ($questionList as $questionId) {
}
if ($is_allowedToEdit && $isFeedbackAllowed) {
if (in_array($answerType, array(FREE_ANSWER, ORAL_EXPRESSION))) {
if (in_array($answerType, array(FREE_ANSWER, ORAL_EXPRESSION, ANNOTATION))) {
$marksname = "marksName" . $questionId;
echo '<div id="' . $marksname . '" style="display:none">';
echo '<form name="marksform_' . $questionId . '" method="post" action="">';

@ -62,6 +62,7 @@ $htmlHeadXtra[] = api_get_js('epiclock/javascript/jquery.epiclock.min.js');
$htmlHeadXtra[] = api_get_js('epiclock/renderers/minute/epiclock.minute.js');
$htmlHeadXtra[] = '<link rel="stylesheet" href="' . api_get_path(WEB_LIBRARY_JS_PATH) . 'hotspot/css/hotspot.css">';
$htmlHeadXtra[] = '<script src="' . api_get_path(WEB_LIBRARY_JS_PATH) . 'hotspot/js/hotspot.js"></script>';
$htmlHeadXtra[] = '<script src="' . api_get_path(WEB_LIBRARY_JS_PATH) . 'annotation/js/annotation.js"></script>';
if (api_get_setting('enable_record_audio') === 'true') {
$htmlHeadXtra[] = '<script src="' . api_get_path(WEB_LIBRARY_JS_PATH) . 'rtc/RecordRTC.js"></script>';

@ -51,8 +51,9 @@ abstract class Question
CALCULATED_ANSWER => array('calculated_answer.class.php' , 'CalculatedAnswer'),
UNIQUE_ANSWER_IMAGE => ['UniqueAnswerImage.php', 'UniqueAnswerImage'],
DRAGGABLE => ['Draggable.php', 'Draggable'],
MATCHING_DRAGGABLE => ['MatchingDraggable.php', 'MatchingDraggable']
MATCHING_DRAGGABLE => ['MatchingDraggable.php', 'MatchingDraggable'],
//MEDIA_QUESTION => array('media_question.class.php' , 'MediaQuestion')
ANNOTATION => ['Annotation.php', 'Annotation']
);
/**

@ -2204,7 +2204,7 @@ function get_thread_users_qualify($thread_id)
FROM $t_posts post , $t_users user, $t_session_rel_user scu, $t_qualify qualify
WHERE poster_id = user.id
AND post.poster_id = qualify.user_id
AND user.id = session_rel_user_rel_course.user_id
AND user.id = scu.user_id
AND scu.status<>'2'
AND scu.user_id NOT IN ($user_to_avoid)
AND qualify.thread_id = ".intval($thread_id)."

@ -467,6 +467,7 @@ define('CALCULATED_ANSWER', 16);
define('UNIQUE_ANSWER_IMAGE', 17);
define('DRAGGABLE', 18);
define('MATCHING_DRAGGABLE', 19);
define('ANNOTATION', 20);
define('EXERCISE_CATEGORY_RANDOM_SHUFFLED', 1);
define('EXERCISE_CATEGORY_RANDOM_ORDERED', 2);
@ -504,7 +505,8 @@ define('QUESTION_TYPES',
CALCULATED_ANSWER.':'.
UNIQUE_ANSWER_IMAGE.':'.
DRAGGABLE.':'.
MATCHING_DRAGGABLE
MATCHING_DRAGGABLE.':'.
ANNOTATION
);
//Some alias used in the QTI exports

@ -103,7 +103,7 @@ class Blog
$_user = api_get_user_info();
$course_id = api_get_course_int_id();
$current_date = date('Y-m-d H:i:s', time());
$current_date = api_get_utc_datetime();
$session_id = api_get_session_id();
$tbl_blogs = Database::get_course_table(TABLE_BLOGS);
$tbl_tool = Database::get_course_table(TABLE_TOOL_LIST);

@ -58,7 +58,7 @@ class ExerciseLib
$pictureName = $objQuestionTmp->selectPicture();
$s = '';
if ($answerType != HOT_SPOT && $answerType != HOT_SPOT_DELINEATION) {
if ($answerType != HOT_SPOT && $answerType != HOT_SPOT_DELINEATION && $answerType != ANNOTATION) {
// Question is not a hotspot
if (!$only_questions) {
$questionDescription = $objQuestionTmp->selectDescription();
@ -1248,6 +1248,71 @@ HOTSPOT;
</div>
</div>
HOTSPOT;
} elseif ($answerType == ANNOTATION) {
global $exerciseId, $exe_id;
$relPath = api_get_path(WEB_CODE_PATH);
if ($freeze) {
echo <<<HTML
<div id="annotation-canvas-$questionId" class="center-block"></div>
<script>
AnnotationQuestion({
questionId: $questionId,
exerciseId: $exe_id,
relPath: '$relPath',
use: 'user'
});
</script>
HTML;
return '';
}
if (api_is_platform_admin() || api_is_course_admin()) {
$course = api_get_course_info();
$docId = DocumentManager::get_document_id($course, '/images/' . $pictureName);
if (is_numeric($docId)) {
$images_folder_visibility = api_get_item_visibility(
$course,
'document',
$docId,
api_get_session_id()
);
if (!$images_folder_visibility) {
echo Display::return_message(get_lang('ChangeTheVisibilityOfTheCurrentImage'), 'warning');
}
}
}
if (!$only_questions) {
if ($show_title) {
TestCategory::displayCategoryAndTitle($objQuestionTmp->id);
echo '<div class="question_title">'.$current_item.'. '.$objQuestionTmp->selectTitle().'</div>';
}
echo <<<HTML
<input type="hidden" name="hidden_hotspot_id" value="$questionId" />
<div class="exercise_questions">
{$objQuestionTmp->selectDescription()}
<div id="annotation-canvas-$questionId" class="annotation-canvas center-block"></div>
<script>
AnnotationQuestion({
questionId: $questionId,
exerciseId: $exe_id,
relPath: '$relPath',
use: 'user'
});
</script>
</div>
HTML;
}
$objAnswerTmp = new Answer($questionId);
$nbrAnswers = $objAnswerTmp->selectNbrAnswers();
unset($objAnswerTmp, $objQuestionTmp);
}
return $nbrAnswers;
}

@ -569,4 +569,22 @@ class ExerciseShowFunctions
</tr>
<?php
}
public static function displayAnnotationAnswer(
$feedback_type,
$answer,
$exe_id,
$questionId,
$questionScore = null,
$results_disabled = 0
)
{
$comments = Event::get_comments($exe_id, $questionId);
if ($feedback_type != EXERCISE_FEEDBACK_TYPE_EXAM) {
if ($questionScore <= 0 && empty($comments)) {
echo '<br>'.Display::return_message(get_lang('notCorrectedYet'));
}
}
}
}

@ -0,0 +1,299 @@
/* For licensing terms, see /license.txt */
(function (window) {
/**
* @param referenceElement Element to get the point
* @param x MouseEvent's clientX
* @param y MouseEvent's clientY
* @returns {{x: number, y: number}}
*/
function getPointOnImage(referenceElement, x, y) {
var pointerPosition = {
left: x + window.scrollX,
top: y + window.scrollY
},
canvasOffset = {
x: referenceElement.getBoundingClientRect().left + window.scrollX,
y: referenceElement.getBoundingClientRect().top + window.scrollY
};
return {
x: Math.round(pointerPosition.left - canvasOffset.x),
y: Math.round(pointerPosition.top - canvasOffset.y)
};
};
/**
* @param Object attributes
* @constructor
*/
var SvgElementModel = function (attributes) {
this.attributes = attributes;
this.id = 0;
this.name = '';
this.changeEvent = null;
};
SvgElementModel.prototype.set = function (key, value) {
this.attributes[key] = value;
if (this.changeEvent) {
this.changeEvent(this);
}
};
SvgElementModel.prototype.get = function (key) {
return this.attributes[key];
};
SvgElementModel.prototype.onChange = function (callback) {
this.changeEvent = callback;
};
SvgElementModel.decode = function () {
return new this;
};
SvgElementModel.prototype.encode = function () {
return '';
};
/**
* @param Object attributes
* @constructor
*/
var SvgPathModel = function (attributes) {
SvgElementModel.call(this, attributes);
};
SvgPathModel.prototype = Object.create(SvgElementModel.prototype);
SvgPathModel.prototype.addPoint = function (x, y) {
x = parseInt(x);
y = parseInt(y);
var points = this.get('points');
points.push([x, y]);
this.set('points', points);
};
SvgPathModel.prototype.encode = function () {
var pairedPoints = [];
this.get('points').forEach(function (point) {
pairedPoints.push(
point.join(';')
);
});
return 'P)(' + pairedPoints.join(')(');
};
SvgPathModel.decode = function (pathInfo) {
var points = [];
$(pathInfo).each(function (i, point) {
points.push([point.x, point.y]);
});
return new SvgPathModel({points: points});
};
/**
* @param Object model
* @constructor
*/
var SvgPathView = function (model) {
var self = this;
this.model = model;
this.model.onChange(function () {
self.render();
});
this.el = document.createElementNS('http://www.w3.org/2000/svg', 'path');
this.el.setAttribute('fill', 'transparent');
this.el.setAttribute('stroke', 'red');
this.el.setAttribute('stroke-width', 3);
};
SvgPathView.prototype.render = function () {
var d = '',
points = this.model.get('points');
$.each(
this.model.get('points'),
function (i, point) {
d += (i === 0) ? 'M' : ' L ';
d += point[0] + ' ' + point[1];
}
);
this.el.setAttribute('d', d);
return this;
};
/**
* @constructor
*/
var PathsCollection = function () {
this.models = [];
this.length = 0;
this.addEvent = null;
};
PathsCollection.prototype.add = function (pathModel) {
pathModel.id = ++this.length;
this.models.push(pathModel);
if (this.addEvent) {
this.addEvent(pathModel);
}
};
PathsCollection.prototype.get = function (index) {
return this.models[index];
};
PathsCollection.prototype.onAdd = function (callback) {
this.addEvent = callback;
};
/**
* @param pathsCollection
* @param image
* @param questionId
* @constructor
*/
var AnnotationCanvasView = function (pathsCollection, image, questionId) {
var self = this;
this.el = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
this.$el = $(this.el);
this.questionId = parseInt(questionId);
this.image = image;
this.pathsCollection = pathsCollection;
this.pathsCollection.onAdd(function (pathModel) {
self.renderPath(pathModel);
});
};
AnnotationCanvasView.prototype.render = function () {
this.el.setAttribute('version', '1.1');
this.el.setAttribute('viewBox', '0 0 ' + this.image.width + ' ' + this.image.height);
var svgImage = document.createElementNS('http://www.w3.org/2000/svg', 'image');
svgImage.setAttributeNS('http://www.w3.org/1999/xlink', 'href', this.image.src);
svgImage.setAttribute('width', this.image.width);
svgImage.setAttribute('height', this.image.height);
this.el.appendChild(svgImage);
this.setEvents();
return this;
};
AnnotationCanvasView.prototype.setEvents = function () {
var self = this;
var isMoving = false,
pathModel = null;
self.$el
.on('dragstart', function (e) {
e.preventDefault();
})
.on('mousedown', function (e) {
e.preventDefault();
var point = getPointOnImage(self.el, e.clientX, e.clientY);
pathModel = new SvgPathModel({points: [[point.x, point.y]]});
self.pathsCollection.add(pathModel);
isMoving = true;
})
.on('mousemove', function (e) {
e.preventDefault();
if (!isMoving) {
return;
}
var point = getPointOnImage(self.el, e.clientX, e.clientY);
if (!pathModel) {
return;
}
pathModel.addPoint(point.x, point.y);
})
.on('mouseup', function (e) {
e.preventDefault();
if (!isMoving) {
return;
}
$('input[name="choice[' + self.questionId + '][' + pathModel.id + ']"]').val(pathModel.encode());
$('input[name="hotspot[' + self.questionId + '][' + pathModel.id + ']"]').val(pathModel.encode());
pathModel = null;
isMoving = false;
});
};
AnnotationCanvasView.prototype.renderPath = function (pathModel) {
var pathView = new SvgPathView(pathModel);
this.el.appendChild(pathView.render().el);
$('<input>')
.attr({
type: 'hidden',
name: 'choice[' + this.questionId + '][' + pathModel.id + ']'
})
.val(pathModel.encode())
.appendTo(this.el.parentNode);
$('<input>')
.attr({
type: 'hidden',
name: 'hotspot[' + this.questionId + '][' + pathModel.id + ']'
})
.val(pathModel.encode())
.appendTo(this.el.parentNode);
};
window.AnnotationQuestion = function (userSettings) {
var settings = $.extend({
questionId: 0,
exerciseId: 0,
relPath: '/',
use: 'user'
}, userSettings);
var xhrUrl = (settings.use == 'preview')
? 'exercise/annotation_preview.php'
: (settings.use == 'admin')
? 'exercise/annotation_admin.php'
: 'exercise/annotation_user.php';
$
.getJSON(settings.relPath + xhrUrl, {
question_id: parseInt(settings.questionId),
exe_id: parseInt(settings.exerciseId)
})
.done(function (questionInfo) {
var image = new Image();
image.onload = function () {
var pathsCollection = new PathsCollection(),
canvas = new AnnotationCanvasView(pathsCollection, this, settings.questionId);
$('#annotation-canvas-' + settings.questionId)
.css({width: this.width})
.html(canvas.render().el);
$.each(questionInfo.answers.paths, function (i, pathInfo) {
var pathModel = SvgPathModel.decode(pathInfo);
pathsCollection.add(pathModel);
});
};
image.src = questionInfo.image.path;
});
};
})(window);
Loading…
Cancel
Save