PluginProbe
VikBooking Hotel Booking Engine & PMS / 1.6.5
VikBooking Hotel Booking Engine & PMS v1.6.5
1.8.16 1.8.15 1.8.14 1.8.13 1.8.12 1.8.11 1.8.10 1.8.9 1.8.6 1.8.7 1.8.8 trunk 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.7 1.6.8 1.6.9 1.7.0 1.7.1 1.7.2 All 37 releases
vikbooking / admin / views / config / tmpl / default_seven.php

default_seven.php in VikBooking Hotel Booking Engine & PMS 1.6.5, at admin/views/config/tmpl/default_seven.php

922 lines 36.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * @package VikBooking
4 * @subpackage com_vikbooking
5 * @author Alessio Gaggii - e4j - Extensionsforjoomla.com
6 * @copyright Copyright (C) 2018 e4j - Extensionsforjoomla.com. All rights reserved.
7 * @license GNU General Public License version 2 or later; see LICENSE
8 * @link https://vikwp.com
9 */
10
11 defined('ABSPATH') or die('No script kiddies please!');
12
13 $dbo = JFactory::getDbo();
14 $app = JFactory::getApplication();
15 $vbo_app = VikBooking::getVboApplication();
16
17 VikBooking::getConditionalRulesInstance(true);
18 $tpl_names = VikBookingHelperConditionalRules::getTemplateFilesNames();
19 $tpl_contents = VikBookingHelperConditionalRules::getTemplateFilesContents();
20
21 $lim = $app->getUserStateFromRequest("com_vikbooking.limit", 'limit', $app->get('list_limit'), 'int');
22 $lim0 = VikRequest::getVar('limitstart', 0, '', 'int');
23
24 // load lang vars for JS
25 JText::script('VBDELCONFIRM');
26 JText::script('VBOCONFIGEDITTMPLFILE');
27 JText::script('VBO_CONDTEXT_TAG_ADD_HELP');
28 JText::script('VBO_CONDTEXT_TAG_RM_HELP');
29 JText::script('VBO_CSS_EDITING_HELP');
30 JText::script('VBO_INSPECTOR_START');
31 JText::script('VBO_EDITTPL_FATALERROR');
32
33 $navbut = "";
34
35 $q = "SELECT SQL_CALC_FOUND_ROWS * FROM `#__vikbooking_condtexts` ORDER BY `#__vikbooking_condtexts`.`lastupd` DESC";
36 $dbo->setQuery($q, $lim0, $lim);
37 $rows = $dbo->loadAssocList();
38 if ($rows) {
39 $dbo->setQuery('SELECT FOUND_ROWS();');
40 jimport('joomla.html.pagination');
41 $pageNav = new JPagination($dbo->loadResult(), $lim0, $lim);
42 $navbut = "<table align=\"center\"><tr><td>".$pageNav->getPagesLinks()."</td></tr></table>";
43 }
44
45 ?>
46 <div class="vbo-config-maintab-top">
47 <fieldset class="adminform vbo-config-fieldset-large">
48 <div class="vbo-params-wrap">
49 <legend class="adminlegend"><?php echo JText::translate('VBO_COND_TEXT_RULES'); ?></legend>
50 <div class="vbo-params-container">
51 <div class="vbo-param-container">
52 <div class="vbo-param-setting">
53 <a href="index.php?option=com_vikbooking&task=newcondtext" class="btn vbo-config-btn"><?php VikBookingIcons::e('plus-circle'); ?> <?php echo JText::translate('VBO_NEW_COND_TEXT'); ?></a>
54 </div>
55 </div>
56 <div class="vbo-param-container">
57 <div class="vbo-param-setting">
58 <div class="table-responsive vbo-list-table-rounded">
59 <table cellpadding="4" cellspacing="0" border="0" width="100%" class="table table-striped vbo-list-table">
60 <thead>
61 <tr>
62 <th class="title left" width="200"><?php echo JText::translate( 'VBO_CONDTEXT_NAME' ); ?></th>
63 <th class="title left vbo-white-break" width="200"><?php echo JText::translate( 'VBO_CONDTEXT_TKN' ); ?></th>
64 <th class="title center vbo-white-break" width="100"><?php echo JText::translate( 'VBO_WIDGETS_LASTUPD' ); ?></th>
65 <th class="title center vbo-white-break" width="300"><?php echo JText::translate( 'VBO_TEMPLATE_FILES' ); ?></th>
66 <th class="title center" width="100">&nbsp;</th>
67 </tr>
68 </thead>
69 <?php
70 $k = 0;
71 $i = 0;
72 for ($i = 0, $n = count($rows); $i < $n; $i++) {
73 $row = $rows[$i];
74 ?>
75 <tr class="row<?php echo $k; ?>">
76 <td>
77 <a href="index.php?option=com_vikbooking&amp;task=editcondtext&amp;cid[]=<?php echo $row['id']; ?>"><?php echo $row['name']; ?></a>
78 </td>
79 <td class="vbo-white-break">
80 <span class="vbo-condtext-token-full"><?php echo $row['token']; ?></span>
81 </td>
82 <td class="center vbo-white-break"><?php echo $row['lastupd']; ?></td>
83 <td class="center vbo-white-break">
84 <?php
85 foreach ($tpl_names as $file => $name) {
86 $tag_used = VikBookingHelperConditionalRules::isTagInContent($row['token'], $tpl_contents[$file]);
87 $btn_icon = $tag_used ? VikBookingIcons::i('check-circle') : VikBookingIcons::i('plus');
88 $btn_classes = array(
89 'btn',
90 'vbo-condtext-tmpl-status',
91 );
92 if ($tag_used) {
93 array_push($btn_classes, 'btn-success');
94 array_push($btn_classes, 'vbo-condtext-intmpl');
95 } else {
96 array_push($btn_classes, 'btn-secondary');
97 array_push($btn_classes, 'vbo-condtext-notintmpl');
98 }
99 ?>
100 <button type="button" class="<?php echo implode(' ', $btn_classes); ?>" data-inspectfile="<?php echo $file; ?>" data-specialtag="<?php echo $row['token']; ?>"><i class="<?php echo $btn_icon; ?>"></i> <?php echo $name; ?></button>
101 <?php
102 }
103 ?>
104 </td>
105 <td class="center">
106 <a href="index.php?option=com_vikbooking&amp;task=removecondtext&amp;cid[]=<?php echo $row['id']; ?>" class="btn btn-danger" onclick="return confirm(Joomla.JText._('VBDELCONFIRM'));"><?php VikBookingIcons::e('trash'); ?> <?php echo JText::translate('VBMAINCRONDEL'); ?></a>
107 </td>
108 </tr>
109 <?php
110 $k = 1 - $k;
111 }
112 ?>
113 </table>
114 <?php echo $navbut; ?>
115 </div>
116 </div>
117 </div>
118 </div>
119 </div>
120 </fieldset>
121 <fieldset class="adminform vbo-config-fieldset-small">
122 <div class="vbo-params-wrap">
123 <legend class="adminlegend"><?php echo JText::translate('VBOCONFIGEDITTMPLFILE'); ?></legend>
124 <div class="vbo-params-container">
125 <div class="vbo-param-container">
126 <div class="vbo-param-label"><?php echo JText::translate('VBOCONFIGEMAILTEMPLATE'); ?></div>
127 <div class="vbo-param-setting">
128 <button type="button" class="btn vbo-inspector-btn" title="<?php echo addslashes(JText::translate('VBO_INSPECTOR_START')); ?>" data-inspectfile="email_tmpl.php"><?php VikBookingIcons::e('paint-brush'); ?></button>
129 </div>
130 </div>
131 <div class="vbo-param-container">
132 <div class="vbo-param-label"><?php echo JText::translate('VBOCONFIGINVOICETEMPLATE'); ?></div>
133 <div class="vbo-param-setting">
134 <button type="button" class="btn vbo-inspector-btn" title="<?php echo addslashes(JText::translate('VBO_INSPECTOR_START')); ?>" data-inspectfile="invoice_tmpl.php"><?php VikBookingIcons::e('paint-brush'); ?></button>
135 </div>
136 </div>
137 <div class="vbo-param-container">
138 <div class="vbo-param-label"><?php echo JText::translate('VBOCONFIGCHECKINTEMPLATE'); ?></div>
139 <div class="vbo-param-setting">
140 <button type="button" class="btn vbo-inspector-btn" title="<?php echo addslashes(JText::translate('VBO_INSPECTOR_START')); ?>" data-inspectfile="checkin_tmpl.php"><?php VikBookingIcons::e('paint-brush'); ?></button>
141 </div>
142 </div>
143 <div class="vbo-param-container">
144 <div class="vbo-param-label"><?php echo JText::translate('VBO_CONT_WRAPPER'); ?></div>
145 <div class="vbo-param-setting">
146 <button type="button" class="btn vbo-contwrapper-btn" onclick="jQuery('.vbo-contwrapper-edit').toggle();"><?php VikBookingIcons::e('code'); ?></button>
147 </div>
148 </div>
149 <div class="vbo-param-container vbo-param-nested vbo-contwrapper-edit" style="display: none;">
150 <?php
151 $cont_wrapper_opening = VBOMailParser::getWrapperLayout($opening = true);
152 $cont_wrapper_closing = VBOMailParser::getWrapperLayout($opening = false);
153 ?>
154 <div class="vbo-param-setting">
155 <textarea id="vbo-contwrapper-html" style="width: 100% !important; min-height: 250px;"><?php echo JHtml::fetch('esc_textarea', $cont_wrapper_opening . "\n\n\t\t--- " . JText::translate('VBO_TPL_TEXT') . " ---\n\n" . $cont_wrapper_closing); ?></textarea>
156 <div class="vbo-param-setting-comment"><?php echo JText::translate('VBO_CONT_WRAPPER_HELP'); ?></div>
157 </div>
158 </div>
159 <div class="vbo-param-container vbo-param-nested vbo-contwrapper-edit" style="display: none;">
160 <div class="vbo-param-setting">
161 <button id="vbo-contwrapper-save" type="button" class="btn btn-success"><?php VikBookingIcons::e('save'); ?> <?php echo JText::translate('VBSAVE'); ?></button>
162 </div>
163 </div>
164 </div>
165 </div>
166 </fieldset>
167 </div>
168
169 <div id="vbo-inspector-outer" class="vbo-config-maintab-bottom" style="display: none;">
170 <fieldset class="adminform">
171 <div class="vbo-params-wrap">
172 <legend class="adminlegend"><span id="vbo-inspector-title"></span></legend>
173 <div class="vbo-params-container">
174 <div class="vbo-param-container">
175 <div class="vbo-param-setting">
176 <div class="vbo-inspector-cmds">
177 <button id="vbo-inspector-save" type="button" class="btn btn-success" disabled><?php VikBookingIcons::e('save'); ?> <?php echo JText::translate('VBSAVE'); ?></button>
178 <button id="vbo-inspector-preview" type="button" class="btn btn-secondary" data-prew-type="" style="display: none;"><?php VikBookingIcons::e('eye'); ?> <?php echo JText::translate('VBOPREVIEW'); ?></button>
179 <button id="vbo-inspector-cancel" type="button" class="btn btn-secondary"><?php VikBookingIcons::e('times'); ?> <?php echo JText::translate('VBANNULLA'); ?></button>
180 </div>
181 </div>
182 </div>
183 <div class="vbo-param-container">
184 <div class="vbo-param-setting">
185 <p id="vbo-inspector-help" class="info notice-noicon"></p>
186 </div>
187 </div>
188 <div class="vbo-param-container vbo-inspector-css-param" style="display: none;">
189 <div class="vbo-param-label"><?php echo JText::translate('VBO_INSP_HTML_TAG'); ?></div>
190 <div class="vbo-param-setting">
191 <span id="vbo-inspector-css-tag" class="vbo-inspector-css-tag"></span>
192 </div>
193 </div>
194 <div class="vbo-param-container vbo-inspector-css-param" style="display: none;">
195 <div class="vbo-param-label"><?php echo JText::translate('VBO_INSP_CSS_FONTCOLOR'); ?></div>
196 <div class="vbo-param-setting">
197 <span class="vbo-inspector-colorpicker-wrap">
198 <span id="vbo-inspector-css-color" class="vbo-inspector-colorpicker vbo-inspector-colorpicker-trig"><?php VikBookingIcons::e('palette'); ?></span>
199 </span>
200 </div>
201 </div>
202 <div class="vbo-param-container vbo-inspector-css-param" style="display: none;">
203 <div class="vbo-param-label"><?php echo JText::translate('VBO_INSP_CSS_BACKGCOLOR'); ?></div>
204 <div class="vbo-param-setting">
205 <span class="vbo-inspector-colorpicker-wrap">
206 <span id="vbo-inspector-css-backgcolor" class="vbo-inspector-colorpicker vbo-inspector-colorpicker-trig"><?php VikBookingIcons::e('palette'); ?></span>
207 </span>
208 </div>
209 </div>
210 <div class="vbo-param-container vbo-inspector-css-param" style="display: none;">
211 <div class="vbo-param-label"><?php echo JText::translate('VBO_INSP_CSS_BORDER'); ?></div>
212 <div class="vbo-param-setting vbo-toggle-small">
213 <?php echo $vbo_app->printYesNoButtons('vbo-inspector-css-border', JText::translate('VBYES'), JText::translate('VBNO'), 0, 1, 0, 'vboToggleCSSBorderParams();'); ?>
214 </div>
215 </div>
216 <div class="vbo-param-container vbo-inspector-css-border-param" style="display: none;">
217 <div class="vbo-param-label"><?php echo JText::translate('VBO_INSP_CSS_BORDERWIDTH'); ?> (px)</div>
218 <div class="vbo-param-setting">
219 <input type="number" min="0" id="vbo-inspector-css-borderwidth" value="0" />
220 </div>
221 </div>
222 <div class="vbo-param-container vbo-inspector-css-border-param" style="display: none;">
223 <div class="vbo-param-label"><?php echo JText::translate('VBO_INSP_CSS_BORDERCOLOR'); ?></div>
224 <div class="vbo-param-setting">
225 <span class="vbo-inspector-colorpicker-wrap">
226 <span id="vbo-inspector-css-bordercolor" class="vbo-inspector-colorpicker vbo-inspector-colorpicker-trig"><?php VikBookingIcons::e('palette'); ?></span>
227 </span>
228 </div>
229 </div>
230 <div class="vbo-param-container">
231 <div class="vbo-param-setting">
232 <div class="vbo-inspector-wrap" data-inspectfile=""></div>
233 </div>
234 </div>
235 </div>
236 </div>
237 </fieldset>
238 </div>
239
240 <?php
241 foreach ($tpl_contents as $file => $content) {
242 ?>
243 <div class="vbo-tplcontent-inspector-ghost" style="display: none;" data-inspectfile="<?php echo $file; ?>">
244 <?php echo $content; ?>
245 </div>
246 <?php
247 }
248 ?>
249
250 <a class="vbo-reload-plchld-link" href="index.php?option=com_vikbooking&task=config" style="display: none;">&nbsp;</a>
251
252 <script type="text/javascript">
253 /**
254 * Define global scope vars.
255 */
256 var tpl_names = <?php echo json_encode($tpl_names); ?>;
257 var current_tag = null,
258 current_file = null,
259 current_target = null,
260 css_editing = false,
261 css_custom_classes = [],
262 vbo_back_to_tab = null;
263
264 /**
265 * Generates a unique class for the target in the CSS inspector.
266 */
267 function vboTargetUniqueClassName() {
268 var now = new Date;
269 return 'vbo-inspector-custom-' + now.getTime();
270 }
271
272 /**
273 * Adds the temporary class of the current target to the pool.
274 * Should be called when target's CSS properties have been modified.
275 * All classes in the pool may be processed via PHP for update.
276 */
277 function vboCSSTargetChanged() {
278 if (current_target === null) {
279 return false;
280 }
281 var tmpclass = current_target.data('tmpclass');
282 if (!tmpclass) {
283 return false;
284 }
285 if (css_custom_classes.indexOf(tmpclass) < 0) {
286 // push custom/temporary CSS rule
287 css_custom_classes.push(tmpclass);
288 // enable save button
289 jQuery('#vbo-inspector-save').prop('disabled', false);
290 }
291 }
292
293 /**
294 * Unbinds the hover events for the inspector.
295 */
296 function vboUnregisterInspector() {
297 jQuery('.vbo-inspector-wrap').find('*').not('center, table, thead, tbody, tr').unbind('mouseenter mouseleave');
298 }
299
300 /**
301 * Register the hover events for the inspector.
302 */
303 function vboRegisterInspector(unregister) {
304 if (unregister === true) {
305 vboUnregisterInspector();
306 }
307
308 jQuery('.vbo-inspector-wrap').find('*').not('center, table, thead, tbody, tr').hover(function() {
309 jQuery('.vbo-inspector-hover').removeClass('vbo-inspector-hover vbo-tooltip vbo-tooltip-top');
310 let current_elem = jQuery(this);
311 current_elem.addClass('vbo-inspector-hover vbo-tooltip vbo-tooltip-top').attr('data-tooltiptext', current_elem.prop('tagName'));
312 }, function() {
313 let current_elem = jQuery(this);
314 if (current_elem.parent().length && current_elem.parent().is(':hover')) {
315 current_elem.parent().addClass('vbo-inspector-hover vbo-tooltip vbo-tooltip-top').attr('data-tooltiptext', current_elem.parent().prop('tagName'));
316 }
317 current_elem.removeClass('vbo-inspector-hover vbo-tooltip vbo-tooltip-top');
318 });
319
320 jQuery('.vbo-inspector-wrap').mouseleave(function() {
321 jQuery('.vbo-inspector-hover').removeClass('vbo-inspector-hover vbo-tooltip vbo-tooltip-top');
322 });
323 }
324
325 /**
326 * Enables the CSS editing mode.
327 */
328 function vboEnableCSSEditing() {
329 css_editing = true;
330 }
331
332 /**
333 * Disables the CSS editing mode.
334 */
335 function vboDisableCSSEditing() {
336 css_editing = false;
337 // hide CSS params
338 jQuery('.vbo-inspector-css-param, .vbo-inspector-css-border-param').hide();
339 }
340
341 /**
342 * Starts the CSS inspector. Can be called also by other tabs in this page.
343 */
344 function vboStartCSSInspector(file) {
345 // when a specific file is requested, simulate the cancel action
346 if (file && jQuery('.vbo-tplcontent-inspector-ghost[data-inspectfile="' + file + '"]').length) {
347 // hide current CSS params
348 jQuery('.vbo-inspector-css-param, .vbo-inspector-css-border-param').hide();
349 // unset current target
350 current_target = null;
351 // make the list of targets with custom CSS empty
352 css_custom_classes = [];
353 // disable save button
354 jQuery('#vbo-inspector-save').prop('disabled', true);
355 // sanitize template source code from any script tag in case of malformed markup
356 jQuery('.vbo-tplcontent-inspector-ghost[data-inspectfile="' + file + '"]').find('script').remove();
357 // grab requested content and move it to the inspector wrapper
358 jQuery('.vbo-inspector-wrap').html(jQuery('.vbo-tplcontent-inspector-ghost[data-inspectfile="' + file + '"]').html()).attr('data-inspectfile', file);
359 // always hide the preview button
360 jQuery('#vbo-inspector-preview').attr('data-prew-type', '').hide();
361 // register hovering event
362 vboRegisterInspector(true);
363 }
364 if (!file && current_file !== null) {
365 // triggers after adding and saving a conditional text tag
366 file = current_file;
367 }
368 if (!tpl_names.hasOwnProperty(file)) {
369 console.error('file not found', file, tpl_names);
370 return false;
371 }
372 // turn off adding tag mode
373 current_tag = null;
374 // define global file editing
375 current_file = file;
376 // enable flag for CSS editing
377 vboEnableCSSEditing();
378 // update title
379 jQuery('#vbo-inspector-title').text(tpl_names[file] + ' - ' + Joomla.JText._('VBO_INSPECTOR_START'));
380 // update helper
381 jQuery('#vbo-inspector-help').html('<?php VikBookingIcons::e('paint-brush'); ?> ' + Joomla.JText._('VBO_CSS_EDITING_HELP')).show();
382 // display inspector outer
383 jQuery('#vbo-inspector-outer').show();
384 if (current_target !== null) {
385 // render CSS properties
386 vboRenderCSSInspector();
387 } else {
388 // animate scroll to the outer position
389 jQuery('html,body').animate({scrollTop: jQuery('#vbo-inspector-outer').offset().top - 40}, {duration: 400});
390 }
391 }
392
393 /**
394 * Displays the CSS properties of the selected target.
395 * Creates a new class identifier for the current target.
396 */
397 function vboRenderCSSInspector() {
398 if (current_target === null || !css_editing) {
399 console.error('CSS editing not available', current_target, css_editing);
400 return false;
401 }
402 // add the unique class to the target element
403 var unique_class_id = vboTargetUniqueClassName();
404 current_target.removeClass('vbo-inspector-hover').addClass(unique_class_id).data('tmpclass', unique_class_id);
405 // set current tag name
406 jQuery('#vbo-inspector-css-tag').text(current_target.prop('tagName'));
407 // set current font color
408 jQuery('#vbo-inspector-css-color').css('backgroundColor', current_target.css('color'));
409 // set current background color
410 jQuery('#vbo-inspector-css-backgcolor').css('backgroundColor', current_target.css('backgroundColor'));
411 // check if element has borders and set values
412 var elborder = current_target.css('border-left-width').match(/^([0-9.]+)/);
413 if (elborder && elborder[1] > 0) {
414 // has got a border
415 jQuery('input[name="vbo-inspector-css-border"]').prop('checked', true);
416 jQuery('.vbo-inspector-css-border-param').show();
417 jQuery('#vbo-inspector-css-borderwidth').val(elborder[1]);
418 jQuery('#vbo-inspector-css-bordercolor').css('backgroundColor', current_target.css('border-left-color'));
419 } else {
420 // has got no border
421 jQuery('input[name="vbo-inspector-css-border"]').prop('checked', false);
422 jQuery('.vbo-inspector-css-border-param').hide();
423 jQuery('#vbo-inspector-css-borderwidth').val('0');
424 // unset background completely, not just the bgcolor
425 jQuery('#vbo-inspector-css-bordercolor').css('background', '');
426 }
427 // display CSS params
428 jQuery('.vbo-inspector-css-param').show();
429 // animate scroll to the outer position
430 jQuery('html,body').animate({scrollTop: jQuery('#vbo-inspector-outer').offset().top - 40}, {duration: 400});
431 }
432
433 /**
434 * Toggles the CSS params for the border
435 */
436 function vboToggleCSSBorderParams() {
437 if (jQuery('input[name="vbo-inspector-css-border"]').is(':checked')) {
438 jQuery('.vbo-inspector-css-border-param').show();
439 if (current_target !== null) {
440 // restore border, if any
441 var borderwidth = jQuery('#vbo-inspector-css-borderwidth').val();
442 if (borderwidth.length && !isNaN(borderwidth) && borderwidth > 0) {
443 current_target.css('border', borderwidth + 'px solid ' + vboRgb2Hex(jQuery('#vbo-inspector-css-bordercolor').css('backgroundColor')));
444 }
445 }
446 } else {
447 jQuery('.vbo-inspector-css-border-param').hide();
448 if (current_target !== null) {
449 // unset border completely
450 current_target.css('border', '');
451 }
452 }
453 }
454
455 /**
456 * AJAX request to remove a special tag from a template file.
457 */
458 function vboRemoveCondTextTagFromTpl(tag, file) {
459 var jqxhr = jQuery.ajax({
460 type: "POST",
461 url: "<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=condtext_update_tmpl'); ?>",
462 data: {
463 tmpl: "component",
464 tagaction: 'remove',
465 tag: tag,
466 file: file
467 }
468 }).done(function(response) {
469 try {
470 var obj_res = typeof response === 'string' ? JSON.parse(response) : response;
471 if (!obj_res.hasOwnProperty('newhtml')) {
472 console.error('Unexpected JSON response', obj_res);
473 return false;
474 }
475 // update template file HTML code
476 jQuery('.vbo-tplcontent-inspector-ghost[data-inspectfile="' + file + '"]').html(obj_res['newhtml']);
477 // update button classes and icon
478 var btn_triggering = jQuery('.vbo-condtext-tmpl-status[data-inspectfile="' + file + '"][data-specialtag="' + tag + '"]');
479 btn_triggering.removeClass('btn-success vbo-condtext-intmpl').addClass('btn-secondary vbo-condtext-notintmpl');
480 btn_triggering.find('i').removeClass().addClass('<?php echo VikBookingIcons::i('plus'); ?>');
481 } catch(err) {
482 console.error('could not parse JSON response', err, response);
483 alert('Request failed');
484 }
485 }).fail(function() {
486 alert('Request failed');
487 console.error('Request failed');
488 });
489 }
490
491 /**
492 * Removes (undo) a special tag from the inspector.
493 */
494 function vboRemoveTagFromInspector() {
495 if (current_tag === null) {
496 return false;
497 }
498 var escape_tag = current_tag.replace(/[.*+\-?^${}()|[\]\\]/g, '\\$&');
499 // replace all occurrences of escaped tag
500 var empty_html = jQuery('.vbo-inspector-wrap').html();
501 empty_html = empty_html.replace(new RegExp(escape_tag, 'g'), '');
502 // restore correct HTML
503 jQuery('.vbo-inspector-wrap').html(empty_html);
504 }
505
506 /**
507 * When manipulating the source code of the template files, errors may occur.
508 * This function makes a new AJAX request to restore the file from the backup.
509 */
510 function vboRestoreBackupFile() {
511 if (current_file === null) {
512 console.error('file cannot be null, unable to restore file');
513 return false;
514 }
515 // make the request
516 var jqxhr = jQuery.ajax({
517 type: "POST",
518 url: "<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=condtext_update_tmpl'); ?>",
519 data: {
520 tmpl: "component",
521 tagaction: 'restore',
522 file: current_file
523 }
524 }).done(function(response) {
525 var reload_href = jQuery('.vbo-reload-plchld-link').attr('href');
526 try {
527 var obj_res = typeof response === 'string' ? JSON.parse(response) : response;
528 if (!obj_res.hasOwnProperty('newhtml')) {
529 console.error('Unexpected JSON response while restoring', obj_res, response);
530 return false;
531 }
532 location.href = reload_href;
533 return;
534 } catch(err) {
535 console.error('could not parse JSON response when restoring', err, response);
536 // display error message
537 alert('Restoring failed. The template file ' + current_file + ' may be corrupted');
538 location.href = reload_href;
539 return;
540 }
541 }).fail(function() {
542 alert('Restoring request failed');
543 console.error('Restoring request failed');
544 });
545 }
546
547 /**
548 * Declare the functions for the document ready event.
549 */
550 jQuery(function() {
551
552 /**
553 * Register border width number input change event.
554 */
555 jQuery('#vbo-inspector-css-borderwidth').change(function() {
556 if (current_target === null) {
557 return;
558 }
559 var borderwidth = jQuery(this).val();
560 if (borderwidth.length && !isNaN(borderwidth) && borderwidth > 0) {
561 // use short-hand syntax to update the border
562 current_target.css('border', borderwidth + 'px solid ' + vboRgb2Hex(jQuery('#vbo-inspector-css-bordercolor').css('backgroundColor')));
563 } else {
564 // unset the border completely
565 current_target.css('border', '');
566 }
567 // trigger target style modification
568 vboCSSTargetChanged();
569 });
570
571 /**
572 * Register color-picker for CSS editing parameters.
573 */
574 jQuery('.vbo-inspector-colorpicker-trig').ColorPicker({
575 color: '#ffffff',
576 onShow: function (colpkr, el) {
577 if (current_target === null) {
578 return false;
579 }
580 var cur_color = jQuery(el).css('backgroundColor');
581 jQuery(el).ColorPickerSetColor(vboRgb2Hex(cur_color));
582 jQuery(colpkr).show();
583 return false;
584 },
585 onChange: function (hsb, hex, rgb, el) {
586 var element = jQuery(el);
587 var elid = element.attr('id');
588 element.css('backgroundColor', '#'+hex);
589 if (current_target !== null) {
590 var css_prop = 'backgroundColor';
591 if (elid == 'vbo-inspector-css-color') {
592 css_prop = 'color';
593 } else if (elid == 'vbo-inspector-css-bordercolor') {
594 css_prop = 'borderColor';
595 }
596 current_target.css(css_prop, '#'+hex);
597 }
598 // trigger target style modification
599 vboCSSTargetChanged();
600 },
601 onSubmit: function(hsb, hex, rgb, el) {
602 var element = jQuery(el);
603 var elid = element.attr('id');
604 element.css('backgroundColor', '#'+hex);
605 if (current_target !== null) {
606 var css_prop = 'backgroundColor';
607 if (elid == 'vbo-inspector-css-color') {
608 css_prop = 'color';
609 } else if (elid == 'vbo-inspector-css-bordercolor') {
610 css_prop = 'borderColor';
611 }
612 current_target.css(css_prop, '#'+hex);
613 }
614 element.ColorPickerHide();
615 // trigger target style modification
616 vboCSSTargetChanged();
617 }
618 });
619
620 /**
621 * Listens to the buttons to start the CSS editing mode. May be used on different tabs.
622 */
623 jQuery('.vbo-inspector-btn').click(function() {
624 var file = jQuery(this).attr('data-inspectfile');
625 if (!file || !tpl_names.hasOwnProperty(file)) {
626 alert('Template not found');
627 console.error('Template not found ' + file, tpl_names);
628 return false;
629 }
630 // make sure the proper configuration tab is active
631 var proper_tab_cont = jQuery('.vbo-inspector-wrap').closest('dd.tabs');
632 if (!proper_tab_cont.is(':visible')) {
633 var tab_id = proper_tab_cont.attr('id').replace('pt', '');
634 if (jQuery('dt.tabs[data-ptid="' + tab_id + '"]').length) {
635 // simulate click on proper tab, as CSS editing can be started also from another tab
636 jQuery('dt.tabs[data-ptid="' + tab_id + '"]').trigger('click');
637 }
638 }
639 // start CSS inspector
640 vboStartCSSInspector(file);
641 });
642
643 /**
644 * Listens to the click on the buttons to add or remove special tags.
645 */
646 jQuery('.vbo-condtext-tmpl-status').click(function() {
647 // always hide inspector outer
648 jQuery('#vbo-inspector-outer').hide();
649 // always make the helper text empty
650 jQuery('#vbo-inspector-help').html('');
651 // always disable the save button
652 jQuery('#vbo-inspector-save').prop('disabled', true);
653 // always disable CSS editing
654 vboDisableCSSEditing();
655 // find file name and tag
656 var file = jQuery(this).attr('data-inspectfile');
657 if (!file || !tpl_names.hasOwnProperty(file)) {
658 alert('Template not found');
659 console.error('Template not found ' + file, tpl_names);
660 return false;
661 }
662 // update global current tag and file selected
663 var tag = jQuery(this).attr('data-specialtag');
664 current_tag = tag;
665 current_file = file;
666 // check if tag is already in the template file
667 if (jQuery(this).hasClass('vbo-condtext-intmpl')) {
668 // ask to remove it
669 var rmtxt = Joomla.JText._('VBO_CONDTEXT_TAG_RM_HELP');
670 if (confirm(rmtxt.replace('%s', tpl_names[file]))) {
671 vboRemoveCondTextTagFromTpl(current_tag, file);
672 } else {
673 current_tag = null;
674 current_file = null;
675 }
676 return false;
677 }
678 // update title
679 jQuery('#vbo-inspector-title').text(tpl_names[file] + ' - ' + Joomla.JText._('VBOCONFIGEDITTMPLFILE'));
680 // update helper
681 var helper_txt = Joomla.JText._('VBO_CONDTEXT_TAG_ADD_HELP');
682 jQuery('#vbo-inspector-help').html('<?php VikBookingIcons::e('magic'); ?> ' + helper_txt.replace('%s', current_tag)).show();
683 // sanitize template source code from any script tag in case of malformed markup
684 jQuery('.vbo-tplcontent-inspector-ghost[data-inspectfile="' + file + '"]').find('script').remove();
685 // grab requested content and move it to the inspector wrapper
686 jQuery('.vbo-inspector-wrap').html(jQuery('.vbo-tplcontent-inspector-ghost[data-inspectfile="' + file + '"]').html()).attr('data-inspectfile', file);
687 // display inspector outer
688 jQuery('#vbo-inspector-outer').show();
689 // animate scroll to the outer position
690 jQuery('html,body').animate({scrollTop: jQuery('#vbo-inspector-outer').offset().top - 40}, {duration: 400});
691 // register hovering event
692 vboRegisterInspector(true);
693 });
694
695 /**
696 * Listens to the click on the elements of the HTML inspector.
697 * It can append a special tag, remove one before, or start the CSS editing.
698 */
699 jQuery('.vbo-inspector-wrap').click(function(e) {
700 if (current_file === null) {
701 // file cannot be null
702 return false;
703 }
704 // update current target
705 var target = jQuery(e.target);
706 current_target = target;
707 // insert tag, if requested
708 if (current_tag != null) {
709 // check if the tag was already added
710 var removed = false;
711 if (jQuery('.vbo-inspector-wrap').html().indexOf(current_tag) >= 0) {
712 // remove current tag before appending it to the new position
713 vboRemoveTagFromInspector();
714 removed = true;
715 }
716 target.append(current_tag);
717 // enable the save button
718 jQuery('#vbo-inspector-save').prop('disabled', false);
719 if (removed) {
720 // inspector hovering needs to be re-registered after removing the tag
721 vboRegisterInspector(true);
722 }
723 return;
724 }
725 // if we reach this point, start CSS inspector
726 vboStartCSSInspector(null);
727 });
728
729 /**
730 * Tries to undo the last action. Behaves differently depending on the active mode.
731 */
732 jQuery('#vbo-inspector-cancel').click(function() {
733 // always hide the preview button
734 jQuery('#vbo-inspector-preview').attr('data-prew-type', '').hide();
735 if (current_file === null) {
736 // file cannot be null, hide inspector outer no matter what
737 jQuery('#vbo-inspector-outer').hide();
738 return false;
739 }
740 if (current_tag != null) {
741 // unset all occurrences of the current tag (if any)
742 var empty_html = jQuery('.vbo-inspector-wrap').html();
743 if (empty_html.length && empty_html.indexOf(current_tag) >= 0) {
744 // remove tag from inspector
745 vboRemoveTagFromInspector();
746 // inspector hovering needs to be re-registered after editing the content
747 vboRegisterInspector(true);
748 } else {
749 // hide inspector outer, as the tag was not added yet
750 jQuery('#vbo-inspector-outer').hide();
751 }
752 } else {
753 if (css_editing && current_target !== null) {
754 // hide current CSS params
755 jQuery('.vbo-inspector-css-param, .vbo-inspector-css-border-param').hide();
756 // unset current target
757 current_target = null;
758 // make the list of targets with custom CSS empty
759 css_custom_classes = [];
760 // disable save button
761 jQuery('#vbo-inspector-save').prop('disabled', true);
762 // sanitize template source code from any script tag in case of malformed markup
763 jQuery('.vbo-tplcontent-inspector-ghost[data-inspectfile="' + current_file + '"]').find('script').remove();
764 // cancelling during CSS editing means restoring the original source code
765 jQuery('.vbo-inspector-wrap').html(jQuery('.vbo-tplcontent-inspector-ghost[data-inspectfile="' + current_file + '"]').html()).attr('data-inspectfile', current_file);
766 // register hovering event is necessary
767 vboRegisterInspector(true);
768 } else {
769 // hide inspector outer, tag not yet added or already added and saved
770 jQuery('#vbo-inspector-outer').hide();
771 }
772 }
773 });
774
775 /**
776 * Saves the last action made through the inspector.
777 */
778 jQuery('#vbo-inspector-save').click(function() {
779 if (current_file === null) {
780 console.error('file cannot be null');
781 return false;
782 }
783 var savebtn = jQuery(this);
784 // show loading
785 savebtn.find('i').removeClass().addClass('<?php echo VikBookingIcons::i('refresh', 'fa-spin fa-fw'); ?>');
786 // detect action type
787 var action_type = 'add';
788 if (css_editing && css_custom_classes.length) {
789 action_type = 'styles';
790 }
791 // make the request
792 VBOCore.doAjax(
793 "<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=condtext_update_tmpl'); ?>",
794 {
795 tmpl: "component",
796 tagaction: action_type,
797 tag: current_tag,
798 file: current_file,
799 newcontent: jQuery('.vbo-inspector-wrap').html(),
800 custom_classes: css_custom_classes
801 },
802 (response) => {
803 try {
804 var obj_res = typeof response === 'string' ? JSON.parse(response) : response;
805 if (!obj_res.hasOwnProperty('newhtml')) {
806 console.error('Unexpected JSON response', obj_res);
807 return false;
808 }
809 // stop loading
810 savebtn.find('i').removeClass().addClass('<?php echo VikBookingIcons::i('check-circle'); ?>');
811 // disable another saving
812 savebtn.prop('disabled', true);
813 // check for preview if supported
814 if (current_file && jQuery('.vbo-preview-btn[data-prew-type="' + current_file + '"]').length) {
815 // display the preview button
816 jQuery('#vbo-inspector-preview').attr('data-prew-type', current_file).show();
817 } else {
818 // hide the preview button no matter what
819 jQuery('#vbo-inspector-preview').hide();
820 }
821 if (current_tag !== null) {
822 // update button classes and icon
823 var btn_triggering = jQuery('.vbo-condtext-tmpl-status[data-inspectfile="' + current_file + '"][data-specialtag="' + current_tag + '"]');
824 btn_triggering.removeClass('btn-secondary vbo-condtext-notintmpl').addClass('btn-success vbo-condtext-intmpl');
825 btn_triggering.find('i').removeClass().addClass('<?php echo VikBookingIcons::i('check-circle'); ?>');
826 // hide helper
827 jQuery('#vbo-inspector-help').hide().html('');
828 // unset tag editing mode
829 current_tag = null;
830 }
831 if (css_editing && css_custom_classes.length) {
832 // empty the list of custom CSS classes as they were all saved
833 css_custom_classes = [];
834 }
835 // update template file HTML code
836 jQuery('.vbo-tplcontent-inspector-ghost[data-inspectfile="' + current_file + '"]').html(obj_res['newhtml']);
837 } catch(err) {
838 console.error('could not parse JSON response after saving', err, response);
839 // display error message
840 alert(Joomla.JText._('VBO_EDITTPL_FATALERROR'));
841 // restore backup of the file source code
842 vboRestoreBackupFile();
843 }
844 },
845 (err) => {
846 console.error('Request failed completely');
847 // display error message
848 alert(Joomla.JText._('VBO_EDITTPL_FATALERROR'));
849 // restore backup of the file source code
850 vboRestoreBackupFile();
851 }
852 );
853 });
854
855 /**
856 * Handles the preview button clicked from a tab outside the actual preview modal.
857 */
858 jQuery('#vbo-inspector-preview').click(function() {
859 var prev_type = jQuery(this).attr('data-prew-type');
860 var target_btn = jQuery('.vbo-preview-btn[data-prew-type="' + prev_type + '"]');
861 if (!prev_type || !target_btn.length) {
862 // hide the button
863 jQuery(this).hide();
864 return;
865 }
866
867 // make sure the proper configuration tab is active
868 var proper_tab_cont = target_btn.closest('dd.tabs');
869 if (!proper_tab_cont.is(':visible')) {
870 var tab_id = proper_tab_cont.attr('id').replace('pt', '');
871 if (jQuery('dt.tabs[data-ptid="' + tab_id + '"]').length) {
872 // simulate click on proper tab, as CSS editing can be started also from another tab
873 jQuery('dt.tabs[data-ptid="' + tab_id + '"]').trigger('click');
874 // turn current tab flag on
875 vbo_back_to_tab = jQuery(this).closest('dd.tabs').attr('id').replace('pt', '');
876 }
877 }
878
879 // simulate click on proper preview button
880 target_btn.trigger('click');
881 });
882
883 /**
884 * Register to the event emitted when the modal for edit or preview template file is dismissed.
885 */
886 document.addEventListener('vbo-dismiss-modal-tmplfile', (e) => {
887 if (typeof vbo_back_to_tab !== 'undefined' && vbo_back_to_tab) {
888 // simulate click on proper tab, as CSS editing can be started also from another tab
889 jQuery('dt.tabs[data-ptid="' + vbo_back_to_tab + '"]').trigger('click');
890 // schedule scroll to the proper position
891 setTimeout(() => {
892 jQuery('html,body').animate({scrollTop: jQuery('#vbo-inspector-outer').offset().top - 40}, {duration: 400});
893 }, 50);
894 // turn current tab flag off
895 vbo_back_to_tab = null;
896 }
897 });
898
899 /**
900 * Saves the content-wrapper HTML structure.
901 */
902 jQuery('#vbo-contwrapper-save').click(function() {
903 var wrapper_code = jQuery('#vbo-contwrapper-html').val();
904 if (!wrapper_code || !wrapper_code.length) {
905 return false;
906 }
907 jQuery(this).prop('disabled', true);
908 VBOCore.doAjax('<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=mail.update_ve_contwraper'); ?>', {
909 wrapper_content: wrapper_code
910 }, (resp) => {
911 // hide editing mode
912 jQuery('.vbo-contwrapper-edit').hide();
913 jQuery(this).prop('disabled', false);
914 }, (err) => {
915 alert(err.responseText);
916 jQuery(this).prop('disabled', false);
917 });
918 });
919
920 });
921 </script>
922