script.js
176 lines
| 1 | (function ($) { |
| 2 | |
| 3 | var nonce = bmi_backup_banner.dismiss_nonce; |
| 4 | var pluginUrl = bmi_backup_banner.plugin_url; |
| 5 | // Position the wavy arrow from the banner to the sidebar menu item |
| 6 | function positionArrow() { |
| 7 | if (window.innerWidth < 1200) { |
| 8 | $('#bmi-backup-banner-arrow').hide(); |
| 9 | return; |
| 10 | } |
| 11 | var $arrow = $('#bmi-backup-banner-arrow'); |
| 12 | var $banner = $('#bmi-backup-banner'); |
| 13 | var $menuItem = $('#adminmenu').find('li.toplevel_page_backup-migration'); |
| 14 | |
| 15 | if (!$menuItem.length || !$arrow.length || !$banner.length) return; |
| 16 | |
| 17 | // Position banner so its bottom is 50px below the menu item's bottom |
| 18 | var menuRect = $menuItem[0].getBoundingClientRect(); |
| 19 | var bannerRect = $banner[0].getBoundingClientRect(); |
| 20 | |
| 21 | // Width = horizontal distance between the menu item's right edge and the banner's left edge |
| 22 | var arrowWidth = bannerRect.left - menuRect.right + 45; |
| 23 | |
| 24 | if (arrowWidth <= 0) { |
| 25 | $arrow.hide(); |
| 26 | return; |
| 27 | } |
| 28 | |
| 29 | // Left of arrow at the right edge of the menu item (bottom border) |
| 30 | var arrowLeft = menuRect.right - 40; |
| 31 | |
| 32 | // Vertical span: from menu item bottom to banner bottom-left corner |
| 33 | var arrowTop = menuRect.bottom + 5; |
| 34 | |
| 35 | $arrow.css({ |
| 36 | left: arrowLeft + 'px', |
| 37 | top: arrowTop + 'px', |
| 38 | width: arrowWidth + 'px', |
| 39 | display: 'block' |
| 40 | }); |
| 41 | |
| 42 | // Move banner so its bottom-left corner aligns with the arrow's right end |
| 43 | var arrowBottom = arrowTop + $arrow[0].getBoundingClientRect().height; |
| 44 | var bannerHeight = $banner[0].offsetHeight + 8; |
| 45 | $banner.css({ |
| 46 | top: (arrowBottom - bannerHeight) + 'px', |
| 47 | transform: 'translateX(-50%)' |
| 48 | }); |
| 49 | } |
| 50 | |
| 51 | // Reveal banner elements once page is fully loaded |
| 52 | function showBanner() { |
| 53 | // Find the Backup Migration sidebar menu item |
| 54 | var $menuItem = $('#adminmenu').find('li.toplevel_page_backup-migration'); |
| 55 | |
| 56 | // Highlight the sidebar menu item (exclude from overlay) |
| 57 | if ($menuItem.length) { |
| 58 | $menuItem.addClass('bmi-backup-banner--sidebar-highlight'); |
| 59 | } |
| 60 | |
| 61 | $('#adminmenu li').not('#toplevel_page_backup-migration, #toplevel_page_backup-migration *').each(function () { |
| 62 | $(this).addClass('bmi-menu-dim'); |
| 63 | }); |
| 64 | $('.wp-menu-separator').css('margin', '0'); |
| 65 | positionArrow(); |
| 66 | $('#bmi-backup-banner-overlay').addClass('bmi-backup-banner--ready'); |
| 67 | $('#bmi-backup-banner').addClass('bmi-backup-banner--ready'); |
| 68 | $('#bmi-backup-banner-arrow').addClass('bmi-backup-banner--ready'); |
| 69 | |
| 70 | // Re-emit resize so position is recalculated with transitions now active |
| 71 | requestAnimationFrame(function () { |
| 72 | window.dispatchEvent(new Event('resize')); |
| 73 | }); |
| 74 | } |
| 75 | |
| 76 | $(window).on('resize', positionArrow); |
| 77 | |
| 78 | if (document.readyState === 'complete') { |
| 79 | showBanner(); |
| 80 | } else { |
| 81 | $(window).on('load', showBanner); |
| 82 | } |
| 83 | |
| 84 | // Dismiss helper |
| 85 | function dismissBanner(callback) { |
| 86 | $.post(ajaxurl, { |
| 87 | action: 'dismiss_bmi_backup_banner', |
| 88 | token: 'bmi_backup_banner', |
| 89 | nonce: nonce, |
| 90 | }).done(async function (res) { |
| 91 | if (callback) await callback(); |
| 92 | }).fail(async function (err) { |
| 93 | console.error(err); |
| 94 | if (callback) await callback(); |
| 95 | }); |
| 96 | } |
| 97 | |
| 98 | function hideBanner() { |
| 99 | var $menuItem = $('#adminmenu').find('li.toplevel_page_backup-migration'); |
| 100 | $('#bmi-backup-banner').hide(); |
| 101 | $('#bmi-backup-banner-overlay').hide(); |
| 102 | $('#bmi-backup-banner-arrow').hide(); |
| 103 | $('.bmi-menu-dim').removeClass('bmi-menu-dim'); |
| 104 | $('#adminmenu, #adminmenuwrap').css('pointer-events', 'auto'); |
| 105 | $menuItem.removeClass('bmi-backup-banner--sidebar-highlight'); |
| 106 | clearInterval(countdownInterval); |
| 107 | } |
| 108 | |
| 109 | // CTA button: dismiss + redirect to BMI page |
| 110 | $('.bmi-backup-banner__cta').on('click', function (e) { |
| 111 | e.preventDefault(); |
| 112 | var href = $(e.currentTarget).attr('href'); |
| 113 | dismissBanner(function () { |
| 114 | hideBanner(); |
| 115 | if (href) window.location.href = href; |
| 116 | }); |
| 117 | }); |
| 118 | |
| 119 | $('.bmi-backup-banner__install-btn').on('click', function (e) { |
| 120 | e.preventDefault(); |
| 121 | var href = $(e.currentTarget).attr('href'); |
| 122 | dismissBanner(function () { |
| 123 | hideBanner(); |
| 124 | if (href) window.open(href, '_blank'); |
| 125 | }); |
| 126 | }); |
| 127 | // Close button: dismiss only |
| 128 | $('.bmi-backup-banner__close').on('click', function (e) { |
| 129 | e.preventDefault(); |
| 130 | dismissBanner(function () { |
| 131 | hideBanner(); |
| 132 | }); |
| 133 | }); |
| 134 | |
| 135 | // Clicking the sidebar menu item should also dismiss the banner |
| 136 | $('#toplevel_page_backup-migration a').on('click', function (e) { |
| 137 | e.preventDefault(); |
| 138 | var href = $(this).attr('href'); |
| 139 | dismissBanner(function () { |
| 140 | hideBanner(); |
| 141 | if (href) window.location.href = href; |
| 142 | }); |
| 143 | }); |
| 144 | |
| 145 | function updateCountdown() { |
| 146 | if (!bmi_backup_banner.expiring_at) { |
| 147 | $('#changeable-text').text('before it expires!'); |
| 148 | return; |
| 149 | } |
| 150 | |
| 151 | var remaining = Math.floor(bmi_backup_banner.expiring_at - Date.now() / 1000); |
| 152 | |
| 153 | if (remaining <= 0) { |
| 154 | $('#changeable-text').text('it has expired!'); |
| 155 | clearInterval(countdownInterval); |
| 156 | return; |
| 157 | } |
| 158 | |
| 159 | var hours = Math.floor(remaining / 3600); |
| 160 | var minutes = Math.floor((remaining % 3600) / 60); |
| 161 | |
| 162 | var text = 'It expires in '; |
| 163 | if (hours > 0) text += hours + ' hour' + (hours !== 1 ? 's' : '') + ' and '; |
| 164 | if (hours > 0 || minutes > 0) text += minutes + ' minute' + (minutes !== 1 ? 's' : ''); |
| 165 | |
| 166 | $('#changeable-text').text(text); |
| 167 | positionArrow(); |
| 168 | } |
| 169 | |
| 170 | updateCountdown(); |
| 171 | var countdownInterval = setInterval(updateCountdown, 1000); |
| 172 | |
| 173 | |
| 174 | |
| 175 | })(jQuery); |
| 176 |