/*
 * jsLinks 1.0	http://jlix.net/extensions/jquery/jslinks/1.0
 *
 * Copyright (c) 2009 Sander Aarts	(jlix.net)
 * Dual licensed under the MIT (http://jlix.net/MIT.txt)
 * and GPL (http://jlix.net/GPL.txt) licenses.
 *
 * Requires jQuery to work	(jquery.com). Tested with version 1.3.2
 *
 * 2009-07-21
 */
(function($) { // v1.0
	$.extend( {
	
		jsLinks: {
			defaults: {
				elem:					"a",
				insert:				"append",
				contentReplace:	/\[\[([\s\S]*)\]\]/,	// 
				wrapperReplace:	"[@]",
				tmpClass:			"jsAddedLink_tmp"
			},
			insert: function(relElem, content, fn, options) {
				var lnk = $.extend({}, this.defaults, options);
				if (relElem.length > 0) {
					var activeElem = {
						"a":			"<a href=\"\" class=\"" + lnk.tmpClass + "\">$1</a>",
						"button":	"<button type=\"button\" class=\"" + lnk.tmpClass + "\">$1</button>"
					}[lnk.elem];
					var replContent = lnk.contentReplace.test(content) ? lnk.contentReplace : /([\s\S]*)/;
					var cont = content.replace(replContent, activeElem);
					var fragment = lnk.wrapper ? lnk.wrapper.replace(lnk.wrapperReplace, cont) : cont;
					relElem[lnk.insert](fragment);	// insert fragment into the DOM according to specified method
					relElem.parent().find(lnk.elem + "." + lnk.tmpClass)
						.click(function(e) {
							e.preventDefault();
							if (fn.constructor == Function) { fn.call(this, e, lnk); }
						})
						.removeClass(lnk.tmpClass);
				}
			}
		}
		
	} );

	$.fn.extend( {
	
		addJsLink: function(content, options, fn) {
			// Insert JavaScript link into the DOM
			// Args.:	content:	[String | required] Link/button text
			//				options:	[Object | optional] Properties of inserted link
			//							see http://jlix.net/extensions/jquery/jslinks
			//				fn:		[Function/String | required] Callback function, triggered on click,
			//							or name of one of three predefined link types: "print", "back", "close"
			if (content && content.constructor == String) {
				if (!fn && (options.constructor == Function || options.constructor == String)) {
					fn = options;
					options = {};
				}
				if (fn.constructor == Function) {
					$.jsLinks.insert(this, content, fn, options);
				} else if (fn.constructor == String) {
					var addType = {
						"print":	"addPrintLink",
						"back":	"addBackLink",
						"close":	"addCloseLink"
					}[fn];
					if (addType) { return this[addType](content, options); }
				}
			}
			return this;
		},
		
		addPrintLink: function(content, options) {
			// Insert print link into the DOM, same as addJsLink(content, options, "print");
			if (content && content.constructor == String && window.print) {
				var fn = function() { window.print(); };
				$.jsLinks.insert(this, content, fn, options);
			}
			return this;
		},
		
		addBackLink: function(content, options) {
			// Insert back link into the DOM, same as addJsLink(content, options, "back");
			if (content && content.constructor == String) {
				options = options || {};
				var steps = parseInt(options.steps, 10);
				options.steps = isNaN(steps) ? 1 : steps;
				if (window.history.length > options.steps) {
					var fn = function(e, options) { window.history.go(-1 * options.steps); };
					$.jsLinks.insert(this, content, fn, options);
				}
			}
			return this;
		},
		
		addCloseLink: function(content, options) {
			// Insert close link into the DOM, same as addJsLink(content, options, "close");
			if (content && content.constructor == String) {
				options = options || {};
				options.winClose = options.winClose || window;
				options.winFocus = options.winFocus == "opener" ? options.winClose.opener : options.winFocus;
				if (options.winClose && options.winClose.opener && !options.winClose.closed) {
					var fn = function(e, options) {
						if (options.winFocus && !options.winFocus.closed) { options.winFocus.focus(); }
						options.winClose.close();
					};
					$.jsLinks.insert(this, content, fn, options);
				}
			}
			return this;
		}
		
	} );
} )(jQuery);
