// Moo4Q
// https://github.com/rpflorence/moo4q/blob/master/Source/Class.Mutators.jQuery.js
Class.Mutators.jQuery = function(name){
	var self = this;
	jQuery.fn[name] = function(arg){
		var instance = this.data(name);
		if ($type(arg) == 'string'){
			var prop = instance[arg];
			if ($type(prop) == 'function'){
				var returns = prop.apply(instance, Array.slice(arguments, 1));
				return (returns == instance) ? this : returns;
			} else if (arguments.length == 1){
				return prop;
			}
			instance[arg] = arguments[1];
		} else {
			if (instance) return instance;
			
			// LOCAL MOD: since this.selector is not always, available, we've added || this
			this.data(name, new self(this.selector || this, arg));
		}
		return this;
	};
};

/*------------------ USER CLASS ------------------*/
var User = new Class({

	ui_prefs: {},
	loggedIn: false,
	jQuery:   'user',

	initialize: function(loggedIn, ui_prefs) {
		var self      = this;
		this.loggedIn = loggedIn;
		this.ui_prefs = ui_prefs;

		jQuery(function() {
			//constructor dom loaded page scan stuff
		});
	},

	setUIPref: function(property, value) {
		if(jQuery.user.loggedIn) {
			if(typeof value == 'object') value = value.join(',');
			jQuery.get('/user/SetUIPref/'+property+'/'+escape(value));
			this.ui_prefs[property] = value;
		}
		else {
			//logger.addMessage('Login to Save Preferences');
		}
	}
});


// Global BY Namespace
var BY = {
	
	// User_Link
	rankBy : 'google_position',
	maxPositions : {
		'google_position': 30,
		'bing_position': 30
	}
	
};


