diff --git a/CHANGELOG.md b/CHANGELOG.md index 754196919..c382a3b6f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added -* +* Add debouncer `initialsDebounce` defaulting to 275 for `setInitials` and `setInitialsExtra` methods - [#357](https://github.com/ripe-tech/ripe-sdk/issues/357) ### Changed diff --git a/README.md b/README.md index dd79945be..60ef22470 100644 --- a/README.md +++ b/README.md @@ -312,6 +312,7 @@ if (ripe.isOAuthPending()) { | `usePrice` | *boolean* | Enables the fetch price feature every time a new part is set. True by default. | | `useSync` | *boolean* | Enables the part synchronization feature. False by default. | | `useInitialsBuilderLogic` | *boolean* | Enables the usage of the client-side initials builder logic defined in the 3DB, instead of the default one. True by default. | +| `initialsDebounce` | *number* | The debounce time (in milliseconds) for every initials set request in ms. 275 by default and 0 to disable. | ## Browser Support diff --git a/src/js/base/ripe.js b/src/js/base/ripe.js index be23db179..7afac758d 100644 --- a/src/js/base/ripe.js +++ b/src/js/base/ripe.js @@ -498,7 +498,9 @@ ripe.Ripe.prototype.config = async function(brand, model, options = {}) { // in case the initials extra are defined then runs the setting of the initials // extra on the current instance (without update events) if (options.initialsExtra) { - const setInitialsExtraPromise = this.setInitialsExtra(options.initialsExtra, false); + const setInitialsExtraPromise = this.setInitialsExtra(options.initialsExtra, false, false, { + immediate: true + }); if (options.safe) await setInitialsExtraPromise; } @@ -637,6 +639,7 @@ ripe.Ripe.prototype.setStructure = async function(structure, safe = true) { * - 'useCombinations' - If the combinations should be loaded as part of the initial RIPE loading. * - 'usePrice' - If the price should be automatically retrieved whenever there is a customization change. * - 'useDiag' - If the diagnostics module should be used. + * - 'initialsDebounce' - The debounce time to consider for every initials set request in ms (0 to not debounce). */ ripe.Ripe.prototype.setOptions = function(options = {}) { this.options = options; @@ -687,6 +690,8 @@ ripe.Ripe.prototype.setOptions = function(options = {}) { this.options.useInitialsBuilderLogic === undefined ? true : this.options.useInitialsBuilderLogic; + this.initialsDebounce = + this.options.initialsDebounce === undefined ? 275 : this.options.initialsDebounce; // in case the requested format is the "dynamic" lossless one // tries to find the best lossless image format taking into account @@ -808,9 +813,14 @@ ripe.Ripe.prototype.setInitials = async function( override = false, params = {} ) { + if (!params.immediate && this.initialsDebounce) { + this._setInitialsDebounced(initials, engraving, events, override, params); + return; + } + if (typeof initials === "object") { events = engraving === undefined ? true : engraving; - const result = await this.setInitialsExtra(initials, events); + const result = await this.setInitialsExtra(initials, events, override, params); return result; } @@ -897,6 +907,11 @@ ripe.Ripe.prototype.setInitialsExtra = async function( override = false, params = {} ) { + if (!params.immediate && this.initialsDebounce) { + this._setInitialsExtraDebounced(initialsExtra, events, override, params); + return; + } + const groups = Object.keys(initialsExtra); const isEmpty = groups.length === 0; const mainGroup = groups.includes("main") ? "main" : groups[0]; @@ -1803,6 +1818,39 @@ ripe.Ripe.prototype._setParts = async function(update, events = true) { } }; +/** + * @ignore + */ +ripe.Ripe.prototype._setInitialsDebounced = function( + initials, + engraving, + events = true, + override = false, + params = {} +) { + if (this.setInitialsTimeout) clearTimeout(this.setInitialsTimeout); + this.setInitialsTimeout = setTimeout(() => { + const extraParams = { ...params, immediate: true }; + this.setInitials(initials, engraving, events, override, extraParams); + }, this.initialsDebounce); +}; + +/** + * @ignore + */ +ripe.Ripe.prototype._setInitialsExtraDebounced = function( + initialsExtra, + events = true, + override = false, + params = {} +) { + if (this.setInitialsTimeout) clearTimeout(this.setInitialsTimeout); + this.setInitialsTimeout = setTimeout(() => { + const extraParams = { ...params, immediate: true }; + this.setInitialsExtra(initialsExtra, events, override, extraParams); + }, this.initialsDebounce); +}; + /** * @ignore */ diff --git a/test/js/base/ripe.js b/test/js/base/ripe.js index 9a0c8c0d6..f8bf26b36 100644 --- a/test/js/base/ripe.js +++ b/test/js/base/ripe.js @@ -9,7 +9,10 @@ describe("Ripe", function() { it("should be able to get a simple structure", async () => { let result; - const instance = await new ripe.Ripe("swear", "vyner", { noBundles: true }); + const instance = await new ripe.Ripe("swear", "vyner", { + noBundles: true, + initialsDebounce: 0 + }); await instance.isReady(); result = await instance.getStructure(); @@ -188,7 +191,7 @@ describe("Ripe", function() { describe("#setInitials()", async function() { it("should be able to set initials", async () => { - const instance = await new ripe.Ripe({ noBundles: true }); + const instance = await new ripe.Ripe({ noBundles: true, initialsDebounce: 0 }); await instance.isReady(); assert.strictEqual(instance.initials, "");