/**
 * Selection handler
 *
 * Retrieves caret selections reliably and independently of the document area and browser.
 * Meaning that, it will behave properly no matter whether you have readonly page text
 * selected or have some input inside a text field highlighted.
 * Contains common solutions scraped together from various sources.
 *
 * usage:	var ts = new TextSelector();
 *			var currentSelection = ts.getSelection();
 *
 * @author	Sam Pospischil	<pospi@spadgos.com>
 * @date	6/9/2010
 * @license
 *
 *			DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
 *                    Version 2, December 2004
 *
 * Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
 *
 * Everyone is permitted to copy and distribute verbatim or modified
 * copies of this license document, and changing it is allowed as long
 * as the name is changed.
 *
 *            DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
 *   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
 *
 *  		0. You just DO WHAT THE FUCK YOU WANT TO.
 */

function TextSelector() {
	TextSelector.registerFocusListeners();
}

//======================================================================================
// Selection handling
//======================================================================================

TextSelector.prototype.getSelection = function() {
	var page	= this.getPageSelection();
	var input	= this.getFieldSelection();
	return page.rangeCount ? page.toString() : input;
}

TextSelector.prototype.getPageSelection = function() {
	var txt;
	if (window.getSelection) {
		txt = window.getSelection();
	} else if (document.getSelection) {	// Gecko
		txt = document.getSelection();
	} else if (document.selection) {	// IE
		txt = document.selection.createRange().text;
	}
	return txt;
}

TextSelector.prototype.getFieldSelection = function() {
	var textComponent = TextSelector.activeElement || document.activeElement;
	var txt;
	if (textComponent) {
		if (document.selection != undefined) {					// IE
			txt = document.selection.createRange().text;
		} else if (textComponent.selectionStart != undefined) {	// Gecko
			txt = textComponent.value.substring(textComponent.selectionStart, textComponent.selectionEnd)
		}
	}
	return txt;
}

/*
 * Event listeners to help us determine our focused element if the browser doesn't support the property
 * Note that IE is the only browser which supports this in the way we wish it to - others overwrite
 * it on the click event triggering the function call, which doesn't help. Thus this only gets added
 * for non-IE browsers (ones which support addEventListener())
 * We also don't perform an onblur(), for the same reason. It doesn't matter anyway - the input grabbing
 * function only gets called if there is no in-page selection active.
 */

TextSelector.checkingFocus = false;
TextSelector.activeElement = null;

TextSelector.registerFocusListeners = function() {
	if (TextSelector.checkingFocus) return;
	TextSelector.checkingFocus = true;

	if (document.addEventListener) {
		document.addEventListener("focus", TextSelector.domFocusListener, true);
		//document.addEventListener("blur", TextSelector.domUnFocusListener, true);
	}
}

TextSelector.unregisterFocusListeners = function() {
	if (!TextSelector.checkingFocus) return;
	TextSelector.checkingFocus = false;

	if (document.removeEventListener) {
		document.removeEventListener("focus", TextSelector.domFocusListener, true);
		//document.removeEventListener("blur", TextSelector.domUnFocusListener, true);
	}
}

// A text input is just anything you can enter text into, for our purposes
TextSelector.isTextInput = function(el) {
	return el.nodeName == 'TEXTAREA' || (el.nodeName == 'INPUT' && (el.type == 'text' || el.type == 'file'));
}

TextSelector.domFocusListener = function(evt) {
	if (evt && evt.target && TextSelector.isTextInput(evt.target)) {
		TextSelector.activeElement = evt.target;
	}
}

/*TextSelector.domUnFocusListener = function(evt) {
	TextSelector.activeElement = null;
}*/