if (jQuery){(function($){
	
	
	/*------------------ TOOLTIPS ------------------*/
	BY.tooltips = function(container) {
		var container = container || 'body';
		
		$(container).find('.tooltipTrigger').each(function(){
			$(this).tooltip({  
				offset: [0, 0],
				relative: $(this).next().is('.relative'),
			}).dynamic({
				top:{direction: 'up', position: ['top', 'center']},
				right:{direction: 'right', position: ['center', 'right']},
				bottom:{direction: 'down', position: ['bottom', 'center']},
				left:{direction: 'left', position: ['center', 'left']}
			});
		});
		
		$(container).find('.tooltipAlertTrigger').each(function(){
			$(this).tooltip({ 
				offset: [10, 0], 
				effect: 'slide', 
				position: 'top center',
				relative: true
			});
		});
	};
	
	// init
	$(document).ready(function(){
		BY.tooltips();
	});

	
	/*------------------ POPOVERS ------------------*/
	$.fn.popup = function(options) {
		// return $.fancybox(this, options);
		
		var self = this;
		
		// console.log('opening overlay ' + $(this).attr('id') + ' (' + $('.popup:visible').length + ' overlays already opened)');
		
		var overlay = $(this).overlay($.extend({
			oneInstance: false, // ! secondaryOverlay,
			load: true,
			fixed: false,
			closeOnClick: false,
			closeOnEsc: false,
			onBeforeLoad: function() {
				
				// If other overlays aren't already open, show the mask
				if ($('.popup:visible').length == 0) {
					this.getOverlay().expose({
						color: '#000',
						closeOnClick: false,
						closeOnEsc: false
					});
				} 
				
				// otherwise, hide visible popups behind mask
				else {
					$('.popup:visible').css({'z-index':0});
				}
				
				$(this.getOverlay()).css({'z-index':++$.popup.zIndex});
				
				self.trigger('beforeLoad');
			},
			onLoad: function(){
				
				// max out mask height
				$.popup.maximizeMaskHeight();
				
				self.trigger('load');
			},
			onClose: function(){
				
				// If there are no overlays left, hide the mask too
				if ($('.popup:visible').length < 1) {
					$.mask.close();
				} 
				
				// otherwise pull the next hidden popup out from behind the mask
				else {
					$('.popup:visible').eq(-1).css({'z-index':$.popup.zIndex});
				}
				
				self.trigger('close');
			}

		}, options));
		
		// show the popup now?
		if (!options || !options.load) {
			overlay.load();
		}
		
		return this;
	};
	
	$.popup = {
		zIndex: 10000,
		close : function(popup) {
			var API = $(popup).data('overlay');
			if (API) {
				return API.close();
			}
			return false;
		},
		closeAll : function() {
			return $('.popup:visible').each(function(){
				$.popup.close(this);
			});
		},
		maximizeMaskHeight : function() {
			return $('#exposeMask').height($.documentHeight() + 'px');
		},
		loading : function(activate) {
			if (activate === false) {
				$('.popup.loading').fadeOut('fast', function(){
					$.popup.close('.popup.loading');
				});
			} else {
				if ($('.popup.loading').length == 0) {
					$('<div class="popup loading"><div class="animation"></div></div>').appendTo('body');
				}
				$('.popup.loading').popup({ top: "42%" });
			}
		}
	};
	
	$.documentHeight = function(){
		return Math.max(
	        $(document).height(),
	        $(window).height(),
	        // For opera:
	        document.documentElement.clientHeight
	    );
	};
	

	/*------------------ PLOTS ------------------*/
	$.fn.plot = function(options){
		
		// Check options
		if (!options || !options.series) {
			this.addClass('noPlot');
			return;
		} else {
			this.removeClass('noPlot');
		}
		
		// Line color
		var lineColor = '#63c000' // '#646464';
		if (this.hasClass('positive')) {
			lineColor = '#63c000';
		} else if (this.hasClass('negative')) {
			lineColor = '#E34A31';
		}
		
		/* Run through the series to find the ymax
		yMax = 0;
		$(options.series).each(function(){
			$(this.data).each(function(){
				yMax = Math.max(yMax, this[1]);
			});
		});
		*/
	
		var options = $.extend(true, {
			chart: {
				renderTo: this.attr('id'),
				defaultSeriesType: 'area'
			},
			tooltip: {
				enabled: true
			},
			plotOptions : {
				area: {
					shadow: false, 
					marker: {
						enabled: true,
						radius: 4,
						lineWidth: 3,
						lineColor: lineColor,
						fillColor: '#FFFFFF'
					},
					fillOpacity: .15,
					lineWidth: 3
				}
			},
			colors: [lineColor],
			title:   { text: false },
			yAxis:   {
				// max: yMax,
				maxPadding: 6,
				gridLineWidth: 1,
				gridLineColor: '#dfdfdf',
				startOnTick: true,
				endOnTick: false,
				title: { text: false }, 
				labels: { 
					style: { color: '#B0BAC1' }
				},
			},
			xAxis:   { 
				type: 'datetime', 
				title: { text: false }, 
				labels: { style: { color: '#B0BAC1' }, y: 20 },
				reversed: false, 
				lineWidth: 1,
				gridLineWidth: 1,
				gridLineColor: '#dfdfdf',
				startOnTick: false,
				endOnTick: false
			},
			legend:  { enabled: false },
			credits: { enabled: false },
			series: []
		}, options);
		
		// Some friendly programmer checks
		//if (console) {
		//	if (!options.chart.renderTo) { console.log('All plot containers must have an id attribute'); }
		//}
		
		this.data('plot', new Highcharts.Chart(options));
		
		return this;
			
	}; // $.fn.plot()



	/*------------------ TABS ------------------*/
	$.fn.tab = function(options) {
		
		// EXAMPLE USAGE
		// $('.tab').tab().select();
		
		var options = $.extend(true, {
			tabs: null,
			panes: null
		}, options);
	
		// Add functionality to this jQuery object
		$.extend(this, {
			tabs    : options.tabs  || this.siblings('.tab'),
			panes   : options.panes || this.closest('.tabs').next('.panes').find('.pane'),
		
			// Get the pane associated with this tab
			pane: function() {
				return this.panes.eq(this.index());
			},

			// Select this tab (and only this tab)
			select: function() {
				this.tabs.removeClass('current');
				this.panes.removeClass('current');
				this.addClass('current');
				this.pane().addClass('current');
				return this;
			}
		});
	
		return this;
	};
	
	
	/*------------------ SIDE BY SIDE LINKS ------------------*/
	$('a.sideBySide').live('click', function(){
		var $popup = $(this).closest('.popup');
        var workingWindow = boostActionPopup($(this).attr('href'));
		return false;
    });

	function boostActionPopup(url) {
		// var aHeight = screen.availHeight;
		var aHeight = window.outerHeight;
		var aWidth = (screen.availWidth-850);
		return window.open(url, '', 'width='+aWidth+',height='+ aHeight +',left=850,top=0,scrollbars=yes,location=yes,toolbar=yes');
	}

	

})(jQuery);}


/**
 *
 * Meta Nav
 *
 */
var MetaNav = {};

