﻿jQuery(document).ready(function ($) {
	// placeholder in textfields
	$('input[type=text].toggle_value').each(function () {
		$(this).data('initValue', $(this).val());
	}).focus(function () {
		var $this = $(this);
		if ($this.val().length > 0 && $this.val() == $this.data('initValue'))
			$this.val('');
	}).blur(function () {
		var $this = $(this);
		if ($this.val().length == 0)
			$this.val($this.data('initValue'));
	});

	// login links
	$('a.force_login').click(function () {
		$.scrollTo('#login', 1000);
		return false;
	});

	$('#alert').jqm({
		overlay: 50,
		modal: false,
		trigger: false,
		onShow: function (hash) {
			if (hash.w.data('autoClose') != undefined) {
				setTimeout(function () {
					// re-check fadeout, cause there might be
					// another alert displayed now (3000ms after function invoked)
					if (hash.w.data('autoClose') != undefined)
						hash.w.jqmHide().removeData('autoClose');
				}, 3000);
			}

			hash.w.fadeIn('fast');
		},
		onHide: function (hash) {
			hash.w.fadeOut('fast');
			if (hash.o) hash.o.remove(); // overlay
			hash.w.removeData('autoClose');
		}
	});

	$('#confirm').jqm({
		overlay: 50,
		modal: true,
		trigger: false,
		onShow: function (hash) { hash.w.fadeIn('fast'); },
		onHide: function (hash) {
			hash.w.fadeOut('fast');
			if (hash.o) hash.o.remove();
		}
	});
});

