PluginProbe
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses / 4.4.4
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses v4.4.4
4.4.8 4.4.7 4.4.6 4.4.5 4.4.4 4.4.3 4.4.2 4.4.1 4.4.0 4.3.9.1 4.3.9 4.3.8 4.3.7 4.1.6.9 4.1.6.9.1 4.1.6.9.2 4.1.6.9.3 4.1.6.9.4 4.1.7 4.1.7.1 4.1.7.2 4.1.7.3 4.1.7.3.1 4.1.7.3.2 4.2.0 All 139 releases
learnpress / inc / admin / views / question / fill-in-blanks.php

fill-in-blanks.php in LearnPress – WordPress LMS Plugin for Create and Sell Online Courses 4.4.4, at inc/admin/views/question/fill-in-blanks.php

348 lines 9.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Admin question editor: fib question answer template.
4 *
5 * @since 3.0.0
6 */
7
8 $content_id = uniqid( 'fib-content-' );
9 ?>
10
11 <script type="text/x-template" id="tmpl-lp-fib-question-answer">
12 <div id="lp-admin-question-editor" class="lp-admin-fib-question-editor">
13 <?php learn_press_admin_view( 'question/fib-answer-editor' ); ?>
14 </div>
15 </script>
16
17 <script type="text/javascript">
18 jQuery( document ).ready( function( $ ) {
19 const $Vue = window.$Vue || Vue;
20 const $store = window.LP_Question_Store;
21
22 Vue.component( 'lp-fib-question-answer', {
23 template: '#tmpl-lp-fib-question-answer',
24 props: [ 'type', 'answers', 'rawBlanks' ],
25
26 data() {
27 return {
28 valid: true,
29 canInsertNewBlank: false,
30 blanks: [],
31 };
32 },
33 mounted() {
34 const that = this,
35 content = this.getContent();
36 this.blanks = this.answers[ 0 ].blanks;
37 this.$editor = $( this.$el ).find( '.content-editable' );
38 this.$editor.html( content );
39 this.parseBlanks( content );
40
41 this.$editor[ 0 ].addEventListener( 'DOMCharacterDataModified', function( e ) {
42 const $target = $( e.target ).parent(),
43 id = $target.data( 'id' );
44
45 for ( const i in that.blanks ) {
46 if ( that.blanks[ i ].id == id ) {
47 that.blanks[ i ].fill = $target.html().trim();
48 that.$activeBlank = $target;
49 break;
50 }
51 }
52 }, false );
53
54 this.interval = setInterval( function( a ) {
55 a.parseBlanks( a.getContent() );
56 }, 1000, this );
57 },
58 computed: {
59 answer() {
60 return {
61 order: 1,
62 is_true: '',
63 question_answer_id: this.answers[ 0 ].question_answer_id,
64 title: this.answers[ 0 ].title,
65 value: '',
66 blanks: this.answers[ 0 ].blanks,
67 };
68 },
69 },
70 methods: {
71 updateAnswer( e ) {
72 let answer = JSON.parse( JSON.stringify( this.answer ) );
73 answer.title = this.getShortcode();
74 answer.blanks = this.getBlanksForDB();
75
76 $store.dispatch( 'updateAnswerTitle', answer );
77 },
78 updateAnswerBlank( e, blank ) {
79 blank['comparison'] = e.target.value || '';
80 this.updateAnswer();
81 },
82 updateAnswerMatchCase( e, blank ) {
83 blank['match_case'] = e.target.checked ? true : false;
84 this.updateAnswer();
85 },
86 getContent() {
87 let content = this.answers[ 0 ].title,
88 shortcodes = content.match( /\[fib.*?\]/g ),
89 uids = {};
90
91 if ( shortcodes ) {
92 for ( let i = 0; i < shortcodes.length; i++ ) {
93 var uid,
94 fill,
95 replaceText,
96 props = shortcodes[ i ].match( /([a-z_]+)="(.*?)"/g ),
97 data = [];
98
99 for ( const j in props ) {
100 const prop = props[ j ].match( /([a-z_]+)="(.*?)"/ );
101
102 if ( ! prop ) {
103 continue;
104 }
105
106 switch ( prop[ 1 ] ) {
107 case 'uid':
108 case 'id':
109 uid = prop[ 2 ];
110 break;
111 case 'fill':
112 fill = prop[ 2 ];
113 break;
114 default:
115 data.push( 'data-' + prop[ 1 ] + '="' + prop[ 2 ] + '"' );
116 }
117 }
118
119 uid = uid ? uid : LP.uniqueId();
120
121 if ( uids[ uid ] ) {
122 uid = LP.uniqueId();
123 }
124
125 replaceText = FIB.outerHTML( this.createBlank( fill, uid ).attr( 'data-index', i + 1 ) );// '<span class="fib-blank" id="fib-blank-' + uid + '" data-id="' + uid + '" data-index="' + (i + 1) + '">' + fill + '</span>';
126 uids[ uid ] = true;
127
128 content = content.replace( shortcodes[ i ], replaceText );
129 }
130 }
131 return content;
132 },
133 activeBlank( e ) {
134 this.$activeBlank = $( e.target ).closest( '.fib-blank' );
135 },
136
137 findBlank( id ) {
138 for ( const i in this.blanks ) {
139 if ( this.blanks[ i ].id == id ) {
140 return this.blanks[ i ];
141 }
142 }
143
144 return false;
145 },
146 parseBlanks( content ) {
147 let $container = this.$editor,
148 $inputs = $container.find( '.fib-blank' ),
149 $input,
150 data,
151 blanks = [],
152 uids = [],
153 i = 0,
154 n = 0;
155
156 for ( i = 0; i < $inputs.length; i++ ) {
157 $input = $inputs.eq( i ).attr( 'data-index', i + 1 );
158 data = $input.data();
159
160 if ( -1 !== $.inArray( data.id, uids ) ) {
161 data.id = LP.uniqueId();
162 }
163
164 const oldBlank = this.findBlank( data.id ) || {};
165
166 blanks.push( {
167 fill: $input.html().trim(),
168 id: data.id,
169 comparison: data.comparison || oldBlank.comparison || '',
170 match_case: data.match_case || oldBlank.match_case || 0,
171 index: i + 1,
172 open: !! oldBlank.open,
173 } );
174 uids.push( data.id );
175 }
176 this.blanks = blanks;
177 },
178 updateBlanks( content ) {
179 this.parseBlanks( content !== undefined ? content : this.$editor.html() );
180 return this.getShortcode();
181 },
182 getShortcode() {
183 const that = this,
184 $container = this.$editor.clone(),
185 $blanks = $container.find( '.fib-blank' );
186
187 $blanks.each( function() {
188 let $blank = $( this ),
189 id = $blank.attr( 'id' ),
190 uid = id.replace( 'fib-blank-', '' ),
191 blank = that.getBlankById( uid ),
192 code = 'fib';
193
194 if ( blank ) {
195 if ( ! blank.id ) {
196 return;
197 }
198
199 for ( const i in blank ) {
200 if ( [ 'index' ].indexOf( i ) !== -1 ) {
201 continue;
202 }
203
204 if ( ! blank[ i ] ) {
205 continue;
206 }
207
208 code += ' ' + i + '="' + blank[ i ] + '"';
209 }
210
211 $blank.replaceWith( '[' + code + ']' );
212 } else {
213 console.log( 'Not found: ' + uid );
214 $blank.replaceWith( '' );
215 }
216 } );
217 return $container.html();
218 },
219 getBlankById( id ) {
220 let blank = false;
221
222 $.each( this.blanks, function() {
223 if ( id == this.id ) {
224 blank = this;
225 return true;
226 }
227 } );
228
229 return blank;
230 },
231 updateBlank( e ) {
232 const $el = $( e.target ),
233 id = $el.attr( 'id' ),
234 $blank = this.$editor.find( '#' + id );
235 $blank.html( e.target.value );
236 this.updateAnswer();
237 },
238 removeBlank( e, id ) {
239 e.preventDefault();
240 this.removeBlankById( id );
241 this.updateAll();
242 },
243 removeBlankById( id ) {
244 const $blank = this.$editor.find( '.fib-blank#fib-blank-' + id );
245 $blank.replaceWith( $blank.html() );
246 },
247 updateAll() {
248 this.answer.title = this.updateBlanks();
249 this.updateAnswer();
250 },
251 insertBlank() {
252 if ( ! this.canInsertNewBlank ) {
253 return;
254 }
255
256 const $content = $( this.$el ).find( '.content-editable' ),
257 content = $content.html(),
258 selectedText = FIB.getSelectedText(),
259 selectionRange = FIB.getSelectionRange(),
260 $blank = this.createBlank( selectedText ),
261 nodeValue = selectionRange.anchorNode.nodeValue,
262 x = selectionRange.anchorOffset,
263 y = selectionRange.focusOffset;
264 startRange = x < y ? x : y;
265 endRange = startRange == x ? y : x;
266
267 selectionRange.anchorNode.nodeValue = nodeValue.substr( 0, startRange );
268 $( $blank ).insertAfter( selectionRange.anchorNode );
269 $( FIB.createTextNode( nodeValue.substr( endRange ) ) ).insertAfter( $blank );
270
271 const $blanks = $content.find( '.fib-blank' );
272 $blanks.each( function( i, el ) {
273 const $blank = $( this );
274 if ( $blank.parent().is( 'b' ) ) {
275 const $p = $blank.parent();
276 $p.replaceWith( $p.html() );
277 }
278 $blank.attr( 'data-index', i + 1 );
279 } );
280
281 this.parseBlanks( $content.html() );
282 this.updateAnswer();
283 },
284 clearContent() {
285 this.$editor.html( '' );
286 this.updateAnswer();
287 this.canInsertNewBlank = false;
288 },
289 createBlank( content, id ) {
290 if ( ! id ) {
291 id = LP.uniqueId();
292 }
293 return $( '<b class="fib-blank" id="fib-blank-' + id + '" data-id="' + id + '"> ' + content + '</b>' );
294 },
295 clearBlanks() {
296 if ( ! confirm( $store.getters.i18n.confirm_remove_blanks ) ) {
297 return;
298 }
299
300 for ( const i in this.blanks ) {
301 this.removeBlankById( this.blanks[ i ].id );
302 }
303 this.updateAll();
304 },
305 canInsertBlank() {
306 const $content = $( this.$el ).find( '.content-editable' ),
307 content = $content.html(),
308 selectedText = FIB.getSelectedText(),
309 selectionRange = FIB.getSelectionRange();
310 this.canInsertNewBlank = selectedText.length && ! FIB.isContainHtml( selectionRange.anchorNode );
311 },
312 getBlanksForDB() {
313 const blanks = {};
314 for ( let i = 0, n = this.blanks.length; i < n; i++ ) {
315 const id = this.blanks[ i ].id.replace( 'fib-blank-', '' );
316 blanks[ id ] = JSON.parse( JSON.stringify( this.blanks[ i ] ) );
317 blanks[ id ].id = id;
318 }
319 return blanks;
320 },
321 toggleOptions( e, id ) {
322 e.preventDefault();
323 const that = this;
324 $( e.target ).closest( '.fib-blank' ).find( '.blank-options ul' ).slideToggle( function() {
325 that.setBlankProp( id, 'open', ! $( this ).is( ':hidden' ) );
326 } );
327 },
328 setBlankProp( id, prop, value ) {
329 for ( const i in this.blanks ) {
330 if ( this.blanks[ i ].id == id ) {
331 if ( $.isPlainObject( prop ) ) {
332 for ( const p in prop ) {
333 this.$set( this.blanks[ i ], p, prop[ p ] );
334 }
335 } else {
336 this.$set( this.blanks[ i ], prop, value );
337 }
338
339 break;
340 }
341 }
342 this.updateAnswer();
343 },
344 },
345 } );
346 } );
347 </script>
348