/*
* jQuery Expander plugin
* Version 0.4  (12/09/2008)
* @requires jQuery v1.1.1+
*
* Dual licensed under the MIT and GPL licenses:
* http://www.opensource.org/licenses/mit-license.php
* http://www.gnu.org/licenses/gpl.html
*
*/


(function($) {

	$.fn.expander = function(options) {

		var opts = $.extend({}, $.fn.expander.defaults, options);
		var delayedCollapse;
		return this.each(function() {
			var $this = $(this);
			var o = $.meta ? $.extend({}, opts, $this.data()) : opts;
			var cleanedTag, startTags, endTags;	
			var allText = $this.html();
			var startText = allText.slice(0, o.slicePoint).replace(/\w+$/,'');
			startTags = startText.match(/<\w[^>]*>/g);
			if (startTags) {startText = allText.slice(0,o.slicePoint + startTags.join('').length).replace(/\w+$/,'');}

			if (startText.lastIndexOf('<') > startText.lastIndexOf('>') ) {
				startText = startText.slice(0,startText.lastIndexOf('<'));
			}
			var endText = allText.slice(startText.length);    	  
			// create necessary expand/collapse elements if they don't already exist
			if (!$('span.details', this).length) {
				// end script if text length isn't long enough.
				if ( endText.replace(/\s+$/,'').split(' ').length < o.widow ) { return; }
				// otherwise, continue...    
				if (endText.indexOf('</') > -1) {
					endTags = endText.match(/<(\/)?[^>]*>/g);
					for (var i=0; i < endTags.length; i++) {

						if (endTags[i].indexOf('</') > -1) {
							var startTag, startTagExists = false;
							for (var j=0; j < i; j++) {
								startTag = endTags[j].slice(0, endTags[j].indexOf(' ')).replace(/(\w)$/,'$1>');
								if (startTag == rSlash(endTags[i])) {
									startTagExists = true;
								}
							}              
							if (!startTagExists) {
								startText = startText + endTags[i];
								var matched = false;
								for (var s=startTags.length - 1; s >= 0; s--) {
									if (startTags[s].slice(0, startTags[s].indexOf(' ')).replace(/(\w)$/,'$1>') == rSlash(endTags[i]) 
									&& matched == false) {
										cleanedTag = cleanedTag ? startTags[s] + cleanedTag : startTags[s];
										matched = true;
									}
								};
							}
						}
					}

					endText = cleanedTag && cleanedTag + endText || endText;
				}
				$this.html([
					startText,
					'<span class="read-more">',
					o.expandPrefix,
					'<a href="#">',
					o.expandText,
					'</a>',
					'</span>',
					'<span class="details">',
					endText,
					'</span>'
					].join('')
				);
			}
			var $thisDetails = $('span.details', this),
			$readMore = $('span.read-more', this);
			$thisDetails.hide();
				//$readMore.find('a').click(function() {
				$this.parent().click(function() {

					if (o.expandEffect === 'show' && !o.expandSpeed) {

						
						if($thisDetails.is(':visible')) {
							// Collapse
							$thisDetails.toggle();
							$readMore.show();
							o.onCollapse($this, true);
						} else {
							// Expand
							o.beforeExpand($this);
							$thisDetails.toggle();
							$readMore.hide();
							o.afterExpand($this);
						}
						
						delayCollapse(o, $thisDetails);
					} else {
						o.beforeExpand($this);
						$thisDetails[o.expandEffect](o.expandSpeed, function() {
							$thisDetails.css({zoom: ''});
							o.afterExpand($this);
							delayCollapse(o, $thisDetails);
						});
					}
					return false;
				});
				/*if (o.userCollapse) {

					$this.find('span.details').append('<span class="re-collapse">' + o.userCollapsePrefix + '<a href="#">' + o.userCollapseText + '</a></span>');
					
					//.find('span.details').append('<span class="re-collapse">' + o.userCollapsePrefix + '<a href="#">' + o.userCollapseText + '</a></span>');
					//$this.find('span.re-collapse a').click(function() {
					
					$this.click(function() {

						clearTimeout(delayedCollapse);
						var $detailsCollapsed = $(this).parents('span.details');
						reCollapse($detailsCollapsed);
						o.onCollapse($this, true);
						return false;
					});
				}*/
			});
			function reCollapse(el) {
				el.hide()
				.prev('span.read-more').show();
			}
			function delayCollapse(option, $collapseEl) {
				if (option.collapseTimer) {
					delayedCollapse = setTimeout(function() {  
						reCollapse($collapseEl);
						option.onCollapse($collapseEl.parent(), false);
					},
					option.collapseTimer
				);
			}
		}
		function rSlash(rString) {
			return rString.replace(/\//,'');
		}    
	};
	// plugin defaults
	$.fn.expander.defaults = {
		slicePoint:       100,  // the number of characters at which the contents will be sliced into two parts. 
		// Note: any tag names in the HTML that appear inside the sliced element before 
		// the slicePoint will be counted along with the text characters.
		widow:            4,  // a threshold of sorts for whether to initially hide/collapse part of the element's contents. 
		// If after slicing the contents in two there are fewer words in the second part than 
		// the value set by widow, we won't bother hiding/collapsing anything.
		expandText:       'read more', // text displayed in a link instead of the hidden part of the element. 
		// clicking this will expand/show the hidden/collapsed text
		expandPrefix:     '&hellip; ',
		collapseTimer:    0, // number of milliseconds after text has been expanded at which to collapse the text again
		expandEffect:     'fadeIn',
		expandSpeed:      '',   // speed in milliseconds of the animation effect for expanding the text
		userCollapse:     true, // allow the user to re-collapse the expanded text.
		userCollapseText: '[collapse expanded text]',  // text to use for the link to re-collapse the text
		userCollapsePrefix: ' ',
		beforeExpand: function($thisEl) {},
		afterExpand: function($thisEl) {},
		onCollapse: function($thisEl, byUser) {}
	};
	})(jQuery);