(function($){
    $.fn.scrollTo = function(elem, duration) {
        var d = (duration == undefined || isNaN(duration)) ? 'slow' : duration;
        var p = (typeof(elem) == 'string') ? $(elem) : elem;
        if (p.length == 0) p = 0;
        else p = p.position().top;
        
        $('html, body').animate({scrollTop: p}, d);
        return elem;
    };

	$.fn.extend({
		isChildOf: function(parentSelector) {
			var parentMatch = false;
			$(this).parents().each(function() {
				if ($(this).is(parentSelector)) {
					parentMatch = true;
					return false;
				}
			});

			return parentMatch;
		}
	});

    /**
     * Toggle visibility of block content - inserts Skjul / Vis links in the block header
     * elem = element with .block_header and .block_content (typically a div.block)
     * options {type: 'text/image', onVisible: 'hide text / hide image path', onHidden: 'show text / show image path', appendTo: 'append anchor to given element (selector)' }
     */
    $.fn.toggleContent = function(options) {
        var defaults = {
            type: 'text',
            onVisible: '(skjul)',
            onHidden: '(vis)',
            appendTo: ''
        };
        var opts = $.extend(defaults, options); // merge default with options
        
        var $this = $(this);
        var content = $this.children('.block_content');
        var header = $this.children('.block_header:first');
        
        // render toggle link
        var toggleAnchor = $('<a href="#" style="margin-left:10px;"></a>')
                                    .data('toggleContent', opts)
                                    .click(function(){                                        
                                        var $anchor = $(this);

                                        if (content.is(':visible'))
                                            content.slideUp('fast', function(){
                                                // alter anchor content
                                                renderInnerContent(content, $anchor, opts);                                                
                                            });
                                        else
                                            content.slideDown('fast', function(){
                                                // alter anchor content
                                                renderInnerContent(content, $anchor, opts);
                                            });
                                        
                                        return false;
                                    });
        
        // create and insert anchor
        renderInnerContent(content, toggleAnchor, opts);  
        
        // insert anchor into a specific place in the header?
        if (opts.appendTo.length > 0) {
            var appendToElem = header.children(opts.appendTo);
            if (appendToElem.length > 0) appendToElem.append( toggleAnchor );
        }
        // nope, append directly into header
        else
            header.append( toggleAnchor );
        
        return $this;
    };
    
    // helper function to create / alter inner content of the toggle anchor
    function renderInnerContent($content, $toggleAnchor, opts) {
        var anchorInner = $content.is(':visible') ? opts.onVisible : opts.onHidden;
        if (opts.type == 'image') {
            var img = $toggleAnchor.children('img:first');
            // need to insert image in this anchor?
            if (img.length == 0) {
                img = $('<img src=""/>');
                $toggleAnchor.append(img);
            }
            
            img.attr('src', anchorInner);
        } 
        else 
            $toggleAnchor.text( anchorInner );
    };
    
    /**
     * Insert content at caret position (converted to jquery function)
     * @link http://alexking.org/blog/2003/06/02/inserting-at-the-cursor-using-javascript
     */
    $.fn.insertAtCaret = function (myValue) {
            return this.each(function(){
                    //IE support
                    if (document.selection) {
                            this.focus();
                            sel = document.selection.createRange();
                            sel.text = myValue;
                            this.focus();
                    }
                    //MOZILLA/NETSCAPE support
                    else if (this.selectionStart || this.selectionStart == '0') {
                            var startPos = this.selectionStart;
                            var endPos = this.selectionEnd;
                            var scrollTop = this.scrollTop;
                            this.value = this.value.substring(0, startPos)
                                          + myValue
                                  + this.value.substring(endPos,this.value.length);
                            this.focus();
                            this.selectionStart = startPos + myValue.length;
                            this.selectionEnd = startPos + myValue.length;
                            this.scrollTop = scrollTop;
                    } else {
                            this.value += myValue;
                            this.focus();
                    }
            });
    };
    
    /**
     * Relate tab to content (id) specified in the tab's rel-attr.
     * Options: {
     *              selectFirstTab: true - whether or not to select the first tab when document is ready 
     *              selectedClass: 'current' - class to add when tab is selected
     *          }
     */
    $.fn.relateTab = function(options){
        var defaults = { selectFirstTab: true, selectedClass: 'current' };
        var opts = $.extend(defaults, options);        
        
        return $(this).each(function(index){
            var $this = $(this);
            var content = $( $this.attr('rel') );
            var classSelector = '.' + opts.selectedClass;
            
            // attach click handler
            $this.click(function(){
                if ($this.is(classSelector) || content.length == 0) return false; // already the active tab, ignore click
                
                // remove .current from selected tab
                $this.closest('div').find(classSelector).removeClass( opts.selectedClass );
                
                selectTab($this, opts.selectedClass);
                
                // hide content siblings - show the current tab's content
                content.siblings('.block_content:visible').hide().end().show();
                
                return false;
            });
            
            // select first tab?
            if (index == 0 && opts.selectFirstTab) { 
                selectTab($this, opts.selectedClass);
                content.show();
            }
        });
    };
    
    // helper function that marks given tab as selected
    function selectTab($tab, cssClass) {
        var selectElem;
        var parent = $tab.parent().parent();
        
        // where do we want to add the current class?
        if (parent.is('li')) selectElem = parent;
        else selectElem = $tab;
        
        selectElem.addClass( cssClass );
    }
	
	//
	// TOOLTIP
	//
	$.fn.tooltip = function (options) {
		options = $.extend({ theme: 'light', content: 'title', init: null, yOffset: 2, animSpeed: 300, delay: 0, frame: null }, options);
		var tipName = options.theme + 'Tip';
		var tipFrame = options.frame === null ? '<div class="'+ tipName +'"><div class="content"></div></div>' : options.frame;
		var animSpeed = 300; // animation speed

		var tinyTip;
		var tText = null;
		var tDelay = null;

		if (options.init !== null) 
			options.init.call(this);

		$(this).hover(function () {
			var $this = $(this);
			var divTip = $(tipFrame).appendTo('body:first');
			// var divTip = 'div.' + tipName;
			tinyTip = $(divTip).hide();

			// callback responsible for rendering the tip we so badly want
			var tipRender = function(tipCont){
				// append tip's frame to the body
				if (options.frame === null)
					$(divTip + ' .content').html(tipCont);
				else
					$(divTip).html(tipCont);

				// whether or not to set the tooltips offset to be under the hovered element
				var insertUnderElem = ($this.offset().top - tinyTip.outerHeight()) < $(window).scrollTop();

				// Offsets so that the tooltip is centered over the element it is being applied to but
				// raise it up above the element so it isn't covering it.
				var yOffset = (insertUnderElem ? $this.outerHeight() + options.yOffset : tinyTip.outerHeight() + options.yOffset);
				var xOffset = (tinyTip.width() / 2) - ($this.width() / 2);

				// Grab the coordinates for the element with the tooltip and make a new copy
				// so that we can keep the original un-touched.
				var pos = $this.offset();
				var nPos = { top: pos.top, left: pos.left };

				// Add the offsets to the tooltip position
				nPos.top = insertUnderElem ? nPos.top + yOffset : nPos.top - yOffset;
				nPos.left -= xOffset;

				// Make sure that the tooltip has absolute positioning and a high z-index, 
				// then place it at the correct spot and fade it in.
				tinyTip.css('position', 'absolute').css('z-index', '1000').css(nPos);
			
				var displayTooltip = function(tinyTip) {
					if (options.animSpeed > 0)
						tinyTip.fadeIn(animSpeed);
					else
						tinyTip.show();			
				}
			
				// delay display of tooltip?
				if (options.delay > 0) {
					$this.data('displayTooltip', 1);
					setTimeout(function(){
						if ($this.data('displayTooltip') !== null)
							displayTooltip(tinyTip);
					}, options.delay);
				} 
				// nope, display it right away!
				else
					displayTooltip(tinyTip);			
			}

			// Grab the content for the tooltip from the title attribute (or the supplied content) and
			// inject it into the markup for the current tooltip.
			if (options.content === 'title') {
				var tipCont = $this.attr('title');
				tText = $this.attr('title');
			} 
			// fetch content from an URL, where the actual URL is stored within the url-attrib of the element
			else if (options.content === 'url') {
				$.ajax({
					async: false,
					dataType: 'html',
					url: $this.attr('url'),
					success: tipRender
				});

				return; // prevent the ripRender to be invoked, thats what our success-event should be doing :)
			}
			// render content from the function supplied, with the hovered element as context
			else if (typeof(options.content) === 'function') {
				var tipCont = options.content.call(this);
			} 
			// use whatever content was supplied
			else {
				var tipCont = options.content;
			} 
			
			tipRender(tipCont);
		}, function () {
			// re-insert title, and fadeout/remove tooltip
			if (tText !== null)
				$(this).attr('title', tText);
			
			$(this).removeData('displayTooltip');

			var removeTooltip = function(){ $(this).remove(); };
			if (options.animSpeed > 0)
				tinyTip.fadeOut(animSpeed, removeTooltip);
			else
				tinyTip.show(1, removeTooltip);
		});

		return this;
	}
})(jQuery);

