@windward/core 0.3.0 → 0.4.0

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 (43) hide show
  1. package/components/Content/Blocks/Accordion.vue +37 -0
  2. package/components/Content/Blocks/ClickableIcons.vue +107 -20
  3. package/components/Content/Blocks/Email.vue +9 -0
  4. package/components/Content/Blocks/Image.vue +47 -19
  5. package/components/Content/Blocks/Video.vue +80 -9
  6. package/components/Settings/AccordionSettings.vue +53 -0
  7. package/components/Settings/ClickableIconsSettings.vue +84 -7
  8. package/components/Settings/EmailSettings.vue +0 -9
  9. package/components/Settings/ImageSettings.vue +142 -39
  10. package/components/Settings/OpenResponseSettings.vue +1 -2
  11. package/components/Settings/VideoSettings.vue +100 -63
  12. package/components/utils/ContentViewer.vue +6 -1
  13. package/components/utils/MathExpressionEditor.vue +10 -5
  14. package/components/utils/TinyMCEWrapper.vue +114 -18
  15. package/components/utils/assets/tinymce/content/dark/content.scss +4 -0
  16. package/components/utils/assets/tinymce/{css/content.scss → content/global.scss} +38 -37
  17. package/components/utils/assets/tinymce/content/light/content.scss +4 -0
  18. package/components/utils/assets/tinymce/ui/dark/content.scss +803 -0
  19. package/components/utils/assets/tinymce/ui/dark/skin.scss +4727 -0
  20. package/components/utils/assets/tinymce/ui/global.scss +19 -0
  21. package/components/utils/assets/tinymce/ui/light/content.scss +822 -0
  22. package/components/utils/assets/tinymce/ui/light/skin.scss +4731 -0
  23. package/components/utils/glossary/CourseGlossary.vue +1 -1
  24. package/config/tinymce.config.ts +22 -14
  25. package/helpers/FillInBlankHelper.ts +34 -28
  26. package/helpers/GlossaryHelper.ts +90 -73
  27. package/helpers/MathHelper.ts +49 -28
  28. package/helpers/tinymce/plugin.ts +9 -7
  29. package/i18n/en-US/components/settings/clickable_icon.ts +2 -0
  30. package/i18n/en-US/components/settings/image.ts +6 -1
  31. package/i18n/en-US/shared/settings.ts +3 -0
  32. package/i18n/es-ES/components/settings/clickable_icon.ts +2 -0
  33. package/i18n/es-ES/components/settings/image.ts +8 -1
  34. package/i18n/es-ES/shared/settings.ts +3 -0
  35. package/i18n/sv-SE/components/settings/clickable_icon.ts +2 -0
  36. package/i18n/sv-SE/components/settings/image.ts +6 -1
  37. package/i18n/sv-SE/shared/settings.ts +3 -0
  38. package/package.json +4 -3
  39. package/test/Components/Settings/AccordionSettings.spec.js +16 -2
  40. package/test/__mocks__/contentBlockMock.js +6 -0
  41. package/test/__mocks__/contentSettingsMock.js +6 -0
  42. package/test/helpers/MathHelper.spec.js +22 -3
  43. package/tsconfig.json +1 -0
@@ -14,7 +14,7 @@
14
14
  <DialogBox
15
15
  v-model="dialog"
16
16
  color="primary"
17
- max-width="600px"
17
+ max-width="600"
18
18
  :trigger="
