PluginProbe
VikBooking Hotel Booking Engine & PMS / 1.8.16
VikBooking Hotel Booking Engine & PMS v1.8.16
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
← All changes | admin/helpers/vikbooking.php +259 -35 1.6.5 → 1.8.16 View file →
@@ -41,8 +41,9 @@
41 41 $admin_user = JFactory::getUser();
42 42
43 43 $has_vcm = is_file(VCM_SITE_PATH.DIRECTORY_SEPARATOR.'helpers'.DIRECTORY_SEPARATOR.'lib.vikchannelmanager.php');
44 44 $backlogo = VikBooking::getBackendLogo();
45 + $vbo_auth_admin = $admin_user->authorise('core.admin', 'com_vikbooking');
45 46 $vbo_auth_global = $admin_user->authorise('core.vbo.global', 'com_vikbooking');
46 47 $vbo_auth_rateplans = $admin_user->authorise('core.vbo.rateplans', 'com_vikbooking');
47 48 $vbo_auth_rooms = $admin_user->authorise('core.vbo.rooms', 'com_vikbooking');
48 49 $vbo_auth_pricing = $admin_user->authorise('core.vbo.pricing', 'com_vikbooking');
@@ -49,8 +50,10 @@
49 50 $vbo_auth_bookings = $admin_user->authorise('core.vbo.bookings', 'com_vikbooking');
50 51 $vbo_auth_availability = $admin_user->authorise('core.vbo.availability', 'com_vikbooking');
51 52 $vbo_auth_management = $admin_user->authorise('core.vbo.management', 'com_vikbooking');
52 53 $vbo_auth_pms = $admin_user->authorise('core.vbo.pms', 'com_vikbooking');
54 + $vbo_auth_reports = $admin_user->authorise('core.vbo.pmsreports', 'com_vikbooking');
55 + $vbo_auth_tm = $admin_user->authorise('core.vbo.tm', 'com_vikbooking');
53 56 $reviews_dld = 0;
54 57
55 58 // check for stored quick actions only once
56 59 $admin_menu_actions_checked = $session->get('admin_menu.actions.check', null, 'vikbooking');
@@ -125,9 +128,9 @@
125 128 </li>
126 129 <?php endif; ?>
127 130 <?php if ($vbo_auth_global) : ?>
128 131 <li>
129 - <div class="<?php echo ($highlight == "11" || $highlight == 'backups' ? "vmenulinkactive" : "vmenulink"); ?>">
132 + <div class="<?php echo ($highlight == "11" || $highlight == 'backups' || $highlight == 'overrides' ? "vmenulinkactive" : "vmenulink"); ?>">
130 133 <a href="index.php?option=com_vikbooking&amp;task=config">
131 134 <?php VikBookingIcons::e('cogs'); ?>
132 135 <span class="vbo-submenu-item">
133 136 <span class="vbo-submenu-item-txt"><?php echo JText::translate('VBMENUTWELVE'); ?></span>
@@ -253,9 +256,9 @@
253 256 <ul class="vbo-submenu-ul" data-menu-scope="pricing">
254 257 <li>
255 258 <div class="<?php echo ($highlight == "fares" ? "vmenulinkactive" : "vmenulink"); ?>">
256 259 <a href="index.php?option=com_vikbooking&amp;task=tariffs">
257 - <?php VikBookingIcons::e('toolbox'); ?>
260 + <?php VikBookingIcons::e('filter-circle-dollar'); ?>
258 261 <span class="vbo-submenu-item">
259 262 <span class="vbo-submenu-item-txt"><?php echo JText::translate('VBMENUPRICESTABLE'); ?></span>
260 263 </span>
261 264 </a>
@@ -317,10 +320,20 @@
317 320 <span class="vbo-submenu-item">
318 321 <span class="vbo-submenu-item-txt"><?php echo JText::translate('VBMENUQUICKRES'); ?></span>
319 322 </span>
320 323 </a>
321 - </div>
322 - </li>
324 + </div>
325 + </li>
326 + <li>
327 + <div class="<?php echo ($highlight == "managequote" ? "vmenulinkactive" : "vmenulink"); ?>">
328 + <a href="index.php?option=com_vikbooking&amp;view=managequote">
329 + <?php VikBookingIcons::e('file-alt'); ?>
330 + <span class="vbo-submenu-item">
331 + <span class="vbo-submenu-item-txt"><?php echo JText::translate('VBO_CREATE_QUOTE'); ?></span>
332 + </span>
333 + </a>
334 + </div>
335 + </li>
323 336 <?php endif; ?>
324 337 <?php if ($vbo_auth_availability) : ?>
325 338 <li>
326 339 <div class="<?php echo ($highlight == "15" ? "vmenulinkactive" : "vmenulink"); ?>">
@@ -344,11 +357,11 @@
344 357 </a>
345 358 </div>
346 359 </li>
347 360 <?php endif; ?>
348 - <?php if ($has_vcm && ($vbo_auth_availability || $vbo_auth_bookings)) : ?>
349 - <li>
350 - <div class="vmenulink">
361 + <?php if (($has_vcm || VBOPlatformDetection::isWordPress()) && ($vbo_auth_availability || $vbo_auth_bookings)) : ?>
362 + <li class="vbo-menu-vcm-only">
363 + <div class="<?php echo ($highlight == 'vikchannelmanager' ? 'vmenulinkactive' : 'vmenulink'); ?>">
351 364 <a href="index.php?option=com_vikchannelmanager" class="vbo-menu-vcmlink">
352 365 <?php VikBookingIcons::e('cloud'); ?>
353 366 <span class="vbo-submenu-item">
354 367 <span class="vbo-submenu-item-txt"><?php echo JText::translate('VBMENUCHANNELMANAGER'); ?></span>
@@ -418,14 +431,15 @@
418 431 </ul>
419 432 </div>
420 433 </li><?php
421 434 }
422 - if ($vbo_auth_pms) {
435 + if ($vbo_auth_pms || $vbo_auth_reports || $vbo_auth_tm) {
423 436 ?><li class="vbo-menu-parent-li">
424 437 <span><?php VikBookingIcons::e('tasks'); ?><a><?php echo JText::translate('VBMENUPMS'); ?> <?php VikBookingIcons::e('chevron-down', 'vbo-submenu-chevron'); ?></a></span>
425 438 <div class="vbo-submenu-wrap">
426 - <ul class="vbo-submenu-ul" data-menu-scope="pms">
427 - <li>
439 + <ul class="vbo-submenu-ul" data-menu-scope="pms"><?php
440 + if ($vbo_auth_pms) {
441 + ?><li>
428 442 <div class="<?php echo ($highlight == "operators" ? "vmenulinkactive" : "vmenulink"); ?>">
429 443 <a href="index.php?option=com_vikbooking&amp;task=operators">
430 444 <?php VikBookingIcons::e('user-tie'); ?>
431 445 <span class="vbo-submenu-item">
@@ -442,10 +456,12 @@
442 456 <span class="vbo-submenu-item-txt"><?php echo JText::translate('VBMENUTABLEAUX'); ?></span>
443 457 </span>
444 458 </a>
445 459 </div>
446 - </li>
447 - <li>
460 + </li><?php
461 + }
462 + if ($vbo_auth_admin || $vbo_auth_reports) {
463 + ?><li>
448 464 <div class="<?php echo ($highlight == "pmsreports" ? "vmenulinkactive" : "vmenulink"); ?>">
449 465 <a href="index.php?option=com_vikbooking&amp;task=pmsreports">
450 466 <?php VikBookingIcons::e('cash-register'); ?>
451 467 <span class="vbo-submenu-item">
@@ -452,10 +468,12 @@
452 468 <span class="vbo-submenu-item-txt"><?php echo JText::translate('VBMENUPMSREPORTS'); ?></span>
453 469 </span>
454 470 </a>
455 471 </div>
456 - </li>
457 - <li>
472 + </li><?php
473 + }
474 + if ($vbo_auth_pms) {
475 + ?><li>
458 476 <div class="<?php echo ($highlight == "einvoicing" ? "vmenulinkactive" : "vmenulink"); ?>">
459 477 <a href="index.php?option=com_vikbooking&amp;task=einvoicing">
460 478 <?php VikBookingIcons::e('laptop-code'); ?>
461 479 <span class="vbo-submenu-item">
@@ -462,10 +480,23 @@
462 480 <span class="vbo-submenu-item-txt"><?php echo JText::translate('VBMENUEINVOICING'); ?></span>
463 481 </span>
464 482 </a>
465 483 </div>
466 - </li>
467 - </ul>
484 + </li><?php
485 + }
486 + if ($vbo_auth_admin || $vbo_auth_tm) {
487 + ?><li class="vbo-menu-vcm-only">
488 + <div class="<?php echo ($highlight == "taskmanager" ? "vmenulinkactive" : "vmenulink"); ?>">
489 + <a href="index.php?option=com_vikbooking&amp;view=taskmanager">
490 + <?php VikBookingIcons::e('tasks'); ?>
491 + <span class="vbo-submenu-item">
492 + <span class="vbo-submenu-item-txt"><?php echo JText::translate('VBO_TASK_MANAGER'); ?></span>
493 + </span>
494 + </a>
495 + </div>
496 + </li><?php
497 + }
498 + ?></ul>
468 499 </div>
469 500 </li><?php
470 501 }
471 502 ?>
@@ -483,9 +514,9 @@
483 514 <?php VikBookingIcons::e('rocket'); ?>
484 515 <span><?php echo JText::translate('VBOGOTOPROBTN'); ?></span>
485 516 </button>
486 517 <?php
487 - } else {
518 + } elseif ($vbo_auth_global) {
488 519 ?>
489 520 <button type="button" class="vbo-alreadypro" title="<?php echo addslashes(JText::translate('VBOISPROBTN')); ?>" onclick="document.location.href='admin.php?option=com_vikbooking&view=gotopro';">
490 521 <?php VikBookingIcons::e('trophy'); ?>
491 522 <span><?php echo JText::translate('VBOISPROBTN'); ?></span>
@@ -609,9 +640,9 @@
609 640 }
610 641 }
611 642 }
612 643
613 - if ($vbo_auth_management && in_array($highlight, array('18', '11', '8'))) {
644 + if ($vbo_auth_management && in_array($highlight, array('18', '11'))) {
614 645 // VCM Opportunities
615 646 $opp = VikBooking::getVcmOpportunityInstance();
616 647 if (!is_null($opp)) {
617 648 // download opportunities if it's time to do it
@@ -625,12 +656,12 @@
625 656 );
626 657 $new_opp_count = count($opp->loadOpportunities($opp_filters, null, null));
627 658 if ($new_opp_count > 0) {
628 659 ?>
629 - <button type="button" class="vbo-opportunities-btnbadge" data-opportunity-count="<?php echo $new_opp_count; ?>" title="<?php echo htmlspecialchars(JText::translate('VBOGOTOOPPORTUNITIES')); ?>" onclick="document.location.href='<?php echo VBOFactory::getPlatform()->getUri()->admin('index.php?option=com_vikchannelmanager&task=opportunities', false); ?>';">
660 + <!-- <button type="button" class="vbo-opportunities-btnbadge" data-opportunity-count="<?php echo $new_opp_count; ?>" title="<?php echo htmlspecialchars(JText::translate('VBOGOTOOPPORTUNITIES')); ?>" onclick="document.location.href='<?php echo VBOFactory::getPlatform()->getUri()->admin('index.php?option=com_vikchannelmanager&task=opportunities', false); ?>';">
630 661 <?php VikBookingIcons::e('crown'); ?>
631 662 <span><?php echo JText::translate('VBOGOTOOPPORTUNITIES'); ?></span>
632 - </button>
663 + </button> -->
633 664 <?php
634 665 }
635 666 }
636 667
@@ -636,14 +667,16 @@
636 667
637 668 // Guest Reviews
638 669 $reviews_dld = VikBooking::shouldDownloadReviews();
639 670 $base_lnk = VBOFactory::getPlatform()->getUri()->admin('index.php?option=com_vikchannelmanager&task=reviews', false);
640 - ?>
671 + if ($highlight == '18') {
672 + ?>
641 673 <button type="button" class="vbo-reviews-btnbadge" data-reviews-count="" title="<?php echo htmlspecialchars(JText::translate('VBOPANELREVIEWS')); ?>" onclick="<?php echo $reviews_dld >= 0 ? "window.open('{$base_lnk}', '_blank'); jQuery(this).removeClass('vbo-reviews-btnbadge-alert').attr('data-reviews-count', '');" : "alert(Joomla.JText._('VBOGUESTREVSVCMREQ'));"; ?>">
642 674 <?php VikBookingIcons::e('star'); ?>
643 675 <span><?php echo JText::translate('VBOPANELREVIEWS'); ?></span>
644 676 </button>
645 - <?php
677 + <?php
678 + }
646 679 }
647 680
648 681 /**
649 682 * Admin widgets multitasking side panel.
@@ -652,22 +685,59 @@
652 685 */
653 686 if ($view != 'dashboard') {
654 687 ?>
655 688 <button type="button" class="vbo-multitasking-apps" title="<?php echo htmlspecialchars(JText::translate('VBO_MULTITASK_PANEL'), ENT_QUOTES, 'UTF-8'); ?>">
656 - <?php VikBookingIcons::e('th'); ?>
689 + <?php VikBookingIcons::e('grip'); ?>
657 690 </button>
658 691
659 692 <?php
660 693 // prepare the layout data array
661 - $layout_data = array(
694 + $layout_data = [
662 695 'vbo_page' => (empty($view) ? VikRequest::getString('task', '') : $view),
663 696 'btn_trigger' => '.vbo-multitasking-apps',
664 - );
697 + ];
698 + // render the multitasking layout
665 699 echo JLayoutHelper::render('sidepanel.multitasking', $layout_data);
666 700 ?>
667 701 <?php
668 702 }
669 - ?>
703 +
704 + /**
705 + * Notifications Center.
706 + *
707 + * @since 1.16.8 (J) - 1.6.8 (WP)
708 + */
709 + $ncInstance = VBOFactory::getNotificationCenter();
710 +
711 + // read "old" notifications
712 + $ncInstance->readOldNotifications();
713 +
714 + // check if notifications should be downloaded
715 + $ncInstance->downloadNotifications();
716 +
717 + // count unread notifications
718 + $unreadNotifs = $ncInstance->countUnread();
719 + $unreadNotifsRead = $unreadNotifs > 99 ? '99+' : $unreadNotifs;
720 + $unreadNotifsRead = !$unreadNotifsRead ? '' : $unreadNotifsRead;
721 + ?>
722 + <div class="vbo-notifications-center-container">
723 + <button type="button" class="vbo-notifications-center-handler" data-badge-count="<?php echo $unreadNotifs; ?>" data-badge-read="<?php echo $unreadNotifsRead; ?>" title="<?php echo htmlspecialchars(JText::translate('VBO_W_NOTIFSCENTER_TITLE'), ENT_QUOTES, 'UTF-8'); ?>">
724 + <?php VikBookingIcons::e('bell', 'can-shake'); ?>
725 + </button>
726 + <?php
727 + // prepare the layout data array
728 + $layout_data = [
729 + 'vbo_page' => (empty($view) ? VikRequest::getString('task', '') : $view),
730 + 'btn_trigger' => '.vbo-notifications-center-handler',
731 + 'badge_c_attr' => 'data-badge-count',
732 + 'badge_r_attr' => 'data-badge-read',
733 + 'badge_count' => $unreadNotifs,
734 + ];
735 + // render the notificationscenter layout
736 + echo JLayoutHelper::render('sidepanel.notificationscenter', $layout_data);
737 + ?>
738 + </div>
739 +
670 740 </div>
671 741 </div>
672 742 </div>
673 743
@@ -736,10 +806,15 @@
736 806 } catch(e) {
737 807 console.error(e);
738 808 }
739 809
740 - // proceed with the navigation
741 - window.location.href = jQuery(this).attr('href');
810 + if (e.metaKey) {
811 + // open link on new window
812 + window.open(jQuery(this).attr('href'), '_blank').focus();
813 + } else {
814 + // proceed with the navigation
815 + window.location.href = jQuery(this).attr('href');
816 + }
742 817
743 818 return true;
744 819 });
745 820
@@ -744,8 +819,12 @@
744 819 });
745 820
746 821 // register event to populate quick actions sub-menu helpers
747 822 document.addEventListener('vbo-adminmenu-quickactions-create', () => {
823 + // load the action from the "widgets" scope to be used as fallback
824 + let menu_widgets_actions = VBOCore.getAdminMenuActions('widgets');
825 +
826 + // scan all menu scopes
748 827 jQuery('.vbo-submenu-ul[data-menu-scope]').each(function() {
749 828 let menu_ul = jQuery(this);
750 829 let scope = menu_ul.attr('data-menu-scope');
751 830 if (!scope) {
@@ -750,35 +829,74 @@
750 829 let scope = menu_ul.attr('data-menu-scope');
751 830 if (!scope) {
752 831 return;
753 832 }
833 +
834 + let orig_scope = scope;
754 835 let wrapper = menu_ul.closest('.vbo-submenu-wrap');
755 836 if (!wrapper || !wrapper.length || wrapper.hasClass('vbo-submenu-wrap-multi') || wrapper.find('.vbo-submenu-helper-ul').length) {
756 837 return;
757 838 }
839 +
758 840 let menu_scope_actions = VBOCore.getAdminMenuActions(scope);
759 841 if (!Array.isArray(menu_scope_actions) || !menu_scope_actions.length) {
760 - return;
842 + // check if we can fallback on the "widgets" scope
843 + if (Array.isArray(menu_widgets_actions) && menu_widgets_actions.length) {
844 + // overwrite scope values
845 + scope = 'widgets';
846 + menu_scope_actions = menu_widgets_actions;
847 + } else {
848 + // do not proceed with this scope
849 + return;
850 + }
761 851 }
852 +
853 + // check if menu actions should be merged with the fallback scope
854 + if (scope != 'widgets' && menu_scope_actions[0].hasOwnProperty('fallback')) {
855 + let before_fill_length = menu_scope_actions.length;
856 + menu_scope_actions = VBOCore.fillAdminMenuActions(menu_scope_actions, menu_widgets_actions, scope);
857 + let after_fill_length = menu_scope_actions.length;
858 + if (before_fill_length && after_fill_length > before_fill_length) {
859 + // update scope for the filled entries
860 + VBOCore.storageSetItem(VBOCore.getStorageScopeName(scope), menu_scope_actions);
861 + }
862 + }
863 +
762 864 wrapper.addClass('vbo-submenu-wrap-multi');
763 865 let quick_actions = jQuery('<ul></ul>').addClass('vbo-submenu-helper-ul');
764 866 quick_actions.append('<li class="vbo-submenu-helper-lbl-li"><span class="vbo-submenu-helper-lbl-txt">' + Joomla.JText._('VBO_QUICK_ACTIONS') + '</span></li>');
867 +
868 + // scan all menu actions
765 869 menu_scope_actions.forEach((action, index) => {
766 870 let is_pinned = action.hasOwnProperty('pinned') && action['pinned'];
767 871 let quick_actions_entry = jQuery('<li></li>').addClass((is_pinned ? 'vbo-submenu-item-helper-pinned' : 'vbo-submenu-item-helper-unpinned'));
768 872 let quick_actions_div = jQuery('<div></div>').addClass('vmenulink');
769 873 let quick_action_link = jQuery('<a></a>').attr('href', action['href']).addClass('vbo-submenu-item-helper-link');
874 +
770 875 if (action.hasOwnProperty('target') && action['target']) {
771 876 quick_action_link.attr('target', action['target']);
772 877 }
878 +
879 + if (action.hasOwnProperty('widget') && action['widget']) {
880 + quick_action_link.on('click', () => {
881 + VBOCore.handleDisplayWidgetNotification({widget_id: action['widget']});
882 + });
883 + }
884 +
773 885 if (action.hasOwnProperty('img') && action['img']) {
774 886 let quick_action_img = jQuery('<span></span>').addClass('vbo-submenu-item-helper-avatar');
775 887 quick_action_img.append('<img src="' + action['img'] + '" />');
776 888 quick_action_link.append(quick_action_img);
889 + } else if (action.hasOwnProperty('icon') && action['icon']) {
890 + let quick_action_icon = jQuery('<span></span>').addClass('vbo-submenu-item-helper-avatar');
891 + quick_action_icon.append(action['icon']);
892 + quick_action_link.append(quick_action_icon);
777 893 }
894 +
778 895 let quick_action_name = jQuery('<span></span>').addClass('vbo-submenu-item-helper-txt').text(action['name']);
779 896 quick_action_link.append(quick_action_name);
780 897 quick_actions_div.append(quick_action_link);
898 +
781 899 let quick_action_pin = jQuery('<span></span>').addClass('vbo-submenu-item-helper-setpin').on('click', function() {
782 900 // toggle pinned status and update admin menu action
783 901 if (!action.hasOwnProperty('pinned')) {
784 902 action['pinned'] = !is_pinned;
@@ -785,10 +903,20 @@
785 903 } else {
786 904 action['pinned'] = !action['pinned'];
787 905 }
788 906 try {
789 - // update local storage
790 - VBOCore.updateAdminMenuAction(action, scope);
907 + // register/unregister pin
908 + if (orig_scope != scope && !VBOCore.getAdminMenuActions(orig_scope).length) {
909 + // set fallbacked scope
910 + action['fallback'] = scope;
911 +
912 + // register scope on local storage with the fallbacked scope
913 + VBOCore.registerAdminMenuAction(action, orig_scope);
914 + } else {
915 + // update local storage regularly on this scope
916 + VBOCore.updateAdminMenuAction(action, scope);
917 + }
918 +
791 919 // trigger event
792 920 VBOCore.emitEvent('vbo-adminmenu-quickactions-update');
793 921 } catch(e) {
794 922 console.error(e);
@@ -799,13 +927,16 @@
799 927 } else {
800 928 jQuery(this).closest('li').removeClass('vbo-submenu-item-helper-pinned').addClass('vbo-submenu-item-helper-unpinned');
801 929 }
802 930 });
931 +
803 932 quick_action_pin.html('<?php VikBookingIcons::e('thumbtack'); ?>');
804 933 quick_actions_div.append(quick_action_pin);
805 934 quick_actions_entry.append(quick_actions_div);
806 935 quick_actions.append(quick_actions_entry);
807 936 });
937 +
938 + // append to DOM element
808 939 wrapper.append(quick_actions);
809 940 });
810 941 });
811 942
@@ -844,8 +975,14 @@
844 975 }
845 976 );
846 977 }, 300));
847 978
979 + // append shortcut to title
980 + jQuery('.vbo-multitasking-apps').attr('title',
981 + jQuery('.vbo-multitasking-apps').attr('title') + ' '
982 + + (navigator.platform.toUpperCase().indexOf('MAC') === 0 ? '⌘' : '⌃') + '⏎'
983 + );
984 +
848 985 // register shortcuts
849 986 var vbo_menu_last_keydown = null;
850 987 window.addEventListener('keydown', (e) => {
851 988 e = e || window.event;
@@ -851,26 +988,38 @@
851 988 e = e || window.event;
852 989 if (!e.key) {
853 990 return;
854 991 }
855 - if (e.key === 'Enter' && e.metaKey) {
992 +
993 + let modifier = 'ctrl';
994 +
995 + // change the modifier depending on the platform
996 + if (navigator.platform.toUpperCase().indexOf('MAC') === 0) {
997 + modifier = 'meta';
998 + }
999 +
1000 + if (e.shortcut([modifier, 13])) {
856 1001 // toggle multitask panel
857 1002 VBOCore.emitEvent(VBOCore.multitask_shortcut_event);
858 1003 return;
859 1004 }
860 - if (VBOCore.side_panel_on && e.key === 'f' && e.metaKey) {
1005 +
1006 + if (VBOCore.side_panel_on && e.shortcut([modifier, 'F'])) {
861 1007 // focus search admin widget in multitask panel
862 1008 VBOCore.emitEvent(VBOCore.multitask_searchfs_event);
863 1009 e.preventDefault();
1010 +
864 1011 return;
865 1012 }
866 - if (e.key === 'k' && e.metaKey) {
1013 +
1014 + if (e.shortcut([modifier, 'K'])) {
867 1015 // set special key listener for sequences of combos
868 1016 e.preventDefault();
869 1017 vbo_menu_last_keydown = 'k';
870 1018 return;
871 1019 }
872 - if (vbo_menu_last_keydown === 'k' && e.metaKey && ['a', 'd', 'l'].includes(e.key)) {
1020 +
1021 + if (vbo_menu_last_keydown === 'k' && (e.shortcut([modifier, 'A']) || e.shortcut([modifier, 'D']) || e.shortcut([modifier, 'L']))) {
873 1022 // trigger event to change color scheme preferences
874 1023 e.preventDefault();
875 1024 // unset special key
876 1025 vbo_menu_last_keydown = '';
@@ -882,8 +1031,9 @@
882 1031 };
883 1032 jQuery('.vbo-sidepanel-colorscheme-option[data-scheme="' + color_schemes[e.key] + '"]').trigger('click');
884 1033 return;
885 1034 }
1035 +
886 1036 // always unset last key if this point gets reached
887 1037 vbo_menu_last_keydown = '';
888 1038 }, true);
889 1039
@@ -938,8 +1088,70 @@
938 1088 }
939 1089 );
940 1090 }, 300);
941 1091 }
1092 +
1093 + // declare window resize handler for setting the position of sub-menus
1094 + const subMenuStylesPositioning = () => {
1095 + // get window width
1096 + let windowWidth = window.innerWidth;
1097 +
1098 + // scan all sub-menu entries
1099 + document.querySelectorAll('.vbo-submenu-wrap').forEach((submenu) => {
1100 + // remove the class to style the sub-menu "to left"
1101 + submenu.classList.remove('vbo-submenu-wrap-toleft');
1102 +
1103 + // get sub-menu width and offset left position values
1104 + let elemWidth = submenu.offsetWidth;
1105 + let elemOffLeft = submenu.getBoundingClientRect().left;
1106 +
1107 + if (elemWidth) {
1108 + // sub-menu visibility is hidden, but width has been computed
1109 + if ((elemWidth + elemOffLeft) > windowWidth) {
1110 + // add "to left" positioning class or the sub-menu would exceed the window
1111 + submenu.classList.add('vbo-submenu-wrap-toleft');
1112 + }
1113 + } else {
1114 + // on small screens, the sub-menu may be hidden, hence with no width
1115 + let parentmenu = submenu.closest('.vbo-menu-parent-li');
1116 +
1117 + // register listener for mouseover event
1118 + parentmenu.addEventListener('mouseover', (e) => {
1119 + setTimeout(() => {
1120 + let now_submenu = e.target.querySelector('.vbo-submenu-wrap');
1121 + if (!now_submenu) {
1122 + return;
1123 + }
1124 + if ((now_submenu.offsetWidth + now_submenu.getBoundingClientRect().left) > window.innerWidth) {
1125 + // add "to left" positioning class or the sub-menu would exceed the window
1126 + now_submenu.classList.add('vbo-submenu-wrap-toleft');
1127 + }
1128 + }, 0);
1129 + });
1130 +
1131 + // register listener for touchstart event
1132 + parentmenu.addEventListener('touchstart', (e) => {
1133 + let limenu = e.target;
1134 + if (!limenu.matches('.vbo-menu-parent-li')) {
1135 + limenu = limenu.closest('.vbo-menu-parent-li');
1136 + }
1137 + // propagate the mouseover event
1138 + limenu.dispatchEvent(new Event('mouseover'));
1139 + });
1140 + }
1141 + });
1142 + };
1143 +
1144 + // register listener for window resize event
1145 + window.addEventListener('resize', subMenuStylesPositioning);
1146 +
1147 + // trigger sub-menus styles positioning function on page load
1148 + setTimeout(() => {
1149 + subMenuStylesPositioning();
1150 + }, 0);
1151 +
1152 + // populate admin-dock
1153 + VBOAdminDock.getInstance();
942 1154 });
943 1155 </script>
944 1156 <?php
945 1157
@@ -967,8 +1179,20 @@
967 1179 });
968 1180 </script>
969 1181 <?php
970 1182 }
1183 +
1184 + $helpWizardAjaxUrl = VBOFactory::getPlatform()->getUri()->ajax('index.php?option=com_vikbooking');
1185 + JHtml::fetch('script', VBO_ADMIN_URI . 'resources/helpwizard.js', ['version' => VIKBOOKING_SOFTWARE_VERSION]);
1186 + JText::script('VBSAVE');
1187 + JText::script('VBDISMISS');
1188 + JFactory::getDocument()->addScriptDeclaration(
1189 +<<<JAVASCRIPT
1190 +(function(w) {
1191 + window.VBO_HELP_WIZARD_AJAX_URL = '{$helpWizardAjaxUrl}';
1192 +})(window);
1193 +JAVASCRIPT
1194 + );
971 1195 }
972 1196
973 1197 public static function printFooter()
974 1198 {