/*
 * Metadata - jQuery plugin for parsing metadata from elements
 *
 * Copyright (c) 2006 John Resig, Yehuda Katz, J�örn Zaefferer, Paul McLanahan
 *
 * Dual licensed under the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
 *
 * Revision: $Id: jquery.metadata.js 3640 2007-10-11 18:34:38Z pmclanahan $
 *
 */

/**
 * Sets the type of metadata to use. Metadata is encoded in JSON, and each property
 * in the JSON will become a property of the element itself.
 *
 * There are three supported types of metadata storage:
 *
 *   attr:  Inside an attribute. The name parameter indicates *which* attribute.
 *          
 *   class: Inside the class attribute, wrapped in curly braces: { }
 *   
 *   elem:  Inside a child element (e.g. a script tag). The
 *          name parameter indicates *which* element.
 *          
 * The metadata for an element is loaded the first time the element is accessed via jQuery.
 *
 * As a result, you can define the metadata type, use $(expr) to load the metadata into the elements
 * matched by expr, then redefine the metadata type and run another $(expr) for other elements.
 * 
 * @name $.metadata.setType
 *
 * @example <p id="one" class="some_class {item_id: 1, item_label: 'Label'}">This is a p</p>
 * @before $.metadata.setType("class")
 * @after $("#one").metadata().item_id == 1; $("#one").metadata().item_label == "Label"
 * @desc Reads metadata from the class attribute
 * 
 * @example <p id="one" class="some_class" data="{item_id: 1, item_label: 'Label'}">This is a p</p>
 * @before $.metadata.setType("attr", "data")
 * @after $("#one").metadata().item_id == 1; $("#one").metadata().item_label == "Label"
 * @desc Reads metadata from a "data" attribute
 * 
 * @example <p id="one" class="some_class"><script>{item_id: 1, item_label: 'Label'}</script>This is a p</p>
 * @before $.metadata.setType("elem", "script")
 * @after $("#one").metadata().item_id == 1; $("#one").metadata().item_label == "Label"
 * @desc Reads metadata from a nested script element
 * 
 * @param String type The encoding type
 * @param String name The name of the attribute to be used to get metadata (optional)
 * @cat Plugins/Metadata
 * @descr Sets the type of encoding to be used when loading metadata for the first time
 * @type undefined
 * @see metadata()
 */

(function($) {

$.extend({
	metadata : {
		defaults : {
			type: 'class',
			name: 'metadata',
			cre: /({.*})/,
			single: 'metadata'
		},
		setType: function( type, name ){
			this.defaults.type = type;
			this.defaults.name = name;
		},
		get: function( elem, opts ){
			var settings = $.extend({},this.defaults,opts);
			// check for empty string in single property
			if ( !settings.single.length ) settings.single = 'metadata';
			
			var data = $.data(elem, settings.single);
			// returned cached data if it already exists
			if ( data ) return data;
			
			data = "{}";
			
			if ( settings.type == "class" ) {
				var m = settings.cre.exec( elem.className );
				if ( m )
					data = m[1];
			} else if ( settings.type == "elem" ) {
				if( !elem.getElementsByTagName ) return;
				var e = elem.getElementsByTagName(settings.name);
				if ( e.length )
					data = $.trim(e[0].innerHTML);
			} else if ( elem.getAttribute != undefined ) {
				var attr = elem.getAttribute( settings.name );
				if ( attr )
					data = attr;
			}
			
			if ( data.indexOf( '{' ) <0 )
			data = "{" + data + "}";
			
			data = eval("(" + data + ")");
			
			$.data( elem, settings.single, data );
			return data;
		}
	}
});

/**
 * Returns the metadata object for the first member of the jQuery object.
 *
 * @name metadata
 * @descr Returns element's metadata object
 * @param Object opts An object contianing settings to override the defaults
 * @type jQuery
 * @cat Plugins/Metadata
 */
$.fn.metadata = function( opts ){
	return $.metadata.get( this[0], opts );
};

})(jQuery);





/* Copyright (c) 2007 Paul Bakaus (paul.bakaus@googlemail.com) and Brandon Aaron (brandon.aaron@gmail.com || http://brandonaaron.net)
 * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
 * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
 *
 * $LastChangedDate: 2008-11-20 14:36:57 -0700 (Thu, 20 Nov 2008) $
 * $Rev: 494 $
 *
 * Version: 1.2
 *
 * Requires: jQuery 1.2+
 */