if(jQuery){(function(){

	$.extend(MetaNav, {
		
		showUserMenu: function() {
			$('#utilUserNameHolder').addClass('expanded');
		},
		
		hideUserMenu: function() {
			$('#utilUserNameHolder').removeClass('expanded');
		},
		
		showAllAlerts: function() {
			$('#popupRecentAlerts').appendTo('body').popup();
		},
		
		showAlerts: function() {
			$('#utilAlerts').addClass('expanded');
			
			// $('#viewAlerts_container').slideDown('slow');
			$('#viewAlerts_container').animate({ height:'toggle', width:'toggle' });
			$('#viewAlerts').removeClass('turnOn').addClass('turnOff').animate({ queue: false });

			// Mark the alerts as "read"
			if ($('#utilAlerts:not(.noAlerts)').length) {
				$.post('/user/dashboard/alertsChecked');
				$('#utilAlerts').addClass('noAlerts');
			}
		},
	
		hideAlerts: function() {
			$('#viewAlerts').animate({ width: '59px' }, { queue: false, complete: function(){
				$('#viewAlerts').removeClass('turnOff').addClass('turnOn');
			}});
			$('#viewAlerts_container:visible').animate({ height:'toggle', width:'toggle'}, function(){
				$('#utilAlerts').removeClass('expanded');
			});
		}
	});

	$(document).ready(function(){
		
		// USER MENU hide and show buttons
		$('#utilUserName').click(function(){
			MetaNav.showUserMenu();
			return false;
		});
		$('#utilUserNameOpen > p').click(function(){
			MetaNav.hideUserMenu();
			return false;
		});
		
		// ALERTS popover
		$('#utilAlerts.noAlerts #viewAlerts.turnOn, #viewAllAlerts').live('click', function(){
			MetaNav.showAllAlerts();
			return false;
		});
		
		// ALERTS hide and show buttons
		$('#utilAlerts:not(.noAlerts) #viewAlerts.turnOn').live('click', function(){
			MetaNav.showAlerts();
			return false;
		});
		$('#viewAlerts.turnOff').live('click', function(){
			MetaNav.hideAlerts();
			return false;
		});
	
		// ALERTS + USER MENU hide when you click anywhere else on the page
		$(document).click(function(event){
			if ($(event.target).closest('#utilAlertsHolder').length == 0) {
				MetaNav.hideAlerts();
			}
			if ($(event.target).closest('#utilUserNameHolder').length == 0) {
				MetaNav.hideUserMenu();
			}
		});
	});
	
})(jQuery);}





/*
    http://www.JSON.org/json2.js
    2011-02-23

    Public Domain.

    NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.

    See http://www.JSON.org/js.html

    This file creates a global JSON object containing two methods: stringify
    and parse.

        JSON.stringify(value, replacer, space)
            value       any JavaScript value, usually an object or array.

            replacer    an optional parameter that determines how object
                        values are stringified for objects. It can be a
                        function or an array of strings.

            space       an optional parameter that specifies the indentation
                        of nested structures. If it is omitted, the text will
                        be packed without extra whitespace. If it is a number,
                        it will specify the number of spaces to indent at each
                        level. If it is a string (such as '\t' or '&nbsp;'),
                        it contains the characters used to indent at each level.

            This method produces a JSON text from a JavaScript value.


        JSON.parse(text, reviver)
            This method parses a JSON text to produce an object or array.
            It can throw a SyntaxError exception.

            The optional reviver parameter is a function that can filter and
            transform the results. It receives each of the keys and values,
            and its return value is used instead of the original value.
            If it returns what it received, then the structure is not modified.
            If it returns undefined then the member is deleted.

    This is a reference implementation. You are free to copy, modify, or
    redistribute.
*/

/*jslint evil: true, strict: false, regexp: false */

/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
    call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
    getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
    lastIndex, length, parse, prototype, push, replace, slice, stringify,
    test, toJSON, toString, valueOf
*/


// Create a JSON object only if one does not already exist. We create the
// methods in a closure to avoid creating global variables.

var JSON;
if (!JSON) {
    JSON = {};
}

