var $$ = function(param, context) {
    var key = null;

    context = $(context) || null;

    if ( !$(param, context).length ) {
        key = param.toString();
        param = document;
    }

    var node = $(param, context)[0];
    var id = $.data(node);

    $.cache[id] = $.cache[id] || {};
    $.cache[id].node = node;

    if ( key ) {
        $.cache[id][key] = $.cache[id][key] || {};
        return $.cache[id][key];
    }

    return $.cache[id];
};

/**
* hoverIntent is similar to jQuery's built-in "hover" function except that
* instead of firing the onMouseOver event immediately, hoverIntent checks
* to see if the user's mouse has slowed down (beneath the sensitivity
* threshold) before firing the onMouseOver event.
*
* hoverIntent r5 // 2007.03.27 // jQuery 1.1.2+
* <http://cherne.net/brian/resources/jquery.hoverIntent.html>
*
* hoverIntent is currently available for use in all personal or commercial
* projects under both MIT and GPL licenses. This means that you can choose
* the license that best suits your project, and use it accordingly.
*
* // basic usage (just like .hover) receives onMouseOver and onMouseOut functions
* $("ul li").hoverIntent( showNav , hideNav );
*
* // advanced usage receives configuration object only
* $("ul li").hoverIntent({
*	sensitivity: 7, // number = sensitivity threshold (must be 1 or higher)
*	interval: 100,   // number = milliseconds of polling interval
*	over: showNav,  // function = onMouseOver callback (required)
*	timeout: 0,   // number = milliseconds delay before onMouseOut function call
*	out: hideNav    // function = onMouseOut callback (required)
* });
*
* @param  f  onMouseOver function || An object with configuration options
* @param  g  onMouseOut function  || Nothing (use configuration options object)
* @author    Brian Cherne <brian@cherne.net>
*/
(function($) {
	$.fn.hoverIntent = function(f,g) {
		// default configuration options
		var cfg = {
			sensitivity: 7,
			interval: 650,
			timeout: 750
		};
		// override configuration options with user supplied object
		cfg = $.extend(cfg, g ? { over: f, out: g } : f );

		// instantiate variables
		// cX, cY = current X and Y position of mouse, updated by mousemove event
		// pX, pY = previous X and Y position of mouse, set by mouseover and polling interval
		var cX, cY, pX, pY;

		// A private function for getting mouse position
		var track = function(ev) {
			cX = ev.pageX;
			cY = ev.pageY;
		};

		// A private function for comparing current and previous mouse position
		var compare = function(ev,ob) {
			ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t);
			// compare mouse positions to see if they've crossed the threshold
			if ( ( Math.abs(pX-cX) + Math.abs(pY-cY) ) < cfg.sensitivity ) {
				$(ob).unbind("mousemove",track);
				// set hoverIntent state to true (so mouseOut can be called)
				ob.hoverIntent_s = 1;
                $.extend(true, ev, {
                    pageX: cX,
                    pageY: cY
                });

				return cfg.over.apply(ob,[ev]);
			} else {
				// set previous coordinates for next time
				pX = cX; pY = cY;
				// use self-calling timeout, guarantees intervals are spaced out properly (avoids JavaScript timer bugs)
				ob.hoverIntent_t = setTimeout( function(){compare(ev, ob);} , cfg.interval );
			}
		};

		// A private function for delaying the mouseOut function
		var delay = function(ev,ob) {
			ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t);
			ob.hoverIntent_s = 0;
			return cfg.out.apply(ob,[ev]);
		};

		// A private function for handling mouse 'hovering'
		var handleHover = function(e) {
            /*
			// next three lines copied from jQuery.hover, ignore children onMouseOver/onMouseOut
			var p = (e.type == "mouseover" ? e.fromElement : e.toElement) || e.relatedTarget;
			while ( p && p != this ) { try { p = p.parentNode; } catch(e) { p = this; } }
			if ( p == this ) { return false; }
            */

			// copy objects to be passed into t (required for event object to be passed in IE)
			var ev = jQuery.extend({},e);
			var ob = this;

			// cancel hoverIntent timer if it exists
			if (ob.hoverIntent_t) { ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t); }

			// else e.type == "onmouseover"
			if (e.type == "mouseenter") {
				// set "previous" X and Y position based on initial entry point
				pX = ev.pageX; pY = ev.pageY;
				// update "current" X and Y position based on mousemove
				$(ob).bind("mousemove",track);
				// start polling interval (self-calling timeout) to compare mouse coordinates over time
				if (ob.hoverIntent_s != 1) { ob.hoverIntent_t = setTimeout( function(){compare(ev,ob);} , cfg.interval );}

			// else e.type == "onmouseout"
			} else {
				// unbind expensive mousemove event
				$(ob).unbind("mousemove",track);
				// if hoverIntent state is true, then call the mouseOut function after the specified delay
				if (ob.hoverIntent_s == 1) { ob.hoverIntent_t = setTimeout( function(){delay(ev,ob);} , cfg.timeout );}
			}
		};

		// bind the function to the two event listeners
		return this.mouseenter(handleHover).mouseleave(handleHover);
	};
})(jQuery);

