Issues (1892)

public/main/exercise/overview.php (1 issue)

Labels
Severity
1
<?php
2
3
/* For licensing terms, see /license.txt */
4
5
use Chamilo\CoreBundle\Enums\ActionIcon;
6
use Chamilo\CoreBundle\Framework\Container;
7
8
/**
9
 * Exercise preview.
10
 *
11
 * @author Julio Montoya <[email protected]>
12
 */
13
require_once __DIR__.'/../inc/global.inc.php';
14
$current_course_tool = TOOL_QUIZ;
15
Exercise::cleanSessionVariables();
16
$this_section = SECTION_COURSES;
17
18
//$js = '<script>'.api_get_language_translate_html().'</script>';
19
//$htmlHeadXtra[] = $js;
20
21
// Notice for unauthorized people.
22
api_protect_course_script(true);
23
$courseId = isset($_REQUEST['cid']) ? (int) $_REQUEST['cid'] : api_get_course_int_id();
24
$sessionId = isset($_REQUEST['sid']) ? (int) $_REQUEST['sid'] : api_get_session_id();
25
$courseInfo = api_get_course_info_by_id($courseId);
26
$courseCode = $courseInfo['code'];
27
$exercise_id = isset($_REQUEST['exerciseId']) ? (int) $_REQUEST['exerciseId'] : 0;
28
29
$objExercise = new Exercise($courseId);
30
$result = $objExercise->read($exercise_id, true);
31
32
if (!$result) {
33
    api_not_allowed(true);
34
}
35
36
if (Container::getPluginHelper()->isPluginEnabled('Positioning')) {
37
    $plugin = Positioning::create();
38
    if ($plugin->blockFinalExercise(api_get_user_id(), $exercise_id, $courseId, $sessionId)) {
39
        api_not_allowed(true);
40
    }
41
}
42
43
$learnpath_id = isset($_REQUEST['learnpath_id']) ? (int) $_REQUEST['learnpath_id'] : null;
44
$learnpath_item_id = isset($_REQUEST['learnpath_item_id']) ? (int) $_REQUEST['learnpath_item_id'] : null;
45
$learnpathItemViewId = isset($_REQUEST['learnpath_item_view_id']) ? (int) $_REQUEST['learnpath_item_view_id'] : null;
46
$origin = api_get_origin();
47
48
$logInfo = [
49
    'tool' => TOOL_QUIZ,
50
    'tool_id' => $exercise_id,
51
    'action' => isset($_REQUEST['learnpath_id']) ? 'learnpath_id' : '',
52
    'action_details' => isset($_REQUEST['learnpath_id']) ? (int) $_REQUEST['learnpath_id'] : '',
53
];
54
Event::registerLog($logInfo);
55
56
$interbreadcrumb[] = [
57
    'url' => 'exercise.php?'.api_get_cidreq(),
58
    'name' => get_lang('Tests'),
59
];
60
$interbreadcrumb[] = ['url' => '#', 'name' => $objExercise->selectTitle(true)];
61
62
$time_control = false;
63
$clock_expired_time = ExerciseLib::get_session_time_control_key($objExercise->id, $learnpath_id, $learnpath_item_id);
64
65
if (0 != $objExercise->expired_time && !empty($clock_expired_time)) {
66
    $time_control = true;
67
}
68
69
$htmlHeadXtra[] = api_get_build_js('legacy_exercise.js');
70
if ($time_control) {
71
    // Get time left for expiring time
72
    $time_left = api_strtotime($clock_expired_time->format('Y-m-d H:i:s', 'UTC') - time();
0 ignored issues
show
A parse error occurred: Syntax error, unexpected ';', expecting ',' or ')' on line 72 at column 89
Loading history...
73
    /*$htmlHeadXtra[] = api_get_css(api_get_path(WEB_LIBRARY_PATH).'javascript/epiclock/stylesheet/jquery.epiclock.css');
74
    $htmlHeadXtra[] = api_get_css(api_get_path(WEB_LIBRARY_PATH).'javascript/epiclock/renderers/minute/epiclock.minute.css');
75
    $htmlHeadXtra[] = api_get_js('epiclock/javascript/jquery.dateformat.min.js');
76
    $htmlHeadXtra[] = api_get_js('epiclock/javascript/jquery.epiclock.min.js');
77
    $htmlHeadXtra[] = api_get_js('epiclock/renderers/minute/epiclock.minute.js');*/
78
    $htmlHeadXtra[] = $objExercise->showTimeControlJS($time_left);
79
}
80
81
if (!in_array($origin, ['learnpath', 'embeddable', 'mobileapp'])) {
82
    SessionManager::addFlashSessionReadOnly();
83
    Display::display_header();
84
} else {
85
    $htmlHeadXtra[] = '
86
    <style>
87
    body { background: none;}
88
    </style>
89
    ';
90
    Display::display_reduced_header();
91
}
92
93
if ('mobileapp' === $origin) {
94
    $actions = '<a href="javascript:window.history.go(-1);">'.
95
        Display::getMdiIcon(ActionIcon::BACK, 'ch-tool-icon', null, ICON_SIZE_MEDIUM, get_lang('Go back to the questions list')).'</a>';
96
    echo Display::toolbarAction('toolbar', [$actions]);
97
}
98
99
$html = '';
100
$message = '';
101
$html .= '<div class="exercise-overview">';
102
$is_allowed_to_edit = api_is_allowed_to_edit(null, true);
103
$editLink = '';
104
if ($is_allowed_to_edit) {
105
    if ($objExercise->sessionId == $sessionId) {
106
        $editLink = Display::url(
107
            Display::getMdiIcon(ActionIcon::EDIT, 'ch-tool-icon', null, ICON_SIZE_SMALL, get_lang('Edit')),
108
            api_get_path(WEB_CODE_PATH).'exercise/admin.php?'.api_get_cidreq().'&exerciseId='.$objExercise->id
109
        );
110
    }
111
    $editLink .= Display::url(
112
        Display::getMdiIcon('chart-box', 'ch-tool-icon', null, ICON_SIZE_SMALL, get_lang('Results and feedback')),
113
        api_get_path(WEB_CODE_PATH).'exercise/exercise_report.php?'.api_get_cidreq().'&exerciseId='.$objExercise->id,
114
        ['title' => get_lang('Results and feedback')]
115
    );
116
}
117
118
$iconExercise = Display::getMdiIcon('order-bool-ascending-variant', 'ch-tool-icon-gradient', null, ICON_SIZE_MEDIUM, get_lang('Test'));
119
120
// Exercise name.
121
if ('true' === api_get_setting('editor.save_titles_as_html')) {
122
    $html .= Display::div(
123
        $objExercise->get_formated_title().PHP_EOL.$editLink
124
    );
125
} else {
126
    $html .= Display::page_header(
127
        $iconExercise.PHP_EOL.$objExercise->selectTitle().PHP_EOL.$editLink
128
    );
129
}
130
131
// Exercise description.
132
if (!empty($objExercise->description)) {
133
    $html .= Display::div($objExercise->description, ['class' => 'exercise_description wysiwyg']);
134
}
135
136
$extra_params = '';
137
if (isset($_GET['preview'])) {
138
    $extra_params = '&preview=1';
139
}
140
141
$exercise_stat_info = $objExercise->get_stat_track_exercise_info(
142
    $learnpath_id,
143
    $learnpath_item_id,
144
    0
145
);
146
147
//1. Check if this is a new attempt or a previous
148
$label = get_lang('Start test');
149
if ($time_control && !empty($clock_expired_time) || isset($exercise_stat_info['exe_id'])) {
150
    $label = get_lang('Proceed with the test');
151
}
152
153
if (isset($exercise_stat_info['exe_id'])) {
154
    $message = Display::return_message(get_lang('You have tried to resolve this exercise earlier'));
155
}
156
157
// 2. Exercise button
158
// Notice we not add there the lp_item_view_id because is not already generated
159
$exercise_url = api_get_path(WEB_CODE_PATH).'exercise/exercise_submit.php?'.
160
    api_get_cidreq().'&exerciseId='.$objExercise->id.'&learnpath_id='.$learnpath_id.'&learnpath_item_id='.$learnpath_item_id.'&learnpath_item_view_id='.$learnpathItemViewId.$extra_params;
161
$exercise_url_button = Display::url(
162
    $label,
163
    $exercise_url,
164
    ['class' => 'btn btn--success btn-large']
165
);
166
167
$btnCheck = '';
168
$quizCheckButtonEnabled = ('true' === api_get_setting('exercise.quiz_check_button_enable'));
169
if ($quizCheckButtonEnabled) {
170
    $btnCheck = Display::button(
171
            'quiz_check_request_button',
172
            Display::getMdiIcon('loading', 'animate-spin hidden').' '.get_lang('Test your browser'),
173
            [
174
                'type' => 'button',
175
                'role' => 'button',
176
                'id' => 'quiz-check-request-button',
177
                'class' => 'btn btn--plain',
178
                'data-loading-text' => get_lang('Loading'),
179
                'autocomplete' => 'off',
180
            ]
181
        ).PHP_EOL.'<strong id="quiz-check-request-text"></strong>';
182
}
183
184
// 3. Checking visibility of the exercise (overwrites the exercise button).
185
$visible_return = $objExercise->is_visible(
186
    $learnpath_id,
187
    $learnpath_item_id,
188
    null,
189
    true
190
);
191
192
// Exercise is not visible remove the button
193
if (false == $visible_return['value']) {
194
    if ($is_allowed_to_edit) {
195
        $message = Display::return_message(get_lang('This item is invisible for learner but you have access as teacher.'), 'warning');
196
    } else {
197
        $message = $visible_return['message'];
198
        $exercise_url_button = null;
199
    }
200
}
201
202
if (!api_is_allowed_to_session_edit()) {
203
    $exercise_url_button = null;
204
}
205
206
$attempts = Event::getExerciseResultsByUser(
207
    api_get_user_id(),
208
    $objExercise->id,
209
    $courseId,
210
    $sessionId,
211
    $learnpath_id,
212
    $learnpath_item_id,
213
    'desc'
214
);
215
$counter = count($attempts);
216
$my_attempt_array = [];
217
$table_content = '';
218
219
/* Make a special case for IE, which doesn't seem to be able to handle the
220
 * results popup -> send it to the full results page */
221
222
$url_suffix = '';
223
$btn_class = ' ';
224
$blockShowAnswers = false;
225
if (in_array(
226
    $objExercise->results_disabled,
227
    [
228
        RESULT_DISABLE_SHOW_SCORE_ATTEMPT_SHOW_ANSWERS_LAST_ATTEMPT,
229
        //RESULT_DISABLE_SHOW_SCORE_ATTEMPT_SHOW_ANSWERS_LAST_ATTEMPT_NO_FEEDBACK,
230
        RESULT_DISABLE_DONT_SHOW_SCORE_ONLY_IF_USER_FINISHES_ATTEMPTS_SHOW_ALWAYS_FEEDBACK,
231
    ])
232
) {
233
    if (count($attempts) < $objExercise->attempts) {
234
        $blockShowAnswers = true;
235
    }
236
}
237
238
$certificateBlock = '';
239
240
if (!empty($attempts)) {
241
    $i = $counter;
242
    foreach ($attempts as $attempt_result) {
243
        if (empty($certificateBlock)) {
244
            $certificateBlock = ExerciseLib::generateAndShowCertificateBlock(
245
                $attempt_result['score'],
246
                $attempt_result['max_score'],
247
                $objExercise,
248
                $attempt_result['exe_user_id'],
249
                $courseId,
250
                $sessionId
251
            );
252
        }
253
254
        $score = ExerciseLib::show_score($attempt_result['score'], $attempt_result['max_score']);
255
        $attempt_url = api_get_path(WEB_CODE_PATH).'exercise/result.php?';
256
        $attempt_url .= api_get_cidreq().'&show_headers=1&';
257
        $attempt_url .= http_build_query(['id' => $attempt_result['exe_id']]);
258
        $attempt_url .= $url_suffix;
259
260
        $attempt_link = Display::url(
261
            get_lang('Show'),
262
            $attempt_url,
263
            [
264
                'class' => $btn_class.'btn btn--plain',
265
                'data-title' => get_lang('Show'),
266
                'data-size' => 'lg',
267
            ]
268
        );
269
270
        $teacher_revised = Display::label(get_lang('Validated'), 'success');
271
        if (0 == $attempt_result['attempt_revised']) {
272
            $teacher_revised = Display::label(get_lang('Not validated'), 'info');
273
        }
274
        $row = [
275
            'count' => $i,
276
            'date' => api_convert_and_format_date($attempt_result['start_date'], DATE_TIME_FORMAT_LONG),
277
            'userIp' => $attempt_result['user_ip'],
278
        ];
279
        $attempt_link .= PHP_EOL.$teacher_revised;
280
281
        if (in_array(
282
            $objExercise->results_disabled,
283
            [
284
                RESULT_DISABLE_SHOW_SCORE_AND_EXPECTED_ANSWERS,
285
                RESULT_DISABLE_SHOW_SCORE_AND_EXPECTED_ANSWERS_AND_RANKING,
286
                RESULT_DISABLE_SHOW_SCORE_ONLY,
287
                RESULT_DISABLE_SHOW_FINAL_SCORE_ONLY_WITH_CATEGORIES,
288
                RESULT_DISABLE_SHOW_SCORE_ATTEMPT_SHOW_ANSWERS_LAST_ATTEMPT,
289
                RESULT_DISABLE_SHOW_SCORE_ATTEMPT_SHOW_ANSWERS_LAST_ATTEMPT_NO_FEEDBACK,
290
                RESULT_DISABLE_DONT_SHOW_SCORE_ONLY_IF_USER_FINISHES_ATTEMPTS_SHOW_ALWAYS_FEEDBACK,
291
                RESULT_DISABLE_RANKING,
292
                RESULT_DISABLE_SHOW_ONLY_IN_CORRECT_ANSWER,
293
            ]
294
        )) {
295
            $row['result'] = $score;
296
        }
297
298
        if (in_array(
299
            $objExercise->results_disabled,
300
            [
301
                RESULT_DISABLE_SHOW_SCORE_AND_EXPECTED_ANSWERS,
302
                RESULT_DISABLE_SHOW_SCORE_AND_EXPECTED_ANSWERS_AND_RANKING,
303
                RESULT_DISABLE_SHOW_FINAL_SCORE_ONLY_WITH_CATEGORIES,
304
                RESULT_DISABLE_SHOW_SCORE_ATTEMPT_SHOW_ANSWERS_LAST_ATTEMPT,
305
                RESULT_DISABLE_SHOW_SCORE_ATTEMPT_SHOW_ANSWERS_LAST_ATTEMPT_NO_FEEDBACK,
306
                RESULT_DISABLE_DONT_SHOW_SCORE_ONLY_IF_USER_FINISHES_ATTEMPTS_SHOW_ALWAYS_FEEDBACK,
307
                RESULT_DISABLE_RANKING,
308
                RESULT_DISABLE_SHOW_ONLY_IN_CORRECT_ANSWER,
309
            ]
310
        ) || (
311
            RESULT_DISABLE_SHOW_SCORE_ONLY == $objExercise->results_disabled &&
312
            EXERCISE_FEEDBACK_TYPE_END == $objExercise->getFeedbackType()
313
        )
314
        ) {
315
            if ($blockShowAnswers &&
316
                RESULT_DISABLE_DONT_SHOW_SCORE_ONLY_IF_USER_FINISHES_ATTEMPTS_SHOW_ALWAYS_FEEDBACK != $objExercise->results_disabled
317
            ) {
318
                $attempt_link = '';
319
            }
320
            if (true == $blockShowAnswers &&
321
                RESULT_DISABLE_DONT_SHOW_SCORE_ONLY_IF_USER_FINISHES_ATTEMPTS_SHOW_ALWAYS_FEEDBACK == $objExercise->results_disabled
322
            ) {
323
                if (isset($row['result'])) {
324
                    unset($row['result']);
325
                }
326
            }
327
328
            if (!empty($objExercise->getResultAccess())) {
329
                if (!$objExercise->hasResultsAccess($attempt_result)) {
330
                    $attempt_link = '';
331
                }
332
            }
333
            $row['attempt_link'] = $attempt_link;
334
        }
335
        $my_attempt_array[] = $row;
336
        $i--;
337
    }
338
339
    $header_names = [];
340
    $table = new HTML_Table(['class' => 'table table-striped table-hover']);
341
    // Hiding score and answer.
342
    switch ($objExercise->results_disabled) {
343
        case RESULT_DISABLE_DONT_SHOW_SCORE_ONLY_IF_USER_FINISHES_ATTEMPTS_SHOW_ALWAYS_FEEDBACK:
344
            if ($blockShowAnswers) {
345
                $header_names = [get_lang('Attempt'), get_lang('Start Date'), get_lang('IP'), get_lang('Details')];
346
            } else {
347
                $header_names = [
348
                    get_lang('Attempt'),
349
                    get_lang('Start Date'),
350
                    get_lang('IP'),
351
                    get_lang('Score'),
352
                    get_lang('Details'),
353
                ];
354
            }
355
356
            break;
357
        case RESULT_DISABLE_SHOW_SCORE_ATTEMPT_SHOW_ANSWERS_LAST_ATTEMPT_NO_FEEDBACK:
358
        case RESULT_DISABLE_SHOW_SCORE_ATTEMPT_SHOW_ANSWERS_LAST_ATTEMPT:
359
            if ($blockShowAnswers) {
360
                $header_names = [get_lang('Attempt'), get_lang('Start Date'), get_lang('IP'), get_lang('Score')];
361
            } else {
362
                $header_names = [
363
                    get_lang('Attempt'),
364
                    get_lang('Start Date'),
365
                    get_lang('IP'),
366
                    get_lang('Score'),
367
                    get_lang('Details'),
368
                ];
369
            }
370
371
            break;
372
        case RESULT_DISABLE_SHOW_SCORE_AND_EXPECTED_ANSWERS:
373
        case RESULT_DISABLE_SHOW_SCORE_AND_EXPECTED_ANSWERS_AND_RANKING:
374
        case RESULT_DISABLE_SHOW_FINAL_SCORE_ONLY_WITH_CATEGORIES:
375
        case RESULT_DISABLE_RANKING:
376
        case RESULT_DISABLE_SHOW_ONLY_IN_CORRECT_ANSWER:
377
            $header_names = [
378
                get_lang('Attempt'),
379
                get_lang('Start Date'),
380
                get_lang('IP'),
381
                get_lang('Score'),
382
                get_lang('Details'),
383
            ];
384
385
            break;
386
        case RESULT_DISABLE_NO_SCORE_AND_EXPECTED_ANSWERS:
387
            $header_names = [get_lang('Attempt'), get_lang('Start Date'), get_lang('IP')];
388
389
            break;
390
        case RESULT_DISABLE_SHOW_SCORE_ONLY:
391
            if (EXERCISE_FEEDBACK_TYPE_END != $objExercise->getFeedbackType()) {
392
                $header_names = [get_lang('Attempt'), get_lang('Start Date'), get_lang('IP'), get_lang('Score')];
393
            } else {
394
                $header_names = [
395
                    get_lang('Attempt'),
396
                    get_lang('Start Date'),
397
                    get_lang('IP'),
398
                    get_lang('Score'),
399
                    get_lang('Details'),
400
                ];
401
            }
402
403
            break;
404
    }
405
    $column = 0;
406
    foreach ($header_names as $item) {
407
        $table->setHeaderContents(0, $column, $item);
408
        $column++;
409
    }
410
    $row = 1;
411
    if (!empty($my_attempt_array)) {
412
        foreach ($my_attempt_array as $data) {
413
            $column = 0;
414
            $table->setCellContents($row, $column, $data);
415
            $table->setRowAttributes($row, null, true);
416
            $column++;
417
            $row++;
418
        }
419
    }
420
    $table_content = $table->toHtml();
421
}
422
423
$selectAttempts = $objExercise->selectAttempts();
424
if ($selectAttempts) {
425
    $attempt_message = get_lang('Attempts').' '.$counter.' / '.$selectAttempts;
426
    if ($counter == $selectAttempts) {
427
        $attempt_message = Display::return_message($attempt_message, 'error');
428
    } else {
429
        $attempt_message = Display::return_message($attempt_message, 'info');
430
    }
431
    if (true == $visible_return['value']) {
432
        $message .= $attempt_message;
433
    }
434
}
435
436
if ($time_control) {
437
    $html .= $objExercise->returnTimeLeftDiv();
438
}
439
440
$html .= $message;
441
442
$disable = ('true' === api_get_setting('exercise.exercises_disable_new_attempts'));
443
if ($disable && empty($exercise_stat_info)) {
444
    $exercise_url_button = Display::return_message(get_lang('The portal do not allowed to start new test for the moment, please come back later.'));
445
}
446
447
$isLimitReached = ExerciseLib::isQuestionsLimitPerDayReached(
448
    api_get_user_id(),
449
    count($objExercise->get_validated_question_list()),
450
    $courseId,
451
    $sessionId
452
);
453
454
if (!empty($exercise_url_button) && !$isLimitReached) {
455
    if ($quizCheckButtonEnabled) {
456
        $html .= Display::div(
457
            $btnCheck,
458
            ['class' => 'exercise_overview_options']
459
        );
460
        $html .= '<br>';
461
    }
462
463
    $html .= Display::div(
464
        Display::div(
465
            $exercise_url_button,
466
            ['class' => 'exercise_overview_options']
467
        ),
468
        ['class' => 'options']
469
    );
470
}
471
472
if ($isLimitReached) {
473
    $maxQuestionsAnswered = (int) api_get_course_setting('quiz_question_limit_per_day');
474
475
    $html .= Display::return_message(
476
        sprintf(get_lang('Sorry, you have reached the maximum number of questions (%s) for the day. Please try again tomorrow.'), $maxQuestionsAnswered),
477
        'warning',
478
        false
479
    );
480
}
481
482
$html .= Display::tag(
483
    'div',
484
    $table_content,
485
    ['class' => 'table-responsive']
486
);
487
$html .= '</div>';
488
489
if ($certificateBlock) {
490
    $html .= PHP_EOL.$certificateBlock;
491
}
492
493
if ($quizCheckButtonEnabled) {
494
    $quizCheckRequestUrl = api_get_path(WEB_AJAX_PATH).'exercise.ajax.php?'.api_get_cidreq().'&a=browser_test';
495
    $params = http_build_query(
496
        [
497
            'exe_id' => 1,
498
            'exerciseId' => $exercise_id,
499
            'learnpath_id' => $learnpath_id,
500
            'learnpath_item_id' => $learnpath_item_id,
501
            'learnpath_item_view_id' => $learnpathItemViewId,
502
            'reminder' => '0',
503
            'type' => 'simple',
504
            'question_id' => 23,
505
            'choice[23]' => 45,
506
        ]
507
    ).'&'.api_get_cidreq();
508
509
    $html .= "<script>
510
        $(function () {
511
            var btnTest = $('#quiz-check-request-button'),
512
                iconBtnTest = btnTest.children('.animate-spin');
513
514
            btnTest.on('click', function (e) {
515
                e.preventDefault();
516
517
                btnTest.prop('disabled', true).removeClass('btn--success btn--danger').addClass('btn--plain');
518
                iconBtnTest.removeClass('hidden');
519
520
                var txtResult = $('#quiz-check-request-text').removeClass('text-success text-error').hide();
521
522
                $
523
                    .when(
524
                        $.ajax({
525
                            url: '$quizCheckRequestUrl',
526
                            type: 'post',
527
                            data: '$params'
528
                        }),
529
                        $.ajax({
530
                            url: '$quizCheckRequestUrl',
531
                            type: 'post',
532
                            data: '$params&sleep=1'
533
                        })
534
                    )
535
                    .then(
536
                        function (xhr1, xhr2) {
537
                            var xhr1IsOk = !!xhr1 && xhr1[1] === 'success' && !!xhr1[0] && 'ok' === xhr1[0];
538
                            var xhr2IsOk = !!xhr2 && xhr2[1] === 'success' && !!xhr2[0] && 'ok' === xhr2[0];
539
540
                            if (xhr1IsOk && xhr2IsOk) {
541
                                btnTest.removeClass('btn--plain btn--danger').addClass('btn--success');
542
                                txtResult.text(\"".get_lang('Your browser has been verified. You can safely proceed.')."\").addClass('text-success').show();
543
                            } else {
544
                                btnTest.removeClass('btn--plain btn--success').addClass('btn--danger');
545
                                txtResult.text(\"".get_lang('Your browser could not be verified. Please try again, or try another browser or device before starting your test.')."\").addClass('text-error').show();
546
                            }
547
                        },
548
                        function () {
549
                            txtResult.text(\"".get_lang('Your browser could not be verified. Please try again, or try another browser or device before starting your test.')."\").addClass('text-error').show();
550
                            btnTest.removeClass('btn--plain btn--success').addClass('btn--danger');
551
                        }
552
                    )
553
                    .always(function () {
554
                        btnTest.prop('disabled', false);
555
                        iconBtnTest.addClass('hidden');
556
                    });
557
            });
558
        });
559
        </script>";
560
}
561
562
echo $html;
563
564
Display::display_footer();
565