diff --git a/extension/Documentation/Manual.rst b/extension/Documentation/Manual.rst index 6cbe739435472ef0c7264f4a134480858f160eca..56cd4a92b75e29ab6a538f788d467368acce23df 100644 --- a/extension/Documentation/Manual.rst +++ b/extension/Documentation/Manual.rst @@ -3268,11 +3268,11 @@ Type: annotate Annotate image or text. Typically the image or text has been uploaded during a previous step. The annotation will be saved in *FormElement.name* column of the current record. The uploaded file itself will not be modified. The annotations -can be shown in edit or readonly mode and modified again. +can be shown in edit (and might be modified) or in readonly mode. Two modes are available: -image +grafic A simple grafic editor to paint on top of the image (best by a tablet with pen or grafic tablet). The uploaded image is shown in the background. All drawings are saved as a JSON fabric.js data string. Supported file types: **png, svg**. PDF files can be easily divided into per page SVG files during upload - see `split-pdf-upload`_ @@ -3287,11 +3287,11 @@ text Drawing with fabric.js might produce a lot data. Take care the column type/size is big enough (>=64kB). -Image -""""" +Grafic +"""""" -An image, specified by `FormElement.parameter`: imageSource={{pathFileName}}, will be displayed in the background. On -form load, both, the image and an optional already given JSON fabric.js data string, will be displayed. The image is SIP +An image, specified by ``FormElement.parameter.imageSource={{pathFileName}}``, will be displayed in the background. On +form load, both, the image and an optional already given grafical annotations, will be displayed. The image is SIP protected and will be loaded on demand. **Form.parameter** @@ -3301,9 +3301,9 @@ protected and will be loaded on demand. +===================+=======================+==================================================================================+ | annotateType | grafic | *grafic|text*. Default is *grafic*. Select mode. | +-------------------+-----------------------+----------------------------------------------------------------------------------+ -| imageSource | {{pathFileName2}} | Background image. E.g. `fileadmin/images/scan.png` | +| imageSource | <path filename> | Background image. E.g. `fileadmin/images/scan.png` | +-------------------+-----------------------+----------------------------------------------------------------------------------+ -| defaultPenColor | <rgb hex value> | Pen default color, after loading the fabric element. Default is '0000FF' (blue). | +| defaultPenColor | <rgb hex value> | Pen default color, after loading the fabric element. Default is '0000FF' (blue). | +-------------------+----------------------------------------------------------------------------------------------------------+ .. note:: @@ -3321,7 +3321,7 @@ Code +====================+=======================+==================================================================================+ | annotateType | text | *grafic|text*. Default is *grafic*. Select mode. | +--------------------+-----------------------+----------------------------------------------------------------------------------+ -| textSource | <fileadmin/code.m> | Text file to annotate. | +| textSource | <path filename> | Text file to annotate. | +--------------------+-----------------------+----------------------------------------------------------------------------------+ | annotateUserName | <john doe> | Will be shown at annotation line. | +--------------------+-----------------------+----------------------------------------------------------------------------------+ diff --git a/extension/Source/core/AbstractBuildForm.php b/extension/Source/core/AbstractBuildForm.php index 7982180395fb8310e55f70a181be84e8183eed5a..05ab91f44ac18fd38836e78468befb4ed5b7c13b 100644 --- a/extension/Source/core/AbstractBuildForm.php +++ b/extension/Source/core/AbstractBuildForm.php @@ -3192,7 +3192,7 @@ abstract class AbstractBuildForm { Support::setIfNotSet($formElement, FE_ANNOTATE_USER_NAME); Support::setIfNotSet($formElement, FE_ANNOTATE_USER_AVATAR); - $dataHighlight=HelperFile::getFileTypeHighlight($formElement[FE_HIGHLIGHT]??'',$formElement[FE_TEXT_SOURCE] ); + $dataHighlight = HelperFile::getFileTypeHighlight($formElement[FE_HIGHLIGHT] ?? '', $formElement[FE_TEXT_SOURCE]); // <div class="codeCorrection" data-uid='{"uid": 1, "name": "Reginald Commenter", "avatar": "http://www"}' data-file="../javascript/src/CodeCorrection.js" data-target="codeCorrection-output1"> @@ -3210,7 +3210,11 @@ abstract class AbstractBuildForm { $attributeDiv .= Support::doAttribute('data-target', $formElement[FE_HTML_ID]); $attributeDiv .= Support::doAttribute('data-highlight', $dataHighlight); $attributeDiv .= $this->getAttributeFeMode($formElement[FE_MODE]); - $htmlAnnotate = Support::wrapTag('<div ' . $attributeDiv . ' data-uid=\''. $jsonDataUid . '\' >', '', false); + if ($formElement[FE_MODE] == FE_MODE_READONLY) { + $attributeDiv .= Support::doAttribute('data-view-only', 'true'); + } + + $htmlAnnotate = Support::wrapTag('<div ' . $attributeDiv . ' data-uid=\'' . $jsonDataUid . '\' >', '', false); // $htmlAnnotate = Support::wrapTag('<div ' . $attributeDiv .'>', '', false); $attributeInput = Support::doAttribute('id', $formElement[FE_HTML_ID]); @@ -3271,6 +3275,9 @@ abstract class AbstractBuildForm { $attributeFabric .= Support::doAttribute('data-emojis', 'typo3conf/ext/qfq/Resources/Public/Json/qfq.emoji.json'); $attributeFabric .= Support::doAttribute('data-fabric-color', HelperFormElement::penColorToHex($formElement)); $attributeFabric .= $this->getAttributeFeMode($formElement[FE_MODE]); + if ($formElement[FE_MODE] == FE_MODE_READONLY) { + $attributeFabric .= Support::doAttribute('data-view-only', 'true'); + } $htmlFabric = Support::wrapTag('<div ' . $attributeFabric . ' >', '', false); $attributeInput = Support::doAttribute('id', $formElement[FE_HTML_ID]); @@ -3301,8 +3308,7 @@ abstract class AbstractBuildForm { * @throws CodeException * @throws UserFormException */ - public - function buildImageCut(array $formElement, $htmlFormElementName, $value, array &$json, $mode = FORM_LOAD) { + public function buildImageCut(array $formElement, $htmlFormElementName, $value, array &$json, $mode = FORM_LOAD) { $htmlImage = ''; if ($mode == FORM_LOAD && !empty($formElement[FE_IMAGE_SOURCE])) { @@ -3340,6 +3346,7 @@ abstract class AbstractBuildForm { } $attributeFabric .= Support::doAttribute('data-image-output', $htmlFabricImageId); $attributeFabric .= $this->getAttributeFeMode($formElement[FE_MODE]); + $htmlFabric = Support::wrapTag('<div ' . $attributeFabric . ' >', '', false); // <input id="fabric-output" name="fabric-data" type="hidden"> @@ -3372,8 +3379,7 @@ abstract class AbstractBuildForm { * @throws CodeException * @throws UserFormException */ - private - function fileToSipUrl($pathFileName) { + private function fileToSipUrl($pathFileName) { $param[DOWNLOAD_MODE] = DOWNLOAD_MODE_FILE; $param[SIP_DOWNLOAD_PARAMETER] = base64_encode(TOKEN_FILE . PARAM_TOKEN_DELIMITER . $pathFileName); @@ -3399,8 +3405,7 @@ abstract class AbstractBuildForm { * @throws UserFormException * @throws UserReportException */ - public - function buildDateTime(array $formElement, $htmlFormElementName, $value, array &$json, $mode = FORM_LOAD) { + public function buildDateTime(array $formElement, $htmlFormElementName, $value, array &$json, $mode = FORM_LOAD) { $attribute = ''; $placeholder = ''; @@ -3522,8 +3527,7 @@ abstract class AbstractBuildForm { * @throws CodeException * @throws UserFormException */ - public - function buildDateJQW(array $formElement, $htmlFormElementName, $value, array &$json, $mode = FORM_LOAD) { + public function buildDateJQW(array $formElement, $htmlFormElementName, $value, array &$json, $mode = FORM_LOAD) { $arrMinMax = null; // if ($formElement[FE_PLACEHOLDER] == '') { @@ -3608,8 +3612,7 @@ abstract class AbstractBuildForm { * @throws UserFormException * @throws UserReportException */ - public - function buildEditor(array $formElement, $htmlFormElementName, $value, array &$json, $mode = FORM_LOAD) { + public function buildEditor(array $formElement, $htmlFormElementName, $value, array &$json, $mode = FORM_LOAD) { $attribute = ''; //TODO plugin autoresize nutzen um Editorgroesse anzugeben @@ -3652,8 +3655,7 @@ abstract class AbstractBuildForm { * * @return array */ - private - function setEditorConfig(array $formElement, $htmlFormElementName) { + private function setEditorConfig(array $formElement, $htmlFormElementName) { $flagMaxHeight = false; // plugins @@ -3708,8 +3710,7 @@ abstract class AbstractBuildForm { * @return string * @throws \qfq\UserFormException */ - private - function getPrefixedElementsAsJSON($prefix, array $formElement) { + private function getPrefixedElementsAsJSON($prefix, array $formElement) { $settings = array(); // E.g.: $key = editor-plugins @@ -3746,8 +3747,7 @@ abstract class AbstractBuildForm { * * @throws UserFormException */ - public - function buildGridJQW(array $formElement, $htmlFormElementName, $value, $fake, $mode = FORM_LOAD) { + public function buildGridJQW(array $formElement, $htmlFormElementName, $value, $fake, $mode = FORM_LOAD) { // TODO: implement throw new UserFormException("Not implemented yet: buildGridJQW()", ERROR_NOT_IMPLEMENTED); } @@ -3765,8 +3765,7 @@ abstract class AbstractBuildForm { * @throws CodeException * @throws UserFormException */ - public - function buildNote(array $formElement, $htmlFormElementName, $value, array &$json, $mode = FORM_LOAD) { + public function buildNote(array $formElement, $htmlFormElementName, $value, array &$json, $mode = FORM_LOAD) { $json = $this->getFormElementForJson($htmlFormElementName, $value, $formElement); @@ -3786,8 +3785,7 @@ abstract class AbstractBuildForm { * * @return mixed */ - public - function buildPill(array $formElement, $htmlFormElementName, $value, array &$json) { + public function buildPill(array $formElement, $htmlFormElementName, $value, array &$json) { return $value; } @@ -3810,8 +3808,7 @@ abstract class AbstractBuildForm { * @throws \PhpOffice\PhpSpreadsheet\Reader\Exception * @throws \PhpOffice\PhpSpreadsheet\Writer\Exception */ - public - function buildFieldset(array $formElement, $htmlFormElementName, $value, array &$json, $mode = FORM_LOAD) { + public function buildFieldset(array $formElement, $htmlFormElementName, $value, array &$json, $mode = FORM_LOAD) { $attribute = ''; // save parent processed FE's @@ -3856,8 +3853,7 @@ abstract class AbstractBuildForm { * * @return array */ - private - function fillFeSpecNativeCheckboxWithTgMax(array $formElementArr, $tgMaxCopies) { + private function fillFeSpecNativeCheckboxWithTgMax(array $formElementArr, $tgMaxCopies) { foreach ($formElementArr as $key => $formElement) { if ($formElement[FE_TYPE] == FE_TYPE_CHECKBOX) { @@ -3888,8 +3884,7 @@ abstract class AbstractBuildForm { * @throws \PhpOffice\PhpSpreadsheet\Reader\Exception * @throws \PhpOffice\PhpSpreadsheet\Writer\Exception */ - public - function buildTemplateGroup(array $formElement, $htmlFormElementName, $value, array &$json, $mode = FORM_LOAD) { + public function buildTemplateGroup(array $formElement, $htmlFormElementName, $value, array &$json, $mode = FORM_LOAD) { $attribute = ''; $html = ''; @@ -4012,8 +4007,7 @@ EOT; * @throws \PhpOffice\PhpSpreadsheet\Reader\Exception * @throws \PhpOffice\PhpSpreadsheet\Writer\Exception */ - private - function templateGroupCollectFilledElements($max, $htmlDelete, array &$json) { + private function templateGroupCollectFilledElements($max, $htmlDelete, array &$json) { $record = $this->store->getStore(STORE_RECORD); // current values if ($record === false || count($record) === 0) { @@ -4099,8 +4093,7 @@ EOT; * @throws UserFormException * @throws UserReportException */ - private - function templateGroupDoValue() { + private function templateGroupDoValue() { // Fire 'value' statement $tgMax = 0; diff --git a/javascript/src/CodeCorrection.js b/javascript/src/CodeCorrection.js index 2b98b5556ab781603f2ff5de9269394f3ab7e511..641a0fc157c26bbcbb3b6349d686f69399f0e4b1 100644 --- a/javascript/src/CodeCorrection.js +++ b/javascript/src/CodeCorrection.js @@ -42,6 +42,7 @@ var QfqNS = QfqNS || {}; this.users = []; this.currentUser = {}; this.language = ""; + this.readOnly = false; this.syntaxHighlight = {}; }; @@ -58,22 +59,21 @@ var QfqNS = QfqNS || {}; }; this.page = page; this.language = this.$parent.data("highlight") || "typo3conf/ext/qfq/Resources/Public/Json/javascript.json"; - + this.readOnly = this.$parent.data("view-only") || false; this.currentUser = $container.data("uid"); var that = this; - if (this.$target.val()) { - var jImport = $.parseJSON(this.$target.val()); - if (jImport.annotations) { - this.annotations = jImport.annotations; - console.log("[CodeCorrection] Imported Annotations: " + this.annotations.length); - } - if (jImport.users) { - this.users = jImport.users; - console.log("[CodeCorrection] Imported Users: " + this.users.length); + if (this.readOnly) { + if (this.$parent.data("annotations")) { + var jsonAnnotations = this.$parent.data("annotations"); + this.annotations = jsonAnnotations.annotations; + this.users = jsonAnnotations.users; + } else { + this._importFromTarget(); } + } else { + this._importFromTarget(); } - if (this.data.url) { // Get data of a file and write it to data.text $.get(this.data.url, function(response) { @@ -87,6 +87,20 @@ var QfqNS = QfqNS || {}; } }; + n.CodeCorrection.prototype._importFromTarget = function() { + if (this.$target.val()) { + var jImport = $.parseJSON(this.$target.val()); + if (jImport.annotations) { + this.annotations = jImport.annotations; + console.log("[CodeCorrection] Imported Annotations: " + this.annotations.length); + } + if (jImport.users) { + this.users = jImport.users; + console.log("[CodeCorrection] Imported Users: " + this.users.length); + } + } + }; + n.CodeCorrection.prototype._prepareBuild = function() { var that = this; this.syntaxHighlight = new n.SyntaxHighlighter(); @@ -206,8 +220,11 @@ var QfqNS = QfqNS || {}; * @private */ n.CodeCorrection.prototype._buildCommentContainer = function($hook) { + var options = { + readOnly: this.readOnly + }; var commentController = new n.CommentController(); - commentController.buildContainer($hook); + commentController.buildContainer($hook, options); commentController.setCurrentUser(this.currentUser); return commentController; }; @@ -350,13 +367,15 @@ var QfqNS = QfqNS || {}; comments.commentController.toggle(); comments.commentController.emitEvent("new"); } else { - comments.lineNumber = lineCount; - comments.commentController = new n.CommentController(); - comments.commentController.buildContainer($hook); - comments.commentController.setCurrentUser(this.currentUser); - comments.commentController.displayEditor(); - this._setListeners(comments.commentController); - this.annotations.push(comments); + if (!this.readOnly) { + comments.lineNumber = lineCount; + comments.commentController = new n.CommentController(); + comments.commentController.buildContainer($hook, {readOnly: this.readOnly}); + comments.commentController.setCurrentUser(this.currentUser); + comments.commentController.displayEditor(); + this._setListeners(comments.commentController); + this.annotations.push(comments); + } } }; diff --git a/javascript/src/Comment.js b/javascript/src/Comment.js index bcdaf455f03e66cdb2ee6b13441be6dd4ff74977..97a23366c90aaeb73ebddded4d91fd2935300f9d 100644 --- a/javascript/src/Comment.js +++ b/javascript/src/Comment.js @@ -30,7 +30,7 @@ var QfqNS = QfqNS || {}; this.$comment = {}; this.$text = {}; if (arguments.length === 3) { - this.options = { readonly: false }; + this.options = { readOnly: false }; } else { this.options = options; } @@ -81,7 +81,9 @@ var QfqNS = QfqNS || {}; class: "qfqCommentText" }); $comment.html(this.comment.comment); - $comment.append(this._getCommands()); + if (!this.options.readOnly) { + $comment.append(this._getCommands()); + } this.$text= $comment; $comment.appendTo($commentWrap); return $commentWrap; diff --git a/javascript/src/CommentController.js b/javascript/src/CommentController.js index def288bc3a601f3b50ab03c215a5ce4de5fd71c8..0c2bc76a64b1f4d1432e64bca192aab728e473ea 100644 --- a/javascript/src/CommentController.js +++ b/javascript/src/CommentController.js @@ -28,6 +28,7 @@ var QfqNS = QfqNS || {}; this.$container = {}; this.$parent = {}; this.height = "auto"; + this.options = {}; // Event Emitter is a Library qfq uses to emit custom Events. this.eventEmitter = new EventEmitter(); }; @@ -69,10 +70,11 @@ var QfqNS = QfqNS || {}; this._changeHandler(event); }; - n.CommentController.prototype.buildContainer = function($hook) { + n.CommentController.prototype.buildContainer = function($hook, options) { var $container = $("<div />", { class: "qfqCommentContainer" }); + this.options = options; $hook.after($container); this.$container = $container; }; @@ -99,7 +101,7 @@ var QfqNS = QfqNS || {}; }; n.CommentController.prototype.addComment = function(comment, user) { - var commentObject = new n.Comment(comment, user, this.$container); + var commentObject = new n.Comment(comment, user, this.$container, this.options); commentObject.display(); this.comments.push(commentObject); this._changeHandler("new", commentObject); @@ -129,14 +131,16 @@ var QfqNS = QfqNS || {}; }; n.CommentController.prototype.displayEditor = function() { - var editor = new n.Editor(); - var that = this; - var $editor = editor.buildEditor(); - editor.on("editor.submit", function(editor) { - that._handleEditorSubmit(editor); - }); - $editor.appendTo(this.$container); - editor.$textArea.focus(); + if (!this.options.readOnly) { + var editor = new n.Editor(); + var that = this; + var $editor = editor.buildEditor(); + editor.on("editor.submit", function (editor) { + that._handleEditorSubmit(editor); + }); + $editor.appendTo(this.$container); + editor.$textArea.focus(); + } }; n.CommentController.prototype._handleEditorSubmit = function(editor) { diff --git a/javascript/src/Form.js b/javascript/src/Form.js index 81971d3b124ee41466e9e0683d411e9a24ab2211..014e84a815c7aad0bf760de1098b5eccbba0bf8f 100644 --- a/javascript/src/Form.js +++ b/javascript/src/Form.js @@ -121,6 +121,7 @@ var QfqNS = QfqNS || {}; $.post(submitUrl, this.$form.serialize()) .done(this.ajaxSuccessHandler.bind(this)) .fail(this.submitFailureHandler.bind(this)); + console.log(this.$form.serialize()); }; n.Form.prototype.serialize = function () { diff --git a/less/qfq-bs.css.less b/less/qfq-bs.css.less index c8b9edd97c4f29c024509630556a891e02d2375c..7b95336e1af8b6114434d9d067d758bcf46699c5 100644 --- a/less/qfq-bs.css.less +++ b/less/qfq-bs.css.less @@ -491,6 +491,7 @@ select.qfq-locked:invalid { .codeCorrectionWrap { border: 1px solid #ccc; border-top: unset; + margin-bottom: 10px; } .qfqCodeCorrectionTitle { @@ -520,6 +521,7 @@ select.qfq-locked:invalid { text-align: left; font-size: 1.2em; font-family: monospace; + word-break: break-word; } .qfqCodeLine { diff --git a/mockup/codeCorrectionReadOnly.html b/mockup/codeCorrectionReadOnly.html new file mode 100644 index 0000000000000000000000000000000000000000..c94a33097ec0276248ef601b77021b81dc82ca05 --- /dev/null +++ b/mockup/codeCorrectionReadOnly.html @@ -0,0 +1,148 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <meta http-equiv="X-UA-Compatible" content="IE=edge"> + + <link rel="stylesheet" href="../extension/Resources/Public/Css/bootstrap.min.css"> + <link rel="stylesheet" href="../extension/Resources/Public/Css/bootstrap-theme.min.css"> + + <link rel="stylesheet" href="../extension/Resources/Public/Css/qfq-bs.css"> + <title>Input Mode Switcher</title> + +</head> +<body style="background-color: #f5f5f5;"> +<div class="container-fluid"> + <div class="row"> + <div class="col-md-10 "> + <div class="btn-toolbar pull-right" role="toolbar"> + <div class="btn-group" role="group"> + <button id="save-button" type="button" class="btn btn-default navbar-btn"><span + class="glyphicon glyphicon-ok"></span></button> + <button id="close-button" type="button" class="btn btn-default navbar-btn"><span + class="glyphicon glyphicon-remove"></span></button> + </div> + <div class="btn-group" role="group"> + <button id="delete-button" type="button" class="btn btn-default navbar-btn"><span + class="glyphicon glyphicon-trash"></span></button> + </div> + <div class="btn-group" role="group"> + <a id="form-new-button" href="personmock.html?s=badcaffe1" class="btn btn-default navbar-btn"><span + class="glyphicon glyphicon-plus"></span></a> + </div> + </div> + </div> + </div> + + <div class="row"> + <div class="col-md-2"></div> + <div class="col-md-8"> + + <div class="annotate-text" + data-uid='{ "uid": 5, + "name": "Definitely not an AI", + "avatar": "mockData/avatar1.png"}' + data-file="../javascript/src/CodeCorrection.js" + data-annotations= '{ "annotations": [ + { "lineNumber": 15, + "comments": [ + { "uid": 1, + "comment": "If we knew what it was we were doing, it would not be called research, would it?", + "dateTime": "2018-05-12 09:45:00" + }] + }, { "lineNumber": 47, + "comments": [ + { "uid": 1, + "comment": "The most beautiful thing we can experience is the mysterious. It is the source of all true art and all science.", + "dateTime": "2018-05-12 09:45:00" + }, + { "uid": 1, + "comment": "The only reason for time is so that everything does not happen at once.", + "dateTime": "0000-00-00 00:00:00" + }] + } + ], + "users": [ + { "uid": 1, + "name": "Albert Einstein", + "avatar": "http://institutoiltonesteves.com.br/img/avatar-4.jpg" + } + ]}' + data-highlight="mockData/javascript.json" + data-view-only="true" + > + </div> + + <div class="annotate-text" + data-uid='{ "uid": 5, + "name": "Definitely not an AI", + "avatar": "mockData/avatar1.png"}' + data-file="../javascript/src/CodeCorrection.js" + data-target= 'codeCorrection-output1' + data-highlight="mockData/javascript.json" + data-view-only="true" + > + </div> + + <input id="codeCorrection-output1" name="correction-data" type="hidden" + value='{ "annotations": [ + { "lineNumber": 15, + "comments": [ + { "uid": 1, + "comment": "If we knew what it was we were doing, it would not be called research, would it?", + "dateTime": "2018-05-12 09:45:00" + }] + }, { "lineNumber": 47, + "comments": [ + { "uid": 1, + "comment": "The most beautiful thing we can experience is the mysterious. It is the source of all true art and all science.", + "dateTime": "2018-05-12 09:45:00" + }, + { "uid": 1, + "comment": "The only reason for time is so that everything does not happen at once.", + "dateTime": "0000-00-00 00:00:00" + }] + } + ], + "users": [ + { "uid": 1, + "name": "Albert Einstein", + "avatar": "http://institutoiltonesteves.com.br/img/avatar-4.jpg" + } + ]}'> + </div> + </div> +</div> +<p><br></p> +<script src="../js/jquery.min.js"></script> +<script src="../js/bootstrap.min.js"></script> +<script src="../js/validator.min.js"></script> +<script src="../js/EventEmitter.min.js"></script> +<script src="../js/qfq.debug.js"></script> + +<script type="text/javascript"> + $(function () { + var qfqPage = new QfqNS.QfqPage({ + tabsId: 'myTabs', + formId: 'myForm', + submitTo: 'api/' + $("#submitTo").val(), + deleteUrl: 'api/' + $("#deleteUrl").val(), + fileUploadTo: 'api/' + $("#uploadTo").val(), + fileDeleteUrl: 'api/' + $("#fileDeleteUrl").val() + }); + + QfqNS.Log.level = 0; + + //var codeCorrection = new QfqNS.CodeCorrection(qfqPage, { + // url: '../javascript/src/CodeCorrection.js' + //}, $('.annotate-text'), $('#codeCorrection-output1'), { + // uid: 5, + // name: "Definitely not an AI", + // avatar: "mockData/avatar1.png" + //}, 'http://localhost:63342/qfq/mockup/mockData/javascript.json'); + //codeCorrection.initialize(); + }); +</script> +</body> +</html> \ No newline at end of file