(function($){
	
$.dimensions = {
	version: '1.2'
};

// Create innerHeight, innerWidth, outerHeight and outerWidth methods
$.each( [ 'Height', 'Width' ], function(i, name){
	
	// innerHeight and innerWidth
	$.fn[ 'inner' + name ] = function() {
		if (!this[0]) return;
		
		var torl = name == 'Height' ? 'Top'    : 'Left',  // top or left
		    borr = name == 'Height' ? 'Bottom' : 'Right'; // bottom or right
		
		return this.is(':visible') ? this[0]['client' + name] : num( this, name.toLowerCase() ) + num(this, 'padding' + torl) + num(this, 'padding' + borr);
	};
	
	// outerHeight and outerWidth
	$.fn[ 'outer' + name ] = function(options) {
		if (!this[0]) return;
		
		var torl = name == 'Height' ? 'Top'    : 'Left',  // top or left
		    borr = name == 'Height' ? 'Bottom' : 'Right'; // bottom or right
		
		options = $.extend({ margin: false }, options || {});
		
		var val = this.is(':visible') ? 
				this[0]['offset' + name] : 
				num( this, name.toLowerCase() )
					+ num(this, 'border' + torl + 'Width') + num(this, 'border' + borr + 'Width')
					+ num(this, 'padding' + torl) + num(this, 'padding' + borr);
		
		return val + (options.margin ? (num(this, 'margin' + torl) + num(this, 'margin' + borr)) : 0);
	};
});

// Create scrollLeft and scrollTop methods
$.each( ['Left', 'Top'], function(i, name) {
	$.fn[ 'scroll' + name ] = function(val) {
		if (!this[0]) return;
		
		return val != undefined ?
		
			// Set the scroll offset
			this.each(function() {
				this == window || this == document ?
					window.scrollTo( 
						name == 'Left' ? val : $(window)[ 'scrollLeft' ](),
						name == 'Top'  ? val : $(window)[ 'scrollTop'  ]()
					) :
					this[ 'scroll' + name ] = val;
			}) :
			
			// Return the scroll offset
			this[0] == window || this[0] == document ?
				self[ (name == 'Left' ? 'pageXOffset' : 'pageYOffset') ] ||
					$.boxModel && document.documentElement[ 'scroll' + name ] ||
					document.body[ 'scroll' + name ] :
				this[0][ 'scroll' + name ];
	};
});

$.fn.extend({
	position: function() {
		var left = 0, top = 0, elem = this[0], offset, parentOffset, offsetParent, results;
		
		if (elem) {
			// Get *real* offsetParent
			offsetParent = this.offsetParent();
			
			// Get correct offsets
			offset       = this.offset();
			parentOffset = offsetParent.offset();
			
			// Subtract element margins
			offset.top  -= num(elem, 'marginTop');
			offset.left -= num(elem, 'marginLeft');
			
			// Add offsetParent borders
			parentOffset.top  += num(offsetParent, 'borderTopWidth');
			parentOffset.left += num(offsetParent, 'borderLeftWidth');
			
			// Subtract the two offsets
			results = {
				top:  offset.top  - parentOffset.top,
				left: offset.left - parentOffset.left
			};
		}
		
		return results;
	},
	
	offsetParent: function() {
		var offsetParent = this[0].offsetParent;
		while ( offsetParent && (!/^body|html$/i.test(offsetParent.tagName) && $.css(offsetParent, 'position') == 'static') )
			offsetParent = offsetParent.offsetParent;
		return $(offsetParent);
	}
});

function num(el, prop) {
	return parseInt($.curCSS(el.jquery?el[0]:el,prop,true))||0;
};

})(jQuery);




/*
 * jQuery ifixpng plugin
 * (previously known as pngfix)
 * Version 2.1  (23/04/2008)
 * @requires jQuery v1.1.3 or above
 *
 * Examples at: http://jquery.khurshid.com
 * Copyright (c) 2007 Kush M.
 * Dual licensed under the MIT and GPL licenses:
 * http://www.opensource.org/licenses/mit-license.php
 * http://www.gnu.org/licenses/gpl.html
 */
 
 /**
  *
  * @example
  *
  * optional if location of pixel.gif if different to default which is images/pixel.gif
  * $.ifixpng('media/pixel.gif');
  *
  * $('img[src$=.png], #panel').ifixpng();
  *
  * @apply hack to all png images and #panel which icluded png img in its css
  *
  * @name ifixpng
  * @type jQuery
  * @cat Plugins/Image
  * @return jQuery
  * @author jQuery Community
  */
 
