	//var recursionCount = 0;
	//var maxRecursions = 0;
(function ($) {
	

	function isNumber(n) {
		return !isNaN(parseFloat(n)) && isFinite(n);
	}
	
	function findTruncPoint(maxHeight, text, start, end, $workerEl, token, fromEnd) {
		//recursionCount++;
		//if (recursionCount > maxRecursions){
		//	maxRecursions = recursionCount;
		//}
		var opt1,
			opt2,
			truncatePos;

		if (fromEnd) {
			opt1 = start === 0 ? '' : text.slice(-start);
			opt2 = text.slice(-end);
		} else {
			opt1 = text.slice(0, start);
			opt2 = text.slice(0, end);
		}

		if ($workerEl.html(opt2 + token).height() < $workerEl.html(opt1 + token).height()) {
			return end;
		}

		truncatePos = parseInt((start + end) / 2, 10);
		opt1 = fromEnd ? text.slice(-truncatePos) : text.slice(0, truncatePos);

		$workerEl.html(opt1 + token);
		heightWithToken = $workerEl.height();
		$workerEl.html(opt1 + token + token);
		heightWithTwoTokens = $workerEl.height();
		if (heightWithToken <= maxHeight && heightWithTwoTokens > maxHeight) {
			return truncatePos;
		}

		if ($workerEl.height() > maxHeight) {
			end = truncatePos - 1;
		} else {
			start = truncatePos + 1;
		}

		return findTruncPoint(maxHeight, text, start, end, $workerEl, token, fromEnd);
		//recursionCount--;
	}

	$.fn.truncate = function (options) {
		var defaults = {
			width: 'auto',
			token: '&hellip;',
			center: false,
			addclass: false,
			addTitle: false,
			removeTitleExtraBlanks: true,
			trimTitle: true
		};
		options = $.extend(defaults, options);

		return this.each(function () {
			$element = $(this);
			fontCSS = {
				'fontFamily': $element.css('fontFamily'),
				'fontSize': $element.css('fontSize'),
				'fontStyle': $element.css('fontStyle'),
				'fontWeight': $element.css('fontWeight'),
				'font-variant': $element.css('font-variant'),
				'text-indent': $element.css('text-indent'),
				'text-transform': $element.css('text-transform'),
				'letter-spacing': $element.css('letter-spacing'),
				'word-spacing': $element.css('word-spacing'),
				'display': 'none'
			};
			elementText = $element.html();
			$truncateWorker = $('<span class="jq_truncateWorker"/>').css(fontCSS).html(elementText).appendTo('body');
			truncateWidth = isNumber(options.width) ? options.width : $element.width();
			$truncateWorker.width(truncateWidth);
			originalHeight = $truncateWorker.height();
			truncateHeight = isNumber(options.height) ? options.height : $element.height();
			truncatedText="";

			if (originalHeight > truncateHeight) {
				$truncateWorker.html('');
				if (options.center) {
					truncateHeight = parseInt(truncateHeight / 2, 10) + 1;
					truncatedText = elementText.slice(0, findTruncPoint(truncateHeight, elementText, 0, elementText.length, $truncateWorker, options.token, false))
									+ options.token
									+ elementText.slice(-1 * findTruncPoint(truncateHeight, elementText, 0, elementText.length, $truncateWorker, '', true));
				} else {
					truncatedText = elementText.slice(0, findTruncPoint(truncateHeight, elementText, 0, elementText.length, $truncateWorker, options.token, false)) + options.token;
				}

				if (options.addclass) {
					$element.addClass(options.addclass);
				}

				if (options.addTitle) {
					var title = $element.text();
					if (options.removeTitleExtraBlanks){
						title = title.replace(/(\s+|\t+)/g, ' ');
					}
					
					if (options.trimTitle){
						title = title.trim();
					}
					$element.attr('title', title);
				}

				$element.html(truncatedText);

			}

			$truncateWorker.remove();
		});
	};
})(jQuery);