19
19
  $PermissionService.userHasAccessTo(
20
20
  'windward.global.course,windward.organization.course.contentBlock',
@@ -24,6 +24,14 @@ export default {
24
24
  cmd: false,
25
25
  text: 'i',
26
26
  },
27
+ {
28
+ cmd: false,
29
+ text: '\\$',
30
+ },
31
+ {
32
+ cmd: false,
33
+ text: '\\%',
34
+ },
27
35
  {
28
36
  cmd: true,
29
37
  text: '\\pi',
@@ -31,44 +39,43 @@ export default {
31
39
  },
32
40
  {
33
41
  cmd: true,
34
- text: '{x}^{2}',
35
- latex: 'x^2',
42
+ text: 'x^2',
43
+ latex: '^2',
36
44
  },
37
45
  {
38
46
  cmd: true,
39
47
  text: '{x}^{y}',
40
- latex: '\\placeholder{x}^\\placeholder{y}',
48
+ latex: '^\\placeholder{}',
41
49
  },
42
50
  {
43
51
  cmd: true,
44
52
  text: '{x}_{y}',
45
- latex: '\\placeholder{x}_\\placeholder{y}',
53
+ latex: '_\\placeholder{}',
46
54
  },
47
55
  {
48
56
  text: '\\sqrt{x}',
49
- latex: '\\sqrt{x}',
57
+ latex: '\\sqrt{\\placeholder{}}',
50
58
  cmd: true,
51
59
  },
52
60
  {
53
- latex: '\\sqrt[\\placeholder{n}]{\\placeholder{x}}',
61
+ latex: '\\sqrt[\\placeholder{}]{\\placeholder{}}',
54
62
  text: '\\sqrt[n]{x}',
55
63
  cmd: true,
56
64
  },
57
65
  {
58
- cmd: false,
66
+ cmd: true,
59
67
  text: '\\frac{x}{y}',
60
- latex:
61
- '\\frac\n' +
62
- ' {\\placeholder[numerator]{?}}\n' +
63
- ' {\\placeholder[denominator]{?}}',
68
+ latex: '\\frac',
64
69
  },
65
70
  {
66
- cmd: false,
71
+ cmd: true,
67
72
  text: '\\left|x\\right|',
73
+ latex: '\\left|\\placeholder{}\\right|',
68
74
  },
69
75
  {
70
- cmd: false,
71
- text: '\\left\\{\\right\\}',
76
+ cmd: true,
77
+ text: '\\left\\{x\\right\\}',
78
+ latex: '\\left\\{\\placeholder{}\\right\\}',
72
79
  },
73
80
  {
74
81
  cmd: false,
@@ -78,6 +85,7 @@ export default {
78
85
  cmd: false,
79
86
  text: '(x,y)',
80
87
  },
88
+
81
89
  ],
82
90
  },
83
91
  {
@@ -1,53 +1,59 @@
1
-
2
1
  export default class FillInBlankHelper {
3
-
4
- private static FillBlankRegex = /<span.*?.class="windward-fill-blank".*?>(.*?)<\/span>/gi;
2
+ private static FillBlankRegex =
3
+ /<span.*?.class="windward-fill-blank".*?>(.*?)<\/span>/gi
5
4
 
6
5
  public static containsFillInBlank(content: string): boolean {
7
- const regex = new RegExp(this.FillBlankRegex);
6
+ const regex = new RegExp(this.FillBlankRegex)
8
7
 
9
- return regex.exec(content) !== null;
8
+ return regex.exec(content) !== null
10
9
  }
11
10
 
12
11
  public static makeToolTip(htmlString: string): string {
13
- const parser = new DOMParser();
14
- const doc = parser.parseFromString(htmlString, "text/html");
12
+ const parser: any = new DOMParser()
13
+ const doc: any = parser.parseFromString(htmlString, 'text/html')
15
14
  // doc.body.firstChild can be null
16
- let answer = doc.body.firstChild ? doc.body.firstChild.textContent : "";
17
- let feedback = "";
18
- if (doc.body.getElementsByClassName("windward-fill-blank")[0]["dataset"]["feedback"] !== undefined) {
19
- feedback = doc.body.getElementsByClassName("windward-fill-blank")[0]["dataset"]["feedback"];
15
+ let answer = doc.body.firstChild ? doc.body.firstChild.textContent : ''
16
+ let feedback = ''
17
+ if (
18
+ doc.body.getElementsByClassName('windward-fill-blank')[0][
19
+ 'dataset'
20
+ ]['feedback'] !== undefined
21
+ ) {
22
+ feedback = doc.body.getElementsByClassName(
23
+ 'windward-fill-blank'
24
+ )[0]['dataset']['feedback']
20
25
  }
21
26
 
22
27
  return (
23
- "<plugin-core-fill-in-blank-input answer=\"" + answer + "\" description=\"" + feedback + "\">" +
24
- "</template>" + "</plugin-core-fill-in-blank-input>");
25
-
28
+ '<plugin-core-fill-in-blank-input answer="' +
29
+ answer +
30
+ '" description="' +
31
+ feedback +
32
+ '">' +
33
+ '</template>' +
34
+ '</plugin-core-fill-in-blank-input>'
35
+ )
26
36
  }
27
37
 
28
- public escapeHtml(html) {
29
- var text = document.createTextNode(html);
30
- var p = document.createElement("p");
31
- p.appendChild(text);
32
- return p.innerHTML;
38
+ public escapeHtml(html: any) {
39
+ var text = document.createTextNode(html)
40
+ var p = document.createElement('p')
41
+ p.appendChild(text)
42
+ return p.innerHTML
33
43
  }
34
44
 
35
45
  public static renderFillInTHeBlankHtml(content: string, glossary: any) {
36
- const regex = new RegExp(this.FillBlankRegex);
37
-
46
+ const regex = new RegExp(this.FillBlankRegex)
38
47
 
39
- let match;
48
+ let match
40
49
  while ((match = regex.exec(content)) !== null) {
41
50
  // This is necessary to avoid infinite loops with zero-width matches
42
51
  if (match.index === regex.lastIndex) {
43
- regex.lastIndex++;
52
+ regex.lastIndex++
44
53
  }
45
- content = content.replace(
46
- match[0],
47
- this.makeToolTip(match[0])
48
- );
54
+ content = content.replace(match[0], this.makeToolTip(match[0]))
49
55
  }
50
56
 
51
- return content;
57
+ return content
52
58
  }
53
59
  }
@@ -1,53 +1,49 @@
1
- import GlossaryTerm from "../helpers/GlossaryTerm";
1
+ import GlossaryTerm from '../helpers/GlossaryTerm'
2
2
  import * as _ from 'lodash'
3
3
 
4
4
  export default class GlossaryHelper {
5
- private static glossaryRegex = /<span.*?.class="glossary-word".*?>(.*?)<\/span>/g
6
- public static makeToolTip(term :GlossaryTerm,text :String): string {
7
- let word =
8
- _.isString(term.term)?
9
- '<template v-slot:term>' +
10
- text +
11
- '</template>' :''
12
- let definition =
13
- _.isString(term.definition)?
14
- '<template v-slot:definition>' +
15
- term.definition +
16
- '</template>' :''
17
- let alternate_forms =
18
- _.isString(term.alternate_forms)?
19
- '<template v-slot:alternate_forms>' +
20
- term.alternate_forms +
21
- '</template>' :''
22
- let related_terms =
23
- _.isString(term.related_term)?
24
- '<template v-slot:related_terms>' +
25
- term.related_term +
26
- '</template>' :''
27
- return (
28
- '<plugin-core-glossary-tool-tip>' +
29
- word
30
- +
31
- definition
32
- +
33
- alternate_forms
34
- +
35
- related_terms
36
- +
37
- '</plugin-core-glossary-tool-tip>')
38
-
5
+ private static glossaryRegex =
6
+ /<span.*?.class="glossary-word".*?>(.*?)<\/span>/g
7
+ public static makeToolTip(term: GlossaryTerm, text: String): string {
8
+ let word = _.isString(term.term)
9
+ ? '<template v-slot:term>' + text + '</template>'
10
+ : ''
11
+ let definition = _.isString(term.definition)
12
+ ? '<template v-slot:definition>' + term.definition + '</template>'
13
+ : ''
14
+ let alternate_forms = _.isString(term.alternate_forms)
15
+ ? '<template v-slot:alternate_forms>' +
16
+ term.alternate_forms +
17
+ '</template>'
18
+ : ''
19
+ let related_terms = _.isString(term.related_term)
20
+ ? '<template v-slot:related_terms>' +
21
+ term.related_term +
22
+ '</template>'
23
+ : ''
24
+ return (
25
+ '<plugin-core-glossary-tool-tip>' +
26
+ word +
27
+ definition +
28
+ alternate_forms +
29
+ related_terms +
30
+ '</plugin-core-glossary-tool-tip>'
31
+ )
39
32
  }
40
- public static containsGlossaryTerms(content :string): boolean {
33
+ public static containsGlossaryTerms(content: string): boolean {
41
34
  const regex = new RegExp(this.glossaryRegex)
42
35
 
43
36
  return regex.exec(content) !== null
44
37
  }
45
38
 
46
- public static getContentVerifiedGlossaryTerms(content :string, glossary :any) {
47
- const regex = new RegExp( this.glossaryRegex)
39
+ public static getContentVerifiedGlossaryTerms(
40
+ content: string,
41
+ glossary: any
42
+ ) {
43
+ const regex = new RegExp(this.glossaryRegex)
48
44
  const currentGlossary = glossary
49
45
 
50
- let match
46
+ let match: any
51
47
  const verifiedTerms: GlossaryTerm[] = []
52
48
  while ((match = regex.exec(content)) !== null) {
53
49
  // This is necessary to avoid infinite loops with zero-width matches
@@ -56,28 +52,40 @@ export default class GlossaryHelper {
56
52
  }
57
53
 
58
54
  // The result can be accessed through the `m`-variable.
59
- currentGlossary.forEach((term) => {
55
+ currentGlossary.forEach((term: any) => {
60
56
  let addTerm = true
61
- verifiedTerms.forEach((verifiedTerm)=>{
62
- if(_.trim(_.toLower(verifiedTerm.term)) === _.trim(_.toLower(term.term))){
57
+ verifiedTerms.forEach((verifiedTerm) => {
58
+ if (
59
+ _.trim(_.toLower(verifiedTerm.term)) ===
60
+ _.trim(_.toLower(term.term))
61
+ ) {
63
62
  addTerm = false
64
63
  }
65
- })
66
- if (_.trim(_.toLower(match[1]))=== _.trim(_.toLower(term.term)) && addTerm) {
64
+ })
65
+ if (
66
+ _.trim(_.toLower(match[1])) ===
67
+ _.trim(_.toLower(term.term)) &&
68
+ addTerm
69
+ ) {
67
70
  verifiedTerms.push(new GlossaryTerm(term))
68
71
  }
69
72
  })
70
-
71
73
  }
72
74
 
73
75
  return verifiedTerms
74
76
  }
75
77
 
76
- public static getContentUnVerifiedGlossaryTerms(content :string, glossary :any) {
77
- const regex = new RegExp( this.glossaryRegex)
78
-
79
- let match
80
- const verifiedTerms = this.getContentVerifiedGlossaryTerms(content,glossary)
78
+ public static getContentUnVerifiedGlossaryTerms(
79
+ content: string,
80
+ glossary: any
81
+ ) {
82
+ const regex: any = new RegExp(this.glossaryRegex)
83
+
84
+ let match: any
85
+ const verifiedTerms = this.getContentVerifiedGlossaryTerms(
86
+ content,
87
+ glossary
88
+ )
81
89
  const unVerifiedTerms: GlossaryTerm[] = []
82
90
  while ((match = regex.exec(content)) !== null) {
83
91
  // This is necessary to avoid infinite loops with zero-width matches
@@ -87,33 +95,41 @@ export default class GlossaryHelper {
87
95
 
88
96
  let inGlossary = []
89
97
 
90
- inGlossary = glossary.filter(item => {
91
- if(_.trim(_.toLower(item.term ))=== _.trim(_.toLower(match[1]))){
98
+ inGlossary = glossary.filter((item: any) => {
99
+ if (
100
+ _.trim(_.toLower(item.term)) === _.trim(_.toLower(match[1]))
101
+ ) {
92
102
  return item
93
-
94
103
  }
95
- });
104
+ })
96
105
 
97
106
  let inUnverifiedArray = false
98
- unVerifiedTerms.forEach((unVerifiedTerm)=>{
99
- if(_.trim(_.toLower(unVerifiedTerm.term)) === _.trim(_.toLower(match[1]))){
107
+ unVerifiedTerms.forEach((unVerifiedTerm: any) => {
108
+ if (
109
+ _.trim(_.toLower(unVerifiedTerm.term)) ===
110
+ _.trim(_.toLower(match[1]))
111
+ ) {
100
112
  inUnverifiedArray = true
101
113
  }
102
114
  })
103
- if ( inGlossary.length===0 && !inUnverifiedArray){
104
- unVerifiedTerms.push(new GlossaryTerm( {term:_.trim(match[1]),definition:'n/a'}))
115
+ if (inGlossary.length === 0 && !inUnverifiedArray) {
116
+ unVerifiedTerms.push(
117
+ new GlossaryTerm({
118
+ term: _.trim(match[1]),
119
+ definition: 'n/a',
120
+ })
121
+ )
105
122
  }
106
-
107
-
108
123
  }
109
124
 
110
125
  return unVerifiedTerms
111
126
  }
112
- public static renderGlossaryWordsHtml(content :string, glossary :any) {
113
- const regex = new RegExp( this.glossaryRegex)
114
- const currentGlossary = glossary
127
+ public static renderGlossaryWordsHtml(content: string, glossary: any) {
128
+ const regex: any = new RegExp(this.glossaryRegex)
129
+ const currentGlossary: any = glossary
130
+
131
+ let match: any = []
115
132
 
116
- let match
117
133
  while ((match = regex.exec(content)) !== null) {
118
134
  // This is necessary to avoid infinite loops with zero-width matches
119
135
  if (match.index === regex.lastIndex) {
@@ -121,15 +137,16 @@ export default class GlossaryHelper {
121
137
  }
122
138
 
123
139
  // The result can be accessed through the `m`-variable.
124
- currentGlossary.forEach((term) => {
125
- if (_.trim(_.toLower(match[1]))=== _.trim(_.toLower(term.term))) {
126
- content = content.replace(
127
- match[0],
128
- this.makeToolTip(term,match[1])
129
- )
130
- }
131
- })
132
-
140
+ currentGlossary.forEach((term: any) => {
141
+ if (
142
+ _.trim(_.toLower(match[1])) === _.trim(_.toLower(term.term))
143
+ ) {
144
+ content = content.replace(
145
+ match[0],
146
+ this.makeToolTip(term, match[1])
147
+ )
148
+ }
149
+ })
133
150
  }
134
151
 
135
152
  return content
@@ -1,6 +1,6 @@
1
1
  import * as mathLiveObject from 'mathlive'
2
2
  import * as _ from 'lodash'
3
- import { MathMLToLaTeX } from 'mathml-to-latex';
3
+ import { MathMLToLaTeX } from 'mathml-to-latex'
4
4
  export default class MathHelper {
5
5
  /**
6
6
  * expose mathlive object
@@ -67,38 +67,59 @@ export default class MathHelper {
67
67
  return content
68
68
  }
69
69
 
70
+
70
71
  /**
71
- * wrapMathContentForTinyMCE
72
- * @param content
73
- * wrap content in span with math class for tinymce
74
- * @return string
72
+ * Wraps math content.
73
+ *
74
+ * @param {string} match - The matched string to be wrapped.
75
+ * @param {string} content - The content to be replaced.
76
+ * @param {string} temp - The temporary string.
77
+ * @return {string} - The replaced content with wrapped math content.
78
+ */
79
+ private static wrapMathContentMatch(match : string, content: string, temp: string): string {
80
+ let wrapped = `<span class ='windward-math-content'>${match}</span> &nbsp;`;
81
+ if (match.match(/\$\$.*?\$\$/g) !== null && temp !== '') {
82
+ wrapped = `<span class ='windward-math-content'>$$$${temp}$$$</span> &nbsp;`;
83
+ }
84
+ return content.replaceAll(match, wrapped);
85
+ }
86
+
87
+ /**
88
+ * Checks if the given content already has a specific template wrapped around it.
89
+ *
90
+ * @param {string} content - The original content to be checked.
91
+ * @param {string} match - The template string to be compared against.
92
+ * @param {string} temp - The temp string to be compared against for final template.
93
+ * @return {boolean} - True if the content already contains the specified template, false otherwise.
94
+ */
95
+ private static contentAlreadyWrapped(content: string, match: string, temp: string): boolean {
96
+ const wrappedTemplates = [
97
+ `<span class=\"windward-math-content\" contenteditable=\"true\">$$${temp}$$</span>`,
98
+ `<span class='windward-math-content'>$$${temp}$$</span>`,
99
+ `<span class ='windward-math-content'>$$${temp}$$</span>`,
100
+ `<span class=\"windward-math-content\">$$${temp}$$</span>`];
101
+ return _.some(wrappedTemplates, template => _.includes(content, template));
102
+ }
103
+
104
+ /**
105
+ * Wraps math content for TinyMCE.
106
+ *
107
+ * @param {string} content - The content to be wrapped.
108
+ * @returns {string} - The wrapped content.
75
109
  */
76
110
  public static wrapMathContentForTinyMCE(content: string): string {
77
- const regex = /(\*\*|\$\$)(.*?)\1/g
78
- const matches = content.match(regex)
111
+ const regex = /(\*\*|\$\$)(.*?)\1/g;
112
+ const matches = content.match(regex);
113
+
79
114
  if (matches) {
80
115
  matches.forEach((match) => {
81
- const temp = match.replace(/\$\$/g, '')
82
- if (match.match(/\$\$.*?\$\$/g) !== null) {
83
- content = content.replace(
84
- match,
85
- "<span class ='windward-math-content'>$$$" +
86
- temp +
87
- '$$$</span>'
88
- )
89
- }
90
- if (match.match(/\*\*(.*?)\*\*/g) !== null) {
91
- content = content.replace(
92
- match,
93
- "<span class ='windward-math-content'>" +
94
- match +
95
- '</span>'
96
- )
116
+ const temp = match.replace(/\$\$/g, '');
117
+ if (!this.contentAlreadyWrapped(content, match, temp)) {
118
+ content = this.wrapMathContentMatch(match, content, temp);
97
119
  }
98
- })
120
+ });
99
121
  }
100
-
101
- return content
122
+ return content;
102
123
  }
103
124
 
104
125
  /**
@@ -109,7 +130,7 @@ export default class MathHelper {
109
130
  */
110
131
  public static checkMathContentWrappedForTMCE(content: string): boolean {
111
132
  const regex =
112
- /\<span class ='windward-math-content'>(\*\*|\$\$)(.*?)\1<\/span>/g
133
+ /<span\s+class.*?=.*?(windward-math-content).*?>(.*?)<\/span>/g
113
134
 
114
135
  return regex.exec(content) !== null
115
136
  }
@@ -184,7 +205,7 @@ export default class MathHelper {
184
205
  MathHelper.convertContentLatexToHtml(
185
206
  MathHelper.convertContentMathMLtoLatex(content)
186
207
  )
187
- ).replace(/contenteditable="true"/g, '');
208
+ ).replace(/contenteditable="true"/g, '')
188
209
  }
189
210
 
190
211
  /**
@@ -1,3 +1,4 @@
1
+ import MathHelper from "../MathHelper";
1
2
  const WindwardPlugins = function (editor: any) {
2
3
  let formula: any
3
4
  let fillInBlank: any
@@ -12,8 +13,6 @@ const WindwardPlugins = function (editor: any) {
12
13
  return editor.windowManager.openUrl({
13
14
  url: '/plugins/tinymce/math',
14
15
  title: 'Equation editor',
15
- width: window.innerWidth*.50,
16
- height: window.innerHeight*.75,
17
16
  buttons: [
18
17
  {
19
18
  type: 'cancel',
@@ -32,7 +31,7 @@ const WindwardPlugins = function (editor: any) {
32
31
  editor.selection.setContent(
33
32
  ` <span class='windward-math-content'>` +
34
33
  formula +
35
- `</span>`
34
+ `</span> `
36
35
  )
37
36
 
38
37
  editor.windowManager.close()
@@ -69,10 +68,15 @@ const WindwardPlugins = function (editor: any) {
69
68
  setOnClickEquationContent(editor)
70
69
  setOnClickFillInBlank(editor)
71
70
  })
71
+
72
72
  editor.on('SetContent', function () {
73
73
  setOnClickEquationContent(editor)
74
74
  setOnClickFillInBlank(editor)
75
75
  })
76
+ editor.on('input', function () {
77
+ setOnClickEquationContent(editor)
78
+ setOnClickFillInBlank(editor)
79
+ })
76
80
  function setOnClickEquationContent(editor: any) {
77
81
  const tinymceDoc = editor.getDoc()
78
82
  const mqSpan = tinymceDoc.getElementsByClassName(
@@ -86,7 +90,7 @@ const WindwardPlugins = function (editor: any) {
86
90
  continue
87
91
  }
88
92
 
89
- equationContent.onclick = (event: any) => {
93
+ equationContent.ondblclick = (event: any) => {
90
94
  event.stopPropagation()
91
95
  editor.execCommand('equation-window', {
92
96
  latex: event.target.innerText,
@@ -100,8 +104,6 @@ const WindwardPlugins = function (editor: any) {
100
104
  return editor.windowManager.openUrl({
101
105
  url: '/plugins/tinymce/FIB',
102
106
  title: 'Fill in the blank',
103
- width: window.innerWidth*.50,
104
- height: window.innerHeight*.75,
105
107
  buttons: [
106
108
  {
107
109
  type: 'cancel',
@@ -193,7 +195,7 @@ const WindwardPlugins = function (editor: any) {
193
195
  continue
194
196
  }
195
197
 
196
- fib.onclick = (event: any) => {
198
+ fib.ondblclick = (event: any) => {
197
199
  event.stopPropagation()
198
200
  editor.execCommand('fib-window', {
199
201
  answer: event.target.innerText,
@@ -8,10 +8,12 @@ export default {
8
8
  item_color: 'Item Color',
9
9
  item_text: 'Item Text',
10
10
  autocolor: 'Auto-color Options',
11
+ icon_image: 'Use image for icon',
11
12
  display: {
12
13
  show_title: 'Always Show Title',
13
14
  show_background: 'Show Background',
14
15
  round_icon: 'Round Icons',
15
16
  italic_icon: 'Italic Icons',
17
+ large_icon: 'Large Icons',
16
18
  },
17
19
  }
@@ -2,11 +2,16 @@ export default {
2
2
  hide_background: 'Hide Background',
3
3
  modal: 'Click to open in modal',
4
4
  decorative: 'Decorative Image',
5
- toggle_description:
5
+ decorative_toggle_description:
6
6
  'To meet accessibility standards, alt text is required for all images except for purely decorative images. This setting will add the proper alt text and screen reader text for learners.',
7
+ inherit_global_toggle_description:
8
+ 'When enabled, the selected image will use alt text and screen reader text stored on the file, managed in the file manager. When disabled, the selected image will have its own unique alt text and screen reader text that is not shared globally on the file.',
7
9
  alt_description:
8
10
  'Alternative text is descriptive text that conveys the meaning and context of a visual item in a digital setting, intended for users who are visually impaired or otherwise unable to visually identify an image. This should be short and clear.',
9
11
  screenreader: 'Screen Reader Text',
10
12
  screenreader_description:
11
13
  'Screen reader text can be added to give a user using assistive technology more information about the elements on the page',
14
+ inherit: 'Inherit global settings',
15
+ inherit_no_alt: 'No global alt text available for file',
16
+ inherit_no_aria: 'No global screen reader text available for file',
12
17
  }
@@ -22,4 +22,7 @@ export default {
22
22
  instructions: 'Instructions',
23
23
  placeholder: 'Enter text here',
24
24
  },
25
+ upload_file: 'Upload File',
26
+ alt_image: 'Alternate text for image',
27
+ aria_described: 'Aria described by',
25
28
  }
@@ -9,10 +9,12 @@ export default {
9
9
  item_color: 'Color del artículo',
10
10
  item_text: 'Texto del elemento',
11
11
  autocolor: 'Opciones de color automático',
12
+ icon_image: 'Usar imagen como ícono',
12
13
  display: {
13
14
  show_title: 'Mostrar siempre el título',
14
15
  show_background: 'Mostrar fondo',
15
16
  round_icon: 'Iconos redondos',
16
17
  italic_icon: 'Iconos en cursiva',
18
+ large_icon: 'Iconos grandes',
17
19
  },
18
20
  }
@@ -2,11 +2,18 @@ export default {
2
2
  hide_background: 'Ocultar fondo',
3
3
  modal: 'Haga clic para abrir en modal',
4
4
  decorative: 'Imagen decorativa',
5
- toggle_description:
5
+ decorative_toggle_description:
6
6
  'Para cumplir con los estándares de accesibilidad, se requiere texto alternativo para todas las imágenes, excepto para las imágenes puramente decorativas. Esta configuración agregará el texto alternativo y el texto del lector de pantalla adecuados para los estudiantes.',
7
+ inherit_global_toggle_description:
8
+ 'Cuando está habilitado, la imagen seleccionada utilizará texto alternativo y texto del lector de pantalla almacenado en el archivo, administrado en el administrador de archivos. Cuando está deshabilitada, la imagen seleccionada tendrá su propio texto alternativo y texto de lector de pantalla que no se comparte globalmente en el archivo.',
7
9
  alt_description:
8
10
  'El texto alternativo es un texto descriptivo que transmite el significado y el contexto de un elemento visual en un entorno digital, destinado a usuarios con discapacidad visual o que no pueden identificar visualmente una imagen. Esto debe ser breve y claro.',
9
11
  screenreader: 'Texto del lector de pantalla',
10
12
  screenreader_description:
11
13
  'Se puede agregar texto al lector de pantalla para brindarle al usuario que utiliza tecnología de asistencia más información sobre los elementos de la página',
14
+ inherit: 'Heredar configuración global',
15
+ inherit_no_alt:
16
+ 'No hay texto alternativo global disponible para el archivo',
17
+ inherit_no_aria:
18
+ 'No hay texto de lector de pantalla global disponible para el archivo',
12
19
  }