// -----------------------------------------------------
// Title: Form Help
// version: 0.1
// Date: 2006-03-18
// Author: Gez Lemon
// Copyright (c) 2006, Juicy Studio
// Requires Greasemonkey 0.6.4 or higher
// -----------------------------------------------------
//
// ==UserScript==
// @name Form Help
// @namespace http://juicystudio.com/
// @description Allows textareas to be resized, and drop-down lists to be permanently open.
// @include *
// @exclude http://gmail.google.com/*
// @exclude http://mail.google.com/mail/*
// ==/UserScript==

// SETUP VARIABLES FOR THE SCRIPT
// ==============================

// bImage - true to display images for resizing textareas, and false for using text 
var bImage = true;

// bExpandDropdown - true to automatically expand dropdown lists, and false to leave as a dropdown 
var bExpandDropdown = true;

// iExpandSize - The maximum number of items to expand for a dropdown list.
var iExpandSize = 10;


// =====================================
// END OF SETUP VARIABLES FOR THE SCRIPT

setup();

function setup()
{
	var bXML = (document.xmlVersion === null) ? false : true;
	var objBody = getElementsByName(document, 'body', bXML)[0];
	var objHead = getElementsByName(document, 'head', bXML)[0];
	var objList, iCounter, iInner;

	if (!objBody || !objHead)
		return;

	var objAreas = getElementsByName(objBody, 'textarea', bXML);
	var objLabels = getElementsByName(objBody, 'label', bXML);
	var objSpan, strLabel;

	if (bExpandDropdown)
		var objSelects = getElementsByName(objBody, 'select', bXML);

	if (!objAreas && !objSelects)
		return;

	for (iCounter=0; iCounter<objAreas.length; iCounter++)
	{
		strLabel = getLabel(objAreas[iCounter], objLabels);
		objList = createElement('ul', bXML);
		objList.setAttribute('class', 'jsgmtextarearesizer');
		for (iInner=0; iInner<4; iInner++)
			objList.appendChild(addAnchor(objAreas[iCounter], strLabel, bXML, iInner + 1));

		objAreas[iCounter].parentNode.insertBefore(objList, objAreas[iCounter]);
	}

	if (bExpandDropdown)
	{
		if (isNaN(iExpandSize))
			iExpandSize = 10;

		for (iCounter=0; iCounter<objSelects.length; iCounter++)
			objSelects[iCounter].setAttribute('size', (objSelects[iCounter].childNodes.length<iExpandSize)?objSelects[iCounter].childNodes.length:iExpandSize);
	}

	var objCSS = createElement('style', bXML);

	objCSS.setAttribute('id', 'jsgmFormStyles');
	objCSS.setAttribute('type', 'text/css');

	var strCSS = getCSSString();

	objCSS.appendChild(document.createTextNode(strCSS));
	objHead.appendChild(objCSS);
}