/* options: {title: '', autoClose: bool} */
function alert(msg, options) {
    options = jQuery.extend({
        title:  alert_default_title,
        autoClose: false
    }, options);

	var alerter = jQuery('#alert');

	if (options.autoClose) alerter.data('autoClose', true);
	if (options.title.length > 0) alerter.find('div.jqmAlertTitle h1:first').html(options.title);
    alerter.find('div.jqmAlertContent').html(msg).end().jqmShow();
}    
    
/* Overriding Javascript's Confirm Dialog */
function confirmBox(msg,callback,title) {
    if (title == undefined) title = '';

    jQuery('#confirm')
    .jqmShow()
    .find('p.jqmConfirmMsg')
      .html(msg)
    .end()
    .find(':submit:visible')
      .click(function(){
        if(jQuery(this).is('.yes'))
          (typeof callback == 'string') ? window.location.href = callback : callback();
        
        jQuery('#confirm').jqmHide();
      })
    .end()
    .find('div.jqmConfirmTitle h1:first')
        .html(title);
 }

 function openWindow(url, width, height, options, name) {
 	options = options ? options : 'resizable=yes';
 	name = name ? name : '';
 	if (width) options.length > 0 ? options += ',width=' + width : options = 'width=' + width;
 	if (height) options.length > 0 ? options += ',height=' + height : options = 'height=' + height;
 	window.open(
				url,
				name,
				'screenX=' + (screen.width - width) / 2 + ',screenY=' + (screen.height - height) / 2 + ',' + options
			);
 	return false;
 }