(function($) {
    $.fn.htm = function(regex) {

        return this.html().nlrem().br2nl().replace(regex, '');
    };
})(jQuery);

(function($){
    Sizzle.selectors.order.push('NEQNAME');

    $.extend(Sizzle.selectors.match, {
        NAME: /(?:(?:\[name=['"]?)|(?:(?:^|[^!]+)@))((?:[\w\u00c0-\uFFFF_-]|\\.|:)+)(?:['"]*\])?/,
		PSEUDO: /(?:^|[^:]+):((?:[\w\u00c0-\uFFFF_-]|\\.)+)(?:\((['"]*)((?:\([^\)]+\)|[^\2\(\)]*)+)\2\))?/,
		TAG: /^((?:[\w\u00c0-\uFFFF\*_-]|\\.)+)(?!.*@)/,
        NEQNAME: /^((?:[\w\u00c0-\uFFFF\*_-]|\\.)*)!@((?:[\w\u00c0-\uFFFF_-]|\\.|:)+)/
    });

    $.extend(Sizzle.selectors.find, {
        NEQNAME: function(match, context, isXML) {
			if ( typeof context.getElementsByTagName !== 'undefined' ) {
				var ret = [], results = context.getElementsByTagName(match[1] || '*');

				for ( var i = 0, l = results.length; i < l; i++ )
					if ( !results[i].getAttribute('name') || results[i].getAttribute("name") !== match[2] )
						ret.push( results[i] );

				return ret.length === 0 ? null : ret;
			}
        }
    });

    $.extend(Sizzle.selectors.filter, {
        NAME: function(elem, match) {
			return elem.getAttribute('name') == match[1];
        }
    });
})(jQuery);

(function(jQuery) {
    var _innerHeight = jQuery.fn.innerHeight;
    var _innerWidth = jQuery.fn.innerWidth;
    var _settings = {
        padding: true,
        border: true
    };

    jQuery.fn.innerHeight = function(settings) {
        if (typeof settings == 'object')
            settings = $.extend({}, _settings, settings);
        else if (typeof settings == 'boolean')
            settings = {padding: settings};
        else settings = _settings;

        delta = (settings.padding) ? 0 : (parseInt(this.css('paddingTop')) || 0) + (parseInt(this.css('paddingBottom')) || 0);

        return _innerHeight.apply(this, arguments) - delta;
    };

    jQuery.fn.innerWidth = function(settings) {
        if (typeof settings == 'object')
            settings = $.extend({}, _settings, settings);
        else if (typeof settings == 'boolean')
            settings = {padding: settings};
        else settings = _settings;

        delta = (settings.padding) ? 0 : (parseInt(this.css('paddingLeft')) || 0) + (parseInt(this.css('paddingRight')) || 0);

        return _innerWidth.apply(this, arguments) - delta;
    };

    jQuery.fn.scrollHeight = function(settings) {
        if (typeof settings == 'object')
            settings = $.extend({}, _settings, settings);
        else if (typeof settings == 'boolean')
            settings = {border: settings};
        else settings = _settings;

        delta = (settings.border) ? (parseInt(this.css('border-top-width')) || 0) + (parseInt(this.css('border-bottom-width')) || 0) : 0;

        return this[0].scrollHeight + delta;
    };

    jQuery.fn.scrollWidth = function(settings) {
        if (typeof settings == 'object')
            settings = $.extend({}, _settings, settings);
        else if (typeof settings == 'boolean')
            settings = {border: settings};
        else settings = _settings;

        delta = (settings.border) ? (parseInt(this.css('border-left-width')) || 0) + (parseInt(this.css('border-right-width')) || 0) : 0;

        return this[0].scrollWidth + delta;
    };
})(jQuery);

// Simple JavaScript Templating
// John Resig - http://ejohn.org/ - MIT Licensed
(function($){
  var cache = {};

  $.tmpl = function tmpl(str, data) {
    if ( !cache[str] && !/\W/.test(str) && !$('#'+str).length ) return '';

    // Figure out if we're getting a template, or if we need to
    // load the template - and be sure to cache the result.
    var fn = !/\W/.test(str) ?
      cache[str] = cache[str] ||
        $.tmpl($.trim($('#'+str).text())) :

      // Generate a reusable function that will serve as a template
      // generator (and which will be cached).
      new Function("obj",
        "var p=[],print=function(){p.push.apply(p,arguments);};" +

        // Introduce the data as local variables using with(){}
        "with(obj){p.push('" +

        // Convert the template into pure JavaScript
        str
          .replace(/<!\[CDATA\[/, '')
          .replace(/\]\]>/, '')
          .replace(/&lt;%/g, '<%')
          .replace(/%&gt;/g, '%>')
          .replace(/[\r\t\n]/g, " ")
          .split("<%").join("\t")
          .replace(/((^|%>)[^\t]*)'/g, "$1\r")
          .replace(/\t=(.*?)%>/g, "',$1,'")
          .split("\t").join("');")
          .split("%>").join("p.push('")
          .split("\r").join("\\'")
      + "');}return p.join('');");

    // Provide some basic currying to the user
    return data ? fn( data ) : fn;
  };
})(jQuery);


(function($) {
    $.fn.defval = function(text,opts) {
        o = $.extend({
            _color: null,
            color: "#aaa",
            e:"focus",
            force : false,
            keep : true,
            plugin: 'defval'
        }, opts || {});

        var clearInput = function (e) {
            var target = $(e.target);
            var value = $.trim(target.val());
            var def_value = target.data('def_value');

            if (e.type == e.data.obj.e && value == e.data.obj.innerText) {
                $(target).css("color", "").val("");
                if (!e.data.obj.keep) {
                    $(target).unbind(e.data.obj.e+" blur",clearInput);
                }
            } else if (e.type == "blur" && value == "" && e.data.obj.keep) {
                $(this).css("color", e.data.obj.color).val(e.data.obj.innerText);
            }
        };

        return this.each(function () {
            var self = $(this);

            o.innerText = $.trim( (typeof text != "string") ? $(text).text() : (text || false) );
            o._color = self.css('color');

            if (o.force || !self.val().length)
                self.css({color: o.color}).val(o.innerText);

            if ( self.data('defval') == undefined ) {
                self.data('defval', {value: o.innerText, lamda: clearInput}).
                    bind(o.e+' blur', {obj:o}, clearInput);
            } else {
                $.each(self.data('events').focus, function(i, event) {
                    if ( event.data && event.data.obj && event.data.obj.plugin )
                        $.extend(event.data.obj, o);
                });
            }
        });
    };
})(jQuery);


(function($) {
    $.fn.within = function(event) {
        // Check if mouse(over|out) are still within the same parent element
        var parent = event.relatedTarget;
        var _this = $(this).get(0);

        // Traverse up the tree
        while ( parent && parent != _this )
            try { parent = parent.parentNode; }
            catch(e) { parent = _this; }

        return parent == _this;
    };
})(jQuery);


(function($) {
    $.uid = function () {
        var rand = new Array();

        for (n=0; n < 8; n++)
            rand[n] = ((Math.random()*0x11111)|0).toString(16);

        return rand[0]+rand[1]+"-"+rand[2]+"-"+rand[3]+"-"+rand[4]+"-"+rand[5]+rand[6]+rand[7];
    };
})(jQuery);


(function($) {
    $.fn.diff = function(delta) {
        return $.grep(this, function(n) {
            return $.inArray(n, delta) == -1;
        });
    }

    $.fn.invert = function() {
        return this.pushStack(this.get().reverse(), arguments);
    };
})(jQuery);


(function($) {
    $.fn.swap_class = function(a, b) {

        return this.each(function() {
            ( $(this).hasClass(a) ) ?
                $(this).removeClass(a).addClass(b) : $(this).removeClass(b).addClass(a);
        });
    };
})(jQuery);


/**
 * Pan/Zoom - it's just a quick hack, so don't expect too much
 * @author Andrew Hedges, andrew@hedges.name
 * @created 2009-12-27 12:27:09
 * @license MIT
 * @usage $.panzoom();
 * @requires jQuery (tested with versions 1.3.2 and 1.4.0)
 */
(function($) {
	var MULT = 0,
        titles = {
            small : 'Zoom in',
            large : 'Zoom out'
        };

    function _coords(e, orig, scale) {
        var mouse = {
                x: e.pageX - orig.offset.left,
                y: e.pageY - orig.offset.top
            },
            delta = {
                x: Math.round(mouse.x * scale.width / orig.width),
                y: Math.round(mouse.y * scale.height / orig.height)
            },
            offset = {
                x: Math.round((orig.width/2 - mouse.x) * MULT),
                y: Math.round((orig.height/2 - mouse.y) * MULT)
            };

		return {
            top: (mouse.y - delta.y + offset.y) + 'px',
            left: (mouse.x - delta.x + offset.x) + 'px'
        };
	}

	function move(e) {
		var a = e.data.a, zoom = e.data.zoom, img = e.data.img,
            pos;

        e.preventDefault();

        // Update the containers offset
        a.offset = a.elem.offset();

        pos = _coords(e, a, zoom);

        new_pos = $.extend({},
            a.width < zoom.width ? {left: pos.left} : null,
            a.height < zoom.height ? {top: pos.top} : null
        );

		//img.elem.css(new_pos);
        img.elem.stop(true)
            .animate(new_pos, {duration: 350, easing: 'easeOutSine'});
	}

	function zoom_in(e, data) {
        var a = data.a, zoom = data.zoom, img = data.img;

        // Update the containers offset
        a.offset = a.elem.offset();

        var css = $.extend(_coords(e, a, zoom), {
            width  : data.zoom.width,
            height : data.zoom.height
        });

        img.elem.attr({
            src: zoom.src,
            width: img.width,
            height: img.height
        });

        img.elem.animate(css, {
            duration: 450,
            easing: 'easeOutQuad',
            complete: function() {

                a.elem.bind('mousemove.zoomable', {a: a, img: img, zoom: zoom}, move); // enable panning
            }
        });
	}

	function zoom_out(data) {
        var a = data.a, zoom = data.zoom, img = data.img;

        a.elem.unbind('mousemove.zoomable');

        img.elem.stop(true).animate({
			top    : img.position.top,
			left   : img.position.left,
			width  : img.width,
			height : img.height
		}, {
            duration: 750,
            easing: 'easeOutQuad',
            complete: function() {
                img.elem.attr({src: img.src});
            }
        });
	}

    $.fn.zoomable = function() {
        var images = [], timer;

        this.each(function(i) {
            var zoomed = 0, zoom = $(new Image()),
                a = $(this), img = $('img:first', this);

            var aux = {
                    a: {elem: a},
                    img: {elem: img, src: img.attr('src')},
                    zoom: {elem: zoom, src: a.attr('href')}
                };

            if ( this.tagName.toLowerCase() !== 'a' ||
                    !img.length ) return;

            images[i] = zoom.one('load', function(e) {
                a.one('mouseenter', function(e) {
                    a.css({
                        position: 'relative',
                        width: img.outerWidth(true),
                        height: img.outerHeight(true),
                        overflow: 'hidden',
                        display: 'inline-block'
                    });

                    img.css($.extend(img.position(), {
                        position: 'absolute'
                    }));

                    $.extend(true, aux, {
                        a: {width: a.width(), height: a.height(), offset: a.offset()},
                        zoom: {width: zoom[0].width, height: zoom[0].height},
                        img: {width: img[0].width, height: img[0].height, position: img.position()}
                    });

                    a.hoverIntent(function(e) {
                        e.preventDefault();
                        if ( !zoomed && ++zoomed ) zoom_in(e, aux);
                    }, function(e) {
                        if ( zoomed && !--zoomed ) zoom_out(aux);
                    }).trigger(e);

                    return false;
			    });
            });

            // Start loading the larger image
            zoom[0].src = aux.zoom.src;
        });

        // Make sure that the load event is triggered for cached images, too
        timer = setInterval(function() {
            for ( var i=0; i < images.length; i++ )
                if ( images[i][0].complete )
                    images.splice(i, 1)[0].trigger('load');

            if ( !images.length ) clearInterval(timer);
        }, 500);

        return this;
    };
})(jQuery);

(function($) {
    $.fn.uprev = function(selector) {
        var elem = $(this[0]);

        do {
            if ( elem.filter(selector).length )
                return elem.filter(selector);
        } while ( (elem = elem.prev()) && elem.length );

        return $([]);
    };
})(jQuery);

(function($) {
    var view = function(i, j, data, fn) {
        try {
            var out = "<div class=\"large_image\">";
            if (this.title.length || this.caption.length) {
                out += " <div class=\"large_image_info\"><div class=\"top\"></div><div class=\"center\"><h1>";
                out += this.title;
                out += "</h1> <h2>";
                out += this.caption;
                out += "</h2></div><div class=\"bottom\"></div></div>";
            }

            out += " <img src=\"";
            out += this.src;
            out += "\" alt=\"";
            out += this.title;
            out += "\"/> </div>";

            return out;
        } catch (e) {
            e.type = "TemplateExecutionError";
            e.args = arguments;
            e.template = arguments.callee.toString();
            throw e;
        }
    };

    var hint = function(i, j, data, fn) {
        try {
            var out = "<div class=\"zoom_hint\"><div class=\"top\"></div><p class=\"center\">[?] F\xFCr die Gro\xDFansicht bitte klicken</p><div class=\"bottom\"></div> </div>";
            return out;
        } catch (e) {
            e.type = "TemplateExecutionError";
            e.args = arguments;
            e.template = arguments.callee.toString();
            throw e;
        }
    };

    $(function() {
        $('a.gallery').each(function(i) {
            var $self = $(this),
                $img = $('img.medium', this),
                data = eval('('+$img.attr('data-zoom')+')');

            $(view.call(data, 0, 0, data)).appendTo('#dump');
            $('a.goto:eq('+( i+1 )+')').data('ref', $self);

            $self.data('item', i)
                .zoomable();
        });

        $('.large_image').bind('wimpy.post', function() {
            var self = this;

            setTimeout(function() {
                $('.large_image_info', self)
                    .animate({opacity: 0}, {duration: 500});
            }, 7500);
        });

        $('a.gallery').live('click', function() {
            var i = $(this).data('item');

            $('#dump .large_image').wimpy({
                index: i,
                fog_duration: 2500,
                box_fade_duration: 0,
                box_scale_duration: 0,
                box_cursor: 'default',
                overlay_duration: 500,
                overlay_opacity: .95,
                overlay_bg_color: '#000'
            });

            return false;
        });

        $('a.gallery').one('mouseenter', function() {
            var self = this;

            $(hint()).appendTo(this)
                .animate({opacity: 1}, {duration: 250, queue: 'hint'});

            setTimeout(function() {
                $('.zoom_hint', self).animate({
                    opacity: 0
                }, {
                    duration: 150,
                    queue: 'hint',
                    complete: function() {
                        $(this).remove();
                    }
                });
            }, 2500);
        });

        $('a.goto:gt(0)').live('click', function() {
            $(this).data('ref').click();
            return false;
        });
    });
})(jQuery);