function addAnchor(objArea, strLabel, bXML, iAction)
{
	var objItem = createElement('li', bXML);
	var objAnchor = createElement('a', bXML);
	var objIncrease = new increaseArea(objAnchor, objArea, iAction);

	objAnchor.setAttribute('href', '#' + objArea.getAttribute('id'));
	objIncrease.initialise();

	if (bImage)
	{
		var objImage = createElement('img', bXML);

		switch (iAction)
		{
			case 1:
					objImage.setAttribute('src', 'data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%0B%00%00%00%14%08%06%00%00%00%5B%2C%C7h%00%00%00%04sBIT%08%08%08%08%7C%08d%88%00%00%00%09pHYs%00%00%0B%12%00%00%0B%12%01%D2%DD~%FC%00%00%00%16tEXtCreation%20Time%0003%2F17%2F06f%E1I%C1%00%00%00%20tEXtSoftware%00Macromedia%20Fireworks%20MX%BB%91*%24%00%00%00%EDIDATx%9C%7D%93Qn%021%10C%DF8%9C%A8Z%B8Q%81%9E%A8p%25%CA%91%C8%B8%1Fl%20d%17%2CE%CA*%F6z%C6%93%84m%06%14%DB%B7%88%88%F1%40%E3w%3Ao%DBc%01%A8%9F%C8Jg%9D%0E%050%BBc%D1(%D0H%D4l%9E%CE%85%40%802%B3N%FB\'%B1!%9D%EC~%9E%82%F0%DC%A1m%8C%99%F6%05%09%24q%F9%AD%D8%A6%F5%AA%B6%22%A2%B0%08%86%9CS%11%A0%0D%3C(%8B%A8%3AxL%E3U%B2t!%BA%A1%08%A8%FD%90%22%C2%FD%0F7%A3%D5%CA%E0%1E%E8%C9%D8f%7B%14%11A%10%5CN%F5%3D%F9.%98MV%0C%FA%06WZZ%96%E1%0F%F5%06%90m%1F%B6e%BBN%07!%05C%1A%00%FC%9D%12%40-%BA%C5Ej%B8%9E%DD%1C%1E5%A7B%E5z%AE%A4%D7%89%F7%AE%EC~%A9f%F5%D77%9E%F1r%1E%2B%CFJ%B6%EB%DA%B3%FA%07.%84%97%9C%FC%D6%B8m%00%00%00%00IEND%AEB%60%82');
					objImage.setAttribute('alt', 'Increase height for ' + strLabel);
					objAnchor.setAttribute('title', 'Increase height for ' + strLabel);
				break;
			case 2:
					objImage.setAttribute('src', 'data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%0B%00%00%00%14%08%06%00%00%00%5B%2C%C7h%00%00%00%04sBIT%08%08%08%08%7C%08d%88%00%00%00%09pHYs%00%00%0B%12%00%00%0B%12%01%D2%DD~%FC%00%00%00%16tEXtCreation%20Time%0003%2F17%2F06f%E1I%C1%00%00%00%20tEXtSoftware%00Macromedia%20Fireworks%20MX%BB%91*%24%00%00%00%EFIDATx%9C%7D%93Qr%830%10C%DF%8A%9C%A8Cr%A3%26%F4DM%AE%94%E6H%F5%AA%1F%18j%0C%13%CD%F8%03%24%EDz%C5%12%B6%A9%08%20%D9%C2%80%96%87%D3%86%B19O%22%22%08%82%E7%BDl%9C%1B%F1l%A8%05%A3g%9A%16%B5%E5%5B%9C%AA%C8%00%11%BBr%ED%1C%11%B6e%BB%8C7!%05%CD%C0%AB%F9%E7%9E%00%8AJ*%9De%BC%0D%A8%2B%FEzx%E9%B0%DE9%15%1A%5E%8FB%FAX8Oe%B7G%25%8B%3F%3Eq%C5%86%8F%F6%8E%15%B2%5D%E2%60Z%F5%2F8L%F8X%ACt%FE%9E%A7%01%A0%BC%13%AF%89%80%B9L%83z%83z%E1%12%5D%3Aw%06%01%CA%CC2%5E%F7%19%A7%93%CB%D7%BF!%5C%E3%B0%8D1%E3u%40%02I%3C%BF%CB%1CY%0DF%CB%89%88%E1%60%95%B2F(%40%CB%22%C1%9B%C8%16%CD%3E%E7h%E9%8Ej%BE%A0%80%D2m%DD%E6%B7%FA%03u%FB%94%99%25%DE9%D0%00%00%00%00IEND%AEB%60%82');
					objImage.setAttribute('alt', 'Decrease height for ' + strLabel);
					objAnchor.setAttribute('title', 'Decrease height for ' + strLabel);
				break;
			case 3:
					objImage.setAttribute('src', 'data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%14%00%00%00%0B%08%06%00%00%00%7F%09%ADC%00%00%00%04sBIT%08%08%08%08%7C%08d%88%00%00%00%09pHYs%00%00%0B%12%00%00%0B%12%01%D2%DD~%FC%00%00%00%16tEXtCreation%20Time%0003%2F17%2F06f%E1I%C1%00%00%00%20tEXtSoftware%00Macromedia%20Fireworks%20MX%BB%91*%24%00%00%00%B5IDATx%9C%8DR%C1%0D%C3%20%10%B3%8F%91%9A%AE%D4t%A4d%A5%A6%2Bq%EE%23P.%04E%B1d%C1%C36%E6%80%92%D0%81%00%BC%ACW%D0Hc%03%A1%17%F1%1D%9Ct%7D%A0%9E%EF%D1%19cL3O%A1%D1%AD%22%00%DA%B5%23%D5q%18%CA2%C3%18%062%ECA%7C%96%1C%CDC%7CW%01%00M%92%1E%AF%A3PR%E3%CDq%D6%A6F2mk%86%07%9F%14y%2F%B06%ACW6%97%E7iNHFl%8B%1F%82%E2%08%06%AD%FEa%40%7B%147Z%FA%AE%19%BEW%15w%18I%2B%3Av%3C%85%01%EDQ*LR%26)%8C%FFhD5%1E%EA%F7%26\'%99z%D1%05N%BA%1Fl%83e.%D5Z%12%25%00%00%00%00IEND%AEB%60%82');
					objImage.setAttribute('alt', 'Increase width for ' + strLabel);
					objAnchor.setAttribute('title', 'Increase width for ' + strLabel);
				break;
			case 4:
					objImage.setAttribute('src', 'data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%14%00%00%00%0B%08%06%00%00%00%7F%09%ADC%00%00%00%04sBIT%08%08%08%08%7C%08d%88%00%00%00%09pHYs%00%00%0B%12%00%00%0B%12%01%D2%DD~%FC%00%00%00%16tEXtCreation%20Time%0003%2F17%2F06f%E1I%C1%00%00%00%20tEXtSoftware%00Macromedia%20Fireworks%20MX%BB%91*%24%00%00%00%BBIDATx%9C%85S%5B%0E%C3%20%0C%B3%C3%91%D6%5Di%DD%91%DA%2B%AD%BB%12%F1%3E%0AmFA%B5d%09%11%C7y%08(%09%0D%04%80%EDe%07%04%E0%AD%D6%06%E2K%95%0E%BC%A7%EB%1AN3%EFL%F5%7C%F7%7B%B1%92%18yg%AA%12%03%CE%B1%0FRR%14%5C%F0%5DU%13%5B3%90%E1%0C%E2%B3%E4%E1%0E%0F%D4N%25%E9%F1%FA%2F%2C%E9d%19%E6%D6%B0vH2mk%86%87%25H%91%7B%80%EA%BC%9B%3AV3.%00%98%CB%F34\'%24%23%B6%C5%11%D3I%C2JB%E4%C8%0C%00%DCh%E9%BBf%F8%DE%AA%B8%C3H%1A%00%E3%E0a%F7%CC%22LR%26)4k%1B%ED%F0%EE%A78%C9%D4%D3%FD%00%FE%CCg%2C%D60%9B%E6%00%00%00%00IEND%AEB%60%82');
					objImage.setAttribute('alt', 'Decrease width for ' + strLabel);
					objAnchor.setAttribute('title', 'Decrease width for ' + strLabel);
				break;
		}

		objAnchor.appendChild(objImage);
	}
	else
	{
		switch (iAction)
		{
			case 1:
					var strContent = 'Increase height for ' + strLabel;
				break;
			case 2:
					var strContent = 'Decrease height for ' + strLabel;
				break;
			case 3:
					var strContent = 'Increase width for ' + strLabel;
				break;
			case 4:
					var strContent = 'Decrease width for ' + strLabel;
				break;
		}

		objAnchor.appendChild(document.createTextNode(strContent));
	}

	objItem.appendChild(objAnchor);

	return objItem;
}

