mumuki-laboratory 7.7.6 → 7.10.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +83 -3
- data/Rakefile +7 -1
- data/app/assets/javascripts/mumuki_laboratory/application/alias-modes.js +1 -1
- data/app/assets/javascripts/mumuki_laboratory/application/bridge.js +66 -57
- data/app/assets/javascripts/mumuki_laboratory/application/codemirror-builder.js +28 -25
- data/app/assets/javascripts/mumuki_laboratory/application/codemirror.js +8 -10
- data/app/assets/javascripts/mumuki_laboratory/application/confirmation.js +2 -2
- data/app/assets/javascripts/mumuki_laboratory/application/console.js +41 -43
- data/app/assets/javascripts/mumuki_laboratory/application/csrf-token.js +9 -12
- data/app/assets/javascripts/mumuki_laboratory/application/custom-editor.js +11 -15
- data/app/assets/javascripts/mumuki_laboratory/application/discussions.js +1 -3
- data/app/assets/javascripts/mumuki_laboratory/application/editors.js +104 -0
- data/app/assets/javascripts/mumuki_laboratory/application/elipsis.js +5 -4
- data/app/assets/javascripts/mumuki_laboratory/application/events.js +51 -0
- data/app/assets/javascripts/mumuki_laboratory/application/exercise.js +68 -0
- data/app/assets/javascripts/mumuki_laboratory/application/inputs.js +4 -2
- data/app/assets/javascripts/mumuki_laboratory/application/interval.js +2 -4
- data/app/assets/javascripts/mumuki_laboratory/application/kids.js +1 -1
- data/app/assets/javascripts/mumuki_laboratory/application/load-analytics.js +1 -1
- data/app/assets/javascripts/mumuki_laboratory/application/load-error-svg.js +1 -1
- data/app/assets/javascripts/mumuki_laboratory/application/messages.js +2 -2
- data/app/assets/javascripts/mumuki_laboratory/application/multiple-choice.js +1 -1
- data/app/assets/javascripts/mumuki_laboratory/application/multiple-scenarios.js +3 -6
- data/app/assets/javascripts/mumuki_laboratory/application/pin.js +3 -5
- data/app/assets/javascripts/mumuki_laboratory/application/profile.js +71 -0
- data/app/assets/javascripts/mumuki_laboratory/application/progress.js +24 -6
- data/app/assets/javascripts/mumuki_laboratory/application/results-renderer.js +20 -11
- data/app/assets/javascripts/mumuki_laboratory/application/speech-bubble-renderer.js +12 -5
- data/app/assets/javascripts/mumuki_laboratory/application/submission.js +19 -101
- data/app/assets/javascripts/mumuki_laboratory/application/submissions-store.js +93 -0
- data/app/assets/javascripts/mumuki_laboratory/application/sync-mode.js +75 -0
- data/app/assets/javascripts/mumuki_laboratory/application/timer.js +5 -6
- data/app/assets/javascripts/mumuki_laboratory/application/tooltip.js +1 -1
- data/app/assets/javascripts/mumuki_laboratory/application/upload.js +1 -1
- data/app/assets/javascripts/mumuki_laboratory/application/user.js +1 -1
- data/app/assets/stylesheets/mumuki_laboratory/application.scss +1 -1
- data/app/assets/stylesheets/mumuki_laboratory/application/_modules.scss +19 -17
- data/app/assets/stylesheets/mumuki_laboratory/application/modules/_avatar.scss +41 -0
- data/app/assets/stylesheets/mumuki_laboratory/application/modules/_gs-board.scss +3 -0
- data/app/assets/stylesheets/mumuki_laboratory/application/modules/{guide-corollary.scss → _guide_corollary.scss} +0 -0
- data/app/assets/stylesheets/mumuki_laboratory/application/modules/_kids.scss +1 -2
- data/app/assets/stylesheets/mumuki_laboratory/application/modules/_kindergarten.scss +2 -1
- data/app/assets/stylesheets/mumuki_laboratory/application/modules/{popover.scss → _popover.scss} +0 -0
- data/app/assets/stylesheets/mumuki_laboratory/application/modules/_user_profile.scss +36 -0
- data/app/controllers/application_controller.rb +2 -1
- data/app/controllers/users_controller.rb +5 -1
- data/app/helpers/application_helper.rb +6 -4
- data/app/helpers/avatar_helper.rb +9 -0
- data/app/helpers/discussions_helper.rb +2 -2
- data/app/helpers/{locale_helper.rb → globals_helper.rb} +6 -2
- data/app/helpers/profile_helper.rb +5 -0
- data/app/mailers/user_mailer.rb +24 -11
- data/app/views/book/show.html.erb +1 -1
- data/app/views/exercises/show.html.erb +3 -0
- data/app/views/layouts/_main.html.erb +1 -2
- data/app/views/layouts/_progress.html.erb +1 -1
- data/app/views/layouts/_progress_bar.html.erb +7 -1
- data/app/views/layouts/_runner_assets.html.erb +1 -2
- data/app/views/layouts/application.html.erb +2 -2
- data/app/views/layouts/modals/_avatar_picker.html.erb +16 -0
- data/app/views/users/_avatar_list.html.erb +11 -0
- data/app/views/users/_edit_user_form.html.erb +22 -0
- data/app/views/users/_user_form.html.erb +21 -8
- data/app/views/users/edit.html.erb +5 -0
- data/app/views/users/show.html.erb +0 -4
- data/config/routes.rb +1 -1
- data/lib/mumuki/laboratory/controllers.rb +1 -0
- data/lib/mumuki/laboratory/controllers/incognito_mode.rb +28 -0
- data/lib/mumuki/laboratory/locales/datetime.es.yml +14 -14
- data/lib/mumuki/laboratory/locales/en.yml +12 -4
- data/lib/mumuki/laboratory/locales/es.yml +12 -4
- data/lib/mumuki/laboratory/locales/pt.yml +10 -2
- data/lib/mumuki/laboratory/version.rb +1 -1
- data/spec/dummy/db/schema.rb +13 -1
- data/spec/features/chapter_spec.rb +17 -0
- data/spec/features/exercise_flow_spec.rb +54 -6
- data/spec/features/home_public_flow_spec.rb +16 -0
- data/spec/helpers/avatar_helper_spec.rb +26 -0
- data/spec/javascripts/editors-spec.js +54 -0
- data/spec/javascripts/events-spec.js +33 -0
- data/spec/javascripts/exercise-spec.js +41 -0
- data/spec/javascripts/global-spec.js +6 -0
- data/spec/javascripts/spec-helper.js +4 -0
- data/spec/javascripts/submissions-store-spec.js +44 -0
- data/spec/javascripts/sync-mode-spec.js +15 -0
- data/spec/mailers/user_mailer_spec.rb +23 -3
- data/spec/teaspoon_env.rb +8 -2
- data/vendor/assets/javascripts/codemirror-modes/gobstones.js +3 -3
- metadata +38 -11
- data/app/assets/stylesheets/mumuki_laboratory/application/modules/_follow_us.scss +0 -16
- data/app/helpers/version_helper.rb +0 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bebb464d17fe422eab18c1b6690c0572a7ca3acb53aed8c52b43fcedb51836a9
|
4
|
+
data.tar.gz: f65bd35e2c7091674c3139e44cd65c7a74fd7f2fdfbbea8f28b48017b2be4893
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b28b1f33dcf29c849792765306717ddd1b3de8dcae84e38a7d50ebe30ff5da7615d0f41d1f7d510393cfc274c66818c90f1c019ca9fdb8a066fb3f047904e945
|
7
|
+
data.tar.gz: f14e48c807c249054ef2f15e5843ee6c6ff87cae9f773c77346da94d89a54d440f64d943d15d57d1159e98c764bb859d82e32bc47a1ce7e203ab9497a09d9167
|
data/README.md
CHANGED
@@ -141,9 +141,53 @@ bundle exec rspec
|
|
141
141
|
> it and add it to your path
|
142
142
|
|
143
143
|
```bash
|
144
|
-
bundle exec rake teaspoon
|
144
|
+
MOZ_HEADLESS=1 bundle exec rake teaspoon
|
145
145
|
```
|
146
146
|
|
147
|
+
## Running `eslint`
|
148
|
+
|
149
|
+
```bash
|
150
|
+
yarn run lint
|
151
|
+
```
|
152
|
+
|
153
|
+
## Using a local runner
|
154
|
+
|
155
|
+
Sometimes you will need to check `laboratory` against a local runner. Run the following code in you `rails console`:
|
156
|
+
|
157
|
+
```ruby
|
158
|
+
require 'mumuki/domain/seed'
|
159
|
+
|
160
|
+
# import a new language
|
161
|
+
Mumuki::Domain::Seed.languages_syncer.locate_and_import! Language, 'http://localhost:9292'
|
162
|
+
|
163
|
+
# update an existing language object
|
164
|
+
Mumuki::Domain::Seed.languages_syncer.import! Mumukit::Sync.key(Language, 'http://localhost:9292'), language
|
165
|
+
```
|
166
|
+
|
167
|
+
## Using a remote content
|
168
|
+
|
169
|
+
Likewise, you will sometimes require a guide that is not locally available. Run the following code in `rails console`:
|
170
|
+
|
171
|
+
```ruby
|
172
|
+
require 'mumuki/domain/seed'
|
173
|
+
|
174
|
+
# import a new guide
|
175
|
+
Mumuki::Domain::Seed.contents_syncer.locate_and_import! Guide, slug)
|
176
|
+
|
177
|
+
# update an existing guide object
|
178
|
+
Mumuki::Domain::Seed.contents_syncer.import! Mumukit::Sync.key(Guide, slug), guide
|
179
|
+
```
|
180
|
+
|
181
|
+
After that you will probably to add it somewhere. The easiest way is to create a complement of `central`:
|
182
|
+
|
183
|
+
```ruby
|
184
|
+
o = Organization.central
|
185
|
+
o.book.complements << Guide.locate!(slug).as_complement_of(o.book)
|
186
|
+
o.reindex_usages!
|
187
|
+
```
|
188
|
+
|
189
|
+
Now you will be able to visit that guide at `http://localhost:3000/central/guides/#{slug}`
|
190
|
+
|
147
191
|
## JavaScript API Docs
|
148
192
|
|
149
193
|
In order to be customized by runners, Laboratory exposes the following selectors and methods
|
@@ -208,6 +252,10 @@ which are granted to be safe and stable.
|
|
208
252
|
* `SpeechBubbleRenderer`
|
209
253
|
* `renderSpeechBubbleResultItem`
|
210
254
|
* `mumuki.locale`
|
255
|
+
* `mumuki.exercise`
|
256
|
+
* `id`: the `id` of the currently loaded exercise, if any
|
257
|
+
* `layout`: the `layout` of the currently loaded exercise, if any
|
258
|
+
* `mumuki.incognitoUser`: whether the current user is an incognito user
|
211
259
|
* `mumuki.MultipleScenarios`
|
212
260
|
* `scenarios`
|
213
261
|
* `currentScenarioIndex`
|
@@ -258,6 +306,38 @@ which are granted to be safe and stable.
|
|
258
306
|
2. Laboratory Kids Layout Initialization
|
259
307
|
3. Runner Editor HTML
|
260
308
|
|
309
|
+
## Generic event system
|
310
|
+
|
311
|
+
Laboartory provides the `mumuki.events` object, which acts as minimal, generic event system, which is mostly designed for third party components built on top of laboratory and runners. It does nothing by default.
|
312
|
+
|
313
|
+
This API has two parts: consumers API and producers API.
|
314
|
+
|
315
|
+
```javascript
|
316
|
+
// ======
|
317
|
+
// producer
|
318
|
+
// ======
|
319
|
+
|
320
|
+
// you need to call this method in order to enable registration of event handlers
|
321
|
+
// otherwise, it will be ignored
|
322
|
+
mumuki.events.enable('myEvent');
|
323
|
+
|
324
|
+
// fire the event, with an optional event object as payload
|
325
|
+
mumuki.events.fire('myEvent', aPlainOldObject);
|
326
|
+
|
327
|
+
// clear all the registered event handlers
|
328
|
+
mumuki.events.clear('myEvent');
|
329
|
+
|
330
|
+
// ========
|
331
|
+
// consumer
|
332
|
+
// ========
|
333
|
+
|
334
|
+
// register an event handler
|
335
|
+
mumuki.events.on('myEvent', (anEventObject) => {
|
336
|
+
// do stuff
|
337
|
+
});
|
338
|
+
```
|
339
|
+
|
340
|
+
|
261
341
|
## Custom editors
|
262
342
|
|
263
343
|
Mumuki provides several editor types: code editors, multiple choice, file upload, and so on.
|
@@ -369,14 +449,14 @@ contents. There are two different approaches:
|
|
369
449
|
|
370
450
|
```javascript
|
371
451
|
// simplest method - you can register just one
|
372
|
-
mumuki.
|
452
|
+
mumuki.editors.registerContentSyncer(() => {
|
373
453
|
// ... write here your custom component content...
|
374
454
|
$('#mu-custom-editor-value').val(/* ... */);
|
375
455
|
});
|
376
456
|
|
377
457
|
// alternate method
|
378
458
|
// you can register many sources
|
379
|
-
mumuki.
|
459
|
+
mumuki.editors.addCustomSource({
|
380
460
|
getContent() {
|
381
461
|
return { name: "solution[content]", value: /* ... */ } ;
|
382
462
|
}
|
data/Rakefile
CHANGED
@@ -27,8 +27,14 @@ require 'rspec/core/rake_task'
|
|
27
27
|
desc "Run all specs in spec directory (excluding plugin specs)"
|
28
28
|
RSpec::Core::RakeTask.new(:spec => 'app:db:test:prepare')
|
29
29
|
|
30
|
+
desc "Force development environment, required by javascript specs"
|
31
|
+
task :development do
|
32
|
+
ENV['RACK_ENV'] = 'development'
|
33
|
+
ENV['RAILS_ENV'] = 'development'
|
34
|
+
end
|
35
|
+
|
30
36
|
desc "Run the javascript specs"
|
31
|
-
task :
|
37
|
+
task teaspoon: [:development, "app:teaspoon"]
|
32
38
|
|
33
39
|
task default: :spec
|
34
40
|
|
@@ -1,60 +1,41 @@
|
|
1
1
|
/**
|
2
|
-
* @typedef {
|
2
|
+
* @typedef {"errored"|"failed"|"passed_with_warnings"|"passed"|"pending"|"aborted"} SubmissionStatus
|
3
3
|
*/
|
4
4
|
|
5
5
|
/**
|
6
|
-
* @typedef {{
|
6
|
+
* @typedef {{
|
7
|
+
* status: SubmissionStatus,
|
8
|
+
* test_results: [{status: SubmissionStatus, title: string}]
|
9
|
+
* }} SubmissionClientResult
|
7
10
|
*/
|
8
11
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
}
|
17
|
-
|
18
|
-
function asString(json){
|
19
|
-
return JSON.stringify(json);
|
20
|
-
}
|
21
|
-
|
22
|
-
function sameAsLastSolution(newSolution){
|
23
|
-
return asString(lastSubmission.content) === asString(newSolution);
|
24
|
-
}
|
25
|
-
|
26
|
-
function lastSubmissionFinishedSuccessfully(){
|
27
|
-
return lastSubmission.result && lastSubmission.result.status !== 'aborted';
|
28
|
-
}
|
29
|
-
|
30
|
-
function sendNewSolution(submission){
|
31
|
-
var token = new mumuki.CsrfToken();
|
32
|
-
var request = token.newRequest({
|
33
|
-
type: 'POST',
|
34
|
-
url: window.location.origin + window.location.pathname + '/solutions' + window.location.search,
|
35
|
-
data: submission
|
36
|
-
});
|
37
|
-
|
38
|
-
return $.ajax(request).then(preRenderResult).done(function (result) {
|
39
|
-
lastSubmission = { content: {solution: submission.solution}, result: result };
|
40
|
-
});
|
41
|
-
}
|
12
|
+
/**
|
13
|
+
* @typedef {{
|
14
|
+
* status: SubmissionStatus,
|
15
|
+
* class_for_progress_list_item?: string,
|
16
|
+
* guide_finished_by_solution?: boolean
|
17
|
+
* }} SubmissionResult
|
18
|
+
*/
|
42
19
|
|
20
|
+
/**
|
21
|
+
* @typedef {object} Solution
|
22
|
+
*/
|
43
23
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
24
|
+
/**
|
25
|
+
* @typedef {{
|
26
|
+
* "solution[content]"?:string,
|
27
|
+
* solution?: Solution,
|
28
|
+
* client_result?: SubmissionClientResult
|
29
|
+
* }} Submission
|
30
|
+
*/
|
51
31
|
|
52
|
-
|
53
|
-
|
54
|
-
|
32
|
+
/**
|
33
|
+
* @typedef {{submission?: Submission, result?: SubmissionResult}} SubmissionAndResult
|
34
|
+
*/
|
55
35
|
|
56
|
-
|
36
|
+
mumuki.bridge = (() => {
|
57
37
|
|
38
|
+
class Laboratory {
|
58
39
|
// ==========
|
59
40
|
// Public API
|
60
41
|
// ==========
|
@@ -65,9 +46,9 @@ var mumuki = mumuki || {};
|
|
65
46
|
*
|
66
47
|
* @param {object} content the content object
|
67
48
|
* */
|
68
|
-
runTests
|
49
|
+
runTests(content) {
|
69
50
|
return this._submitSolution({ solution: content });
|
70
|
-
}
|
51
|
+
}
|
71
52
|
|
72
53
|
// ===========
|
73
54
|
// Private API
|
@@ -77,18 +58,46 @@ var mumuki = mumuki || {};
|
|
77
58
|
* Sends a solution object
|
78
59
|
*
|
79
60
|
* @param {Submission} submission the submission object
|
61
|
+
* @returns {JQuery.Promise<SubmissionResult>}
|
80
62
|
*/
|
81
|
-
_submitSolution
|
82
|
-
|
83
|
-
|
63
|
+
_submitSolution(submission) {
|
64
|
+
const lastSubmission = mumuki.SubmissionsStore.getSubmissionResultFor(mumuki.exercise.id, submission);
|
65
|
+
if (lastSubmission) {
|
66
|
+
return $.Deferred().resolve(lastSubmission);
|
84
67
|
} else {
|
85
|
-
return
|
68
|
+
return this._sendNewSolution(submission).done((result) => {
|
69
|
+
mumuki.SubmissionsStore.setSubmissionResultFor(mumuki.exercise.id, {submission, result});
|
70
|
+
});
|
86
71
|
}
|
87
72
|
}
|
88
|
-
};
|
89
73
|
|
90
|
-
|
91
|
-
|
92
|
-
|
74
|
+
/**
|
75
|
+
* @param {Submission} submission the submission object
|
76
|
+
* @returns {JQuery.Promise<SubmissionResult>}
|
77
|
+
*/
|
78
|
+
_sendNewSolution(submission){
|
79
|
+
var token = new mumuki.CsrfToken();
|
80
|
+
var request = token.newRequest({
|
81
|
+
type: 'POST',
|
82
|
+
url: window.location.origin + window.location.pathname + '/solutions' + window.location.search,
|
83
|
+
data: submission
|
84
|
+
});
|
85
|
+
return $.ajax(request).then((result) => this._preRenderResult(result));
|
86
|
+
}
|
87
|
+
|
88
|
+
/**
|
89
|
+
* Pre-renders some html parts of submission UI, adding them to the given result
|
90
|
+
*
|
91
|
+
* @param {SubmissionResult} result
|
92
|
+
* @returns {SubmissionResult}
|
93
|
+
*/
|
94
|
+
_preRenderResult(result) {
|
95
|
+
result.class_for_progress_list_item = mumuki.renderers.progressListItemClassForStatus(result.status, true)
|
96
|
+
return result;
|
97
|
+
}
|
98
|
+
}
|
93
99
|
|
94
|
-
|
100
|
+
return {
|
101
|
+
Laboratory
|
102
|
+
};
|
103
|
+
})();
|
@@ -1,12 +1,4 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
(function (mumuki) {
|
4
|
-
|
5
|
-
function CodeMirrorBuilder(textarea) {
|
6
|
-
this.textarea = textarea;
|
7
|
-
this.$textarea = $(textarea);
|
8
|
-
}
|
9
|
-
|
1
|
+
(() => {
|
10
2
|
function submit() {
|
11
3
|
$('body').removeClass('fullscreen');
|
12
4
|
$('.editor-resize .fa-stack-1x').removeClass('fa-compress').addClass('fa-expand');
|
@@ -29,8 +21,13 @@ var mumuki = mumuki || {};
|
|
29
21
|
autoRefresh: true
|
30
22
|
};
|
31
23
|
|
32
|
-
CodeMirrorBuilder
|
33
|
-
|
24
|
+
class CodeMirrorBuilder {
|
25
|
+
constructor(textarea) {
|
26
|
+
this.textarea = textarea;
|
27
|
+
this.$textarea = $(textarea);
|
28
|
+
}
|
29
|
+
|
30
|
+
setupEditor() {
|
34
31
|
this.editor = this.createEditor({
|
35
32
|
lineNumbers: true,
|
36
33
|
extraKeys: {
|
@@ -47,8 +44,9 @@ var mumuki = mumuki || {};
|
|
47
44
|
});
|
48
45
|
|
49
46
|
return this;
|
50
|
-
}
|
51
|
-
|
47
|
+
}
|
48
|
+
|
49
|
+
setupSimpleEditor() {
|
52
50
|
this.editor = this.createEditor({
|
53
51
|
mode: 'text',
|
54
52
|
extraKeys: {
|
@@ -61,8 +59,9 @@ var mumuki = mumuki || {};
|
|
61
59
|
});
|
62
60
|
|
63
61
|
return this;
|
64
|
-
}
|
65
|
-
|
62
|
+
}
|
63
|
+
|
64
|
+
setupReadOnlyEditor() {
|
66
65
|
this.editor = this.createEditor({
|
67
66
|
readOnly: true,
|
68
67
|
cursorBlinkRate: -1, //Hides the cursor
|
@@ -70,8 +69,9 @@ var mumuki = mumuki || {};
|
|
70
69
|
});
|
71
70
|
|
72
71
|
return this;
|
73
|
-
}
|
74
|
-
|
72
|
+
}
|
73
|
+
|
74
|
+
setupLanguage(language) {
|
75
75
|
var highlightMode = language || this.$textarea.data('editor-language');
|
76
76
|
if (highlightMode === 'dynamic') {
|
77
77
|
mumuki.page.dynamicEditors.push(this.editor);
|
@@ -81,20 +81,23 @@ var mumuki = mumuki || {};
|
|
81
81
|
}
|
82
82
|
|
83
83
|
return this;
|
84
|
-
}
|
85
|
-
|
84
|
+
}
|
85
|
+
|
86
|
+
setupMinLines(minLines) {
|
86
87
|
this.editor.setOption('minLines', minLines);
|
87
88
|
|
88
89
|
return this;
|
89
|
-
}
|
90
|
-
|
90
|
+
}
|
91
|
+
|
92
|
+
build() {
|
91
93
|
return this.editor;
|
92
|
-
}
|
93
|
-
|
94
|
+
}
|
95
|
+
|
96
|
+
createEditor(customOptions) {
|
94
97
|
return CodeMirror.fromTextArea(this.textarea, Object.assign({}, codeMirrorDefaults, customOptions));
|
95
98
|
}
|
96
|
-
}
|
99
|
+
}
|
97
100
|
|
98
101
|
mumuki.editor = mumuki.editor || {};
|
99
102
|
mumuki.editor.CodeMirrorBuilder = CodeMirrorBuilder;
|
100
|
-
}(
|
103
|
+
})();
|
@@ -1,6 +1,9 @@
|
|
1
|
-
|
1
|
+
mumuki.editor = mumuki.editor || {};
|
2
|
+
mumuki.page = mumuki.page || {};
|
3
|
+
mumuki.page.dynamicEditors = [];
|
4
|
+
mumuki.page.editors = [];
|
2
5
|
|
3
|
-
(
|
6
|
+
(() => {
|
4
7
|
function createCodeMirrors() {
|
5
8
|
return $(".editor").map(function (index, textarea) {
|
6
9
|
var $textarea = $("#solution_content");
|
@@ -68,21 +71,16 @@ var mumuki = mumuki || {};
|
|
68
71
|
});
|
69
72
|
}
|
70
73
|
|
71
|
-
mumuki.editor = mumuki.editor || {};
|
72
74
|
mumuki.editor.reset = resetEditor;
|
73
75
|
mumuki.editor.toggleFullscreen = toggleFullscreen;
|
74
76
|
mumuki.editor.formatContent = formatContent;
|
75
77
|
mumuki.editor.indentWithSpaces = indentWithSpaces;
|
76
78
|
mumuki.editor.syncContent = syncContent;
|
77
79
|
|
78
|
-
mumuki.page = mumuki.page || {};
|
79
|
-
mumuki.page.dynamicEditors = [];
|
80
|
-
mumuki.page.editors = [];
|
81
80
|
|
82
|
-
|
83
|
-
mumuki.load(function () {
|
81
|
+
mumuki.load(() => {
|
84
82
|
mumuki.page.editors = createCodeMirrors();
|
85
|
-
mumuki.
|
83
|
+
mumuki.editors.registerContentSyncer(mumuki.editor.syncContent);
|
86
84
|
updateCodeMirrorLanguage();
|
87
85
|
onSelectUpdateCodeMirror();
|
88
86
|
|
@@ -101,4 +99,4 @@ var mumuki = mumuki || {};
|
|
101
99
|
});
|
102
100
|
});
|
103
101
|
|
104
|
-
}(
|
102
|
+
})();
|