MediaWiki:Gadget-idle-util.js: Difference between revisions

From Idle Clans wiki
No edit summary
No edit summary
 
(9 intermediate revisions by the same user not shown)
Line 1: Line 1:
// REQUIRES oojs-ui-widgets
;(function($, mw, idleClans) {
idleClans.util = {
/**
* If we should print debug information to the console.
*/
DEBUG: false,
/**
* Send a debug message to the console.
*
* @param  {...*} arguments
*          The arguments to log.
*/
debug: function() {
if (!this.DEBUG) return;
var args = Array.prototype.slice.call(arguments);
console.log.apply(console, ["DEBUG:"].concat(args));
},
/**
* The gemstone prefixes for each tier.
*/
GEMSTONE_PREFIXES: [ "Normal", "Refined", "Great", "Elite", "Superior", "Outstanding", "Godlike" ],
/**
* Get the refined name for the given name and tier.
*
* If the tier is out of bounds, an error is logged and the name is
* returned with an error prefix.
*
* @param  {string} name
*          The name to prepend the prefix to.
* @param  {number} tier
*          The tier of the gemstone.
*
* @returns {string}
*          The refined name.
*/
getRefinedName: function(name, tier) {
if (tier < 0 || tier >= this.GEMSTONE_PREFIXES.length) {
mw.error("getRefinedName: Tier out of bounds (" + tier + ", " + this.GEMSTONE_PREFIXES.length + ")");
return "Err " + name;
}
return this.GEMSTONE_PREFIXES[tier] + " " + name;
},
// utils.tierify(["House", "Mansion", "Castle"]);
// utils.tierify([function(i) { return NAMES[i]; }, 10]);
/**
* Tierify the given supplier, adding "T1", "T2", etc. to the names.
*
* @param  {[function(number): string, number]|string[]} supplier
*          Either a tuple containing a function and a number, or an array
*          of names to tierify. If a tuple is provided, the function will
*          be used to supply the names based on the index, with the number
*          specifying how many tiers to create.
* @param  {string[]|string} [prepend]
*          Optionally, an array of names to prepend to the tier array.
* @param  {string[]|string} [append]
*          Optionally, an array of names to append to the tier array.
*/
tierify: function(supplier, prepend, append) {
prepend = prepend || [];
append = append || [];
if (!Array.isArray(prepend)) prepend = [prepend];
if (!Array.isArray(append)) append = [append];
// Get the names from the supplier.
var names = supplier;
if (typeof supplier[0] === 'function') {
names = [];
var nameSupplier = supplier[0];
var tierCount = supplier[1];
for (var i = 0; i < tierCount; i++)
names.push(nameSupplier(i));
}
// Tierify the names.
var tiered = names.map(function(name, index) {
return "(T" + (index + 1) + ") " + name;
});
// Add the prepended and appended names.
return prepend.concat(tiered, append);
},
/**
* Format the given number with commas.
*
* @param  {number} number
*          The number to format.
* @param  {number} [decimals]
*          The number of decimals to display.
*
* @returns {string}
*          The formatted number.
*/
formatNumber: function(number, decimals) {
decimals = decimals || 2;
return new Intl.NumberFormat('en-US', { maximumFractionDigits: decimals }).format(number);
},
number: {
/**
* Round the given value to the specified number of decimals using
* bankers rounding.
*
* This is mainly used by calculators to ensure the values are the
* same as the game (C# uses bankers rounding by default).
*
* @param  {number} value
*          The value to round.
* @param  {number} decimals
*          The maximum number of decimals to display.
*
* @returns {number}
*          The rounded value.
*/
bankersRound: function(value, decimals) {
value = parseFloat(value.toFixed(6)); // Try to fix floating point errors.
decimals = decimals || 2; // Default to 2 decimal places.
var x = value * Math.pow(10, decimals);
var r = Math.round(x);
var br = Math.abs(x) % 1 === 0.5 ? (r % 2 === 0 ? r : r-1) : r;
return br / Math.pow(10, decimals);
},
/**
* Round the given value to the specified number of decimals, removing
* any trailing zeros if necessary.
*
* @param  {number} value
*          The value to round.
* @param  {number} decimals
*          The maximum number of decimals to display.
*
* @returns {number}
*          The rounded value.
*/
toFixedSmall: function(value, decimals) {
return parseFloat(value.toFixed(decimals));
}
},
ui: {
/**
* Create a dropdown widget with the given items and optionally the
* selected item.
*
* @param  {(string|{label:string,header:boolean=,disabled:boolean=,hidden:boolean=})[]} items
*          The items to display in the dropdown widget.
* @param  {number} [selected]
*          Optionally, the index of the selected item.
* @param  {string} [label]
*          Optionally, the label for the dropdown widget.
*
* @returns {OO.ui.DropdownWidget}
*          The dropdown widget.
*/
dropdown: function(items, selected, label) {
var currentIndex = 0;
var dropdown = new OO.ui.DropdownWidget({
label: label,
menu: {
items: items.map(function (item, index) {
if (typeof item === 'string')
return new OO.ui.MenuOptionWidget({ data: currentIndex++, label: item });
var label = item.label || "Unknown";
var header = item.header || false;
var disabled = item.disabled || false;
var hidden = item.hidden || false;
if (header) {
label = $("<div style='text-align:center'>" + label + "</div>");
return new OO.ui.MenuSectionOptionWidget( { label: label } );
}
if (!hidden)
return new OO.ui.MenuOptionWidget({ data: currentIndex++, label: label,
disabled: disabled });
return new OO.ui.MenuOptionWidget({ data: currentIndex++, label: label, disabled: disabled,
invisibleLabel: hidden, $element: $("<div style='display:none'></div>") });
})
}
});
// We need to override the "below" key to have value "below".
// If we don't then it might go above the dropdown and hide
// items behind the navbar.
OO.ui.MenuSelectWidget.static.flippedPositions = {
below: 'below',
above: 'below',
top: 'bottom',
bottom: 'top'
};
if (selected !== undefined && typeof selected === 'number') {
if (selected < 0 || selected >= items.length)
mw.error("UI.dropdown: Selected index out of bounds (" + selected + ", " + items.length + ")");
else dropdown.getMenu().selectItemByData(selected);
}
return dropdown;
},
/**
* Create a button widget with the given label and flags.
*
* @param  {string} [label]
*          Optionally, the label for the button.
* @param  {string[]} [flags]
*          Optionally, the flags for the button.
*
* @returns {OO.ui.ButtonWidget}
*          The button widget.
*/
button: function(label, flags) {
label = label || "Button";
flags = flags || [];
return new OO.ui.ButtonWidget({ label: label, flags: flags });
},
/**
* Create a button input widget with the given label and flags.
*
* @param  {string} [label]
*          Optionally, the label for the button.
* @param  {string[]} [flags]
*          Optionally, the flags for the button.
*
* @returns {OO.ui.ButtonInputWidget}
*          The button input widget.
*/
buttonInput: function(label, flags) {
label = label || "Button";
flags = flags || [];
return new OO.ui.ButtonInputWidget({ label: label, flags: flags });
},
/**
/**
* Create a checkbox widget with an optional label and selected
* Create a checkbox widget with an optional label and selected

Latest revision as of 07:23, 11 June 2024

// REQUIRES oojs-ui-widgets
;(function($, mw, idleClans) {
	idleClans.util = {

		/**
		 * If we should print debug information to the console.
		 */
		DEBUG: false,

		/**
		 * Send a debug message to the console.
		 *
		 * @param   {...*} arguments
		 *          The arguments to log.
		 */
		debug: function() {
			if (!this.DEBUG) return;
			var args = Array.prototype.slice.call(arguments);
			console.log.apply(console, ["DEBUG:"].concat(args));
		},

		/**
		 * The gemstone prefixes for each tier.
		 */
		GEMSTONE_PREFIXES: [ "Normal", "Refined", "Great", "Elite", "Superior", "Outstanding", "Godlike" ],

		/**
		 * Get the refined name for the given name and tier.
		 *
		 * If the tier is out of bounds, an error is logged and the name is
		 * returned with an error prefix.
		 *
		 * @param   {string} name
		 *          The name to prepend the prefix to.
		 * @param   {number} tier
		 *          The tier of the gemstone.
		 *
		 * @returns {string}
		 *          The refined name.
		 */
		getRefinedName: function(name, tier) {
			if (tier < 0 || tier >= this.GEMSTONE_PREFIXES.length) {
				mw.error("getRefinedName: Tier out of bounds (" + tier + ", " + this.GEMSTONE_PREFIXES.length + ")");
				return "Err " + name;
			}
			return this.GEMSTONE_PREFIXES[tier] + " " + name;
		},

		// utils.tierify(["House", "Mansion", "Castle"]);
		// utils.tierify([function(i) { return NAMES[i]; }, 10]);

		/**
		 * Tierify the given supplier, adding "T1", "T2", etc. to the names.
		 *
		 * @param   {[function(number): string, number]|string[]} supplier
		 *          Either a tuple containing a function and a number, or an array
		 *          of names to tierify. If a tuple is provided, the function will
		 *          be used to supply the names based on the index, with the number
		 *          specifying how many tiers to create.
		 * @param   {string[]|string} [prepend]
		 *          Optionally, an array of names to prepend to the tier array.
		 * @param   {string[]|string} [append]
		 *          Optionally, an array of names to append to the tier array.
		 */
		tierify: function(supplier, prepend, append) {
			prepend = prepend || [];
			append = append || [];
			if (!Array.isArray(prepend)) prepend = [prepend];
			if (!Array.isArray(append)) append = [append];

			// Get the names from the supplier.
			var names = supplier;
			if (typeof supplier[0] === 'function') {
				names = [];
				var nameSupplier = supplier[0];
				var tierCount = supplier[1];

				for (var i = 0; i < tierCount; i++)
					names.push(nameSupplier(i));
			}

			// Tierify the names.
			var tiered = names.map(function(name, index) {
				return "(T" + (index + 1) + ") " + name;
			});

			// Add the prepended and appended names.
			return prepend.concat(tiered, append);
		},

		/**
		 * Format the given number with commas.
		 *
		 * @param   {number} number
		 *          The number to format.
		 * @param   {number} [decimals]
		 *          The number of decimals to display.
		 * 
		 * @returns {string}
		 *          The formatted number.
		 */
		formatNumber: function(number, decimals) {
			decimals = decimals || 2;
			return new Intl.NumberFormat('en-US', { maximumFractionDigits: decimals }).format(number);
		},

		number: {
			/**
			 * Round the given value to the specified number of decimals using
			 * bankers rounding.
			 *
			 * This is mainly used by calculators to ensure the values are the
			 * same as the game (C# uses bankers rounding by default).
			 *
			 * @param   {number} value
			 *          The value to round.
			 * @param   {number} decimals
			 *          The maximum number of decimals to display.
			 *
			 * @returns {number}
			 *          The rounded value.
			 */
			bankersRound: function(value, decimals) {
				value = parseFloat(value.toFixed(6)); // Try to fix floating point errors.
				decimals = decimals || 2; // Default to 2 decimal places.

				var x = value * Math.pow(10, decimals);
				var r = Math.round(x);
				var br = Math.abs(x) % 1 === 0.5 ? (r % 2 === 0 ? r : r-1) : r;
				return br / Math.pow(10, decimals);
			},

			/**
			 * Round the given value to the specified number of decimals, removing
			 * any trailing zeros if necessary.
			 *
			 * @param   {number} value
			 *          The value to round.
			 * @param   {number} decimals
			 *          The maximum number of decimals to display.
			 *
			 * @returns {number}
			 *          The rounded value.
			 */
			toFixedSmall: function(value, decimals) {
				return parseFloat(value.toFixed(decimals));
			}
		},

		ui: {

			/**
			 * Create a dropdown widget with the given items and optionally the
			 * selected item.
			 *
			 * @param   {(string|{label:string,header:boolean=,disabled:boolean=,hidden:boolean=})[]} items
			 *          The items to display in the dropdown widget.
			 * @param   {number} [selected]
			 *          Optionally, the index of the selected item.
			 * @param   {string} [label]
			 *          Optionally, the label for the dropdown widget.
			 *
			 * @returns {OO.ui.DropdownWidget}
			 *          The dropdown widget.
			 */
			dropdown: function(items, selected, label) {
				var currentIndex = 0;
				var dropdown = new OO.ui.DropdownWidget({
					label: label,
					menu: {
						items: items.map(function (item, index) {
							if (typeof item === 'string')
								return new OO.ui.MenuOptionWidget({ data: currentIndex++, label: item });

							var label = item.label || "Unknown";
							var header = item.header || false;
							var disabled = item.disabled || false;
							var hidden = item.hidden || false;

							if (header) {
								label = $("<div style='text-align:center'>" + label + "</div>");
								return new OO.ui.MenuSectionOptionWidget( { label: label } );
							}

							if (!hidden)
								return new OO.ui.MenuOptionWidget({ data: currentIndex++, label: label,
									disabled: disabled });

							return new OO.ui.MenuOptionWidget({ data: currentIndex++, label: label, disabled: disabled,
								invisibleLabel: hidden, $element: $("<div style='display:none'></div>") });
						})
					}
				});

				// We need to override the "below" key to have value "below".
				// If we don't then it might go above the dropdown and hide
				// items behind the navbar.
				OO.ui.MenuSelectWidget.static.flippedPositions = {
					below: 'below',
					above: 'below',
					top: 'bottom',
					bottom: 'top'
				};

				if (selected !== undefined && typeof selected === 'number') {
					if (selected < 0 || selected >= items.length)
						mw.error("UI.dropdown: Selected index out of bounds (" + selected + ", " + items.length + ")");
					else dropdown.getMenu().selectItemByData(selected);
				}

				return dropdown;
			},

			/**
			 * Create a button widget with the given label and flags.
			 *
			 * @param   {string} [label]
			 *          Optionally, the label for the button.
			 * @param   {string[]} [flags]
			 *          Optionally, the flags for the button.
			 *
			 * @returns {OO.ui.ButtonWidget}
			 *          The button widget.
			 */
			button: function(label, flags) {
				label = label || "Button";
				flags = flags || [];
				return new OO.ui.ButtonWidget({ label: label, flags: flags });
			},

			/**
			 * Create a button input widget with the given label and flags.
			 *
			 * @param   {string} [label]
			 *          Optionally, the label for the button.
			 * @param   {string[]} [flags]
			 *          Optionally, the flags for the button.
			 *
			 * @returns {OO.ui.ButtonInputWidget}
			 *          The button input widget.
			 */
			buttonInput: function(label, flags) {
				label = label || "Button";
				flags = flags || [];
				return new OO.ui.ButtonInputWidget({ label: label, flags: flags });
			},

			/**
			 * Create a checkbox widget with an optional label and selected
			 * state.
			 *
			 * @param   {boolean} [selected]
             *          Optionally, whether the checkbox is selected.
			 * @param   {string} [label]
			 *          Optionally, the label for the checkbox.
			 *
			 * @returns {OO.ui.CheckboxInputWidget|OO.ui.FieldLayout}
			 *          The checkbox widget, or a field layout with the checkbox
			 *          and the label.
			 */
			checkbox: function(selected, label) {
				var checkbox = new OO.ui.CheckboxInputWidget({ selected: selected });

				if (label !== undefined && typeof label === 'string') {
					return new OO.ui.FieldLayout(checkbox, { label: label, align: 'inline' });
				}

				return checkbox;
			},

			/**
			 * Create a toggle switch widget with an optional initial state.
			 *
			 * @param   {boolean} [switched]
			 *          Optionally, whether the switch is on.
			 *
			 * @returns {OO.ui.ToggleSwitchWidget}
			 *          The toggle switch widget.
			 */
			switch: function(switched) {
				switched = switched || false;
				return new OO.ui.ToggleSwitchWidget({ value: switched });
			}
		}
	}
})(window.jQuery, window.mw, window.idleClans = window.idleClans || {});