// CellarTracker Bulk Purchase script
// version 0.81 BETA
// 2008-08-22
// Copyright (c) 2008-2009, Tom Shields
// Released under the Apache license
//
// --------------------------------------------------------------------
//
// This is a Greasemonkey user script.  To install it, you need
// Greasemonkey 0.8 or later: http://www.greasespot.net/
// Then restart Firefox and revisit this script.
// Under Tools, there will be a new menu item to "Install User Script".
// Accept the default configuration and install.
//
// To uninstall, go to Tools/Manage User Scripts,
// select "CellarTracker Bulk Purchase", and click Uninstall.
//
// Hi all.  I've been a user of CellarTracker (http://www.cellartracker.com/) for years, and I generally find it functional and easy to use.  But there's one typical (for me) use case that I find cumbersome: entering a series of bottles that I order from a mailing list offering.  In fairness, I've never voiced this complaint before, and there may be a solution I haven't found, but it's been annoying me for years.  So, I wrote some code to solve it.
//
// I used a Firefox extension called GreaseMonkey to write client-side Javascript that actually edits one of the CellarTracker pages in the browser to provide additional functionality.  In this case, if you are in the Purchase Wine results page, sorted by Vintage, it will add fields to allow you to purchase standard bottles of multiple wines in one go.  You can enter the purchase place and delivery date once, then enter a few quantities and prices, and click one button to have them all entered.
//
// A number of caveats: the orders are entered with purchase date today, and the bottles are all 750ml.  Delivery is always pending, although you can easily check them off and add them to your cellar immediately as well.  I don't have the "store" drop-down, so you need to enter it every time (I just use "Winery" in my case).  And as always, this is beta code, and while I make an effort to check for errors, if this screws up your wine database, you don't get to sue me. No warranty whatsoever.  Happy to hear about bugs - ts at oxyfish.com - but no guarantees to fix them.
//
// This code is released under the Apache license, so Eric, if you want to take it and put it in the product, feel free.
//
// --------------------------------------------------------------------
//
// ==UserScript==
// @name          CellarTracker Bulk Purchase
// @namespace     http://www.oxyfish.com/software/
// @description   Adds a bulk purchase capability to CellarTracker
// @include       http://www.cellartracker.com/pickproducer.asp?*
// ==/UserScript==

function dosubmits(event) {
	// alert("Submitting...");
	var winenum, num, cost, where, deliverydate;
	var error = 0;
	
	var now = new Date();
	var today = (1+now.getMonth())+"/"+now.getDate()+"/"+now.getFullYear();
	
	for (var x=0; x<window.document.getElementsByTagName('input').length; x++) {
		inputfield = window.document.getElementsByTagName('input')[x];
		
		if (!(fieldname = inputfield.getAttribute('name'))) { continue; } // get around null name crash
		
		if (fieldname.search("bulkdate")==0) {
			deliverydate = inputfield.value;
			var validformat=/^\d\d?\/\d\d?\/\d\d(\d\d)?$/ // check for format validity
			if (!validformat.test(deliverydate)) {
				alert("Please enter date as mm/dd/yyyy and submit again.");
				error = 1; break;
			}
			
		} else if (fieldname.search("bulkplace")==0) {
			where = inputfield.value;
			var blankRE=/^\s*$/;
			if (blankRE.test(where)) { // place should not be blank
				alert("Please enter a place of purchase and submit again.");
				error = 1; break;
			}
			
		} else if (fieldname.search("n_")==0) {
			num = parseInt(inputfield.value);
			
		} else if (fieldname.search("c_")==0) {
			cost = parseInt(inputfield.value);
			if ((cost > 0) && (num > 0)) {
				// we got one, build URLfor submission
				winenum = fieldname.substr(2);
				alert("Entering purchase of "+num+" bottles of wine #"+winenum+" at $"+cost+" from "+where+
				      " for delivery on "+deliverydate);
				submiturl = "/purchase.asp?iWine="+winenum+"&iPurchase=0&Quantity="+num+
							"&Size=750ml&BottleCost="+cost+"&StoreName=&StoreName_new="+escape(where)+
							"&PurchaseDate="+escape(today)+"&DeliveryDate="+escape(deliverydate)+
							"&OrderNumber=&DeliveryState=pending&Action=Add";
				// alert(submiturl);

				// submit request
				req = new XMLHttpRequest();
				req.open("GET", submiturl, false);
				req.send("");
				
				// check response - since it's sychronous, should be available here
				var errRE = /(VALIDATION ERROR[^<]*)</
				var iserr = errRE.exec(req.responseText);
				if (iserr) {
					alert(iserr[1]);
				}
			}
			cost = num = winenum = 0;
		}
	}
	
	// when done, go see the pending deliveries unless there was an error
	if (!error) {
		window.location.href = "http://www.cellartracker.com/list.asp?table=Pending";
	}
}

// start of main code

// check if sorted by vintage - not very robust code here...
if (!document.forms[1].elements[4].checked) {
	exit();
}
// alert("Vintage!");

// find the right table
winetable = document.getElementsByTagName('table')[6]; // once again not that robust
winetbody = winetable.getElementsByTagName('tbody')[0];
firstrow = winetbody.childNodes[0];

// create and place the row with the input elements
newcell = document.createElement('td');
newcell.innerHTML = "Place of purchase: <input type='text' name='bulkplace' style='width:150px'> Delivery Date: <input type='text' name='bulkdate' style='width:150px'>";
newcell.setAttribute('colspan','3');
newcell.setAttribute('style','BORDER-BOTTOM: 1px solid white;font-size:13px;text-align:center;');

newbutton = document.createElement('input');
newbutton.setAttribute('onclick', dosubmits + "; dosubmits(this);");
newbutton.setAttribute('type','button');
newbutton.setAttribute('value','Bulk Purchase');
newcell.appendChild(newbutton);

newrow = document.createElement('tr');
newrow.appendChild(newcell);
winetbody.insertBefore(newrow, firstrow);

// edit all the table rows to add input elements
for (var x=0; x<winetbody.getElementsByTagName('a').length; x++) {
	anchor = winetbody.getElementsByTagName('a')[x];
	href= anchor.getAttribute('href');
	if (href.search('wine.asp')==0) {
		winenum = href.substr(15); // strip out only wine number
		newtext = document.createElement('nobr');
		newtext.innerHTML = " # <input type='text' name='n_" + winenum + "' style='width:50px'> $ <input type='text' name='c_" + winenum + "' style='width:50px'>";
		anchor.parentNode.appendChild(newtext);
	}
}
