mumuki-laboratory 7.12.0 → 7.12.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f6139ebdb5d0f4a7148fb6fd64c07a2b7c28ea534fdafe4593cb185ab2b95371
4
- data.tar.gz: cea3b7ec16acc73e48a58a9257194a22ad5cf6c46e4dc0530d2b2a92c93dc0cd
3
+ metadata.gz: e025a36f6aa947e6a39b8372e2a0f257d473143a9c5bef32575885fcf375312b
4
+ data.tar.gz: 81428a5522e48781ed29cde5b8f2c219f3388a8d36e1ae466f91ee412e69b246
5
5
  SHA512:
6
- metadata.gz: 95b409773eb897492565a17980ae66cb30e8fbb341edc2034b83d01f117b1f6d6ac1a47c7367179cbf67c430b3c02208c2bda9e5dbc347cd19e3de91ee4d3543
7
- data.tar.gz: d58e05c853128d3d12b188160066231494945cc571704b588899f4bf61a88b69054d7c50ffca51478328a39110cc346f24008dbccdd907c22a197515a60987b9
6
+ metadata.gz: 374aec02893b3e31880b6bb3bbaf1031e0c2b567ee1b25b8d03bb7a30bda810aa72f5ff9974d70cab6637cede23a8e734e95ec5e9a1357d14772300e64a0fc6f
7
+ data.tar.gz: 70637e35aa57f98661f78f787a15e181ed4737d4b1d3080adcf06e90f4564e5cec9b642055106cccf6ae29fbaa90b1695367c7ac424c89b225166f80ab007557
@@ -9,8 +9,10 @@ mumuki.load(() => {
9
9
  });
10
10
 
11
11
  function placeKidsAnimations() {
12
+ placeAnimation('.mu-kids-character-result-aborted', 'failure');
12
13
  placeAnimation('.mu-kids-character-animation', 'blink');
13
14
  placeAnimation('.mu-kids-character-context', 'context');
15
+ placeAnimation('.mu-kids-character-result', 'blink');
14
16
  }
15
17
 
16
18
  function placeAnimation(selector, clip) {
@@ -20,7 +22,7 @@ mumuki.load(() => {
20
22
 
21
23
  function atRandom(array) {
22
24
  return array[Math.floor(Math.random() * array.length)];
23
- }
25
+ }
24
26
 
25
27
  mumuki.characters = characters;
26
28
  });
