Changeset 3420105
- Timestamp:
- 12/15/2025 12:22:59 PM (3 months ago)
- Location:
- surewp-app-bottom-menu/trunk
- Files:
-
- 3 edited
-
assets/js/mobile-bottom-menu.js (modified) (10 diffs)
-
mobile-bottom-menu.php (modified) (5 diffs)
-
readme.txt (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
surewp-app-bottom-menu/trunk/assets/js/mobile-bottom-menu.js
r3407881 r3420105 1 (function( $) {1 (function() { 2 2 'use strict'; 3 3 4 $(document).ready(function() { 4 // Wait for both DOM and jQuery to be ready 5 function initMobileBottomMenu() { 6 // Check if jQuery is available 7 if (typeof jQuery === 'undefined') { 8 // If jQuery isn't available yet, wait and try again 9 setTimeout(initMobileBottomMenu, 50); 10 return; 11 } 12 13 var $ = jQuery; 14 15 // Make sure DOM is ready 16 if (document.readyState === 'loading') { 17 document.addEventListener('DOMContentLoaded', function() { 18 runMobileBottomMenu($); 19 }); 20 } else { 21 runMobileBottomMenu($); 22 } 23 } 24 25 function runMobileBottomMenu($) { 5 26 // Add animation class on load 6 27 $('.mobile-bottom-menu').addClass('animate'); 7 28 8 29 // Set active menu item based on current URL 9 setActiveMenuItem( );30 setActiveMenuItem($); 10 31 11 32 // Initialize cart count if WooCommerce is active 12 33 if (typeof swpabmData !== 'undefined' && swpabmData.isWooCommerce) { 13 updateCartCount( );34 updateCartCount($); 14 35 } 15 36 … … 23 44 if (label === 'search') { 24 45 e.preventDefault(); 25 openSearchModal( );46 openSearchModal($); 26 47 return; 27 48 } … … 40 61 }); 41 62 42 // Search Modal functionality43 function openSearchModal() {44 var $modal = $('#swpabmSearchModal');45 $modal.addClass('active');46 $('body').css('overflow', 'hidden');47 48 // Focus on search input after animation49 setTimeout(function() {50 $('#swpabmSearchInput').focus();51 }, 300);52 }53 54 function closeSearchModal() {55 var $modal = $('#swpabmSearchModal');56 $modal.removeClass('active');57 $('body').css('overflow', '');58 $('#swpabmSearchInput').val('');59 $('#swpabmSearchClear').hide();60 $('#swpabmSearchSuggestions').show();61 $('#swpabmSearchResults').hide();62 }63 64 63 // Close search modal 65 $( '#swpabmSearchClose, .swpabm-search-modal-overlay').on('click', function(e) {64 $(document).on('click', '#swpabmSearchClose, .swpabm-search-modal-overlay', function(e) { 66 65 e.preventDefault(); 67 closeSearchModal( );66 closeSearchModal($); 68 67 }); 69 68 … … 71 70 $(document).on('keydown', function(e) { 72 71 if (e.key === 'Escape' && $('#swpabmSearchModal').hasClass('active')) { 73 closeSearchModal( );72 closeSearchModal($); 74 73 } 75 74 }); 76 75 77 76 // Search input handling 78 $( '#swpabmSearchInput').on('input', function() {77 $(document).on('input', '#swpabmSearchInput', function() { 79 78 var value = $(this).val(); 80 79 if (value.length > 0) { … … 88 87 89 88 // Clear search input 90 $( '#swpabmSearchClear').on('click', function() {89 $(document).on('click', '#swpabmSearchClear', function() { 91 90 $('#swpabmSearchInput').val('').focus(); 92 91 $(this).hide(); … … 95 94 }); 96 95 97 // Update cart count via AJAX98 function updateCartCount() {99 $.ajax({100 url: swpabmData.ajaxUrl,101 type: 'POST',102 data: {103 action: 'swpabm_get_cart_count',104 nonce: swpabmData.nonce105 },106 success: function(response) {107 if (response.success) {108 updateCartBadge(response.data.count);109 }110 }111 });112 }113 114 // Update cart badge display115 function updateCartBadge(count) {116 var $cartItems = $('.mobile-bottom-menu-item').filter(function() {117 return $(this).find('.mobile-bottom-menu-label').text().trim().toLowerCase() === 'cart';118 });119 120 $cartItems.each(function() {121 var $icon = $(this).find('.mobile-bottom-menu-icon');122 var $badge = $icon.find('.mobile-bottom-menu-badge');123 124 if (count > 0) {125 if ($badge.length === 0) {126 $badge = $('<span class="mobile-bottom-menu-badge swpabm-cart-count"></span>');127 $icon.append($badge);128 }129 $badge.text(count).attr('data-count', count);130 } else {131 $badge.remove();132 }133 });134 }135 136 96 // Listen for WooCommerce cart updates 137 97 $(document.body).on('added_to_cart removed_from_cart updated_cart_totals', function() { 138 98 if (typeof swpabmData !== 'undefined' && swpabmData.isWooCommerce) { 139 setTimeout(updateCartCount, 500); 99 setTimeout(function() { 100 updateCartCount($); 101 }, 500); 140 102 } 141 103 }); … … 143 105 // Handle dynamic URL changes (for single page apps) 144 106 $(window).on('popstate', function() { 145 setActiveMenuItem( );107 setActiveMenuItem($); 146 108 }); 147 109 148 110 // Smooth scroll to top when home is clicked and already on home 149 $( '.mobile-bottom-menu-item').on('click', function(e) {111 $(document).on('click', '.mobile-bottom-menu-item', function(e) { 150 112 var href = $(this).attr('href'); 151 113 var currentUrl = window.location.href.replace(/\/$/, ''); 152 var linkUrl = href.replace(/\/$/, '');114 var linkUrl = (href || '').replace(/\/$/, ''); 153 115 154 116 if (currentUrl === linkUrl) { … … 166 128 var menuHeight = $('.mobile-bottom-menu').outerHeight(); 167 129 168 $(window). scroll(function() {130 $(window).on('scroll', function() { 169 131 var scrollTop = $(this).scrollTop(); 170 132 … … 184 146 }); 185 147 } 186 }); 148 149 // Initialize public API 150 initPublicAPI($); 151 } 152 153 /** 154 * Search Modal functionality 155 */ 156 function openSearchModal($) { 157 var $modal = $('#swpabmSearchModal'); 158 $modal.addClass('active'); 159 $('body').css('overflow', 'hidden'); 160 161 // Focus on search input after animation 162 setTimeout(function() { 163 $('#swpabmSearchInput').focus(); 164 }, 300); 165 } 166 167 function closeSearchModal($) { 168 var $modal = $('#swpabmSearchModal'); 169 $modal.removeClass('active'); 170 $('body').css('overflow', ''); 171 $('#swpabmSearchInput').val(''); 172 $('#swpabmSearchClear').hide(); 173 $('#swpabmSearchSuggestions').show(); 174 $('#swpabmSearchResults').hide(); 175 } 176 177 /** 178 * Update cart count via AJAX 179 */ 180 function updateCartCount($) { 181 if (typeof swpabmData === 'undefined') { 182 return; 183 } 184 185 $.ajax({ 186 url: swpabmData.ajaxUrl, 187 type: 'POST', 188 data: { 189 action: 'swpabm_get_cart_count', 190 nonce: swpabmData.nonce 191 }, 192 success: function(response) { 193 if (response.success) { 194 updateCartBadge($, response.data.count); 195 } 196 } 197 }); 198 } 199 200 /** 201 * Update cart badge display 202 */ 203 function updateCartBadge($, count) { 204 var $cartItems = $('.mobile-bottom-menu-item').filter(function() { 205 return $(this).find('.mobile-bottom-menu-label').text().trim().toLowerCase() === 'cart'; 206 }); 207 208 $cartItems.each(function() { 209 var $icon = $(this).find('.mobile-bottom-menu-icon'); 210 var $badge = $icon.find('.mobile-bottom-menu-badge'); 211 212 if (count > 0) { 213 if ($badge.length === 0) { 214 $badge = $('<span class="mobile-bottom-menu-badge swpabm-cart-count"></span>'); 215 $icon.append($badge); 216 } 217 $badge.text(count).attr('data-count', count); 218 } else { 219 $badge.remove(); 220 } 221 }); 222 } 187 223 188 224 /** 189 225 * Set active menu item based on current URL 190 226 */ 191 function setActiveMenuItem( ) {227 function setActiveMenuItem($) { 192 228 var currentUrl = window.location.href.replace(/\/$/, ''); 193 229 var currentPath = window.location.pathname.replace(/\/$/, ''); … … 225 261 226 262 /** 227 * Public API for updating badge counts228 */ 229 window.SWPABMMenu ={230 updateBadge: function(itemIndex, count){231 var $item = $('.mobile-bottom-menu-item').eq(itemIndex);232 var $badge = $item.find('.mobile-bottom-menu-badge');233 234 if (count > 0) {235 if ( $badge.length ===0) {236 $badge = $('<span class="mobile-bottom-menu-badge"></span>');237 $item.find('.mobile-bottom-menu-icon').append($badge);238 }239 $badge.text(count);240 } else {241 $badge.remove();242 }243 },244 245 setActive: function(itemIndex) {246 $('.mobile-bottom-menu-item').removeClass('active');247 $('.mobile-bottom-menu-item').eq(itemIndex).addClass('active');248 },249 250 hide: function() {251 $('.mobile-bottom-menu').slideUp(300);252 },253 254 show: function() {255 $('.mobile-bottom-menu').slideDown(300);256 },257 258 openSearch: function() {259 $('#swpabmSearchModal').addClass('active');260 $('body').css('overflow', 'hidden');261 setTimeout(function() {262 $('#swpabmSearchInput').focus();263 }, 300);264 },265 266 closeSearch: function() {267 $('#swpabmSearchModal').removeClass('active');268 $('body').css('overflow', '');269 }270 };271 272 })( jQuery);263 * Initialize Public API for updating badge counts 264 */ 265 function initPublicAPI($) { 266 window.SWPABMMenu = { 267 updateBadge: function(itemIndex, count) { 268 var $item = $('.mobile-bottom-menu-item').eq(itemIndex); 269 var $badge = $item.find('.mobile-bottom-menu-badge'); 270 271 if (count > 0) { 272 if ($badge.length === 0) { 273 $badge = $('<span class="mobile-bottom-menu-badge"></span>'); 274 $item.find('.mobile-bottom-menu-icon').append($badge); 275 } 276 $badge.text(count); 277 } else { 278 $badge.remove(); 279 } 280 }, 281 282 setActive: function(itemIndex) { 283 $('.mobile-bottom-menu-item').removeClass('active'); 284 $('.mobile-bottom-menu-item').eq(itemIndex).addClass('active'); 285 }, 286 287 hide: function() { 288 $('.mobile-bottom-menu').slideUp(300); 289 }, 290 291 show: function() { 292 $('.mobile-bottom-menu').slideDown(300); 293 }, 294 295 openSearch: function() { 296 openSearchModal($); 297 }, 298 299 closeSearch: function() { 300 closeSearchModal($); 301 } 302 }; 303 } 304 305 // Start initialization 306 initMobileBottomMenu(); 307 308 })(); -
surewp-app-bottom-menu/trunk/mobile-bottom-menu.php
r3420054 r3420105 4 4 * Plugin URI: https://surewp.pro/app-style-bottom-menu 5 5 * Description: Adds an app-style bottom menu for mobile devices with Elementor widget support, WooCommerce cart integration, and search modal 6 * Version: 1.1. 56 * Version: 1.1.6 7 7 * Author: SureWP 8 8 * Author URI: https://surewp.pro … … 19 19 20 20 // Define plugin constants 21 define('SWPABM_VERSION', '1.1. 5');21 define('SWPABM_VERSION', '1.1.6'); 22 22 define('SWPABM_PLUGIN_DIR', plugin_dir_path(__FILE__)); 23 23 define('SWPABM_PLUGIN_URL', plugin_dir_url(__FILE__)); … … 60 60 // Add body class for mobile 61 61 add_filter('body_class', array($this, 'add_body_class')); 62 63 // Add custom CSS for custom theme64 add_action('wp_head', array($this, 'add_custom_css'));65 62 66 63 // AJAX handlers for cart count … … 118 115 SWPABM_VERSION 119 116 ); 117 118 // Add custom theme colors inline CSS right after the stylesheet 119 if (isset($settings['theme']) && $settings['theme'] === 'custom') { 120 $bg_color = isset($settings['custom_bg_color']) ? $settings['custom_bg_color'] : '#ffffff'; 121 $text_color = isset($settings['custom_text_color']) ? $settings['custom_text_color'] : '#666666'; 122 $active_color = isset($settings['custom_active_color']) ? $settings['custom_active_color'] : '#0073aa'; 123 124 $custom_css = ' 125 .mobile-bottom-menu.theme-custom { 126 background: ' . esc_attr($bg_color) . ' !important; 127 } 128 .mobile-bottom-menu.theme-custom .mobile-bottom-menu-item { 129 color: ' . esc_attr($text_color) . ' !important; 130 } 131 .mobile-bottom-menu.theme-custom .mobile-bottom-menu-item:hover, 132 .mobile-bottom-menu.theme-custom .mobile-bottom-menu-item:focus, 133 .mobile-bottom-menu.theme-custom .mobile-bottom-menu-item.active { 134 color: ' . esc_attr($active_color) . ' !important; 135 } 136 .mobile-bottom-menu.theme-custom .mobile-bottom-menu-item.active::after { 137 background: ' . esc_attr($active_color) . ' !important; 138 } 139 '; 140 141 wp_add_inline_style('surewp-app-bottom-menu', $custom_css); 142 } 120 143 121 144 // Enqueue search modal CSS … … 253 276 } 254 277 255 public function add_custom_css() {256 $settings = get_option('swpabm_settings');257 258 if (!isset($settings['enable_menu']) || $settings['enable_menu'] != '1') {259 return;260 }261 262 if ($settings['theme'] === 'custom') {263 $bg_color = isset($settings['custom_bg_color']) ? $settings['custom_bg_color'] : '#ffffff';264 $text_color = isset($settings['custom_text_color']) ? $settings['custom_text_color'] : '#666666';265 $active_color = isset($settings['custom_active_color']) ? $settings['custom_active_color'] : '#0073aa';266 267 $custom_css = '268 .mobile-bottom-menu.theme-custom {269 background: ' . esc_attr($bg_color) . ';270 }271 .mobile-bottom-menu.theme-custom .mobile-bottom-menu-item {272 color: ' . esc_attr($text_color) . ';273 }274 .mobile-bottom-menu.theme-custom .mobile-bottom-menu-item:hover,275 .mobile-bottom-menu.theme-custom .mobile-bottom-menu-item:focus,276 .mobile-bottom-menu.theme-custom .mobile-bottom-menu-item.active {277 color: ' . esc_attr($active_color) . ';278 }279 .mobile-bottom-menu.theme-custom .mobile-bottom-menu-item.active::after {280 background: ' . esc_attr($active_color) . ';281 }282 ';283 284 wp_add_inline_style('surewp-app-bottom-menu', $custom_css);285 }286 }287 288 278 public function render_bottom_menu() { 289 279 $settings = get_option('swpabm_settings'); -
surewp-app-bottom-menu/trunk/readme.txt
r3420054 r3420105 3 3 Tags: mobile menu, bottom menu, navigation, app menu, mobile navigation 4 4 Requires at least: 5.0 5 Tested up to: 6. 96 Stable tag: 1.1. 55 Tested up to: 6.8 6 Stable tag: 1.1.6 7 7 Requires PHP: 7.0 8 8 License: GPLv2 or later
Note: See TracChangeset
for help on using the changeset viewer.