xblocks-core 2.0.0__py3-none-any.whl

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.
Files changed (261) hide show
  1. xblock_annotatable/.tx/config +8 -0
  2. xblock_annotatable/__init__.py +5 -0
  3. xblock_annotatable/block.py +307 -0
  4. xblock_annotatable/conf/locale/__init__.py +0 -0
  5. xblock_annotatable/conf/locale/config.yaml +93 -0
  6. xblock_annotatable/static/css/annotatable.css +188 -0
  7. xblock_annotatable/static/css/annotatable_editor.css +12 -0
  8. xblock_annotatable/static/js/src/annotatable.js +367 -0
  9. xblock_annotatable/static/js/src/annotatable_editor.js +74 -0
  10. xblock_annotatable/templates/annotatable.html +24 -0
  11. xblock_annotatable/templates/annotatable_editor.html +20 -0
  12. xblock_discussion/.tx/config +8 -0
  13. xblock_discussion/__init__.py +5 -0
  14. xblock_discussion/apps.py +53 -0
  15. xblock_discussion/block.py +265 -0
  16. xblock_discussion/conf/locale/__init__.py +0 -0
  17. xblock_discussion/conf/locale/config.yaml +93 -0
  18. xblock_discussion/public/css/inline-discussion-rtl.css +4572 -0
  19. xblock_discussion/public/css/inline-discussion.css +4572 -0
  20. xblock_discussion/public/js/discussion_bundle.js +2 -0
  21. xblock_discussion/templates/_discussion_inline_studio.html +16 -0
  22. xblock_discussion/templates/discussion_templates/_discussion_inline.html +49 -0
  23. xblock_discussion/templates/discussion_templates/_thread_list_template.html +55 -0
  24. xblock_discussion/templates/discussion_templates/_underscore_templates.html +19 -0
  25. xblock_discussion/templates/discussion_templates/templates.underscore +889 -0
  26. xblock_html/.tx/config +8 -0
  27. xblock_html/__init__.py +6 -0
  28. xblock_html/block.py +498 -0
  29. xblock_html/conf/locale/__init__.py +0 -0
  30. xblock_html/conf/locale/config.yaml +93 -0
  31. xblock_html/static/css/html.css +297 -0
  32. xblock_html/templates/html/announcement.yaml +18 -0
  33. xblock_html/templates/html/anon_user_id.yaml +19 -0
  34. xblock_html/templates/html/iframe.yaml +32 -0
  35. xblock_html/templates/html/raw.yaml +9 -0
  36. xblock_html/templates/html/zooming_image.yaml +239 -0
  37. xblock_lti/.tx/config +8 -0
  38. xblock_lti/__init__.py +7 -0
  39. xblock_lti/block.py +1018 -0
  40. xblock_lti/conf/locale/__init__.py +0 -0
  41. xblock_lti/conf/locale/config.yaml +93 -0
  42. xblock_lti/lti_2_util.py +388 -0
  43. xblock_lti/static/css/lti.css +57 -0
  44. xblock_lti/static/js/src/lti.js +23 -0
  45. xblock_lti/templates/lti.html +73 -0
  46. xblock_lti/templates/lti_form.html +38 -0
  47. xblock_pdf/__init__.py +3 -0
  48. xblock_pdf/block.py +129 -0
  49. xblock_pdf/js_tests/jquery.d.ts +5 -0
  50. xblock_pdf/js_tests/specs/helpers/loadAsElement.js +1 -0
  51. xblock_pdf/js_tests/specs/helpers/loadAsJQuery.js +1 -0
  52. xblock_pdf/js_tests/specs/helpers/mockRuntime.js +23 -0
  53. xblock_pdf/js_tests/specs/helpers/proveJQuery.js +12 -0
  54. xblock_pdf/js_tests/tsconfig.json +10 -0
  55. xblock_pdf/js_tests/vitest.config.ts +15 -0
  56. xblock_pdf/static/js/pdf.js +17 -0
  57. xblock_pdf/templates/html/pdf.html +22 -0
  58. xblock_pdf/utils.py +13 -0
  59. xblock_poll_question/.tx/config +8 -0
  60. xblock_poll_question/__init__.py +5 -0
  61. xblock_poll_question/block.py +311 -0
  62. xblock_poll_question/conf/locale/__init__.py +0 -0
  63. xblock_poll_question/conf/locale/config.yaml +93 -0
  64. xblock_poll_question/static/css/poll.css +356 -0
  65. xblock_poll_question/static/js/src/poll.js +196 -0
  66. xblock_poll_question/templates/poll.html +7 -0
  67. xblock_problem/.tx/config +8 -0
  68. xblock_problem/__init__.py +5 -0
  69. xblock_problem/block.py +2728 -0
  70. xblock_problem/capa/__init__.py +0 -0
  71. xblock_problem/capa/apps.py +54 -0
  72. xblock_problem/capa/capa_problem.py +1241 -0
  73. xblock_problem/capa/checker.py +174 -0
  74. xblock_problem/capa/correctmap.py +217 -0
  75. xblock_problem/capa/customrender.py +195 -0
  76. xblock_problem/capa/errors.py +62 -0
  77. xblock_problem/capa/inputtypes.py +1819 -0
  78. xblock_problem/capa/registry.py +57 -0
  79. xblock_problem/capa/responsetypes.py +3867 -0
  80. xblock_problem/capa/safe_exec/README.rst +43 -0
  81. xblock_problem/capa/safe_exec/__init__.py +4 -0
  82. xblock_problem/capa/safe_exec/exceptions.py +21 -0
  83. xblock_problem/capa/safe_exec/lazymod.py +43 -0
  84. xblock_problem/capa/safe_exec/remote_exec.py +142 -0
  85. xblock_problem/capa/safe_exec/safe_exec.py +506 -0
  86. xblock_problem/capa/static/applets/Protex.jar +0 -0
  87. xblock_problem/capa/static/applets/genex.jar +0 -0
  88. xblock_problem/capa/static/images/vsepr/AX2E0-3D-balls.png +0 -0
  89. xblock_problem/capa/static/images/vsepr/AX2E1-3D-balls.png +0 -0
  90. xblock_problem/capa/static/images/vsepr/AX2E2-3D-balls.png +0 -0
  91. xblock_problem/capa/static/images/vsepr/AX2E3-3D-balls.png +0 -0
  92. xblock_problem/capa/static/images/vsepr/AX3E0-3D-balls.png +0 -0
  93. xblock_problem/capa/static/images/vsepr/AX3E1-3D-balls.png +0 -0
  94. xblock_problem/capa/static/images/vsepr/AX3E2-3D-balls.png +0 -0
  95. xblock_problem/capa/static/images/vsepr/AX4E0-3D-balls.png +0 -0
  96. xblock_problem/capa/static/images/vsepr/AX4E1-3D-balls.png +0 -0
  97. xblock_problem/capa/static/images/vsepr/AX4E2-3D-balls.png +0 -0
  98. xblock_problem/capa/static/images/vsepr/AX5E1-3D-balls.png +0 -0
  99. xblock_problem/capa/static/images/vsepr/AX5E2-3D-balls.png +0 -0
  100. xblock_problem/capa/static/images/vsepr/AX6E0-3D-balls.png +0 -0
  101. xblock_problem/capa/static/images/vsepr/AX6E1-3D-balls.png +0 -0
  102. xblock_problem/capa/static/images/vsepr/AX7E0-3D-balls.png +0 -0
  103. xblock_problem/capa/static/images/vsepr/AX8E0-3D-balls.png +0 -0
  104. xblock_problem/capa/static/images/vsepr/AX9E0-3D-balls.png +0 -0
  105. xblock_problem/capa/static/images/vsepr/Bent-3D-balls.png +0 -0
  106. xblock_problem/capa/static/images/vsepr/Linear-3D-balls.png +0 -0
  107. xblock_problem/capa/static/images/vsepr/Linear-stick.png +0 -0
  108. xblock_problem/capa/static/images/vsepr/Octahedral-3D-balls.png +0 -0
  109. xblock_problem/capa/static/images/vsepr/Octahedral-stick.png +0 -0
  110. xblock_problem/capa/static/images/vsepr/Pentagonal-bipyramidal-3D-balls.png +0 -0
  111. xblock_problem/capa/static/images/vsepr/Pentagonal-planar-3D-balls.png +0 -0
  112. xblock_problem/capa/static/images/vsepr/Pentagonal-pyramidal-3D-balls.png +0 -0
  113. xblock_problem/capa/static/images/vsepr/Pyramidal-3D-balls.png +0 -0
  114. xblock_problem/capa/static/images/vsepr/Seesaw-3D-balls.png +0 -0
  115. xblock_problem/capa/static/images/vsepr/Square-antiprismatic-3D-balls.png +0 -0
  116. xblock_problem/capa/static/images/vsepr/Square-planar-3D-balls.png +0 -0
  117. xblock_problem/capa/static/images/vsepr/T-shaped-3D-balls.png +0 -0
  118. xblock_problem/capa/static/images/vsepr/Tetrahedral-3D-balls.png +0 -0
  119. xblock_problem/capa/static/images/vsepr/Tetrahedral-stick.png +0 -0
  120. xblock_problem/capa/static/images/vsepr/Trigonal-3D-balls.png +0 -0
  121. xblock_problem/capa/static/images/vsepr/Trigonal-bipyramidal-3D-balls.png +0 -0
  122. xblock_problem/capa/static/images/vsepr/Trigonal-bipyramidal-stick.png +0 -0
  123. xblock_problem/capa/static/images/vsepr/Trigonal-planar-stick.png +0 -0
  124. xblock_problem/capa/static/js/capa/README +1 -0
  125. xblock_problem/capa/static/js/capa/annotationinput.js +98 -0
  126. xblock_problem/capa/static/js/capa/chemical_equation_preview.js +36 -0
  127. xblock_problem/capa/static/js/capa/choicetextinput.js +73 -0
  128. xblock_problem/capa/static/js/capa/design-protein-2d.js +85 -0
  129. xblock_problem/capa/static/js/capa/drag_and_drop/base_image.js +45 -0
  130. xblock_problem/capa/static/js/capa/drag_and_drop/config_parser.js +271 -0
  131. xblock_problem/capa/static/js/capa/drag_and_drop/container.js +13 -0
  132. xblock_problem/capa/static/js/capa/drag_and_drop/draggable_events.js +143 -0
  133. xblock_problem/capa/static/js/capa/drag_and_drop/draggable_logic.js +400 -0
  134. xblock_problem/capa/static/js/capa/drag_and_drop/draggables.js +281 -0
  135. xblock_problem/capa/static/js/capa/drag_and_drop/main.js +107 -0
  136. xblock_problem/capa/static/js/capa/drag_and_drop/scroller.js +162 -0
  137. xblock_problem/capa/static/js/capa/drag_and_drop/state.js +95 -0
  138. xblock_problem/capa/static/js/capa/drag_and_drop/targets.js +266 -0
  139. xblock_problem/capa/static/js/capa/drag_and_drop/update_input.js +373 -0
  140. xblock_problem/capa/static/js/capa/drag_and_drop.js +25 -0
  141. xblock_problem/capa/static/js/capa/edit-a-gene.js +71 -0
  142. xblock_problem/capa/static/js/capa/genex/21B31BA00E7CE7B6BD63DD13A8586A45.cache.html +652 -0
  143. xblock_problem/capa/static/js/capa/genex/63308EE54E8033A708B414CAC05B0C32.cache.html +642 -0
  144. xblock_problem/capa/static/js/capa/genex/7AC57DC6EC8C1D8672DDF6E6D4EF57CC.cache.html +628 -0
  145. xblock_problem/capa/static/js/capa/genex/9B4F4D4EFA24CDE2E4287CC07897F249.cache.html +654 -0
  146. xblock_problem/capa/static/js/capa/genex/A069AC107D79C29D6237614AC340F0C0.cache.html +652 -0
  147. xblock_problem/capa/static/js/capa/genex/C6220FCC8B9234FEAD8D826A73C6D2A4.cache.html +642 -0
  148. xblock_problem/capa/static/js/capa/genex/clear.cache.gif +0 -0
  149. xblock_problem/capa/static/js/capa/genex/genex.css +122 -0
  150. xblock_problem/capa/static/js/capa/genex/genex.nocache.js +18 -0
  151. xblock_problem/capa/static/js/capa/genex/hosted.html +365 -0
  152. xblock_problem/capa/static/js/capa/genex/images/circles.png +0 -0
  153. xblock_problem/capa/static/js/capa/genex/images/circles_ie6.png +0 -0
  154. xblock_problem/capa/static/js/capa/genex/images/corner.png +0 -0
  155. xblock_problem/capa/static/js/capa/genex/images/corner_ie6.png +0 -0
  156. xblock_problem/capa/static/js/capa/genex/images/hborder.png +0 -0
  157. xblock_problem/capa/static/js/capa/genex/images/hborder_ie6.png +0 -0
  158. xblock_problem/capa/static/js/capa/genex/images/thumb_horz.png +0 -0
  159. xblock_problem/capa/static/js/capa/genex/images/thumb_vertical.png +0 -0
  160. xblock_problem/capa/static/js/capa/genex/images/vborder.png +0 -0
  161. xblock_problem/capa/static/js/capa/genex/images/vborder_ie6.png +0 -0
  162. xblock_problem/capa/static/js/capa/jsinput/jsinput_example.css +9 -0
  163. xblock_problem/capa/static/js/capa/jsinput/jsinput_example.html +15 -0
  164. xblock_problem/capa/static/js/capa/jsinput/jsinput_example.js +86 -0
  165. xblock_problem/capa/static/js/capa/protex/39CC89519B0E1FCB47B935AC9FE13D7B.cache.html +743 -0
  166. xblock_problem/capa/static/js/capa/protex/6E05B1CD5BFCAF7D53C7C64D84318178.cache.html +750 -0
  167. xblock_problem/capa/static/js/capa/protex/C824A958AB642DC2213DFFDAC640BEAA.cache.html +760 -0
  168. xblock_problem/capa/static/js/capa/protex/D9267DE8FB02F8B995B4A58C66C76E29.cache.html +758 -0
  169. xblock_problem/capa/static/js/capa/protex/F275492F7098103BCB05F4F86ABF6218.cache.html +750 -0
  170. xblock_problem/capa/static/js/capa/protex/F3301B0E65F38C7FCF2EF3764B3BB0B6.cache.html +754 -0
  171. xblock_problem/capa/static/js/capa/protex/clear.cache.gif +0 -0
  172. xblock_problem/capa/static/js/capa/protex/hosted.html +365 -0
  173. xblock_problem/capa/static/js/capa/protex/protex.css +57 -0
  174. xblock_problem/capa/static/js/capa/protex/protex.nocache.js +18 -0
  175. xblock_problem/capa/static/js/capa/protex/scrollTableLoading.gif +0 -0
  176. xblock_problem/capa/static/js/capa/schematicinput.js +49 -0
  177. xblock_problem/capa/static/js/capa/src/formula_equation_preview.js +221 -0
  178. xblock_problem/capa/static/js/capa/src/jschannel.js +790 -0
  179. xblock_problem/capa/static/js/capa/src/jsinput.js +221 -0
  180. xblock_problem/capa/static/js/capa/symbolic_mathjax_preprocessor.js +35 -0
  181. xblock_problem/capa/static/js/vendor/CodeMirror/octave.js +118 -0
  182. xblock_problem/capa/templates/annotationinput.html +61 -0
  183. xblock_problem/capa/templates/chemicalequationinput.html +19 -0
  184. xblock_problem/capa/templates/choicegroup.html +41 -0
  185. xblock_problem/capa/templates/choicetext.html +61 -0
  186. xblock_problem/capa/templates/clarification.html +10 -0
  187. xblock_problem/capa/templates/codeinput.html +31 -0
  188. xblock_problem/capa/templates/crystallography.html +29 -0
  189. xblock_problem/capa/templates/designprotein2dinput.html +25 -0
  190. xblock_problem/capa/templates/drag_and_drop_input.html +27 -0
  191. xblock_problem/capa/templates/editageneinput.html +32 -0
  192. xblock_problem/capa/templates/editamolecule.html +32 -0
  193. xblock_problem/capa/templates/filesubmission.html +16 -0
  194. xblock_problem/capa/templates/formulaequationinput.html +29 -0
  195. xblock_problem/capa/templates/imageinput.html +33 -0
  196. xblock_problem/capa/templates/jsinput.html +42 -0
  197. xblock_problem/capa/templates/mathstring.html +8 -0
  198. xblock_problem/capa/templates/matlabinput.html +121 -0
  199. xblock_problem/capa/templates/optioninput.html +20 -0
  200. xblock_problem/capa/templates/problem.html +154 -0
  201. xblock_problem/capa/templates/problem_ajax.html +16 -0
  202. xblock_problem/capa/templates/problem_notifications.html +19 -0
  203. xblock_problem/capa/templates/schematicinput.html +18 -0
  204. xblock_problem/capa/templates/solutionspan.html +3 -0
  205. xblock_problem/capa/templates/status_span.html +12 -0
  206. xblock_problem/capa/templates/textline.html +39 -0
  207. xblock_problem/capa/templates/vsepr_input.html +38 -0
  208. xblock_problem/capa/testing/__init__.py +7 -0
  209. xblock_problem/capa/testing/codejail.py +31 -0
  210. xblock_problem/capa/testing/response_xml_factory.py +934 -0
  211. xblock_problem/capa/util.py +252 -0
  212. xblock_problem/capa/xqueue_interface.py +185 -0
  213. xblock_problem/capa/xqueue_submission.py +111 -0
  214. xblock_problem/conf/locale/__init__.py +0 -0
  215. xblock_problem/conf/locale/config.yaml +93 -0
  216. xblock_problem/markup.py +33 -0
  217. xblock_problem/public/css/ProblemBlockDisplay.css +2306 -0
  218. xblock_problem/public/js/ProblemBlockDisplay.js +1 -0
  219. xblock_problem/stringify.py +33 -0
  220. xblock_problem/xmlparser.py +146 -0
  221. xblock_video/.tx/config +8 -0
  222. xblock_video/__init__.py +5 -0
  223. xblock_video/ajax_handler_mixin.py +52 -0
  224. xblock_video/block.py +1184 -0
  225. xblock_video/bumper_utils.py +147 -0
  226. xblock_video/cache_utils.py +97 -0
  227. xblock_video/conf/locale/__init__.py +0 -0
  228. xblock_video/conf/locale/config.yaml +93 -0
  229. xblock_video/constants.py +17 -0
  230. xblock_video/exceptions.py +11 -0
  231. xblock_video/mixin.py +58 -0
  232. xblock_video/public/css/video.css +1260 -0
  233. xblock_video/public/js/video-xblock.js +2 -0
  234. xblock_video/studio_metadata_mixin.py +166 -0
  235. xblock_video/templates/video.html +213 -0
  236. xblock_video/validation.py +129 -0
  237. xblock_video/video_handlers.py +514 -0
  238. xblock_video/video_static_content_utils.py +49 -0
  239. xblock_video/video_transcripts_utils.py +236 -0
  240. xblock_video/video_utils.py +178 -0
  241. xblock_video/video_xfields.py +229 -0
  242. xblock_word_cloud/.tx/config +8 -0
  243. xblock_word_cloud/__init__.py +3 -0
  244. xblock_word_cloud/block.py +295 -0
  245. xblock_word_cloud/conf/locale/__init__.py +0 -0
  246. xblock_word_cloud/conf/locale/config.yaml +93 -0
  247. xblock_word_cloud/static/css/word_cloud.css +29 -0
  248. xblock_word_cloud/static/js/src/d3.layout.cloud.js +434 -0
  249. xblock_word_cloud/static/js/src/d3.min.js +37 -0
  250. xblock_word_cloud/static/js/src/html_utils.js +75 -0
  251. xblock_word_cloud/static/js/src/word_cloud.js +289 -0
  252. xblock_word_cloud/templates/word_cloud.html +50 -0
  253. xblocks_core/__init__.py +11 -0
  254. xblocks_core/legacy_utils/__init__.py +6 -0
  255. xblocks_core/legacy_utils/xml_utils.py +584 -0
  256. xblocks_core-2.0.0.dist-info/METADATA +366 -0
  257. xblocks_core-2.0.0.dist-info/RECORD +261 -0
  258. xblocks_core-2.0.0.dist-info/WHEEL +5 -0
  259. xblocks_core-2.0.0.dist-info/entry_points.txt +18 -0
  260. xblocks_core-2.0.0.dist-info/licenses/LICENSE.txt +664 -0
  261. xblocks_core-2.0.0.dist-info/top_level.txt +10 -0