// pad numbers, adds 0 before digits under 10
function numberPad(number) {
	return (number < 10) ? "0" + number : number;
}

// helper function which converts date 
// to a standard string representation (dd.MM.yyyy)
function dateToStr(date) {
	return (date != null) ? numberPad(date.getDate()) + '.' + numberPad(date.getMonth() + 1) + '.' + date.getFullYear() : '';
}



/**
 * CSS Browser Selector v0.3.4
 * (http://rafael.adm.br/css_browser_selector)
 * 
 */

	function css_browser_selector(u){var ua = u.toLowerCase(),is=function(t){return ua.indexOf(t)>-1;},g='gecko',w='webkit',s='safari',o='opera',h=document.getElementsByTagName('html')[0],b=[(!(/opera|webtv/i.test(ua))&&/msie\s(\d)/.test(ua))?('ie ie'+RegExp.$1):is('firefox/2')?g+' ff2':is('firefox/3.5')?g+' ff3 ff3_5':is('firefox/3')?g+' ff3':is('gecko/')?g:is('opera')?o+(/version\/(\d+)/.test(ua)?' '+o+RegExp.$1:(/opera(\s|\/)(\d+)/.test(ua)?' '+o+RegExp.$2:'')):is('konqueror')?'konqueror':is('chrome')?w+' chrome':is('iron')?w+' iron':is('applewebkit/')?w+' '+s+(/version\/(\d+)/.test(ua)?' '+s+RegExp.$1:''):is('mozilla/')?g:'',is('j2me')?'mobile':is('iphone')?'iphone':is('ipod')?'ipod':is('mac')?'mac':is('darwin')?'mac':is('webtv')?'webtv':is('win')?'win':is('freebsd')?'freebsd':(is('x11')||is('linux'))?'linux':'','js']; c = b.join(' '); h.className += ' '+c; return c;}; css_browser_selector(navigator.userAgent);



/**
 * In-Field Label v1.0 
 * (http://fuelyourcoding.com/scripts/infield.html)
 * 
 */

	(function($){$.InFieldLabels=function(b,c,d){var f=this;f.$label=$(b);f.label=b;f.$field=$(c);f.field=c;f.$label.data("InFieldLabels",f);f.showing=true;f.init=function(){f.options=$.extend({},$.InFieldLabels.defaultOptions,d);if(f.$field.val()!=""){f.$label.hide();f.showing=false};f.$field.focus(function(){f.fadeOnFocus()}).blur(function(){f.checkForEmpty(true)}).bind('keydown.infieldlabel',function(e){f.hideOnChange(e)}).change(function(e){f.checkForEmpty()}).bind('onPropertyChange',function(){f.checkForEmpty()})};f.fadeOnFocus=function(){if(f.showing){f.setOpacity(f.options.fadeOpacity)}};f.setOpacity=function(a){f.$label.stop().animate({opacity:a},f.options.fadeDuration);f.showing=(a>0.0)};f.checkForEmpty=function(a){if(f.$field.val()==""){f.prepForShow();f.setOpacity(a?1.0:f.options.fadeOpacity)}else{f.setOpacity(0.0)}};f.prepForShow=function(e){if(!f.showing){f.$label.css({opacity:0.0}).show();f.$field.bind('keydown.infieldlabel',function(e){f.hideOnChange(e)})}};f.hideOnChange=function(e){if((e.keyCode==16)||(e.keyCode==9))return;if(f.showing){f.$label.hide();f.showing=false};f.$field.unbind('keydown.infieldlabel')};f.init()};$.InFieldLabels.defaultOptions={fadeOpacity:0.5,fadeDuration:300};$.fn.inFieldLabels=function(c){return this.each(function(){var a=$(this).attr('for');if(!a)return;var b=$("input#"+a+"[type='text'],"+"input#"+a+"[type='password'],"+"textarea#"+a);if(b.length==0)return;(new $.InFieldLabels(this,b[0],c))})}})(jQuery);
	$(document).ready(function(){
		$(".ui-infieldlabel label").inFieldLabels({ fadeOpacity:0.3, fadeDuration:300 });
	});