(function () {
    "use strict";

    function f(n) {
        // Format integers to have at least two digits.
        return n < 10 ? '0' + n : n;
    }

    if (typeof Date.prototype.toJSON !== 'function') {

        Date.prototype.toJSON = function (key) {

            return isFinite(this.valueOf()) ?
                this.getUTCFullYear()     + '-' +
                f(this.getUTCMonth() + 1) + '-' +
                f(this.getUTCDate())      + 'T' +
                f(this.getUTCHours())     + ':' +
                f(this.getUTCMinutes())   + ':' +
                f(this.getUTCSeconds())   + 'Z' : null;
        };

        String.prototype.toJSON      =
            Number.prototype.toJSON  =
            Boolean.prototype.toJSON = function (key) {
                return this.valueOf();
            };
    }

    var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
        escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
        gap,
        indent,
        meta = {    // table of character substitutions
            '\b': '\\b',
            '\t': '\\t',
            '\n': '\\n',
            '\f': '\\f',
            '\r': '\\r',
            '"' : '\\"',
            '\\': '\\\\'
        },
        rep;


    function quote(string) {

        escapable.lastIndex = 0;
        return escapable.test(string) ? '"' + string.replace(escapable, function (a) {
            var c = meta[a];
            return typeof c === 'string' ? c :
                '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
        }) + '"' : '"' + string + '"';
    }


    function str(key, holder) {

        var i,          // The loop counter.
            k,          // The member key.
            v,          // The member value.
            length,
            mind = gap,
            partial,
            value = holder[key];

        if (value && typeof value === 'object' &&
                typeof value.toJSON === 'function') {
            value = value.toJSON(key);
        }

        if (typeof rep === 'function') {
            value = rep.call(holder, key, value);
        }

        switch (typeof value) {
        case 'string':
            return quote(value);

        case 'number':

            return isFinite(value) ? String(value) : 'null';

        case 'boolean':
        case 'null':

            return String(value);

        case 'object':

            if (!value) {
                return 'null';
            }

            gap += indent;
            partial = [];

            if (Object.prototype.toString.apply(value) === '[object Array]') {

                length = value.length;
                for (i = 0; i < length; i += 1) {
                    partial[i] = str(i, value) || 'null';
                }

                v = partial.length === 0 ? '[]' : gap ?
                    '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' :
                    '[' + partial.join(',') + ']';
                gap = mind;
                return v;
            }

            if (rep && typeof rep === 'object') {
                length = rep.length;
                for (i = 0; i < length; i += 1) {
                    if (typeof rep[i] === 'string') {
                        k = rep[i];
                        v = str(k, value);
                        if (v) {
                            partial.push(quote(k) + (gap ? ': ' : ':') + v);
                        }
                    }
                }
            } else {

                for (k in value) {
                    if (Object.prototype.hasOwnProperty.call(value, k)) {
                        v = str(k, value);
                        if (v) {
                            partial.push(quote(k) + (gap ? ': ' : ':') + v);
                        }
                    }
                }
            }

            v = partial.length === 0 ? '{}' : gap ?
                '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' :
                '{' + partial.join(',') + '}';
            gap = mind;
            return v;
        }
    }


    if (typeof JSON.stringify !== 'function') {
        JSON.stringify = function (value, replacer, space) {

            var i;
            gap = '';
            indent = '';

            if (typeof space === 'number') {
                for (i = 0; i < space; i += 1) {
                    indent += ' ';
                }

            } else if (typeof space === 'string') {
                indent = space;
            }

            rep = replacer;
            if (replacer && typeof replacer !== 'function' &&
                    (typeof replacer !== 'object' ||
                    typeof replacer.length !== 'number')) {
                throw new Error('JSON.stringify');
            }

            return str('', {'': value});
        };
    }


    if (typeof JSON.parse !== 'function') {
        JSON.parse = function (text, reviver) {

            var j;

            function walk(holder, key) {

                var k, v, value = holder[key];
                if (value && typeof value === 'object') {
                    for (k in value) {
                        if (Object.prototype.hasOwnProperty.call(value, k)) {
                            v = walk(value, k);
                            if (v !== undefined) {
                                value[k] = v;
                            } else {
                                delete value[k];
                            }
                        }
                    }
                }
                return reviver.call(holder, key, value);
            }

            text = String(text);
            cx.lastIndex = 0;
            if (cx.test(text)) {
                text = text.replace(cx, function (a) {
                    return '\\u' +
                        ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
                });
            }

            if (/^[\],:{}\s]*$/
                    .test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@')
                        .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']')
                        .replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {

                j = eval('(' + text + ')');

                return typeof reviver === 'function' ?
                    walk({'': j}, '') : j;
            }

            throw new SyntaxError('JSON.parse');
        };
    }
}());

// IE8 and below don’t support ES5 Date.now()
if (!Date.now) {
	Date.now = function() {
		return +new Date();
	};
};

