| @@ -1,12 +1,13 @@ | ||
| 1 | 1 | |
| 2 | 2 | (function ($) { |
| 3 | - if (!window.mainwpPopup) { | |
| 4 | - window.mainwpPopup = function (selector) { | |
| 3 | + if (!globalThis.mainwpPopup) { | |
| 4 | + globalThis.mainwpPopup = function (selector) { | |
| 5 | 5 | let popup = mainwpListPopups.getItem(selector); |
| 6 | 6 | if (popup === null) { |
| 7 | 7 | popup = new Mainwp_InstancePopup(); |
| 8 | 8 | popup.initWrapper(selector); |
| 9 | + popup.initElements(); | |
| 9 | 10 | mainwpListPopups.pushItem(popup); |
| 10 | 11 | } |
| 11 | 12 | return popup; |
| 12 | 13 | }; |
| @@ -39,9 +40,13 @@ | ||
| 39 | 40 | title: '', |
| 40 | 41 | totalSites: 0, |
| 41 | 42 | progressMax: 0, // length of process bar. |
| 42 | 43 | progressInit: 0, // init value of process bar. |
| 44 | + hideProgress: false, | |
| 43 | 45 | statusText: '', |
| 46 | + contentMsg: '', | |
| 47 | + initVisibleContentMsg: false, | |
| 48 | + clearListItems: false, | |
| 44 | 49 | hideStatusText: false, |
| 45 | 50 | doCloseCallback: null, |
| 46 | 51 | init: function (data) { |
| 47 | 52 | data = data || {}; |
| @@ -49,13 +54,17 @@ | ||
| 49 | 54 | if (data.callback) { |
| 50 | 55 | this.actionsCloseCallback = data.callback; |
| 51 | 56 | delete data.callback; |
| 52 | 57 | } |
| 58 | + // default init values. | |
| 53 | 59 | let defaultVal = { |
| 54 | 60 | totalSites: 0, |
| 55 | 61 | progressMax: 0, |
| 56 | 62 | progressInit: 0, |
| 57 | - statusText: 'synced' | |
| 63 | + statusText: 'synced', | |
| 64 | + initVisibleContentMsg: false, | |
| 65 | + hideProgress: false, | |
| 66 | + clearListItems: false | |
| 58 | 67 | }; |
| 59 | 68 | this.doCloseCallback = true; // default is yes. |
| 60 | 69 | $.extend(this, defaultVal, data); |
| 61 | 70 | if (0 == this.totalSites) { |
| @@ -63,8 +72,13 @@ | ||
| 63 | 72 | } |
| 64 | 73 | this.initProgress(); |
| 65 | 74 | this.render(); |
| 66 | 75 | this.bindEvents(); |
| 76 | + | |
| 77 | + if (this.clearListItems) { | |
| 78 | + this.clearList(); | |
| 79 | + } | |
| 80 | + | |
| 67 | 81 | }, |
| 68 | 82 | initWrapper: function (el) { // may be call this very first to set custom wrapper. |
| 69 | 83 | this.overlayId = el; |
| 70 | 84 | this.$overlayElementId = $(this.overlayId); |
| @@ -81,26 +95,80 @@ | ||
| 81 | 95 | |
| 82 | 96 | if (!this.hideStatusText) { |
| 83 | 97 | this.setStatusText('0 / ' + this.totalSites + ' ' + this.statusText); |
| 84 | 98 | } |
| 85 | - this.$overlayElementId.find('.mainwp-modal-progress').progress(pData); | |
| 99 | + this.$progress = this.$overlayElementId.find('.mainwp-modal-progress'); | |
| 100 | + this.$progress.progress(pData); | |
| 86 | 101 | }, |
| 102 | + initElements: function () { | |
| 103 | + if (!this.$overlayElementId) return; | |
| 104 | + | |
| 105 | + this.$header = this.$overlayElementId.find('.header'); | |
| 106 | + this.$progress = this.$overlayElementId.find('.mainwp-modal-progress'); | |
| 107 | + this.$label = this.$progress.find('.label'); | |
| 108 | + this.$contentMsg = this.$overlayElementId.find('.sync-sites-content-massage'); | |
| 109 | + this.$list = this.$overlayElementId.find('#sync-sites-status'); | |
| 110 | + this.$actions = this.$overlayElementId.find('.mainwp-modal-actions'); | |
| 111 | + this.$content = this.$overlayElementId.find('.mainwp-modal-content'); | |
| 112 | + this.$wrap = this.$overlayElementId.find('.mainwp-popup-wrap'); | |
| 113 | + this.$backdrop = this.$overlayElementId.find('.mainwp-popup-backdrop'); | |
| 114 | + this.$closeBtn = this.$overlayElementId.find('.mainwp-modal-close'); | |
| 115 | + }, | |
| 87 | 116 | render: function () { |
| 117 | + if (!this.$overlayElementId) return; | |
| 118 | + | |
| 119 | + this.initProgressBatch(); | |
| 120 | + | |
| 88 | 121 | if (this.title) { |
| 89 | - this.$overlayElementId.find('.header').html(this.title); | |
| 122 | + this.$header.html(this.title); | |
| 90 | 123 | } |
| 91 | 124 | |
| 92 | - if (!this.progressMax) | |
| 93 | - this.$overlayElementId.find('.mainwp-modal-progress').hide(); // hide status and progress. | |
| 94 | - else | |
| 95 | - this.$overlayElementId.find('.mainwp-modal-progress').show(); | |
| 96 | - let self = this; | |
| 97 | - this.$overlayElementId.modal({ | |
| 98 | - onHide: function () { | |
| 99 | - self.onHideModal(); | |
| 100 | - } | |
| 101 | - }).modal('setting', 'closable', false).modal('show').modal('set active'); // trick to fix diplay issue. | |
| 125 | + if (this.hideProgress) { | |
| 126 | + this.$progress.hide(); | |
| 127 | + } else { | |
| 128 | + this.$progress.show(); | |
| 129 | + } | |
| 130 | + | |
| 131 | + if (this.initVisibleContentMsg && this.contentMsg) { | |
| 132 | + this.$contentMsg.html(this.contentMsg).show(); | |
| 133 | + } else { | |
| 134 | + this.contentMsg = ''; // clear caching msg. | |
| 135 | + this.$contentMsg.html('').hide(); | |
| 136 | + } | |
| 137 | + | |
| 138 | + this.$overlayElementId | |
| 139 | + .modal({ | |
| 140 | + onHide: () => this.onHideModal(), | |
| 141 | + allowMultiple: this.allowMultiple ?? false, | |
| 142 | + closable: false | |
| 143 | + }) | |
| 144 | + .modal('show') | |
| 145 | + .modal('set active'); // keep if still needed for your UI bug | |
| 102 | 146 | }, |
| 147 | + bindEvents: function () { | |
| 148 | + if (this.$closeBtn?.length) { | |
| 149 | + this.$closeBtn.off('click.mainwp').on('click.mainwp', () => this.close(true)); | |
| 150 | + } | |
| 151 | + }, | |
| 152 | + setTitle: function (title) { | |
| 153 | + this.$header?.html(title); | |
| 154 | + }, | |
| 155 | + setStatusText: function (label) { | |
| 156 | + this.$label?.html(label); | |
| 157 | + }, | |
| 158 | + clearList: function () { | |
| 159 | + this.$list?.empty(); | |
| 160 | + }, | |
| 161 | + setActionButtons: function (html) { | |
| 162 | + this.$actions?.html(html); | |
| 163 | + }, | |
| 164 | + getContentEl: function () { | |
| 165 | + return this.$content; | |
| 166 | + }, | |
| 167 | + setElementsZIndex: function (val) { | |
| 168 | + this.$wrap?.css('z-index', val); | |
| 169 | + this.$backdrop?.css('z-index', val); | |
| 170 | + }, | |
| 103 | 171 | onHideModal: function () { |
| 104 | 172 | if (this.doCloseCallback) { |
| 105 | 173 | // do call back when clicking on close button or clicking on dimmer. |
| 106 | 174 | typeof this.actionsCloseCallback === 'function' && this.actionsCloseCallback(); |
| @@ -105,69 +173,92 @@ | ||
| 105 | 173 | // do call back when clicking on close button or clicking on dimmer. |
| 106 | 174 | typeof this.actionsCloseCallback === 'function' && this.actionsCloseCallback(); |
| 107 | 175 | } |
| 108 | 176 | }, |
| 109 | - bindEvents: function () { | |
| 110 | - let self = this; | |
| 111 | - let closebuttonEl = this.$overlayElementId.find('.mainwp-modal-close'); | |
| 112 | - if (closebuttonEl.length > 0) { | |
| 113 | - $(closebuttonEl).on('click', function () { | |
| 114 | - self.close(true); | |
| 115 | - }); | |
| 116 | - } | |
| 117 | - | |
| 177 | + showProgress: function () { | |
| 178 | + this.$progress.show(); | |
| 118 | 179 | }, |
| 119 | - setTitle: function (title) { | |
| 120 | - this.$overlayElementId.find('.header').html(title); | |
| 180 | + getContentMsgEl: function () { | |
| 181 | + return this.$contentMsg; | |
| 121 | 182 | }, |
| 122 | - setStatusText: function (label) { | |
| 123 | - this.$overlayElementId.find('.mainwp-modal-progress').find('.label').html(label); | |
| 183 | + initProgressBatch: function () { | |
| 184 | + this._pendingCount = 0; | |
| 185 | + this._lastValue = 0; | |
| 186 | + this._flushTimer = null; | |
| 124 | 187 | }, |
| 125 | - getProgressValue: function () { | |
| 126 | - return this.$overlayElementId.find('.mainwp-modal-progress').progress('get value'); | |
| 188 | + updateStatusLabel: function (text) { | |
| 189 | + this.statusText = text; | |
| 190 | + this.setStatusText( | |
| 191 | + `${this._lastValue} / ${this.totalSites} ${this.statusText}` | |
| 192 | + ); | |
| 127 | 193 | }, |
| 128 | - setProgressValue: function (value) { | |
| 129 | - this.$overlayElementId.find('.mainwp-modal-progress').progress('set progress', value); | |
| 130 | - }, | |
| 131 | 194 | setProgressSite: function (value) { |
| 132 | - // progress label. | |
| 133 | - let lb = value + ' / ' + this.totalSites + ' ' + this.statusText; | |
| 134 | - this.setStatusText(lb); | |
| 135 | - let pVal = this.getProgressValue(); | |
| 136 | - pVal += 1; | |
| 137 | - this.setProgressValue(pVal); | |
| 195 | + if (!this.$progress) return; | |
| 196 | + | |
| 197 | + this._pendingCount = (this._pendingCount || 0) + 1; | |
| 198 | + this._lastValue = value; | |
| 199 | + | |
| 200 | + if (this._rafScheduled) return; | |
| 201 | + | |
| 202 | + this._rafScheduled = true; | |
| 203 | + | |
| 204 | + requestAnimationFrame(() => { | |
| 205 | + this.flushProgress(); | |
| 206 | + this._rafScheduled = false; | |
| 207 | + }); | |
| 138 | 208 | }, |
| 139 | - appendItemsList: function (left, right) { | |
| 140 | - if (this.$overlayElementId == null) | |
| 141 | - return; | |
| 209 | + flushProgress: function () { | |
| 210 | + if (!this.$progress) return; | |
| 142 | 211 | |
| 143 | - let row = '<div class="item">'; | |
| 144 | - row += '<div class="right floated content">'; | |
| 145 | - row += right; | |
| 146 | - row += '</div>'; | |
| 147 | - row += '<div class="content">'; | |
| 148 | - row += left; | |
| 149 | - row += '</div>'; | |
| 150 | - row += '</div>'; | |
| 212 | + // update label once | |
| 213 | + this.setStatusText( | |
| 214 | + `${this._lastValue} / ${this.totalSites} ${this.statusText}` | |
| 215 | + ); | |
| 151 | 216 | |
| 152 | - this.$overlayElementId.find('#sync-sites-status').append(row); | |
| 217 | + // batch increment | |
| 218 | + const current = this.$progress.progress('get value') || 0; | |
| 219 | + this.$progress.progress('set progress', current + this._pendingCount); | |
| 220 | + | |
| 221 | + // reset | |
| 222 | + this._pendingCount = 0; | |
| 223 | + this._flushTimer = null; | |
| 153 | 224 | }, |
| 154 | - clearList: function () { | |
| 155 | - this.$overlayElementId.find('#sync-sites-status').empty(); | |
| 225 | + getProgressValue: function () { | |
| 226 | + return this.$progress | |
| 227 | + ? this.$progress.progress('get value') | |
| 228 | + : 0; | |
| 156 | 229 | }, |
| 157 | - setActionButtons: function (html) { | |
| 158 | - this.$overlayElementId.find('.mainwp-modal-actions').html(html); | |
| 230 | + setProgressValue: function (value) { | |
| 231 | + if (this.$progress) { | |
| 232 | + this.$progress.progress('set progress', value); | |
| 233 | + } | |
| 159 | 234 | }, |
| 160 | - getContentEl: function () { | |
| 161 | - return this.$overlayElementId.find('.mainwp-modal-content'); | |
| 235 | + appendItemsList: function (left, right, { allowHtml = true } = {}) { | |
| 236 | + if (!this.$overlayElementId) return; | |
| 237 | + | |
| 238 | + const $list = this.$list || ( | |
| 239 | + this.$list = this.$overlayElementId.find('#sync-sites-status') | |
| 240 | + ); | |
| 241 | + | |
| 242 | + const $row = $('<div>', { class: 'item' }); | |
| 243 | + | |
| 244 | + const $right = $('<div>', { class: 'right floated content' }); | |
| 245 | + const $left = $('<div>', { class: 'content' }); | |
| 246 | + | |
| 247 | + if (allowHtml) { | |
| 248 | + $right.html(right); | |
| 249 | + $left.html(left); | |
| 250 | + } else { | |
| 251 | + $right.text(right); | |
| 252 | + $left.text(left); | |
| 253 | + } | |
| 254 | + | |
| 255 | + $row.append($right, $left); | |
| 256 | + $list.append($row); | |
| 162 | 257 | }, |
| 163 | - setElementsZIndex: function (val) { | |
| 164 | - this.$overlayElementId.find('.mainwp-popup-wrap').css('z-index', val); | |
| 165 | - this.$overlayElementId.find('.mainwp-popup-backdrop').css('z-index', val); | |
| 166 | - }, | |
| 167 | 258 | // close modal with executing callback or not executing callback. |
| 168 | 259 | close: function (execCallback) { |
| 169 | - this.doCloseCallback = typeof execCallback !== 'undefined' && execCallback; // do not do callback. | |
| 260 | + this.doCloseCallback = execCallback !== undefined && execCallback; // do not do callback. | |
| 170 | 261 | this.closePopup(); |
| 171 | 262 | }, |
| 172 | 263 | closePopup: function () { |
| 173 | 264 | this.$overlayElementId.modal('hide'); |