@@ -0,0 +1,367 @@
1
+ function Annotatable(runtime, element) {
2
+ var _debug = false;
3
+
4
+ /*
5
+ Selectors for the annotatable xmodule
6
+ */
7
+ var wrapperSelector = '.annotatable-wrapper';
8
+ var toggleAnnotationsSelector = '.annotatable-toggle-annotations';
9
+ var toggleInstructionsSelector = '.annotatable-toggle-instructions';
10
+ var instructionsSelector = '.annotatable-instructions';
11
+ var spanSelector = '.annotatable-span';
12
+ var replySelector = '.annotatable-reply';
13
+
14
+ /*
15
+ Selectors for responding to events from the annotation capa problem type
16
+ */
17
+ var problemInputSelector = 'div.problem .annotation-input';
18
+ var problemReturnSelector = 'div.problem .annotation-return';
19
+
20
+ var annotationsHidden = false;
21
+ var instructionsHidden = false;
22
+
23
+ var $el = $(element);
24
+
25
+ init();
26
+
27
+ function init() {
28
+ initEvents();
29
+ initTips();
30
+ if (_debug) {
31
+ console.log('Annotatable XBlock Loaded');
32
+ }
33
+ }
34
+
35
+ function initEvents() {
36
+ annotationsHidden = false;
37
+ instructionsHidden = false;
38
+
39
+ /*
40
+ Initialize toggle handlers for the instructions and annotations sections
41
+ */
42
+ $(toggleAnnotationsSelector).on('click', onClickToggleAnnotations);
43
+ $(toggleInstructionsSelector).on('click', onClickToggleInstructions);
44
+
45
+ /*
46
+ Initialize handler for 'reply to annotation' events that scroll to
47
+ the associated problem. The reply buttons are part of the tooltip
48
+ content. It's important that the tooltips be configured to render
49
+ as descendants of the annotation module and *not* the document.body.
50
+ */
51
+ $el.on('click', replySelector, onClickReply);
52
+
53
+ /*
54
+ Initialize handler for 'return to annotation' events triggered from problems.
55
+ 1) There are annotationinput capa problems rendered on the page
56
+ 2) Each one has an embedded return link (see annotation capa problem template).
57
+ Since the capa problem injects HTML content via AJAX, the best we can do is
58
+ let the click events bubble up to the body and handle them there.
59
+ */
60
+ $(document).on('click', problemReturnSelector, onClickReturn);
61
+ }
62
+
63
+ function initTips() {
64
+ /*
65
+ Tooltips are used to display annotations for highlighted text spans
66
+ */
67
+ $(spanSelector).each(function(index, el) {
68
+ $(el).qtip(getSpanTipOptions(el));
69
+ });
70
+ }
71
+
72
+ function getSpanTipOptions(el) {
73
+ return {
74
+ content: {
75
+ title: {
76
+ text: makeTipTitle(el),
77
+ },
78
+ text: makeTipContent(el),
79
+ },
80
+ position: {
81
+ /*
82
+ Of tooltip
83
+ */
84
+ my: 'bottom center',
85
+ /*
86
+ Of target
87
+ */
88
+ at: 'top center',
89
+ /*
90
+ Where the tooltip was triggered (i.e., the annotation span)
91
+ */
92
+ target: $(el),
93
+ container: $(wrapperSelector),
94
+ adjust: {
95
+ y: -5,
96
+ },
97
+ },
98
+ show: {
99
+ event: 'click mouseenter',
100
+ solo: true,
101
+ },
102
+ hide: {
103
+ event: 'click mouseleave',
104
+ delay: 500,
105
+ /*
106
+ Don't hide the tooltip if it is moused over
107
+ */
108
+ fixed: true,
109
+ },
110
+ style: {
111
+ classes: 'ui-tooltip-annotatable',
112
+ },
113
+ events: {
114
+ show: onShowTip,
115
+ move: onMoveTip,
116
+ },
117
+ };
118
+ }
119
+
120
+ function onClickToggleAnnotations(e) {
121
+ toggleAnnotations();
122
+ }
123
+
124
+ function onClickToggleInstructions(e) {
125
+ toggleInstructions();
126
+ }
127
+
128
+ function onClickReply(e) {
129
+ replyTo(e.currentTarget);
130
+ }
131
+
132
+ function onClickReturn(e) {
133
+ returnFrom(e.currentTarget);
134
+ }
135
+
136
+ function onShowTip(event, api) {
137
+ if (annotationsHidden) {
138
+ event.preventDefault();
139
+ }
140
+ }
141
+
142
+ function onMoveTip(event, api, position) {
143
+ /*
144
+ This method handles a vertical positioning bug in Firefox as
145
+ well as an edge case in which a tooltip is displayed above a
146
+ non-overlapping span like this:
147
+
148
+ (( TOOLTIP ))
149
+ \/
150
+ text text text ... text text text ...... <span span span>
151
+ <span span span>
152
+
153
+ The problem is that the tooltip looks disconnected from both spans, so
154
+ we should re-position the tooltip to appear above the span.
155
+ */
156
+ var tip = api.elements.tooltip;
157
+ var adjustY = (api.options.position && api.options.position.adjust && api.options.position.adjust.y) || 0;
158
+ var container = (api.options.position && api.options.position.container) || $('body');
159
+ var target = api.elements.target;
160
+ var rects = $(target).get(0).getClientRects();
161
+ var isNonOverlapping = rects && rects.length === 2 && rects[0].left > rects[1].right;
162
+ var focusRect;
163
+
164
+ if (isNonOverlapping) {
165
+ /*
166
+ Choose the largest of the two non-overlapping spans and display
167
+ the tooltip above the center of it
168
+ */
169
+ focusRect = rects[0].width > rects[1].width ? rects[0] : rects[1];
170
+ } else {
171
+ /*
172
+ Always compute the new position because Firefox doesn't
173
+ properly vertically position the tooltip
174
+ */
175
+ focusRect = rects[0];
176
+ }
177
+
178
+ var rectCenter = focusRect.left + focusRect.width / 2;
179
+ var rectTop = focusRect.top;
180
+ var tipWidth = $(tip).width();
181
+ var tipHeight = $(tip).height();
182
+
183
+ /*
184
+ Tooltip is positioned relative to its container, so we need to factor in offsets
185
+ */
186
+ var containerOffset = $(container).offset();
187
+ var offsetLeft = -containerOffset.left;
188
+ var offsetTop = $(document).scrollTop() - containerOffset.top;
189
+ var tipLeft = offsetLeft + rectCenter - tipWidth / 2;
190
+ var tipTop = offsetTop + rectTop - tipHeight + adjustY;
191
+
192
+ /*
193
+ Make sure the new tip position doesn't clip the edges of the screen
194
+ */
195
+ var winWidth = $(window).width();
196
+ if (tipLeft < offsetLeft) {
197
+ tipLeft = offsetLeft;
198
+ } else if (tipLeft + tipWidth > winWidth + offsetLeft) {
199
+ tipLeft = winWidth + offsetLeft - tipWidth;
200
+ }
201
+
202
+ /*
203
+ Update the position object (used by qTip2 to show the tip after the move event)
204
+ */
205
+ $.extend(position, {
206
+ left: tipLeft,
207
+ top: tipTop,
208
+ });
209
+ }
210
+
211
+ function getSpanForProblemReturn(el) {
212
+ var problemId = $(problemReturnSelector).index(el);
213
+ return $(spanSelector).filter("[data-problem-id='" + problemId + "']");
214
+ }
215
+
216
+ function getProblem(el) {
217
+ var problemId = getProblemId(el);
218
+ return $(problemInputSelector).eq(problemId);
219
+ }
220
+
221
+ function getProblemId(el) {
222
+ return $(el).data('problem-id');
223
+ }
224
+
225
+ function toggleAnnotations() {
226
+ annotationsHidden = !annotationsHidden;
227
+ var hide = annotationsHidden;
228
+ toggleAnnotationButtonText(hide);
229
+ toggleSpans(hide);
230
+ toggleTips(hide);
231
+ }
232
+
233
+ function toggleTips(hide) {
234
+ var visible = findVisibleTips();
235
+ hideTips(visible);
236
+ }
237
+
238
+ function toggleAnnotationButtonText(hide) {
239
+ var buttonText = hide ? gettext('Show Annotations') : gettext('Hide Annotations');
240
+ $(toggleAnnotationsSelector).text(buttonText);
241
+ }
242
+
243
+ function toggleInstructions() {
244
+ instructionsHidden = !instructionsHidden;
245
+ var hide = instructionsHidden;
246
+ toggleInstructionsButton(hide);
247
+ toggleInstructionsText(hide);
248
+ }
249
+
250
+ function toggleInstructionsButton(hide) {
251
+ var txt = hide ? gettext('Expand Instructions') : gettext('Collapse Instructions');
252
+ var cls = hide ? ['expanded', 'collapsed'] : ['collapsed', 'expanded'];
253
+ $(toggleInstructionsSelector).text(txt).removeClass(cls[0]).addClass(cls[1]);
254
+ }
255
+
256
+ function toggleInstructionsText(hide) {
257
+ var slideMethod = hide ? 'slideUp' : 'slideDown';
258
+ $(instructionsSelector)[slideMethod]();
259
+ }
260
+
261
+ function toggleSpans(hide) {
262
+ $(spanSelector).toggleClass('hide', hide, 250);
263
+ }
264
+
265
+ function replyTo(buttonEl) {
266
+ var offset = -20;
267
+ var el = getProblem(buttonEl);
268
+ if (el.length > 0) {
269
+ scrollTo(el, afterScrollToProblem, offset);
270
+ } else if (_debug) {
271
+ console.log('Problem not found. Element:', buttonEl);
272
+ }
273
+ }
274
+
275
+ function returnFrom(buttonEl) {
276
+ var offset = -200;
277
+ var el = getSpanForProblemReturn(buttonEl);
278
+ if (el.length > 0) {
279
+ scrollTo(el, afterScrollToSpan, offset);
280
+ } else if (_debug) {
281
+ console.log('Span not found. Element:', buttonEl);
282
+ }
283
+ }
284
+
285
+ function scrollTo(el, after, offset) {
286
+ offset = offset || -20;
287
+ if ($(el).length > 0) {
288
+ $('html,body').scrollTo(el, {
289
+ duration: 500,
290
+ onAfter: _once(function() {
291
+ if (after) {
292
+ after.call(this, el);
293
+ }
294
+ }),
295
+ offset: offset,
296
+ });
297
+ }
298
+ }
299
+
300
+ function afterScrollToProblem(problemEl) {
301
+ problemEl.effect('highlight', {}, 500);
302
+ }
303
+
304
+ function afterScrollToSpan(spanEl) {
305
+ spanEl.addClass('selected', 400, 'swing', function() {
306
+ spanEl.removeClass('selected', 400, 'swing');
307
+ });
308
+ }
309
+
310
+ function makeTipContent(el) {
311
+ return function(api) {
312
+ var text = $(el).data('comment-body');
313
+ var comment = createComment(text);
314
+ var problemId = getProblemId(el);
315
+ var reply = createReplyLink(problemId);
316
+ return $(comment).add(reply);
317
+ };
318
+ }
319
+
320
+ function makeTipTitle(el) {
321
+ return function(api) {
322
+ var title = $(el).data('comment-title');
323
+ return title || gettext('Commentary');
324
+ };
325
+ }
326
+
327
+ function createComment(text) {
328
+ return $('<div class="annotatable-comment">' + text + '</div>'); // xss-lint: disable=javascript-concat-html
329
+ }
330
+
331
+ function createReplyLink(problemId) {
332
+ var linkText = gettext('Reply to Annotation');
333
+ return $(
334
+ '<a class="annotatable-reply" href="javascript:void(0);" data-problem-id="'
335
+ + problemId
336
+ + '">'
337
+ + linkText
338
+ + '</a>',
339
+ ); // xss-lint: disable=javascript-concat-html
340
+ }
341
+
342
+ function findVisibleTips() {
343
+ var visible = [];
344
+ $(spanSelector).each(function(index, el) {
345
+ var api = $(el).qtip('api');
346
+ var tip = $(api && api.elements.tooltip);
347
+ if (tip.is(':visible')) {
348
+ visible.push(el);
349
+ }
350
+ });
351
+ return visible;
352
+ }
353
+
354
+ function hideTips(elements) {
355
+ $(elements).qtip('hide');
356
+ }
357
+
358
+ function _once(fn) {
359
+ var done = false;
360
+ return function() {
361
+ if (!done) {
362
+ fn.call(this);
363
+ done = true;
364
+ }
365
+ };
366
+ }
367
+ }
@@ -0,0 +1,74 @@
1
+ function XMLEditingDescriptor(runtime, element) {
2
+ var saveButtonSelector = '.save-button';
3
+ var cancelButtonSelector = '.cancel-button';
4
+ var editBoxSelector = '.edit-box';
5
+ var _debug = false;
6
+
7
+ var el = element;
8
+
9
+ var textarea = $(editBoxSelector, el)[0];
10
+ if (!textarea) {
11
+ console.error('Error: Textarea with class "edit-box" not found.');
12
+ return;
13
+ }
14
+
15
+ var editBox = CodeMirror.fromTextArea(textarea, {
16
+ mode: 'xml',
17
+ lineNumbers: true,
18
+ lineWrapping: true
19
+ });
20
+
21
+ if (_debug) {
22
+ console.log('loaded XMLEditingDescriptor');
23
+ }
24
+
25
+ function init() {
26
+ initEvents();
27
+ }
28
+
29
+ function initEvents() {
30
+ $(saveButtonSelector, el).on('click', onClickSave);
31
+ $(cancelButtonSelector, el).on('click', onClickCancel);
32
+ }
33
+
34
+ function onClickSave(e) {
35
+ e.preventDefault();
36
+ submit();
37
+ }
38
+
39
+ function onClickCancel(e) {
40
+ e.preventDefault();
41
+ closeEditor();
42
+ }
43
+
44
+ function save() {
45
+ return {
46
+ data: editBox.getValue()
47
+ };
48
+ }
49
+
50
+ function submit() {
51
+ var handlerUrl = runtime.handlerUrl(el, 'submit_studio_edits');
52
+ runtime.notify('save', {state: 'start', message: 'Saving...'});
53
+ var data = save();
54
+
55
+ $.ajax({
56
+ type: 'POST',
57
+ url: handlerUrl,
58
+ data: JSON.stringify(data),
59
+ dataType: 'json',
60
+ success: function(response) {
61
+ runtime.notify('save', {state: 'end'});
62
+ }
63
+ }).fail(function(jqXHR) {
64
+ var message = 'There was an issue saving the settings. Please try again.';
65
+ runtime.notify('error', {title: 'Unable to save', message: message});
66
+ });
67
+ }
68
+
69
+ function closeEditor() {
70
+ runtime.notify('cancel', {});
71
+ }
72
+
73
+ init();
74
+ }
@@ -0,0 +1,24 @@
1
+ {% load i18n %}
2
+ <div class="annotatable-wrapper" id="annotatable_{{ element_id }}">
3
+ <div class="annotatable-header">
4
+ {% if display_name %}<h3 class="hd hd-3 annotatable-title">{{ display_name }}</h3>{% endif %}
5
+ </div>
6
+ {% if instructions_html %}
7
+ <div class="annotatable-section shaded">
8
+ <div class="annotatable-section-title">
9
+ {% trans "Instructions" %}
10
+ <a class="annotatable-toggle annotatable-toggle-instructions expanded"
11
+ href="javascript:void(0)">{% trans "Collapse Instructions" %}</a>
12
+ </div>
13
+ <div class="annotatable-section-body annotatable-instructions">{{ instructions_html|safe }}</div>
14
+ </div>
15
+ {% endif %}
16
+ <div class="annotatable-section">
17
+ <div class="annotatable-section-title">
18
+ {% trans "Guided Discussion" %}
19
+ <a class="annotatable-toggle annotatable-toggle-annotations"
20
+ href="javascript:void(0)">{% trans "Hide Annotations" %}</a>
21
+ </div>
22
+ <div class="annotatable-section-body annotatable-content">{{ content_html|safe }}</div>
23
+ </div>
24
+ </div>
@@ -0,0 +1,20 @@
1
+ {% load i18n %}
2
+ <div class="editor-with-buttons">
3
+ <div class="wrapper-comp-editor" id="editor-tab">
4
+ <section class="raw-edit">
5
+ <textarea name="data" class="edit-box" rows="8" cols="40">{{ data }}</textarea>
6
+ </section>
7
+ </div>
8
+
9
+ <div class="xblock-actions">
10
+ <ul>
11
+ <li class="action-item">
12
+ <a href="#" class="button action-primary save-button">{% trans "Save" %}</a>
13
+ </li>
14
+
15
+ <li class="action-item">
16
+ <a href="#" class="button cancel-button">{% trans "Cancel" %}</a>
17
+ </li>
18
+ </ul>
19
+ </div>
20
+ </div>
@@ -0,0 +1,8 @@
1
+ [main]
2
+ host = https://www.transifex.com
3
+
4
+ [o:open-edx:p:openedx-translations:r:xblock-discussion]
5
+ file_filter = conf/locale/<lang>/LC_MESSAGES/text.po
6
+ source_file = conf/locale/en/LC_MESSAGES/text.po
7
+ source_lang = en
8
+ type = PO
@@ -0,0 +1,5 @@
1
+ """
2
+ Init for the DiscussionXBlock.
3
+ """
4
+
5
+ from .block import DiscussionXBlock as DiscussionXBlock
@@ -0,0 +1,53 @@
1
+ """
2
+ Django App configuration for the xblocks-core Discussion XBlock.
3
+ """
4
+
5
+ from django.apps import AppConfig
6
+
7
+
8
+ class DiscussionAppConfig(AppConfig):
9
+ """
10
+ Configuration for the Discussion XBlock Django application.
11
+
12
+ Why are we registering this as a Django App?
13
+ --------------------------------------------
14
+ By default, Django's template engine (specifically the `app_directories` loader)
15
+ only discovers `templates/` folders that belong to an app listed in `INSTALLED_APPS`.
16
+
17
+ Since XBlocks are inherently isolated components, they are not typically added
18
+ to the LMS/CMS global `INSTALLED_APPS`. As a result, any standard Django templates
19
+ (.html files) inside this block would be invisible to the core Open edX platform
20
+ when it attempts to route or render them natively.
21
+
22
+ Instead of forcing repository consumers to manually modify `lms/envs/common.py`
23
+ or use deployment-specific Tutor plugins to append to `TEMPLATES['DIRS']`, we
24
+ leverage the Open edX Django App Plugin Framework (`plugin_app`). This hook
25
+ dynamically injects this module into `INSTALLED_APPS` at runtime.
26
+
27
+ This automatically exposes our `templates/` directory to the platform natively
28
+ without manual intervention.
29
+
30
+ References:
31
+
32
+ - Open edX Plugin App Framework:
33
+ https://docs.openedx.org/projects/edx-django-utils/en/latest/plugins/how_tos/how_to_create_a_plugin_app.html
34
+
35
+ - Django App Directories Loader:
36
+ https://docs.djangoproject.com/en/stable/ref/templates/api/#django.template.loaders.app_directories.Loader
37
+
38
+ """
39
+
40
+ name = "xblock_discussion"
41
+ label = "xblock_discussion"
42
+ verbose_name = "XBlocks Core - Discussion Templates"
43
+
44
+ plugin_app = {
45
+ "settings_config": {
46
+ "lms.djangoapp": {
47
+ "default": "",
48
+ },
49
+ "cms.djangoapp": {
50
+ "default": "",
51
+ },
52
+ },
53
+ }