@@ -1,379 +1,205 @@
1
- mumuki.load(() => {
2
- let $bubble = $('.mu-kids-character-speech-bubble').children('.mu-kids-character-speech-bubble-normal');
3
-
4
- let availableTabs = ['.description', '.hint'];
5
- let $speechParagraphs, paragraphHeight, scrollHeight, nextSpeechBlinking;
6
- let currentParagraphIndex = 0;
7
- let paragraphCount = 1;
8
- let paragraphsLines = 2;
9
- let $prevSpeech = $('.mu-kids-character-speech-bubble-normal > .mu-kids-prev-speech').hide();
10
- let $nextSpeech = $('.mu-kids-character-speech-bubble-normal > .mu-kids-next-speech');
11
- let $speechTabs = $('.mu-kids-character-speech-bubble-tabs > li:not(.separator)');
12
- let $defaultSpeechTabName = 'description';
13
- let $texts = $bubble.children(availableTabs.join(", "));
14
- let $hint = $('.mu-kids-hint');
15
- let $description = $('.mu-kids-description');
16
- let discussionsLinkHtml = $('#mu-kids-discussion-link-html').html();
17
- let $kidsContext = $('#mu-kids-context');
18
- let contextModalButton = new mumuki.Button($('.mu-kids-context .modal-footer button'));
19
-
20
- // It is important that context is shown as early as possible
21
- // in order to display the loading animation
22
- function showContext() {
23
- $kidsContext.modal({
1
+ mumuki.Kids = class {
2
+
3
+ constructor() {
4
+ this.initialize();
5
+ this.showContext();
6
+ $(document).ready(this.onReady.bind(this));
7
+ }
8
+
9
+ // ================
10
+ // == Public API ==
11
+ // ================
12
+
13
+ initialize() {
14
+ this.submitButton = new mumuki.submission.SubmitButton($('#kids-btn-retry'), $('.submission_control'));
15
+ this.resultActions = {};
16
+ this.$states = $('.mu-kids-states');
17
+ this.$state = $('.mu-kids-state');
18
+ this.$blocks = $('.mu-kids-blocks');
19
+ this.$exercise = $('.mu-kids-exercise');
20
+ this.$exerciseDescription = $('.mu-kids-exercise-description');
21
+ this.$stateImage = $('.mu-kids-state-image');
22
+ this.$contextModal = $('#mu-kids-context');
23
+ this.$resultsModal = $('#kids-results');
24
+ this.$resultsAbortedModal = $('#kids-results-aborted');
25
+ this.$bubbleCharacterAnimation = $('.mu-kids-character-animation');
26
+ this.$submissionResult = $('.submission-results');
27
+ }
28
+
29
+ showContext() {
30
+ this.$contextModal.modal({
24
31
  backdrop: 'static',
25
32
  keyboard: false
26
33
  });
27
34
  }
28
35
 
29
- $kidsContext.on('hidden.bs.modal', function () {
30
- animateSpeech();
31
- });
32
-
33
- showContext();
34
-
35
- function floatFromPx(value) {
36
- return parseFloat(value.substring(0, value.length - 2));
36
+ showNonAbortedPopup(data, animation_name, open_modal_delay_ms = 0) {
37
+ this.$submissionResult.html(data.html);
38
+ mumuki.presenterCharacter.playAnimation(animation_name, $('.mu-kids-character-result'));
39
+ setTimeout(() => this._openSubmissionResultModal(data), open_modal_delay_ms);
40
+ this.onNonAbortedPopupCall(data);
37
41
  }
38
42
 
39
- function resizeSpeechParagraphs(paragraphIndex) {
40
- var previousParagraphCount = paragraphCount;
41
- scrollHeight = $bubble[0].scrollHeight;
42
- paragraphHeight = floatFromPx($speechParagraphs.css('line-height')) * paragraphsLines;
43
- paragraphCount = Math.ceil(scrollHeight / paragraphHeight);
44
- var newParagraphIndex = Math.floor((paragraphCount / previousParagraphCount) * currentParagraphIndex);
45
- showParagraph(paragraphIndex || newParagraphIndex);
43
+ showAbortedPopup(_data) {
44
+ this.submitButton.disable();
45
+ this.$resultsAbortedModal.modal();
46
46
  }
47
47
 
48
- function tabParagraphs(selector) {
49
- return $('.mu-kids-character-speech-bubble > .mu-kids-character-speech-bubble-normal > div' + selector + ' > p');
50
- }
48
+ // ==================
49
+ // == Hook Methods ==
50
+ // ==================
51
51
 
52
- function updateSpeechParagraphs() {
53
- $speechParagraphs = tabParagraphs('.' + getSelectedTabName());
54
- resizeSpeechParagraphs(0);
52
+ _showSuccessPopup() {
53
+ this._mustImplementThisMethod()
55
54
  }
56
55
 
57
- function getSelectedTabName() {
58
- return $speechTabs.filter(".active").data('target') || $defaultSpeechTabName;
56
+ _showFailurePopup() {
57
+ this._mustImplementThisMethod()
59
58
  }
60
59
 
61
- function showParagraph(index) {
62
- $bubble[0].scrollTop = index * paragraphHeight;
63
- currentParagraphIndex = index;
64
- checkArrowsSpeechVisibility();
65
- }
60
+ // ====================
61
+ // == Event Callback ==
62
+ // ====================
66
63
 
67
- function checkArrowsSpeechVisibility() {
68
- setVisibility($prevSpeech, currentParagraphIndex !== 0);
69
- setVisibility($nextSpeech, currentParagraphIndex !== paragraphCount - 1);
64
+ onReady() {
65
+ // SubClasses may override this method
70
66
  }
71
67
 
72
- function setVisibility(element, isVisible) {
73
- isVisible ? element.show() : element.hide();
68
+ onResize() {
69
+ // SubClasses may override this method
74
70
  }
75
71
 
76
- /**
77
- * Assigns propert widths to the states and blocks areas
78
- * depending on the presence and type of available states
79
- *
80
- * @param {*} $muKidsStateImage
81
- * @param {*} $muKidsStatesContainer
82
- * @param {*} $muKidsBlocks
83
- * @param {number} fullMargin
84
- */
85
- function distributeAreas($muKidsStateImage, $muKidsStatesContainer, $muKidsBlocks, fullMargin) {
86
- if ($muKidsStateImage.children().length) {
87
- var ratio = $muKidsStatesContainer.hasClass('mu-kids-single-state') ? 1 : 2;
88
- $muKidsStatesContainer.width($muKidsStatesContainer.height() / ratio * 1.25 - fullMargin);
89
- } else {
90
- $muKidsStatesContainer.width(0);
91
- $muKidsBlocks.width('100%');
92
- }
72
+ onNonAbortedPopupCall(_data) {
73
+ // SubClasses may override this method
93
74
  }
94
75
 
95
- mumuki.kids = {
96
-
97
- // ==========
98
- // Public API
99
- // ==========
100
-
101
- // Sets a function that will be called each
102
- // time the states need to be resized. The function takes:
103
- //
104
- // * $state: a single state area
105
- // * fullMargin
106
- // * preferredWidth
107
- // * preferredHeight
108
- //
109
- // Runners must call this method on within the runner's editor.js extension
110
- registerStateScaler: function (scaler) {
111
- this._stateScaler = scaler;
112
- },
113
-
114
- // Sets a function that will be called each
115
- // time the blocks area needs to be resized. The function takes:
116
- //
117
- // * $blocks: the blocks area
118
- //
119
- // Runners must call this method on within the runner's editor.js extension
120
- registerBlocksAreaScaler: function (scaler) {
121
- this._blocksAreaScaler = scaler;
122
- },
123
-
124
- // Scales a single state.
125
- //
126
- // This method is called by the kids code, but the runner's editor.js extension may need
127
- // to perform additional calls to it.
128
- scaleState: function ($state, fullMargin) {
129
- const preferredWidth = $state.width() - fullMargin * 2;
130
- const preferredHeight = $state.height() - fullMargin * 2;
131
- this._stateScaler($state, fullMargin, preferredWidth, preferredHeight);
132
- },
133
-
134
- // Scales the blocks area.
135
- //
136
- // This method is called by the kids code, but the runner's editor.js extension may need
137
- // to perform additional calls to it.
138
- scaleBlocksArea: function ($blocks) {
139
- this._blocksAreaScaler($blocks);
140
- },
141
-
142
- // Displays the kids results, updating the progress bar
143
- // firing the modal and running appropriate animations.
144
- //
145
- // This method needs to be called by the runner's editor.html extension
146
- // in order to finish an exercise
147
- showResult: function (data) {
148
- mumuki.updateProgressBarAndShowModal(data);
149
- if (data.guide_finished_by_solution) return;
150
- mumuki.kids.resultAction[data.status](data);
151
- },
152
-
153
- // Restarts the kids exercise.
154
- //
155
- // This method may need to be called by the runner's editor.html extension
156
- // in order to recover from a failed submission
157
- restart: function () {
158
- mumuki.kids._hideMessageOnCharacterBubble();
159
- var $bubble = mumuki.kids._getCharacterBubble();
160
- Object.keys(mumuki.kids.resultAction).forEach($bubble.removeClass.bind($bubble));
161
- mumuki.presenterCharacter.playAnimation('talk', mumuki.kids._getCharacterImage());
162
- },
163
-
164
- disableContextModalButton: function () {
165
- contextModalButton.setWaiting();
166
- },
167
-
168
- enableContextModalButton: function () {
169
- contextModalButton.enable();
170
- },
171
-
172
- showContext,
173
-
174
- // ===========
175
- // Private API
176
- // ===========
177
-
178
- _updateSubmissionResult: function (html) {
179
- return $('.submission-results').html(html);
180
- },
181
-
182
- _getResultsModal: function () {
183
- return $('#kids-results');
184
- },
185
-
186
- _getResultsAbortedModal: function () {
187
- return $('#kids-results-aborted');
188
- },
189
-
190
- _getCharacterImage: function () {
191
- return $('.mu-kids-character > img');
192
- },
193
-
194
- _getCharacterBubble: function () {
195
- return $('.mu-kids-character-speech-bubble');
196
- },
197
-
198
- _getOverlay: function () {
199
- return $('.mu-kids-overlay');
200
- },
201
-
202
- _hideMessageOnCharacterBubble: function () {
203
- var $bubble = mumuki.kids._getCharacterBubble();
204
- $bubble.find('.mu-kids-character-speech-bubble-tabs').show();
205
- $bubble.find('.mu-kids-character-speech-bubble-normal').show();
206
- $bubble.find('.mu-kids-character-speech-bubble-failed').hide();
207
- $bubble.find('.mu-kids-discussion-link').remove();
208
- Object.keys(mumuki.kids.resultAction).forEach($bubble.removeClass.bind($bubble));
209
- mumuki.kids._getOverlay().hide()
210
- },
211
-
212
- _showMessageOnCharacterBubble: function (data) {
213
- const renderer = new mumuki.renderers.SpeechBubbleRenderer(mumuki.kids._getCharacterBubble());
214
- renderer.setDiscussionsLinkHtml(discussionsLinkHtml);
215
- renderer.setResponseData(data);
216
- renderer.render();
217
- mumuki.kids._getOverlay().show();
218
- },
219
-
220
- _showOnSuccessPopup: function (data) {
221
- mumuki.kids._updateSubmissionResult(data.html);
222
- mumuki.presenterCharacter.playAnimation('success_l', mumuki.kids._getCharacterImage());
223
- mumuki.kids._showMessageOnCharacterBubble(data);
224
- mumuki.presenterCharacter.playAnimation('success2_l', $('.mu-kids-character-success'));
225
- setTimeout(function () {
226
- var $resultsKidsModal = mumuki.kids._getResultsModal();
227
- if ($resultsKidsModal) {
228
- $resultsKidsModal.modal({
229
- backdrop: 'static',
230
- keyboard: false
231
- });
232
- $resultsKidsModal.find('.modal-header').first().html(data.title_html);
233
- $resultsKidsModal.find('.modal-footer').first().html(data.button_html);
234
- mumuki.kids._showCorollaryCharacter();
235
- $('.mu-close-modal').click(() => mumuki.kids._getResultsModal().modal('hide'));
236
- }
237
- }, 1000 * 4);
238
- },
239
-
240
- _showOnFailurePopup: function () {
241
- mumuki.kids.submitButton.disable();
242
- mumuki.kids._getResultsAbortedModal().modal();
243
- mumuki.submission.animateTimeoutError(mumuki.kids.submitButton);
244
- },
245
-
246
- _showOnCharacterBubble: function (data) {
247
- mumuki.presenterCharacter.playAnimation('failure', mumuki.kids._getCharacterImage());
248
- mumuki.kids._showMessageOnCharacterBubble(data);
249
- },
250
-
251
- _showCorollaryCharacter: function () {
252
- mumuki.characters.magnifying_glass.playAnimation('show', $('.mu-kids-corollary-animation'));
253
- },
254
-
255
- _stateScaler: function ($state, fullMargin, preferredWidth, preferredHeight) {
256
- var $table = $state.find('gs-board > table');
257
- if (!$table.length) return setTimeout(() => this.scaleState($state, fullMargin));
258
-
259
- console.warn("You are using the default states scaler, which is gobstones-specific. Please register your own scaler in the future");
260
-
261
- $table.css('transform', 'scale(1)');
262
- var scaleX = preferredWidth / $table.width();
263
- var scaleY = preferredHeight / $table.height();
264
- $table.css('transform', 'scale(' + Math.min(scaleX, scaleY) + ')');
265
- },
266
-
267
- _blocksAreaScaler: function ($blocks) {
268
- console.warn("You are using the default blocks scaler, which is blockly-specific. Please register your own scaler in the future");
269
-
270
- var $blockArea = $blocks.find('#blocklyDiv');
271
- var $blockSvg = $blocks.find('.blocklySvg');
272
-
273
- $blockArea.width($blocks.width());
274
- $blockArea.height($blocks.height());
275
-
276
- $blockSvg.width($blocks.width());
277
- $blockSvg.height($blocks.height());
278
- },
279
-
280
- resultAction: {}
281
-
282
- };
283
-
284
- mumuki.kids.submitButton = new mumuki.submission.SubmitButton($('#kids-btn-retry'), $('.submission_control'));
285
-
286
- function showPrevParagraph() {
287
- animateSpeech();
288
- showParagraph(currentParagraphIndex - 1);
76
+ onSubmissionResultModalOpen(_data) {
77
+ // SubClasses may override this method
289
78
  }
290
79
 
291
- function showNextParagraph() {
292
- animateSpeech();
293
- showParagraph(currentParagraphIndex + 1);
294
- clearInterval(nextSpeechBlinking);
80
+ // =================
81
+ // == Private API ==
82
+ // =================
83
+
84
+ _openSubmissionResultModal(data) {
85
+ this.$resultsModal.modal({ backdrop: 'static', keyboard: false })
86
+ this.$resultsModal.find('.modal-header').first().html(data.title_html)
87
+ this.$resultsModal.find('.modal-footer').first().html(data.button_html)
88
+ $('.mu-close-modal').click(() => this.$resultsModal.modal('hide'));
89
+ this.onSubmissionResultModalOpen(data);
295
90
  }
296
91
 
297
- function animateSpeech() {
298
- mumuki.presenterCharacter.playAnimation('talk', mumuki.kids._getCharacterImage());
92
+ // ==========================
93
+ // == Called by the runner ==
94
+ // ==========================
95
+
96
+ // Displays the exercise results, updating the progress bar
97
+ // firing the modal and running appropriate animations.
98
+ //
99
+ // This method needs to be called by the runner's editor.html extension
100
+ // in order to finish an exercise
101
+ showResult(data) {
102
+ mumuki.progress.updateProgressBarAndShowModal(data);
103
+ if (data.guide_finished_by_solution) return;
104
+ this.resultActions[data.status](data);
299
105
  }
300
106
 
301
- function animateHint() {
302
- mumuki.presenterCharacter.playAnimation('hint', mumuki.kids._getCharacterImage());
107
+ // Restarts the kids exercise.
108
+ //
109
+ // This method may need to be called by the runner's editor.html extension
110
+ // in order to recover from a failed submission
111
+ restart() {
112
+ this._mustImplementThisMethod();
303
113
  }
304
114
 
305
- mumuki.kids.resultAction.passed = mumuki.kids._showOnSuccessPopup;
306
- mumuki.kids.resultAction.passed_with_warnings = mumuki.kids._showOnCharacterBubble;
115
+ // =================================
116
+ // == Called by the assets loader ==
117
+ // =================================
307
118
 
308
- mumuki.kids.resultAction.aborted = mumuki.kids._showOnFailurePopup;
119
+ disableContextModalButton() {
120
+ this.$contextModalButton.setWaiting();
121
+ }
309
122
 
310
- mumuki.kids.resultAction.failed = mumuki.kids._showOnCharacterBubble;
311
- mumuki.kids.resultAction.errored = mumuki.kids._showOnCharacterBubble;
312
- mumuki.kids.resultAction.pending = mumuki.kids._showOnCharacterBubble;
123
+ enableContextModalButton() {
124
+ this.$contextModalButton.enable();
125
+ }
313
126
 
127
+ // ============
128
+ // == Helper ==
129
+ // ============
314
130
 
315
- $(document).ready(() => {
316
- // Speech initialization
317
- if (!$bubble.length) return;
131
+ _mustImplementThisMethod() {
132
+ throw new Error('TODO: implement method')
133
+ }
318
134
 
319
- availableTabs.forEach(function (tabSelector) {
320
- tabParagraphs(tabSelector).contents().unwrap().wrapAll('<p>');
321
- });
135
+ // ============
136
+ // == Scaler ==
137
+ // ============
138
+
139
+ // Sets a function that will be called each
140
+ // time the states need to be resized. The function takes:
141
+ //
142
+ // * $state: a single state area
143
+ // * fullMargin
144
+ // * preferredWidth
145
+ // * preferredHeight
146
+ //
147
+ // Runners must call this method on within the runner's editor.js extension
148
+ registerStateScaler(scaler) {
149
+ this._stateScaler = scaler;
150
+ }
322
151
 
323
- updateSpeechParagraphs();
324
-
325
- resizeSpeechParagraphs();
326
-
327
- $speechTabs.each(function (i) {
328
- var $tab = $($speechTabs[i]);
329
- if ($tab.data('target')) {
330
- $tab.click(function () {
331
- $speechTabs.removeClass('active');
332
- $tab.addClass('active');
333
- $texts.hide();
334
- $bubble.children('.' + $tab.data('target')).show();
335
- updateSpeechParagraphs();
336
- })
337
- }
338
- });
152
+ // Sets a function that will be called each
153
+ // time the blocks area needs to be resized. The function takes:
154
+ //
155
+ // * $blocks: the blocks area
156
+ //
157
+ // Runners must call this method on within the runner's editor.js extension
158
+ registerBlocksAreaScaler(scaler) {
159
+ this._blocksAreaScaler = scaler;
160
+ }
339
161
 
340
- if (paragraphCount > 1) {
341
- nextSpeechBlinking = mumuki.setInterval(() => $nextSpeech.fadeTo('slow', 0.1).fadeTo('slow', 1.0), 1000);
342
- }
162
+ // Scales a single state.
163
+ //
164
+ // This method is called by the kids code, but the runner's editor.js extension may need
165
+ // to perform additional calls to it.
166
+ scaleState($state, fullMargin) {
167
+ const preferredWidth = $state.width() - fullMargin * 2;
168
+ const preferredHeight = $state.height() - fullMargin * 2;
169
+ this._stateScaler($state, fullMargin, preferredWidth, preferredHeight);
170
+ }
343
171
 
344
- $nextSpeech.click(showNextParagraph);
345
- $prevSpeech.click(showPrevParagraph);
346
- $description.click(animateSpeech);
172
+ // Scales the blocks area.
173
+ //
174
+ // This method is called by the kids code, but the runner's editor.js extension may need
175
+ // to perform additional calls to it.
176
+ scaleBlocksArea($blocks) {
177
+ this._blocksAreaScaler($blocks);
178
+ }
347
179
 
348
- $hint.click(function () {
349
- animateHint();
350
- this.classList.remove('blink');
351
- });
180
+ _stateScaler($state, fullMargin, preferredWidth, preferredHeight) {
181
+ const $table = $state.find('gs-board > table');
182
+ if (!$table.length) return setTimeout(() => this.scaleState($state, fullMargin));
352
183
 
353
- // States initial resizing
354
- mumuki.resize(function () {
355
- var margin = 15;
356
- var fullMargin = margin * 2;
184
+ console.warn("You are using the default states scaler, which is gobstones-specific. Please register your own scaler in the future");
357
185
 
358
- let $muKidsStatesContainer = $('.mu-kids-states');
359
- let $muKidsStates = $('.mu-kids-state');
360
- let $muKidsBlocks = $('.mu-kids-blocks');
361
- let $muKidsExercise = $('.mu-kids-exercise');
362
- let $muKidsExerciseDescription = $('.mu-kids-exercise-description');
363
- let $muKidsStateImage = $('.mu-kids-state-image');
186
+ $table.css('transform', 'scale(1)');
187
+ const scaleX = preferredWidth / $table.width();
188
+ const scaleY = preferredHeight / $table.height();
189
+ $table.css('transform', 'scale(' + Math.min(scaleX, scaleY) + ')');
190
+ }
364
191
 
365
- distributeAreas($muKidsStateImage, $muKidsStatesContainer, $muKidsBlocks, fullMargin);
192
+ _blocksAreaScaler($blocks) {
193
+ console.warn("You are using the default blocks scaler, which is blockly-specific. Please register your own scaler in the future");
366
194
 
367
- if (!$muKidsExerciseDescription.hasClass('mu-kids-exercise-description-fixed')) {
368
- $muKidsExerciseDescription.width($muKidsExercise.width() - $muKidsStatesContainer.width() - margin);
369
- }
195
+ const $blockArea = $blocks.find('#blocklyDiv');
196
+ const $blockSvg = $blocks.find('.blocklySvg');
370
197
 
371
- $muKidsStates.each((index, state) => mumuki.kids.scaleState($(state), fullMargin));
372
- mumuki.kids.scaleBlocksArea($muKidsBlocks);
198
+ $blockArea.width($blocks.width());
199
+ $blockArea.height($blocks.height());
373
200
 
374
- if (paragraphCount <= 1) clearInterval(nextSpeechBlinking);
201
+ $blockSvg.width($blocks.width());
202
+ $blockSvg.height($blocks.height());
203
+ }
375
204
 
376
- resizeSpeechParagraphs();
377
- });
378
- })
379
- });
205
+ }