/**
 *	Popout form functions
 *
 **/

	$(document).ready(function () {

	    // Cancel login function
	    function cancelLogin(form) {
	        $('.js-popoutform.js-active').hide();
	        $('.js-popoutform.js-active input:not(:submit)').val('').removeAttr('checked').removeAttr('selected');
	        // $('.js-popoutform.js-active input').not(':button, :submit, :reset, :hidden').val('').removeAttr('checked').removeAttr('selected');
	        $('.js-popoutform.js-active').removeClass('js-active');
	    }

	    // If user clicks outside
	    $(document).click(function () {
	        cancelLogin();
	    });

	    // If user presses ESC
	    $(document).keyup(function (e) {
	        if (e.keyCode == 27) {
	            cancelLogin();
	        }
	    });

	    // Prevents login form from closing if clicked
	    $('.js-popoutform').click(function (e) {
	        e.stopPropagation();
	    });

	    // Open login form
	    $('.js-show-popoutform').click(function (e) {
	        e.preventDefault();
	        e.stopPropagation();
	        $(this).siblings('.js-popoutform').addClass('js-active').show().find('input:first').focus();
	    });

	});



/**
 * Entire story in storygrid clickable
 *
 */

	$(document).ready(function(){
		$('.js-clickable').click(function(){
			var link = $(this).find('a').attr("href");
			window.location.href = link;
		}).css('cursor', 'pointer');

	});


/**
 * Flash Status Messags
 *
 */
 
	$(document).ready(function(){
		$('.js-remove-statusmessage').click(function(){
			$(this).parent('li').fadeOut();
		});
	});


/**
 * Floating Ad
 *
 */

	$(document).ready(function () {
		var el = $('.js-ad-float');
		if (el.length > 0) {
			var elpos_original = el.offset().top;
			$(window).scroll(function () {
				var elpos = el.offset().top;
				var windowpos = $(window).scrollTop();
				var finaldestination = windowpos;
				if (windowpos < elpos_original) {
					finaldestination = elpos_original;
					el.stop().css({ 'top': 0 });
				} else {
					el.stop().animate({ 'top': finaldestination - elpos_original + 4 }, 300);
				}
			});		
		}
	});


