function initButtons(){$(".scrollNextDoAction").click(function(){var a=$(".inview");var b=a.next().attr("id");if(b){goToByScroll(b)}$("#upButton").show(500)});$(".scrollPreviousDoAction").click(function(){var a=$(".inview");var b=a.prev().attr("id");if(b){goToByScroll(b)}});$("#subMenu").localScroll();$("#subMenu .displayTooltipDoAction").hover(function(a){$("#subMenu .tips").hide();$(a.target).next("div").show()});$.fn.qtip.styles.etsw={width:{min:100,max:150},background:"#b21f24",color:"#f2f2f2",textAlign:"center",border:{width:2,radius:5,color:"#b21f24"},tip:"bottomLeft",name:"dark"};$(".showtip").qtip({style:{name:"etsw",tip:true},position:{corner:{target:"leftMiddle",tooltip:"rightMiddle"}},content:{text:false},hide:{effect:{type:"slide"}},show:{effect:{type:"grow"}}})}function goToByScroll(a){$("html,body").animate({scrollTop:$("#"+a).offset().top+10},"slow")}
function action_submitForm(a){
if ( !$(this).hasClass('noAjax') ){
a.preventDefault();$(".submitFormDoAction").val("Sending");var b=$(a.target).serialize();var c=$(a.target).find(" :input");c.each(function(a,b){$(this).attr("disabled","true")});$.ajax({url:"ajax/sendMail.php",type:"POST",dataType:"json",data:b,success:function(a,b,d){if(!a||a.status!="success"){c.each(function(a,b){$(this).removeAttr("disabled")});$(".submitFormDoAction").val("Send");var e="Opps! Something wrong happened.
";if(a.message){e+=a.message}$("#status").html(e);return false}if(a.status=="success"){$(".submitFormDoAction").val("Send");c.each(function(a,b){$(this).removeAttr("disabled")});$("#status").html("Thank you for your email, we will get back to you shortly.")}},error:function(a,b,d){c.each(function(a,b){$(this).removeAttr("disabled")});$(".submitFormDoAction").val("Send");$("#status").html("There was an error. Please try again.");return false;if(typeof console!="undefined")console.dir(a);return false}})}}
function initAll(){$(".submitFormDoAction").die("click").live("click",function(){$(this).closest("form").submit()});$("form").submit(action_submitForm)}$(document).ready(initAll);$(document).ready(function(a){$(".grindSignature").hover(function(){$("#grindSignature").fadeIn()},function(){$("#grindSignature").fadeOut()})})/**
* jQuery.LocalScroll - Animated scrolling navigation, using anchors.
* Copyright (c) 2007-2009 Ariel Flesler - aflesler(at)gmail(dot)com | http://flesler.blogspot.com
* Dual licensed under MIT and GPL.
* Date: 3/11/2009
* @author Ariel Flesler
* @version 1.2.7
**/
;(function($){var l=location.href.replace(/#.*/,'');var g=$.localScroll=function(a){$('body').localScroll(a)};g.defaults={duration:1e3,axis:'y',event:'click',stop:true,target:window,reset:true};g.hash=function(a){if(location.hash){a=$.extend({},g.defaults,a);a.hash=false;if(a.reset){var e=a.duration;delete a.duration;$(a.target).scrollTo(0,a);a.duration=e}i(0,location,a)}};$.fn.localScroll=function(b){b=$.extend({},g.defaults,b);return b.lazy?this.bind(b.event,function(a){var e=$([a.target,a.target.parentNode]).filter(d)[0];if(e)i(a,e,b)}):this.find('a,area').filter(d).bind(b.event,function(a){i(a,this,b)}).end().end();function d(){return!!this.href&&!!this.hash&&this.href.replace(this.hash,'')==l&&(!b.filter||$(this).is(b.filter))}};function i(a,e,b){var d=e.hash.slice(1),f=document.getElementById(d)||document.getElementsByName(d)[0];if(!f)return;if(a)a.preventDefault();var h=$(b.target);if(b.lock&&h.is(':animated')||b.onBefore&&b.onBefore.call(b,a,f,h)===false)return;if(b.stop)h.stop(true);if(b.hash){var j=f.id==d?'id':'name',k=$(' ').attr(j,d).css({position:'absolute',top:$(window).scrollTop(),left:$(window).scrollLeft()});f[j]='';$('body').prepend(k);location=e.hash;k.remove();f[j]=d}h.scrollTo(f,b).trigger('notify.serialScroll',[f])}})(jQuery);/**
* jQuery.ScrollTo - Easy element scrolling using jQuery.
* Copyright (c) 2007-2009 Ariel Flesler - aflesler(at)gmail(dot)com | http://flesler.blogspot.com
* Dual licensed under MIT and GPL.
* Date: 5/25/2009
* @author Ariel Flesler
* @version 1.4.2
*
* http://flesler.blogspot.com/2007/10/jqueryscrollto.html
*/
;(function(d){var k=d.scrollTo=function(a,i,e){d(window).scrollTo(a,i,e)};k.defaults={axis:'xy',duration:parseFloat(d.fn.jquery)>=1.3?0:1};k.window=function(a){return d(window)._scrollable()};d.fn._scrollable=function(){return this.map(function(){var a=this,i=!a.nodeName||d.inArray(a.nodeName.toLowerCase(),['iframe','#document','html','body'])!=-1;if(!i)return a;var e=(a.contentWindow||a).document||a.ownerDocument||a;return d.browser.safari||e.compatMode=='BackCompat'?e.body:e.documentElement})};d.fn.scrollTo=function(n,j,b){if(typeof j=='object'){b=j;j=0}if(typeof b=='function')b={onAfter:b};if(n=='max')n=9e9;b=d.extend({},k.defaults,b);j=j||b.speed||b.duration;b.queue=b.queue&&b.axis.length>1;if(b.queue)j/=2;b.offset=p(b.offset);b.over=p(b.over);return this._scrollable().each(function(){var q=this,r=d(q),f=n,s,g={},u=r.is('html,body');switch(typeof f){case'number':case'string':if(/^([+-]=)?\d+(\.\d+)?(px|%)?$/.test(f)){f=p(f);break}f=d(f,this);case'object':if(f.is||f.style)s=(f=d(f)).offset()}d.each(b.axis.split(''),function(a,i){var e=i=='x'?'Left':'Top',h=e.toLowerCase(),c='scroll'+e,l=q[c],m=k.max(q,i);if(s){g[c]=s[h]+(u?0:l-r.offset()[h]);if(b.margin){g[c]-=parseInt(f.css('margin'+e))||0;g[c]-=parseInt(f.css('border'+e+'Width'))||0}g[c]+=b.offset[h]||0;if(b.over[h])g[c]+=f[i=='x'?'width':'height']()*b.over[h]}else{var o=f[h];g[c]=o.slice&&o.slice(-1)=='%'?parseFloat(o)/100*m:o}if(/^\d+$/.test(g[c]))g[c]=g[c]<=0?0:Math.min(g[c],m);if(!a&&b.queue){if(l!=g[c])t(b.onAfterFirst);delete g[c]}});t(b.onAfter);function t(a){r.animate(g,j,b.easing,a&&function(){a.call(this,n,b)})}}).end()};k.max=function(a,i){var e=i=='x'?'Width':'Height',h='scroll'+e;if(!d(a).is('html,body'))return a[h]-d(a)[e.toLowerCase()]();var c='client'+e,l=a.ownerDocument.documentElement,m=a.ownerDocument.body;return Math.max(l[h],m[h])-Math.min(l[c],m[c])};function p(a){return typeof a=='object'?a:{top:a,left:a}}})(jQuery);/**
* author Remy Sharp
* url http://remysharp.com/2009/01/26/element-in-view-event-plugin/
*/
(function ($) {
function getViewportHeight() {
var height = window.innerHeight; // Safari, Opera
var mode = document.compatMode;
if ( (mode || !$.support.boxModel) ) { // IE, Gecko
height = (mode == 'CSS1Compat') ?
document.documentElement.clientHeight : // Standards
document.body.clientHeight; // Quirks
}
return height;
}
$(window).scroll(function () {
var vpH = getViewportHeight(),
scrolltop = (document.documentElement.scrollTop ?
document.documentElement.scrollTop :
document.body.scrollTop),
elems = [];
// naughty, but this is how it knows which elements to check for
$.each($.cache, function () {
if (this.events && this.events.inview) {
elems.push(this.handle.elem);
}
});
if (elems.length) {
$(elems).each(function () {
var $el = $(this),
top = $el.offset().top,
height = $el.height(),
inview = $el.data('inview') || false;
if (scrolltop > (top + height) || scrolltop + vpH < top) {
if (inview) {
$el.data('inview', false);
$el.trigger('inview', [ false ]);
}
} else if (scrolltop < (top + height)) {
if (!inview) {
$el.data('inview', true);
$el.trigger('inview', [ true ]);
}
}
});
}
});
// kick the event to pick up any elements already in view.
// note however, this only works if the plugin is included after the elements are bound to 'inview'
$(function () {
$(window).scroll();
});
})(jQuery);
/*!
* jQuery UI 1.8
*
* Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT (MIT-LICENSE.txt)
* and GPL (GPL-LICENSE.txt) licenses.
*
* http://docs.jquery.com/UI
*/
;jQuery.ui || (function($) {
//Helper functions and ui object
$.ui = {
version: "1.8",
// $.ui.plugin is deprecated. Use the proxy pattern instead.
plugin: {
add: function(module, option, set) {
var proto = $.ui[module].prototype;
for(var i in set) {
proto.plugins[i] = proto.plugins[i] || [];
proto.plugins[i].push([option, set[i]]);
}
},
call: function(instance, name, args) {
var set = instance.plugins[name];
if(!set || !instance.element[0].parentNode) { return; }
for (var i = 0; i < set.length; i++) {
if (instance.options[set[i][0]]) {
set[i][1].apply(instance.element, args);
}
}
}
},
contains: function(a, b) {
return document.compareDocumentPosition
? a.compareDocumentPosition(b) & 16
: a !== b && a.contains(b);
},
hasScroll: function(el, a) {
//If overflow is hidden, the element might have extra content, but the user wants to hide it
if ($(el).css('overflow') == 'hidden') { return false; }
var scroll = (a && a == 'left') ? 'scrollLeft' : 'scrollTop',
has = false;
if (el[scroll] > 0) { return true; }
// TODO: determine which cases actually cause this to happen
// if the element doesn't have the scroll set, see if it's possible to
// set the scroll
el[scroll] = 1;
has = (el[scroll] > 0);
el[scroll] = 0;
return has;
},
isOverAxis: function(x, reference, size) {
//Determines when x coordinate is over "b" element axis
return (x > reference) && (x < (reference + size));
},
isOver: function(y, x, top, left, height, width) {
//Determines when x, y coordinates is over "b" element
return $.ui.isOverAxis(y, top, height) && $.ui.isOverAxis(x, left, width);
},
keyCode: {
BACKSPACE: 8,
CAPS_LOCK: 20,
COMMA: 188,
CONTROL: 17,
DELETE: 46,
DOWN: 40,
END: 35,
ENTER: 13,
ESCAPE: 27,
HOME: 36,
INSERT: 45,
LEFT: 37,
NUMPAD_ADD: 107,
NUMPAD_DECIMAL: 110,
NUMPAD_DIVIDE: 111,
NUMPAD_ENTER: 108,
NUMPAD_MULTIPLY: 106,
NUMPAD_SUBTRACT: 109,
PAGE_DOWN: 34,
PAGE_UP: 33,
PERIOD: 190,
RIGHT: 39,
SHIFT: 16,
SPACE: 32,
TAB: 9,
UP: 38
}
};
//jQuery plugins
$.fn.extend({
_focus: $.fn.focus,
focus: function(delay, fn) {
return typeof delay === 'number'
? this.each(function() {
var elem = this;
setTimeout(function() {
$(elem).focus();
(fn && fn.call(elem));
}, delay);
})
: this._focus.apply(this, arguments);
},
enableSelection: function() {
return this
.attr('unselectable', 'off')
.css('MozUserSelect', '')
.unbind('selectstart.ui');
},
disableSelection: function() {
return this
.attr('unselectable', 'on')
.css('MozUserSelect', 'none')
.bind('selectstart.ui', function() { return false; });
},
scrollParent: function() {
var scrollParent;
if(($.browser.msie && (/(static|relative)/).test(this.css('position'))) || (/absolute/).test(this.css('position'))) {
scrollParent = this.parents().filter(function() {
return (/(relative|absolute|fixed)/).test($.curCSS(this,'position',1)) && (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
}).eq(0);
} else {
scrollParent = this.parents().filter(function() {
return (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
}).eq(0);
}
return (/fixed/).test(this.css('position')) || !scrollParent.length ? $(document) : scrollParent;
},
zIndex: function(zIndex) {
if (zIndex !== undefined) {
return this.css('zIndex', zIndex);
}
if (this.length) {
var elem = $(this[0]), position, value;
while (elem.length && elem[0] !== document) {
// Ignore z-index if position is set to a value where z-index is ignored by the browser
// This makes behavior of this function consistent across browsers
// WebKit always returns auto if the element is positioned
position = elem.css('position');
if (position == 'absolute' || position == 'relative' || position == 'fixed')
{
// IE returns 0 when zIndex is not specified
// other browsers return a string
// we ignore the case of nested elements with an explicit value of 0
//
value = parseInt(elem.css('zIndex'));
if (!isNaN(value) && value != 0) {
return value;
}
}
elem = elem.parent();
}
}
return 0;
}
});
//Additional selectors
$.extend($.expr[':'], {
data: function(elem, i, match) {
return !!$.data(elem, match[3]);
},
focusable: function(element) {
var nodeName = element.nodeName.toLowerCase(),
tabIndex = $.attr(element, 'tabindex');
return (/input|select|textarea|button|object/.test(nodeName)
? !element.disabled
: 'a' == nodeName || 'area' == nodeName
? element.href || !isNaN(tabIndex)
: !isNaN(tabIndex))
// the element and all of its ancestors must be visible
// the browser may report that the area is hidden
&& !$(element)['area' == nodeName ? 'parents' : 'closest'](':hidden').length;
},
tabbable: function(element) {
var tabIndex = $.attr(element, 'tabindex');
return (isNaN(tabIndex) || tabIndex >= 0) && $(element).is(':focusable');
}
});
})(jQuery);
/*!
* jQuery UI Widget 1.8
*
* Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT (MIT-LICENSE.txt)
* and GPL (GPL-LICENSE.txt) licenses.
*
* http://docs.jquery.com/UI/Widget
*/
(function( $ ) {
var _remove = $.fn.remove;
$.fn.remove = function( selector, keepData ) {
return this.each(function() {
if ( !keepData ) {
if ( !selector || $.filter( selector, [ this ] ).length ) {
$( "*", this ).add( this ).each(function() {
$( this ).triggerHandler( "remove" );
});
}
}
return _remove.call( $(this), selector, keepData );
});
};
$.widget = function( name, base, prototype ) {
var namespace = name.split( "." )[ 0 ],
fullName;
name = name.split( "." )[ 1 ];
fullName = namespace + "-" + name;
if ( !prototype ) {
prototype = base;
base = $.Widget;
}
// create selector for plugin
$.expr[ ":" ][ fullName ] = function( elem ) {
return !!$.data( elem, name );
};
$[ namespace ] = $[ namespace ] || {};
$[ namespace ][ name ] = function( options, element ) {
// allow instantiation without initializing for simple inheritance
if ( arguments.length ) {
this._createWidget( options, element );
}
};
var basePrototype = new base();
// we need to make the options hash a property directly on the new instance
// otherwise we'll modify the options hash on the prototype that we're
// inheriting from
// $.each( basePrototype, function( key, val ) {
// if ( $.isPlainObject(val) ) {
// basePrototype[ key ] = $.extend( {}, val );
// }
// });
basePrototype.options = $.extend( {}, basePrototype.options );
$[ namespace ][ name ].prototype = $.extend( true, basePrototype, {
namespace: namespace,
widgetName: name,
widgetEventPrefix: $[ namespace ][ name ].prototype.widgetEventPrefix || name,
widgetBaseClass: fullName
}, prototype );
$.widget.bridge( name, $[ namespace ][ name ] );
};
$.widget.bridge = function( name, object ) {
$.fn[ name ] = function( options ) {
var isMethodCall = typeof options === "string",
args = Array.prototype.slice.call( arguments, 1 ),
returnValue = this;
// allow multiple hashes to be passed on init
options = !isMethodCall && args.length ?
$.extend.apply( null, [ true, options ].concat(args) ) :
options;
// prevent calls to internal methods
if ( isMethodCall && options.substring( 0, 1 ) === "_" ) {
return returnValue;
}
if ( isMethodCall ) {
this.each(function() {
var instance = $.data( this, name ),
methodValue = instance && $.isFunction( instance[options] ) ?
instance[ options ].apply( instance, args ) :
instance;
if ( methodValue !== instance && methodValue !== undefined ) {
returnValue = methodValue;
return false;
}
});
} else {
this.each(function() {
var instance = $.data( this, name );
if ( instance ) {
if ( options ) {
instance.option( options );
}
instance._init();
} else {
$.data( this, name, new object( options, this ) );
}
});
}
return returnValue;
};
};
$.Widget = function( options, element ) {
// allow instantiation without initializing for simple inheritance
if ( arguments.length ) {
this._createWidget( options, element );
}
};
$.Widget.prototype = {
widgetName: "widget",
widgetEventPrefix: "",
options: {
disabled: false
},
_createWidget: function( options, element ) {
// $.widget.bridge stores the plugin instance, but we do it anyway
// so that it's stored even before the _create function runs
this.element = $( element ).data( this.widgetName, this );
this.options = $.extend( true, {},
this.options,
$.metadata && $.metadata.get( element )[ this.widgetName ],
options );
var self = this;
this.element.bind( "remove." + this.widgetName, function() {
self.destroy();
});
this._create();
this._init();
},
_create: function() {},
_init: function() {},
destroy: function() {
this.element
.unbind( "." + this.widgetName )
.removeData( this.widgetName );
this.widget()
.unbind( "." + this.widgetName )
.removeAttr( "aria-disabled" )
.removeClass(
this.widgetBaseClass + "-disabled " +
this.namespace + "-state-disabled" );
},
widget: function() {
return this.element;
},
option: function( key, value ) {
var options = key,
self = this;
if ( arguments.length === 0 ) {
// don't return a reference to the internal hash
return $.extend( {}, self.options );
}
if (typeof key === "string" ) {
if ( value === undefined ) {
return this.options[ key ];
}
options = {};
options[ key ] = value;
}
$.each( options, function( key, value ) {
self._setOption( key, value );
});
return self;
},
_setOption: function( key, value ) {
this.options[ key ] = value;
if ( key === "disabled" ) {
this.widget()
[ value ? "addClass" : "removeClass"](
this.widgetBaseClass + "-disabled" + " " +
this.namespace + "-state-disabled" )
.attr( "aria-disabled", value );
}
return this;
},
enable: function() {
return this._setOption( "disabled", false );
},
disable: function() {
return this._setOption( "disabled", true );
},
_trigger: function( type, event, data ) {
var callback = this.options[ type ];
event = $.Event( event );
event.type = ( type === this.widgetEventPrefix ?
type :
this.widgetEventPrefix + type ).toLowerCase();
data = data || {};
// copy original event properties over to the new event
// this would happen if we could call $.event.fix instead of $.Event
// but we don't have a way to force an event to be fixed multiple times
if ( event.originalEvent ) {
for ( var i = $.event.props.length, prop; i; ) {
prop = $.event.props[ --i ];
event[ prop ] = event.originalEvent[ prop ];
}
}
this.element.trigger( event, data );
return !( $.isFunction(callback) &&
callback.call( this.element[0], event, data ) === false ||
event.isDefaultPrevented() );
}
};
})( jQuery );
(function ($) {
$.widget("ui.rcarousel", {
_create: function() {
var data,
$root = $( this.element ),
_self = this,
options = this.options;
// if options were default there should be no problem
// check if user set options before init: $('element').rcarousel({with: "foo", visible: 3});
// in above example exception will be thrown because 'with' should be a number!
this._checkOptionsValidity( this.options );
// for every carousel create a data object and keeps it in the element
this._createDataObject();
data = $root.data( "data" );
// create wrapper inside root element; this is needed for animating
$root
.addClass( "ui-carousel" )
.children()
.wrapAll( "" );
// save all children of root element in ‘paths’ array
this._saveElements();
// make pages using paginate algorithm
this._generatePages();
this._loadElements();
this._setCarouselWidth();
this._setCarouselHeight();
// handle default event handlers
$( options.navigation.next ).click(
function( event ) {
_self.next();
event.preventDefault();
}
);
$( options.navigation.prev ).click(
function( event ) {
_self.prev();
event.preventDefault();
}
);
data.navigation.next = $( options.navigation.next );
data.navigation.prev = $( options.navigation.prev );
// stop on hover feature
$root.hover(
function() {
if ( options.auto.enabled ) {
clearInterval( data.interval );
data.hoveredOver = true;
}
},
function() {
if ( options.auto.enabled ) {
data.hoveredOver = false;
_self._autoMode( options.auto.direction );
}
}
);
this._setStep();
// if auto mode is enabled run it
if ( options.auto.enabled ) {
this._autoMode( options.auto.direction );
}
// broadcast event
this._trigger( "start" );
},
_addElement: function( jQueryElement, direction ) {
var $root = $( this.element ),
$content = $root.find( "div.wrapper" ),
options = this.options;
jQueryElement
.width( options.width )
.height( options.height );
if ( options.orientation === "horizontal" ) {
$( jQueryElement ).css( "marginRight", options.margin );
} else {
$( jQueryElement ).css({
marginBottom: options.margin,
"float": "none"
});
}
if ( direction === "prev" ) {
// clone event handlers and data as well
$content.prepend( jQueryElement.clone(true, true) );
} else {
$content.append( jQueryElement.clone(true, true) );
}
},
append: function( jqElements ) {
var $root = $( this.element ),
data = $root.data( "data" );
// add new elements
jqElements.each(
function( i, el ) {
data.paths.push( $(el) );
}
);
data.oldPage = data.pages[data.oldPageIndex].slice(0);
data.appended = true;
// rebuild pages
this._generatePages();
},
_autoMode: function( direction ) {
var options = this.options,
data = $( this.element ).data( "data" );
if ( direction === "next" ) {
data.interval = setTimeout( $.proxy(this.next, this), options.auto.interval );
} else {
data.interval = setTimeout( $.proxy(this.prev, this), options.auto.interval );
}
},
_checkOptionsValidity: function( options ) {
var i,
self = this,
_correctSteps = "";
// for every element in options object check its validity
$.each(options,
function( key, value ) {
switch ( key ) {
case "visible":
// visible should be a positive integer
if ( !value || typeof value !== "number" || value <= 0 || (Math.ceil(value) - value > 0) ) {
throw new Error( "visible should be defined as a positive integer" );
}
break;
case "step":
if ( !value || typeof value !== "number" || value <= 0 || (Math.ceil(value) - value > 0) ) {
throw new Error( "step should be defined as a positive integer" );
} else if ( value > self.options.visible ) {
// for example for visible: 3 the following array of values for 'step' is valid
// 3 <= step >= 1 by 1 ==> [1,2,3]
// output correct values
for ( i = 1; i <= Math.floor(options.visible); i++ ) {
_correctSteps += ( i < Math.floor(value) ) ? i + ", " : i;
}
throw new Error( "Only following step values are correct: " + _correctSteps );
}
break;
case "width":
// width & height is defined by default so you can omit them to some extent
if ( !value || typeof value !== "number" || value <= 0 || Math.ceil(value) - value > 0 ) {
throw new Error( "width should be defined as a positive integer" );
}
break;
case "height":
if ( !value || typeof value !== "number" || value <= 0 || Math.ceil(value) - value > 0 ) {
throw new Error("height should be defined as a positive integer");
}
break;
case "speed":
if ( !value && value !== 0 ) {
throw new Error("speed should be defined as a number or a string");
}
if ( typeof value === "number" && value < 0 ) {
throw new Error( "speed should be a positive number" );
} else if ( typeof value === "string" && !(value === "slow" || value === "normal" || value === "fast") ) {
throw new Error( 'Only "slow", "normal" and "fast" values are valid' );
}
break;
case "navigation":
if ( !value || $.isPlainObject(value) === false ) {
throw new Error( "navigation should be defined as an object with at least one of the properties: 'prev' or 'next' in it");
}
if ( value.prev && typeof value.prev !== "string" ) {
throw new Error( "navigation.prev should be defined as a string and point to '.class' or '#id' of an element" );
}
if ( value.next && typeof value.next !== "string" ) {
throw new Error(" navigation.next should be defined as a string and point to '.class' or '#id' of an element" );
}
break;
case "auto":
if ( typeof value.direction !== "string" ) {
throw new Error( "direction should be defined as a string" );
}
if ( !(value.direction === "next" || value.direction === "prev") ) {
throw new Error( "direction: only 'right' and 'left' values are valid" );
}
if ( isNaN(value.interval) || typeof value.interval !== "number" || value.interval < 0 || Math.ceil(value.interval) - value.interval > 0 ) {
throw new Error( "interval should be a positive number" );
}
break;
case "margin":
if ( isNaN(value) || typeof value !== "number" || value < 0 || Math.ceil(value) - value > 0 ) {
throw new Error( "margin should be a positive number" );
}
break;
}
}
);
},
_createDataObject: function() {
var $root = $( this.element );
$root.data("data",
{
paths: [],
pathsLen: 0,
pages: [],
lastPage: [],
oldPageIndex: 0,
pageIndex: 0,
navigation: {},
animated: false,
appended: false,
hoveredOver: false
}
);
},
_generatePages: function() {
var self = this,
options = this.options,
data = $( this.element ).data( "data" ),
_visible = options.visible,
_pathsLen = data.paths.length;
// having 10 elements: A, B, C, D, E, F, G, H, I, J the algorithm
// creates 3 pages for ‘visible: 5’ and ‘step: 4’:
// [ABCDE], [EFGHI], [FGHIJ]
function _init() {
// init creates the last page [FGHIJ] and remembers it
data.pages = [];
data.lastPage = [];
data.pages[0] = [];
// init last page
for ( var i = _pathsLen - 1; i >= _pathsLen - _visible; i-- ) {
data.lastPage.unshift( data.paths[i] );
}
// and first page
for ( var i = 0; i < _visible; i++ ) {
data.pages[0][data.pages[0].length] = data.paths[i];
}
}
function _islastPage( page ) {
var _isLast = false;
for ( var i = 0; i < data.lastPage.length; i++ ) {
if ( data.lastPage[i].get(0) === page[i].get(0) ) {
_isLast = true;
} else {
_isLast = false;
break;
}
}
return _isLast;
}
function _append( start, end, atIndex ) {
var _index = atIndex || data.pages.length;
if ( !atIndex ) {
data.pages[_index] = [];
}
for ( var i = start; i < end; i++ ) {
data.pages[_index].push( data.paths[i] );
}
return _index;
}
function _paginate() {
var _isBeginning = true,
_complement = false,
_start = options.step,
_end, _index, _oldFirstEl, _oldLastEl;
// continue until you reach the last page
// we start from the 2nd page (1st page has been already initiated)
while ( !_islastPage(data.pages[data.pages.length - 1]) || _isBeginning ) {
_isBeginning = false;
_end = _start + _visible;
// we cannot exceed _pathsLen
if ( _end > _pathsLen ) {
_end = _pathsLen;
}
// when we run ouf of elements (_end - _start < _visible) we must add the difference at the begining
// in our example the 3rd page is [FGHIJ] and J element is added in the second step
// first we add [FGHI] as old elements
// we must assure that we have always ‘visible’ (5 in our example) elements
if ( _end - _start < _visible ) {
_complement = true;
} else {
_complement = false;
}
if ( _complement ) {
// first add old elemets; for 3rd page it adds [FGHI…]
// remember the page we add to (_index)
_oldFirstEl = _start - ( _visible - (_end - _start) );
_oldLastEl = _oldFirstEl + ( _visible - (_end - _start) );
_index = _append( _oldFirstEl, _oldLastEl );
// then add new elements; for 3th page it is J element:
// [fghiJ]
_append( _start, _end, _index );
} else {
// normal pages like [ABCDE], [EFGHI]
_append( _start, _end );
// next step
_start += options.step;
}
}
}
// go!
_init();
_paginate();
},
getCurrentPage: function() {
var data = $( this.element ).data( "data" );
return data.pageIndex + 1;
},
getTotalPages: function() {
var data = $( this.element ).data( "data" );
return data.pages.length;
},
goToPage: function( page ) {
var _by,
data = $( this.element ).data( "data" );
if ( !data.animated && page !== data.pageIndex ) {
data.animated = true;
if ( page > data.pages.length - 1 ) {
page = data.pages.length - 1;
} else if ( page < 0 ) {
page = 0;
}
data.pageIndex = page;
_by = page - data.oldPageIndex;
if ( _by >= 0 ) {
//move by n elements from current index
this._goToNextPage( _by );
} else {
this._goToPrevPage( _by );
}
data.oldPageIndex = page;
}
},
_loadElements: function(elements, direction) {
var options = this.options,
data = $( this.element ).data( "data" ),
_dir = direction || "next",
_elem = elements || data.pages[options.startAtPage],
_start = 0,
_end = _elem.length;
if ( _dir === "next" ) {
for ( var i = _start; i < _end; i++ ) {
this._addElement( _elem[i], _dir );
}
} else {
for ( var i = _end - 1; i >= _start; i-- ) {
this._addElement( _elem[i], _dir );
}
}
},
_goToPrevPage: function( by ) {
var _page, _oldPage, _dist, _index, _animOpts, $lastEl, _unique, _pos, _theSame,
$root = $( this.element ),
self = this,
options = this.options,
data = $( this.element ).data( "data" );
// pick pages
if ( data.appended ) {
_oldPage = data.oldPage;
} else {
_oldPage = data.pages[data.oldPageIndex];
}
_index = data.oldPageIndex + by;
_page = data.pages[_index].slice( 0 );
// For example, the first time widget was initiated there were 5
// elements: A, B, C, D, E and 3 pages for visible 2 and step 2:
// AB, CD, DE. Then a user loaded next 5 elements so there were
// 10 already: A, B, C, D, E, F, G, H, I, J and 5 pages:
// AB, CD, EF, GH and IJ. If the other elemets were loaded when
// CD page was shown (from 5 elements) ‘_theSame’ is true because
// we compare the same
// pages, that is, the 2nd page from 5 elements and the 2nd from
// 10 elements. Thus what we do next is to decrement the index and
// loads the first page from 10 elements.
$( _page ).each(
function( i, el ) {
if ( el.get(0) === $(_oldPage[i]).get(0) ) {
_theSame = true;
} else {
_theSame = false;
}
}
);
if ( data.appended && _theSame ) {
if ( data.pageIndex === 0 ) {
_index = data.pageIndex = data.pages.length - 1;
} else {
_index = --data.pageIndex;
}
_page = data.pages[_index].slice( 0 );
}
// check if last element from _page appears in _oldPage
// for [ABCDFGHIJ] elements there are 3 pages for ‘visible’ = 6 and
// ‘step’ = 2: [ABCDEF], [CDEFGH] and [EFGHIJ]; going from the 3rd
// to the 2nd page we only loads 2 elements: [CD] because all
// remaining were loaded already
$lastEl = _page[_page.length - 1].get( 0 );
for ( var i = _oldPage.length - 1; i >= 0; i-- ) {
if ( $lastEl === $(_oldPage[i]).get(0) ) {
_unique = false;
_pos = i;
break;
} else {
_unique = true;
}
}
if ( !_unique ) {
while ( _pos >= 0 ) {
if ( _page[_page.length - 1].get(0) === _oldPage[_pos].get(0) ) {
// this element is unique
_page.pop();
}
--_pos;
}
}
// load new elements
self._loadElements( _page, "prev" );
// calculate the distance
_dist = options.width * _page.length + ( options.margin * _page.length );
if (options.orientation === "horizontal") {
_animOpts = {scrollLeft: 0};
$root.scrollLeft( _dist );
} else {
_animOpts = {scrollTop: 0};
$root.scrollTop( _dist );
}
$root
.animate(_animOpts, options.speed, function () {
self._removeOldElements( "last", _page.length );
data.animated = false;
if ( !data.hoveredOver && options.auto.enabled ) {
// if autoMode is on and you change page manually
clearInterval( data.interval );
self._autoMode( options.auto.direction );
}
// scrolling is finished, send an event
self._trigger("pageLoaded", null, {page: _index});
});
// reset to deafult
data.appended = false;
},
_goToNextPage: function( by ) {
var _page, _oldPage, _dist, _index, _animOpts, $firstEl, _unique, _pos, _theSame,
$root = $( this.element ),
options = this.options,
data = $root.data( "data" ),
self = this;
// pick pages
if ( data.appended ) {
_oldPage = data.oldPage;
} else {
_oldPage = data.pages[data.oldPageIndex];
}
_index = data.oldPageIndex + by;
_page = data.pages[_index].slice( 0 );
// For example, the first time widget was initiated there were 5
// elements: A, B, C, D, E and 2 pages for visible 4 and step 3:
// ABCD and BCDE. Then a user loaded next 5 elements so there were
// 10 already: A, B, C, D, E, F, G, H, I, J and 3 pages:
// ABCD, DEFG and GHIJ. If the other elemets were loaded when
// ABCD page was shown (from 5 elements) ‘_theSame’ is true because
// we compare the same
// pages, that is, the first pages from 5 elements and the first from
// 10 elements. Thus what we do next is to increment the index and
// loads the second page from 10 elements.
$( _page ).each(
function( i, el ) {
if ( el.get(0) === $(_oldPage[i]).get(0) ) {
_theSame = true;
} else {
_theSame = false;
}
}
);
if ( data.appended && _theSame ) {
_page = data.pages[++data.pageIndex].slice( 0 );
}
// check if 1st element from _page appears in _oldPage
// for [ABCDFGHIJ] elements there are 3 pages for ‘visible’ = 6 and
// ‘step’ = 2: [ABCDEF], [CDEFGH] and [EFGHIJ]; going from the 2nd
// to the 3rd page we only loads 2 elements: [IJ] because all
// remaining were loaded already
$firstEl = _page[0].get( 0 );
for ( var i = 0; i < _page.length; i++) {
if ( $firstEl === $(_oldPage[i]).get(0) ) {
_unique = false;
_pos = i;
break;
} else {
_unique = true;
}
}
if ( !_unique ) {
while ( _pos < _oldPage.length ) {
if ( _page[0].get(0) === _oldPage[_pos].get(0) ) {
_page.shift();
}
++_pos;
}
}
// load new elements
this._loadElements( _page, "next" );
// calculate the distance
_dist = options.width * _page.length + ( options.margin * _page.length );
if ( options.orientation === "horizontal" ) {
_animOpts = {scrollLeft: "+=" + _dist};
} else {
_animOpts = {scrollTop: "+=" + _dist};
}
$root
.animate(_animOpts, options.speed, function() {
self._removeOldElements( "first", _page.length );
if ( options.orientation === "horizontal" ) {
$root.scrollLeft( 0 );
} else {
$root.scrollTop( 0 );
}
data.animated = false;
if ( !data.hoveredOver && options.auto.enabled ) {
// if autoMode is on and you change page manually
clearInterval( data.interval );
self._autoMode( options.auto.direction );
}
// scrolling is finished, send an event
self._trigger( "pageLoaded", null, {page: _index});
});
// reset to deafult
data.appended = false;
},
next: function() {
var options = this.options,
data = $( this.element ).data( "data" );
if ( !data.animated ) {
data.animated = true;
if ( !data.appended ) {
++data.pageIndex;
}
if ( data.pageIndex > data.pages.length - 1 ) {
data.pageIndex = 0;
}
// move by one element from current index
this._goToNextPage( data.pageIndex - data.oldPageIndex );
data.oldPageIndex = data.pageIndex;
}
},
prev: function() {
var options = this.options,
data = $( this.element ).data( "data" );
if ( !data.animated ) {
data.animated = true;
if ( !data.appended ) {
--data.pageIndex;
}
if ( data.pageIndex < 0 ) {
data.pageIndex = data.pages.length - 1;
}
// move left by one element from current index
this._goToPrevPage( data.pageIndex - data.oldPageIndex );
data.oldPageIndex = data.pageIndex;
}
},
_removeOldElements: function(position, length) {
// remove 'step' elements
var $root = $( this.element );
for ( var i = 0; i < length; i++ ) {
if ( position === "first" ) {
$root
.find( "div.wrapper" )
.children()
.first()
.remove();
} else {
$root
.find( "div.wrapper" )
.children()
.last()
.remove();
}
}
},
_saveElements: function() {
var $el,
$root = $( this.element ),
$elements = $root.find( "div.wrapper" ).children(),
data = $root.data( "data" );
$elements.each(
function( i, el ) {
$el = $( el );
// keep element’s data and events
data.paths.push( $el.clone(true, true) );
$el.remove();
}
);
},
_setOption: function( key, value ) {
var _newOptions,
options = this.options,
data = $( this.element ).data( "data" );
switch (key) {
case "speed":
this._checkOptionsValidity({speed: value});
options.speed = value;
$.Widget.prototype._setOption.apply( this, arguments );
break;
case "auto":
_newOptions = $.extend( options.auto, value );
this._checkOptionsValidity({auto: _newOptions});
if ( options.auto.enabled ) {
this._autoMode( options.auto.direction );
}
}
},
_setStep: function(s) {
// calculate a step
var _step,
options = this.options,
data = $( this.element ).data( "data" );
_step = s || options.step;
options.step = _step;
data.step = options.width * _step;
},
_setCarouselHeight: function() {
var _newHeight,
$root = $( this.element ),
data = $( this.element ).data( "data" ),
options = this.options;
if ( options.orientation === "vertical" ) {
_newHeight = options.visible * options.height + options.margin * (options.visible - 1) + options.border;
} else {
_newHeight = options.height + options.border;
}
$root.height(_newHeight);
},
_setCarouselWidth: function() {
var _newWidth,
$root = $( this.element ),
options = this.options,
data = $( this.element ).data( "data" );
if ( options.orientation === "horizontal" ) {
_newWidth = options.visible * options.width + options.margin * (options.visible - 1);
} else {
_newWidth = options.width;
}
// set carousel width and disable overflow: auto
$root.css({
width: _newWidth,
overflow: "hidden"
});
},
options: {
visible: 3,
step: 3,
width: 100,
height: 100,
speed: 1000,
margin: 0,
border:0,
orientation: "horizontal",
auto: {
enabled: false,
direction: "next",
interval: 5000
},
startAtPage: 0,
navigation: {
next: "#ui-carousel-next",
prev: "#ui-carousel-prev"
}
}
});
}(jQuery));