Difference between revisions of "Widget:CodeExplorer"
From Coder Merlin
(6 intermediate revisions by one other user not shown) | |||
Line 1: | Line 1: | ||
<noinclude> | <noinclude> | ||
Parameters: | Parameters: | ||
;userName: The current user's username | ;userName: string: The current user's username | ||
; | ;sessionID: string: The ID of the current user's session | ||
;experienceID: string: The experienceID of the page from which the widget is invoked | |||
;codeExplorerGroupID: string: The code explorer group. If empty, the submit button will be disabled. | |||
;exerciseID: integer: exercise id for editor, must be unique per page | |||
;width: integer|string: percentage (as string, e.g. "100%" or integer size in pixels), null for no change (full width) | ;width: integer|string: percentage (as string, e.g. "100%" or integer size in pixels), null for no change (full width) | ||
;height: integer|string: percentage (as string, e.g. "100%" or integer size in pixels), null for no change (~10 lines) | ;height: integer|string: percentage (as string, e.g. "100%" or integer size in pixels), null for no change (~10 lines) | ||
Line 15: | Line 18: | ||
{{#widget:CodeExplorer | {{#widget:CodeExplorer | ||
|userName=john-williams | |userName=john-williams | ||
| | |sessionID=qh0ubrrme911kcg7db0i0ec6lct94h7f | ||
|experienceID=W1020.23 | |||
|codeExplorerGroupID=WTRS-8527 | |||
|exerciseID=10 | |||
|width=null | |width=null | ||
|height=null | |height=null | ||
Line 30: | Line 36: | ||
<includeonly> | <includeonly> | ||
<form action="" id="codeEditorForm<!--{$ | <form action="" id="codeEditorForm<!--{$exerciseID|validate:int}-->"> | ||
<div class="merlin-code-explorer-container"> | <div class="merlin-code-explorer-container"> | ||
<div class="merlin-code-explorer-banner"> | <div class="merlin-code-explorer-banner"> | ||
<img class="merlin-code-explorer-banner-merlin-icon" src="/wiki/resources/assets/MerlinRoundIcon.png" /> | <img class="merlin-code-explorer-banner-merlin-icon" src="/wiki/resources/assets/MerlinRoundIcon.png" /> | ||
<span class="merlin-code-explorer-banner-text">CoderMerlin™ Code Explorer</span> | <span class="merlin-code-explorer-banner-text">CoderMerlin™ Code Explorer: <!--{$experienceID}--> (<!--{$exerciseID}-->)</span> | ||
<img class="merlin-code-explorer-banner-language-icon" src="/wiki/images/thumb/3/3b/Swift-og.png/600px-Swift-og.png" /> | <img class="merlin-code-explorer-banner-language-icon" src="/wiki/images/thumb/3/3b/Swift-og.png/600px-Swift-og.png" /> | ||
</div> | </div> | ||
<div class="merlin-code-explorer-code-panel"> | <div class="merlin-code-explorer-code-panel"> | ||
<textarea id="codeEditorTextArea<!--{$ | <textarea id="codeEditorTextArea<!--{$exerciseID|validate:int}-->"><!--{$initialCode}--></textarea> | ||
<script> | <script> | ||
var codeEditor<!--{$ | var codeEditor<!--{$exerciseID|validate:int}-->; | ||
window.addEventListener('load', (event) => { | window.addEventListener('load', (event) => { | ||
codeEditor<!--{$ | codeEditor<!--{$exerciseID|validate:int}--> = CodeMirror.fromTextArea(document.getElementById('codeEditorTextArea<!--{$exerciseID|validate:int}-->'), | ||
{ | { | ||
keyMap: "emacs", | keyMap: "emacs", | ||
Line 51: | Line 57: | ||
} | } | ||
); | ); | ||
codeEditor<!--{$ | // Set size | ||
codeEditor<!--{$exerciseID|validate:int}-->.setSize("<!--{$width}-->", "<!--{$height}-->"); | |||
// Determine if submit button is enabled, if not, disable | |||
var isSubmitEnabled = '<!--{$codeExplorerGroupID|strip}-->'.length > 0; | |||
if (isSubmitEnabled) { | |||
var submitButton = $("#codeEditorSubmitButton<!--{$exerciseID|validate:int}-->"); | |||
submitButton.prop("value", "Submit to <!--{$codeExplorerGroupID|strip}-->"); | |||
} else { | |||
var submitButton = $("#codeEditorSubmitButton<!--{$exerciseID|validate:int}-->"); | |||
submitButton.attr("disabled", true); | |||
submitButton.css("background-color", "gray"); | |||
} | |||
// Attach handler to form | // Attach handler to form | ||
$("#codeEditorForm<!--{$ | $("#codeEditorForm<!--{$exerciseID|validate:int}-->").submit(function(event) { | ||
// Suppress standard submission | // Suppress standard submission | ||
event.preventDefault(); | event.preventDefault(); | ||
// Disable | // Disable buttons | ||
var submitButton = $("#codeEditorSubmitButton<!--{$ | var executeButton = $("#codeEditorExecuteButton<!--{$exerciseID|validate:int}-->"); | ||
var submitButton = $("#codeEditorSubmitButton<!--{$exerciseID|validate:int}-->"); | |||
var executeButtonBackgroundColor = executeButton.css("background-color"); | |||
var submitButtonBackgroundColor = submitButton.css("background-color"); | var submitButtonBackgroundColor = submitButton.css("background-color"); | ||
executeButton.attr("disabled", true); | |||
executeButton.css("background-color", "gray"); | |||
submitButton.attr("disabled", true); | submitButton.attr("disabled", true); | ||
submitButton.css("background-color", "gray"); | submitButton.css("background-color", "gray"); | ||
// Clear output | // Clear output | ||
$("#codeEditorCombinedOutput<!--{$ | $("#codeEditorCombinedOutput<!--{$exerciseID|validate:int}-->").empty(); | ||
// Submit form via POST | // Submit form via POST | ||
var username = "<!--{$userName}-->".toLowerCase(); | |||
var sessionID = "<!--{$sessionID}-->" | |||
var url = (subdomain() == "stg") ? | var url = (subdomain() == "stg") ? | ||
"https://language-server-stg.codermerlin.com/ | "https://language-server-stg.codermerlin.com/" : | ||
"https://language-server.codermerlin.com/ | "https://language-server.codermerlin.com/"; | ||
switch (event.target.submitter) { | |||
case "execute": | |||
" | url += "experiences/" + "<!--{$experienceID}-->/" + "exercises/" + "<!--{$exerciseID}-->" + "/executions"; | ||
" | break; | ||
case "submit": | |||
"sourceCodeLanguage": "swift", | url += "codeExplorerGroups/" + "<!--{$codeExplorerGroupID}-->/" + "experiences/" + "<!--{$experienceID}-->/" + "exercises/" + "<!--{$exerciseID}-->"; | ||
break; | |||
} | |||
console.log(url); | |||
var response = $.ajax({ | |||
type: "POST", | |||
url, | |||
headers: { | |||
"username": username, | |||
"sessionID": sessionID | |||
}, | |||
data: { | |||
"sourceCodeLanguage": "swift", | |||
"sourceCode": codeEditor<!--{$exerciseID|validate:int}-->.getValue() | |||
}, | |||
timeout: 6000, | |||
error: function(jqXHR, textStatus, errorThrown) { | |||
// Display error | |||
$("#codeEditorCombinedOutput<!--{$exerciseID|validate:int}-->").append("<span class='merlin-code-explorer-combined-output-error'>" + | |||
"Failed to complete operation." + | |||
"</span><br/>"); | |||
console.log(textStatus + " " + errorThrown); | |||
// Re-enable buttons | |||
executeButton.attr("disabled", false); | |||
executeButton.css("background-color", executeButtonBackgroundColor); | |||
if (isSubmitEnabled) { | |||
submitButton.attr("disabled", false); | |||
submitButton.css("background-color", submitButtonBackgroundColor); | |||
} | |||
} | |||
}); | }); | ||
// Collect response data | // Collect response data | ||
response.done(function(data) { | response.done(function(data) { | ||
var executionCodeResponse = | var executionCodeResponse = JSON.parse(data); | ||
var standardError = consoleToHTML(executionCodeResponse.standardError); | var standardError = consoleToHTML(executionCodeResponse.standardError); | ||
var standardOutput = consoleToHTML(executionCodeResponse.standardOutput); | var standardOutput = consoleToHTML(executionCodeResponse.standardOutput); | ||
Line 102: | Line 155: | ||
errorClass = "merlin-code-explorer-combined-output-error"; | errorClass = "merlin-code-explorer-combined-output-error"; | ||
}; | }; | ||
$("#codeEditorCombinedOutput<!--{$ | $("#codeEditorCombinedOutput<!--{$exerciseID|validate:int}-->").append("<span class='" + errorClass + "'>" + errorLine + "</span><br/>"); | ||
}; | }; | ||
$("#codeEditorCombinedOutput<!--{$ | $("#codeEditorCombinedOutput<!--{$exerciseID|validate:int}-->").append(standardOutput); | ||
// Re-enable | // Re-enable buttons | ||
submitButton.attr("disabled", false); | executeButton.attr("disabled", false); | ||
executeButton.css("background-color", executeButtonBackgroundColor); | |||
if (isSubmitEnabled) { | |||
submitButton.attr("disabled", false); | |||
submitButton.css("background-color", submitButtonBackgroundColor); | |||
} | |||
}); | }); | ||
}); | }); | ||
Line 115: | Line 172: | ||
</div> | </div> | ||
<div class="merlin-code-explorer-control-panel"> | <div class="merlin-code-explorer-control-panel"> | ||
<input id="codeEditorSubmitButton<!--{$ | <input id="codeEditorExecuteButton<!--{$exerciseID|validate:int}-->" class="merlin-code-explorer-execute-button" onclick="this.form.submitter = 'execute';" type="submit" value="Run" /> | ||
<input id="codeEditorSubmitButton<!--{$exerciseID|validate:int}-->" class="merlin-code-explorer-submit-button" onclick="this.form.submitter = 'submit';" type="submit" value="Submit"/> | |||
</div> | </div> | ||
<div id="codeEditorCombinedOutput<!--{$ | <div id="codeEditorCombinedOutput<!--{$exerciseID|validate:int}-->" class="merlin-code-explorer-combined-output"></div> | ||
</div> | </div> | ||
</form> | </form> | ||
</includeonly> | </includeonly> |
Revision as of 20:18, 5 October 2021
Parameters:
- userName
- string: The current user's username
- sessionID
- string: The ID of the current user's session
- experienceID
- string: The experienceID of the page from which the widget is invoked
- codeExplorerGroupID
- string: The code explorer group. If empty, the submit button will be disabled.
- exerciseID
- integer: exercise id for editor, must be unique per page
- width
- integer|string: percentage (as string, e.g. "100%" or integer size in pixels), null for no change (full width)
- height
- integer|string: percentage (as string, e.g. "100%" or integer size in pixels), null for no change (~10 lines)
- lineNumbers
- boolean: true to display line numbers
- theme
- string: name of theme (which must be loaded via css)
- readOnly
- boolean: true if editing should be disabled
- mode
- string: language for highlighting (which must be loaded via js)
- initialCode
- string: initial code to place in editor
Example:
{{#widget:CodeExplorer |userName=john-williams |sessionID=qh0ubrrme911kcg7db0i0ec6lct94h7f |experienceID=W1020.23 |codeExplorerGroupID=WTRS-8527 |exerciseID=10 |width=null |height=null |lineNumbers=true |theme=vibrant-ink |readOnly=false |mode=swift |initialCode=func sayHello() { print("Hello, World!") } }}