function getLabel(objField, objLabels)
{
	for (var iCounter=0; iCounter<objLabels.length; iCounter++)
		if (objLabels[iCounter].htmlFor == objField.id)
			return objLabels[iCounter].firstChild.nodeValue;

	return 'the following text area';
}

function increaseArea(objAnchor, objArea, iAction)
{
	var objThis = this;

	this.element = objAnchor;
	this.textArea = objArea;
	this.action = iAction;

	this.initialise = function() {this.element.addEventListener('click', this.listener, false);};

	this.listener = function(objEvent)
	{
		var iRows = parseInt(objThis.textArea.getAttribute('rows'), 10);
		var iCols = parseInt(objThis.textArea.getAttribute('cols'), 10);

		if (isNaN(iRows))
			iRows = 10;

		if (isNaN(iCols))
			iCols = 50;

		switch (objThis.action)
		{
			case 1:
				iRows += 5;
				break;
			case 2:
				if (iRows > 5)
					iRows -= 5;
				break;
			case 3:
				iCols += 5;
				break;
			case 4:
				if (iCols > 5)
					iCols -= 5;
				break;
		}

		objThis.textArea.setAttribute('rows', iRows);
		objThis.textArea.setAttribute('cols', iCols);
		objEvent.stopPropagation();
		objEvent.preventDefault();
	};
}

function getElementsByName(objNode, strElement, bXML)
{
	if (bXML)
		return objNode.getElementsByTagNameNS('http://www.w3.org/1999/xhtml', strElement);
	else
		return objNode.getElementsByTagName(strElement);
}

function createElement(strElement, bXML)
{
	if (bXML)
		return document.createElementNS('http://www.w3.org/1999/xhtml', strElement);
	else
		return document.createElement(strElement);
}

function getCSSString()
{
	var strCSS = 'ul.jsgmtextarearesizer' +
				'{' +
					'clear: both !important;' +
					'float: none !important;' +
					'display: block !important;' +
					'margin: 0 !important;' +
					'padding: 0 !important;' +
					'list-style-type: none !important;' +
					'background-image: none !important;' + 
				'}' +
				'ul.jsgmtextarearesizer li' +
				'{' +
					'margin: 0 0.25em !important;' +
					'display: inline !important;' +
					'background-image: none !important;' + 
				'}' +
				'ul.jsgmtextarearesizer li img' +
				'{' +
					'border: none !important;' +
				'}' +
				'ul.jsgmtextarearesizer li, ul.jsgmtextarearesizer li a, ul.jsgmtextarearesizer li a img' +
				'{' +
					'float: none !important;' +
					'width: auto !important;' +
				'}' +
				'ul.jsgmtextarearesizer li a:link, ul.jsgmtextarearesizer li a:hover, ul.jsgmtextarearesizer li a:active, ul.jsgmtextarearesizer li a:focus' +
				'{' +
					'background: transparent !important;' +
				'}' +
				'textarea' +
				'{' +
					'width: auto !important;' +
					'height: auto !important;' +
				'}';

	return strCSS;
}