/**
* jQuery.timers - Timer abstractions for jQuery
* Written by Blair Mitchelmore (blair DOT mitchelmore AT gmail DOT com)
* Licensed under the WTFPL (http://sam.zoy.org/wtfpl/).
* Date: 2009/10/16
*
* @author Blair Mitchelmore
* @version 1.2
*
**/

	jQuery.fn.extend({
		everyTime: function (interval, label, fn, times) {
			return this.each(function () {
				jQuery.timer.add(this, interval, label, fn, times);
			});
		},
		oneTime: function (interval, label, fn) {
			return this.each(function () {
				jQuery.timer.add(this, interval, label, fn, 1);
			});
		},
		stopTime: function (label, fn) {
			return this.each(function () {
				jQuery.timer.remove(this, label, fn);
			});
		}
	});

	jQuery.extend({
		timer: {
			global: [],
			guid: 1,
			dataKey: "jQuery.timer",
			regex: /^([0-9]+(?:\.[0-9]*)?)\s*(.*s)?$/,
			powers: {
				// Yeah this is major overkill...
				'ms': 1,
				'cs': 10,
				'ds': 100,
				's': 1000,
				'das': 10000,
				'hs': 100000,
				'ks': 1000000
			},
			timeParse: function (value) {
				if (value == undefined || value == null)
					return null;
				var result = this.regex.exec(jQuery.trim(value.toString()));
				if (result[2]) {
					var num = parseFloat(result[1]);
					var mult = this.powers[result[2]] || 1;
					return num * mult;
				} else {
					return value;
				}
			},
			add: function (element, interval, label, fn, times) {
				var counter = 0;

				if (jQuery.isFunction(label)) {
					if (!times)
						times = fn;
					fn = label;
					label = interval;
				}

				interval = jQuery.timer.timeParse(interval);

				if (typeof interval != 'number' || isNaN(interval) || interval < 0)
					return;

				if (typeof times != 'number' || isNaN(times) || times < 0)
					times = 0;

				times = times || 0;

				var timers = jQuery.data(element, this.dataKey) || jQuery.data(element, this.dataKey, {});

				if (!timers[label])
					timers[label] = {};

				fn.timerID = fn.timerID || this.guid++;

				var handler = function () {
					if ((++counter > times && times !== 0) || fn.call(element, counter) === false)
						jQuery.timer.remove(element, label, fn);
				};

				handler.timerID = fn.timerID;

				if (!timers[label][fn.timerID])
					timers[label][fn.timerID] = window.setInterval(handler, interval);

				this.global.push(element);

			},
			remove: function (element, label, fn) {
				var timers = jQuery.data(element, this.dataKey), ret;

				if (timers) {

					if (!label) {
						for (label in timers)
							this.remove(element, label, fn);
					} else if (timers[label]) {
						if (fn) {
							if (fn.timerID) {
								window.clearInterval(timers[label][fn.timerID]);
								delete timers[label][fn.timerID];
							}
						} else {
							for (var fn in timers[label]) {
								window.clearInterval(timers[label][fn]);
								delete timers[label][fn];
							}
						}

						for (ret in timers[label]) break;
						if (!ret) {
							ret = null;
							delete timers[label];
						}
					}

					for (ret in timers) break;
					if (!ret)
						jQuery.removeData(element, this.dataKey);
				}
			}
		}
	});

	jQuery(window).bind("unload", function () {
		jQuery.each(jQuery.timer.global, function (index, item) {
			jQuery.timer.remove(item);
		});
});

// Flood prevention
var FloodPrevention = {
    operations: [],

    // returns true if the check allows the user to perform the operation
    check: function (method, limitCount, limitMinutes, limitMessage) {
        // no operations added?
        if (this.operations.length == 0)
            return true;

        // operation not found?
        var operationRef = this.getOperation(method);
        if (operationRef == null)
            return true;

        // invocation limit exceeded?
        if (typeof (limitCount) == 'undefined' || limitCount == 1)
            return false;

        if (operationRef.invokeCount >= limitCount) {
            var validCheck = true;

            // no timelimit set
            if (typeof (limitMinutes) == 'undefined' || limitMinutes == 0) {
                validCheck = false;
            }
            // check timelimit
            else {
                var currentTime = new Date();
                var limitDate = currentTime.setTime(currentTime.getTime() - (limitMinutes * 60 * 1000));
                validCheck = operationRef.lastInvoked < limitDate;
            }

            // check was not valid, any message to display?
            if (!validCheck) {
                if (typeof (limitMessage) != 'undefined' && limitMessage.length > 0)
                    alert(limitMessage);

                return false;
            }
        }

        return true;
    },

    // add successfully performed operation
    add: function (method) {
        var operationRef = this.getOperation(method);

        // new operation?
        if (operationRef == null) {
            operationRef = new Operation(method);
            this.operations.push(operationRef);
        }
        // existing operation
        else {
            operationRef.invokeCount++;
            operationRef.lastInvoked = new Date();
        }
    },

    // searches thru the list of performed operations, returns
    // the object if any match was found
    getOperation: function (method) {
        var operationRef = null;

        for (var i = 0; i < this.operations.length; i++) {
            var operation = this.operations[i];
            // got method match?
            if (operation.method == method) {
                operationRef = operation;
                break;
            }
        }

        return operationRef;
    }
}

function Operation(method) {
    this.method = method;
    this.lastInvoked = new Date();
    this.invokeCount = 1;
}

function modalIframe(elem, width, height) {
    $.fancybox({
        'padding': 0,
        'autoScale': true,
        'transitionIn': 'none',
        'transitionOut': 'none',
        'height': height,
        'width': width,
        'title': elem.title,
        'href': elem.href,
        'type': 'iframe'
    });
    return false;
}