(function($) {

	/**
	 * helper variables and function
	 */
	$.ifixpng = function(customPixel) {
		$.ifixpng.pixel = customPixel;
	};
	
	$.ifixpng.getPixel = function() {
		return $.ifixpng.pixel || 'images/pixel.gif';
	};
	
	var hack = {
		ltie7  : $.browser.msie && $.browser.version < 7,
		filter : function(src) {
			return "progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true,sizingMethod=crop,src='"+src+"')";
		}
	};
	
	/**
	 * Applies ie png hack to selected dom elements
	 *
	 * $('img[src$=.png]').ifixpng();
	 * @desc apply hack to all images with png extensions
	 *
	 * $('#panel, img[src$=.png]').ifixpng();
	 * @desc apply hack to element #panel and all images with png extensions
	 *
	 * @name ifixpng
	 */
	 
	$.fn.ifixpng = hack.ltie7 ? function() {
    	return this.each(function() {
			var $$ = $(this);
			// in case rewriting urls
			var base = $('base').attr('href');
			if (base) {
				// remove anything after the last '/'
				base = base.replace(/\/[^\/]+$/,'/');
			}
			if ($$.is('img') || $$.is('input')) { // hack image tags present in dom
				if ($$.attr('src')) {
					if ($$.attr('src').match(/.*\.png([?].*)?$/i)) { // make sure it is png image
						// use source tag value if set 
						var source = (base && $$.attr('src').search(/^(\/|http:)/i)) ? base + $$.attr('src') : $$.attr('src');
						// apply filter
						$$.css({filter:hack.filter(source), width:$$.width(), height:$$.height()})
						  .attr({src:$.ifixpng.getPixel()})
						  .positionFix();
					}
				}
			} else { // hack png css properties present inside css
				var image = $$.css('backgroundImage');
				if (image.match(/^url\(["']?(.*\.png([?].*)?)["']?\)$/i)) {
					image = RegExp.$1;
					image = (base && image.substring(0,1)!='/') ? base + image : image;
					$$.css({backgroundImage:'none', filter:hack.filter(image)})
					  .children().children().positionFix();
				}
			}
		});
	} : function() { return this; };
	
	/**
	 * Removes any png hack that may have been applied previously
	 *
	 * $('img[src$=.png]').iunfixpng();
	 * @desc revert hack on all images with png extensions
	 *
	 * $('#panel, img[src$=.png]').iunfixpng();
	 * @desc revert hack on element #panel and all images with png extensions
	 *
	 * @name iunfixpng
	 */
	 
	$.fn.iunfixpng = hack.ltie7 ? function() {
    	return this.each(function() {
			var $$ = $(this);
			var src = $$.css('filter');
			if (src.match(/src=["']?(.*\.png([?].*)?)["']?/i)) { // get img source from filter
				src = RegExp.$1;
				if ($$.is('img') || $$.is('input')) {
					$$.attr({src:src}).css({filter:''});
				} else {
					$$.css({filter:'', background:'url('+src+')'});
				}
			}
		});
	} : function() { return this; };
	
	/**
	 * positions selected item relatively
	 */
	 
	$.fn.positionFix = function() {
		return this.each(function() {
			var $$ = $(this);
			var position = $$.css('position');
			if (position != 'absolute' && position != 'relative') {
				$$.css({position:'relative'});
			}
		});
	};

})(jQuery);

/**
 * Flash (http://jquery.lukelutman.com/plugins/flash)
 * A jQuery plugin for embedding Flash movies.
 * 
 * Version 1.0
 * November 9th, 2006
 *
 * Copyright (c) 2006 Luke Lutman (http://www.lukelutman.com)
 * Dual licensed under the MIT and GPL licenses.
 * http://www.opensource.org/licenses/mit-license.php
 * http://www.opensource.org/licenses/gpl-license.php
 * 
 * Inspired by:
 * SWFObject (http://blog.deconcept.com/swfobject/)
 * UFO (http://www.bobbyvandersluis.com/ufo/)
 * sIFR (http://www.mikeindustries.com/sifr/)
 * 
 * IMPORTANT: 
 * The packed version of jQuery breaks ActiveX control
 * activation in Internet Explorer. Use JSMin to minifiy
 * jQuery (see: http://jquery.lukelutman.com/plugins/flash#activex).
 *
 **/ 
;(function(){
	
var $$;

/**
 * 
 * @desc Replace matching elements with a flash movie.
 * @author Luke Lutman
 * @version 1.0.1
 *
 * @name flash
 * @param Hash htmlOptions Options for the embed/object tag.
 * @param Hash pluginOptions Options for detecting/updating the Flash plugin (optional).
 * @param Function replace Custom block called for each matched element if flash is installed (optional).
 * @param Function update Custom block called for each matched if flash isn't installed (optional).
 * @type jQuery
 *
 * @cat plugins/flash
 * 
 * @example $('#hello').flash({ src: 'hello.swf' });
 * @desc Embed a Flash movie.
 *
 * @example $('#hello').flash({ src: 'hello.swf' }, { version: 8 });
 * @desc Embed a Flash 8 movie.
 *
 * @example $('#hello').flash({ src: 'hello.swf' }, { expressInstall: true });
 * @desc Embed a Flash movie using Express Install if flash isn't installed.
 *
 * @example $('#hello').flash({ src: 'hello.swf' }, { update: false });
 * @desc Embed a Flash movie, don't show an update message if Flash isn't installed.
 *
**/
$$ = jQuery.fn.flash = function(htmlOptions, pluginOptions, replace, update) {
	
	// Set the default block.
	var block = replace || $$.replace;
	
	// Merge the default and passed plugin options.
	pluginOptions = $$.copy($$.pluginOptions, pluginOptions);
	
	// Detect Flash.
	if(!$$.hasFlash(pluginOptions.version)) {
		// Use Express Install (if specified and Flash plugin 6,0,65 or higher is installed).
		if(pluginOptions.expressInstall && $$.hasFlash(6,0,65)) {
			// Add the necessary flashvars (merged later).
			var expressInstallOptions = {
				flashvars: {  	
					MMredirectURL: location,
					MMplayerType: 'PlugIn',
					MMdoctitle: jQuery('title').text() 
				}					
			};
		// Ask the user to update (if specified).
		} else if (pluginOptions.update) {
			// Change the block to insert the update message instead of the flash movie.
			block = update || $$.update;
		// Fail
		} else {
			// The required version of flash isn't installed.
			// Express Install is turned off, or flash 6,0,65 isn't installed.
			// Update is turned off.
			// Return without doing anything.
			return this;
		}
	}
	
	// Merge the default, express install and passed html options.
	htmlOptions = $$.copy($$.htmlOptions, expressInstallOptions, htmlOptions);
	
	// Invoke $block (with a copy of the merged html options) for each element.
	return this.each(function(){
		block.call(this, $$.copy(htmlOptions));
	});
	
};
/**
 *
 * @name flash.copy
 * @desc Copy an arbitrary number of objects into a new object.
 * @type Object
 * 
 * @example $$.copy({ foo: 1 }, { bar: 2 });
 * @result { foo: 1, bar: 2 };
 *
**/
$$.copy = function() {
	var options = {}, flashvars = {};
	for(var i = 0; i < arguments.length; i++) {
		var arg = arguments[i];
		if(arg == undefined) continue;
		jQuery.extend(options, arg);
		// don't clobber one flash vars object with another
		// merge them instead
		if(arg.flashvars == undefined) continue;
		jQuery.extend(flashvars, arg.flashvars);
	}
	options.flashvars = flashvars;
	return options;
};
/*
 * @name flash.hasFlash
 * @desc Check if a specific version of the Flash plugin is installed
 * @type Boolean
 *
**/
$$.hasFlash = function() {
	// look for a flag in the query string to bypass flash detection
	if(/hasFlash\=true/.test(location)) return true;
	if(/hasFlash\=false/.test(location)) return false;
	var pv = $$.hasFlash.playerVersion().match(/\d+/g);
	var rv = String([arguments[0], arguments[1], arguments[2]]).match(/\d+/g) || String($$.pluginOptions.version).match(/\d+/g);
	for(var i = 0; i < 3; i++) {
		pv[i] = parseInt(pv[i] || 0);
		rv[i] = parseInt(rv[i] || 0);
		// player is less than required
		if(pv[i] < rv[i]) return false;
		// player is greater than required
		if(pv[i] > rv[i]) return true;
	}
	// major version, minor version and revision match exactly
	return true;
};
/**
 *
 * @name flash.hasFlash.playerVersion
 * @desc Get the version of the installed Flash plugin.
 * @type String
 *
**/
$$.hasFlash.playerVersion = function() {
	// ie
	try {
		try {
			// avoid fp6 minor version lookup issues
			// see: http://blog.deconcept.com/2006/01/11/getvariable-setvariable-crash-internet-explorer-flash-6/
			var axo = new ActiveXObject('ShockwaveFlash.ShockwaveFlash.6');
			try { axo.AllowScriptAccess = 'always';	} 
			catch(e) { return '6,0,0'; }				
		} catch(e) {}
		return new ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable('$version').replace(/\D+/g, ',').match(/^,?(.+),?$/)[1];
	// other browsers
	} catch(e) {
		try {
			if(navigator.mimeTypes["application/x-shockwave-flash"].enabledPlugin){
				return (navigator.plugins["Shockwave Flash 2.0"] || navigator.plugins["Shockwave Flash"]).description.replace(/\D+/g, ",").match(/^,?(.+),?$/)[1];
			}
		} catch(e) {}		
	}
	return '0,0,0';
};
/**
 *
 * @name flash.htmlOptions
 * @desc The default set of options for the object or embed tag.
 *
**/
$$.htmlOptions = {
	height: 240,
	flashvars: {},
	pluginspage: 'http://www.adobe.com/go/getflashplayer',
	src: '#',
	type: 'application/x-shockwave-flash',
	width: 320		
};
/**
 *
 * @name flash.pluginOptions
 * @desc The default set of options for checking/updating the flash Plugin.
 *
**/
$$.pluginOptions = {
	expressInstall: false,
	update: true,
	version: '6.0.65'
};
/**
 *
 * @name flash.replace
 * @desc The default method for replacing an element with a Flash movie.
 *
**/
$$.replace = function(htmlOptions) {
	this.innerHTML = '<div class="alt">'+this.innerHTML+'</div>';
	jQuery(this)
		.addClass('flash-replaced')
		.prepend($$.transform(htmlOptions));
};
/**
 *
 * @name flash.update
 * @desc The default method for replacing an element with an update message.
 *
**/
$$.update = function(htmlOptions) {
	var url = String(location).split('?');
	url.splice(1,0,'?hasFlash=true&');
	url = url.join('');
	var msg = '<p>This content requires the Flash Player. <a href="http://www.adobe.com/go/getflashplayer" target="_blank">Download Flash Player</a>. Already have Flash Player? <a href="'+url+'" target="_blank">Click here.</a></p>';
	this.innerHTML = '<span class="alt">'+this.innerHTML+'</span>';
	jQuery(this)
		.addClass('flash-update')
		.prepend(msg);
};
/**
 *
 * @desc Convert a hash of html options to a string of attributes, using Function.apply(). 
 * @example toAttributeString.apply(htmlOptions)
 * @result foo="bar" foo="bar"
 *
**/
function toAttributeString() {
	var s = '';
	for(var key in this)
		if(typeof this[key] != 'function')
			s += key+'="'+this[key]+'" ';
	return s;		
};
/**
 *
 * @desc Convert a hash of flashvars to a url-encoded string, using Function.apply(). 
 * @example toFlashvarsString.apply(flashvarsObject)
 * @result foo=bar&foo=bar
 *
**/
function toFlashvarsString() {
	var s = '';
	for(var key in this)
		if(typeof this[key] != 'function')
			s += key+'='+encodeURIComponent(this[key])+'&';
	return s.replace(/&$/, '');		
};
/**
 *
 * @name flash.transform
 * @desc Transform a set of html options into an embed tag.
 * @type String 
 *
 * @example $$.transform(htmlOptions)
 * @result <embed src="foo.swf" ... />
 *
 * Note: The embed tag is NOT standards-compliant, but it 
 * works in all current browsers. flash.transform can be
 * overwritten with a custom function to generate more 
 * standards-compliant markup.
 *
**/
$$.transform = function(htmlOptions) {
	htmlOptions.toString = toAttributeString;
	if(htmlOptions.flashvars) htmlOptions.flashvars.toString = toFlashvarsString;
	return '<embed ' + String(htmlOptions) + '/>';		
};

/**
 *
 * Flash Player 9 Fix (http://blog.deconcept.com/2006/07/28/swfobject-143-released/)
 *
**/
if (window.attachEvent) {
	window.attachEvent("onbeforeunload", function(){
		__flash_unloadHandler = function() {};
		__flash_savedUnloadHandler = function() {};
	});
}
	
})();

/**  
 *  Script lazy loader 0.5 - Modified By Web2ajaX
 *  Copyright (c) 2008 Bob Matsuoka
 *
 *  This program is free software; you can redistribute it and/or 
 *  modify it under the terms of the GNU General Public License
 *  as published by the Free Software Foundation; either version 2
 *  of the License, or (at your option) any later version.
 *
 *  Lazyloader updated for a jQuery implementation and appendChild in context
 *  not only in document.body
 *  Add script remove on callback to clean space.
 *
 */

var LazyLoader = {}; //namespace
LazyLoader.timer = {}; // contains timers for scripts
LazyLoader.scripts = []; // contains called script references
LazyLoader.load = function (url, context, callback) {
    // handle object or path
    var classname = null,
        properties = null;
    try {

        // make sure we only load once
        // note that we loaded already
        LazyLoader.scripts.push(url);
        var script = document.createElement("script");
        script.src = url;
        script.type = "text/javascript";
        context.get(0).appendChild(script); // add script tag to head element
        // was a callback requested
        if (callback) {
            // test for onreadystatechange to trigger callback
            script.onreadystatechange = function () {
                if (script.readyState === 'loaded' || script.readyState === 'complete') {
                    callback();
                    $(script).remove();
                }
            };
            // test for onload to trigger callback
            script.onload = function () {
                callback();
                $(script).remove();
                return;
            };
            // safari doesn't support either onload or readystate, create a timer
            // only way to do this in safari
            try {
                if (($.browser.webkit && !navigator.userAgent.match(/Version\/3/)) || $.browser.opera) { // sniff
                    LazyLoader.timer[url] = setInterval(function () {
                        if (/loaded|complete/.test(document.readyState)) {
                            clearInterval(LazyLoader.timer[url]);
                            callback(); // call the callback handler
                        }
                    }, 10);
                }
            } catch (e) {}
        }
    } catch (er) {
        alert(er);
    }
};


/**
 *  Display an xray overlay to show Ad loading progression
 */

var xrayAd = {

    div: null,
    viewport: null,
    thresold: 200,
    elements: [],
    adBlockCount: 0,
    w: 160,
    h: 200,

    // -- Init XrayAd Div
    init: function () {
        this.div = $('#xrayAd');
        if (!this.div) {
            this.div = $('<div>', {
                id: 'xrayAd',
                css: {
                    position: 'fixed',
                    top: 10,
                    left: 10,
                    width: this.w,
                    height: this.h,
                    zIndex: 10000,
                    background: 'rgba(0,0,0, 0.5)'
                }
            });
            this.div.appendTo($('body'));
        }
    },

    // -- Update viewport div
    viewportUpdate: function () {

        // Create div if not exists
        if (!this.viewport) {
            this.viewport = $('<div>', {
                id: 'xrayAdViewport',
                css: {
                    position: 'absolute',
                    width: this.w,
                    height: 10,
                    zIndex: 10001,
                    background: 'rgba(255,255,255, 0.3)'
                }
            });
            this.viewport.appendTo(this.div);
        }

        // Create div if not exists
        if (!this.viewThresoldTop) {
            this.viewThresoldTop = $('<div>', {
                id: 'xrayAdThresold',
                css: {
                    position: 'absolute',
                    width: this.w,
                    height: 1,
                    zIndex: 10002,
                    background: 'rgba(255,0,0, 0.5)'
                }
            });
            this.viewThresoldTop.appendTo(this.div);
            this.viewThresoldBottom = this.viewThresoldTop.clone().appendTo(this.div);
        }

        // Update div size and position
        this.bodyHeight = $(document).height();
        this.bodyWidth = $(window).width();
        var vH = ($(window).height() / this.bodyHeight) * xrayAd.h,
            vT = ($(window).scrollTop() / this.bodyHeight) * xrayAd.h;
        this.viewport.css({
            height: vH,
            top: vT
        });

        // Update thresold size and position
        this.viewThresoldTop.css({
            top: (($(window).scrollTop() - xrayAd.thresold) / this.bodyHeight) * xrayAd.h
        });
        this.viewThresoldBottom.css({
            top: (($(window).scrollTop() + xrayAd.thresold) / this.bodyHeight) * xrayAd.h + vH - 1
        });

        // Refresh Ad blocks
        if (this.div && this.div.length) {
            var blocks = this.div.find('.xrayAdBlock');

            $.each(blocks, function (key, val) {

                // Get block id 
                var xrayBlock = $(this);
                var adBlock = $(xrayAd.elements[key]);

                if (xrayBlock.length && adBlock.length) {
                    // Get offset and size of the page ad
                    var size = {};
                    size.off = adBlock.offset();
                    if (size.off) {
                        size.top = (size.off.top / xrayAd.bodyHeight) * xrayAd.h;
                        size.left = (size.off.left / xrayAd.bodyWidth) * xrayAd.w;
                        size.w = (Math.max(adBlock.width(), 10) / xrayAd.bodyWidth) * xrayAd.w;
                        size.h = (Math.max(adBlock.height(), 10) / xrayAd.bodyHeight) * xrayAd.h;

                        // Get ad load status
                        var bgColor = '#FF0071';
                        bgColor = (adBlock.data('loading') === 'true' ? 'orange' : bgColor);
                        bgColor = (adBlock.data('loaded') === 'true' ? '#00FF00' : bgColor);

                        // Update xray Block
                        xrayBlock.css({
                            top: size.top,
                            left: size.left,
                            width: size.w,
                            height: size.h,
                            borderColor: bgColor
                        });
                    }
                }

            });
        }
    },

    // -- Load elemnts to xray
    load: function (el, thresold) {

        // Init thresold
        this.thresold = thresold || 0;

        // Init Overlay Div
        this.init();

        // Draw each elements on div
        var adBlock = $('<div>', {
            'class': 'xrayAdBlock',
            'css': {
                position: 'absolute',
                background: '#ffffff',
                border: '1px solid #FF0071',
                top: 0,
                left: 0,
                width: 0,
                height: 0,
                zIndex: 10003
            }
        });

        // Init elements
        $.each(el, function () {

            // Create adBlock
            adBlock.clone().attr('xrayblock', 'xrayAdBlock_' + (xrayAd.adBlockCount++)).appendTo(xrayAd.div);

            // Bind load and complete
            $(this).bind('onCompleteXray', function () {
                xrayAd.viewportUpdate();
            });
            $(this).bind('onLoadXray', function () {
                xrayAd.viewportUpdate();
            });

            // Push src
            xrayAd.elements.push(this);
        });


        // Init viewport Div
        xrayAd.viewportUpdate();

        // Bind scroll
        $(window).bind("scroll", function (event) {
            xrayAd.viewportUpdate();
        });
    }


};

(function ($) {

    $.lazyLoadAdRunning = false;
    $.lazyLoadAdTimers = [];

    $.fn.lazyLoadAd = function (options) {
        var settings = {
            threshold: 0,
            failurelimit: 1,
            forceLoad: false,
            event: "scroll",
            viewport: window,
            placeholder: false,
            // Can specify a picture to replace media while loading
            onLoad: false,
            onComplete: false,
            timeout: 1500,
            debug: false,
            xray: false
        };

        if (options) {
            $.extend(settings, options);
        }

        /* Write logs if possible in console */

        function _debug() {
            if (typeof console !== 'undefined' && settings.debug) {
                var args = [];
                for (var i = 0; i < arguments.length; i++) {
                    args.push(arguments[i]);
                }
                try {
                    console.log('LazyLoadAD |', args);
                } catch (e) {}
            }
        }

        /* If xray display requested */
        if (settings.xray && (typeof xrayAd === 'object')) {
            xrayAd.load(this, settings.threshold);
        }

        /* Fire one scroll event per scroll. Not one scroll event per image. */
        var elements = this;
        $(settings.viewport).bind("checkLazyLoadAd", function () {
            var counter = 0;
            elements.each(function () {
                if ($.lazyLoadAdRunning) {
                    if ($.lazyLoadAdTimers.runTimeOut) {
                        clearTimeout($.lazyLoadAdTimers.runTimeOut);
                    }

                    $.lazyLoadAdTimers.runTimeOut = setTimeout(function () {
                        $(settings.viewport).trigger("checkLazyLoadAd");
                    }, 300);
                    return false;
                } else if (settings.forceLoad === true) {
                    $(this).trigger("load");
                } else if (!$.belowthefold(this, settings) && !$.abovethetop(this, settings)) {
                    $(this).trigger("load");
                } else {
                    if (counter++ > settings.failurelimit) {
                        return false;
                    }
                }
            }); /* Remove element from array so it is not looped next time. */
            var temp = $.grep(elements, function (element) {
                return !(($(element).data('loaded') === 'true') ? true : false);
            });
            elements = $(temp);
        });

        if ("scroll" === settings.event) {
            $(settings.viewport).bind("scroll", function (event) {
                if (elements.length === 0) {
                    return false;
                }

                $(settings.viewport).trigger("checkLazyLoadAd");
            });
        }


        // -- Bind each element
        this.each(function (_index, _value) {

            var self = $(this);

            /* Save original only if it is not defined in HTML. */
            if (undefined === self.attr("original")) {
                self.attr("original", self.attr("src"));
            }

            /* Test if element is loaded */
            self.isLoaded = function () {
                return ((self.data('loaded') === 'true') ? true : false);
            };

            /* Trigger Debug Display */
            self.bind("debug", function (e, status) {

                status = status || 'start';

                // -- Trigger xRay if possible
                if (settings.xray) {
                    if (status === 'start') {
                        self.trigger('onLoadXray');
                    }
                    else if (status === 'error') {
                        self.trigger('onErrorXray');
                    }
                    else if (status === 'complete') {
                        self.trigger('onCompleteXray');
                    }
                }

                // -- Change border color of ad frame
                if (settings.debug) {
                    if (status === 'start') {
                        self.css({
                            border: '3px solid orange'
                        });
                    }
                    else if (status === 'error') {
                        self.css({
                            border: '3px solid red'
                        });
                    }
                    else if (status === 'complete') {
                        self.css({
                            border: '3px solid green'
                        });
                    }
                }

            });

            /* On ad Load successful */
            self.one('onComplete', function () {

                _debug('---> lazyLoadComplete');

                // -- Remove original attr
                $(self).removeAttr("original");

                // -- Set as loaded
                $.lazyLoadAdRunning = false;
                self.data('loaded', 'true');

                // -- Mark debug
                self.trigger('debug', 'complete');

                if (typeof settings.onComplete === 'function') {
                    try {
                        settings.onComplete();
                    } catch (e) {}
                }
            });


            /* Launch the makina !! */
            self.stack = [];
            self.makinaBlock = false;
            self.bind('makina_go', function () {

                if (self.makinaBlock) {
                    return false;
                }

                if (self.stack.length > 0) {
                    var el = self.stack.shift();

                    var wrapAd = self.find('.wrapAd');
                    if (!wrapAd.length) {
                        wrapAd = $('<div class="wrapAd"></div>').clone();
                        wrapAd.appendTo(self);
                    }

                    var wrap = $('<div>').clone().appendTo(wrapAd);

                    if (typeof el === 'string') {
                        wrap.replaceWith(el);
                    } else if (typeof el === 'object') {
                        if (el.is('script')) {

                            // -- Load JS and block makina until script is loaded
                            if (el.attr('src')) {
                                _debug('JS to load !! --> ' + el.attr('src'));
                                //self.makinaBlock = true ;
                                LazyLoader.load(el.attr('src'), self, function () {
                                    self.makinaBlock = false;
                                    _debug('JS to load !! ++> ' + el.attr('src'));
                                    self.trigger('makina_go');
                                });
                            }

                            // -- Write JS code in wrapper
                            else {
                                wrap.replaceWith(el);
                            }
                        } else {
                            wrap.replaceWith(el);
                        }
                    }

                    self.trigger('makina_go');
                } else {
                    if ($.lazyLoadAdTimers.loadJS) {
                        clearTimeout($.lazyLoadAdTimers.loadJS);
                    }
                    $.lazyLoadAdTimers.loadJS = setTimeout(function () {
                        self.trigger('onComplete');
                    }, settings.timeout);
                }

            });

            /* Write directly in DOM : tag is html valid */
            self.bind('docWrite_direct', function (e, html) {
                var el = $(html);
                _debug('Fragment Direct Write : ', el, el.length);
                $.each(el, function () {
                    self.stack.push($(this));
                });
                self.trigger('makina_go');
            });

            /* Write directly in DOM : tag is html valid */
            self.bind('docWrite_delayed', function (e, html) {
                _debug('Fragment Delayed Write : ', html);

                self.numWrappers--;
                _debug("Fragment append : ", self.numWrappers, html);
                self.docHtmlCurrent += html;
                if (self.numWrappers === 0) {
                    html = self.docHtmlCurrent;
                    self.docHtmlCurrent = '';
                    setTimeout(function () {
                        self.stack.push(html);
                        self.docHtmlCurrent = '';
                        self.trigger('makina_go');
                    }, 0);
                }
            });



            /* Overload the default document.write */
            self.numWrappers = 0;
            self.docHtmlCurrent = '';
            self.bind('docWrite_overload', function () {

                // -- Overload default document.write function
                document._writeOriginal = document.write;
                document.write = document.writeln = function () {

                    var args = arguments,
                        id = null;
                    var html = '';
                    for (var i = 0; i < args.length; i++) {
                        html += args[i];
                    }

                    // -- Check if html to write is valid
                    var testHTML = '',
                        directWrite = false;

                    try {
                        testHTML = $(html);
                        directWrite = ((testHTML.is('div') || testHTML.is('script')) ? true : false);
                    } catch (e) {}

                    self.history[self.fragmentId] = self.history[self.fragmentId] || {};
                    if (self.history[self.fragmentId][html] === undefined) {
                        self.history[self.fragmentId][html] = true;
                        if (directWrite) {
                            self.trigger('docWrite_direct', html);
                        } else {
                            self.numWrappers++;
                            setTimeout(function () {
                                self.trigger('docWrite_delayed', html);
                            }, 0);

                        }
                    }
                };
            });


            /* Eval Script into <code> tags */
            self.bind('evalCode', function () {
                var scripts = [],
                    script, regexp = /<code[^>]*>([\s\S]*?)<\/code>/gi;

                while ((script = regexp.exec(self.html()))) {
                    var _s = script[1];
                    _s = _s.replace('<!--//<![CDATA[', '').replace('//]]>-->', '').replace('<!--', '').replace('//-->', '');
                    _s = _s.replace(/\&gt\;/g, '>').replace(/\&lt\;/g, '<');
                    scripts.push($.trim(_s));
                }

                // -- Eval param code before calling ad script                    
                try {
                    scripts = (scripts.length ? scripts.join('\n') : '');
                    _debug('Script to eval : ', scripts);
                    if (scripts !== '') {
                        eval(scripts);
                    }
                } catch (e) {}
            });


            /* Load a JS and wait for callback */
            self.bind('loadJS', function (e, js2load) {

                var callback = null,
                    script = null;
                if (js2load.src) {
                    callback = js2load.callback ||  null;
                    js2load = js2load.src;
                }

                // Add an anticache 
                if (js2load.indexOf('?') === -1) {
                    js2load += '?_=' + (new Date().getTime());
                } else {
                    js2load += '&_=' + (new Date().getTime());
                }

                _debug('loadJS :: ', js2load);

                // Request JS
                LazyLoader.load(js2load, self, function () {
                    _debug('loadJS COMPLETE :: ' + js2load);
                    if (callback) {
                        callback();
                    } 
                    else {
                        $.lazyLoadAdTimers.loadJS = setTimeout(function () {
                            self.trigger('onComplete');
                        }, settings.timeout);
                    }
                });

            });


            /* When appear is triggered load ad. */
            self.one("load", function () {

                // Detect if element is already loaded
                if (!self.isLoaded()) {

                    // Lock other adverts load
                    $.lazyLoadAdRunning = true;

                    // Have to load the current ad...
                    self.data('loading', 'true');
                    self.trigger('debug', 'start');

                    // Get original source to load
                    var srcOriginal = $(self).attr("original");

                    // Set fragmentId
                    self.history = {};

                    // -- Call script and let's dance
                    _debug('------------------------------  Lazy Load Ad CALL ----');
                    _debug('Context : ', self);

                    // Bind document.write overload
                    self.trigger('docWrite_overload');

                    // Eval code
                    self.trigger('evalCode');

                    // Eval attached script
                    if (srcOriginal) {
                        self.trigger('loadJS', srcOriginal);
                    }

                }
            });



            /* When wanted event is triggered load ad */
            /* by triggering appear.                              */
            if ("scroll" !== settings.event) {
                self.bind(settings.event, function (event) {
                    if (!self.isLoaded()) {
                        self.trigger("load");
                    }
                });
            }
        });

        /* Force initial check if images should appear. */
        $(settings.viewport).trigger('checkLazyLoadAd');

        return this;

    };

    /* Convenience methods in $ namespace.           */
    /* Use as  $.belowthefold(element, {threshold : 100, container : window}) */

    $.belowthefold = function (element, settings) {
        var fold = 0;
        if (settings.viewport === undefined || settings.viewport === window) {
            fold = $(window).height() + $(window).scrollTop();
        } else {
            fold = $(settings.viewport).offset().top + $(settings.viewport).height();
        }
        return fold <= $(element).offset().top - settings.threshold;
    };

    $.abovethetop = function (element, settings) {
        var fold = 0;
        if (settings.viewport === undefined || settings.viewport === window) {
            fold = $(window).scrollTop();
        } else {
            fold = $(settings.viewport).offset().top;
        }
        return fold >= $(element).offset().top + settings.threshold + $(element).height();
    };

})(jQuery);
