Batch edit flavors in stash js script

Hi, just wanted to share this little script I use to update my stash when all my flavors are gone and I order a ton of new ones. It can only update all at once and it will override yours existing values. It’s easy to implement other stuff like “Update only tpa or capella”, “Don’t overwrite set values” etc. but I don’t need it. If you want some feature please tell me and I might add it.

How to use:

  1. Go to your stash
  2. Open console in your browser (F12 or Ctrl+Shift+I in Chrome for example)
  3. Paste code from below into the console
  4. Run the function by typing in the console
    batchEdit(10, 5)
    where 10 is bottle size and 5 is cost

Code:

function isNumeric(n) {
	return !isNaN(parseFloat(n)) && isFinite(n);
}

function batchEdit (size, cost) {
	if (isNumeric(size) && isNumeric(cost)) {
		$("input[name^='ml']" ).each(function(){
			$(this).val(size);
		});
		$("input[name^='cost']" ).each(function(){
			$(this).val(cost);
		});
		alert("Success! Click \"Save\" to update stash.");
		return true;
	} else {
		alert("Error: input values are not numeric.");
		return false;
	}
}
1 Like

Update:
Added filtering by flavor names.
You can leave it blank if you want to update all your flavors.

Usage:
Open your flavor stash, copy the following string into your browser’s address bar and hit enter.
This will prompt you for size, cost and filter values and update data (you still want to click save to… actually save new values).
In case anyone wondering - this is the same code but processed with babel to work with older browsers.

javascript:'use strict';var _createClass=function(){function a(b,c){for(var e,d=0;d<c.length;d++)e=c[d],e.enumerable=e.enumerable||!1,e.configurable=!0,'value'in e&&(e.writable=!0),Object.defineProperty(b,e.key,e)}return function(b,c,d){return c&&a(b.prototype,c),d&&a(b,d),b}}();function _classCallCheck(a,b){if(!(a instanceof b))throw new TypeError('Cannot call a class as a function')}var BatchEdit=function(){function a(){_classCallCheck(this,a)}return _createClass(a,[{key:'run',value:function run(b,c,d){var e=$('tr[id^="flavor-"]');if(d&&0<d.length){var f=d.toLowerCase();e=jQuery.grep(e,function(g){return $(g).find('a.fname')[0].innerText.toLowerCase().includes(f)})}return this.isNumeric(b)&&this.isNumeric(c)&&($(e).find('input[name^=\'ml\']').each(function(){$(this).val(b)}),$(e).find('input[name^=\'cost\']').each(function(){$(this).val(c)}),!0)}},{key:'interactive',value:function interactive(){var b=prompt('Enter bottle size (numeric):'),c=prompt('Enter bottle cost (numeric):'),d=prompt('Enter name filter. Filtering is case insensetive. e.g. \'(cap)\'. Can be blank.'),e=this.run(b,c,d);e?alert('Success! Click "Save" to update stash.'):alert('Error: input values are not numeric.')}},{key:'isNumeric',value:function isNumeric(b){return!isNaN(parseFloat(b))&&isFinite(b)}}]),a}();function initInteractiveEdit(){var a=new BatchEdit;a.interactive()}initInteractiveEdit();

Alternatively copy code into your browser’s console and run with initInteractiveEdit();

You can still run edit function programmatically:

const be = new BatchEdit();
be.run(10, 2, '(CAP)');

Code:

class BatchEdit {
	/**
	* size: int = Bottle size input value. e.g. 10
	* cost: int = Cost input value. e.g. 2
	* nameIncludes: string = String to filter wanted flavors. Filtering is case insensetive. e.g. '(cap)' 
	**/
	run(size, cost, nameIncludes) {
		let flavors = $('tr[id^="flavor-"]');

		if (nameIncludes && nameIncludes.length > 0) {
			const matchSubstr = nameIncludes.toLowerCase();
			flavors = jQuery.grep(flavors, function(item) {
				return $(item).find('a.fname')[0].innerText
					.toLowerCase().includes(matchSubstr);
			});
		}

		if (this.isNumeric(size) && this.isNumeric(cost)) {
			$(flavors).find("input[name^='ml']" ).each(function(){
				$(this).val(size);
			});
			$(flavors).find("input[name^='cost']" ).each(function(){
				$(this).val(cost);
			});
			return true;
		} else {		
			return false;
		}
	}

	interactive() {
		const size = prompt("Enter bottle size (numeric):");
		const cost = prompt("Enter bottle cost (numeric):");
		const nameIncludes = prompt("Enter name filter. Filtering is case insensetive. e.g. '(cap)'. Can be blank.");

		const result = this.run(size, cost, nameIncludes);

		if (result) {			
			alert("Success! Click \"Save\" to update stash.");
		} else {
			alert("Error: input values are not numeric.");			
		}
		return;
	}

	isNumeric(n) {
		return !isNaN(parseFloat(n)) && isFinite(n)
	}
}

// run in interactive mode.
function initInteractiveEdit() {
	const be = new BatchEdit();
	be.interactive();
	return;
}

Since it was written in a couple minutes to help me update my flavor stash it’s not very well written. Also it depends on jQuery (used by the site itself so I went with it).

TODO:

  • Get rid of jQuery dependency
  • ???
  • Profit!

@daath Also can you consider supporting this feature natively?
I can not be the only one struggling with my laziness to update a bunch of flavors manually.
Thanks in advance!

1 Like

That’s cool tplk :smiley: My plan is to give the stash an overhaul soon - I might incorporate some of those features :slight_smile:

2 Likes