PluginProbe
VikBooking Hotel Booking Engine & PMS / trunk
VikBooking Hotel Booking Engine & PMS vtrunk
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 1.7.3 All 36 releases
vikbooking / admin / views / config / tmpl / default_seven.php

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

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