· 6 years ago · Jun 08, 2019, 11:32 AM
1///****************************** UTILITY JS ******************************///
2///****************************** UTILITY JS ******************************///
3///****************************** UTILITY JS ******************************///
4///****************************** UTILITY JS ******************************///
5
6
7// Utility function
8function Util () {};
9
10/*
11 class manipulation functions
12 */
13 Util.hasClass = function(el, className) {
14 if (el.classList) return el.classList.contains(className);
15 else return !!el.className.match(new RegExp('(\\s|^)' + className + '(\\s|$)'));
16 };
17
18 Util.addClass = function(el, className) {
19 var classList = className.split(' ');
20 if (el.classList) el.classList.add(classList[0]);
21 else if (!Util.hasClass(el, classList[0])) el.className += " " + classList[0];
22 if (classList.length > 1) Util.addClass(el, classList.slice(1).join(' '));
23 };
24
25 Util.removeClass = function(el, className) {
26 var classList = className.split(' ');
27 if (el.classList) el.classList.remove(classList[0]);
28 else if(Util.hasClass(el, classList[0])) {
29 var reg = new RegExp('(\\s|^)' + classList[0] + '(\\s|$)');
30 el.className=el.className.replace(reg, ' ');
31 }
32 if (classList.length > 1) Util.removeClass(el, classList.slice(1).join(' '));
33 };
34
35 Util.toggleClass = function(el, className, bool) {
36 if(bool) Util.addClass(el, className);
37 else Util.removeClass(el, className);
38 };
39
40 Util.setAttributes = function(el, attrs) {
41 for(var key in attrs) {
42 el.setAttribute(key, attrs[key]);
43 }
44 };
45
46/*
47 DOM manipulation
48 */
49 Util.getChildrenByClassName = function(el, className) {
50 var children = el.children,
51 childrenByClass = [];
52 for (var i = 0; i < el.children.length; i++) {
53 if (Util.hasClass(el.children[i], className)) childrenByClass.push(el.children[i]);
54 }
55 return childrenByClass;
56 };
57
58 Util.is = function(elem, selector) {
59 if(selector.nodeType){
60 return elem === selector;
61 }
62
63 var qa = (typeof(selector) === 'string' ? document.querySelectorAll(selector) : selector),
64 length = qa.length,
65 returnArr = [];
66
67 while(length--){
68 if(qa[length] === elem){
69 return true;
70 }
71 }
72
73 return false;
74 };
75
76/*
77 Animate height of an element
78 */
79 Util.setHeight = function(start, to, element, duration, cb) {
80 var change = to - start,
81 currentTime = null;
82
83 var animateHeight = function(timestamp){
84 if (!currentTime) currentTime = timestamp;
85 var progress = timestamp - currentTime;
86 var val = parseInt((progress/duration)*change + start);
87 element.style.height = val+"px";
88 if(progress < duration) {
89 window.requestAnimationFrame(animateHeight);
90 } else {
91 cb();
92 }
93 };
94
95 //set the height of the element before starting animation -> fix bug on Safari
96 element.style.height = start+"px";
97 window.requestAnimationFrame(animateHeight);
98};
99
100/*
101 Smooth Scroll
102 */
103
104 Util.scrollTo = function(final, duration, cb) {
105 var start = window.scrollY || document.documentElement.scrollTop,
106 currentTime = null;
107
108 var animateScroll = function(timestamp){
109 if (!currentTime) currentTime = timestamp;
110 var progress = timestamp - currentTime;
111 if(progress > duration) progress = duration;
112 var val = Math.easeInOutQuad(progress, start, final-start, duration);
113 window.scrollTo(0, val);
114 if(progress < duration) {
115 window.requestAnimationFrame(animateScroll);
116 } else {
117 cb && cb();
118 }
119 };
120
121 window.requestAnimationFrame(animateScroll);
122 };
123
124/*
125 Focus utility classes
126 */
127
128//Move focus to an element
129Util.moveFocus = function (element) {
130 if( !element ) element = document.getElementsByTagName("body")[0];
131 element.focus();
132 if (document.activeElement !== element) {
133 element.setAttribute('tabindex','-1');
134 element.focus();
135 }
136};
137
138/*
139 Misc
140 */
141
142 Util.getIndexInArray = function(array, el) {
143 return Array.prototype.indexOf.call(array, el);
144 };
145
146 Util.cssSupports = function(property, value) {
147 if('CSS' in window) {
148 return CSS.supports(property, value);
149 } else {
150 var jsProperty = property.replace(/-([a-z])/g, function (g) { return g[1].toUpperCase();});
151 return jsProperty in document.body.style;
152 }
153 };
154
155// merge a set of user options into plugin defaults
156// https://gomakethings.com/vanilla-javascript-version-of-jquery-extend/
157Util.extend = function() {
158 // Variables
159 var extended = {};
160 var deep = false;
161 var i = 0;
162 var length = arguments.length;
163
164 // Check if a deep merge
165 if ( Object.prototype.toString.call( arguments[0] ) === '[object Boolean]' ) {
166 deep = arguments[0];
167 i++;
168 }
169
170 // Merge the object into the extended object
171 var merge = function (obj) {
172 for ( var prop in obj ) {
173 if ( Object.prototype.hasOwnProperty.call( obj, prop ) ) {
174 // If deep merge and property is an object, merge properties
175 if ( deep && Object.prototype.toString.call(obj[prop]) === '[object Object]' ) {
176 extended[prop] = extend( true, extended[prop], obj[prop] );
177 } else {
178 extended[prop] = obj[prop];
179 }
180 }
181}
182};
183
184 // Loop through each object and conduct a merge
185 for ( ; i < length; i++ ) {
186 var obj = arguments[i];
187 merge(obj);
188 }
189
190 return extended;
191};
192
193/*
194 Polyfills
195 */
196//Closest() method
197if (!Element.prototype.matches) {
198 Element.prototype.matches = Element.prototype.msMatchesSelector || Element.prototype.webkitMatchesSelector;
199}
200
201if (!Element.prototype.closest) {
202 Element.prototype.closest = function(s) {
203 var el = this;
204 if (!document.documentElement.contains(el)) return null;
205 do {
206 if (el.matches(s)) return el;
207 el = el.parentElement || el.parentNode;
208 } while (el !== null && el.nodeType === 1);
209 return null;
210 };
211}
212
213//Custom Event() constructor
214if ( typeof window.CustomEvent !== "function" ) {
215
216 function CustomEvent ( event, params ) {
217 params = params || { bubbles: false, cancelable: false, detail: undefined };
218 var evt = document.createEvent( 'CustomEvent' );
219 evt.initCustomEvent( event, params.bubbles, params.cancelable, params.detail );
220 return evt;
221 }
222
223 CustomEvent.prototype = window.Event.prototype;
224
225 window.CustomEvent = CustomEvent;
226}
227
228/*
229 Animation curves
230 */
231 Math.easeInOutQuad = function (t, b, c, d) {
232 t /= d/2;
233 if (t < 1) return c/2*t*t + b;
234 t--;
235 return -c/2 * (t*(t-2) - 1) + b;
236 };
237
238
239
240
241 (function() {
242 var backTop = document.getElementsByClassName('js-cd-top')[0],
243 // browser window scroll (in pixels) after which the "back to top" link is shown
244 offset = 300,
245 //browser window scroll (in pixels) after which the "back to top" link opacity is reduced
246 offsetOpacity = 1200,
247 scrollDuration = 700
248 scrolling = false;
249 if (backTop) {
250 //update back to top visibility on scrolling
251 window.addEventListener("scroll", function(event) {
252 if (!scrolling) {
253 scrolling = true;
254 (!window.requestAnimationFrame) ? setTimeout(checkBackToTop, 250): window
255 .requestAnimationFrame(checkBackToTop);
256 }
257 });
258 //smooth scroll to top
259 backTop.addEventListener('click', function(event) {
260 event.preventDefault();
261 (!window.requestAnimationFrame) ? window.scrollTo(0, 0): scrollTop(scrollDuration);
262 });
263 }
264
265 function checkBackToTop() {
266 var windowTop = window.scrollY || document.documentElement.scrollTop;
267 (windowTop > offset) ? addClass(backTop, 'cd-top--show'): removeClass(backTop, 'cd-top--show',
268 'cd-top--fade-out');
269 (windowTop > offsetOpacity) && addClass(backTop, 'cd-top--fade-out');
270 scrolling = false;
271 }
272
273 function scrollTop(duration) {
274 var start = window.scrollY || document.documentElement.scrollTop,
275 currentTime = null;
276 var animateScroll = function(timestamp) {
277 if (!currentTime) currentTime = timestamp;
278 var progress = timestamp - currentTime;
279 var val = Math.max(Math.easeInOutQuad(progress, start, -start, duration), 0);
280 window.scrollTo(0, val);
281 if (progress < duration) {
282 window.requestAnimationFrame(animateScroll);
283 }
284 };
285 window.requestAnimationFrame(animateScroll);
286 }
287 Math.easeInOutQuad = function(t, b, c, d) {
288 t /= d / 2;
289 if (t < 1) return c / 2 * t * t + b;
290 t--;
291 return -c / 2 * (t * (t - 2) - 1) + b;
292 };
293 //class manipulations - needed if classList is not supported
294 function hasClass(el, className) {
295 if (el.classList) return el.classList.contains(className);
296 else return !!el.className.match(new RegExp('(\\s|^)' + className + '(\\s|$)'));
297 }
298
299 function addClass(el, className) {
300 var classList = className.split(' ');
301 if (el.classList) el.classList.add(classList[0]);
302 else if (!hasClass(el, classList[0])) el.className += " " + classList[0];
303 if (classList.length > 1) addClass(el, classList.slice(1).join(' '));
304 }
305
306 function removeClass(el, className) {
307 var classList = className.split(' ');
308 if (el.classList) el.classList.remove(classList[0]);
309 else if (hasClass(el, classList[0])) {
310 var reg = new RegExp('(\\s|^)' + classList[0] + '(\\s|$)');
311 el.className = el.className.replace(reg, ' ');
312 }
313 if (classList.length > 1) removeClass(el, classList.slice(1).join(' '));
314 }
315})();
316(function() {
317 var Accordion = function(element) {
318 this.element = element;
319 this.items = Util.getChildrenByClassName(this.element, 'js-accordion__item');
320 this.showClass = 'accordion__item--is-open';
321 this.animateHeight = (this.element.getAttribute('data-animation') == 'on');
322 this.multiItems = !(this.element.getAttribute('data-multi-items') == 'off');
323 this.initAccordion();
324 };
325
326 Accordion.prototype.initAccordion = function() {
327 //set initial aria attributes
328 for( var i = 0; i < this.items.length; i++) {
329 var button = this.items[i].getElementsByTagName('button')[0],
330 content = this.items[i].getElementsByClassName('js-accordion__panel')[0],
331 isOpen = Util.hasClass(this.items[i], this.showClass) ? 'true' : 'false';
332 Util.setAttributes(button, {'aria-expanded': isOpen, 'aria-controls': 'accordion-content-'+i, 'id': 'accordion-header-'+i});
333 Util.addClass(button, 'js-accordion__trigger');
334 Util.setAttributes(content, {'aria-labelledby': 'accordion-header-'+i, 'id': 'accordion-content-'+i});
335 }
336
337 //listen for Accordion events
338 this.initAccordionEvents();
339 };
340
341 Accordion.prototype.initAccordionEvents = function() {
342 var self = this;
343
344 this.element.addEventListener('click', function(event) {
345 var trigger = event.target.closest('.js-accordion__trigger');
346 //check index to make sure the click didn't happen inside a children accordion
347 if( trigger && Util.getIndexInArray(self.items, trigger.parentElement) >= 0) self.triggerAccordion(trigger);
348 });
349 };
350
351 Accordion.prototype.triggerAccordion = function(trigger) {
352 var self = this;
353 var bool = (trigger.getAttribute('aria-expanded') === 'true');
354
355 this.animateAccordion(trigger, bool);
356 };
357
358 Accordion.prototype.animateAccordion = function(trigger, bool) {
359 var self = this;
360 var item = trigger.closest('.js-accordion__item'),
361 content = item.getElementsByClassName('js-accordion__panel')[0],
362 ariaValue = bool ? 'false' : 'true';
363
364 if(!bool) Util.addClass(item, this.showClass);
365 trigger.setAttribute('aria-expanded', ariaValue);
366
367 if(this.animateHeight) {
368 //store initial and final height - animate accordion content height
369 var initHeight = bool ? content.offsetHeight: 0,
370 finalHeight = bool ? 0 : content.offsetHeight;
371 }
372
373 if(window.requestAnimationFrame && this.animateHeight) {
374 Util.setHeight(initHeight, finalHeight, content, 200, function(){
375 self.resetContentVisibility(item, content, bool);
376 });
377 } else {
378 self.resetContentVisibility(item, content, bool);
379 }
380
381 if( !this.multiItems && !bool) this.closeSiblings(item);
382
383 };
384
385 Accordion.prototype.resetContentVisibility = function(item, content, bool) {
386 Util.toggleClass(item, this.showClass, !bool);
387 content.removeAttribute("style");
388 };
389
390 Accordion.prototype.closeSiblings = function(item) {
391 //if only one accordion can be open -> search if there's another one open
392 var index = Util.getIndexInArray(this.items, item);
393 for( var i = 0; i < this.items.length; i++) {
394 if(Util.hasClass(this.items[i], this.showClass) && i != index) {
395 this.animateAccordion(this.items[i].getElementsByClassName('js-accordion__trigger')[0], true);
396 return false;
397 }
398 }
399 };
400
401 //initialize the Accordion objects
402 var accordions = document.getElementsByClassName('js-accordion');
403 if( accordions.length > 0 ) {
404 for( var i = 0; i < accordions.length; i++) {
405 (function(i){new Accordion(accordions[i]);})(i);
406 }
407 }
408}());
409jQuery(document).ready(function($){
410 var mainHeader = $('.fixed_header'),
411 secondaryNavigation = $('.cd-secondary-nav'),
412 //this applies only if secondary nav is below intro section
413 belowNavHeroContent = $('.sub-nav-hero'),
414 headerHeight = mainHeader.height();
415
416 //set scrolling variables
417 var scrolling = false,
418 previousTop = 0,
419 currentTop = 0,
420 scrollDelta = 10,
421 scrollOffset = 150;
422
423 mainHeader.on('click', '.nav-trigger', function(event){
424 // open primary navigation on mobile
425 event.preventDefault();
426 mainHeader.toggleClass('nav-open');
427 });
428
429 $(window).on('scroll', function(){
430 if( !scrolling ) {
431 scrolling = true;
432 (!window.requestAnimationFrame)
433 ? setTimeout(autoHideHeader, 250)
434 : requestAnimationFrame(autoHideHeader);
435 }
436 });
437
438 $(window).on('resize', function(){
439 headerHeight = mainHeader.height();
440 });
441
442 function autoHideHeader() {
443 var currentTop = $(window).scrollTop();
444
445 ( belowNavHeroContent.length > 0 )
446 ? checkStickyNavigation(currentTop) // secondary navigation below intro
447 : checkSimpleNavigation(currentTop);
448
449 previousTop = currentTop;
450 scrolling = false;
451 }
452
453 function checkSimpleNavigation(currentTop) {
454 //there's no secondary nav or secondary nav is below primary nav
455 if (previousTop - currentTop > scrollDelta) {
456 //if scrolling up...
457 mainHeader.removeClass('is-hidden');
458 } else if( currentTop - previousTop > scrollDelta && currentTop > scrollOffset) {
459 //if scrolling down...
460 mainHeader.addClass('is-hidden');
461
462 }
463 }
464
465 function checkStickyNavigation(currentTop) {
466 //secondary nav below intro section - sticky secondary nav
467 var secondaryNavOffsetTop = belowNavHeroContent.offset().top - secondaryNavigation.height() - mainHeader.height();
468
469 if (previousTop >= currentTop ) {
470 //if scrolling up...
471 if( currentTop < secondaryNavOffsetTop ) {
472 //secondary nav is not fixed
473 mainHeader.removeClass('is-hidden');
474 secondaryNavigation.removeClass('fixed slide-up');
475 belowNavHeroContent.removeClass('secondary-nav-fixed');
476 } else if( previousTop - currentTop > scrollDelta ) {
477 //secondary nav is fixed
478 mainHeader.removeClass('is-hidden');
479 secondaryNavigation.removeClass('slide-up').addClass('fixed');
480 belowNavHeroContent.addClass('secondary-nav-fixed');
481 }
482
483 } else {
484 //if scrolling down...
485 if( currentTop > secondaryNavOffsetTop + scrollOffset ) {
486 //hide primary nav
487 mainHeader.addClass('is-hidden');
488 secondaryNavigation.addClass('fixed slide-up');
489 belowNavHeroContent.addClass('secondary-nav-fixed');
490 } else if( currentTop > secondaryNavOffsetTop ) {
491 //once the secondary nav is fixed, do not hide primary nav if you haven't scrolled more than scrollOffset
492 mainHeader.removeClass('is-hidden');
493 secondaryNavigation.addClass('fixed').removeClass('slide-up');
494 belowNavHeroContent.addClass('secondary-nav-fixed');
495 }
496
497 }
498 }
499});
500usernoise = {};
501jQuery(function($){
502 function FeedbackForm($form){
503 var self = this;
504 self.form = $form;
505 $form.find('.text').unAutoPlaceholder();
506 $form.find('.un-types-wrapper a').click(selectTypeHandler);
507 $form.submit(submitHandler);
508
509 function selectTypeHandler(){
510 var $selector = $(this).parent();
511 $selector.find('a').removeClass('selected');
512 $(this).addClass('selected');
513 var type = $(this).attr('class').replace(/\s*selected\s*/, '').replace('un-type-', '');
514 $selector.find('input[type=hidden]').val(type);
515 $(document).trigger('typeselected#feedbackform#window.un', type);
516 return false;
517 }
518
519 function submitHandler(){
520 var data = $form.unSerializeObject();
521 data.referer = window.parent.document.location.href;
522 $(document).trigger('submitting#feedbackform#window.un', data);
523 self.lock();
524 $form.find('.loader').show();
525 self.errors.hide();
526 $.post($form.attr('action'), data , function(response){
527 $form.find('.loader').hide();
528 self.unlock();
529 response = usernoise.helpers.parseJSON(response);
530 if (response.success){
531 $(document).trigger('sent#feedbackform#window.un');
532 } else {
533 self.errors.show(response.errors);
534 }
535 });
536 return false;
537 }
538
539 $.extend(self, {
540 unlock: function(){
541 $(document).trigger('unlocking#feedbackform#window.un');
542 $form.find('input, select, textarea').removeAttr('disabled');
543 $form.find('.un-types-wrapper a').click(selectTypeHandler);
544 },
545 lock: function(){
546 $form.find('*').unbind('click');
547 $(document).trigger('locking#feedbackform#window.un');
548 $form.find('input, select, textarea').attr('disabled', 'disabled');
549 },
550 errors: new Errors($form.find('.un-feedback-errors-wrapper')),
551 selectedType: function(){
552 var type = $('#types-wrapper a.selected').attr('id');
553 return type ? type.replace('un-type-', '') : null;
554 }
555 });
556 $(document).trigger('created#feedbackform#window.un', self);
557 }
558
559 usernoise.FeedbackForm = FeedbackForm;
560
561 function Errors($errorsWrapper){
562 var self = this;
563 var $errors = $errorsWrapper.find('.un-errors');
564 $.extend(self, {
565 show: function(errors){
566 $('#window').addClass('transitionEnabled');
567 $(errors).each(function(index, error){
568 $errors.append($("<p />").text(error));
569 });
570 $errorsWrapper.fadeIn('fast');
571 },
572 hide: function(errors){
573 $errors.html('');
574 $errorsWrapper.fadeOut('fast', function(){
575 $errorsWrapper.hide();
576 });
577 }
578 });
579 }
580 usernoise.Errors = Errors;
581
582 function ThankYouScreen(){
583 var self = this;
584 var $screen = $screen;
585 $.extend(self, {
586 show: function(){
587 $('#un-thankyou').show();
588 $('#un-feedback-close').click(function(){
589 usernoise.window.hide();
590 return false;
591 });
592 }
593 });
594 }
595 usernoise.ThankYouScreen = ThankYouScreen;
596
597 function UsernoiseWindow(windowSelector){
598 var self = this;
599 var $window = $('#window');
600
601
602 function detectBrowser(){
603 if (!$('#wrapper').hasClass('un')) return;
604 $('#wrapper').addClass('un');
605 if ($.browser.msie && $.browser.version == '7.0')
606 $('#wrapper').addClass('un-ie7');
607 if ($.browser.msie && $.browser.version == '8.0')
608 $('#wrapper').addClass('un-ie8');
609 }
610
611 function showThankYouHandler(event, html){
612 self.thankYouScreen = new ThankYouScreen($window.find('.thank-you-screen'));
613 self.thankYouScreen.show(html);
614 }
615 detectBrowser();
616 $.extend(self, {
617 hide: function(){
618 $('#un-overlay').remove();
619 $('#un-frame').remove();
620 $('#un-loading').remove();
621 },
622 adjustSize: function(){
623 $window.css({
624 'margin-top': '-' + $window.height() / 2 + "px",
625 'margin-left': '-' + $window.width() / 2 + "px"});
626 }
627 });
628 self.adjustSize();
629 }
630
631 $.fn.unAutoPlaceholder = function(){
632 $(this).each(function(){
633 $(this).attr('data-default', $(this).val());
634 $(this).focus(function(){
635 if ($(this).val() == $(this).attr('data-default')){
636 $(this).val('');
637 $(this).addClass('text-normal');
638 $(this).removeClass('text-empty');
639 }
640 });
641 $(this).blur(function(){
642 if ($(this).val() == ''){
643 $(this).val($(this).attr('data-default'));
644 $(this).removeClass('text-normal');
645 $(this).addClass('text-empty');
646
647 }
648 });
649 });
650 };
651
652 $.fn.unSerializeObject = function(){
653 var o = {};
654 var a = this.serializeArray();
655 $.each(a, function() {
656 if (o[this.name]) {
657 if (!o[this.name].push) {
658 o[this.name] = [o[this.name]];
659 }
660 o[this.name].push(this.value || '');
661 } else {
662 o[this.name] = this.value || '';
663 }
664 });
665 return o;
666 };
667
668 usernoise.helpers = {
669 parseJSON: function(json){
670 return $.parseJSON ? $.parseJSON(json) : eval("(" + json + ")");
671 }
672 };
673
674 usernoise.Window = UsernoiseWindow;
675});
676jQuery(function($){
677 usernoise.window = new usernoise.Window();
678 usernoise.feedbackForm = new usernoise.FeedbackForm($('.un-feedback-form'));
679 usernoise.thankYouScreen = new usernoise.ThankYouScreen();
680 $('#window').resize(function(){
681 $('#window').css({
682 'margin-top': '-' + $('#window').height() / 2 + "px",
683 'margin-left': '-' + $('#window').width() / 2 + "px"});
684 });
685 $('#window-close').click(function(){
686 usernoise.window.hide();
687 return false;
688 });
689 $(document).bind('sent#feedbackform#window.un', function(){
690 $('#un-feedback-form-wrapper').fadeOut('fast', function(){
691 usernoise.thankYouScreen.show();
692 });
693 });
694 $(document).click(function(event){
695 if (event.target.parentNode == document)
696 usernoise.window.hide();
697 });
698});
699/*!
700 * jQuery Raty - A Star Rating Plugin
701 * ------------------------------------------------------------------
702 *
703 * jQuery Raty is a plugin that generates a customizable star rating.
704 *
705 * Licensed under The MIT License
706 *
707 * @version 2.5.2
708 * @since 2010.06.11
709 * @author Washington Botelho
710 * @documentation wbotelhos.com/raty
711 *
712 * ------------------------------------------------------------------
713 *
714 * <div id="star"></div>
715 *
716 * $('#star').raty();
717 *
718 */
719
720 ;(function($) {
721
722 var methods = {
723 init: function(settings) {
724 return this.each(function() {
725 methods.destroy.call(this);
726
727 this.opt = $.extend(true, {}, $.fn.raty.defaults, settings);
728
729 var that = $(this),
730 inits = ['number', 'readOnly', 'score', 'scoreName'];
731
732 methods._callback.call(this, inits);
733
734 if (this.opt.precision) {
735 methods._adjustPrecision.call(this);
736 }
737
738 this.opt.number = methods._between(this.opt.number, 0, this.opt.numberMax)
739
740 this.opt.path = this.opt.path || '';
741
742 if (this.opt.path && this.opt.path.slice(this.opt.path.length - 1, this.opt.path.length) !== '/') {
743 this.opt.path += '/';
744 }
745
746 this.stars = methods._createStars.call(this);
747 this.score = methods._createScore.call(this);
748
749 methods._apply.call(this, this.opt.score);
750
751 var space = this.opt.space ? 4 : 0,
752 width = this.opt.width || (this.opt.number * this.opt.size + this.opt.number * space);
753
754 if (this.opt.cancel) {
755 this.cancel = methods._createCancel.call(this);
756
757 width += (this.opt.size + space);
758 }
759
760 if (this.opt.readOnly) {
761 methods._lock.call(this);
762 } else {
763 that.css('cursor', 'pointer');
764 methods._binds.call(this);
765 }
766
767 if (this.opt.width !== false) {
768 that.css('width', width);
769 }
770
771 methods._target.call(this, this.opt.score);
772
773 that.data({ 'settings': this.opt, 'raty': true });
774 });
775 }, _adjustPrecision: function() {
776 this.opt.targetType = 'score';
777 this.opt.half = true;
778 }, _apply: function(score) {
779 if (score && score > 0) {
780 score = methods._between(score, 0, this.opt.number);
781 this.score.val(score);
782 }
783
784 methods._fill.call(this, score);
785
786 if (score) {
787 methods._roundStars.call(this, score);
788 }
789 }, _between: function(value, min, max) {
790 return Math.min(Math.max(parseFloat(value), min), max);
791 }, _binds: function() {
792 if (this.cancel) {
793 methods._bindCancel.call(this);
794 }
795
796 methods._bindClick.call(this);
797 methods._bindOut.call(this);
798 methods._bindOver.call(this);
799 }, _bindCancel: function() {
800 methods._bindClickCancel.call(this);
801 methods._bindOutCancel.call(this);
802 methods._bindOverCancel.call(this);
803 }, _bindClick: function() {
804 var self = this,
805 that = $(self);
806
807 self.stars.on('click.raty', function(evt) {
808 self.score.val((self.opt.half || self.opt.precision) ? that.data('score') : this.alt);
809
810 if (self.opt.click) {
811 self.opt.click.call(self, parseFloat(self.score.val()), evt);
812 }
813 });
814 }, _bindClickCancel: function() {
815 var self = this;
816
817 self.cancel.on('click.raty', function(evt) {
818 self.score.removeAttr('value');
819
820 if (self.opt.click) {
821 self.opt.click.call(self, null, evt);
822 }
823 });
824 }, _bindOut: function() {
825 var self = this;
826
827 $(this).on('mouseleave.raty', function(evt) {
828 var score = parseFloat(self.score.val()) || undefined;
829
830 methods._apply.call(self, score);
831 methods._target.call(self, score, evt);
832
833 if (self.opt.mouseout) {
834 self.opt.mouseout.call(self, score, evt);
835 }
836 });
837 }, _bindOutCancel: function() {
838 var self = this;
839
840 self.cancel.on('mouseleave.raty', function(evt) {
841 $(this).attr('src', self.opt.path + self.opt.cancelOff);
842
843 if (self.opt.mouseout) {
844 self.opt.mouseout.call(self, self.score.val() || null, evt);
845 }
846 });
847 }, _bindOverCancel: function() {
848 var self = this;
849
850 self.cancel.on('mouseover.raty', function(evt) {
851 $(this).attr('src', self.opt.path + self.opt.cancelOn);
852
853 self.stars.attr('src', self.opt.path + self.opt.starOff);
854
855 methods._target.call(self, null, evt);
856
857 if (self.opt.mouseover) {
858 self.opt.mouseover.call(self, null);
859 }
860 });
861 }, _bindOver: function() {
862 var self = this,
863 that = $(self),
864 action = self.opt.half ? 'mousemove.raty' : 'mouseover.raty';
865
866 self.stars.on(action, function(evt) {
867 var score = parseInt(this.alt, 10);
868
869 if (self.opt.half) {
870 var position = parseFloat((evt.pageX - $(this).offset().left) / self.opt.size),
871 plus = (position > .5) ? 1 : .5;
872
873 score = score - 1 + plus;
874
875 methods._fill.call(self, score);
876
877 if (self.opt.precision) {
878 score = score - plus + position;
879 }
880
881 methods._roundStars.call(self, score);
882
883 that.data('score', score);
884 } else {
885 methods._fill.call(self, score);
886 }
887
888 methods._target.call(self, score, evt);
889
890 if (self.opt.mouseover) {
891 self.opt.mouseover.call(self, score, evt);
892 }
893 });
894 }, _callback: function(options) {
895 for (i in options) {
896 if (typeof this.opt[options[i]] === 'function') {
897 this.opt[options[i]] = this.opt[options[i]].call(this);
898 }
899 }
900 }, _createCancel: function() {
901 var that = $(this),
902 icon = this.opt.path + this.opt.cancelOff,
903 cancel = $('<img />', { src: icon, alt: 'x', title: this.opt.cancelHint, 'class': 'raty-cancel' });
904
905 if (this.opt.cancelPlace == 'left') {
906 that.prepend(' ').prepend(cancel);
907 } else {
908 that.append(' ').append(cancel);
909 }
910
911 return cancel;
912 }, _createScore: function() {
913 return $('<input />', { type: 'hidden', name: this.opt.scoreName }).appendTo(this);
914 }, _createStars: function() {
915 var that = $(this);
916
917 for (var i = 1; i <= this.opt.number; i++) {
918 var title = methods._getHint.call(this, i),
919 icon = (this.opt.score && this.opt.score >= i) ? 'starOn' : 'starOff';
920
921 icon = this.opt.path + this.opt[icon];
922
923 $('<img />', { src : icon, alt: i, title: title }).appendTo(this);
924
925 if (this.opt.space) {
926 that.append((i < this.opt.number) ? ' ' : '');
927 }
928 }
929
930 return that.children('img');
931 }, _error: function(message) {
932 $(this).html(message);
933
934 $.error(message);
935 }, _fill: function(score) {
936 var self = this,
937 hash = 0;
938
939 for (var i = 1; i <= self.stars.length; i++) {
940 var star = self.stars.eq(i - 1),
941 select = self.opt.single ? (i == score) : (i <= score);
942
943 if (self.opt.iconRange && self.opt.iconRange.length > hash) {
944 var irange = self.opt.iconRange[hash],
945 on = irange.on || self.opt.starOn,
946 off = irange.off || self.opt.starOff,
947 icon = select ? on : off;
948
949 if (i <= irange.range) {
950 star.attr('src', self.opt.path + icon);
951 }
952
953 if (i == irange.range) {
954 hash++;
955 }
956 } else {
957 var icon = select ? 'starOn' : 'starOff';
958
959 star.attr('src', this.opt.path + this.opt[icon]);
960 }
961 }
962 }, _getHint: function(score) {
963 var hint = this.opt.hints[score - 1];
964 return (hint === '') ? '' : (hint || score);
965 }, _lock: function() {
966 var score = parseInt(this.score.val(), 10), // TODO: 3.1 >> [['1'], ['2'], ['3', '.1', '.2']]
967 hint = score ? methods._getHint.call(this, score) : this.opt.noRatedMsg;
968
969 $(this).data('readonly', true).css('cursor', '').attr('title', hint);
970
971 this.score.attr('readonly', 'readonly');
972 this.stars.attr('title', hint);
973
974 if (this.cancel) {
975 this.cancel.hide();
976 }
977 }, _roundStars: function(score) {
978 var rest = (score - Math.floor(score)).toFixed(2);
979
980 if (rest > this.opt.round.down) {
981 var icon = 'starOn'; // Up: [x.76 .. x.99]
982
983 if (this.opt.halfShow && rest < this.opt.round.up) { // Half: [x.26 .. x.75]
984 icon = 'starHalf';
985 } else if (rest < this.opt.round.full) { // Down: [x.00 .. x.5]
986 icon = 'starOff';
987 }
988
989 this.stars.eq(Math.ceil(score) - 1).attr('src', this.opt.path + this.opt[icon]);
990 } // Full down: [x.00 .. x.25]
991 }, _target: function(score, evt) {
992 if (this.opt.target) {
993 var target = $(this.opt.target);
994
995 if (target.length === 0) {
996 methods._error.call(this, 'Target selector invalid or missing!');
997 }
998
999 if (this.opt.targetFormat.indexOf('{score}') < 0) {
1000 methods._error.call(this, 'Template "{score}" missing!');
1001 }
1002
1003 var mouseover = evt && evt.type == 'mouseover';
1004
1005 if (score === undefined) {
1006 score = this.opt.targetText;
1007 } else if (score === null) {
1008 score = mouseover ? this.opt.cancelHint : this.opt.targetText;
1009 } else {
1010 if (this.opt.targetType == 'hint') {
1011 score = methods._getHint.call(this, Math.ceil(score));
1012 } else if (this.opt.precision) {
1013 score = parseFloat(score).toFixed(1);
1014 }
1015
1016 if (!mouseover && !this.opt.targetKeep) {
1017 score = this.opt.targetText;
1018 }
1019 }
1020
1021 if (score) {
1022 score = this.opt.targetFormat.toString().replace('{score}', score);
1023 }
1024
1025 if (target.is(':input')) {
1026 target.val(score);
1027 } else {
1028 target.html(score);
1029 }
1030 }
1031 }, _unlock: function() {
1032 $(this).data('readonly', false).css('cursor', 'pointer').removeAttr('title');
1033
1034 this.score.removeAttr('readonly', 'readonly');
1035
1036 for (var i = 0; i < this.opt.number; i++) {
1037 this.stars.eq(i).attr('title', methods._getHint.call(this, i + 1));
1038 }
1039
1040 if (this.cancel) {
1041 this.cancel.css('display', '');
1042 }
1043 }, cancel: function(click) {
1044 return this.each(function() {
1045 if ($(this).data('readonly') !== true) {
1046 methods[click ? 'click' : 'score'].call(this, null);
1047 this.score.removeAttr('value');
1048 }
1049 });
1050 }, click: function(score) {
1051 return $(this).each(function() {
1052 if ($(this).data('readonly') !== true) {
1053 methods._apply.call(this, score);
1054
1055 if (!this.opt.click) {
1056 methods._error.call(this, 'You must add the "click: function(score, evt) { }" callback.');
1057 }
1058
1059 this.opt.click.call(this, score, { type: 'click' });
1060
1061 methods._target.call(this, score);
1062 }
1063 });
1064 }, destroy: function() {
1065 return $(this).each(function() {
1066 var that = $(this),
1067 raw = that.data('raw');
1068
1069 if (raw) {
1070 that.off('.raty').empty().css({ cursor: raw.style.cursor, width: raw.style.width }).removeData('readonly');
1071 } else {
1072 that.data('raw', that.clone()[0]);
1073 }
1074 });
1075 }, getScore: function() {
1076 var score = [],
1077 value ;
1078
1079 $(this).each(function() {
1080 value = this.score.val();
1081
1082 score.push(value ? parseFloat(value) : undefined);
1083 });
1084
1085 return (score.length > 1) ? score : score[0];
1086 }, readOnly: function(readonly) {
1087 return this.each(function() {
1088 var that = $(this);
1089
1090 if (that.data('readonly') !== readonly) {
1091 if (readonly) {
1092 that.off('.raty').children('img').off('.raty');
1093
1094 methods._lock.call(this);
1095 } else {
1096 methods._binds.call(this);
1097 methods._unlock.call(this);
1098 }
1099
1100 that.data('readonly', readonly);
1101 }
1102 });
1103 }, reload: function() {
1104 return methods.set.call(this, {});
1105 }, score: function() {
1106 return arguments.length ? methods.setScore.apply(this, arguments) : methods.getScore.call(this);
1107 }, set: function(settings) {
1108 return this.each(function() {
1109 var that = $(this),
1110 actual = that.data('settings'),
1111 news = $.extend({}, actual, settings);
1112
1113 that.raty(news);
1114 });
1115 }, setScore: function(score) {
1116 return $(this).each(function() {
1117 if ($(this).data('readonly') !== true) {
1118 methods._apply.call(this, score);
1119 methods._target.call(this, score);
1120 }
1121 });
1122 }
1123};
1124
1125$.fn.raty = function(method) {
1126 if (methods[method]) {
1127 return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
1128 } else if (typeof method === 'object' || !method) {
1129 return methods.init.apply(this, arguments);
1130 } else {
1131 $.error('Method ' + method + ' does not exist!');
1132 }
1133};
1134
1135$.fn.raty.defaults = {
1136 cancel : false,
1137 cancelHint : 'Cancel this rating!',
1138 cancelOff : 'cancel-off.png',
1139 cancelOn : 'cancel-on.png',
1140 cancelPlace : 'left',
1141 click : undefined,
1142 half : false,
1143 halfShow : true,
1144 hints : ['bad', 'poor', 'regular', 'good', 'gorgeous'],
1145 iconRange : undefined,
1146 mouseout : undefined,
1147 mouseover : undefined,
1148 noRatedMsg : 'Not rated yet!',
1149 number : 5,
1150 numberMax : 20,
1151 path : '',
1152 precision : false,
1153 readOnly : false,
1154 round : { down: .25, full: .6, up: .76 },
1155 score : undefined,
1156 scoreName : 'score',
1157 single : false,
1158 size : 16,
1159 space : true,
1160 starHalf : 'star-half.png',
1161 starOff : 'star-off.png',
1162 starOn : 'star-on.png',
1163 target : undefined,
1164 targetFormat : '{score}',
1165 targetKeep : false,
1166 targetText : '',
1167 targetType : 'hint',
1168 width : undefined
1169};
1170
1171})(jQuery);
1172
1173/*
1174 html2canvas 0.4.0 <http://html2canvas.hertzen.com>
1175 Copyright (c) 2013 Niklas von Hertzen (@niklasvh)
1176
1177 Released under MIT License
1178 */
1179
1180 (function(window, document, undefined){
1181
1182 "use strict";
1183
1184 var _html2canvas = {},
1185 previousElement,
1186 computedCSS,
1187 html2canvas;
1188
1189 function h2clog(a) {
1190 if (_html2canvas.logging && window.console && window.console.log) {
1191 window.console.log(a);
1192 }
1193 }
1194
1195 _html2canvas.Util = {};
1196
1197 _html2canvas.Util.trimText = (function(isNative){
1198 return function(input){
1199 if(isNative) { return isNative.apply( input ); }
1200 else { return ((input || '') + '').replace( /^\s+|\s+$/g , '' ); }
1201 };
1202 })( String.prototype.trim );
1203
1204 _html2canvas.Util.parseBackgroundImage = function (value) {
1205 var whitespace = ' \r\n\t',
1206 method, definition, prefix, prefix_i, block, results = [],
1207 c, mode = 0, numParen = 0, quote, args;
1208
1209 var appendResult = function(){
1210 if(method) {
1211 if(definition.substr( 0, 1 ) === '"') {
1212 definition = definition.substr( 1, definition.length - 2 );
1213 }
1214 if(definition) {
1215 args.push(definition);
1216 }
1217 if(method.substr( 0, 1 ) === '-' &&
1218 (prefix_i = method.indexOf( '-', 1 ) + 1) > 0) {
1219 prefix = method.substr( 0, prefix_i);
1220 method = method.substr( prefix_i );
1221 }
1222 results.push({
1223 prefix: prefix,
1224 method: method.toLowerCase(),
1225 value: block,
1226 args: args
1227 });
1228 }
1229 args = []; //for some odd reason, setting .length = 0 didn't work in safari
1230 method =
1231 prefix =
1232 definition =
1233 block = '';
1234 };
1235
1236 appendResult();
1237 for(var i = 0, ii = value.length; i<ii; i++) {
1238 c = value[i];
1239 if(mode === 0 && whitespace.indexOf( c ) > -1){
1240 continue;
1241 }
1242 switch(c) {
1243 case '"':
1244 if(!quote) {
1245 quote = c;
1246 }
1247 else if(quote === c) {
1248 quote = null;
1249 }
1250 break;
1251
1252 case '(':
1253 if(quote) { break; }
1254 else if(mode === 0) {
1255 mode = 1;
1256 block += c;
1257 continue;
1258 } else {
1259 numParen++;
1260 }
1261 break;
1262
1263 case ')':
1264 if(quote) { break; }
1265 else if(mode === 1) {
1266 if(numParen === 0) {
1267 mode = 0;
1268 block += c;
1269 appendResult();
1270 continue;
1271 } else {
1272 numParen--;
1273 }
1274 }
1275 break;
1276
1277 case ',':
1278 if(quote) { break; }
1279 else if(mode === 0) {
1280 appendResult();
1281 continue;
1282 }
1283 else if (mode === 1) {
1284 if(numParen === 0 && !method.match(/^url$/i)) {
1285 args.push(definition);
1286 definition = '';
1287 block += c;
1288 continue;
1289 }
1290 }
1291 break;
1292 }
1293
1294 block += c;
1295 if(mode === 0) { method += c; }
1296 else { definition += c; }
1297 }
1298 appendResult();
1299
1300 return results;
1301};
1302
1303_html2canvas.Util.Bounds = function getBounds (el) {
1304 var clientRect,
1305 bounds = {};
1306
1307 if (el.getBoundingClientRect){
1308 clientRect = el.getBoundingClientRect();
1309
1310
1311 // TODO add scroll position to bounds, so no scrolling of window necessary
1312 bounds.top = clientRect.top;
1313 bounds.bottom = clientRect.bottom || (clientRect.top + clientRect.height);
1314 bounds.left = clientRect.left;
1315
1316 // older IE doesn't have width/height, but top/bottom instead
1317 bounds.width = clientRect.width || (clientRect.right - clientRect.left);
1318 bounds.height = clientRect.height || (clientRect.bottom - clientRect.top);
1319
1320 return bounds;
1321
1322}
1323};
1324
1325_html2canvas.Util.getCSS = function (el, attribute, index) {
1326 // return $(el).css(attribute);
1327
1328 var val,
1329 isBackgroundSizePosition = attribute.match( /^background(Size|Position)$/ );
1330
1331 function toPX( attribute, val ) {
1332 var rsLeft = el.runtimeStyle && el.runtimeStyle[ attribute ],
1333 left,
1334 style = el.style;
1335
1336 // Check if we are not dealing with pixels, (Opera has issues with this)
1337 // Ported from jQuery css.js
1338 // From the awesome hack by Dean Edwards
1339 // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
1340
1341 // If we're not dealing with a regular pixel number
1342 // but a number that has a weird ending, we need to convert it to pixels
1343
1344 if ( !/^-?[0-9]+\.?[0-9]*(?:px)?$/i.test( val ) && /^-?\d/.test( val ) ) {
1345
1346 // Remember the original values
1347 left = style.left;
1348
1349 // Put in the new values to get a computed value out
1350 if ( rsLeft ) {
1351 el.runtimeStyle.left = el.currentStyle.left;
1352 }
1353 style.left = attribute === "fontSize" ? "1em" : (val || 0);
1354 val = style.pixelLeft + "px";
1355
1356 // Revert the changed values
1357 style.left = left;
1358 if ( rsLeft ) {
1359 el.runtimeStyle.left = rsLeft;
1360 }
1361
1362 }
1363
1364 if (!/^(thin|medium|thick)$/i.test( val )) {
1365 return Math.round(parseFloat( val )) + "px";
1366 }
1367
1368 return val;
1369}
1370
1371if (previousElement !== el) {
1372 computedCSS = document.defaultView.getComputedStyle(el, null);
1373}
1374val = computedCSS[attribute];
1375
1376if (isBackgroundSizePosition) {
1377 val = (val || '').split( ',' );
1378 val = val[index || 0] || val[0] || 'auto';
1379 val = _html2canvas.Util.trimText(val).split(' ');
1380
1381 if(attribute === 'backgroundSize' && (!val[ 0 ] || val[ 0 ].match( /cover|contain|auto/ ))) {
1382 //these values will be handled in the parent function
1383
1384 } else {
1385 val[ 0 ] = ( val[ 0 ].indexOf( "%" ) === -1 ) ? toPX( attribute + "X", val[ 0 ] ) : val[ 0 ];
1386 if(val[ 1 ] === undefined) {
1387 if(attribute === 'backgroundSize') {
1388 val[ 1 ] = 'auto';
1389 return val;
1390 }
1391 else {
1392 // IE 9 doesn't return double digit always
1393 val[ 1 ] = val[ 0 ];
1394 }
1395 }
1396 val[ 1 ] = ( val[ 1 ].indexOf( "%" ) === -1 ) ? toPX( attribute + "Y", val[ 1 ] ) : val[ 1 ];
1397}
1398} else if ( /border(Top|Bottom)(Left|Right)Radius/.test( attribute) ) {
1399 var arr = val.split(" ");
1400 if ( arr.length <= 1 ) {
1401 arr[ 1 ] = arr[ 0 ];
1402 }
1403 arr[ 0 ] = parseInt( arr[ 0 ], 10 );
1404 arr[ 1 ] = parseInt( arr[ 1 ], 10 );
1405 val = arr;
1406}
1407
1408return val;
1409};
1410
1411_html2canvas.Util.resizeBounds = function( current_width, current_height, target_width, target_height, stretch_mode ){
1412 var target_ratio = target_width / target_height,
1413 current_ratio = current_width / current_height,
1414 output_width, output_height;
1415
1416 if(!stretch_mode || stretch_mode === 'auto') {
1417 output_width = target_width;
1418 output_height = target_height;
1419
1420 } else {
1421 if(target_ratio < current_ratio ^ stretch_mode === 'contain') {
1422 output_height = target_height;
1423 output_width = target_height * current_ratio;
1424 } else {
1425 output_width = target_width;
1426 output_height = target_width / current_ratio;
1427 }
1428 }
1429
1430 return { width: output_width, height: output_height };
1431};
1432
1433function backgroundBoundsFactory( prop, el, bounds, image, imageIndex, backgroundSize ) {
1434 var bgposition = _html2canvas.Util.getCSS( el, prop, imageIndex ) ,
1435 topPos,
1436 left,
1437 percentage,
1438 val;
1439
1440 if (bgposition.length === 1){
1441 val = bgposition[0];
1442
1443 bgposition = [];
1444
1445 bgposition[0] = val;
1446 bgposition[1] = val;
1447 }
1448
1449 if (bgposition[0].toString().indexOf("%") !== -1){
1450 percentage = (parseFloat(bgposition[0])/100);
1451 left = bounds.width * percentage;
1452 if(prop !== 'backgroundSize') {
1453 left -= (backgroundSize || image).width*percentage;
1454 }
1455
1456 } else {
1457 if(prop === 'backgroundSize') {
1458 if(bgposition[0] === 'auto') {
1459 left = image.width;
1460
1461 } else {
1462 if(bgposition[0].match(/contain|cover/)) {
1463 var resized = _html2canvas.Util.resizeBounds( image.width, image.height, bounds.width, bounds.height, bgposition[0] );
1464 left = resized.width;
1465 topPos = resized.height;
1466 } else {
1467 left = parseInt (bgposition[0], 10 );
1468 }
1469 }
1470
1471 } else {
1472 left = parseInt( bgposition[0], 10 );
1473 }
1474 }
1475
1476
1477 if(bgposition[1] === 'auto') {
1478 topPos = left / image.width * image.height;
1479 } else if (bgposition[1].toString().indexOf("%") !== -1){
1480 percentage = (parseFloat(bgposition[1])/100);
1481 topPos = bounds.height * percentage;
1482 if(prop !== 'backgroundSize') {
1483 topPos -= (backgroundSize || image).height * percentage;
1484 }
1485
1486 } else {
1487 topPos = parseInt(bgposition[1],10);
1488 }
1489
1490 return [left, topPos];
1491}
1492
1493_html2canvas.Util.BackgroundPosition = function( el, bounds, image, imageIndex, backgroundSize ) {
1494 var result = backgroundBoundsFactory( 'backgroundPosition', el, bounds, image, imageIndex, backgroundSize );
1495 return { left: result[0], top: result[1] };
1496};
1497_html2canvas.Util.BackgroundSize = function( el, bounds, image, imageIndex ) {
1498 var result = backgroundBoundsFactory( 'backgroundSize', el, bounds, image, imageIndex );
1499 return { width: result[0], height: result[1] };
1500};
1501
1502_html2canvas.Util.Extend = function (options, defaults) {
1503 for (var key in options) {
1504 if (options.hasOwnProperty(key)) {
1505 defaults[key] = options[key];
1506 }
1507 }
1508 return defaults;
1509};
1510
1511
1512/*
1513 * Derived from jQuery.contents()
1514 * Copyright 2010, John Resig
1515 * Dual licensed under the MIT or GPL Version 2 licenses.
1516 * http://jquery.org/license
1517 */
1518 _html2canvas.Util.Children = function( elem ) {
1519
1520
1521 var children;
1522 try {
1523
1524 children = (elem.nodeName && elem.nodeName.toUpperCase() === "IFRAME") ?
1525 elem.contentDocument || elem.contentWindow.document : (function( array ){
1526 var ret = [];
1527
1528 if ( array !== null ) {
1529
1530 (function( first, second ) {
1531 var i = first.length,
1532 j = 0;
1533
1534 if ( typeof second.length === "number" ) {
1535 for ( var l = second.length; j < l; j++ ) {
1536 first[ i++ ] = second[ j ];
1537 }
1538
1539 } else {
1540 while ( second[j] !== undefined ) {
1541 first[ i++ ] = second[ j++ ];
1542 }
1543 }
1544
1545 first.length = i;
1546
1547 return first;
1548 })( ret, array );
1549
1550 }
1551
1552 return ret;
1553 })( elem.childNodes );
1554
1555 } catch (ex) {
1556 h2clog("html2canvas.Util.Children failed with exception: " + ex.message);
1557 children = [];
1558 }
1559 return children;
1560 };
1561
1562 _html2canvas.Util.Font = (function () {
1563
1564 var fontData = {};
1565
1566 return function(font, fontSize, doc) {
1567 if (fontData[font + "-" + fontSize] !== undefined) {
1568 return fontData[font + "-" + fontSize];
1569 }
1570
1571 var container = doc.createElement('div'),
1572 img = doc.createElement('img'),
1573 span = doc.createElement('span'),
1574 sampleText = 'Hidden Text',
1575 baseline,
1576 middle,
1577 metricsObj;
1578
1579 container.style.visibility = "hidden";
1580 container.style.fontFamily = font;
1581 container.style.fontSize = fontSize;
1582 container.style.margin = 0;
1583 container.style.padding = 0;
1584
1585 doc.body.appendChild(container);
1586
1587 // http://probablyprogramming.com/2009/03/15/the-tiniest-gif-ever (handtinywhite.gif)
1588 img.src = "data:image/gif;base64,R0lGODlhAQABAIABAP///wAAACwAAAAAAQABAAACAkQBADs=";
1589 img.width = 1;
1590 img.height = 1;
1591
1592 img.style.margin = 0;
1593 img.style.padding = 0;
1594 img.style.verticalAlign = "baseline";
1595
1596 span.style.fontFamily = font;
1597 span.style.fontSize = fontSize;
1598 span.style.margin = 0;
1599 span.style.padding = 0;
1600
1601 span.appendChild(doc.createTextNode(sampleText));
1602 container.appendChild(span);
1603 container.appendChild(img);
1604 baseline = (img.offsetTop - span.offsetTop) + 1;
1605
1606 container.removeChild(span);
1607 container.appendChild(doc.createTextNode(sampleText));
1608
1609 container.style.lineHeight = "normal";
1610 img.style.verticalAlign = "super";
1611
1612 middle = (img.offsetTop-container.offsetTop) + 1;
1613 metricsObj = {
1614 baseline: baseline,
1615 lineWidth: 1,
1616 middle: middle
1617 };
1618
1619 fontData[font + "-" + fontSize] = metricsObj;
1620
1621 doc.body.removeChild(container);
1622
1623 return metricsObj;
1624};
1625})();
1626
1627(function(){
1628
1629 _html2canvas.Generate = {};
1630
1631 var reGradients = [
1632 /^(-webkit-linear-gradient)\(([a-z\s]+)([\w\d\.\s,%\(\)]+)\)$/,
1633 /^(-o-linear-gradient)\(([a-z\s]+)([\w\d\.\s,%\(\)]+)\)$/,
1634 /^(-webkit-gradient)\((linear|radial),\s((?:\d{1,3}%?)\s(?:\d{1,3}%?),\s(?:\d{1,3}%?)\s(?:\d{1,3}%?))([\w\d\.\s,%\(\)\-]+)\)$/,
1635 /^(-moz-linear-gradient)\(((?:\d{1,3}%?)\s(?:\d{1,3}%?))([\w\d\.\s,%\(\)]+)\)$/,
1636 /^(-webkit-radial-gradient)\(((?:\d{1,3}%?)\s(?:\d{1,3}%?)),\s(\w+)\s([a-z\-]+)([\w\d\.\s,%\(\)]+)\)$/,
1637 /^(-moz-radial-gradient)\(((?:\d{1,3}%?)\s(?:\d{1,3}%?)),\s(\w+)\s?([a-z\-]*)([\w\d\.\s,%\(\)]+)\)$/,
1638 /^(-o-radial-gradient)\(((?:\d{1,3}%?)\s(?:\d{1,3}%?)),\s(\w+)\s([a-z\-]+)([\w\d\.\s,%\(\)]+)\)$/
1639 ];
1640
1641 /*
1642 * TODO: Add IE10 vendor prefix (-ms) support
1643 * TODO: Add W3C gradient (linear-gradient) support
1644 * TODO: Add old Webkit -webkit-gradient(radial, ...) support
1645 * TODO: Maybe some RegExp optimizations are possible ;o)
1646 */
1647 _html2canvas.Generate.parseGradient = function(css, bounds) {
1648 var gradient, i, len = reGradients.length, m1, stop, m2, m2Len, step, m3, tl,tr,br,bl;
1649
1650 for(i = 0; i < len; i+=1){
1651 m1 = css.match(reGradients[i]);
1652 if(m1) {
1653 break;
1654 }
1655 }
1656
1657 if(m1) {
1658 switch(m1[1]) {
1659 case '-webkit-linear-gradient':
1660 case '-o-linear-gradient':
1661
1662 gradient = {
1663 type: 'linear',
1664 x0: null,
1665 y0: null,
1666 x1: null,
1667 y1: null,
1668 colorStops: []
1669 };
1670
1671 // get coordinates
1672 m2 = m1[2].match(/\w+/g);
1673 if(m2){
1674 m2Len = m2.length;
1675 for(i = 0; i < m2Len; i+=1){
1676 switch(m2[i]) {
1677 case 'top':
1678 gradient.y0 = 0;
1679 gradient.y1 = bounds.height;
1680 break;
1681
1682 case 'right':
1683 gradient.x0 = bounds.width;
1684 gradient.x1 = 0;
1685 break;
1686
1687 case 'bottom':
1688 gradient.y0 = bounds.height;
1689 gradient.y1 = 0;
1690 break;
1691
1692 case 'left':
1693 gradient.x0 = 0;
1694 gradient.x1 = bounds.width;
1695 break;
1696 }
1697 }
1698 }
1699 if(gradient.x0 === null && gradient.x1 === null){ // center
1700 gradient.x0 = gradient.x1 = bounds.width / 2;
1701 }
1702 if(gradient.y0 === null && gradient.y1 === null){ // center
1703 gradient.y0 = gradient.y1 = bounds.height / 2;
1704 }
1705
1706 // get colors and stops
1707 m2 = m1[3].match(/((?:rgb|rgba)\(\d{1,3},\s\d{1,3},\s\d{1,3}(?:,\s[0-9\.]+)?\)(?:\s\d{1,3}(?:%|px))?)+/g);
1708 if(m2){
1709 m2Len = m2.length;
1710 step = 1 / Math.max(m2Len - 1, 1);
1711 for(i = 0; i < m2Len; i+=1){
1712 m3 = m2[i].match(/((?:rgb|rgba)\(\d{1,3},\s\d{1,3},\s\d{1,3}(?:,\s[0-9\.]+)?\))\s*(\d{1,3})?(%|px)?/);
1713 if(m3[2]){
1714 stop = parseFloat(m3[2]);
1715 if(m3[3] === '%'){
1716 stop /= 100;
1717 } else { // px - stupid opera
1718 stop /= bounds.width;
1719 }
1720 } else {
1721 stop = i * step;
1722 }
1723 gradient.colorStops.push({
1724 color: m3[1],
1725 stop: stop
1726 });
1727 }
1728 }
1729 break;
1730
1731 case '-webkit-gradient':
1732
1733 gradient = {
1734 type: m1[2] === 'radial' ? 'circle' : m1[2], // TODO: Add radial gradient support for older mozilla definitions
1735 x0: 0,
1736 y0: 0,
1737 x1: 0,
1738 y1: 0,
1739 colorStops: []
1740 };
1741
1742 // get coordinates
1743 m2 = m1[3].match(/(\d{1,3})%?\s(\d{1,3})%?,\s(\d{1,3})%?\s(\d{1,3})%?/);
1744 if(m2){
1745 gradient.x0 = (m2[1] * bounds.width) / 100;
1746 gradient.y0 = (m2[2] * bounds.height) / 100;
1747 gradient.x1 = (m2[3] * bounds.width) / 100;
1748 gradient.y1 = (m2[4] * bounds.height) / 100;
1749 }
1750
1751 // get colors and stops
1752 m2 = m1[4].match(/((?:from|to|color-stop)\((?:[0-9\.]+,\s)?(?:rgb|rgba)\(\d{1,3},\s\d{1,3},\s\d{1,3}(?:,\s[0-9\.]+)?\)\))+/g);
1753 if(m2){
1754 m2Len = m2.length;
1755 for(i = 0; i < m2Len; i+=1){
1756 m3 = m2[i].match(/(from|to|color-stop)\(([0-9\.]+)?(?:,\s)?((?:rgb|rgba)\(\d{1,3},\s\d{1,3},\s\d{1,3}(?:,\s[0-9\.]+)?\))\)/);
1757 stop = parseFloat(m3[2]);
1758 if(m3[1] === 'from') {
1759 stop = 0.0;
1760 }
1761 if(m3[1] === 'to') {
1762 stop = 1.0;
1763 }
1764 gradient.colorStops.push({
1765 color: m3[3],
1766 stop: stop
1767 });
1768 }
1769 }
1770 break;
1771
1772 case '-moz-linear-gradient':
1773
1774 gradient = {
1775 type: 'linear',
1776 x0: 0,
1777 y0: 0,
1778 x1: 0,
1779 y1: 0,
1780 colorStops: []
1781 };
1782
1783 // get coordinates
1784 m2 = m1[2].match(/(\d{1,3})%?\s(\d{1,3})%?/);
1785
1786 // m2[1] == 0% -> left
1787 // m2[1] == 50% -> center
1788 // m2[1] == 100% -> right
1789
1790 // m2[2] == 0% -> top
1791 // m2[2] == 50% -> center
1792 // m2[2] == 100% -> bottom
1793
1794 if(m2){
1795 gradient.x0 = (m2[1] * bounds.width) / 100;
1796 gradient.y0 = (m2[2] * bounds.height) / 100;
1797 gradient.x1 = bounds.width - gradient.x0;
1798 gradient.y1 = bounds.height - gradient.y0;
1799 }
1800
1801 // get colors and stops
1802 m2 = m1[3].match(/((?:rgb|rgba)\(\d{1,3},\s\d{1,3},\s\d{1,3}(?:,\s[0-9\.]+)?\)(?:\s\d{1,3}%)?)+/g);
1803 if(m2){
1804 m2Len = m2.length;
1805 step = 1 / Math.max(m2Len - 1, 1);
1806 for(i = 0; i < m2Len; i+=1){
1807 m3 = m2[i].match(/((?:rgb|rgba)\(\d{1,3},\s\d{1,3},\s\d{1,3}(?:,\s[0-9\.]+)?\))\s*(\d{1,3})?(%)?/);
1808 if(m3[2]){
1809 stop = parseFloat(m3[2]);
1810 if(m3[3]){ // percentage
1811 stop /= 100;
1812 }
1813 } else {
1814 stop = i * step;
1815 }
1816 gradient.colorStops.push({
1817 color: m3[1],
1818 stop: stop
1819 });
1820 }
1821 }
1822 break;
1823
1824 case '-webkit-radial-gradient':
1825 case '-moz-radial-gradient':
1826 case '-o-radial-gradient':
1827
1828 gradient = {
1829 type: 'circle',
1830 x0: 0,
1831 y0: 0,
1832 x1: bounds.width,
1833 y1: bounds.height,
1834 cx: 0,
1835 cy: 0,
1836 rx: 0,
1837 ry: 0,
1838 colorStops: []
1839 };
1840
1841 // center
1842 m2 = m1[2].match(/(\d{1,3})%?\s(\d{1,3})%?/);
1843 if(m2){
1844 gradient.cx = (m2[1] * bounds.width) / 100;
1845 gradient.cy = (m2[2] * bounds.height) / 100;
1846 }
1847
1848 // size
1849 m2 = m1[3].match(/\w+/);
1850 m3 = m1[4].match(/[a-z\-]*/);
1851 if(m2 && m3){
1852 switch(m3[0]){
1853 case 'farthest-corner':
1854 case 'cover': // is equivalent to farthest-corner
1855 case '': // mozilla removes "cover" from definition :(
1856 tl = Math.sqrt(Math.pow(gradient.cx, 2) + Math.pow(gradient.cy, 2));
1857 tr = Math.sqrt(Math.pow(gradient.cx, 2) + Math.pow(gradient.y1 - gradient.cy, 2));
1858 br = Math.sqrt(Math.pow(gradient.x1 - gradient.cx, 2) + Math.pow(gradient.y1 - gradient.cy, 2));
1859 bl = Math.sqrt(Math.pow(gradient.x1 - gradient.cx, 2) + Math.pow(gradient.cy, 2));
1860 gradient.rx = gradient.ry = Math.max(tl, tr, br, bl);
1861 break;
1862 case 'closest-corner':
1863 tl = Math.sqrt(Math.pow(gradient.cx, 2) + Math.pow(gradient.cy, 2));
1864 tr = Math.sqrt(Math.pow(gradient.cx, 2) + Math.pow(gradient.y1 - gradient.cy, 2));
1865 br = Math.sqrt(Math.pow(gradient.x1 - gradient.cx, 2) + Math.pow(gradient.y1 - gradient.cy, 2));
1866 bl = Math.sqrt(Math.pow(gradient.x1 - gradient.cx, 2) + Math.pow(gradient.cy, 2));
1867 gradient.rx = gradient.ry = Math.min(tl, tr, br, bl);
1868 break;
1869 case 'farthest-side':
1870 if(m2[0] === 'circle'){
1871 gradient.rx = gradient.ry = Math.max(
1872 gradient.cx,
1873 gradient.cy,
1874 gradient.x1 - gradient.cx,
1875 gradient.y1 - gradient.cy
1876 );
1877 } else { // ellipse
1878
1879 gradient.type = m2[0];
1880
1881 gradient.rx = Math.max(
1882 gradient.cx,
1883 gradient.x1 - gradient.cx
1884 );
1885 gradient.ry = Math.max(
1886 gradient.cy,
1887 gradient.y1 - gradient.cy
1888 );
1889 }
1890 break;
1891 case 'closest-side':
1892 case 'contain': // is equivalent to closest-side
1893 if(m2[0] === 'circle'){
1894 gradient.rx = gradient.ry = Math.min(
1895 gradient.cx,
1896 gradient.cy,
1897 gradient.x1 - gradient.cx,
1898 gradient.y1 - gradient.cy
1899 );
1900 } else { // ellipse
1901
1902 gradient.type = m2[0];
1903
1904 gradient.rx = Math.min(
1905 gradient.cx,
1906 gradient.x1 - gradient.cx
1907 );
1908 gradient.ry = Math.min(
1909 gradient.cy,
1910 gradient.y1 - gradient.cy
1911 );
1912 }
1913 break;
1914
1915 // TODO: add support for "30px 40px" sizes (webkit only)
1916 }
1917 }
1918
1919 // color stops
1920 m2 = m1[5].match(/((?:rgb|rgba)\(\d{1,3},\s\d{1,3},\s\d{1,3}(?:,\s[0-9\.]+)?\)(?:\s\d{1,3}(?:%|px))?)+/g);
1921 if(m2){
1922 m2Len = m2.length;
1923 step = 1 / Math.max(m2Len - 1, 1);
1924 for(i = 0; i < m2Len; i+=1){
1925 m3 = m2[i].match(/((?:rgb|rgba)\(\d{1,3},\s\d{1,3},\s\d{1,3}(?:,\s[0-9\.]+)?\))\s*(\d{1,3})?(%|px)?/);
1926 if(m3[2]){
1927 stop = parseFloat(m3[2]);
1928 if(m3[3] === '%'){
1929 stop /= 100;
1930 } else { // px - stupid opera
1931 stop /= bounds.width;
1932 }
1933 } else {
1934 stop = i * step;
1935 }
1936 gradient.colorStops.push({
1937 color: m3[1],
1938 stop: stop
1939 });
1940 }
1941 }
1942 break;
1943}
1944}
1945
1946return gradient;
1947};
1948
1949_html2canvas.Generate.Gradient = function(src, bounds) {
1950 if(bounds.width === 0 || bounds.height === 0) {
1951 return;
1952 }
1953
1954 var canvas = document.createElement('canvas'),
1955 ctx = canvas.getContext('2d'),
1956 gradient, grad, i, len;
1957
1958 canvas.width = bounds.width;
1959 canvas.height = bounds.height;
1960
1961 // TODO: add support for multi defined background gradients
1962 gradient = _html2canvas.Generate.parseGradient(src, bounds);
1963
1964 if(gradient) {
1965 if(gradient.type === 'linear') {
1966 grad = ctx.createLinearGradient(gradient.x0, gradient.y0, gradient.x1, gradient.y1);
1967
1968 for (i = 0, len = gradient.colorStops.length; i < len; i+=1) {
1969 try {
1970 grad.addColorStop(gradient.colorStops[i].stop, gradient.colorStops[i].color);
1971 }
1972 catch(e) {
1973 h2clog(['failed to add color stop: ', e, '; tried to add: ', gradient.colorStops[i], '; stop: ', i, '; in: ', src]);
1974 }
1975 }
1976
1977 ctx.fillStyle = grad;
1978 ctx.fillRect(0, 0, bounds.width, bounds.height);
1979
1980 } else if(gradient.type === 'circle') {
1981
1982 grad = ctx.createRadialGradient(gradient.cx, gradient.cy, 0, gradient.cx, gradient.cy, gradient.rx);
1983
1984 for (i = 0, len = gradient.colorStops.length; i < len; i+=1) {
1985 try {
1986 grad.addColorStop(gradient.colorStops[i].stop, gradient.colorStops[i].color);
1987 }
1988 catch(e) {
1989 h2clog(['failed to add color stop: ', e, '; tried to add: ', gradient.colorStops[i], '; stop: ', i, '; in: ', src]);
1990 }
1991 }
1992
1993 ctx.fillStyle = grad;
1994 ctx.fillRect(0, 0, bounds.width, bounds.height);
1995
1996 } else if(gradient.type === 'ellipse') {
1997
1998 // draw circle
1999 var canvasRadial = document.createElement('canvas'),
2000 ctxRadial = canvasRadial.getContext('2d'),
2001 ri = Math.max(gradient.rx, gradient.ry),
2002 di = ri * 2, imgRadial;
2003
2004 canvasRadial.width = canvasRadial.height = di;
2005
2006 grad = ctxRadial.createRadialGradient(gradient.rx, gradient.ry, 0, gradient.rx, gradient.ry, ri);
2007
2008 for (i = 0, len = gradient.colorStops.length; i < len; i+=1) {
2009 try {
2010 grad.addColorStop(gradient.colorStops[i].stop, gradient.colorStops[i].color);
2011 }
2012 catch(e) {
2013 h2clog(['failed to add color stop: ', e, '; tried to add: ', gradient.colorStops[i], '; stop: ', i, '; in: ', src]);
2014 }
2015 }
2016
2017 ctxRadial.fillStyle = grad;
2018 ctxRadial.fillRect(0, 0, di, di);
2019
2020 ctx.fillStyle = gradient.colorStops[i - 1].color;
2021 ctx.fillRect(0, 0, canvas.width, canvas.height);
2022 ctx.drawImage(canvasRadial, gradient.cx - gradient.rx, gradient.cy - gradient.ry, 2 * gradient.rx, 2 * gradient.ry);
2023
2024 }
2025}
2026
2027return canvas;
2028};
2029
2030_html2canvas.Generate.ListAlpha = function(number) {
2031 var tmp = "",
2032 modulus;
2033
2034 do {
2035 modulus = number % 26;
2036 tmp = String.fromCharCode((modulus) + 64) + tmp;
2037 number = number / 26;
2038 }while((number*26) > 26);
2039
2040 return tmp;
2041};
2042
2043_html2canvas.Generate.ListRoman = function(number) {
2044 var romanArray = ["M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"],
2045 decimal = [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1],
2046 roman = "",
2047 v,
2048 len = romanArray.length;
2049
2050 if (number <= 0 || number >= 4000) {
2051 return number;
2052 }
2053
2054 for (v=0; v < len; v+=1) {
2055 while (number >= decimal[v]) {
2056 number -= decimal[v];
2057 roman += romanArray[v];
2058 }
2059 }
2060
2061 return roman;
2062
2063};
2064
2065})();
2066_html2canvas.Parse = function (images, options) {
2067 window.scroll(0,0);
2068
2069 var element = (( options.elements === undefined ) ? document.body : options.elements[0]), // select body by default
2070 numDraws = 0,
2071 doc = element.ownerDocument,
2072 support = _html2canvas.Util.Support(options, doc),
2073 ignoreElementsRegExp = new RegExp("(" + options.ignoreElements + ")"),
2074 body = doc.body,
2075 getCSS = _html2canvas.Util.getCSS,
2076 pseudoHide = "___html2canvas___pseudoelement",
2077 hidePseudoElements = doc.createElement('style');
2078
2079 hidePseudoElements.innerHTML = '.' + pseudoHide + '-before:before { content: "" !important; display: none !important; }' +
2080 '.' + pseudoHide + '-after:after { content: "" !important; display: none !important; }';
2081
2082 body.appendChild(hidePseudoElements);
2083
2084 images = images || {};
2085
2086 function documentWidth () {
2087 return Math.max(
2088 Math.max(doc.body.scrollWidth, doc.documentElement.scrollWidth),
2089 Math.max(doc.body.offsetWidth, doc.documentElement.offsetWidth),
2090 Math.max(doc.body.clientWidth, doc.documentElement.clientWidth)
2091 );
2092 }
2093
2094 function documentHeight () {
2095 return Math.max(
2096 Math.max(doc.body.scrollHeight, doc.documentElement.scrollHeight),
2097 Math.max(doc.body.offsetHeight, doc.documentElement.offsetHeight),
2098 Math.max(doc.body.clientHeight, doc.documentElement.clientHeight)
2099 );
2100 }
2101
2102 function getCSSInt(element, attribute) {
2103 var val = parseInt(getCSS(element, attribute), 10);
2104 return (isNaN(val)) ? 0 : val; // borders in old IE are throwing 'medium' for demo.html
2105}
2106
2107function renderRect (ctx, x, y, w, h, bgcolor) {
2108 if (bgcolor !== "transparent"){
2109 ctx.setVariable("fillStyle", bgcolor);
2110 ctx.fillRect(x, y, w, h);
2111 numDraws+=1;
2112 }
2113}
2114
2115function textTransform (text, transform) {
2116 switch(transform){
2117 case "lowercase":
2118 return text.toLowerCase();
2119 case "capitalize":
2120 return text.replace( /(^|\s|:|-|\(|\))([a-z])/g , function (m, p1, p2) {
2121 if (m.length > 0) {
2122 return p1 + p2.toUpperCase();
2123 }
2124 } );
2125 case "uppercase":
2126 return text.toUpperCase();
2127 default:
2128 return text;
2129 }
2130}
2131
2132function noLetterSpacing(letter_spacing) {
2133 return (/^(normal|none|0px)$/.test(letter_spacing));
2134}
2135
2136function drawText(currentText, x, y, ctx){
2137 if (currentText !== null && _html2canvas.Util.trimText(currentText).length > 0) {
2138 ctx.fillText(currentText, x, y);
2139 numDraws+=1;
2140 }
2141}
2142
2143function setTextVariables(ctx, el, text_decoration, color) {
2144 var align = false,
2145 bold = getCSS(el, "fontWeight"),
2146 family = getCSS(el, "fontFamily"),
2147 size = getCSS(el, "fontSize");
2148
2149 switch(parseInt(bold, 10)){
2150 case 401:
2151 bold = "bold";
2152 break;
2153 case 400:
2154 bold = "normal";
2155 break;
2156 }
2157
2158 ctx.setVariable("fillStyle", color);
2159 ctx.setVariable("font", [getCSS(el, "fontStyle"), getCSS(el, "fontVariant"), bold, size, family].join(" "));
2160 ctx.setVariable("textAlign", (align) ? "right" : "left");
2161
2162 if (text_decoration !== "none"){
2163 return _html2canvas.Util.Font(family, size, doc);
2164 }
2165}
2166
2167function renderTextDecoration(ctx, text_decoration, bounds, metrics, color) {
2168 switch(text_decoration) {
2169 case "underline":
2170 // Draws a line at the baseline of the font
2171 // TODO As some browsers display the line as more than 1px if the font-size is big, need to take that into account both in position and size
2172 renderRect(ctx, bounds.left, Math.round(bounds.top + metrics.baseline + metrics.lineWidth), bounds.width, 1, color);
2173 break;
2174 case "overline":
2175 renderRect(ctx, bounds.left, Math.round(bounds.top), bounds.width, 1, color);
2176 break;
2177 case "line-through":
2178 // TODO try and find exact position for line-through
2179 renderRect(ctx, bounds.left, Math.ceil(bounds.top + metrics.middle + metrics.lineWidth), bounds.width, 1, color);
2180 break;
2181 }
2182}
2183
2184function getTextBounds(state, text, textDecoration, isLast) {
2185 var bounds;
2186 if (support.rangeBounds) {
2187 if (textDecoration !== "none" || _html2canvas.Util.trimText(text).length !== 0) {
2188 bounds = textRangeBounds(text, state.node, state.textOffset);
2189 }
2190 state.textOffset += text.length;
2191 } else if (state.node && typeof state.node.nodeValue === "string" ){
2192 var newTextNode = (isLast) ? state.node.splitText(text.length) : null;
2193 bounds = textWrapperBounds(state.node);
2194 state.node = newTextNode;
2195 }
2196 return bounds;
2197}
2198
2199function textRangeBounds(text, textNode, textOffset) {
2200 var range = doc.createRange();
2201 range.setStart(textNode, textOffset);
2202 range.setEnd(textNode, textOffset + text.length);
2203 return range.getBoundingClientRect();
2204}
2205
2206function textWrapperBounds(oldTextNode) {
2207 var parent = oldTextNode.parentNode,
2208 wrapElement = doc.createElement('wrapper'),
2209 backupText = oldTextNode.cloneNode(true);
2210
2211 wrapElement.appendChild(oldTextNode.cloneNode(true));
2212 parent.replaceChild(wrapElement, oldTextNode);
2213
2214 var bounds = _html2canvas.Util.Bounds(wrapElement);
2215 parent.replaceChild(backupText, wrapElement);
2216 return bounds;
2217}
2218
2219function renderText(el, textNode, stack) {
2220 var ctx = stack.ctx,
2221 color = getCSS(el, "color"),
2222 textDecoration = getCSS(el, "textDecoration"),
2223 textAlign = getCSS(el, "textAlign"),
2224 metrics,
2225 textList,
2226 state = {
2227 node: textNode,
2228 textOffset: 0
2229 };
2230
2231 if (_html2canvas.Util.trimText(textNode.nodeValue).length > 0) {
2232 textNode.nodeValue = textTransform(textNode.nodeValue, getCSS(el, "textTransform"));
2233 textAlign = textAlign.replace(["-webkit-auto"],["auto"]);
2234
2235 textList = (!options.letterRendering && /^(left|right|justify|auto)$/.test(textAlign) && noLetterSpacing(getCSS(el, "letterSpacing"))) ?
2236 textNode.nodeValue.split(/(\b| )/)
2237 : textNode.nodeValue.split("");
2238
2239 metrics = setTextVariables(ctx, el, textDecoration, color);
2240
2241 if (options.chinese) {
2242 textList.forEach(function(word, index) {
2243 if (/.*[\u4E00-\u9FA5].*$/.test(word)) {
2244 word = word.split("");
2245 word.unshift(index, 1);
2246 textList.splice.apply(textList, word);
2247 }
2248 });
2249 }
2250
2251 textList.forEach(function(text, index) {
2252 var bounds = getTextBounds(state, text, textDecoration, (index < textList.length - 1));
2253 if (bounds) {
2254 drawText(text, bounds.left, bounds.bottom, ctx);
2255 renderTextDecoration(ctx, textDecoration, bounds, metrics, color);
2256 }
2257 });
2258 }
2259}
2260
2261function listPosition (element, val) {
2262 var boundElement = doc.createElement( "boundelement" ),
2263 originalType,
2264 bounds;
2265
2266 boundElement.style.display = "inline";
2267
2268 originalType = element.style.listStyleType;
2269 element.style.listStyleType = "none";
2270
2271 boundElement.appendChild(doc.createTextNode(val));
2272
2273 element.insertBefore(boundElement, element.firstChild);
2274
2275 bounds = _html2canvas.Util.Bounds(boundElement);
2276 element.removeChild(boundElement);
2277 element.style.listStyleType = originalType;
2278 return bounds;
2279}
2280
2281function elementIndex( el ) {
2282 var i = -1,
2283 count = 1,
2284 childs = el.parentNode.childNodes;
2285
2286 if (el.parentNode) {
2287 while( childs[ ++i ] !== el ) {
2288 if ( childs[ i ].nodeType === 1 ) {
2289 count++;
2290 }
2291 }
2292 return count;
2293 } else {
2294 return -1;
2295 }
2296}
2297
2298function listItemText(element, type) {
2299 var currentIndex = elementIndex(element),
2300 text;
2301 switch(type){
2302 case "decimal":
2303 text = currentIndex;
2304 break;
2305 case "decimal-leading-zero":
2306 text = (currentIndex.toString().length === 1) ? currentIndex = "0" + currentIndex.toString() : currentIndex.toString();
2307 break;
2308 case "upper-roman":
2309 text = _html2canvas.Generate.ListRoman( currentIndex );
2310 break;
2311 case "lower-roman":
2312 text = _html2canvas.Generate.ListRoman( currentIndex ).toLowerCase();
2313 break;
2314 case "lower-alpha":
2315 text = _html2canvas.Generate.ListAlpha( currentIndex ).toLowerCase();
2316 break;
2317 case "upper-alpha":
2318 text = _html2canvas.Generate.ListAlpha( currentIndex );
2319 break;
2320 }
2321
2322 text += ". ";
2323 return text;
2324}
2325
2326function renderListItem(element, stack, elBounds) {
2327 var x,
2328 text,
2329 ctx = stack.ctx,
2330 type = getCSS(element, "listStyleType"),
2331 listBounds;
2332
2333 if (/^(decimal|decimal-leading-zero|upper-alpha|upper-latin|upper-roman|lower-alpha|lower-greek|lower-latin|lower-roman)$/i.test(type)) {
2334 text = listItemText(element, type);
2335 listBounds = listPosition(element, text);
2336 setTextVariables(ctx, element, "none", getCSS(element, "color"));
2337
2338 if (getCSS(element, "listStylePosition") === "inside") {
2339 ctx.setVariable("textAlign", "left");
2340 x = elBounds.left;
2341 } else {
2342 return;
2343 }
2344
2345 drawText(text, x, listBounds.bottom, ctx);
2346 }
2347}
2348
2349function loadImage (src){
2350 var img = images[src];
2351 if (img && img.succeeded === true) {
2352 return img.img;
2353 } else {
2354 return false;
2355 }
2356}
2357
2358function clipBounds(src, dst){
2359 var x = Math.max(src.left, dst.left),
2360 y = Math.max(src.top, dst.top),
2361 x2 = Math.min((src.left + src.width), (dst.left + dst.width)),
2362 y2 = Math.min((src.top + src.height), (dst.top + dst.height));
2363
2364 return {
2365 left:x,
2366 top:y,
2367 width:x2-x,
2368 height:y2-y
2369 };
2370}
2371
2372function setZ(zIndex, parentZ){
2373 // TODO fix static elements overlapping relative/absolute elements under same stack, if they are defined after them
2374 var newContext;
2375 if (!parentZ){
2376 newContext = h2czContext(0);
2377 return newContext;
2378 }
2379
2380 if (zIndex !== "auto"){
2381 newContext = h2czContext(zIndex);
2382 parentZ.children.push(newContext);
2383 return newContext;
2384
2385 }
2386
2387 return parentZ;
2388}
2389
2390function renderImage(ctx, element, image, bounds, borders) {
2391
2392 var paddingLeft = getCSSInt(element, 'paddingLeft'),
2393 paddingTop = getCSSInt(element, 'paddingTop'),
2394 paddingRight = getCSSInt(element, 'paddingRight'),
2395 paddingBottom = getCSSInt(element, 'paddingBottom');
2396
2397 drawImage(
2398 ctx,
2399 image,
2400 0, //sx
2401 0, //sy
2402 image.width, //sw
2403 image.height, //sh
2404 bounds.left + paddingLeft + borders[3].width, //dx
2405 bounds.top + paddingTop + borders[0].width, // dy
2406 bounds.width - (borders[1].width + borders[3].width + paddingLeft + paddingRight), //dw
2407 bounds.height - (borders[0].width + borders[2].width + paddingTop + paddingBottom) //dh
2408 );
2409}
2410
2411function getBorderData(element) {
2412 return ["Top", "Right", "Bottom", "Left"].map(function(side) {
2413 return {
2414 width: getCSSInt(element, 'border' + side + 'Width'),
2415 color: getCSS(element, 'border' + side + 'Color')
2416 };
2417 });
2418}
2419
2420function getBorderRadiusData(element) {
2421 return ["TopLeft", "TopRight", "BottomRight", "BottomLeft"].map(function(side) {
2422 return getCSS(element, 'border' + side + 'Radius');
2423 });
2424}
2425
2426var getCurvePoints = (function(kappa) {
2427
2428 return function(x, y, r1, r2) {
2429 var ox = (r1) * kappa, // control point offset horizontal
2430 oy = (r2) * kappa, // control point offset vertical
2431 xm = x + r1, // x-middle
2432 ym = y + r2; // y-middle
2433 return {
2434 topLeft: bezierCurve({
2435 x:x,
2436 y:ym
2437 }, {
2438 x:x,
2439 y:ym - oy
2440 }, {
2441 x:xm - ox,
2442 y:y
2443 }, {
2444 x:xm,
2445 y:y
2446 }),
2447 topRight: bezierCurve({
2448 x:x,
2449 y:y
2450 }, {
2451 x:x + ox,
2452 y:y
2453 }, {
2454 x:xm,
2455 y:ym - oy
2456 }, {
2457 x:xm,
2458 y:ym
2459 }),
2460 bottomRight: bezierCurve({
2461 x:xm,
2462 y:y
2463 }, {
2464 x:xm,
2465 y:y + oy
2466 }, {
2467 x:x + ox,
2468 y:ym
2469 }, {
2470 x:x,
2471 y:ym
2472 }),
2473 bottomLeft: bezierCurve({
2474 x:xm,
2475 y:ym
2476 }, {
2477 x:xm - ox,
2478 y:ym
2479 }, {
2480 x:x,
2481 y:y + oy
2482 }, {
2483 x:x,
2484 y:y
2485 })
2486 };
2487 };
2488})(4 * ((Math.sqrt(2) - 1) / 3));
2489
2490function bezierCurve(start, startControl, endControl, end) {
2491
2492 var lerp = function (a, b, t) {
2493 return {
2494 x:a.x + (b.x - a.x) * t,
2495 y:a.y + (b.y - a.y) * t
2496 };
2497 };
2498
2499 return {
2500 start: start,
2501 startControl: startControl,
2502 endControl: endControl,
2503 end: end,
2504 subdivide: function(t) {
2505 var ab = lerp(start, startControl, t),
2506 bc = lerp(startControl, endControl, t),
2507 cd = lerp(endControl, end, t),
2508 abbc = lerp(ab, bc, t),
2509 bccd = lerp(bc, cd, t),
2510 dest = lerp(abbc, bccd, t);
2511 return [bezierCurve(start, ab, abbc, dest), bezierCurve(dest, bccd, cd, end)];
2512 },
2513 curveTo: function(borderArgs) {
2514 borderArgs.push(["bezierCurve", startControl.x, startControl.y, endControl.x, endControl.y, end.x, end.y]);
2515 },
2516 curveToReversed: function(borderArgs) {
2517 borderArgs.push(["bezierCurve", endControl.x, endControl.y, startControl.x, startControl.y, start.x, start.y]);
2518 }
2519 };
2520}
2521
2522function parseCorner(borderArgs, radius1, radius2, corner1, corner2, x, y) {
2523 if (radius1[0] > 0 || radius1[1] > 0) {
2524 borderArgs.push(["line", corner1[0].start.x, corner1[0].start.y]);
2525 corner1[0].curveTo(borderArgs);
2526 corner1[1].curveTo(borderArgs);
2527 } else {
2528 borderArgs.push(["line", x, y]);
2529 }
2530
2531 if (radius2[0] > 0 || radius2[1] > 0) {
2532 borderArgs.push(["line", corner2[0].start.x, corner2[0].start.y]);
2533 }
2534}
2535
2536function drawSide(borderData, radius1, radius2, outer1, inner1, outer2, inner2) {
2537 var borderArgs = [];
2538
2539 if (radius1[0] > 0 || radius1[1] > 0) {
2540 borderArgs.push(["line", outer1[1].start.x, outer1[1].start.y]);
2541 outer1[1].curveTo(borderArgs);
2542 } else {
2543 borderArgs.push([ "line", borderData.c1[0], borderData.c1[1]]);
2544 }
2545
2546 if (radius2[0] > 0 || radius2[1] > 0) {
2547 borderArgs.push(["line", outer2[0].start.x, outer2[0].start.y]);
2548 outer2[0].curveTo(borderArgs);
2549 borderArgs.push(["line", inner2[0].end.x, inner2[0].end.y]);
2550 inner2[0].curveToReversed(borderArgs);
2551 } else {
2552 borderArgs.push([ "line", borderData.c2[0], borderData.c2[1]]);
2553 borderArgs.push([ "line", borderData.c3[0], borderData.c3[1]]);
2554 }
2555
2556 if (radius1[0] > 0 || radius1[1] > 0) {
2557 borderArgs.push(["line", inner1[1].end.x, inner1[1].end.y]);
2558 inner1[1].curveToReversed(borderArgs);
2559 } else {
2560 borderArgs.push([ "line", borderData.c4[0], borderData.c4[1]]);
2561 }
2562
2563 return borderArgs;
2564}
2565
2566function calculateCurvePoints(bounds, borderRadius, borders) {
2567
2568 var x = bounds.left,
2569 y = bounds.top,
2570 width = bounds.width,
2571 height = bounds.height,
2572
2573 tlh = borderRadius[0][0],
2574 tlv = borderRadius[0][1],
2575 trh = borderRadius[1][0],
2576 trv = borderRadius[1][1],
2577 brv = borderRadius[2][0],
2578 brh = borderRadius[2][1],
2579 blh = borderRadius[3][0],
2580 blv = borderRadius[3][1],
2581
2582 topWidth = width - trh,
2583 rightHeight = height - brv,
2584 bottomWidth = width - brh,
2585 leftHeight = height - blv;
2586
2587 return {
2588 topLeftOuter: getCurvePoints(
2589 x,
2590 y,
2591 tlh,
2592 tlv
2593 ).topLeft.subdivide(0.5),
2594
2595 topLeftInner: getCurvePoints(
2596 x + borders[3].width,
2597 y + borders[0].width,
2598 Math.max(0, tlh - borders[3].width),
2599 Math.max(0, tlv - borders[0].width)
2600 ).topLeft.subdivide(0.5),
2601
2602 topRightOuter: getCurvePoints(
2603 x + topWidth,
2604 y,
2605 trh,
2606 trv
2607 ).topRight.subdivide(0.5),
2608
2609 topRightInner: getCurvePoints(
2610 x + Math.min(topWidth, width + borders[3].width),
2611 y + borders[0].width,
2612 (topWidth > width + borders[3].width) ? 0 :trh - borders[3].width,
2613 trv - borders[0].width
2614 ).topRight.subdivide(0.5),
2615
2616 bottomRightOuter: getCurvePoints(
2617 x + bottomWidth,
2618 y + rightHeight,
2619 brh,
2620 brv
2621 ).bottomRight.subdivide(0.5),
2622
2623 bottomRightInner: getCurvePoints(
2624 x + Math.min(bottomWidth, width + borders[3].width),
2625 y + Math.min(rightHeight, height + borders[0].width),
2626 Math.max(0, brh - borders[1].width),
2627 Math.max(0, brv - borders[2].width)
2628 ).bottomRight.subdivide(0.5),
2629
2630 bottomLeftOuter: getCurvePoints(
2631 x,
2632 y + leftHeight,
2633 blh,
2634 blv
2635 ).bottomLeft.subdivide(0.5),
2636
2637 bottomLeftInner: getCurvePoints(
2638 x + borders[3].width,
2639 y + leftHeight,
2640 Math.max(0, blh - borders[3].width),
2641 Math.max(0, blv - borders[2].width)
2642 ).bottomLeft.subdivide(0.5)
2643 };
2644}
2645
2646function getBorderClip(element, borderPoints, borders, radius, bounds) {
2647 var backgroundClip = getCSS(element, 'backgroundClip'),
2648 borderArgs = [];
2649
2650 switch(backgroundClip) {
2651 case "content-box":
2652 case "padding-box":
2653 parseCorner(borderArgs, radius[0], radius[1], borderPoints.topLeftInner, borderPoints.topRightInner, bounds.left + borders[3].width, bounds.top + borders[0].width);
2654 parseCorner(borderArgs, radius[1], radius[2], borderPoints.topRightInner, borderPoints.bottomRightInner, bounds.left + bounds.width - borders[1].width, bounds.top + borders[0].width);
2655 parseCorner(borderArgs, radius[2], radius[3], borderPoints.bottomRightInner, borderPoints.bottomLeftInner, bounds.left + bounds.width - borders[1].width, bounds.top + bounds.height - borders[2].width);
2656 parseCorner(borderArgs, radius[3], radius[0], borderPoints.bottomLeftInner, borderPoints.topLeftInner, bounds.left + borders[3].width, bounds.top + bounds.height - borders[2].width);
2657 break;
2658
2659 default:
2660 parseCorner(borderArgs, radius[0], radius[1], borderPoints.topLeftOuter, borderPoints.topRightOuter, bounds.left, bounds.top);
2661 parseCorner(borderArgs, radius[1], radius[2], borderPoints.topRightOuter, borderPoints.bottomRightOuter, bounds.left + bounds.width, bounds.top);
2662 parseCorner(borderArgs, radius[2], radius[3], borderPoints.bottomRightOuter, borderPoints.bottomLeftOuter, bounds.left + bounds.width, bounds.top + bounds.height);
2663 parseCorner(borderArgs, radius[3], radius[0], borderPoints.bottomLeftOuter, borderPoints.topLeftOuter, bounds.left, bounds.top + bounds.height);
2664 break;
2665 }
2666
2667 return borderArgs;
2668}
2669
2670function parseBorders(element, bounds, borders){
2671 var x = bounds.left,
2672 y = bounds.top,
2673 width = bounds.width,
2674 height = bounds.height,
2675 borderSide,
2676 bx,
2677 by,
2678 bw,
2679 bh,
2680 borderArgs,
2681 // http://www.w3.org/TR/css3-background/#the-border-radius
2682 borderRadius = getBorderRadiusData(element),
2683 borderPoints = calculateCurvePoints(bounds, borderRadius, borders),
2684 borderData = {
2685 clip: getBorderClip(element, borderPoints, borders, borderRadius, bounds),
2686 borders: []
2687 };
2688
2689 for (borderSide = 0; borderSide < 4; borderSide++) {
2690
2691 if (borders[borderSide].width > 0) {
2692 bx = x;
2693 by = y;
2694 bw = width;
2695 bh = height - (borders[2].width);
2696
2697 switch(borderSide) {
2698 case 0:
2699 // top border
2700 bh = borders[0].width;
2701
2702 borderArgs = drawSide({
2703 c1: [bx, by],
2704 c2: [bx + bw, by],
2705 c3: [bx + bw - borders[1].width, by + bh],
2706 c4: [bx + borders[3].width, by + bh]
2707 }, borderRadius[0], borderRadius[1],
2708 borderPoints.topLeftOuter, borderPoints.topLeftInner, borderPoints.topRightOuter, borderPoints.topRightInner);
2709 break;
2710 case 1:
2711 // right border
2712 bx = x + width - (borders[1].width);
2713 bw = borders[1].width;
2714
2715 borderArgs = drawSide({
2716 c1: [bx + bw, by],
2717 c2: [bx + bw, by + bh + borders[2].width],
2718 c3: [bx, by + bh],
2719 c4: [bx, by + borders[0].width]
2720 }, borderRadius[1], borderRadius[2],
2721 borderPoints.topRightOuter, borderPoints.topRightInner, borderPoints.bottomRightOuter, borderPoints.bottomRightInner);
2722 break;
2723 case 2:
2724 // bottom border
2725 by = (by + height) - (borders[2].width);
2726 bh = borders[2].width;
2727
2728 borderArgs = drawSide({
2729 c1: [bx + bw, by + bh],
2730 c2: [bx, by + bh],
2731 c3: [bx + borders[3].width, by],
2732 c4: [bx + bw - borders[2].width, by]
2733 }, borderRadius[2], borderRadius[3],
2734 borderPoints.bottomRightOuter, borderPoints.bottomRightInner, borderPoints.bottomLeftOuter, borderPoints.bottomLeftInner);
2735 break;
2736 case 3:
2737 // left border
2738 bw = borders[3].width;
2739
2740 borderArgs = drawSide({
2741 c1: [bx, by + bh + borders[2].width],
2742 c2: [bx, by],
2743 c3: [bx + bw, by + borders[0].width],
2744 c4: [bx + bw, by + bh]
2745 }, borderRadius[3], borderRadius[0],
2746 borderPoints.bottomLeftOuter, borderPoints.bottomLeftInner, borderPoints.topLeftOuter, borderPoints.topLeftInner);
2747 break;
2748 }
2749
2750 borderData.borders.push({
2751 args: borderArgs,
2752 color: borders[borderSide].color
2753 });
2754
2755 }
2756}
2757
2758return borderData;
2759}
2760
2761function createShape(ctx, args) {
2762 var shape = ctx.drawShape();
2763 args.forEach(function(border, index) {
2764 shape[(index === 0) ? "moveTo" : border[0] + "To" ].apply(null, border.slice(1));
2765 });
2766 return shape;
2767}
2768
2769function renderBorders(ctx, borderArgs, color) {
2770 if (color !== "transparent") {
2771 ctx.setVariable( "fillStyle", color);
2772 createShape(ctx, borderArgs);
2773 ctx.fill();
2774 numDraws+=1;
2775 }
2776}
2777
2778function renderFormValue (el, bounds, stack){
2779
2780 var valueWrap = doc.createElement('valuewrap'),
2781 cssPropertyArray = ['lineHeight','textAlign','fontFamily','color','fontSize','paddingLeft','paddingTop','width','height','border','borderLeftWidth','borderTopWidth'],
2782 textValue,
2783 textNode;
2784
2785 cssPropertyArray.forEach(function(property) {
2786 try {
2787 valueWrap.style[property] = getCSS(el, property);
2788 } catch(e) {
2789 // Older IE has issues with "border"
2790 h2clog("html2canvas: Parse: Exception caught in renderFormValue: " + e.message);
2791 }
2792});
2793
2794 valueWrap.style.borderColor = "black";
2795 valueWrap.style.borderStyle = "solid";
2796 valueWrap.style.display = "block";
2797 valueWrap.style.position = "absolute";
2798
2799 if (/^(submit|reset|button|text|password)$/.test(el.type) || el.nodeName === "SELECT"){
2800 valueWrap.style.lineHeight = getCSS(el, "height");
2801 }
2802
2803 valueWrap.style.top = bounds.top + "px";
2804 valueWrap.style.left = bounds.left + "px";
2805
2806 textValue = (el.nodeName === "SELECT") ? (el.options[el.selectedIndex] || 0).text : el.value;
2807 if(!textValue) {
2808 textValue = el.placeholder;
2809 }
2810
2811 textNode = doc.createTextNode(textValue);
2812
2813 valueWrap.appendChild(textNode);
2814 body.appendChild(valueWrap);
2815
2816 renderText(el, textNode, stack);
2817 body.removeChild(valueWrap);
2818}
2819
2820function drawImage (ctx) {
2821 ctx.drawImage.apply(ctx, Array.prototype.slice.call(arguments, 1));
2822 numDraws+=1;
2823}
2824
2825function getPseudoElement(el, which) {
2826 var elStyle = window.getComputedStyle(el, which);
2827 if(!elStyle || !elStyle.content || elStyle.content === "none" || elStyle.content === "-moz-alt-content") {
2828 return;
2829 }
2830 var content = elStyle.content + '',
2831 first = content.substr( 0, 1 );
2832 //strips quotes
2833 if(first === content.substr( content.length - 1 ) && first.match(/'|"/)) {
2834 content = content.substr( 1, content.length - 2 );
2835 }
2836
2837 var isImage = content.substr( 0, 3 ) === 'url',
2838 elps = document.createElement( isImage ? 'img' : 'span' );
2839
2840 elps.className = pseudoHide + "-before " + pseudoHide + "-after";
2841
2842 Object.keys(elStyle).filter(indexedProperty).forEach(function(prop) {
2843 elps.style[prop] = elStyle[prop];
2844 });
2845
2846 if(isImage) {
2847 elps.src = _html2canvas.Util.parseBackgroundImage(content)[0].args[0];
2848 } else {
2849 elps.innerHTML = content;
2850 }
2851 return elps;
2852}
2853
2854function indexedProperty(property) {
2855 return (isNaN(window.parseInt(property, 10)));
2856}
2857
2858function injectPseudoElements(el, stack) {
2859 var before = getPseudoElement(el, ':before'),
2860 after = getPseudoElement(el, ':after');
2861 if(!before && !after) {
2862 return;
2863 }
2864
2865 if(before) {
2866 el.className += " " + pseudoHide + "-before";
2867 el.parentNode.insertBefore(before, el);
2868 parseElement(before, stack, true);
2869 el.parentNode.removeChild(before);
2870 el.className = el.className.replace(pseudoHide + "-before", "").trim();
2871 }
2872
2873 if (after) {
2874 el.className += " " + pseudoHide + "-after";
2875 el.appendChild(after);
2876 parseElement(after, stack, true);
2877 el.removeChild(after);
2878 el.className = el.className.replace(pseudoHide + "-after", "").trim();
2879 }
2880
2881}
2882
2883function renderBackgroundRepeat(ctx, image, backgroundPosition, bounds) {
2884 var offsetX = Math.round(bounds.left + backgroundPosition.left),
2885 offsetY = Math.round(bounds.top + backgroundPosition.top);
2886
2887 ctx.createPattern(image);
2888 ctx.translate(offsetX, offsetY);
2889 ctx.fill();
2890 ctx.translate(-offsetX, -offsetY);
2891}
2892
2893function backgroundRepeatShape(ctx, image, backgroundPosition, bounds, left, top, width, height) {
2894 var args = [];
2895 args.push(["line", Math.round(left), Math.round(top)]);
2896 args.push(["line", Math.round(left + width), Math.round(top)]);
2897 args.push(["line", Math.round(left + width), Math.round(height + top)]);
2898 args.push(["line", Math.round(left), Math.round(height + top)]);
2899 createShape(ctx, args);
2900 ctx.save();
2901 ctx.clip();
2902 renderBackgroundRepeat(ctx, image, backgroundPosition, bounds);
2903 ctx.restore();
2904}
2905
2906function renderBackgroundColor(ctx, backgroundBounds, bgcolor) {
2907 renderRect(
2908 ctx,
2909 backgroundBounds.left,
2910 backgroundBounds.top,
2911 backgroundBounds.width,
2912 backgroundBounds.height,
2913 bgcolor
2914 );
2915}
2916
2917function renderBackgroundRepeating(el, bounds, ctx, image, imageIndex) {
2918 var backgroundSize = _html2canvas.Util.BackgroundSize(el, bounds, image, imageIndex),
2919 backgroundPosition = _html2canvas.Util.BackgroundPosition(el, bounds, image, imageIndex, backgroundSize),
2920 backgroundRepeat = getCSS(el, "backgroundRepeat").split(",").map(function(value) {
2921 return value.trim();
2922 });
2923
2924 image = resizeImage(image, backgroundSize);
2925
2926 backgroundRepeat = backgroundRepeat[imageIndex] || backgroundRepeat[0];
2927
2928 switch (backgroundRepeat) {
2929 case "repeat-x":
2930 backgroundRepeatShape(ctx, image, backgroundPosition, bounds,
2931 bounds.left, bounds.top + backgroundPosition.top, 99999, image.height);
2932 break;
2933
2934 case "repeat-y":
2935 backgroundRepeatShape(ctx, image, backgroundPosition, bounds,
2936 bounds.left + backgroundPosition.left, bounds.top, image.width, 99999);
2937 break;
2938
2939 case "no-repeat":
2940 backgroundRepeatShape(ctx, image, backgroundPosition, bounds,
2941 bounds.left + backgroundPosition.left, bounds.top + backgroundPosition.top, image.width, image.height);
2942 break;
2943
2944 default:
2945 renderBackgroundRepeat(ctx, image, backgroundPosition, {
2946 top: bounds.top,
2947 left: bounds.left,
2948 width: image.width,
2949 height: image.height
2950 });
2951 break;
2952 }
2953}
2954
2955function renderBackgroundImage(element, bounds, ctx) {
2956 var backgroundImage = getCSS(element, "backgroundImage"),
2957 backgroundImages = _html2canvas.Util.parseBackgroundImage(backgroundImage),
2958 image,
2959 imageIndex = backgroundImages.length;
2960
2961 while(imageIndex--) {
2962 backgroundImage = backgroundImages[imageIndex];
2963
2964 if (!backgroundImage.args || backgroundImage.args.length === 0) {
2965 continue;
2966 }
2967
2968 var key = backgroundImage.method === 'url' ?
2969 backgroundImage.args[0] :
2970 backgroundImage.value;
2971
2972 image = loadImage(key);
2973
2974 // TODO add support for background-origin
2975 if (image) {
2976 renderBackgroundRepeating(element, bounds, ctx, image, imageIndex);
2977 } else {
2978 h2clog("html2canvas: Error loading background:", backgroundImage);
2979 }
2980 }
2981}
2982
2983function resizeImage(image, bounds) {
2984 if(image.width === bounds.width && image.height === bounds.height) {
2985 return image;
2986 }
2987
2988 var ctx, canvas = doc.createElement('canvas');
2989 canvas.width = bounds.width;
2990 canvas.height = bounds.height;
2991 ctx = canvas.getContext("2d");
2992 drawImage(ctx, image, 0, 0, image.width, image.height, 0, 0, bounds.width, bounds.height );
2993 return canvas;
2994}
2995
2996function setOpacity(ctx, element, parentStack) {
2997 var opacity = getCSS(element, "opacity") * ((parentStack) ? parentStack.opacity : 1);
2998 ctx.setVariable("globalAlpha", opacity);
2999 return opacity;
3000}
3001
3002function createStack(element, parentStack, bounds) {
3003
3004 var ctx = h2cRenderContext((!parentStack) ? documentWidth() : bounds.width , (!parentStack) ? documentHeight() : bounds.height),
3005 stack = {
3006 ctx: ctx,
3007 zIndex: setZ(getCSS(element, "zIndex"), (parentStack) ? parentStack.zIndex : null),
3008 opacity: setOpacity(ctx, element, parentStack),
3009 cssPosition: getCSS(element, "position"),
3010 borders: getBorderData(element),
3011 clip: (parentStack && parentStack.clip) ? _html2canvas.Util.Extend( {}, parentStack.clip ) : null
3012 };
3013
3014 // TODO correct overflow for absolute content residing under a static position
3015 if (options.useOverflow === true && /(hidden|scroll|auto)/.test(getCSS(element, "overflow")) === true && /(BODY)/i.test(element.nodeName) === false){
3016 stack.clip = (stack.clip) ? clipBounds(stack.clip, bounds) : bounds;
3017 }
3018
3019 stack.zIndex.children.push(stack);
3020
3021 return stack;
3022}
3023
3024function getBackgroundBounds(borders, bounds, clip) {
3025 var backgroundBounds = {
3026 left: bounds.left + borders[3].width,
3027 top: bounds.top + borders[0].width,
3028 width: bounds.width - (borders[1].width + borders[3].width),
3029 height: bounds.height - (borders[0].width + borders[2].width)
3030 };
3031
3032 if (clip) {
3033 backgroundBounds = clipBounds(backgroundBounds, clip);
3034 }
3035
3036 return backgroundBounds;
3037}
3038
3039function renderElement(element, parentStack, pseudoElement){
3040 var bounds = _html2canvas.Util.Bounds(element),
3041 image,
3042 bgcolor = (ignoreElementsRegExp.test(element.nodeName)) ? "#efefef" : getCSS(element, "backgroundColor"),
3043 stack = createStack(element, parentStack, bounds),
3044 borders = stack.borders,
3045 ctx = stack.ctx,
3046 backgroundBounds = getBackgroundBounds(borders, bounds, stack.clip),
3047 borderData = parseBorders(element, bounds, borders);
3048
3049 createShape(ctx, borderData.clip);
3050
3051 ctx.save();
3052 ctx.clip();
3053
3054 if (backgroundBounds.height > 0 && backgroundBounds.width > 0){
3055 renderBackgroundColor(ctx, bounds, bgcolor);
3056 renderBackgroundImage(element, backgroundBounds, ctx);
3057 }
3058
3059 ctx.restore();
3060
3061 borderData.borders.forEach(function(border) {
3062 renderBorders(ctx, border.args, border.color);
3063 });
3064
3065 if (!pseudoElement) {
3066 injectPseudoElements(element, stack);
3067 }
3068
3069 switch(element.nodeName){
3070 case "IMG":
3071 if ((image = loadImage(element.getAttribute('src')))) {
3072 renderImage(ctx, element, image, bounds, borders);
3073 } else {
3074 h2clog("html2canvas: Error loading <img>:" + element.getAttribute('src'));
3075 }
3076 break;
3077 case "INPUT":
3078 // TODO add all relevant type's, i.e. HTML5 new stuff
3079 // todo add support for placeholder attribute for browsers which support it
3080 if (/^(text|url|email|submit|button|reset)$/.test(element.type) && (element.value || element.placeholder).length > 0){
3081 renderFormValue(element, bounds, stack);
3082 }
3083 break;
3084 case "TEXTAREA":
3085 if ((element.value || element.placeholder || "").length > 0){
3086 renderFormValue(element, bounds, stack);
3087 }
3088 break;
3089 case "SELECT":
3090 if ((element.options||element.placeholder || "").length > 0){
3091 renderFormValue(element, bounds, stack);
3092 }
3093 break;
3094 case "LI":
3095 renderListItem(element, stack, backgroundBounds);
3096 break;
3097 case "CANVAS":
3098 renderImage(ctx, element, element, bounds, borders);
3099 break;
3100 }
3101
3102 return stack;
3103}
3104
3105function isElementVisible(element) {
3106 return (getCSS(element, 'display') !== "none" && getCSS(element, 'visibility') !== "hidden" && !element.hasAttribute("data-html2canvas-ignore"));
3107}
3108
3109function parseElement (el, stack, pseudoElement) {
3110
3111 if (isElementVisible(el)) {
3112 stack = renderElement(el, stack, pseudoElement) || stack;
3113 if (!ignoreElementsRegExp.test(el.nodeName)) {
3114 _html2canvas.Util.Children(el).forEach(function(node) {
3115 if (node.nodeType === 1) {
3116 parseElement(node, stack, pseudoElement);
3117 } else if (node.nodeType === 3) {
3118 renderText(el, node, stack);
3119 }
3120 });
3121 }
3122 }
3123}
3124
3125function svgDOMRender(body, stack) {
3126 var img = new Image(),
3127 docWidth = documentWidth(),
3128 docHeight = documentHeight(),
3129 html = "";
3130
3131 function parseDOM(el) {
3132 var children = _html2canvas.Util.Children( el ),
3133 len = children.length,
3134 attr,
3135 a,
3136 alen,
3137 elm,
3138 i;
3139 for ( i = 0; i < len; i+=1 ) {
3140 elm = children[ i ];
3141 if ( elm.nodeType === 3 ) {
3142 // Text node
3143 html += elm.nodeValue.replace(/</g,"<").replace(/>/g,">");
3144 } else if ( elm.nodeType === 1 ) {
3145 // Element
3146 if ( !/^(script|meta|title)$/.test(elm.nodeName.toLowerCase()) ) {
3147
3148 html += "<" + elm.nodeName.toLowerCase();
3149
3150 // add attributes
3151 if ( elm.hasAttributes() ) {
3152 attr = elm.attributes;
3153 alen = attr.length;
3154 for ( a = 0; a < alen; a+=1 ) {
3155 html += " " + attr[ a ].name + '="' + attr[ a ].value + '"';
3156 }
3157 }
3158
3159
3160 html += '>';
3161
3162 parseDOM( elm );
3163
3164
3165 html += "</" + elm.nodeName.toLowerCase() + ">";
3166 }
3167 }
3168
3169}
3170
3171}
3172
3173parseDOM(body);
3174img.src = [
3175"data:image/svg+xml,",
3176"<svg xmlns='http://www.w3.org/2000/svg' version='1.1' width='" + docWidth + "' height='" + docHeight + "'>",
3177"<foreignObject width='" + docWidth + "' height='" + docHeight + "'>",
3178"<html xmlns='http://www.w3.org/1999/xhtml' style='margin:0;'>",
3179html.replace(/\#/g,"%23"),
3180"</html>",
3181"</foreignObject>",
3182"</svg>"
3183].join("");
3184
3185img.onload = function() {
3186 stack.svgRender = img;
3187};
3188
3189}
3190
3191function init() {
3192 var stack = renderElement(element, null);
3193
3194 if (support.svgRendering) {
3195 svgDOMRender(document.documentElement, stack);
3196 }
3197
3198 Array.prototype.slice.call(element.children, 0).forEach(function(childElement) {
3199 parseElement(childElement, stack);
3200 });
3201
3202 stack.backgroundColor = getCSS(document.documentElement, "backgroundColor");
3203 body.removeChild(hidePseudoElements);
3204 return stack;
3205}
3206
3207return init();
3208};
3209
3210function h2czContext(zindex) {
3211 return {
3212 zindex: zindex,
3213 children: []
3214 };
3215}
3216_html2canvas.Preload = function( options ) {
3217
3218 var images = {
3219 numLoaded: 0, // also failed are counted here
3220 numFailed: 0,
3221 numTotal: 0,
3222 cleanupDone: false
3223},
3224pageOrigin,
3225methods,
3226i,
3227count = 0,
3228element = options.elements[0] || document.body,
3229doc = element.ownerDocument,
3230 domImages = doc.images, // TODO probably should limit it to images present in the element only
3231 imgLen = domImages.length,
3232 link = doc.createElement("a"),
3233 supportCORS = (function( img ){
3234 return (img.crossOrigin !== undefined);
3235 })(new Image()),
3236 timeoutTimer;
3237
3238 link.href = window.location.href;
3239 pageOrigin = link.protocol + link.host;
3240
3241 function isSameOrigin(url){
3242 link.href = url;
3243 link.href = link.href; // YES, BELIEVE IT OR NOT, that is required for IE9 - http://jsfiddle.net/niklasvh/2e48b/
3244 var origin = link.protocol + link.host;
3245 return (origin === pageOrigin);
3246}
3247
3248function start(){
3249 h2clog("html2canvas: start: images: " + images.numLoaded + " / " + images.numTotal + " (failed: " + images.numFailed + ")");
3250 if (!images.firstRun && images.numLoaded >= images.numTotal){
3251 h2clog("Finished loading images: # " + images.numTotal + " (failed: " + images.numFailed + ")");
3252
3253 if (typeof options.complete === "function"){
3254 options.complete(images);
3255 }
3256
3257 }
3258}
3259
3260 // TODO modify proxy to serve images with CORS enabled, where available
3261 function proxyGetImage(url, img, imageObj){
3262 var callback_name,
3263 scriptUrl = options.proxy,
3264 script;
3265
3266 link.href = url;
3267 url = link.href; // work around for pages with base href="" set - WARNING: this may change the url
3268
3269 callback_name = 'html2canvas_' + (count++);
3270 imageObj.callbackname = callback_name;
3271
3272 if (scriptUrl.indexOf("?") > -1) {
3273 scriptUrl += "&";
3274 } else {
3275 scriptUrl += "?";
3276 }
3277 scriptUrl += 'url=' + encodeURIComponent(url) + '&callback=' + callback_name;
3278 script = doc.createElement("script");
3279
3280 window[callback_name] = function(a){
3281 if (a.substring(0,6) === "error:"){
3282 imageObj.succeeded = false;
3283 images.numLoaded++;
3284 images.numFailed++;
3285 start();
3286 } else {
3287 setImageLoadHandlers(img, imageObj);
3288 img.src = a;
3289 }
3290 window[callback_name] = undefined; // to work with IE<9 // NOTE: that the undefined callback property-name still exists on the window object (for IE<9)
3291 try {
3292 delete window[callback_name]; // for all browser that support this
3293 } catch(ex) {}
3294 script.parentNode.removeChild(script);
3295 script = null;
3296 delete imageObj.script;
3297 delete imageObj.callbackname;
3298};
3299
3300script.setAttribute("type", "text/javascript");
3301script.setAttribute("src", scriptUrl);
3302imageObj.script = script;
3303window.document.body.appendChild(script);
3304
3305}
3306
3307function loadPseudoElement(element, type) {
3308 var style = window.getComputedStyle(element, type),
3309 content = style.content;
3310 if (content.substr(0, 3) === 'url') {
3311 methods.loadImage(_html2canvas.Util.parseBackgroundImage(content)[0].args[0]);
3312 }
3313 loadBackgroundImages(style.backgroundImage, element);
3314}
3315
3316function loadPseudoElementImages(element) {
3317 loadPseudoElement(element, ":before");
3318 loadPseudoElement(element, ":after");
3319}
3320
3321function loadGradientImage(backgroundImage, bounds) {
3322 var img = _html2canvas.Generate.Gradient(backgroundImage, bounds);
3323
3324 if (img !== undefined){
3325 images[backgroundImage] = {
3326 img: img,
3327 succeeded: true
3328 };
3329 images.numTotal++;
3330 images.numLoaded++;
3331 start();
3332 }
3333}
3334
3335function invalidBackgrounds(background_image) {
3336 return (background_image && background_image.method && background_image.args && background_image.args.length > 0 );
3337}
3338
3339function loadBackgroundImages(background_image, el) {
3340 var bounds;
3341
3342 _html2canvas.Util.parseBackgroundImage(background_image).filter(invalidBackgrounds).forEach(function(background_image) {
3343 if (background_image.method === 'url') {
3344 methods.loadImage(background_image.args[0]);
3345 } else if(background_image.method.match(/\-?gradient$/)) {
3346 if(bounds === undefined) {
3347 bounds = _html2canvas.Util.Bounds(el);
3348 }
3349 loadGradientImage(background_image.value, bounds);
3350 }
3351 });
3352}
3353
3354function getImages (el) {
3355 var elNodeType = false;
3356
3357 // Firefox fails with permission denied on pages with iframes
3358 try {
3359 _html2canvas.Util.Children(el).forEach(function(img) {
3360 getImages(img);
3361 });
3362 }
3363 catch( e ) {}
3364
3365 try {
3366 elNodeType = el.nodeType;
3367 } catch (ex) {
3368 elNodeType = false;
3369 h2clog("html2canvas: failed to access some element's nodeType - Exception: " + ex.message);
3370 }
3371
3372 if (elNodeType === 1 || elNodeType === undefined) {
3373 loadPseudoElementImages(el);
3374 try {
3375 loadBackgroundImages(_html2canvas.Util.getCSS(el, 'backgroundImage'), el);
3376 } catch(e) {
3377 h2clog("html2canvas: failed to get background-image - Exception: " + e.message);
3378 }
3379 loadBackgroundImages(el);
3380 }
3381}
3382
3383function setImageLoadHandlers(img, imageObj) {
3384 img.onload = function() {
3385 if ( imageObj.timer !== undefined ) {
3386 // CORS succeeded
3387 window.clearTimeout( imageObj.timer );
3388 }
3389
3390 images.numLoaded++;
3391 imageObj.succeeded = true;
3392 img.onerror = img.onload = null;
3393 start();
3394};
3395img.onerror = function() {
3396 if (img.crossOrigin === "anonymous") {
3397 // CORS failed
3398 window.clearTimeout( imageObj.timer );
3399
3400 // let's try with proxy instead
3401 if ( options.proxy ) {
3402 var src = img.src;
3403 img = new Image();
3404 imageObj.img = img;
3405 img.src = src;
3406
3407 proxyGetImage( img.src, img, imageObj );
3408 return;
3409 }
3410 }
3411
3412 images.numLoaded++;
3413 images.numFailed++;
3414 imageObj.succeeded = false;
3415 img.onerror = img.onload = null;
3416 start();
3417};
3418}
3419
3420methods = {
3421 loadImage: function( src ) {
3422 var img, imageObj;
3423 if ( src && images[src] === undefined ) {
3424 img = new Image();
3425 if ( src.match(/data:image\/.*;base64,/i) ) {
3426 img.src = src.replace(/url\(['"]{0,}|['"]{0,}\)$/ig, '');
3427 imageObj = images[src] = {
3428 img: img
3429 };
3430 images.numTotal++;
3431 setImageLoadHandlers(img, imageObj);
3432 } else if ( isSameOrigin( src ) || options.allowTaint === true ) {
3433 imageObj = images[src] = {
3434 img: img
3435 };
3436 images.numTotal++;
3437 setImageLoadHandlers(img, imageObj);
3438 img.src = src;
3439 } else if ( supportCORS && !options.allowTaint && options.useCORS ) {
3440 // attempt to load with CORS
3441
3442 img.crossOrigin = "anonymous";
3443 imageObj = images[src] = {
3444 img: img
3445 };
3446 images.numTotal++;
3447 setImageLoadHandlers(img, imageObj);
3448 img.src = src;
3449
3450 // work around for https://bugs.webkit.org/show_bug.cgi?id=80028
3451 img.customComplete = function () {
3452 if (!this.img.complete) {
3453 this.timer = window.setTimeout(this.img.customComplete, 100);
3454 } else {
3455 this.img.onerror();
3456 }
3457 }.bind(imageObj);
3458 img.customComplete();
3459
3460 } else if ( options.proxy ) {
3461 imageObj = images[src] = {
3462 img: img
3463 };
3464 images.numTotal++;
3465 proxyGetImage( src, img, imageObj );
3466 }
3467 }
3468
3469},
3470cleanupDOM: function(cause) {
3471 var img, src;
3472 if (!images.cleanupDone) {
3473 if (cause && typeof cause === "string") {
3474 h2clog("html2canvas: Cleanup because: " + cause);
3475 } else {
3476 h2clog("html2canvas: Cleanup after timeout: " + options.timeout + " ms.");
3477 }
3478
3479 for (src in images) {
3480 if (images.hasOwnProperty(src)) {
3481 img = images[src];
3482 if (typeof img === "object" && img.callbackname && img.succeeded === undefined) {
3483 // cancel proxy image request
3484 window[img.callbackname] = undefined; // to work with IE<9 // NOTE: that the undefined callback property-name still exists on the window object (for IE<9)
3485 try {
3486 delete window[img.callbackname]; // for all browser that support this
3487 } catch(ex) {}
3488 if (img.script && img.script.parentNode) {
3489 img.script.setAttribute("src", "about:blank"); // try to cancel running request
3490 img.script.parentNode.removeChild(img.script);
3491 }
3492 images.numLoaded++;
3493 images.numFailed++;
3494 h2clog("html2canvas: Cleaned up failed img: '" + src + "' Steps: " + images.numLoaded + " / " + images.numTotal);
3495 }
3496 }
3497}
3498
3499 // cancel any pending requests
3500 if(window.stop !== undefined) {
3501 window.stop();
3502 } else if(document.execCommand !== undefined) {
3503 document.execCommand("Stop", false);
3504 }
3505 if (document.close !== undefined) {
3506 document.close();
3507 }
3508 images.cleanupDone = true;
3509 if (!(cause && typeof cause === "string")) {
3510 start();
3511 }
3512 }
3513},
3514
3515renderingDone: function() {
3516 if (timeoutTimer) {
3517 window.clearTimeout(timeoutTimer);
3518 }
3519}
3520};
3521
3522if (options.timeout > 0) {
3523 timeoutTimer = window.setTimeout(methods.cleanupDOM, options.timeout);
3524}
3525
3526h2clog('html2canvas: Preload starts: finding background-images');
3527images.firstRun = true;
3528
3529getImages(element);
3530
3531h2clog('html2canvas: Preload: Finding images');
3532 // load <img> images
3533 for (i = 0; i < imgLen; i+=1){
3534 methods.loadImage( domImages[i].getAttribute( "src" ) );
3535 }
3536
3537 images.firstRun = false;
3538 h2clog('html2canvas: Preload: Done.');
3539 if ( images.numTotal === images.numLoaded ) {
3540 start();
3541 }
3542
3543 return methods;
3544
3545};
3546function h2cRenderContext(width, height) {
3547 var storage = [];
3548 return {
3549 storage: storage,
3550 width: width,
3551 height: height,
3552 clip: function() {
3553 storage.push({
3554 type: "function",
3555 name: "clip",
3556 'arguments': arguments
3557 });
3558 },
3559 translate: function() {
3560 storage.push({
3561 type: "function",
3562 name: "translate",
3563 'arguments': arguments
3564 });
3565 },
3566 fill: function() {
3567 storage.push({
3568 type: "function",
3569 name: "fill",
3570 'arguments': arguments
3571 });
3572 },
3573 save: function() {
3574 storage.push({
3575 type: "function",
3576 name: "save",
3577 'arguments': arguments
3578 });
3579 },
3580 restore: function() {
3581 storage.push({
3582 type: "function",
3583 name: "restore",
3584 'arguments': arguments
3585 });
3586 },
3587 fillRect: function () {
3588 storage.push({
3589 type: "function",
3590 name: "fillRect",
3591 'arguments': arguments
3592 });
3593 },
3594 createPattern: function() {
3595 storage.push({
3596 type: "function",
3597 name: "createPattern",
3598 'arguments': arguments
3599 });
3600 },
3601 drawShape: function() {
3602
3603 var shape = [];
3604
3605 storage.push({
3606 type: "function",
3607 name: "drawShape",
3608 'arguments': shape
3609 });
3610
3611 return {
3612 moveTo: function() {
3613 shape.push({
3614 name: "moveTo",
3615 'arguments': arguments
3616 });
3617 },
3618 lineTo: function() {
3619 shape.push({
3620 name: "lineTo",
3621 'arguments': arguments
3622 });
3623 },
3624 arcTo: function() {
3625 shape.push({
3626 name: "arcTo",
3627 'arguments': arguments
3628 });
3629 },
3630 bezierCurveTo: function() {
3631 shape.push({
3632 name: "bezierCurveTo",
3633 'arguments': arguments
3634 });
3635 },
3636 quadraticCurveTo: function() {
3637 shape.push({
3638 name: "quadraticCurveTo",
3639 'arguments': arguments
3640 });
3641 }
3642 };
3643
3644 },
3645 drawImage: function () {
3646 storage.push({
3647 type: "function",
3648 name: "drawImage",
3649 'arguments': arguments
3650 });
3651 },
3652 fillText: function () {
3653 storage.push({
3654 type: "function",
3655 name: "fillText",
3656 'arguments': arguments
3657 });
3658 },
3659 setVariable: function (variable, value) {
3660 storage.push({
3661 type: "variable",
3662 name: variable,
3663 'arguments': value
3664 });
3665 }
3666 };
3667}
3668_html2canvas.Renderer = function(parseQueue, options){
3669
3670 function createRenderQueue(parseQueue) {
3671 var queue = [];
3672
3673 var sortZ = function(zStack){
3674 var subStacks = [],
3675 stackValues = [];
3676
3677 zStack.children.forEach(function(stackChild) {
3678 if (stackChild.children && stackChild.children.length > 0){
3679 subStacks.push(stackChild);
3680 stackValues.push(stackChild.zindex);
3681 } else {
3682 queue.push(stackChild);
3683 }
3684 });
3685
3686 stackValues.sort(function(a, b) {
3687 return a - b;
3688 });
3689
3690 stackValues.forEach(function(zValue) {
3691 var index;
3692
3693 subStacks.some(function(stack, i){
3694 index = i;
3695 return (stack.zindex === zValue);
3696 });
3697 sortZ(subStacks.splice(index, 1)[0]);
3698
3699 });
3700 };
3701
3702 sortZ(parseQueue.zIndex);
3703
3704 return queue;
3705 }
3706
3707 function getRenderer(rendererName) {
3708 var renderer;
3709
3710 if (typeof options.renderer === "string" && _html2canvas.Renderer[rendererName] !== undefined) {
3711 renderer = _html2canvas.Renderer[rendererName](options);
3712 } else if (typeof rendererName === "function") {
3713 renderer = rendererName(options);
3714 } else {
3715 throw new Error("Unknown renderer");
3716 }
3717
3718 if ( typeof renderer !== "function" ) {
3719 throw new Error("Invalid renderer defined");
3720 }
3721 return renderer;
3722 }
3723
3724 return getRenderer(options.renderer)(parseQueue, options, document, createRenderQueue(parseQueue), _html2canvas);
3725};
3726
3727_html2canvas.Util.Support = function (options, doc) {
3728
3729 function supportSVGRendering() {
3730 var img = new Image(),
3731 canvas = doc.createElement("canvas"),
3732 ctx = (canvas.getContext === undefined) ? false : canvas.getContext("2d");
3733 if (ctx === false) {
3734 return false;
3735 }
3736 canvas.width = canvas.height = 10;
3737 img.src = [
3738 "data:image/svg+xml,",
3739 "<svg xmlns='http://www.w3.org/2000/svg' width='10' height='10'>",
3740 "<foreignObject width='10' height='10'>",
3741 "<div xmlns='http://www.w3.org/1999/xhtml' style='width:10;height:10;'>",
3742 "sup",
3743 "</div>",
3744 "</foreignObject>",
3745 "</svg>"
3746 ].join("");
3747 try {
3748 ctx.drawImage(img, 0, 0);
3749 canvas.toDataURL();
3750 } catch(e) {
3751 return false;
3752 }
3753 h2clog('html2canvas: Parse: SVG powered rendering available');
3754 return true;
3755 }
3756
3757 // Test whether we can use ranges to measure bounding boxes
3758 // Opera doesn't provide valid bounds.height/bottom even though it supports the method.
3759
3760 function supportRangeBounds() {
3761 var r, testElement, rangeBounds, rangeHeight, support = false;
3762
3763 if (doc.createRange) {
3764 r = doc.createRange();
3765 if (r.getBoundingClientRect) {
3766 testElement = doc.createElement('boundtest');
3767 testElement.style.height = "123px";
3768 testElement.style.display = "block";
3769 doc.body.appendChild(testElement);
3770
3771 r.selectNode(testElement);
3772 rangeBounds = r.getBoundingClientRect();
3773 rangeHeight = rangeBounds.height;
3774
3775 if (rangeHeight === 123) {
3776 support = true;
3777 }
3778 doc.body.removeChild(testElement);
3779 }
3780 }
3781
3782 return support;
3783 }
3784
3785 return {
3786 rangeBounds: supportRangeBounds(),
3787 svgRendering: options.svgRendering && supportSVGRendering()
3788 };
3789};
3790window.html2canvas = function(elements, opts) {
3791 elements = (elements.length) ? elements : [elements];
3792 var queue,
3793 canvas,
3794 options = {
3795 // general
3796 logging: false,
3797 elements: elements,
3798 background: "#fff",
3799
3800 // preload options
3801 proxy: null,
3802 timeout: 0, // no timeout
3803 useCORS: false, // try to load images as CORS (where available), before falling back to proxy
3804 allowTaint: false, // whether to allow images to taint the canvas, won't need proxy if set to true
3805
3806 // parse options
3807 svgRendering: false, // use svg powered rendering where available (FF11+)
3808 ignoreElements: "IFRAME|OBJECT|PARAM",
3809 useOverflow: true,
3810 letterRendering: false,
3811 chinese: false,
3812
3813 // render options
3814
3815 width: null,
3816 height: null,
3817 taintTest: true, // do a taint test with all images before applying to canvas
3818 renderer: "Canvas"
3819};
3820
3821options = _html2canvas.Util.Extend(opts, options);
3822
3823_html2canvas.logging = options.logging;
3824options.complete = function( images ) {
3825
3826 if (typeof options.onpreloaded === "function") {
3827 if ( options.onpreloaded( images ) === false ) {
3828 return;
3829 }
3830 }
3831 queue = _html2canvas.Parse( images, options );
3832
3833 if (typeof options.onparsed === "function") {
3834 if ( options.onparsed( queue ) === false ) {
3835 return;
3836 }
3837 }
3838
3839 canvas = _html2canvas.Renderer( queue, options );
3840
3841 if (typeof options.onrendered === "function") {
3842 options.onrendered( canvas );
3843 }
3844
3845
3846};
3847
3848 // for pages without images, we still want this to be async, i.e. return methods before executing
3849 window.setTimeout( function(){
3850 _html2canvas.Preload( options );
3851 }, 0 );
3852
3853 return {
3854 render: function( queue, opts ) {
3855 return _html2canvas.Renderer( queue, _html2canvas.Util.Extend(opts, options) );
3856 },
3857 parse: function( images, opts ) {
3858 return _html2canvas.Parse( images, _html2canvas.Util.Extend(opts, options) );
3859 },
3860 preload: function( opts ) {
3861 return _html2canvas.Preload( _html2canvas.Util.Extend(opts, options) );
3862 },
3863 log: h2clog
3864 };
3865};
3866
3867window.html2canvas.log = h2clog; // for renderers
3868window.html2canvas.Renderer = {
3869 Canvas: undefined // We are assuming this will be used
3870};
3871_html2canvas.Renderer.Canvas = function(options) {
3872
3873 options = options || {};
3874
3875 var doc = document,
3876 safeImages = [],
3877 testCanvas = document.createElement("canvas"),
3878 testctx = testCanvas.getContext("2d"),
3879 canvas = options.canvas || doc.createElement('canvas');
3880
3881
3882 function createShape(ctx, args) {
3883 ctx.beginPath();
3884 args.forEach(function(arg) {
3885 ctx[arg.name].apply(ctx, arg['arguments']);
3886 });
3887 ctx.closePath();
3888 }
3889
3890 function safeImage(item) {
3891 if (safeImages.indexOf(item['arguments'][0].src ) === -1) {
3892 testctx.drawImage(item['arguments'][0], 0, 0);
3893 try {
3894 testctx.getImageData(0, 0, 1, 1);
3895 } catch(e) {
3896 testCanvas = doc.createElement("canvas");
3897 testctx = testCanvas.getContext("2d");
3898 return false;
3899 }
3900 safeImages.push(item['arguments'][0].src);
3901 }
3902 return true;
3903 }
3904
3905 function isTransparent(backgroundColor) {
3906 return (backgroundColor === "transparent" || backgroundColor === "rgba(0, 0, 0, 0)");
3907 }
3908
3909 function renderItem(ctx, item) {
3910 switch(item.type){
3911 case "variable":
3912 ctx[item.name] = item['arguments'];
3913 break;
3914 case "function":
3915 if (item.name === "createPattern") {
3916 if (item['arguments'][0].width > 0 && item['arguments'][0].height > 0) {
3917 try {
3918 ctx.fillStyle = ctx.createPattern(item['arguments'][0], "repeat");
3919 }
3920 catch(e) {
3921 h2clog("html2canvas: Renderer: Error creating pattern", e.message);
3922 }
3923 }
3924 } else if (item.name === "drawShape") {
3925 createShape(ctx, item['arguments']);
3926 } else if (item.name === "drawImage") {
3927 if (item['arguments'][8] > 0 && item['arguments'][7] > 0) {
3928 if (!options.taintTest || (options.taintTest && safeImage(item))) {
3929 ctx.drawImage.apply( ctx, item['arguments'] );
3930 }
3931 }
3932 } else {
3933 ctx[item.name].apply(ctx, item['arguments']);
3934 }
3935 break;
3936 }
3937 }
3938
3939 return function(zStack, options, doc, queue, _html2canvas) {
3940
3941 var ctx = canvas.getContext("2d"),
3942 storageContext,
3943 i,
3944 queueLen,
3945 newCanvas,
3946 bounds,
3947 fstyle;
3948
3949 canvas.width = canvas.style.width = options.width || zStack.ctx.width;
3950 canvas.height = canvas.style.height = options.height || zStack.ctx.height;
3951
3952 fstyle = ctx.fillStyle;
3953 ctx.fillStyle = (isTransparent(zStack.backgroundColor) && options.background !== undefined) ? options.background : zStack.backgroundColor;
3954 ctx.fillRect(0, 0, canvas.width, canvas.height);
3955 ctx.fillStyle = fstyle;
3956
3957
3958 if ( options.svgRendering && zStack.svgRender !== undefined ) {
3959 // TODO: enable async rendering to support this
3960 ctx.drawImage( zStack.svgRender, 0, 0 );
3961 } else {
3962 for ( i = 0, queueLen = queue.length; i < queueLen; i+=1 ) {
3963 storageContext = queue.splice(0, 1)[0];
3964 storageContext.canvasPosition = storageContext.canvasPosition || {};
3965
3966 // set common settings for canvas
3967 ctx.textBaseline = "bottom";
3968
3969 if (storageContext.clip){
3970 ctx.save();
3971 ctx.beginPath();
3972 // console.log(storageContext);
3973 ctx.rect(storageContext.clip.left, storageContext.clip.top, storageContext.clip.width, storageContext.clip.height);
3974 ctx.clip();
3975 }
3976
3977 if (storageContext.ctx.storage) {
3978 storageContext.ctx.storage.forEach(renderItem.bind(null, ctx));
3979 }
3980
3981 if (storageContext.clip){
3982 ctx.restore();
3983 }
3984 }
3985}
3986
3987h2clog("html2canvas: Renderer: Canvas renderer done - returning canvas obj");
3988
3989queueLen = options.elements.length;
3990
3991if (queueLen === 1) {
3992 if (typeof options.elements[0] === "object" && options.elements[0].nodeName !== "BODY") {
3993 // crop image to the bounds of selected (single) element
3994 bounds = _html2canvas.Util.Bounds(options.elements[0]);
3995 newCanvas = doc.createElement('canvas');
3996 newCanvas.width = bounds.width;
3997 newCanvas.height = bounds.height;
3998 ctx = newCanvas.getContext("2d");
3999
4000 ctx.drawImage(canvas, bounds.left, bounds.top, bounds.width, bounds.height, 0, 0, bounds.width, bounds.height);
4001 canvas = null;
4002 return newCanvas;
4003 }
4004}
4005
4006return canvas;
4007};
4008};
4009})(window,document);
4010
4011/**
4012 @license html2canvas v0.34 <http://html2canvas.hertzen.com>
4013 Copyright (c) 2011 Niklas von Hertzen. All rights reserved.
4014 http://www.twitter.com/niklasvh
4015
4016 Released under MIT License
4017 */
4018/*
4019 * jQuery helper plugin for examples and tests
4020 */
4021 (function( $ ){
4022 $.fn.html2canvas = function(options) {
4023 if (options && options.profile && window.console && window.console.profile) {
4024 console.profile();
4025 }
4026 var date = new Date(),
4027 html2obj,
4028 $message = null,
4029 timeoutTimer = false,
4030 timer = date.getTime();
4031 options = options || {};
4032
4033 options.onrendered = options.onrendered || function( canvas ) {
4034 var $canvas = $(canvas),
4035 finishTime = new Date();
4036
4037 if (options && options.profile && window.console && window.console.profileEnd) {
4038 console.profileEnd();
4039 }
4040 $canvas.css({
4041 position: 'absolute',
4042 left: 0,
4043 top: 0
4044 }).appendTo(document.body);
4045 $canvas.siblings().toggle();
4046
4047 $(window).click(function(){
4048 $canvas.toggle().siblings().toggle();
4049 throwMessage("Canvas Render " + ($canvas.is(':visible') ? "visible" : "hidden"));
4050 });
4051 throwMessage('Screenshot created in '+ ((finishTime.getTime()-timer)) + " ms<br />",4000);
4052
4053 // test if canvas is read-able
4054 try {
4055 $canvas[0].toDataURL();
4056 } catch(e) {
4057 if ($canvas[0].nodeName.toLowerCase() === "canvas") {
4058 // TODO, maybe add a bit less offensive way to present this, but still something that can easily be noticed
4059 alert("Canvas is tainted, unable to read data");
4060 }
4061 }
4062 };
4063
4064 html2obj = html2canvas(this, options);
4065
4066 function throwMessage(msg,duration){
4067 window.clearTimeout(timeoutTimer);
4068 timeoutTimer = window.setTimeout(function(){
4069 $message.fadeOut(function(){
4070 $message.remove();
4071 $message = null;
4072 });
4073 },duration || 2000);
4074 if ($message)
4075 $message.remove();
4076 $message = $('<div />').html(msg).css({
4077 margin:0,
4078 padding:10,
4079 background: "#000",
4080 opacity:0.7,
4081 position:"fixed",
4082 top:10,
4083 right:10,
4084 fontFamily: 'Tahoma',
4085 color:'#fff',
4086 fontSize:12,
4087 borderRadius:12,
4088 width:'auto',
4089 height:'auto',
4090 textAlign:'center',
4091 textDecoration:'none',
4092 display:'none'
4093 }).appendTo(document.body).fadeIn();
4094 html2obj.log(msg);
4095 }
4096 };
4097})( jQuery );
4098
4099
4100jQuery(function($){
4101 var $button = $('<a href="#" id="un-button" class="un-button" />Feedback').appendTo($('body'));
4102 var property;
4103 $button.text(usernoiseButton.text);
4104 $button.addClass(usernoiseButton['class']);
4105 $button.attr('style', usernoiseButton.style);
4106 $button.attr('rel', 'website');
4107 if ($.browser && $.browser.msie && $.browser.version == '7.0'){
4108 if ($button.is('.un-left') || $button.is('.un-right'))
4109 $button.css('margin-top', '-' + $button.width() / 2 + "px");
4110 $button.addClass('ie7');
4111 } else if ($.browser && $.browser.msie && $.browser.version == '8.0'){
4112 if ($button.is('.un-right')){
4113 $button.css('right', "-" + $button.outerWidth() + "px");
4114 }
4115 if ($button.is('.un-left') || $button.is('.un-right'))
4116 $button.css('margin-top', '-' + $button.width() / 2 + "px");
4117 $button.addClass('ie8');
4118 } else {
4119 $button.addClass('css3');
4120 }
4121
4122 if ($button.is('.un-bottom') || $button.is('.un-top'))
4123 $button.css('margin-left', "-" + ($('#un-button').width() / 2) + "px");
4124 if ($button.is('.un-left'))
4125 property = 'left';
4126 else if ($button.is('.un-right'))
4127 property = 'right';
4128 else if ($button.is('.un-bottom'))
4129 property = 'bottom';
4130 else
4131 property = 'top';
4132
4133 if ($button.is('.un-left.css3'))
4134 $button.css('margin-top', ($button.width() / 2) + "px");
4135 if ($button.is('.un-right.css3')){
4136 $button.css('margin-top', "-" + ($button.width() / 2) + "px");
4137 }
4138 var propOnStart = {};
4139 var propOnIn = {opacity: 1};
4140 var propOnOut = {opacity: 0.96};
4141 propOnStart[property] = '+=40px';
4142 propOnIn[property] = '+=3px';
4143 propOnOut[property] = '-=3px';
4144 $button.animate(propOnStart).hover(
4145 function(){$button.animate(propOnIn, 100)},
4146 function(){$button.animate(propOnOut, 100)});
4147
4148
4149 $('body').on('click', '.un-button', function() {
4150 $.ajax({
4151 'url': '/weblife_custom/feedback/index.php?type='+$(this).attr('rel'),
4152 'beforeSend': function() {
4153
4154
4155 $('<div id="un-overlay"></div>').appendTo($('body'));
4156 $('<div id="un-loading"></div>').appendTo($('body'));
4157 },
4158 'success' : function(data) {
4159 $('#un-loading').hide();
4160 $('<div id="un-iframe"></div>').appendTo($('body'));
4161 $('#un-iframe').html(data);
4162 }
4163 });
4164 });
4165
4166 $('body').on('click', 'a#addscreenshot', function() {
4167 $('#un-overlay').hide();
4168 $('#un-iframe').hide();
4169
4170 $('body').html2canvas({
4171 onrendered: function (canvas) {
4172 //Set hidden field's value to image data (base-64 strin//g)
4173 $('<input type="hidden" id="image" name="image" value="'+canvas.toDataURL("image/jpeg",0.7)+'"/>').appendTo($('#thescreenshot'));
4174 $('a#addscreenshot').hide();
4175 $('<div class="alert alert-success" style="clear: both;margin: 10px 0px 15px 0px !important;float: left;width: 100%;">Screenshot added!</div>').appendTo($('#thescreenshot'));
4176 }
4177 });
4178
4179 setTimeout(function() {
4180 $('#un-overlay').show();
4181 $('#un-iframe').show();
4182 },100);
4183 });
4184
4185 $('body').on('click', 'a#usernoisesubmit', function() {
4186 $('.un-feedback-errors-wrapper').hide();
4187 $('.un-errors').html(' ');
4188 var error = 0;
4189 if ($('#un-title').val() == '') { error = 1; $('.un-errors').append('<p>Please enter your title</p>');}
4190 if ($('#un-description').val() == '') { error = 1; $('.un-errors').append('<p>Please enter your description</p>');}
4191 if ($('#un-name').val() == '') { error = 1; $('.un-errors').append('<p>Please enter your name</p>');}
4192
4193 var re = /\S+@\S+\.\S+/;
4194 if (!re.test($('#un-email').val())) { error = 1; $('.un-errors').append('<p>Please enter correct email</p>');}
4195
4196 if (error == 1) {
4197 $('.un-feedback-errors-wrapper').show();
4198 return;
4199 }
4200
4201 $('#theusernoiseform').ajaxSubmit({
4202 beforeSubmit: function() {
4203 $('#un-feedback-form-wrapper').hide();
4204 $('#un-formloading').show();
4205 },
4206 success: function(response) {
4207 $('#un-formloading').hide();
4208 $('#un-thankyou').show();
4209 setTimeout(function() {
4210 $('#un-overlay').remove();
4211 $('#un-iframe').remove();
4212 $('#un-loading').remove();
4213 },1000);
4214 }
4215 });
4216 });
4217
4218 $('body').on('click', 'a#un-feedback-close, a#window-close, #un-iframe', function(){
4219 $('#un-overlay').remove();
4220 $('#un-iframe').remove();
4221 $('#un-loading').remove();
4222 })
4223
4224
4225 $('body').on('click', '#viewport', function(event) {
4226 event.stopPropagation();
4227 });
4228
4229
4230});
4231/*!
4232 * headroom.js v0.9.4 - Give your page some headroom. Hide your header until you need it
4233 * Copyright (c) 2017 Nick Williams - http://wicky.nillia.ms/headroom.js
4234 * License: MIT
4235 */
4236
4237 !(function(a, b) {
4238 "use strict";
4239 "function" == typeof define && define.amd
4240 ? define([], b)
4241 : "object" == typeof exports
4242 ? (module.exports = b())
4243 : (a.Headroom = b());
4244 })(this, function() {
4245 "use strict";
4246 function a(a) {
4247 (this.callback = a), (this.ticking = !1);
4248 }
4249 function b(a) {
4250 return a && "undefined" != typeof window && (a === window || a.nodeType);
4251 }
4252 function c(a) {
4253 if (arguments.length <= 0)
4254 throw new Error("Missing arguments in extend function");
4255 var d,
4256 e,
4257 f = a || {};
4258 for (e = 1; e < arguments.length; e++) {
4259 var g = arguments[e] || {};
4260 for (d in g)
4261 "object" != typeof f[d] || b(f[d])
4262 ? (f[d] = f[d] || g[d])
4263 : (f[d] = c(f[d], g[d]));
4264 }
4265 return f;
4266 }
4267 function d(a) {
4268 return a === Object(a) ? a : { down: a, up: a };
4269 }
4270 function e(a, b) {
4271 (b = c(b, e.options)),
4272 (this.lastKnownScrollY = 0),
4273 (this.elem = a),
4274 (this.tolerance = d(b.tolerance)),
4275 (this.classes = b.classes),
4276 (this.offset = b.offset),
4277 (this.scroller = b.scroller),
4278 (this.initialised = !1),
4279 (this.onPin = b.onPin),
4280 (this.onUnpin = b.onUnpin),
4281 (this.onTop = b.onTop),
4282 (this.onNotTop = b.onNotTop),
4283 (this.onBottom = b.onBottom),
4284 (this.onNotBottom = b.onNotBottom);
4285 }
4286 var f = {
4287 bind: !!function() {}.bind,
4288 classList: "classList" in document.documentElement,
4289 rAF: !!(
4290 window.requestAnimationFrame ||
4291 window.webkitRequestAnimationFrame ||
4292 window.mozRequestAnimationFrame
4293 )
4294 };
4295 return (
4296 (window.requestAnimationFrame =
4297 window.requestAnimationFrame ||
4298 window.webkitRequestAnimationFrame ||
4299 window.mozRequestAnimationFrame),
4300 (a.prototype = {
4301 constructor: a,
4302 update: function() {
4303 this.callback && this.callback(), (this.ticking = !1);
4304 },
4305 requestTick: function() {
4306 this.ticking ||
4307 (requestAnimationFrame(
4308 this.rafCallback || (this.rafCallback = this.update.bind(this))
4309 ),
4310 (this.ticking = !0));
4311 },
4312 handleEvent: function() {
4313 this.requestTick();
4314 }
4315 }),
4316 (e.prototype = {
4317 constructor: e,
4318 init: function() {
4319 if (e.cutsTheMustard)
4320 return (
4321 (this.debouncer = new a(this.update.bind(this))),
4322 this.elem.classList.add(this.classes.initial),
4323 setTimeout(this.attachEvent.bind(this), 100),
4324 this
4325 );
4326 },
4327 destroy: function() {
4328 var a = this.classes;
4329 this.initialised = !1;
4330 for (var b in a)
4331 a.hasOwnProperty(b) && this.elem.classList.remove(a[b]);
4332 this.scroller.removeEventListener("scroll", this.debouncer, !1);
4333 },
4334 attachEvent: function() {
4335 this.initialised ||
4336 ((this.lastKnownScrollY = this.getScrollY()),
4337 (this.initialised = !0),
4338 this.scroller.addEventListener("scroll", this.debouncer, !1),
4339 this.debouncer.handleEvent());
4340 },
4341 unpin: function() {
4342 var a = this.elem.classList,
4343 b = this.classes;
4344 (!a.contains(b.pinned) && a.contains(b.unpinned)) ||
4345 (a.add(b.unpinned),
4346 a.remove(b.pinned),
4347 this.onUnpin && this.onUnpin.call(this));
4348 },
4349 pin: function() {
4350 var a = this.elem.classList,
4351 b = this.classes;
4352 a.contains(b.unpinned) &&
4353 (a.remove(b.unpinned),
4354 a.add(b.pinned),
4355 this.onPin && this.onPin.call(this));
4356 },
4357 top: function() {
4358 var a = this.elem.classList,
4359 b = this.classes;
4360 a.contains(b.top) ||
4361 (a.add(b.top),
4362 a.remove(b.notTop),
4363 this.onTop && this.onTop.call(this));
4364 },
4365 notTop: function() {
4366 var a = this.elem.classList,
4367 b = this.classes;
4368 a.contains(b.notTop) ||
4369 (a.add(b.notTop),
4370 a.remove(b.top),
4371 this.onNotTop && this.onNotTop.call(this));
4372 },
4373 bottom: function() {
4374 var a = this.elem.classList,
4375 b = this.classes;
4376 a.contains(b.bottom) ||
4377 (a.add(b.bottom),
4378 a.remove(b.notBottom),
4379 this.onBottom && this.onBottom.call(this));
4380 },
4381 notBottom: function() {
4382 var a = this.elem.classList,
4383 b = this.classes;
4384 a.contains(b.notBottom) ||
4385 (a.add(b.notBottom),
4386 a.remove(b.bottom),
4387 this.onNotBottom && this.onNotBottom.call(this));
4388 },
4389 getScrollY: function() {
4390 return void 0 !== this.scroller.pageYOffset
4391 ? this.scroller.pageYOffset
4392 : void 0 !== this.scroller.scrollTop
4393 ? this.scroller.scrollTop
4394 : (
4395 document.documentElement ||
4396 document.body.parentNode ||
4397 document.body
4398 ).scrollTop;
4399 },
4400 getViewportHeight: function() {
4401 return (
4402 window.innerHeight ||
4403 document.documentElement.clientHeight ||
4404 document.body.clientHeight
4405 );
4406 },
4407 getElementPhysicalHeight: function(a) {
4408 return Math.max(a.offsetHeight, a.clientHeight);
4409 },
4410 getScrollerPhysicalHeight: function() {
4411 return this.scroller === window || this.scroller === document.body
4412 ? this.getViewportHeight()
4413 : this.getElementPhysicalHeight(this.scroller);
4414 },
4415 getDocumentHeight: function() {
4416 var a = document.body,
4417 b = document.documentElement;
4418 return Math.max(
4419 a.scrollHeight,
4420 b.scrollHeight,
4421 a.offsetHeight,
4422 b.offsetHeight,
4423 a.clientHeight,
4424 b.clientHeight
4425 );
4426 },
4427 getElementHeight: function(a) {
4428 return Math.max(a.scrollHeight, a.offsetHeight, a.clientHeight);
4429 },
4430 getScrollerHeight: function() {
4431 return this.scroller === window || this.scroller === document.body
4432 ? this.getDocumentHeight()
4433 : this.getElementHeight(this.scroller);
4434 },
4435 isOutOfBounds: function(a) {
4436 var b = a < 0,
4437 c = a + this.getScrollerPhysicalHeight() > this.getScrollerHeight();
4438 return b || c;
4439 },
4440 toleranceExceeded: function(a, b) {
4441 return Math.abs(a - this.lastKnownScrollY) >= this.tolerance[b];
4442 },
4443 shouldUnpin: function(a, b) {
4444 var c = a > this.lastKnownScrollY,
4445 d = a >= this.offset;
4446 return c && d && b;
4447 },
4448 shouldPin: function(a, b) {
4449 var c = a < this.lastKnownScrollY,
4450 d = a <= this.offset;
4451 return (c && b) || d;
4452 },
4453 update: function() {
4454 var a = this.getScrollY(),
4455 b = a > this.lastKnownScrollY ? "down" : "up",
4456 c = this.toleranceExceeded(a, b);
4457 this.isOutOfBounds(a) ||
4458 (a <= this.offset ? this.top() : this.notTop(),
4459 a + this.getViewportHeight() >= this.getScrollerHeight()
4460 ? this.bottom()
4461 : this.notBottom(),
4462 this.shouldUnpin(a, c)
4463 ? this.unpin()
4464 : this.shouldPin(a, c) && this.pin(),
4465 (this.lastKnownScrollY = a));
4466 }
4467 }),
4468(e.options = {
4469 tolerance: { up: 0, down: 0 },
4470 offset: 0,
4471 scroller: window,
4472 classes: {
4473 pinned: "headroom--pinned",
4474 unpinned: "headroom--unpinned",
4475 top: "headroom--top",
4476 notTop: "headroom--not-top",
4477 bottom: "headroom--bottom",
4478 notBottom: "headroom--not-bottom",
4479 initial: "headroom"
4480 }
4481}),
4482(e.cutsTheMustard =
4483 "undefined" != typeof f && f.rAF && f.bind && f.classList),
4484e
4485);
4486});
4487
4488
4489(function() {
4490 var readingIndicator = document.getElementsByClassName('js-reading-progressbar')[0],
4491 readingIndicatorContent = document.getElementsByClassName('js-reading-content')[0];
4492
4493 if( readingIndicator && readingIndicatorContent) {
4494 var progressInfo = [],
4495 progressEvent = false,
4496 progressFallback = readingIndicator.getElementsByClassName('js-reading-progressbar__fallback')[0],
4497 progressIsSupported = 'value' in readingIndicator;
4498
4499 progressInfo['height'] = readingIndicatorContent.offsetHeight;
4500 progressInfo['top'] = readingIndicatorContent.getBoundingClientRect().top;
4501 progressInfo['window'] = window.innerHeight;
4502 progressInfo['class'] = 'reading-progressbar--is-active';
4503
4504 //init indicator
4505 setProgressIndicator();
4506 //listen to the window scroll event - update progress
4507 window.addEventListener('scroll', function(event){
4508 if(progressEvent) return;
4509 progressEvent = true;
4510 (!window.requestAnimationFrame) ? setTimeout(function(){setProgressIndicator();}, 250) : window.requestAnimationFrame(setProgressIndicator);
4511 });
4512 // listen to window resize - update progress
4513 window.addEventListener('resize', function(event){
4514 if(progressEvent) return;
4515 progressEvent = true;
4516 (!window.requestAnimationFrame) ? setTimeout(function(){resetProgressIndicator();}, 250) : window.requestAnimationFrame(resetProgressIndicator);
4517 });
4518
4519 function setProgressIndicator() {
4520 progressInfo['top'] = readingIndicatorContent.getBoundingClientRect().top;
4521 if(progressInfo['height'] <= progressInfo['window']) {
4522 // short content - hide progress indicator
4523 Util.removeClass(readingIndicator, progressInfo['class']);
4524 progressEvent = false;
4525 return;
4526 }
4527 // get new progress and update element
4528 Util.addClass(readingIndicator, progressInfo['class']);
4529 var value = (progressInfo['top'] >= 0) ? 0 : 100*(0 - progressInfo['top'])/(progressInfo['height'] - progressInfo['window']);
4530 readingIndicator.setAttribute('value', value);
4531 if(!progressIsSupported && progressFallback) progressFallback.style.width = value+'%';
4532 progressEvent = false;
4533 };
4534
4535 function resetProgressIndicator() {
4536 progressInfo['height'] = readingIndicatorContent.offsetHeight;
4537 progressInfo['window'] = window.innerHeight;
4538 setProgressIndicator();
4539 };
4540 }
4541}());
4542$(document).ready(function() {
4543 $(".checkout-btn").click(function() {
4544 $("#wizard").show();
4545 $('#example-form').show();
4546 $(".checkout-btn").hide();
4547 $(".viewcart-btn").show();
4548 $("#updatecart21321332").hide();
4549 });
4550});
4551$(document).ready(function() {
4552 $(".viewcart-btn").click(function() {
4553 $("#wizard").hide();
4554 $(".checkout-btn").show();
4555 $(".viewcart-btn").hide();
4556 $("#updatecart21321332").show();
4557 });
4558});
4559
4560$( document ).ready( function () {
4561 $( '#safebox' ).hide();
4562 $( '#safe-toggle' ).click( function () {
4563 $( '#safebox' ).toggle( 400 );
4564 return false;
4565 } );
4566 $( ".trigger" ).click( function () {
4567 $( ".trigger2" ).toggle( "fast" );
4568 $( this ).toggleClass( "active" );
4569 return false;
4570 } );
4571 $( ".trigger" ).click( function () {
4572 $( ".trigger3" ).toggle( "fast" );
4573 $( this ).toggleClass( "active" );
4574 return false;
4575 } );
4576 $( ".trigger" ).click( function () {
4577 $( ".panel" ).toggle( "fast" );
4578 $( this ).toggleClass( "active" );
4579 return false;
4580 } );
4581 $( ".toggle-cart" ).click( function () {
4582 $( "#un-button" ).toggle( "fast" );
4583 $( this ).toggleClass( "active" );
4584 return false;
4585 } );
4586} );
4587
4588
4589function addToCompare(prodid, prodname) {
4590 var url = "/my_ajax/ajax_add_to_compare_list?prodid=" + prodid;
4591 $.get(url, function(data) {
4592 $('#compare_link').html('<a href="javascript:openCompareList();">Product Compare </a>');
4593 if (document.getElementById("compare_total")) {
4594 document.getElementById("compare_total").innerHTML = data;
4595 $.growlUI(
4596 '<div class="latestincart_loader_compare"><img width="100" style="margin-bottom:0px" alt="" src="/images/clipboard@2x.png"></div><span class="compare_add">You\'ve added <span class="test">' +
4597 prodname +
4598 '</span> to the compare list!</span><div style="margin-top:20px; clear:left"><div class="row-fluid"><a class="btn span7" style="color:#333 !important; margin-bottom:5px; background-image: none; background:white" href="/shopping/comparelist">go to my compare list</a><a id="contshopping_ajax" class="btn span5" onclick="unblockthisone();" style="color:#333 !important; margin-bottom:5px; background-image: none; background:white " href="#continue">close</a></div></div>'
4599 );
4600 }
4601 });
4602}
4603function getCompareCount() {
4604 var url = "/my_ajax/ajax_add_to_compare_list";
4605 $.get(url, function(data) {
4606 if (document.getElementById("compare_total")) {
4607 document.getElementById("compare_total").innerHTML = data;
4608 }
4609 });
4610}
4611function addToWishlist(prodid, prodname) {
4612 var url = "/my_ajax/ajax_add_to_wishlist?prodid=" + prodid;
4613 $.get(url, function(data) {
4614 display_wishlist_count();
4615 $.growlUI(
4616 '<div class="latestincart_loader_compare"><img width="100" style="margin-bottom:0px" alt="" src="/images/clipboard@2x.png"></div><span class="compare_add">You\'ve added <span class="test">' +
4617 prodname +
4618 '</span> to the wish list!</span><div style="margin-top:20px; clear:left"><div class="row-fluid"><a class="btn span7" style="color:#333 !important; margin-bottom:5px; background-image: none; background:white" href="/customer/wishlist">go to my wish list</a><a id="contshopping_ajax3" class="btn span5" onclick="unblockthisone();" style="color:#333 !important; margin-bottom:5px; background-image: none; background:white " href="#continue">close</a></div></div>'
4619 );
4620 });
4621}
4622function display_wishlist_count() {
4623 var url = '/my_ajax/ajax_get_wishlist_count';
4624 $.get(url, function(data) {
4625 if (document.getElementById("wishlist_count"))
4626 document.getElementById('wishlist_count').innerHTML = data;
4627 });
4628}
4629getCompareCount();
4630
4631$(document).ready(function() {
4632 $("#content_show").click(function() {
4633 $("#content_hide").slideDown();
4634 });
4635 $("#show_signin").click(function() {
4636 $(".hiding").slideDown();
4637 $(".signin").addClass("well");
4638 $(".h3_text").addClass("hidden");
4639 $(".h3_user").removeClass("hidden");
4640 });
4641 $('body').on('click', '.ajax_cart_submit', function(e) {
4642 var dataid = $(this).attr('data-id');
4643 var minqty = $(this).attr('data-minimum-qty');
4644 // alert(minqty);
4645 var $L = 1200,
4646 //$menu_navigation = $('#main-nav'),
4647 //$cart_trigger = $('#cd-cart-trigger'),
4648 //$hamburger_icon = $('#cd-hamburger-menu'),
4649 $lateral_cart = $('#cd-cart'),
4650 $shadow_layer = $('#cd-shadow-layer');
4651 var idvar = 'id[' + dataid + ']';
4652 var qtyvar = 'qty[' + dataid + ']';
4653 var data = {};
4654 data[idvar] = dataid;
4655 data[qtyvar] = minqty;
4656 $.ajax({
4657 url: '/shopping/add_to_cart_bulk',
4658 data: data,
4659 success: function(response) {
4660 $('#my_cart').html(response);
4661 //show_mashup();
4662 toggle_panel_visibility($lateral_cart, $shadow_layer, $('body'));
4663 show_cart_items_in_tabarea();
4664 rename_btn_name();
4665 return false;
4666 }
4667 });
4668 e.preventDefault();
4669 });
4670 $("#catgprodlist_option").on("click", function() {
4671 var popt = $("#catgprodlist_option_start").val();
4672 if (popt == '1') {
4673 $("#catgprodlist_option_start").val(4);
4674 var chk = $("#catgprodlist_option:checked").length;
4675 var url = "/my_ajax/save_catgprod_list_option?opt=" + chk;
4676 $.get(url, function() {
4677 window.location.href = category_firstpage_url;
4678 });
4679 }
4680 });
4681});
4682
4683function submit_ajax_cart(e) {
4684 var dataid = $(this).attr('data-id');
4685 var idvar = 'id[' + dataid + ']';
4686 var qtyvar = 'qty[' + dataid + ']';
4687 var data = {};
4688 data[idvar] = dataid;
4689 data[qtyvar] = 1;
4690 $.ajax({
4691 url: '/shopping/add_to_cart_bulk',
4692 data: data,
4693 success: function(response) {
4694 $('#my_cart').html(response);
4695 $(".panel").addClass("fast");
4696 $(".panel").show(400);
4697 $("#trigger_id").addClass("active");
4698 return false;
4699 }
4700 });
4701 return true;
4702 e.preventDefault;
4703}
4704
4705function ajax_addtocart_fn_frm_popup(autoid) {
4706 var url = "/shopping/add_to_cart_bulk?tts=" + Math.random();
4707 prod_id_var = 'prod_id' + autoid;
4708 prod_id = document.getElementById(prod_id_var).value;
4709 parent_id_var = 'parent_id' + autoid;
4710 parent_id = document.getElementById(parent_id_var).value;
4711 var idvar = 'id[' + prod_id + ']';
4712 var qtyvar = 'qty[' + prod_id + ']';
4713 var data = {};
4714 data[idvar] = prod_id;
4715 data['prod_id'] = prod_id;
4716 data['parent_id'] = parent_id;
4717 qtyidvar = "qty" + prod_id;
4718 data[qtyvar] = document.getElementById(qtyidvar).value;
4719 if (document.getElementById(qtyidvar).value < 1) {
4720 alert('Enter Quantity');
4721 return false;
4722 }
4723 var spec1 = "specification_id1[" + prod_id + "]";
4724 var spec2 = "specification_id2[" + prod_id + "]";
4725 var spec3 = "specification_id3[" + prod_id + "]";
4726 data[spec1] = data[spec2] = data[spec3] = '';
4727 if (document.getElementById(spec1)) {
4728 data[spec1] = document.getElementById(spec1).value;
4729 if (document.getElementById(spec1).value <= 0) {
4730 alert("Please Choose all specifications");
4731 return false;
4732 }
4733 }
4734 if (document.getElementById(spec2)) {
4735 data[spec2] = document.getElementById(spec2).value;
4736 if (document.getElementById(spec2).value <= 0) {
4737 alert("Please Choose all specifications");
4738 return false;
4739 }
4740 }
4741 if (document.getElementById(spec3)) {
4742 data[spec3] = document.getElementById(spec3).value;
4743 if (document.getElementById(spec3).value <= 0) {
4744 alert("Please Choose all specifications");
4745 return false;
4746 }
4747 }
4748 has_spec_var = 'has_spec' + autoid;
4749 has_spec = document.getElementById(has_spec_var).value;
4750 data['has_spec'] = has_spec;
4751 $.ajax({
4752 url: '/shopping/add_to_cart_bulk',
4753 method: "get",
4754 data: data,
4755 success: function(data) {
4756 responseText = data;
4757 // alert(responseText);
4758 if (responseText == '11111') {
4759 alert(
4760 "Qty adjusted for stock in hand"); //if user orders more than available... (back order not enabled)
4761 //return false;
4762 } else if (responseText == '00000') {
4763 alert("Minimum Qty Requirements not met for this product group"); //for parent product...
4764 //return false;
4765 } else if (responseText == -1) {
4766 alert("Selected Product Combination does not exist");
4767 return false;
4768 } else if (responseText < -1) {
4769 var howmany = -1 * responseText;
4770 alert("Minimum Order Quantity for this Product is " + howmany);
4771 return false;
4772 }
4773 $('#my_cart').html(data);
4774 show_mashup();
4775 show_cart_items_in_tabarea();
4776 return false;
4777 }
4778 });
4779 parent.window.hs.close();
4780 return false;
4781}
4782
4783function show_price_ajax_popup(prodid) {
4784 var url = "/my_ajax/ajax_show_price?tts=" + Math.random();
4785 var spec1 = "specification_id1[" + prodid + "]";
4786 var spec2 = "specification_id2[" + prodid + "]";
4787 var spec3 = "specification_id3[" + prodid + "]";
4788 url += "&prodid=" + prodid;
4789 qtyidvar = "qty" + prodid;
4790 qty = document.getElementById(qtyidvar).value;
4791 url += "&qty=" + qty;
4792 if (document.getElementById(spec1) && !isNaN(document.getElementById(spec1).value)) url += "&spec1=" + document
4793 .getElementById(spec1).value;
4794 if (document.getElementById(spec2) && !isNaN(document.getElementById(spec2).value)) url += "&spec2=" + document
4795 .getElementById(spec2).value;
4796 if (document.getElementById(spec3) && !isNaN(document.getElementById(spec3).value)) url += "&spec3=" + document
4797 .getElementById(spec3).value;
4798 $.get(url, function(data) {
4799 // alert(data);
4800 price_area_str = "price_area" + prodid;
4801 if (document.getElementById(price_area_str))
4802 document.getElementById(price_area_str).innerHTML = data;
4803 });
4804}
4805
4806function popup_addcart(dataid, dataname) {
4807 var idvar = 'id[' + dataid + ']';
4808 var qtyvar = 'qty[' + dataid + ']';
4809 var data = {};
4810 data[idvar] = dataid;
4811 qtyidvar = "qty" + dataid;
4812 data[qtyvar] = document.getElementById(qtyidvar).value;
4813 $.ajax({
4814 url: '/shopping/add_to_cart_bulk',
4815 method: "get",
4816 data: data,
4817 success: function(data) {
4818 $('#my_cart').html(data);
4819 show_mashup();
4820 show_cart_items_in_tabarea();
4821 return false;
4822 }
4823 });
4824 parent.window.hs.close();
4825 show_cart_items_in_tabarea();
4826 show_mashup();
4827 return false;
4828}
4829
4830function showResponse_flyoutcart(responseText, statusText, xhr, $form) {
4831 alert(responseText);
4832 if (responseText == '11111') {
4833 alert("Qty adjusted for stock in hand"); //if user orders more than available... (back order not enabled)
4834 //return false;
4835 } else if (responseText == '00000') {
4836 alert("Minimum Qty Requirements not met for this product group"); //for parent product...
4837 //return false;
4838 } else if (responseText == -1) {
4839 alert("Selected Product Combination does not exist");
4840 return false;
4841 } else if (responseText < -1) {
4842 var howmany = -1 * responseText;
4843 alert("Minimum Order Quantity for this Product is " + howmany);
4844 return false;
4845 }
4846 rename_btn_name();
4847 show_cart_items_in_tabarea(0);
4848 show_mashup();
4849}
4850
4851function show_cart_items_in_tabarea(where) {
4852 var url = "/my_ajax/ajax_display_totalitems_cart";
4853 $.get(url, function(data) {
4854 if (document.getElementById("total_items_incart")) {
4855 document.getElementById("total_items_incart").innerHTML = data;
4856 }
4857 });
4858}
4859/* show_cart_items_in_tabarea();
4860 $( document ).ready( function () {
4861 $( '#minimise-writing' ).hide();
4862 $( '.slick-slidetoggle' ).click( function () {
4863 $( '#minimise-writing' ).slideToggle( 400 );
4864 return false;
4865 } );
4866 $( '#slick-up' ).click( function () {
4867 $( '#minimise-writing' ).hide( 'fast' );
4868 return false;
4869 } );
4870 $( '#secure-toggle' ).click( function () {
4871 $( '#securebox' ).toggle( 400 );
4872 return false;
4873 } );
4874 } );
4875 */
4876
4877 function show_mashup() {
4878 // window.hs.close();
4879 var data = 'loading...';
4880 $("#latestincart").html(data);
4881 var url = "/my_ajax/ajax_latestincart";
4882 url = url + "?sid=" + Math.random();
4883 //dummyfunction();
4884 $.get(url, function(data) {
4885 $('#latestincart').html(data);
4886 });
4887 dummyfunction();
4888 $.blockUI({
4889 fadeIn: 10,
4890 message: $('#latestincart')
4891 });
4892 $('.blockOverlay').attr('title', 'Click to unblock').click($.unblockUI);
4893}
4894
4895function unblockthisone() {
4896 $.unblockUI();
4897}
4898
4899function dummyfunction() {
4900 for (i = 1; i < 1000; i++) {}
4901};
4902
4903function calculate_freight_ajax() {
4904 var ship_country = document.getElementById('flyout_country').value;
4905 var ship_zip = document.getElementById('flyout_zip').value;
4906 url = "/cart/flyout_with_freight_new";
4907 url = url + '?ship_country=' + ship_country
4908 url = url + '&ship_zip=' + ship_zip;
4909 url = url + '&tts=' + new Date().getMilliseconds();
4910 // url = encodeURI(url);
4911 $.get(url, function(data) {
4912 $('#my_cart').html(data);
4913 });
4914}
4915
4916function calculate_freight_ajax_latestincart() {
4917 var ship_country = document.getElementById('flyout_country2').value;
4918 var ship_zip = document.getElementById('flyout_zip2').value;
4919 url = "/cart/flyout_with_freight_new";
4920 url = url + '?ship_country=' + ship_country
4921 url = url + '&ship_zip=' + ship_zip;
4922 url = url + '&tts=' + new Date().getMilliseconds();
4923 // url = encodeURI(url);
4924 $.get(url, function(data) {
4925 dummyfunction();
4926 $('#my_cart').html(data);
4927 show_mashup();
4928 /*
4929 $(".panel").addClass("fast");
4930 $(".panel").show(400);
4931 $("#trigger_id").addClass("active");
4932 */
4933 });
4934 // unblockthisone();
4935}
4936
4937function rename_btn_name() {
4938 var url = '/my_ajax/ajax_chk_already_in_cart?tts=' + new Date().getMilliseconds();
4939 $.get(url, function(data) {
4940 tempvalue = $.trim(data); //data;
4941 if (tempvalue > 0) {
4942 tempvar = '.p' + tempvalue; //products
4943 $(tempvar).val('Add More');
4944 $(tempvar).addClass('add_more');
4945 tempvar = '.ppp' + tempvalue; //shopping
4946 $(tempvar).val('Add More');
4947 $(tempvar).addClass('add_more');
4948 tempvar = '.aj_p' + tempvalue; //tags
4949 $(tempvar).val('Add More');
4950 $(tempvar).addClass('add_more');
4951 }
4952 });
4953}
4954
4955
4956
4957/*
4958 $("#search_keyword").autocomplete(
4959 "/my_ajax/autocomplete/",
4960 {
4961 delay:10,
4962 minChars:2,
4963 matchSubset:1,
4964 matchContains:1,
4965 cacheLength:10,
4966 onItemSelect:selectItem,
4967 onFindValue:findValue,
4968 formatItem:formatItem,
4969 autoFill:true
4970 }
4971 );
4972 */
4973 $("#contains_key1").autocomplete({
4974 source: "/my_ajax/autocomplete",
4975 minLength: 2,
4976 select: function(event, ui) {
4977 var url = ui.item.id;
4978 if (url != '#') {
4979 location.href = url;
4980 }
4981 },
4982 html: false
4983 });
4984
4985
4986
4987 (function() {
4988 var header = document.querySelector(".main-header");
4989
4990 if(window.location.hash) {
4991 header.classList.add("headroom--unpinned");
4992 }
4993
4994 var headroom = new Headroom(header, {
4995 tolerance: {
4996 down : 10,
4997 up : 20
4998 },
4999 offset : 205
5000 });
5001 headroom.init();
5002
5003 }());
5004
5005
5006
5007
5008 $(document).ready(function (e) {
5009
5010 $('.is-arrow-down a').on('click', function (e) {
5011 if ($(this).parents(".is-section").nextAll('div:not(.is-hidden)').html()) { /* .hidden class can be used as an exception */
5012 $('html,body').animate({
5013 scrollTop: $(this).parents(".is-section").nextAll('div:not(.is-hidden)').offset().top - parseInt($('.is-wrapper').css('padding-top')) /* + 1 Adjustment due to topbar height*/
5014 }, 800);
5015 }
5016 e.preventDefault();
5017 e.stopImmediatePropagation();
5018 return false;
5019 });
5020
5021 $('.is-wrapper > div:first-child').find('.is-scale-animated').addClass('is-appeared');
5022
5023 $('.is-scale-animated').appear();
5024 $('.is-scale-animated').on('appear', function () {
5025 $(this).addClass('is-appeared');
5026 });
5027 $('.is-scale-animated').on('disappear', function () {
5028 $(this).removeClass('is-appeared');
5029 });
5030
5031 //Hide all animated elements first
5032 $('.is-animated').each(function () {
5033 $(this).addClass('animated');
5034 $(this).addClass('fadeOut');
5035 });
5036
5037
5038 /* Animate Section/Boxes */
5039 $('.is-section').appear();
5040 $('.is-section').each(function () {
5041 if ($(this).is(':appeared')) {
5042 applyAnimationSection($(this));
5043 }
5044 });
5045 if ($(window).scrollTop() == 0) {//on editing, appear not triggered on first load (on top only). This is the fix.
5046 setTimeout(applyAnimationSection($('.is-section').first()), 2000);
5047 }
5048 $('.is-section').on('appear', function () {
5049 applyAnimationSection($(this));
5050 });
5051 $('.is-section').on('disappear', function () {
5052 removeAnimationSection($(this));
5053 });
5054
5055
5056 /* Animate Content/Container */
5057 $('.is-container').appear();
5058 $('.is-container').each(function () {
5059 if ($(this).is(':appeared')) {
5060 applyAnimation($(this));
5061 }
5062 });
5063 if ($(window).scrollTop() == 0) {//on editing, appear not triggered on first load (on top only). This is the fix.
5064 $('.is-section').first().find('.is-container').each(function () {
5065 setTimeout(applyAnimation($(this)), 2000);
5066 });
5067 }
5068 $('.is-container').on('appear', function () {
5069 applyAnimation($(this));
5070 });
5071 $('.is-container').on('disappear', function () {
5072 removeAnimation($(this));
5073 });
5074
5075});
5076
5077 function applyAnimation($root) {
5078 var n = 0;
5079 $root.find('.is-animated').each(function () {
5080
5081 if ($(this).data('animated') != 'done') {
5082
5083 if (n > 0) $(this).css('animation-delay', n + 's');
5084 n = n + 0.2;
5085
5086 $(this).removeClass('fadeOut');
5087
5088 if ($(this).hasClass('is-pulse')) $(this).addClass('pulse');
5089 if ($(this).hasClass('is-bounceIn')) $(this).addClass('bounceIn');
5090 if ($(this).hasClass('is-fadeIn')) $(this).addClass('fadeIn');
5091 if ($(this).hasClass('is-fadeInDown')) $(this).addClass('fadeInDown');
5092 if ($(this).hasClass('is-fadeInLeft')) $(this).addClass('fadeInLeft');
5093 if ($(this).hasClass('is-fadeInRight')) $(this).addClass('fadeInRight');
5094 if ($(this).hasClass('is-fadeInUp')) $(this).addClass('fadeInUp');
5095 if ($(this).hasClass('is-flipInX')) $(this).addClass('flipInX');
5096 if ($(this).hasClass('is-flipInY')) $(this).addClass('flipInY');
5097 if ($(this).hasClass('is-slideInUp')) $(this).addClass('slideInUp');
5098 if ($(this).hasClass('is-slideInDown')) $(this).addClass('slideInDown');
5099 if ($(this).hasClass('is-slideInLeft')) $(this).addClass('slideInLeft');
5100 if ($(this).hasClass('is-slideInRight')) $(this).addClass('slideInRight');
5101 if ($(this).hasClass('is-zoomIn')) $(this).addClass('zoomIn');
5102
5103 if ($(this).hasClass('once')) $(this).data('animated', 'done');
5104 }
5105
5106 });
5107 }
5108
5109 function removeAnimation($root) {
5110 $root.find('.is-animated').each(function () {
5111
5112 //$(this).removeClass('animated');
5113 $(this).removeClass('pulse');
5114 $(this).removeClass('bounceIn');
5115 $(this).removeClass('fadeIn');
5116 $(this).removeClass('fadeInDown');
5117 $(this).removeClass('fadeInLeft');
5118 $(this).removeClass('fadeInRight');
5119 $(this).removeClass('fadeInUp');
5120 $(this).removeClass('flipInX');
5121 $(this).removeClass('flipInY');
5122 $(this).removeClass('slideInUp');
5123 $(this).removeClass('slideInDown');
5124 $(this).removeClass('slideInLeft');
5125 $(this).removeClass('slideInRight');
5126 $(this).removeClass('zoomIn');
5127
5128 if (!$(this).hasClass('once')) {
5129 $(this).addClass('fadeOut');
5130 }
5131 });
5132 }
5133
5134
5135 function applyAnimationSection($section) {
5136 /*
5137 try {
5138 var s = $('.is-wrapper').data('contentbox').settings;
5139 //return;
5140 } catch (e) { }
5141 */
5142
5143 var n = 0;
5144
5145 if ($section.hasClass('is-animated')) {
5146
5147 if ($section.data('animated') != 'done') {
5148
5149 if(n>0) $section.css('animation-delay', n + 's');
5150 n = n + 0.2;
5151
5152 $section.removeClass('fadeOut');
5153
5154 if ($section.hasClass('is-pulse')) $section.addClass('pulse');
5155 if ($section.hasClass('is-bounceIn')) $section.addClass('bounceIn');
5156 if ($section.hasClass('is-fadeIn')) $section.addClass('fadeIn');
5157 if ($section.hasClass('is-fadeInDown')) $section.addClass('fadeInDown');
5158 if ($section.hasClass('is-fadeInLeft')) $section.addClass('fadeInLeft');
5159 if ($section.hasClass('is-fadeInRight')) $section.addClass('fadeInRight');
5160 if ($section.hasClass('is-fadeInUp')) $section.addClass('fadeInUp');
5161 if ($section.hasClass('is-flipInX')) $section.addClass('flipInX');
5162 if ($section.hasClass('is-flipInY')) $section.addClass('flipInY');
5163 if ($section.hasClass('is-slideInUp')) $section.addClass('slideInUp');
5164 if ($section.hasClass('is-slideInDown')) $section.addClass('slideInDown');
5165 if ($section.hasClass('is-slideInLeft')) $section.addClass('slideInLeft');
5166 if ($section.hasClass('is-slideInRight')) $section.addClass('slideInRight');
5167 if ($section.hasClass('is-zoomIn')) $section.addClass('zoomIn');
5168
5169 if ($section.hasClass('once')) $section.data('animated', 'done');
5170
5171 }
5172 }
5173
5174 $section.find('.is-box.is-animated').each(function () {
5175
5176 if ($(this).data('animated') != 'done') {
5177
5178 if(n>0) $(this).css('animation-delay', n + 's');
5179 n = n + 0.2;
5180
5181 $(this).removeClass('fadeOut');
5182
5183 if ($(this).hasClass('is-pulse')) $(this).addClass('pulse');
5184 if ($(this).hasClass('is-bounceIn')) $(this).addClass('bounceIn');
5185 if ($(this).hasClass('is-fadeIn')) $(this).addClass('fadeIn');
5186 if ($(this).hasClass('is-fadeInDown')) $(this).addClass('fadeInDown');
5187 if ($(this).hasClass('is-fadeInLeft')) $(this).addClass('fadeInLeft');
5188 if ($(this).hasClass('is-fadeInRight')) $(this).addClass('fadeInRight');
5189 if ($(this).hasClass('is-fadeInUp')) $(this).addClass('fadeInUp');
5190 if ($(this).hasClass('is-flipInX')) $(this).addClass('flipInX');
5191 if ($(this).hasClass('is-flipInY')) $(this).addClass('flipInY');
5192 if ($(this).hasClass('is-slideInUp')) $(this).addClass('slideInUp');
5193 if ($(this).hasClass('is-slideInDown')) $(this).addClass('slideInDown');
5194 if ($(this).hasClass('is-slideInLeft')) $(this).addClass('slideInLeft');
5195 if ($(this).hasClass('is-slideInRight')) $(this).addClass('slideInRight');
5196 if ($(this).hasClass('is-zoomIn')) $(this).addClass('zoomIn');
5197
5198 if ($(this).hasClass('once')) $(this).data('animated', 'done');
5199 }
5200 });
5201}
5202
5203function removeAnimationSection($section) {
5204
5205 if ($section.hasClass('is-animated')) {
5206
5207 $section.removeClass('pulse');
5208 $section.removeClass('bounceIn');
5209 $section.removeClass('fadeIn');
5210 $section.removeClass('fadeInDown');
5211 $section.removeClass('fadeInLeft');
5212 $section.removeClass('fadeInRight');
5213 $section.removeClass('fadeInUp');
5214 $section.removeClass('flipInX');
5215 $section.removeClass('flipInY');
5216 $section.removeClass('slideInUp');
5217 $section.removeClass('slideInDown');
5218 $section.removeClass('slideInLeft');
5219 $section.removeClass('slideInRight');
5220 $section.removeClass('zoomIn');
5221
5222 if (!$section.hasClass('once')) {
5223 $section.addClass('fadeOut');
5224 }
5225 }
5226
5227 $section.find('.is-animated').each(function () {
5228
5229 $(this).removeClass('pulse');
5230 $(this).removeClass('bounceIn');
5231 $(this).removeClass('fadeIn');
5232 $(this).removeClass('fadeInDown');
5233 $(this).removeClass('fadeInLeft');
5234 $(this).removeClass('fadeInRight');
5235 $(this).removeClass('fadeInUp');
5236 $(this).removeClass('flipInX');
5237 $(this).removeClass('flipInY');
5238 $(this).removeClass('slideInUp');
5239 $(this).removeClass('slideInDown');
5240 $(this).removeClass('slideInLeft');
5241 $(this).removeClass('slideInRight');
5242 $(this).removeClass('zoomIn');
5243
5244 if (!$(this).hasClass('once')) {
5245 $(this).addClass('fadeOut');
5246 }
5247
5248 });
5249
5250}
5251
5252
5253/*
5254//How to use:
5255//on body load, call: demo($('.is-wrapper > div:first-child'))");
5256var $activeSect;
5257function demo($section) {
5258setTimeout(function () {
5259$activeSect = $section;
5260$('html,body').animate({
5261scrollTop: $activeSect.offset().top
5262}, 700, function () {
5263if ($activeSect.next().html()) {
5264demo($activeSect.next());
5265return false;
5266}
5267});
5268}, 700);
5269}
5270*/
5271
5272
5273/*
5274* jQuery appear plugin
5275*
5276* Copyright (c) 2012 Andrey Sidorov
5277* licensed under MIT license.
5278*
5279* https://github.com/morr/jquery.appear/
5280*
5281* Version: 0.3.6
5282*/
5283(function ($) {
5284 var selectors = [];
5285
5286 var check_binded = false;
5287 var check_lock = false;
5288 var defaults = {
5289 interval: 250,
5290 force_process: false
5291 };
5292 var $window = $(window);
5293
5294 var $prior_appeared = [];
5295
5296 function process() {
5297 check_lock = false;
5298 for (var index = 0, selectorsLength = selectors.length; index < selectorsLength; index++) {
5299 var $appeared = $(selectors[index]).filter(function () {
5300 return $(this).is(':appeared');
5301 });
5302
5303 $appeared.trigger('appear', [$appeared]);
5304
5305 if ($prior_appeared[index]) {
5306 var $disappeared = $prior_appeared[index].not($appeared);
5307 $disappeared.trigger('disappear', [$disappeared]);
5308 }
5309 $prior_appeared[index] = $appeared;
5310 }
5311 };
5312
5313 function add_selector(selector) {
5314 selectors.push(selector);
5315 $prior_appeared.push();
5316 }
5317
5318 // "appeared" custom filter
5319 $.expr.pseudos['appeared'] = function (element) {
5320 var $element = $(element);
5321 if (!$element.is(':visible')) {
5322 return false;
5323 }
5324
5325 var window_left = $window.scrollLeft();
5326 var window_top = $window.scrollTop();
5327 var offset = $element.offset();
5328 var left = offset.left;
5329 var top = offset.top;
5330
5331 if (top + $element.height() >= window_top &&
5332 top - ($element.data('appear-top-offset') || 0) <= window_top + $window.height() - 200 && /* - 200 (custom) */
5333 left + $element.width() >= window_left &&
5334 left - ($element.data('appear-left-offset') || 0) <= window_left + $window.width()) {
5335 return true;
5336 } else {
5337 return false;
5338 }
5339};
5340
5341$.fn.extend({
5342 // watching for element's appearance in browser viewport
5343 appear: function (options) {
5344 var opts = $.extend({}, defaults, options || {});
5345 var selector = this.selector || this;
5346 if (!check_binded) {
5347 var on_check = function () {
5348 if (check_lock) {
5349 return;
5350 }
5351 check_lock = true;
5352
5353 setTimeout(process, opts.interval);
5354 };
5355
5356 $(window).on('scroll', on_check).on('resize', on_check);
5357 check_binded = true;
5358 }
5359
5360 if (opts.force_process) {
5361 setTimeout(process, opts.interval);
5362 }
5363 add_selector(selector);
5364 return $(selector);
5365 }
5366 });
5367
5368$.extend({
5369 // force elements's appearance check
5370 force_appear: function () {
5371 if (check_binded) {
5372 process();
5373 return true;
5374 }
5375 return false;
5376 }
5377 });
5378})(function () {
5379 if (typeof module !== 'undefined') {
5380 // Node
5381 return require('jquery');
5382 } else {
5383 return jQuery;
5384 }
5385} ());
5386
5387
5388
5389/*
5390 _ _ _ _
5391 ___| (_) ___| | __ (_)___
5392/ __| | |/ __| |/ / | / __|
5393\__ \ | | (__| < _ | \__ \
5394|___/_|_|\___|_|\_(_)/ |___/
5395 |__/
5396
5397 Version: 1.5.9
5398 Author: Ken Wheeler
5399 Website: http://kenwheeler.github.io
5400 Docs: http://kenwheeler.github.io/slick
5401 Repo: http://github.com/kenwheeler/slick
5402 Issues: http://github.com/kenwheeler/slick/issues
5403
5404 */
5405 !function(a){"use strict";"function"==typeof define&&define.amd?define(["jquery"],a):"undefined"!=typeof exports?module.exports=a(require("jquery")):a(jQuery)}(function(a){"use strict";var b=window.Slick||{};b=function(){function c(c,d){var f,e=this;e.defaults={accessibility:!0,adaptiveHeight:!1,appendArrows:a(c),appendDots:a(c),arrows:!0,asNavFor:null,prevArrow:'<button type="button" data-role="none" class="slick-prev" aria-label="Previous" tabindex="0" role="button">Previous</button>',nextArrow:'<button type="button" data-role="none" class="slick-next" aria-label="Next" tabindex="0" role="button">Next</button>',autoplay:!1,autoplaySpeed:3e3,centerMode:!1,centerPadding:"50px",cssEase:"ease",customPaging:function(a,b){return'<button type="button" data-role="none" role="button" aria-required="false" tabindex="0">'+(b+1)+"</button>"},dots:!1,dotsClass:"slick-dots",draggable:!0,easing:"linear",edgeFriction:.35,fade:!1,focusOnSelect:!1,infinite:!0,initialSlide:0,lazyLoad:"ondemand",mobileFirst:!1,pauseOnHover:!0,pauseOnDotsHover:!1,respondTo:"window",responsive:null,rows:1,rtl:!1,slide:"",slidesPerRow:1,slidesToShow:1,slidesToScroll:1,speed:500,swipe:!0,swipeToSlide:!1,touchMove:!0,touchThreshold:5,useCSS:!0,useTransform:!1,variableWidth:!1,vertical:!1,verticalSwiping:!1,waitForAnimate:!0,zIndex:1e3},e.initials={animating:!1,dragging:!1,autoPlayTimer:null,currentDirection:0,currentLeft:null,currentSlide:0,direction:1,$dots:null,listWidth:null,listHeight:null,loadIndex:0,$nextArrow:null,$prevArrow:null,slideCount:null,slideWidth:null,$slideTrack:null,$slides:null,sliding:!1,slideOffset:0,swipeLeft:null,$list:null,touchObject:{},transformsEnabled:!1,unslicked:!1},a.extend(e,e.initials),e.activeBreakpoint=null,e.animType=null,e.animProp=null,e.breakpoints=[],e.breakpointSettings=[],e.cssTransitions=!1,e.hidden="hidden",e.paused=!1,e.positionProp=null,e.respondTo=null,e.rowCount=1,e.shouldClick=!0,e.$slider=a(c),e.$slidesCache=null,e.transformType=null,e.transitionType=null,e.visibilityChange="visibilitychange",e.windowWidth=0,e.windowTimer=null,f=a(c).data("slick")||{},e.options=a.extend({},e.defaults,f,d),e.currentSlide=e.options.initialSlide,e.originalSettings=e.options,"undefined"!=typeof document.mozHidden?(e.hidden="mozHidden",e.visibilityChange="mozvisibilitychange"):"undefined"!=typeof document.webkitHidden&&(e.hidden="webkitHidden",e.visibilityChange="webkitvisibilitychange"),e.autoPlay=a.proxy(e.autoPlay,e),e.autoPlayClear=a.proxy(e.autoPlayClear,e),e.changeSlide=a.proxy(e.changeSlide,e),e.clickHandler=a.proxy(e.clickHandler,e),e.selectHandler=a.proxy(e.selectHandler,e),e.setPosition=a.proxy(e.setPosition,e),e.swipeHandler=a.proxy(e.swipeHandler,e),e.dragHandler=a.proxy(e.dragHandler,e),e.keyHandler=a.proxy(e.keyHandler,e),e.autoPlayIterator=a.proxy(e.autoPlayIterator,e),e.instanceUid=b++,e.htmlExpr=/^(?:\s*(<[\w\W]+>)[^>]*)$/,e.registerBreakpoints(),e.init(!0),e.checkResponsive(!0)}var b=0;return c}(),b.prototype.addSlide=b.prototype.slickAdd=function(b,c,d){var e=this;if("boolean"==typeof c)d=c,c=null;else if(0>c||c>=e.slideCount)return!1;e.unload(),"number"==typeof c?0===c&&0===e.$slides.length?a(b).appendTo(e.$slideTrack):d?a(b).insertBefore(e.$slides.eq(c)):a(b).insertAfter(e.$slides.eq(c)):d===!0?a(b).prependTo(e.$slideTrack):a(b).appendTo(e.$slideTrack),e.$slides=e.$slideTrack.children(this.options.slide),e.$slideTrack.children(this.options.slide).detach(),e.$slideTrack.append(e.$slides),e.$slides.each(function(b,c){a(c).attr("data-slick-index",b)}),e.$slidesCache=e.$slides,e.reinit()},b.prototype.animateHeight=function(){var a=this;if(1===a.options.slidesToShow&&a.options.adaptiveHeight===!0&&a.options.vertical===!1){var b=a.$slides.eq(a.currentSlide).outerHeight(!0);a.$list.animate({height:b},a.options.speed)}},b.prototype.animateSlide=function(b,c){var d={},e=this;e.animateHeight(),e.options.rtl===!0&&e.options.vertical===!1&&(b=-b),e.transformsEnabled===!1?e.options.vertical===!1?e.$slideTrack.animate({left:b},e.options.speed,e.options.easing,c):e.$slideTrack.animate({top:b},e.options.speed,e.options.easing,c):e.cssTransitions===!1?(e.options.rtl===!0&&(e.currentLeft=-e.currentLeft),a({animStart:e.currentLeft}).animate({animStart:b},{duration:e.options.speed,easing:e.options.easing,step:function(a){a=Math.ceil(a),e.options.vertical===!1?(d[e.animType]="translate("+a+"px, 0px)",e.$slideTrack.css(d)):(d[e.animType]="translate(0px,"+a+"px)",e.$slideTrack.css(d))},complete:function(){c&&c.call()}})):(e.applyTransition(),b=Math.ceil(b),e.options.vertical===!1?d[e.animType]="translate3d("+b+"px, 0px, 0px)":d[e.animType]="translate3d(0px,"+b+"px, 0px)",e.$slideTrack.css(d),c&&setTimeout(function(){e.disableTransition(),c.call()},e.options.speed))},b.prototype.asNavFor=function(b){var c=this,d=c.options.asNavFor;d&&null!==d&&(d=a(d).not(c.$slider)),null!==d&&"object"==typeof d&&d.each(function(){var c=a(this).slick("getSlick");c.unslicked||c.slideHandler(b,!0)})},b.prototype.applyTransition=function(a){var b=this,c={};b.options.fade===!1?c[b.transitionType]=b.transformType+" "+b.options.speed+"ms "+b.options.cssEase:c[b.transitionType]="opacity "+b.options.speed+"ms "+b.options.cssEase,b.options.fade===!1?b.$slideTrack.css(c):b.$slides.eq(a).css(c)},b.prototype.autoPlay=function(){var a=this;a.autoPlayTimer&&clearInterval(a.autoPlayTimer),a.slideCount>a.options.slidesToShow&&a.paused!==!0&&(a.autoPlayTimer=setInterval(a.autoPlayIterator,a.options.autoplaySpeed))},b.prototype.autoPlayClear=function(){var a=this;a.autoPlayTimer&&clearInterval(a.autoPlayTimer)},b.prototype.autoPlayIterator=function(){var a=this;a.options.infinite===!1?1===a.direction?(a.currentSlide+1===a.slideCount-1&&(a.direction=0),a.slideHandler(a.currentSlide+a.options.slidesToScroll)):(a.currentSlide-1===0&&(a.direction=1),a.slideHandler(a.currentSlide-a.options.slidesToScroll)):a.slideHandler(a.currentSlide+a.options.slidesToScroll)},b.prototype.buildArrows=function(){var b=this;b.options.arrows===!0&&(b.$prevArrow=a(b.options.prevArrow).addClass("slick-arrow"),b.$nextArrow=a(b.options.nextArrow).addClass("slick-arrow"),b.slideCount>b.options.slidesToShow?(b.$prevArrow.removeClass("slick-hidden").removeAttr("aria-hidden tabindex"),b.$nextArrow.removeClass("slick-hidden").removeAttr("aria-hidden tabindex"),b.htmlExpr.test(b.options.prevArrow)&&b.$prevArrow.prependTo(b.options.appendArrows),b.htmlExpr.test(b.options.nextArrow)&&b.$nextArrow.appendTo(b.options.appendArrows),b.options.infinite!==!0&&b.$prevArrow.addClass("slick-disabled").attr("aria-disabled","true")):b.$prevArrow.add(b.$nextArrow).addClass("slick-hidden").attr({"aria-disabled":"true",tabindex:"-1"}))},b.prototype.buildDots=function(){var c,d,b=this;if(b.options.dots===!0&&b.slideCount>b.options.slidesToShow){for(d='<ul class="'+b.options.dotsClass+'">',c=0;c<=b.getDotCount();c+=1)d+="<li>"+b.options.customPaging.call(this,b,c)+"</li>";d+="</ul>",b.$dots=a(d).appendTo(b.options.appendDots),b.$dots.find("li").first().addClass("slick-active").attr("aria-hidden","false")}},b.prototype.buildOut=function(){var b=this;b.$slides=b.$slider.children(b.options.slide+":not(.slick-cloned)").addClass("slick-slide"),b.slideCount=b.$slides.length,b.$slides.each(function(b,c){a(c).attr("data-slick-index",b).data("originalStyling",a(c).attr("style")||"")}),b.$slider.addClass("slick-slider"),b.$slideTrack=0===b.slideCount?a('<div class="slick-track"/>').appendTo(b.$slider):b.$slides.wrapAll('<div class="slick-track"/>').parent(),b.$list=b.$slideTrack.wrap('<div aria-live="polite" class="slick-list"/>').parent(),b.$slideTrack.css("opacity",0),(b.options.centerMode===!0||b.options.swipeToSlide===!0)&&(b.options.slidesToScroll=1),a("img[data-lazy]",b.$slider).not("[src]").addClass("slick-loading"),b.setupInfinite(),b.buildArrows(),b.buildDots(),b.updateDots(),b.setSlideClasses("number"==typeof b.currentSlide?b.currentSlide:0),b.options.draggable===!0&&b.$list.addClass("draggable")},b.prototype.buildRows=function(){var b,c,d,e,f,g,h,a=this;if(e=document.createDocumentFragment(),g=a.$slider.children(),a.options.rows>1){for(h=a.options.slidesPerRow*a.options.rows,f=Math.ceil(g.length/h),b=0;f>b;b++){var i=document.createElement("div");for(c=0;c<a.options.rows;c++){var j=document.createElement("div");for(d=0;d<a.options.slidesPerRow;d++){var k=b*h+(c*a.options.slidesPerRow+d);g.get(k)&&j.appendChild(g.get(k))}i.appendChild(j)}e.appendChild(i)}a.$slider.html(e),a.$slider.children().children().children().css({width:100/a.options.slidesPerRow+"%",display:"inline-block"})}},b.prototype.checkResponsive=function(b,c){var e,f,g,d=this,h=!1,i=d.$slider.width(),j=window.innerWidth||a(window).width();if("window"===d.respondTo?g=j:"slider"===d.respondTo?g=i:"min"===d.respondTo&&(g=Math.min(j,i)),d.options.responsive&&d.options.responsive.length&&null!==d.options.responsive){f=null;for(e in d.breakpoints)d.breakpoints.hasOwnProperty(e)&&(d.originalSettings.mobileFirst===!1?g<d.breakpoints[e]&&(f=d.breakpoints[e]):g>d.breakpoints[e]&&(f=d.breakpoints[e]));null!==f?null!==d.activeBreakpoint?(f!==d.activeBreakpoint||c)&&(d.activeBreakpoint=f,"unslick"===d.breakpointSettings[f]?d.unslick(f):(d.options=a.extend({},d.originalSettings,d.breakpointSettings[f]),b===!0&&(d.currentSlide=d.options.initialSlide),d.refresh(b)),h=f):(d.activeBreakpoint=f,"unslick"===d.breakpointSettings[f]?d.unslick(f):(d.options=a.extend({},d.originalSettings,d.breakpointSettings[f]),b===!0&&(d.currentSlide=d.options.initialSlide),d.refresh(b)),h=f):null!==d.activeBreakpoint&&(d.activeBreakpoint=null,d.options=d.originalSettings,b===!0&&(d.currentSlide=d.options.initialSlide),d.refresh(b),h=f),b||h===!1||d.$slider.trigger("breakpoint",[d,h])}},b.prototype.changeSlide=function(b,c){var f,g,h,d=this,e=a(b.target);switch(e.is("a")&&b.preventDefault(),e.is("li")||(e=e.closest("li")),h=d.slideCount%d.options.slidesToScroll!==0,f=h?0:(d.slideCount-d.currentSlide)%d.options.slidesToScroll,b.data.message){case"previous":g=0===f?d.options.slidesToScroll:d.options.slidesToShow-f,d.slideCount>d.options.slidesToShow&&d.slideHandler(d.currentSlide-g,!1,c);break;case"next":g=0===f?d.options.slidesToScroll:f,d.slideCount>d.options.slidesToShow&&d.slideHandler(d.currentSlide+g,!1,c);break;case"index":var i=0===b.data.index?0:b.data.index||e.index()*d.options.slidesToScroll;d.slideHandler(d.checkNavigable(i),!1,c),e.children().trigger("focus");break;default:return}},b.prototype.checkNavigable=function(a){var c,d,b=this;if(c=b.getNavigableIndexes(),d=0,a>c[c.length-1])a=c[c.length-1];else for(var e in c){if(a<c[e]){a=d;break}d=c[e]}return a},b.prototype.cleanUpEvents=function(){var b=this;b.options.dots&&null!==b.$dots&&(a("li",b.$dots).off("click.slick",b.changeSlide),b.options.pauseOnDotsHover===!0&&b.options.autoplay===!0&&a("li",b.$dots).off("mouseenter.slick",a.proxy(b.setPaused,b,!0)).off("mouseleave.slick",a.proxy(b.setPaused,b,!1))),b.options.arrows===!0&&b.slideCount>b.options.slidesToShow&&(b.$prevArrow&&b.$prevArrow.off("click.slick",b.changeSlide),b.$nextArrow&&b.$nextArrow.off("click.slick",b.changeSlide)),b.$list.off("touchstart.slick mousedown.slick",b.swipeHandler),b.$list.off("touchmove.slick mousemove.slick",b.swipeHandler),b.$list.off("touchend.slick mouseup.slick",b.swipeHandler),b.$list.off("touchcancel.slick mouseleave.slick",b.swipeHandler),b.$list.off("click.slick",b.clickHandler),a(document).off(b.visibilityChange,b.visibility),b.$list.off("mouseenter.slick",a.proxy(b.setPaused,b,!0)),b.$list.off("mouseleave.slick",a.proxy(b.setPaused,b,!1)),b.options.accessibility===!0&&b.$list.off("keydown.slick",b.keyHandler),b.options.focusOnSelect===!0&&a(b.$slideTrack).children().off("click.slick",b.selectHandler),a(window).off("orientationchange.slick.slick-"+b.instanceUid,b.orientationChange),a(window).off("resize.slick.slick-"+b.instanceUid,b.resize),a("[draggable!=true]",b.$slideTrack).off("dragstart",b.preventDefault),a(window).off("load.slick.slick-"+b.instanceUid,b.setPosition),a(document).off("ready.slick.slick-"+b.instanceUid,b.setPosition)},b.prototype.cleanUpRows=function(){var b,a=this;a.options.rows>1&&(b=a.$slides.children().children(),b.removeAttr("style"),a.$slider.html(b))},b.prototype.clickHandler=function(a){var b=this;b.shouldClick===!1&&(a.stopImmediatePropagation(),a.stopPropagation(),a.preventDefault())},b.prototype.destroy=function(b){var c=this;c.autoPlayClear(),c.touchObject={},c.cleanUpEvents(),a(".slick-cloned",c.$slider).detach(),c.$dots&&c.$dots.remove(),c.$prevArrow&&c.$prevArrow.length&&(c.$prevArrow.removeClass("slick-disabled slick-arrow slick-hidden").removeAttr("aria-hidden aria-disabled tabindex").css("display",""),c.htmlExpr.test(c.options.prevArrow)&&c.$prevArrow.remove()),c.$nextArrow&&c.$nextArrow.length&&(c.$nextArrow.removeClass("slick-disabled slick-arrow slick-hidden").removeAttr("aria-hidden aria-disabled tabindex").css("display",""),c.htmlExpr.test(c.options.nextArrow)&&c.$nextArrow.remove()),c.$slides&&(c.$slides.removeClass("slick-slide slick-active slick-center slick-visible slick-current").removeAttr("aria-hidden").removeAttr("data-slick-index").each(function(){a(this).attr("style",a(this).data("originalStyling"))}),c.$slideTrack.children(this.options.slide).detach(),c.$slideTrack.detach(),c.$list.detach(),c.$slider.append(c.$slides)),c.cleanUpRows(),c.$slider.removeClass("slick-slider"),c.$slider.removeClass("slick-initialized"),c.unslicked=!0,b||c.$slider.trigger("destroy",[c])},b.prototype.disableTransition=function(a){var b=this,c={};c[b.transitionType]="",b.options.fade===!1?b.$slideTrack.css(c):b.$slides.eq(a).css(c)},b.prototype.fadeSlide=function(a,b){var c=this;c.cssTransitions===!1?(c.$slides.eq(a).css({zIndex:c.options.zIndex}),c.$slides.eq(a).animate({opacity:1},c.options.speed,c.options.easing,b)):(c.applyTransition(a),c.$slides.eq(a).css({opacity:1,zIndex:c.options.zIndex}),b&&setTimeout(function(){c.disableTransition(a),b.call()},c.options.speed))},b.prototype.fadeSlideOut=function(a){var b=this;b.cssTransitions===!1?b.$slides.eq(a).animate({opacity:0,zIndex:b.options.zIndex-2},b.options.speed,b.options.easing):(b.applyTransition(a),b.$slides.eq(a).css({opacity:0,zIndex:b.options.zIndex-2}))},b.prototype.filterSlides=b.prototype.slickFilter=function(a){var b=this;null!==a&&(b.$slidesCache=b.$slides,b.unload(),b.$slideTrack.children(this.options.slide).detach(),b.$slidesCache.filter(a).appendTo(b.$slideTrack),b.reinit())},b.prototype.getCurrent=b.prototype.slickCurrentSlide=function(){var a=this;return a.currentSlide},b.prototype.getDotCount=function(){var a=this,b=0,c=0,d=0;if(a.options.infinite===!0)for(;b<a.slideCount;)++d,b=c+a.options.slidesToScroll,c+=a.options.slidesToScroll<=a.options.slidesToShow?a.options.slidesToScroll:a.options.slidesToShow;else if(a.options.centerMode===!0)d=a.slideCount;else for(;b<a.slideCount;)++d,b=c+a.options.slidesToScroll,c+=a.options.slidesToScroll<=a.options.slidesToShow?a.options.slidesToScroll:a.options.slidesToShow;return d-1},b.prototype.getLeft=function(a){var c,d,f,b=this,e=0;return b.slideOffset=0,d=b.$slides.first().outerHeight(!0),b.options.infinite===!0?(b.slideCount>b.options.slidesToShow&&(b.slideOffset=b.slideWidth*b.options.slidesToShow*-1,e=d*b.options.slidesToShow*-1),b.slideCount%b.options.slidesToScroll!==0&&a+b.options.slidesToScroll>b.slideCount&&b.slideCount>b.options.slidesToShow&&(a>b.slideCount?(b.slideOffset=(b.options.slidesToShow-(a-b.slideCount))*b.slideWidth*-1,e=(b.options.slidesToShow-(a-b.slideCount))*d*-1):(b.slideOffset=b.slideCount%b.options.slidesToScroll*b.slideWidth*-1,e=b.slideCount%b.options.slidesToScroll*d*-1))):a+b.options.slidesToShow>b.slideCount&&(b.slideOffset=(a+b.options.slidesToShow-b.slideCount)*b.slideWidth,e=(a+b.options.slidesToShow-b.slideCount)*d),b.slideCount<=b.options.slidesToShow&&(b.slideOffset=0,e=0),b.options.centerMode===!0&&b.options.infinite===!0?b.slideOffset+=b.slideWidth*Math.floor(b.options.slidesToShow/2)-b.slideWidth:b.options.centerMode===!0&&(b.slideOffset=0,b.slideOffset+=b.slideWidth*Math.floor(b.options.slidesToShow/2)),c=b.options.vertical===!1?a*b.slideWidth*-1+b.slideOffset:a*d*-1+e,b.options.variableWidth===!0&&(f=b.slideCount<=b.options.slidesToShow||b.options.infinite===!1?b.$slideTrack.children(".slick-slide").eq(a):b.$slideTrack.children(".slick-slide").eq(a+b.options.slidesToShow),c=b.options.rtl===!0?f[0]?-1*(b.$slideTrack.width()-f[0].offsetLeft-f.width()):0:f[0]?-1*f[0].offsetLeft:0,b.options.centerMode===!0&&(f=b.slideCount<=b.options.slidesToShow||b.options.infinite===!1?b.$slideTrack.children(".slick-slide").eq(a):b.$slideTrack.children(".slick-slide").eq(a+b.options.slidesToShow+1),c=b.options.rtl===!0?f[0]?-1*(b.$slideTrack.width()-f[0].offsetLeft-f.width()):0:f[0]?-1*f[0].offsetLeft:0,c+=(b.$list.width()-f.outerWidth())/2)),c},b.prototype.getOption=b.prototype.slickGetOption=function(a){var b=this;return b.options[a]},b.prototype.getNavigableIndexes=function(){var e,a=this,b=0,c=0,d=[];for(a.options.infinite===!1?e=a.slideCount:(b=-1*a.options.slidesToScroll,c=-1*a.options.slidesToScroll,e=2*a.slideCount);e>b;)d.push(b),b=c+a.options.slidesToScroll,c+=a.options.slidesToScroll<=a.options.slidesToShow?a.options.slidesToScroll:a.options.slidesToShow;return d},b.prototype.getSlick=function(){return this},b.prototype.getSlideCount=function(){var c,d,e,b=this;return e=b.options.centerMode===!0?b.slideWidth*Math.floor(b.options.slidesToShow/2):0,b.options.swipeToSlide===!0?(b.$slideTrack.find(".slick-slide").each(function(c,f){return f.offsetLeft-e+a(f).outerWidth()/2>-1*b.swipeLeft?(d=f,!1):void 0}),c=Math.abs(a(d).attr("data-slick-index")-b.currentSlide)||1):b.options.slidesToScroll},b.prototype.goTo=b.prototype.slickGoTo=function(a,b){var c=this;c.changeSlide({data:{message:"index",index:parseInt(a)}},b)},b.prototype.init=function(b){var c=this;a(c.$slider).hasClass("slick-initialized")||(a(c.$slider).addClass("slick-initialized"),c.buildRows(),c.buildOut(),c.setProps(),c.startLoad(),c.loadSlider(),c.initializeEvents(),c.updateArrows(),c.updateDots()),b&&c.$slider.trigger("init",[c]),c.options.accessibility===!0&&c.initADA()},b.prototype.initArrowEvents=function(){var a=this;a.options.arrows===!0&&a.slideCount>a.options.slidesToShow&&(a.$prevArrow.on("click.slick",{message:"previous"},a.changeSlide),a.$nextArrow.on("click.slick",{message:"next"},a.changeSlide))},b.prototype.initDotEvents=function(){var b=this;b.options.dots===!0&&b.slideCount>b.options.slidesToShow&&a("li",b.$dots).on("click.slick",{message:"index"},b.changeSlide),b.options.dots===!0&&b.options.pauseOnDotsHover===!0&&b.options.autoplay===!0&&a("li",b.$dots).on("mouseenter.slick",a.proxy(b.setPaused,b,!0)).on("mouseleave.slick",a.proxy(b.setPaused,b,!1))},b.prototype.initializeEvents=function(){var b=this;b.initArrowEvents(),b.initDotEvents(),b.$list.on("touchstart.slick mousedown.slick",{action:"start"},b.swipeHandler),b.$list.on("touchmove.slick mousemove.slick",{action:"move"},b.swipeHandler),b.$list.on("touchend.slick mouseup.slick",{action:"end"},b.swipeHandler),b.$list.on("touchcancel.slick mouseleave.slick",{action:"end"},b.swipeHandler),b.$list.on("click.slick",b.clickHandler),a(document).on(b.visibilityChange,a.proxy(b.visibility,b)),b.$list.on("mouseenter.slick",a.proxy(b.setPaused,b,!0)),b.$list.on("mouseleave.slick",a.proxy(b.setPaused,b,!1)),b.options.accessibility===!0&&b.$list.on("keydown.slick",b.keyHandler),b.options.focusOnSelect===!0&&a(b.$slideTrack).children().on("click.slick",b.selectHandler),a(window).on("orientationchange.slick.slick-"+b.instanceUid,a.proxy(b.orientationChange,b)),a(window).on("resize.slick.slick-"+b.instanceUid,a.proxy(b.resize,b)),a("[draggable!=true]",b.$slideTrack).on("dragstart",b.preventDefault),a(window).on("load.slick.slick-"+b.instanceUid,b.setPosition),a(document).on("ready.slick.slick-"+b.instanceUid,b.setPosition)},b.prototype.initUI=function(){var a=this;a.options.arrows===!0&&a.slideCount>a.options.slidesToShow&&(a.$prevArrow.show(),a.$nextArrow.show()),a.options.dots===!0&&a.slideCount>a.options.slidesToShow&&a.$dots.show(),a.options.autoplay===!0&&a.autoPlay()},b.prototype.keyHandler=function(a){var b=this;a.target.tagName.match("TEXTAREA|INPUT|SELECT")||(37===a.keyCode&&b.options.accessibility===!0?b.changeSlide({data:{message:"previous"}}):39===a.keyCode&&b.options.accessibility===!0&&b.changeSlide({data:{message:"next"}}))},b.prototype.lazyLoad=function(){function g(b){a("img[data-lazy]",b).each(function(){var b=a(this),c=a(this).attr("data-lazy"),d=document.createElement("img");d.onload=function(){b.animate({opacity:0},100,function(){b.attr("src",c).animate({opacity:1},200,function(){b.removeAttr("data-lazy").removeClass("slick-loading")})})},d.src=c})}var c,d,e,f,b=this;b.options.centerMode===!0?b.options.infinite===!0?(e=b.currentSlide+(b.options.slidesToShow/2+1),f=e+b.options.slidesToShow+2):(e=Math.max(0,b.currentSlide-(b.options.slidesToShow/2+1)),f=2+(b.options.slidesToShow/2+1)+b.currentSlide):(e=b.options.infinite?b.options.slidesToShow+b.currentSlide:b.currentSlide,f=e+b.options.slidesToShow,b.options.fade===!0&&(e>0&&e--,f<=b.slideCount&&f++)),c=b.$slider.find(".slick-slide").slice(e,f),g(c),b.slideCount<=b.options.slidesToShow?(d=b.$slider.find(".slick-slide"),g(d)):b.currentSlide>=b.slideCount-b.options.slidesToShow?(d=b.$slider.find(".slick-cloned").slice(0,b.options.slidesToShow),g(d)):0===b.currentSlide&&(d=b.$slider.find(".slick-cloned").slice(-1*b.options.slidesToShow),g(d))},b.prototype.loadSlider=function(){var a=this;a.setPosition(),a.$slideTrack.css({opacity:1}),a.$slider.removeClass("slick-loading"),a.initUI(),"progressive"===a.options.lazyLoad&&a.progressiveLazyLoad()},b.prototype.next=b.prototype.slickNext=function(){var a=this;a.changeSlide({data:{message:"next"}})},b.prototype.orientationChange=function(){var a=this;a.checkResponsive(),a.setPosition()},b.prototype.pause=b.prototype.slickPause=function(){var a=this;a.autoPlayClear(),a.paused=!0},b.prototype.play=b.prototype.slickPlay=function(){var a=this;a.paused=!1,a.autoPlay()},b.prototype.postSlide=function(a){var b=this;b.$slider.trigger("afterChange",[b,a]),b.animating=!1,b.setPosition(),b.swipeLeft=null,b.options.autoplay===!0&&b.paused===!1&&b.autoPlay(),b.options.accessibility===!0&&b.initADA()},b.prototype.prev=b.prototype.slickPrev=function(){var a=this;a.changeSlide({data:{message:"previous"}})},b.prototype.preventDefault=function(a){a.preventDefault()},b.prototype.progressiveLazyLoad=function(){var c,d,b=this;c=a("img[data-lazy]",b.$slider).length,c>0&&(d=a("img[data-lazy]",b.$slider).first(),d.attr("src",null),d.attr("src",d.attr("data-lazy")).removeClass("slick-loading").load(function(){d.removeAttr("data-lazy"),b.progressiveLazyLoad(),b.options.adaptiveHeight===!0&&b.setPosition()}).error(function(){d.removeAttr("data-lazy"),b.progressiveLazyLoad()}))},b.prototype.refresh=function(b){var d,e,c=this;e=c.slideCount-c.options.slidesToShow,c.options.infinite||(c.slideCount<=c.options.slidesToShow?c.currentSlide=0:c.currentSlide>e&&(c.currentSlide=e)),d=c.currentSlide,c.destroy(!0),a.extend(c,c.initials,{currentSlide:d}),c.init(),b||c.changeSlide({data:{message:"index",index:d}},!1)},b.prototype.registerBreakpoints=function(){var c,d,e,b=this,f=b.options.responsive||null;if("array"===a.type(f)&&f.length){b.respondTo=b.options.respondTo||"window";for(c in f)if(e=b.breakpoints.length-1,d=f[c].breakpoint,f.hasOwnProperty(c)){for(;e>=0;)b.breakpoints[e]&&b.breakpoints[e]===d&&b.breakpoints.splice(e,1),e--;b.breakpoints.push(d),b.breakpointSettings[d]=f[c].settings}b.breakpoints.sort(function(a,c){return b.options.mobileFirst?a-c:c-a})}},b.prototype.reinit=function(){var b=this;b.$slides=b.$slideTrack.children(b.options.slide).addClass("slick-slide"),b.slideCount=b.$slides.length,b.currentSlide>=b.slideCount&&0!==b.currentSlide&&(b.currentSlide=b.currentSlide-b.options.slidesToScroll),b.slideCount<=b.options.slidesToShow&&(b.currentSlide=0),b.registerBreakpoints(),b.setProps(),b.setupInfinite(),b.buildArrows(),b.updateArrows(),b.initArrowEvents(),b.buildDots(),b.updateDots(),b.initDotEvents(),b.checkResponsive(!1,!0),b.options.focusOnSelect===!0&&a(b.$slideTrack).children().on("click.slick",b.selectHandler),b.setSlideClasses(0),b.setPosition(),b.$slider.trigger("reInit",[b]),b.options.autoplay===!0&&b.focusHandler()},b.prototype.resize=function(){var b=this;a(window).width()!==b.windowWidth&&(clearTimeout(b.windowDelay),b.windowDelay=window.setTimeout(function(){b.windowWidth=a(window).width(),b.checkResponsive(),b.unslicked||b.setPosition()},50))},b.prototype.removeSlide=b.prototype.slickRemove=function(a,b,c){var d=this;return"boolean"==typeof a?(b=a,a=b===!0?0:d.slideCount-1):a=b===!0?--a:a,d.slideCount<1||0>a||a>d.slideCount-1?!1:(d.unload(),c===!0?d.$slideTrack.children().remove():d.$slideTrack.children(this.options.slide).eq(a).remove(),d.$slides=d.$slideTrack.children(this.options.slide),d.$slideTrack.children(this.options.slide).detach(),d.$slideTrack.append(d.$slides),d.$slidesCache=d.$slides,void d.reinit())},b.prototype.setCSS=function(a){var d,e,b=this,c={};b.options.rtl===!0&&(a=-a),d="left"==b.positionProp?Math.ceil(a)+"px":"0px",e="top"==b.positionProp?Math.ceil(a)+"px":"0px",c[b.positionProp]=a,b.transformsEnabled===!1?b.$slideTrack.css(c):(c={},b.cssTransitions===!1?(c[b.animType]="translate("+d+", "+e+")",b.$slideTrack.css(c)):(c[b.animType]="translate3d("+d+", "+e+", 0px)",b.$slideTrack.css(c)))},b.prototype.setDimensions=function(){var a=this;a.options.vertical===!1?a.options.centerMode===!0&&a.$list.css({padding:"0px "+a.options.centerPadding}):(a.$list.height(a.$slides.first().outerHeight(!0)*a.options.slidesToShow),a.options.centerMode===!0&&a.$list.css({padding:a.options.centerPadding+" 0px"})),a.listWidth=a.$list.width(),a.listHeight=a.$list.height(),a.options.vertical===!1&&a.options.variableWidth===!1?(a.slideWidth=Math.ceil(a.listWidth/a.options.slidesToShow),a.$slideTrack.width(Math.ceil(a.slideWidth*a.$slideTrack.children(".slick-slide").length))):a.options.variableWidth===!0?a.$slideTrack.width(5e3*a.slideCount):(a.slideWidth=Math.ceil(a.listWidth),a.$slideTrack.height(Math.ceil(a.$slides.first().outerHeight(!0)*a.$slideTrack.children(".slick-slide").length)));var b=a.$slides.first().outerWidth(!0)-a.$slides.first().width();a.options.variableWidth===!1&&a.$slideTrack.children(".slick-slide").width(a.slideWidth-b)},b.prototype.setFade=function(){var c,b=this;b.$slides.each(function(d,e){c=b.slideWidth*d*-1,b.options.rtl===!0?a(e).css({position:"relative",right:c,top:0,zIndex:b.options.zIndex-2,opacity:0}):a(e).css({position:"relative",left:c,top:0,zIndex:b.options.zIndex-2,opacity:0})}),b.$slides.eq(b.currentSlide).css({zIndex:b.options.zIndex-1,opacity:1})},b.prototype.setHeight=function(){var a=this;if(1===a.options.slidesToShow&&a.options.adaptiveHeight===!0&&a.options.vertical===!1){var b=a.$slides.eq(a.currentSlide).outerHeight(!0);a.$list.css("height",b)}},b.prototype.setOption=b.prototype.slickSetOption=function(b,c,d){var f,g,e=this;if("responsive"===b&&"array"===a.type(c))for(g in c)if("array"!==a.type(e.options.responsive))e.options.responsive=[c[g]];else{for(f=e.options.responsive.length-1;f>=0;)e.options.responsive[f].breakpoint===c[g].breakpoint&&e.options.responsive.splice(f,1),f--;e.options.responsive.push(c[g])}else e.options[b]=c;d===!0&&(e.unload(),e.reinit())},b.prototype.setPosition=function(){var a=this;a.setDimensions(),a.setHeight(),a.options.fade===!1?a.setCSS(a.getLeft(a.currentSlide)):a.setFade(),a.$slider.trigger("setPosition",[a])},b.prototype.setProps=function(){var a=this,b=document.body.style;a.positionProp=a.options.vertical===!0?"top":"left","top"===a.positionProp?a.$slider.addClass("slick-vertical"):a.$slider.removeClass("slick-vertical"),(void 0!==b.WebkitTransition||void 0!==b.MozTransition||void 0!==b.msTransition)&&a.options.useCSS===!0&&(a.cssTransitions=!0),a.options.fade&&("number"==typeof a.options.zIndex?a.options.zIndex<3&&(a.options.zIndex=3):a.options.zIndex=a.defaults.zIndex),void 0!==b.OTransform&&(a.animType="OTransform",a.transformType="-o-transform",a.transitionType="OTransition",void 0===b.perspectiveProperty&&void 0===b.webkitPerspective&&(a.animType=!1)),void 0!==b.MozTransform&&(a.animType="MozTransform",a.transformType="-moz-transform",a.transitionType="MozTransition",void 0===b.perspectiveProperty&&void 0===b.MozPerspective&&(a.animType=!1)),void 0!==b.webkitTransform&&(a.animType="webkitTransform",a.transformType="-webkit-transform",a.transitionType="webkitTransition",void 0===b.perspectiveProperty&&void 0===b.webkitPerspective&&(a.animType=!1)),void 0!==b.msTransform&&(a.animType="msTransform",a.transformType="-ms-transform",a.transitionType="msTransition",void 0===b.msTransform&&(a.animType=!1)),void 0!==b.transform&&a.animType!==!1&&(a.animType="transform",a.transformType="transform",a.transitionType="transition"),a.transformsEnabled=a.options.useTransform&&null!==a.animType&&a.animType!==!1},b.prototype.setSlideClasses=function(a){var c,d,e,f,b=this;d=b.$slider.find(".slick-slide").removeClass("slick-active slick-center slick-current").attr("aria-hidden","true"),b.$slides.eq(a).addClass("slick-current"),b.options.centerMode===!0?(c=Math.floor(b.options.slidesToShow/2),b.options.infinite===!0&&(a>=c&&a<=b.slideCount-1-c?b.$slides.slice(a-c,a+c+1).addClass("slick-active").attr("aria-hidden","false"):(e=b.options.slidesToShow+a,d.slice(e-c+1,e+c+2).addClass("slick-active").attr("aria-hidden","false")),0===a?d.eq(d.length-1-b.options.slidesToShow).addClass("slick-center"):a===b.slideCount-1&&d.eq(b.options.slidesToShow).addClass("slick-center")),b.$slides.eq(a).addClass("slick-center")):a>=0&&a<=b.slideCount-b.options.slidesToShow?b.$slides.slice(a,a+b.options.slidesToShow).addClass("slick-active").attr("aria-hidden","false"):d.length<=b.options.slidesToShow?d.addClass("slick-active").attr("aria-hidden","false"):(f=b.slideCount%b.options.slidesToShow,e=b.options.infinite===!0?b.options.slidesToShow+a:a,b.options.slidesToShow==b.options.slidesToScroll&&b.slideCount-a<b.options.slidesToShow?d.slice(e-(b.options.slidesToShow-f),e+f).addClass("slick-active").attr("aria-hidden","false"):d.slice(e,e+b.options.slidesToShow).addClass("slick-active").attr("aria-hidden","false")),"ondemand"===b.options.lazyLoad&&b.lazyLoad()},b.prototype.setupInfinite=function(){var c,d,e,b=this;if(b.options.fade===!0&&(b.options.centerMode=!1),b.options.infinite===!0&&b.options.fade===!1&&(d=null,b.slideCount>b.options.slidesToShow)){for(e=b.options.centerMode===!0?b.options.slidesToShow+1:b.options.slidesToShow,c=b.slideCount;c>b.slideCount-e;c-=1)d=c-1,a(b.$slides[d]).clone(!0).attr("id","").attr("data-slick-index",d-b.slideCount).prependTo(b.$slideTrack).addClass("slick-cloned");for(c=0;e>c;c+=1)d=c,a(b.$slides[d]).clone(!0).attr("id","").attr("data-slick-index",d+b.slideCount).appendTo(b.$slideTrack).addClass("slick-cloned");b.$slideTrack.find(".slick-cloned").find("[id]").each(function(){a(this).attr("id","")})}},b.prototype.setPaused=function(a){var b=this;b.options.autoplay===!0&&b.options.pauseOnHover===!0&&(b.paused=a,a?b.autoPlayClear():b.autoPlay())},b.prototype.selectHandler=function(b){var c=this,d=a(b.target).is(".slick-slide")?a(b.target):a(b.target).parents(".slick-slide"),e=parseInt(d.attr("data-slick-index"));return e||(e=0),c.slideCount<=c.options.slidesToShow?(c.setSlideClasses(e),void c.asNavFor(e)):void c.slideHandler(e)},b.prototype.slideHandler=function(a,b,c){var d,e,f,g,h=null,i=this;return b=b||!1,i.animating===!0&&i.options.waitForAnimate===!0||i.options.fade===!0&&i.currentSlide===a||i.slideCount<=i.options.slidesToShow?void 0:(b===!1&&i.asNavFor(a),d=a,h=i.getLeft(d),g=i.getLeft(i.currentSlide),i.currentLeft=null===i.swipeLeft?g:i.swipeLeft,i.options.infinite===!1&&i.options.centerMode===!1&&(0>a||a>i.getDotCount()*i.options.slidesToScroll)?void(i.options.fade===!1&&(d=i.currentSlide,c!==!0?i.animateSlide(g,function(){i.postSlide(d);
5406 }) : i.postSlide(d))) : i.options.infinite === !1 && i.options.centerMode === !0 && (0 > a || a > i.slideCount - i.options.slidesToScroll) ? void (i.options.fade === !1 && (d = i.currentSlide, c !== !0 ? i.animateSlide(g, function () { i.postSlide(d) }) : i.postSlide(d))) : (i.options.autoplay === !0 && clearInterval(i.autoPlayTimer), e = 0 > d ? i.slideCount % i.options.slidesToScroll !== 0 ? i.slideCount - i.slideCount % i.options.slidesToScroll : i.slideCount + d : d >= i.slideCount ? i.slideCount % i.options.slidesToScroll !== 0 ? 0 : d - i.slideCount : d, i.animating = !0, i.$slider.trigger("beforeChange", [i, i.currentSlide, e]), f = i.currentSlide, i.currentSlide = e, i.setSlideClasses(i.currentSlide), i.updateDots(), i.updateArrows(), i.options.fade === !0 ? (c !== !0 ? (i.fadeSlideOut(f), i.fadeSlide(e, function () { i.postSlide(e) })) : i.postSlide(e), void i.animateHeight()) : void (c !== !0 ? i.animateSlide(h, function () { i.postSlide(e) }) : i.postSlide(e))))
5407}, b.prototype.startLoad = function () { var a = this; a.options.arrows === !0 && a.slideCount > a.options.slidesToShow && (a.$prevArrow.hide(), a.$nextArrow.hide()), a.options.dots === !0 && a.slideCount > a.options.slidesToShow && a.$dots.hide(), a.$slider.addClass("slick-loading") }, b.prototype.swipeDirection = function () { var a, b, c, d, e = this; return a = e.touchObject.startX - e.touchObject.curX, b = e.touchObject.startY - e.touchObject.curY, c = Math.atan2(b, a), d = Math.round(180 * c / Math.PI), 0 > d && (d = 360 - Math.abs(d)), 45 >= d && d >= 0 ? e.options.rtl === !1 ? "left" : "right" : 360 >= d && d >= 315 ? e.options.rtl === !1 ? "left" : "right" : d >= 135 && 225 >= d ? e.options.rtl === !1 ? "right" : "left" : e.options.verticalSwiping === !0 ? d >= 35 && 135 >= d ? "left" : "right" : "vertical" }, b.prototype.swipeEnd = function (a) { var c, b = this; if (b.dragging = !1, b.shouldClick = b.touchObject.swipeLength > 10 ? !1 : !0, void 0 === b.touchObject.curX) return !1; if (b.touchObject.edgeHit === !0 && b.$slider.trigger("edge", [b, b.swipeDirection()]), b.touchObject.swipeLength >= b.touchObject.minSwipe) switch (b.swipeDirection()) { case "left": c = b.options.swipeToSlide ? b.checkNavigable(b.currentSlide + b.getSlideCount()) : b.currentSlide + b.getSlideCount(), b.slideHandler(c), b.currentDirection = 0, b.touchObject = {}, b.$slider.trigger("swipe", [b, "left"]); break; case "right": c = b.options.swipeToSlide ? b.checkNavigable(b.currentSlide - b.getSlideCount()) : b.currentSlide - b.getSlideCount(), b.slideHandler(c), b.currentDirection = 1, b.touchObject = {}, b.$slider.trigger("swipe", [b, "right"]) } else b.touchObject.startX !== b.touchObject.curX && (b.slideHandler(b.currentSlide), b.touchObject = {}) }, b.prototype.swipeHandler = function (a) { var b = this; if (!(b.options.swipe === !1 || "ontouchend" in document && b.options.swipe === !1 || b.options.draggable === !1 && -1 !== a.type.indexOf("mouse"))) switch (b.touchObject.fingerCount = a.originalEvent && void 0 !== a.originalEvent.touches ? a.originalEvent.touches.length : 1, b.touchObject.minSwipe = b.listWidth / b.options.touchThreshold, b.options.verticalSwiping === !0 && (b.touchObject.minSwipe = b.listHeight / b.options.touchThreshold), a.data.action) { case "start": b.swipeStart(a); break; case "move": b.swipeMove(a); break; case "end": b.swipeEnd(a) } }, b.prototype.swipeMove = function (a) { var d, e, f, g, h, b = this; return h = void 0 !== a.originalEvent ? a.originalEvent.touches : null, !b.dragging || h && 1 !== h.length ? !1 : (d = b.getLeft(b.currentSlide), b.touchObject.curX = void 0 !== h ? h[0].pageX : a.clientX, b.touchObject.curY = void 0 !== h ? h[0].pageY : a.clientY, b.touchObject.swipeLength = Math.round(Math.sqrt(Math.pow(b.touchObject.curX - b.touchObject.startX, 2))), b.options.verticalSwiping === !0 && (b.touchObject.swipeLength = Math.round(Math.sqrt(Math.pow(b.touchObject.curY - b.touchObject.startY, 2)))), e = b.swipeDirection(), "vertical" !== e ? (void 0 !== a.originalEvent && b.touchObject.swipeLength > 4 && a.preventDefault(), g = (b.options.rtl === !1 ? 1 : -1) * (b.touchObject.curX > b.touchObject.startX ? 1 : -1), b.options.verticalSwiping === !0 && (g = b.touchObject.curY > b.touchObject.startY ? 1 : -1), f = b.touchObject.swipeLength, b.touchObject.edgeHit = !1, b.options.infinite === !1 && (0 === b.currentSlide && "right" === e || b.currentSlide >= b.getDotCount() && "left" === e) && (f = b.touchObject.swipeLength * b.options.edgeFriction, b.touchObject.edgeHit = !0), b.options.vertical === !1 ? b.swipeLeft = d + f * g : b.swipeLeft = d + f * (b.$list.height() / b.listWidth) * g, b.options.verticalSwiping === !0 && (b.swipeLeft = d + f * g), b.options.fade === !0 || b.options.touchMove === !1 ? !1 : b.animating === !0 ? (b.swipeLeft = null, !1) : void b.setCSS(b.swipeLeft)) : void 0) }, b.prototype.swipeStart = function (a) { var c, b = this; return 1 !== b.touchObject.fingerCount || b.slideCount <= b.options.slidesToShow ? (b.touchObject = {}, !1) : (void 0 !== a.originalEvent && void 0 !== a.originalEvent.touches && (c = a.originalEvent.touches[0]), b.touchObject.startX = b.touchObject.curX = void 0 !== c ? c.pageX : a.clientX, b.touchObject.startY = b.touchObject.curY = void 0 !== c ? c.pageY : a.clientY, void (b.dragging = !0)) }, b.prototype.unfilterSlides = b.prototype.slickUnfilter = function () { var a = this; null !== a.$slidesCache && (a.unload(), a.$slideTrack.children(this.options.slide).detach(), a.$slidesCache.appendTo(a.$slideTrack), a.reinit()) }, b.prototype.unload = function () { var b = this; a(".slick-cloned", b.$slider).remove(), b.$dots && b.$dots.remove(), b.$prevArrow && b.htmlExpr.test(b.options.prevArrow) && b.$prevArrow.remove(), b.$nextArrow && b.htmlExpr.test(b.options.nextArrow) && b.$nextArrow.remove(), b.$slides.removeClass("slick-slide slick-active slick-visible slick-current").attr("aria-hidden", "true").css("width", "") }, b.prototype.unslick = function (a) { var b = this; b.$slider.trigger("unslick", [b, a]), b.destroy() }, b.prototype.updateArrows = function () { var b, a = this; b = Math.floor(a.options.slidesToShow / 2), a.options.arrows === !0 && a.slideCount > a.options.slidesToShow && !a.options.infinite && (a.$prevArrow.removeClass("slick-disabled").attr("aria-disabled", "false"), a.$nextArrow.removeClass("slick-disabled").attr("aria-disabled", "false"), 0 === a.currentSlide ? (a.$prevArrow.addClass("slick-disabled").attr("aria-disabled", "true"), a.$nextArrow.removeClass("slick-disabled").attr("aria-disabled", "false")) : a.currentSlide >= a.slideCount - a.options.slidesToShow && a.options.centerMode === !1 ? (a.$nextArrow.addClass("slick-disabled").attr("aria-disabled", "true"), a.$prevArrow.removeClass("slick-disabled").attr("aria-disabled", "false")) : a.currentSlide >= a.slideCount - 1 && a.options.centerMode === !0 && (a.$nextArrow.addClass("slick-disabled").attr("aria-disabled", "true"), a.$prevArrow.removeClass("slick-disabled").attr("aria-disabled", "false"))) }, b.prototype.updateDots = function () { var a = this; null !== a.$dots && (a.$dots.find("li").removeClass("slick-active").attr("aria-hidden", "true"), a.$dots.find("li").eq(Math.floor(a.currentSlide / a.options.slidesToScroll)).addClass("slick-active").attr("aria-hidden", "false")) }, b.prototype.visibility = function () { var a = this; document[a.hidden] ? (a.paused = !0, a.autoPlayClear()) : a.options.autoplay === !0 && (a.paused = !1, a.autoPlay()) }, b.prototype.initADA = function () { var b = this; b.$slides.add(b.$slideTrack.find(".slick-cloned")).attr({ "aria-hidden": "true", tabindex: "-1" }).find("a, input, button, select").attr({ tabindex: "-1" }), b.$slideTrack.attr("role", "listbox"), b.$slides.not(b.$slideTrack.find(".slick-cloned")).each(function (c) { a(this).attr({ role: "option", "aria-describedby": "slick-slide" + b.instanceUid + c }) }), null !== b.$dots && b.$dots.attr("role", "tablist").find("li").each(function (c) { a(this).attr({ role: "presentation", "aria-selected": "false", "aria-controls": "navigation" + b.instanceUid + c, id: "slick-slide" + b.instanceUid + c }) }).first().attr("aria-selected", "true").end().find("button").attr("role", "button").end().closest("div").attr("role", "toolbar"), b.activateADA() }, b.prototype.activateADA = function () { var a = this; a.$slideTrack.find(".slick-active").attr({ "aria-hidden": "false" }).find("a, input, button, select").attr({ tabindex: "0" }) }, b.prototype.focusHandler = function () { var b = this; b.$slider.on("focus.slick blur.slick", "*", function (c) { c.stopImmediatePropagation(); var d = a(this); setTimeout(function () { b.isPlay && (d.is(":focus") ? (b.autoPlayClear(), b.paused = !0) : (b.paused = !1, b.autoPlay())) }, 0) }) }, a.fn.slick = function () { var f, g, a = this, c = arguments[0], d = Array.prototype.slice.call(arguments, 1), e = a.length; for (f = 0; e > f; f++) if ("object" == typeof c || "undefined" == typeof c ? a[f].slick = new b(a[f], c) : g = a[f].slick[c].apply(a[f].slick, d), "undefined" != typeof g) return g; return a }
5408});
5409
5410
5411
5412/* Utils */
5413function loadScript(url, callback) {
5414
5415 var script = document.createElement("script")
5416 script.type = "text/javascript";
5417
5418 if (script.readyState) { //IE
5419 script.onreadystatechange = function () {
5420 if (script.readyState == "loaded" ||
5421 script.readyState == "complete") {
5422 script.onreadystatechange = null;
5423 callback();
5424 }
5425 };
5426 } else { //Others
5427 script.onload = function () {
5428 callback();
5429 };
5430 }
5431
5432 script.src = url;
5433 document.body.appendChild(script);
5434}
5435document.addEventListener("DOMContentLoaded", function() {
5436 var lazyloadImages;
5437
5438 if ("IntersectionObserver" in window) {
5439 lazyloadImages = document.querySelectorAll(".lazy");
5440 var imageObserver = new IntersectionObserver(function(entries, observer) {
5441 entries.forEach(function(entry) {
5442 if (entry.isIntersecting) {
5443 var image = entry.target;
5444 image.src = image.dataset.src;
5445 image.classList.remove("lazy");
5446 imageObserver.unobserve(image);
5447 }
5448 });
5449 });
5450
5451 lazyloadImages.forEach(function(image) {
5452 imageObserver.observe(image);
5453 });
5454 } else {
5455 var lazyloadThrottleTimeout;
5456 lazyloadImages = document.querySelectorAll(".lazy");
5457
5458 function lazyload () {
5459 if(lazyloadThrottleTimeout) {
5460 clearTimeout(lazyloadThrottleTimeout);
5461 }
5462
5463 lazyloadThrottleTimeout = setTimeout(function() {
5464 var scrollTop = window.pageYOffset;
5465 lazyloadImages.forEach(function(img) {
5466 if(img.offsetTop < (window.innerHeight + scrollTop)) {
5467 img.src = img.dataset.src;
5468 img.classList.remove('lazy');
5469 }
5470 });
5471 if(lazyloadImages.length == 0) {
5472 document.removeEventListener("scroll", lazyload);
5473 window.removeEventListener("resize", lazyload);
5474 window.removeEventListener("orientationChange", lazyload);
5475 }
5476 }, 20);
5477 }
5478
5479 document.addEventListener("scroll", lazyload);
5480 window.addEventListener("resize", lazyload);
5481 window.addEventListener("orientationChange", lazyload);
5482 }
5483})
5484
5485
5486///****************************** CART NAVIGATION JS ******************************///
5487///****************************** CART NAVIGATION JS ******************************///
5488///****************************** CART NAVIGATION JS ******************************///
5489///****************************** CART NAVIGATION JS ******************************///
5490
5491jQuery(document).ready(function($){
5492 //if you change this breakpoint in the style.css file (or _layout.scss if you use SASS), don't forget to update this value as well
5493 var $L = 1200,
5494 $menu_navigation = $('#main-nav'),
5495 $cart_trigger = $('#cd-cart-trigger'),
5496 $hamburger_icon = $('#cd-hamburger-menu'),
5497 $lateral_cart = $('#cd-cart'),
5498 $shadow_layer = $('#cd-shadow-layer');
5499
5500 //open lateral menu on mobile
5501 $hamburger_icon.on('click', function(event){
5502 event.preventDefault();
5503 //close cart panel (if it's open)
5504 $lateral_cart.removeClass('speed-in');
5505 toggle_panel_visibility($menu_navigation, $shadow_layer, $('body'));
5506 });
5507
5508 //open cart
5509 $cart_trigger.on('click', function(event){
5510 event.preventDefault();
5511 //close lateral menu (if it's open)
5512 $menu_navigation.removeClass('speed-in');
5513 toggle_panel_visibility($lateral_cart, $shadow_layer, $('body'));
5514 });
5515
5516 //close lateral cart or lateral menu
5517 $shadow_layer.on('click', function(){
5518 $shadow_layer.removeClass('is-visible');
5519 // firefox transitions break when parent overflow is changed, so we need to wait for the end of the trasition to give the body an overflow hidden
5520 if( $lateral_cart.hasClass('speed-in') ) {
5521 $lateral_cart.removeClass('speed-in').on('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend', function(){
5522 $('body').removeClass('overflow-hidden');
5523 });
5524 $menu_navigation.removeClass('speed-in');
5525 } else {
5526 $menu_navigation.removeClass('speed-in').on('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend', function(){
5527 $('body').removeClass('overflow-hidden');
5528 });
5529 $lateral_cart.removeClass('speed-in');
5530 }
5531 });
5532
5533 //move #main-navigation inside header on laptop
5534 //insert #main-navigation after header on mobile
5535 move_navigation( $menu_navigation, $L);
5536 $(window).on('resize', function(){
5537 move_navigation( $menu_navigation, $L);
5538
5539 if( $(window).width() >= $L && $menu_navigation.hasClass('speed-in')) {
5540 $menu_navigation.removeClass('speed-in');
5541 $shadow_layer.removeClass('is-visible');
5542 $('body').removeClass('overflow-hidden');
5543 }
5544
5545 });
5546});
5547
5548function toggle_panel_visibility ($lateral_panel, $background_layer, $body) {
5549 if( $lateral_panel.hasClass('speed-in') ) {
5550 // firefox transitions break when parent overflow is changed, so we need to wait for the end of the trasition to give the body an overflow hidden
5551 $lateral_panel.removeClass('speed-in').one('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend', function(){
5552 $body.removeClass('overflow-hidden');
5553 });
5554 $background_layer.removeClass('is-visible');
5555
5556 } else {
5557 $lateral_panel.addClass('speed-in').one('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend', function(){
5558 $body.addClass('overflow-hidden');
5559 });
5560 $background_layer.addClass('is-visible');
5561 }
5562}
5563
5564function move_navigation( $navigation, $MQ) {
5565 if ( $(window).width() >= $MQ ) {
5566 $navigation.detach();
5567 $navigation.appendTo('header');
5568 } else {
5569 $navigation.detach();
5570 $navigation.insertAfter('header');
5571 }
5572}
5573function wordInString(str, word) {
5574 return new RegExp("\\b" + word + "\\b", "i").test(str);
5575}
5576var loading_img =
5577"<img src='http://cartt.co/images/ajax-loader.gif' style='padding-top:10px' />";
5578function chk_user_pass_login() {
5579 //remove all the class add the messagebox classes and start fading
5580 $("#msgbox")
5581 .removeClass()
5582 .addClass("messagebox")
5583 .text("Validating....")
5584 .fadeIn(1000);
5585 var url = "/my_ajax/ajax_login";
5586 url = url + "?email=" + $("#email").val();
5587 url = url + "&password=" + $("#password").val();
5588 url = url + "&tts=" + new Date().getMilliseconds();
5589 url = encodeURI(url);
5590 $.get(url, function(data) {
5591 display_afterlogin(data);
5592 });
5593}
5594function display_afterlogin(data) {
5595 if (jQuery.trim(data) == "1") {
5596 //if correct login detail
5597 $("#msgbox").fadeTo(200, 0.1, function() //start fading the messagebox
5598 {
5599 //add message and change the class of the box and start fading
5600 $(this)
5601 .html("Logging in.....")
5602 .addClass("messageboxok")
5603 .fadeTo(900, 1, function() {
5604 //redirect to secure page
5605 $("#login_form").fadeOut(1000);
5606 if (isie) {
5607 window.location.href = "/checkout?cache=" + "<?=$rand_time_var?>";
5608 return;
5609 } else {
5610 window.location.href = "/checkout";
5611 return;
5612 }
5613 /* show_billing_block();
5614 show_shipping_block(1);
5615 update_order_summary_block(document.processorder_frm.shipping_method_hidden, 0);
5616 display_promo_code_block();
5617 show_viparea(); */
5618 });
5619 });
5620} else {
5621 $("#msgbox").fadeTo(200, 0.1, function() //start fading the messagebox
5622 {
5623 //add message and change the class of the box and start fading
5624 $(this)
5625 .html("Incorrect login details...")
5626 .addClass("messageboxerror")
5627 .fadeTo(900, 1);
5628 });
5629}
5630}
5631function show_billing_block() {
5632 $("#billing_block").html = loading_img;
5633 var url = "/my_ajax/ajax_billingblock?tts=" + new Date().getMilliseconds();
5634 $.get(url, function(data) {
5635 $("#billing_block").html(data);
5636 $("#address2_geo").bind("keydown", function(e) {
5637 if (window.event) key = window.event.keyCode;
5638 //IE
5639 else key = e.which; //firefox
5640 // alert(key);
5641 if (key === 13) {
5642 e.preventDefault();
5643 return false;
5644 }
5645 });
5646 });
5647}
5648function show_shipping_block(fromwhere) {
5649 $("#shipping_block").html(loading_img);
5650 var url =
5651 "/my_ajax/ajax_shippingblock?show_default=" +
5652 fromwhere +
5653 "&tts=" +
5654 new Date().getMilliseconds();
5655 $.get(url, function(data) {
5656 $("#shipping_block").html(data);
5657 setTimeout(show_shipping_method_block, 3000);
5658 $("#ship_address2_geo").bind("keydown", function(e) {
5659 if (window.event) key = window.event.keyCode;
5660 //IE
5661 else key = e.which; //firefox
5662 // alert(key);
5663 if (key === 13) {
5664 e.preventDefault();
5665 return false;
5666 }
5667 });
5668 // show_shipping_method_block();
5669});
5670 if (typeof sfw === "undefined" || sfw === null) {
5671 // variable is undefined or null
5672} else {
5673 sfw.refresh();
5674}
5675}
5676function update_order_summary_block(onload) {
5677 $("#order_summary_block").html(loading_img);
5678 pmobj = document.getElementById("pmChecked");
5679 // alert(pmobj.value + ' pmchecked' );
5680 set_extra_gateway_price(pmobj, 1);
5681 var ship_country = 0;
5682 var ship_zip = 0;
5683 if (document.processorder_frm.shipping_method_hidden)
5684 var shipping_method =
5685 document.processorder_frm.shipping_method_hidden.value;
5686 else var shipping_method = "1-aupost";
5687 if (onload < 1) {
5688 if (document.processorder_frm.ship_country) {
5689 ship_country = document.processorder_frm.ship_country.value;
5690 ship_zip = document.processorder_frm.ship_zip.value;
5691 ship_city = document.processorder_frm.ship_city.value;
5692 }
5693 } else {
5694 ship_country = "<?=$cust_user_country?>";
5695 ship_zip = "<?=$cust_user_zip?>";
5696 ship_city = "<?=$cust_user_city?>";
5697 }
5698 var url =
5699 "/my_ajax/ajax_order_summary_block?ship_country=" +
5700 ship_country +
5701 "&shipping_method=" +
5702 shipping_method +
5703 "&ship_zip=" +
5704 ship_zip +
5705 "&ship_city=" +
5706 ship_city +
5707 "&tts=" +
5708 new Date().getMilliseconds();
5709 $.get(url, function(data) {
5710 $("#order_summary_block").html(data);
5711 display_grand_total();
5712 //return true;
5713});
5714}
5715function display_promo_code_block() {
5716 //alert('here display_promo_code_block');
5717 var url = "/my_ajax/ajax_discount_block?tts=" + new Date().getMilliseconds();
5718 $.get(url, function(data) {
5719 //alert(data + 'here');
5720 $("#discount_block").html(data);
5721});
5722}
5723function validate_discount() {
5724 var url = "/my_ajax/ajax_validate_discount?discount_code=";
5725 discount_code = document.getElementById("discount_code").value;
5726 url = url + discount_code;
5727 url = url + "&tts=" + new Date().getMilliseconds();
5728 $.get(url, function(data) {
5729 calculate_discount(data);
5730 });
5731}
5732function delete_item(key) {
5733 var url = "/my_ajax/ajax_delete_from_cart";
5734 url =
5735 url +
5736 "?delid=" +
5737 key +
5738 "&fromarea=checkout" +
5739 "&tts=" +
5740 new Date().getMilliseconds();
5741 $.get(url, function(data) {
5742 update_cartitems_block();
5743 update_order_summary_block();
5744 show_shipping_method_block();
5745 if (typeof sfw === "undefined" || sfw === null) {
5746 // variable is undefined or null
5747 } else {
5748 sfw.refresh();
5749 }
5750});
5751}
5752function calculate_discount(data) {
5753 if (jQuery.trim(data) == "1") {
5754 $("#disc_msgbox").fadeTo(200, 0.1, function() //start fading the messagebox
5755 {
5756 //add message and change the class of the box and start fading
5757 $(this)
5758 .html("validating...")
5759 .addClass("messageboxok")
5760 .fadeTo(200, 1, function() {
5761 $("#disc_msgbox").fadeOut(1000);
5762 update_order_summary_block(0);
5763 });
5764 });
5765} else {
5766 $("#disc_msgbox").fadeTo(200, 0.1, function() //start fading the messagebox
5767 {
5768 var error_msg;
5769 error_msg = jQuery.trim(data);
5770 $(this)
5771 .html(error_msg)
5772 .addClass("messageboxerror")
5773 .fadeTo(900, 1);
5774 });
5775}
5776}
5777function chk_user_login(obj) {
5778 if (!chk_email(obj)) {
5779 alert("Enter valid email");
5780 obj.focus();
5781 return false;
5782 }
5783 cemail = document.getElementById("cemail").value;
5784 if (obj.value != cemail) {
5785 alert("Emails do not match");
5786 return false;
5787 }
5788 var url = "/my_ajax/ajax_login_by_email?email=";
5789 email = obj.value;
5790 url = url + email + "&tts=" + new Date().getMilliseconds();
5791 $.get(url, function(data) {
5792 validate_login(data);
5793 });
5794}
5795function validate_login(data) {
5796 if (jQuery.trim(data) == "1") {
5797 //do ajax calls..
5798 show_billing_block();
5799}
5800update_order_summary_block(0);
5801display_promo_code_block();
5802show_viparea();
5803}
5804function setstatefield(obj, cust_state) {
5805 if (obj.value != 463) {
5806 // $("#ship_zip").attr('maxlength','20');
5807 //document.getElementById('ship_zip').maxLength =20;
5808} else {
5809 // $("#ship_zip").attr('maxlength','4');
5810 // if(document.getElementById('ship_zip').value.length>4) document.getElementById('ship_zip').value=document.getElementById('ship_zip').value.substr(0, 4);
5811 //document.getElementById('ship_zip').maxLength =4;
5812}
5813var url = "/my_ajax/ajax_set_state";
5814url = url + "?sid=" + Math.random();
5815url = url + "&country=" + obj.value;
5816url = url + "&state=" + cust_state;
5817$.get(url, function(data) {
5818 $("#ShipStateOtherRow").html(data);
5819 show_shipping_method_block();
5820 if (typeof sfw === "undefined" || sfw === null) {
5821 // variable is undefined or null
5822 } else {
5823 sfw.refresh();
5824 }
5825});
5826 /*
5827 if(obj.value!=463)
5828 {
5829 document.getElementById('ship_state').selectedIndex=0;
5830 }
5831 */
5832}
5833function setstatefield_billing(obj, cust_state) {
5834 if (obj.value != 463) {
5835 //$("#zip").attr('maxlength','20');
5836 //document.getElementById('ship_zip').maxLength =20;
5837} else {
5838 //$("#zip").attr('maxlength','4');
5839 //if(document.getElementById('zip').value.length>4) document.getElementById('zip').value=document.getElementById('zip').value.substr(0, 4);
5840 //document.getElementById('ship_zip').maxLength =4;
5841}
5842var url = "/my_ajax/ajax_set_state";
5843url = url + "?sid=" + Math.random();
5844url = url + "&state_type=bill";
5845url = url + "&country=" + obj.value;
5846url = url + "&state=" + cust_state;
5847$.get(url, function(data) {
5848 $("#BillStateOtherRow").html(data);
5849});
5850}
5851function validate_checkout(obj) {
5852 var msg = "";
5853 if (
5854 obj.ship_first_name.value.length == 0 ||
5855 obj.ship_first_name.value == "First Name"
5856 )
5857 msg += "Enter Recipient's First Name\n";
5858 if (
5859 obj.ship_last_name.value.length == 0 ||
5860 obj.ship_last_name.value == "Last Name"
5861 )
5862 msg += "Enter Last Name\n";
5863 if ($("#ship_address1").val() == "Unit/Shop/Floor No.")
5864 $("#ship_address1").val("");
5865 if (obj.ship_company.value == "Company Name (if applicable)")
5866 obj.ship_company.value = "";
5867 if (
5868 obj.ship_address2.value.length == 0 ||
5869 obj.ship_address2.value == "Street Number and Name"
5870 )
5871 msg += "Please Enter Your Street Number and Name\n";
5872 if (
5873 obj.ship_city.value.length == 0 ||
5874 obj.ship_city.value == "Town/City/Suburb"
5875 )
5876 msg += "Enter Town/City\n";
5877 // alert(obj.ship_state.value);
5878 if (obj.ship_state.value.length == 0 && obj.ship_country.value == 463)
5879 //200812 fiji / new zealand don't have states
5880msg += "Enter State/Province\n";
5881if (obj.ship_country.value == 0) msg += "Select Country\n";
5882if (obj.ship_zip.value.length == 0 || obj.ship_zip.value == "Post Code")
5883 msg += "Enter Zip/Postal Code\n";
5884else if (obj.ship_country.value == 463 && obj.ship_zip.value.length != 4)
5885 msg += "Enter Zip/Postal Code\n";
5886 // if(obj.ship_phone_area.value.length==0 || obj.ship_phone_area.value=='Area') msg+='Enter an area code for your shipping phone number\n';
5887 if (
5888 obj.ship_phone.value.length == 0 ||
5889 obj.ship_phone.value == "Phone Number"
5890 )
5891 msg += "Enter Shipping Phone Number\n";
5892 if (obj.shipping_ok.value == 0) {
5893 msg += "Select Shipping Method\n";
5894 }
5895 if (obj.shipping_method_hidden.value.length == 0)
5896 msg += "Select Shipping Method\n";
5897 var chk_pobox = 0;
5898 /*
5899 if(wordInString(obj.ship_address1.value, 'po box') || wordInString(obj.ship_address1.value, 'p.o box') || wordInString(obj.ship_address1.value, 'p.o. box') || wordInString(obj.ship_address1.value, 'p o box'))
5900 {
5901 chk_pobox=1;
5902 }
5903 */
5904 if (chk_pobox == 0) {
5905 if (
5906 wordInString(obj.ship_address2.value, "po box") ||
5907 wordInString(obj.ship_address2.value, "p.o box") ||
5908 wordInString(obj.ship_address2.value, "p.o. box") ||
5909 wordInString(obj.ship_address2.value, "p o box")
5910 ) {
5911 chk_pobox = 1;
5912 }
5913}
5914if (chk_pobox == 0) {
5915 if (
5916 wordInString(obj.ship_city.value, "po box") ||
5917 wordInString(obj.ship_city.value, "p.o box") ||
5918 wordInString(obj.ship_city.value, "p.o. box") ||
5919 wordInString(obj.ship_city.value, "p o box")
5920 ) {
5921 chk_pobox = 1;
5922}
5923}
5924if (chk_pobox == 1) {
5925 //if 1 only AUPost is allowed..
5926 if (
5927 $("input[name=shipping_method]:checked", "#processorder_frm").val() == 1
5928 ) {
5929 msg +=
5930 "It appears as though you are trying\n to send your items to a PO Box.\n Please note that this is not possible.\n Please provide a standard \nresidential or business address";
5931}
5932 // return false;
5933}
5934if (msg.length > 0) {
5935 alert(msg);
5936 sfw.goTo(0);
5937 return false;
5938}
5939if (
5940 obj.cemail.value.length == 0 ||
5941 obj.cemail.value == "Confirm Email Address"
5942 )
5943 msg += "Enter Email\n";
5944if (obj.email.value.length == 0 || obj.email.value == "Email Address")
5945 msg += "Please confirm your Email Address\n";
5946else if (obj.email.value != obj.cemail.value) msg += "Emails do not match\n";
5947if (!obj.agreecheck.checked) {
5948 if (obj.first_name.value.length == 0)
5949 msg += "Enter First Name on Account\n";
5950 if (obj.last_name.value.length == 0) msg += "Enter Last Name on Account\n";
5951 if (obj.address2.value.length == 0) msg += "Enter Billing Address\n";
5952 if (obj.city.value.length == 0) msg += "Enter Billing Town/City\n";
5953 if (obj.state.value.length == 0) msg += "Enter Billing State/Province\n";
5954 if (obj.zip.value.length == 0) msg += "Enter Billing Zip/Postal Code\n";
5955 /*if(obj.phone_area.value.length==0) msg+='Enter an area code for your Billing Phone Number\n'; */
5956 if (obj.phone.value.length == 0) msg += "Enter a Billing Phone Number\n";
5957}
5958/*ATL options */
5959if (
5960 obj.delivery_instructions.value.length > 0 &&
5961 obj.delivery_instructions.value !=
5962 "Click here and select your Authority to Leave options"
5963 ) {
5964 if (!obj.agree_atl.checked) {
5965 msg += "Please agree to ATL\n";
5966 }
5967 sfw.goTo(0);
5968}
5969if (document.processorder_frm.agree_atl) {
5970 if (
5971 obj.agree_atl.checked &&
5972 obj.delivery_instructions.value ==
5973 "Click here and select your Authority to Leave options"
5974 ) {
5975 //150816
5976 msg += "Please select an ATL option\n";
5977}
5978sfw.goTo(0);
5979}
5980if (msg.length == 0) {
5981 if (obj.pmChecked.value == 1 || obj.pmChecked.value == 1) {
5982 //CC capture / Gateway
5983 if (obj.is_account.value != 1) {
5984 //if((obj.txtCCAccount1.value.length + obj.txtCCAccount2.value.length + obj.txtCCAccount3.value.length + obj.txtCCAccount4.value.length)<13) msg+='Enter Credit Card No\n';
5985 var use_saved_card = $("#use_saved_card:checkbox:checked").length > 0;
5986 if (!use_saved_card) {
5987 if (
5988 obj.frm_cc_number.value.length < 13 ||
5989 isNaN(obj.frm_cc_number.value)
5990 )
5991 msg += "Enter valid Credit Card No\n";
5992 // if(obj.txtCCAccountName.value.length<13) msg+='Enter name on Card\n';
5993 if (obj.txtCCV.value.length == 0) msg += "Enter CVV\n";
5994 }
5995 } else obj.pmChecked.value = 3; //if account.. User choose to pay by Bank Deposit
5996 }
5997}
5998if (msg.length > 0) {
5999 alert(msg);
6000 return false;
6001}
6002 //empty default values..
6003 if (obj.ship_company.value == "Company Name (if applicable)")
6004 obj.ship_company.value = "";
6005 // if(obj.ship_abn.value=='Purchase Order Number') obj.ship_abn.value='';
6006 if (obj.ship_address1.value == "Unit/Shop/Floor No.")
6007 obj.ship_address1.value = "";
6008 if (obj.ship_address2.value == "Street Number and Name")
6009 obj.ship_address2.value = "";
6010 checkoutProcessStarted = document.getElementById("checkoutProcessStarted")
6011 .value;
6012 if (checkoutProcessStarted == 1) {
6013 alert("Order is under process. Kindly wait...");
6014 return false;
6015 exit;
6016 }
6017 document.getElementById("checkoutProcessStarted").value = 1;
6018 $.prompt(
6019 'Please wait while we process your payment. This can take up to 60 seconds.<br><br><span style="color:red; font-size:14px">Do not refresh the page or you may be charged twice.</span><br><br>Please do not click your back button.<br>Thankyou!'
6020 );
6021 return true;
6022}
6023function add_special(prod_id) {
6024 var url =
6025 "/my_ajax/ajax_add_to_cart_special?tts=" + new Date().getMilliseconds();
6026 $.get(url, function(data) {
6027 update_order_summary_block(0);
6028 update_cartitems_block();
6029 $("#super_upsell").fadeOut(1000);
6030 });
6031}
6032function display_grand_total() {
6033 var url =
6034 "/my_ajax/ajax_display_grand_total?tts=" + new Date().getMilliseconds();
6035 $.get(url, function(data) {
6036 str = data.split("donotprocess"); //minimum order criteria not met
6037 if (str.length > 1) {
6038 window.location.href = "cart";
6039 }
6040 // alert(data);
6041 str = data.split("voucher"); //if voucher..
6042 // alert(str.length);
6043 if (str.length > 1) {
6044 $("#pmChecked").val(3); //set as offline payment....
6045 } else {
6046 var radio_chosen = 0;
6047 if ($("#PayByCC").is(":checked")) {
6048 radio_chosen++;
6049 $("#pmChecked").val(1);
6050 }
6051 if ($("#PayByPayPal").is(":checked")) {
6052 radio_chosen++;
6053 $("#pmChecked").val(2);
6054 }
6055 if ($("#zip-checkout").is(":checked")) {
6056 radio_chosen++;
6057 $("#pmChecked").val(4);
6058 }
6059 if (radio_chosen == 0) $("#pmChecked").val(1); //default
6060 }
6061 $("#order_total_001").html(data);
6062});
6063}
6064function update_cartitems_block() {
6065 var url = "/my_ajax/ajax_display_cartitem?tts=" + new Date().getMilliseconds();
6066 $.get(url, function(data) {
6067 $("#my_cart").html(data);
6068 });
6069}
6070function add_donation(prod_id) {
6071 var url = "/my_ajax/ajax_add_to_cart_donation";
6072 qty = document.getElementById("donation_qty").value;
6073 url = url + "?qty=" + qty + "&tts=" + new Date().getMilliseconds();
6074 $.get(url, function(data) {
6075 update_cartitems_block();
6076 update_order_summary_block(0);
6077 });
6078}
6079function checkout_modify(form) {
6080 var dta = $("form").serialize();
6081 var url = "/cart/modify_checkout_cart?tts=" + new Date().getMilliseconds();
6082 $.get(url, dta, function(data) {
6083 update_cartitems_block();
6084 var bool = update_order_summary_block(0);
6085 show_shipping_method_block();
6086 if (typeof sfw === "undefined" || sfw === null) {
6087 // variable is undefined or null
6088 } else {
6089 sfw.refresh();
6090 }
6091});
6092}
6093function set_extra_gateway_price(obj, when) {
6094 gateway_selected = obj.value;
6095 var url =
6096 "/my_ajax/ajax_set_extra_gateway_price?tts=" +
6097 new Date().getMilliseconds() +
6098 "&gateway_selected=" +
6099 gateway_selected;
6100 $.get(url, function(data) {
6101 if (when != 1) update_order_summary_block(0);
6102 });
6103}
6104function show_hide_delivery_instructions(whattodo) {
6105 if (whattodo == "show") {
6106 $("#delivery_instructions_div").show();
6107 } else {
6108 $("#delivery_instructions_div").hide();
6109 $("#delivery_instructions").val(
6110 "Click here and select your Authority to Leave options"
6111 );
6112 }
6113 if (typeof sfw === "undefined" || sfw === null) {
6114 // variable is undefined or null
6115} else {
6116 sfw.refresh();
6117}
6118}
6119function show_shipping_method_block() {
6120 $("#shipping_method_block").html(loading_img);
6121 if (document.processorder_frm.ship_country) {
6122 var ship_country = document.processorder_frm.ship_country.value;
6123 } else {
6124 var ship_country = "463";
6125 }
6126 var ship_zip = "";
6127 var ship_city = "";
6128 if (document.processorder_frm.ship_zip) {
6129 ship_zip = document.processorder_frm.ship_zip.value;
6130 }
6131 if (document.processorder_frm.ship_city) {
6132 ship_city = document.processorder_frm.ship_city.value;
6133 }
6134 if (document.processorder_frm.ship_state) {
6135 ship_state = document.processorder_frm.ship_state.value;
6136 }
6137 var url =
6138 "/my_ajax/ajax_shipping_method_block?ship_country=" +
6139 ship_country +
6140 "&ship_zip=" +
6141 ship_zip +
6142 "&ship_city=" +
6143 ship_city +
6144 "&ship_state=" +
6145 ship_state +
6146 "&tts=" +
6147 new Date().getMilliseconds();
6148 $.get(url, function(data) {
6149 $("#shipping_method_block").html(data);
6150 document.getElementById("shipping_ok").value = 0;
6151 var str = data;
6152 str = str.split("freight zone"); //incorrect zip code entered..
6153 if (str.length <= 1) document.getElementById("shipping_ok").value = 1;
6154 update_order_summary_block(0);
6155 if (typeof sfw === "undefined" || sfw === null) {
6156 // variable is undefined or null
6157 } else {
6158 sfw.refresh();
6159 }
6160});
6161 if (typeof sfw === "undefined" || sfw === null) {
6162 // variable is undefined or null
6163} else {
6164 sfw.refresh();
6165}
6166}
6167function validate_address() {
6168 var country = $("#ship_country").val();
6169 if (country != 463) return true; //validate address only for AU
6170 var city = $("#ship_city").val();
6171 var state = $("#ship_state").val();
6172 var zip = $("#ship_zip").val();
6173 var url =
6174 "/my_ajax/ajax_validate_address?tts=" + new Date().getMilliseconds();
6175 url += "&city=" + city + "&state=" + state + "&zip=" + zip;
6176 // alert(url);
6177 $.get(url, function(data) {
6178 //alert(data);
6179 if (data == 1) return true;
6180 else {
6181 alert("Kindly check your address fields (City, State, Post Code)");
6182 sfw.goTo(0);
6183 return false;
6184 }
6185});
6186}
6187$(document).ready(function() {
6188 display_promo_code_block();
6189 show_billing_block();
6190 show_shipping_block("");
6191 show_viparea();
6192 update_order_summary_block(
6193 document.processorder_frm.shipping_method_hidden,
6194 1
6195 );
6196 setTimeout(initAutocomplete, 3000);
6197 //initAutocomplete();
6198});
6199function map_google_shipcountry(country, state) {
6200 // alert(country);
6201 var url = "/my_ajax/ajax_get_country_id?country_name=" + country;
6202 url = url + "&tts=" + new Date().getMilliseconds();
6203 $.get(url, function(data) {
6204 //alert(data);
6205 $("#ship_country").val(data);
6206 setstatefield(document.processorder_frm.ship_country, state);
6207});
6208 update_order_summary_block(0);
6209 document.processorder_frm.shipping_method_hidden.value = "0";
6210 show_shipping_method_block();
6211}
6212function map_google_billcountry(country, state) {
6213 // alert(country);
6214 var url = "/my_ajax/ajax_get_country_id?country_name=" + country;
6215 url = url + "&tts=" + new Date().getMilliseconds();
6216 $.get(url, function(data) {
6217 //alert(data);
6218 $("#country").val(data);
6219 setstatefield_billing(document.processorder_frm.country, state);
6220});
6221}
6222function toggle_display() {
6223 var form = document.getElementById("ShowBilling");
6224 var thanks = document.getElementById("shippinginfo");
6225 form.checked
6226 ? (thanks.style.display = "none")
6227 : (thanks.style.display = "block");
6228 if (typeof sfw === "undefined" || sfw === null) {
6229 // variable is undefined or null
6230} else {
6231 sfw.refresh();
6232}
6233}
6234function forcevipdiscount(obj) {
6235 var selected = 0;
6236 if (obj.checked) selected = 1;
6237 url =
6238 "/my_ajax/ajax_set_vip_discount?sid=" +
6239 Math.random() +
6240 "&selected=" +
6241 selected;
6242 $.get(url, function(data) {
6243 update_order_summary_block(0);
6244 });
6245}
6246function payByCCClicked() {
6247 changeDiv("ccform", "block");
6248 changeDiv("cclabel", "block");
6249 changeDiv("cctxt", "block");
6250 changeDiv("cclabel_cvv", "block");
6251 changeDiv("cctxt_cvv", "block");
6252 changeDiv("ccexplabel", "block");
6253 changeDiv("ccexp", "block");
6254 changeDiv("ccname", "block");
6255 changeDiv("ccnamefield", "block");
6256}
6257function payByPayPalClicked() {
6258 changeDiv("ccform", "none");
6259 changeDiv("cclabel", "none");
6260 changeDiv("cctxt", "none");
6261 changeDiv("cclabel_cvv", "none");
6262 changeDiv("cctxt_cvv", "none");
6263 changeDiv("ccexplabel", "none");
6264 changeDiv("ccexp", "none");
6265 changeDiv("ccname", "none");
6266 changeDiv("ccnamefield", "none");
6267}
6268function updateETA() {
6269 if (document.getElementById || document.all) {
6270 var etaDiv = document.getElementById("ETA");
6271 var etaRadio =
6272 document.processorder_frm.ShippingTableOption[
6273 document.processorder_frm.ShippingTableOption.selectedIndex
6274 ];
6275 var etaText = GetShippingTableETA(etaRadio);
6276 etaDiv.innerHTML = etaText;
6277 var shipDateDiv = document.getElementById("EstimatedShipDate");
6278 var shipDateText = GetEstimatedShipDateString(etaRadio);
6279 shipDateDiv.innerHTML = shipDateText;
6280 }
6281}
6282function GetEstimatedShipDateString(radioObj) {
6283 if (!radioObj) {
6284 return "";
6285 }
6286 var radioLength = radioObj.length;
6287 if (radioLength == undefined) {
6288 //1 option, such as international
6289 if (radioObj.selected) return MakeEstimatedShipDateString(radioObj.value);
6290 else return "";
6291}
6292for (var i = 0; i < radioLength; i++) {
6293 if (radioObj[i].selected) {
6294 var checkedValue = radioObj[i].value;
6295 return MakeEstimatedShipDateString(checkedValue);
6296 }
6297}
6298return "";
6299}
6300function MakeEstimatedShipDateString(checkedValue) {
6301 var quickSplit = checkedValue.split("|");
6302 var returnString = unescape(quickSplit[8]);
6303 returnString +=
6304 "<input type='hidden' name='ShipDate' value='" + quickSplit[8] + "'/>";
6305 return returnString;
6306}
6307function GetShippingTableETA(radioObj) {
6308 if (!radioObj) {
6309 return "";
6310 }
6311 var radioLength = radioObj.length;
6312 if (radioLength == undefined) {
6313 //1 option, such as international
6314 if (radioObj.selected) return MakeETAString(radioObj.value);
6315 else return "";
6316}
6317for (var i = 0; i < radioLength; i++) {
6318 if (radioObj[i].selected) {
6319 var checkedValue = radioObj[i].value;
6320 return MakeETAString(checkedValue);
6321 }
6322}
6323return "";
6324}
6325function MakeETAString(checkedValue) {
6326 var quickSplit = checkedValue.split("|");
6327 var returnString = "";
6328 var showHeadings = cartContainsBooks && cartContainsGeneralItems;
6329 var EtaPromise = "";
6330 if (cartContainsGeneralItems) {
6331 if (showHeadings) {
6332 returnString += "<b>General Items:</b><br/>";
6333 }
6334 returnString += unescape(quickSplit[2]);
6335 var selectedShippingMethod = quickSplit[1];
6336 if (
6337 selectedShippingMethod == 3 ||
6338 selectedShippingMethod == 14 ||
6339 selectedShippingMethod == 17 ||
6340 selectedShippingMethod == 20 ||
6341 selectedShippingMethod == 23
6342 ) {
6343 // International Economy and ROW express
6344 returnString +=
6345 "<p><b>Orders may be subject to <a href=\"javascript:launchHelp('/cp/info/help/help_duties.aspx','height=300,width=400,scrollbars=1')\">import taxes</a>.</b></p>";
6346} else if (selectedShippingMethod == 15 || selectedShippingMethod == 16) {
6347 // CA
6348 returnString +=
6349 "<p><b>Includes ALL duties and Taxes (GST, PST, HST)</b></p>";
6350 } else if (selectedShippingMethod == 18 || selectedShippingMethod == 19) {
6351 // UK
6352 returnString += "<p><b>Includes ALL duties and VAT</b></p>";
6353 } else if (selectedShippingMethod == 22) {
6354 // AU
6355 returnString += "<p><b>Includes ALL duties and taxes</b></p>";
6356 }
6357 returnString +=
6358 "<input type='hidden' name='ShippingETA' value='" + quickSplit[2] + "'/>";
6359 if (quickSplit != null && quickSplit[4].length > 0) {
6360 returnString += unescape(quickSplit[4]);
6361 returnString +=
6362 "<input type='hidden' name='ETAInfo' value='" + quickSplit[4] + "'/>";
6363 }
6364 if (quickSplit[6] != null && quickSplit[6].length > 0) {
6365 returnString += "<br/>" + unescape(quickSplit[6]);
6366 }
6367}
6368if (cartContainsBooks) {
6369 if (showHeadings) {
6370 returnString += "<br/><b>Books and Other Items:</b><br/>";
6371 }
6372 returnString += unescape(quickSplit[3]);
6373 returnString +=
6374 "<input type='hidden' name='BookETA' value='" +
6375 encodeURI(quickSplit[3]) +
6376 "'/>";
6377 if (quickSplit[5] != null && quickSplit[5].length > 1) {
6378 returnString += "<br/>";
6379 returnString += unescape(quickSplit[5]);
6380 returnString +=
6381 "<input type='hidden' name='BookETAInfo' value='" +
6382 encodeURI(quickSplit[5]) +
6383 "'/>";
6384 }
6385 if (quickSplit[7] != null && quickSplit[7].length > 1) {
6386 returnString += "<br/>" + unescape(quickSplit[7]);
6387 }
6388}
6389return returnString;
6390}
6391function ClearShippingTable() {
6392 ClearTableRows(document.getElementById("ShippingTable"));
6393}
6394function ClearTableRows(tbl) {
6395 var tblLength = tbl.rows.length;
6396 for (var i = 1; i < tblLength; i++) {
6397 tbl.deleteRow(1);
6398 }
6399}
6400function SetText(spanname, strPrice) {
6401 var myDiv = document.getElementById(spanname);
6402 if (myDiv != null) {
6403 var newNode = document.createTextNode(strPrice);
6404 myDiv.replaceChild(newNode, myDiv.lastChild);
6405 }
6406}
6407function MemorizeShippingOptionIndex() {
6408 var selectedIndex =
6409 document.processorder_frm.ShippingTableOption.selectedIndex;
6410 //CW check where being called
6411 setCookie("shippingoptionindex", selectedIndex);
6412}
6413function RememberShippingOptionIndex() {
6414 return parseInt(getCookie("shippingoptionindex"));
6415}
6416function setCookie(name, value, expires, path, domain, secure) {
6417 var curCookie =
6418 name +
6419 "=" +
6420 escape(value) +
6421 (expires ? "; expires=" + expires.toGMTString() : "") +
6422 (path ? "; path=" + path : "") +
6423 (domain ? "; domain=" + domain : "") +
6424 (secure ? "; secure" : "");
6425 document.cookie = curCookie;
6426}
6427// name - name of the desired cookie
6428// * return string containing value of specified cookie or null if cookie does not exist
6429function getCookie(name) {
6430 var dc = document.cookie;
6431 if (dc == null) {
6432 return "-1";
6433 }
6434 var prefix = name + "=";
6435 var begin = dc.indexOf("; " + prefix);
6436 if (begin == -1) {
6437 begin = dc.indexOf(prefix);
6438 if (begin != 0) return "-1";
6439 } else begin += 2;
6440 var end = document.cookie.indexOf(";", begin);
6441 if (end == -1) end = dc.length;
6442 return unescape(dc.substring(begin + prefix.length, end));
6443}
6444function changeDiv(the_div, the_change) {
6445 if (document.getElementById || document.all) {
6446 var the_style = getStyleObject(the_div);
6447 if (the_style != false) {
6448 the_style.display = the_change;
6449 }
6450 }
6451}
6452function getStyleObject(objectId) {
6453 if (document.getElementById && document.getElementById(objectId)) {
6454 return document.getElementById(objectId).style;
6455 } else if (document.all && document.all(objectId)) {
6456 return document.all(objectId).style;
6457 } else {
6458 return false;
6459 }
6460}
6461function removeNonNumbers() {
6462 return true;
6463 if (document.processorder_frm.txtCCAccount.value.match(/\D/)) {
6464 re = /\D/;
6465 while (document.processorder_frm.txtCCAccount.value.match(/\D/)) {
6466 document.processorder_frm.txtCCAccount.value = document.processorder_frm.txtCCAccount.value.replace(
6467 re,
6468 ""
6469 );
6470 }
6471 alert(
6472 "Invalid characters were removed from your credit card number. Please double-check it."
6473 );
6474 return false;
6475 }
6476}
6477//============================================
6478//Next, we create a function to fill the second drop down from
6479//the array based on the item selected in the first drop down.
6480function ToggleBillState() {
6481 var countryname =
6482 document.processorder_frm.country.options[
6483 document.processorder_frm.country.selectedIndex
6484 ].value;
6485 if (countryname == "UNITED STATES" || countryname == "CANADA") {
6486 document.processorder_frm.state.disabled = false;
6487 changeDiv("stateRow", "block");
6488 if (document.getElementById || document.all) {
6489 var asterisk_style = getStyleObject("stateRowAsterisk");
6490 if (asterisk_style != false) {
6491 asterisk_style.color = "red";
6492 }
6493 }
6494 } else {
6495 document.processorder_frm.state.disabled = true;
6496 changeDiv("stateRow", "none");
6497 if (document.getElementById || document.all) {
6498 var asterisk_style = getStyleObject("stateRowAsterisk");
6499 if (asterisk_style != false) {
6500 asterisk_style.color = "white";
6501 }
6502 }
6503 }
6504}
6505function TogglePhoneFormatHint() {
6506 var countryname =
6507 document.processorder_frm.country.options[
6508 document.processorder_frm.country.selectedIndex
6509 ].value;
6510 if (countryname == "UNITED STATES") {
6511 $("#BillPhoneFormatHint").html("(10+ numbers only, ex. 6505551234)");
6512 changeDiv("BillPhoneFormatHint", "block");
6513 } else {
6514 changeDiv("BillPhoneFormatHint", "none");
6515 }
6516}
6517function ToggleShipState() {
6518 var obj_form = document.checkout_frm;
6519 var countryname =
6520 document.processorder_frm.ship_country.options[
6521 document.processorder_frm.ship_country.selectedIndex
6522 ].value;
6523 if (countryname == "UNITED STATES" || countryname == "CANADA") {
6524 document.processorder_frm.ship_state.disabled = false;
6525 changeDiv("ship_stateRow", "block");
6526 if (document.getElementById || document.all) {
6527 var asterisk_style = getStyleObject("ship_stateRowAsterisk");
6528 if (asterisk_style != false) {
6529 asterisk_style.color = "red";
6530 }
6531 }
6532 } else {
6533 document.processorder_frm.ship_state.disabled = true;
6534 changeDiv("ship_stateRow", "none");
6535 if (document.getElementById || document.all) {
6536 var asterisk_style = getStyleObject("ship_stateRowAsterisk");
6537 if (asterisk_style != false) {
6538 asterisk_style.color = "white";
6539 }
6540 }
6541 }
6542}
6543function getSelectedRadio(buttonGroup) {
6544 // returns the array number of the selected radio button or -1 if no button is selected
6545 //if the button group is an array (one button is not an array)
6546 if (buttonGroup[0]) {
6547 for (var i = 0; i < buttonGroup.length; i++) {
6548 if (buttonGroup[i].checked) {
6549 return i;
6550 }
6551 }
6552 } else {
6553 if (buttonGroup.checked) {
6554 return 0;
6555 } // if the one button is checked, return zero
6556}
6557 // if we get to this point, no radio button is selected
6558 return -1;
6559}
6560function ABpopup(url, windowname, width, height) {
6561 width = width ? width : screen.width / 3;
6562 height = height ? height : screen.height / 3;
6563 var screenX = screen.width / 2 - width / 2;
6564 var screenY = screen.height / 2 - height / 2;
6565 var features = "scrollbars=yes,width=" + width + ",height=" + height;
6566 features += ",screenX=" + screenX + ",left=" + screenX;
6567 features += ",screenY=" + screenY + ",top=" + screenY;
6568 var mywin = window.open(url, windowname, features);
6569 if (mywin) mywin.focus();
6570 return mywin;
6571}
6572function limitText(limitField, limitCount, limitNum) {
6573 if (limitField.value.length > limitNum) {
6574 limitField.value = limitField.value.substring(0, limitNum);
6575 } else {
6576 limitCount.value = limitNum - limitField.value.length;
6577 }
6578}
6579var phoneNumbers = "0123456789";
6580function cleanPhone(phonebox) {
6581 var w = "";
6582 for (i = 0; i < phonebox.value.length; i++) {
6583 x = phonebox.value.charAt(i);
6584 if (phoneNumbers.indexOf(x, 0) != -1) {
6585 w += x;
6586 }
6587 }
6588 phonebox.value = w;
6589}
6590function validateCharacter(e) {
6591 if (window.event) keycode = window.event.keyCode;
6592 else if (e) keycode = e.which;
6593 var sysKeys = new Array(
6594 8,
6595 9,
6596 13,
6597 16,
6598 19,
6599 20,
6600 27,
6601 33,
6602 34,
6603 35,
6604 36,
6605 37,
6606 38,
6607 39,
6608 40,
6609 45,
6610 46,
6611 91,
6612 93,
6613 96,
6614 97,
6615 98,
6616 99,
6617 100,
6618 101,
6619 102,
6620 103,
6621 104,
6622 105,
6623 144
6624 );
6625 for (var i = sysKeys.length; i-- && sysKeys[i] != keycode; );
6626 if (
6627 i > -1 ||
6628 (keycode > 47 && keycode < 58 && !window.event.shiftKey) ||
6629 (keycode > 64 && keycode < 91)
6630 ) {
6631 e.returnValue = true;
6632 return true;
6633 }
6634 e.returnValue = false;
6635 return false;
6636}
6637function validateCoupon(txt) {
6638 txt.value = txt.value.replace(/[^a-zA-Z0-9]+/g, "").toUpperCase();
6639}
6640function onBeforePasteIE() {
6641 var txt = window.clipboardData.getData("Text");
6642 window.clipboardData.setData(
6643 "Text",
6644 txt.replace(/[^a-zA-Z0-9]+/g, "").toUpperCase()
6645 );
6646}
6647function GetSelectedShippingId() {
6648 var thisShippingTableOption = document.processorder_frm.ShippingTableOption;
6649 var shippingTableLength = thisShippingTableOption.length;
6650 if (shippingTableLength == undefined || thisShippingTableOption.length == 0) {
6651 quickShipOption = thisShippingTableOption.value;
6652 } else {
6653 var selectedOption =
6654 document.processorder_frm.ShippingTableOption.selectedIndex;
6655 quickShipOption = thisShippingTableOption[selectedOption].value;
6656 }
6657 var quickSplit = quickShipOption.split("|");
6658 return quickSplit[0];
6659}
6660function showGiftBox() {
6661 if (document.processorder_frm.ShowGiftMsg.checked == true) {
6662 changeDiv("giftmessage", "block");
6663 } else {
6664 changeDiv("giftmessage", "none");
6665 }
6666}
6667function showInstructions() {
6668 if (document.processorder_frm.ShowInstructionsMsg.checked == true) {
6669 changeDiv("order_comments", "block");
6670 } else {
6671 changeDiv("order_comments", "none");
6672 }
6673}
6674function toggle_display() {
6675 var form = document.getElementById("ShowBilling");
6676 var thanks = document.getElementById("shippinginfo");
6677 form.checked
6678 ? (thanks.style.display = "none")
6679 : (thanks.style.display = "block");
6680}
6681function checkBanWords() {
6682 var banned_words = ["unit", "Unit", "level", "Level", "floor", "Floor", "/"];
6683 var textvalue = document.getElementById("ship_address2_geo").value;
6684 for (var i = 0; i < banned_words.length; i++) {
6685 // alert(banned_words[i] + ' *** ' +
6686 if (~textvalue.indexOf(banned_words[i])) {
6687 //DO YOUR STUFF HERE
6688 document.getElementById("error_2").style.display = "block";
6689 break;
6690 // console.log('you have entered a banned word: ' + banned_words[i]);
6691 } else {
6692 document.getElementById("error_2").style.display = "none";
6693 }
6694}
6695}
6696
6697(function() {
6698 var Details = function(element, index) {
6699 this.element = element;
6700 this.summary = this.element.getElementsByClassName('js-details__summary')[0];
6701 this.details = this.element.getElementsByClassName('js-details__content')[0];
6702 this.htmlElSupported = 'open' in this.element;
6703 this.initDetails(index);
6704 this.initDetailsEvents();
6705 };
6706
6707 Details.prototype.initDetails = function(index) {
6708 // init aria attributes
6709 Util.setAttributes(this.summary, {'aria-expanded': 'false', 'aria-controls': 'details--'+index, 'role': 'button'});
6710 Util.setAttributes(this.details, {'aria-hidden': 'true', 'id': 'details--'+index});
6711 };
6712
6713 Details.prototype.initDetailsEvents = function() {
6714 var self = this;
6715 if( this.htmlElSupported ) { // browser supports the <details> element
6716 this.element.addEventListener('toggle', function(event){
6717 var ariaValues = self.element.open ? ['true', 'false'] : ['false', 'true'];
6718 // update aria attributes when details element status change (open/close)
6719 self.updateAriaValues(ariaValues);
6720 });
6721 } else { //browser does not support <details>
6722 this.summary.addEventListener('click', function(event){
6723 event.preventDefault();
6724 var isOpen = self.element.getAttribute('open'),
6725 ariaValues = [];
6726
6727 isOpen ? self.element.removeAttribute('open') : self.element.setAttribute('open', 'true');
6728 ariaValues = isOpen ? ['false', 'true'] : ['true', 'false'];
6729 self.updateAriaValues(ariaValues);
6730 });
6731 }
6732 };
6733
6734 Details.prototype.updateAriaValues = function(values) {
6735 this.summary.setAttribute('aria-expanded', values[0]);
6736 this.details.setAttribute('aria-hidden', values[1]);
6737 };
6738
6739 //initialize the Details objects
6740 var detailsEl = document.getElementsByClassName('js-details');
6741 if( detailsEl.length > 0 ) {
6742 for( var i = 0; i < detailsEl.length; i++) {
6743 (function(i){new Details(detailsEl[i], i);})(i);
6744 }
6745 }
6746}());
6747(function() {
6748 var floatingLabels = document.getElementsByClassName('floating-label');
6749 if( floatingLabels.length > 0 ) {
6750 var placeholderSupported = checkPlaceholderSupport(); // check if browser supports :placeholder
6751 for(var i = 0; i < floatingLabels.length; i++) {
6752 (function(i){initFloatingLabel(floatingLabels[i])})(i);
6753 }
6754
6755 function initFloatingLabel(element) {
6756 if(!placeholderSupported) { // :placeholder is not supported -> show label right away
6757 Util.addClass(element.getElementsByClassName('form-label')[0], 'form-label--floating');
6758 return;
6759 }
6760 var input = element.getElementsByClassName('form-control')[0];
6761 input.addEventListener('input', function(event){
6762 resetFloatingLabel(element, input);
6763 });
6764 };
6765
6766 function resetFloatingLabel(element, input) { // show label if input is not empty
6767 Util.toggleClass(element.getElementsByClassName('form-label')[0], 'form-label--floating', input.value.length > 0);
6768 };
6769
6770 function checkPlaceholderSupport() {
6771 var input = document.createElement('input');
6772 return ('placeholder' in input);
6773 };
6774 }
6775}());
6776// This example displays an address form, using the autocomplete feature
6777// of the Google Places API to help users fill in the information.
6778// This example requires the Places library. Include the libraries=places
6779// parameter when you first load the API. For example:
6780// <script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=places">
6781var placeSearch, autocomplete;
6782var componentForm = {
6783 street_number: "short_name",
6784 route: "long_name",
6785 locality: "long_name",
6786 administrative_area_level_1: "short_name",
6787 country: "long_name",
6788 postal_code: "short_name"
6789};
6790function initAutocomplete() {
6791 // Create the autocomplete object, restricting the search to geographical
6792 // location types.
6793 autocomplete = new google.maps.places.Autocomplete(
6794 /** @type {!HTMLInputElement} */
6795 (document.getElementById("ship_address2_geo")),
6796 {
6797 types: ["geocode"]
6798 /*,
6799 componentRestrictions: {country: '<?=$ip_to_country;?>'}*/
6800 }
6801 );
6802 // When the user selects an address from the dropdown, populate the address
6803 // fields in the form.
6804 autocomplete.addListener("place_changed", fillInAddress);
6805 autocomplete1 = new google.maps.places.Autocomplete(
6806 /** @type {!HTMLInputElement} */
6807 (document.getElementById("address2_geo")),
6808 {
6809 types: ["geocode"]
6810 /* componentRestrictions: {country: 'au'}*/
6811 }
6812 );
6813 autocomplete1.addListener("place_changed", fillInAddress1);
6814}
6815function fillInAddress() {
6816 // Get the place details from the autocomplete object.
6817 var place = autocomplete.getPlace();
6818 for (var component in componentForm) {
6819 // document.getElementById(component).value = '';
6820 //document.getElementById(component).disabled = false;
6821}
6822 // Get each component of the address from the place details
6823 // and fill the corresponding field on the form.
6824 var ship_address2_str = "";
6825 var final_address_str = "";
6826 var temp_country = "";
6827 var temp_state = "";
6828 $("#final_address_div").html(final_address_str);
6829 $("#ship_address2").val("");
6830 for (var i = 0; i < place.address_components.length; i++) {
6831 var addressType = place.address_components[i].types[0];
6832 if (componentForm[addressType]) {
6833 var val = place.address_components[i][componentForm[addressType]];
6834 //document.getElementById(addressType).value = val;
6835 // alert(addressType + ' ' + val);
6836 if (addressType == "street_number") {
6837 addressType = "ship_address1";
6838 ship_address2_str += val;
6839 }
6840 if (addressType == "route") {
6841 addressType = "ship_address2";
6842 val = ship_address2_str + " " + val;
6843 }
6844 if (addressType == "locality") addressType = "ship_city";
6845 if (addressType == "administrative_area_level_1") {
6846 addressType = "ship_state";
6847 temp_state = val;
6848 }
6849 if (addressType == "country") temp_country = val;
6850 if (addressType == "postal_code") addressType = "ship_zip";
6851 tempvar = "#" + addressType;
6852 if (addressType != "ship_address1" && addressType != "country")
6853 $(tempvar).val(val);
6854 }
6855 //alert(val);
6856}
6857get_final_address_ship();
6858map_google_shipcountry(temp_country, temp_state);
6859show_shipping_method_block();
6860if (typeof sfw === "undefined" || sfw === null) {
6861 // variable is undefined or null
6862} else {
6863 sfw.refresh();
6864}
6865return false;
6866}
6867function get_final_address_ship() {
6868 var final_address_str_local = "";
6869 if (
6870 $("#ship_address2").val() != null &&
6871 $("#ship_address2").val() != "Street Number and Name"
6872 )
6873 final_address_str_local += $("#ship_address2").val();
6874 if (
6875 $("#ship_city").val() != null &&
6876 $("#ship_city").val() != "Town/City/Suburb"
6877 )
6878 final_address_str_local += " " + $("#ship_city").val();
6879 if ($("#ship_state").val() != null)
6880 final_address_str_local += " " + $("#ship_state").val();
6881 if ($("#ship_zip").val() != null && $("#ship_zip").val() != "Post Code")
6882 final_address_str_local += " " + $("#ship_zip").val();
6883 // final_address_str=$('#ship_address2').val() + ' ' + $('#ship_city').val() + ' ' + $('#ship_state').val() + ' ' + $('#ship_zip').val();
6884 // alert(final_address_str);
6885 //if ( $( '#ship_address1' ) . val() != null && $( '#ship_address1' ) . val() != 'Unit/Shop/Floor No.' )final_address_str_local = $( '#ship_address1' ) . val() + ' / ' + final_address_str_local;
6886 if ($("#ship_address1").val() != null)
6887 final_address_str_local =
6888 $("#ship_address1").val() + " / " + final_address_str_local;
6889 $("#final_address_div").html(final_address_str_local);
6890 //alert(final_address_str_local);
6891 // return final_address_str_local;
6892}
6893function fillInAddress1() {
6894 // Get the place details from the autocomplete object.
6895 var place = autocomplete1.getPlace();
6896 for (var component in componentForm) {
6897 // document.getElementById(component).value = '';
6898 //document.getElementById(component).disabled = false;
6899}
6900 // Get each component of the address from the place details
6901 // and fill the corresponding field on the form.
6902 var ship_address2_str = "";
6903 var final_address_str = "";
6904 var temp_country = "";
6905 var temp_state = "";
6906 $("#address2").val("");
6907 $("#final_address_div2").html(final_address_str);
6908 for (var i = 0; i < place.address_components.length; i++) {
6909 var addressType = place.address_components[i].types[0];
6910 if (componentForm[addressType]) {
6911 var val = place.address_components[i][componentForm[addressType]];
6912 //document.getElementById(addressType).value = val;
6913 // alert(addressType + ' ' + val);
6914 if (addressType == "street_number") {
6915 addressType = "address1";
6916 ship_address2_str += val;
6917 }
6918 if (addressType == "route") {
6919 addressType = "address2";
6920 val = ship_address2_str + " " + val;
6921 }
6922 if (addressType == "locality") addressType = "city";
6923 if (addressType == "administrative_area_level_1") {
6924 addressType = "state";
6925 temp_state = val;
6926 }
6927 if (addressType == "country") temp_country = val;
6928 if (addressType == "postal_code") addressType = "zip";
6929 tempvar = "#" + addressType;
6930 if (addressType != "address1" && addressType != "country")
6931 $(tempvar).val(val);
6932 }
6933}
6934get_final_address_bill();
6935map_google_billcountry(temp_country, temp_state);
6936 // show_shipping_method_block();
6937 if (typeof sfw === "undefined" || sfw === null) {
6938 // variable is undefined or null
6939} else {
6940 sfw.refresh();
6941}
6942}
6943function get_final_address_bill() {
6944 var final_address_str_local = "";
6945 if (
6946 $("#address2").val() != null &&
6947 $("#address2").val() != "Street Number and Name"
6948 )
6949 final_address_str_local += $("#address2").val();
6950 if ($("#city").val() != null && $("#city").val() != "Town/City/Suburb")
6951 final_address_str_local += " " + $("#city").val();
6952 if ($("#state").val() != null)
6953 final_address_str_local += " " + $("#state").val();
6954 if ($("#zip").val() != null && $("#zip").val() != "Post Code")
6955 final_address_str_local += " " + $("#zip").val();
6956 // final_address_str=$('#address2').val() + ' ' + $('#city').val() + ' ' + $('#state').val() + ' ' + $('#zip').val();
6957 // alert(final_address_str);
6958 if (
6959 $("#address1").val() != null &&
6960 $("#address1").val() != "Unit/Shop/Floor No."
6961 )
6962 final_address_str_local =
6963 $("#address1").val() + " / " + final_address_str_local;
6964 $("#final_address_div2").html(final_address_str_local);
6965 // alert(final_address_str_local);
6966 // return final_address_str_local;
6967}
6968// Bias the autocomplete object to the user's geographical location,
6969// as supplied by the browser's 'navigator.geolocation' object.
6970function geolocate(type) {
6971 var geolocation = {
6972 lng: 153.6125793457,
6973 lat: -28.644830703735
6974 };
6975 var circle = new google.maps.Circle({
6976 center: geolocation,
6977 radius: 3
6978 });
6979 autocomplete.setBounds(circle.getBounds());
6980 thisType = type;
6981}
6982// Bias the autocomplete object to the user's geographical location,
6983// as supplied by the browser's 'navigator.geolocation' object.
6984function geolocate_orig() {
6985 return;
6986 if (navigator.geolocation) {
6987 navigator.geolocation.getCurrentPosition(function(position) {
6988 var geolocation = {
6989 lng: 153.6125793457,
6990 lat: -28.644830703735
6991 };
6992 var circle = new google.maps.Circle({
6993 center: geolocation,
6994 radius: 10
6995 });
6996 autocomplete.setBounds(circle.getBounds());
6997 // thisType = type ;
6998 });
6999 }
7000}
7001
7002/** Minified JS for Menufication jQuery plugin **/"use strict";(function(e){e.fn.extend({menufication:function(n){return w[n]&&m?w[n].apply(this,Array.prototype.slice.call(arguments,1)):"object"!=typeof n&&n?(e.error("Method "+n+" does not exist for menufication"),void 0):w.init.apply(this,arguments)},hasClasses:function(e){var n=e.replace(/\s/g,"").split(","),t=this;for(var i in n)if(jQuery(t).hasClass(n[i]))return!0;return!1},addClasses:function(e){var n=e.replace(/\s/g,"").split(","),t=this;for(var i in n)jQuery(t).addClass(n[i])}});var n,t,i,o,l,r,a,s,d,u,c,g,p=!1,m=!1,h=!1,f="menufication",v=0;t={toggleElement:null,enableSwipe:!0,hideDefaultMenu:!1,showHeader:!0,customFixedHeader:null,menuText:"",headerLogo:"",headerLogoLink:"",triggerWidth:770,addHomeLink:!0,addHomeText:"Home",childMenuSupport:!0,childMenuSelector:"sub-menu, child-menu, children",activeClassSelector:"active-class, active",supportAndroidAbove:3.5,onlyMobile:!1,transitionDuration:600,scrollSpeed:.6,allowedTags:"DIV, NAV, UL, LI, A, P, H1, H2, H3, H4, SPAN, FORM, INPUT",wrapTagsInList:"",addToFixedHolder:"",direction:"left",theme:"dark",menuLogo:"",disableSlideScaling:!1,doCapitalization:!1,enableBlackBerry:!1,enableMultiple:!1,multipleContentElement:"",multipleToggleElement:""};var w={init:function(o){m||b.utils.isOldIE(9)||(n=e(this),o||(o={}),i=e.extend({},t,o),(!i.onlyMobile||b.utils.isMobile())&&(i.enableBlackBerry||!b.utils.isBB())&&((!b.utils.hasTranslate3d()||b.utils.androidVersionIsBelow(i.supportAndroidAbove)||b.utils.isIE())&&(f+="-non-css3"),i.gestures=b.utils.isMobile()?{start:"touchstart",move:"touchmove",end:"touchend",click:"click",fastClick:"touchend"}:{start:"mousedown",move:"mousemove",end:"mouseup",click:"click",fastClick:"click"},b.utils.androidVersionIsBelow(i.supportAndroidAbove)&&(i.gestures.fastClick="click"),0!==n.length&&b.scrolling.setScrollHandlers(),i.triggerWidth?(e(window).bind("resize",function(){b.utils.checkTriggerWidth(e(window).width())}),b.utils.checkTriggerWidth(e(window).width())):b.init()))},openMenu:function(){e(document).trigger("menufication-open",["open"]),l.addClass(f+"-transition-in"),p=!0,o.bind(i.gestures.move,function(e){e.preventDefault()})},closeMenu:function(){e(document).trigger("menufication-close",["close"]),l.removeClass(f+"-transition-in"),p=!1,o.unbind()},openMultiple:function(){e(document).trigger("menufication-multiple-open",["open"]),l.addClass(f+"-transition-in-multiple"),p=!0,o.bind(i.gestures.move,function(e){e.preventDefault()})},closeMultiple:function(){e(document).trigger("menufication-multiple-close",["close"]),l.removeClass(f+"-transition-in-multiple"),p=!1,o.unbind()},toggleMultiple:function(){p?w.closeMultiple():w.openMultiple()},toggleMenu:function(){p?w.closeMenu():w.openMenu()}},b={init:function(){b.utils.wrapBody([f+"-page-holder",f+"-inner-wrap",f+"-outer-wrap"],i.enableMultiple),l.addClass(i.theme).addClass(i.direction+"-direction"),i.customFixedHeader?b.buildCustomFixedHeader():i.showHeader&&b.buildHeader(),b.buildFixedHolder(),b.buildMenu(),i.enableMultiple&&b.buildMultiple(),b.addEvents(),b.utils.isMobile()?b.scrolling.addBouncyScroll():0!==n.length&&a.addClass(f+"-scroll"),m=!0,e(document).trigger("menufication-done",["done"])},buildHeader:function(){var t=e('<div id="'+f+'-top" />');0!==n.length&&t.append('<div id="'+f+'-btn"><p>'+i.menuText+"</p></div>"),i.enableMultiple&&0!==i.multipleToggleElement.length&&t.append(e(i.multipleToggleElement).addClass(f+"-multiple-toggle").show()),l.prepend(t).addClass(f+"-add-padding"),i.toggleElement="#"+f+"-btn",i.headerLogo.length>0&&b.addHeaderLogo(t)},addHeaderLogo:function(n){if(i.headerLogoLink.length>1)var t=e('<center><a href="'+i.headerLogoLink+'"><img src="'+i.headerLogo+'" id="'+f+'-header-logo" /></a></center>');else var t=e('<center><img src="'+i.headerLogo+'" id="'+f+'-header-logo" /></center>');n.append(t)},buildCustomFixedHeader:function(){e(i.customFixedHeader).hide().addClass(f+"-original-custom-fixed-header");var n=e(i.customFixedHeader).clone(!0);n.css("position","static");var t=e('<div class="'+f+'-custom-top" />');n.show().removeClass(f+"-original-custom-fixed-header"),l.prepend(t.append(n)).addClass(f+"-add-padding")},buildFixedHolder:function(){if(i.addToFixedHolder&&i.addToFixedHolder.length>0){u=e('<div id="'+f+'-fixed-holder" />');var n=i.addToFixedHolder.replace(/\s/g,"").split(",");for(var t in n)u.append(e(n[t]));l.prepend(u)}},buildMenu:function(){if(0!==n.length){i.hideDefaultMenu&&n.hide();var t=n.clone().removeAttr("id class");t=b.trimMenu(t),i.addHomeLink&&t.prepend('<li><a href="http://'+window.location.hostname+'">'+i.addHomeText+"</a></li>"),"UL"===t.prop("tagName")?t.addClass(f+"-menu-level-0"):t.find("ul").first().addClass(f+"-menu-level-0").siblings("ul").addClass(f+"-menu-level-0"),i.childMenuSelector&&i.childMenuSupport?b.buildChildMenus(t):b.removeChildMenus(t),i.menuLogo.length>0&&b.addMenuLogo(t),l.prepend(t),t.wrap('<div id="'+f+'-scroll-container" />'),!b.utils.isIOS()&&b.utils.isMobile()||i.disableSlideScaling||t.wrap('<div id="'+f+'-transform-container" />'),t.wrap('<nav id="'+f+'-nav" />').show(),r=e("#"+f+"-nav"),a=e("#"+f+"-scroll-container")}},trimMenu:function(n){var o=i.activeClassSelector?i.activeClassSelector:"",l=i.childMenuSelector?i.childMenuSelector:"",r=i.allowedTags?i.allowedTags.replace(/\s/g,"").split(","):t.allowedTags;return n.find("*").each(function(){var n=e(this),t=n.prop("tagName");if(-1===r.indexOf(t)||n.hasClass("skip-link"))return n.remove(),void 0;if("A"===t&&i.doCapitalization){var a=n.text().toLowerCase(),s=a.charAt(0).toUpperCase()+a.slice(1);n.text(s)}i.wrapTagsInList===t&&n.wrap("li"),n.hasClasses(l)?(n.removeAttr("class id"),n.addClasses(l)):n.hasClasses(o)?(n.removeAttr("class id"),n.addClass(f+"-active-class")):n.removeAttr("class id")}),n},addMenuLogo:function(n){var t=e('<center><img src="'+i.menuLogo+'" id="'+f+'-menu-logo" /></center>');n.prepend(t)},buildChildMenus:function(n){var t=i.childMenuSelector.replace(/\s/g,"").split(",");for(var o in t)n.find("."+t[o]).each(function(){var n=e(this);n.removeAttr("id class"),n.addClass(f+"-child-menu"),n.parent().addClass(f+"-has-child-menu").bind(i.gestures.click,function(t){"A"!==t.target.nodeName&&(t.preventDefault(),e(this).toggleClass(f+"-child-menu-open"),n.toggle(),t.stopPropagation())})}),i.activeClassSelector&&b.toggleActiveClasses(n);b.countMenuLevel(n)},countMenuLevel:function(n){n.find("."+f+"-child-menu").each(function(){var n=e(this),t=n.parents("."+f+"-child-menu").length+1;n.addClass(f+"-menu-level-"+t)})},removeChildMenus:function(n){if(!i.childMenuSupport){if(!i.childMenuSelector||i.childMenuSelector===t.childMenuSelector)return n.find("."+f+"-menu-level-0").children().each(function(){e(this).find("ul").remove()}),void 0;var o=i.childMenuSelector.replace(/\s/g,"").split(",");for(var l in o)n.find("."+o[l]).each(function(){e(this).remove()})}},toggleActiveClasses:function(n){n.find("."+f+"-has-child-menu").each(function(){var n=e(this);n.find("*").children("."+f+"-active-class").length>0&&(n.toggleClass(f+"-child-menu-open"),setTimeout(function(){n.addClass(f+"-child-menu-open"),n.find("."+f+"-child-menu").first().show()},i.transitionDuration))})},buildMultiple:function(){if(0===i.multipleContentElement.length)return console.log("Menufication: Cannot create multiple content without a multipleContentElement"),void 0;var n="left"===i.direction?"right":"left";s=e('<div id="'+f+'-multiple-container" class="'+f+"-multiple-"+n+'" />'),s.append(e(i.multipleContentElement).show()),s.css("height",e(window).height()+75+"px"),l.prepend(s)},addEvents:function(){i.toggleElement&&0!==n.length&&e(i.toggleElement).bind(i.gestures.fastClick,function(e){e.preventDefault(),e.stopPropagation(),w.toggleMenu()}),i.enableMultiple&&0!==i.multipleToggleElement.length&&e(i.multipleToggleElement).bind(i.gestures.fastClick,function(e){e.preventDefault(),e.stopPropagation(),w.toggleMultiple()}),i.enableSwipe&&b.utils.isMobile()&&b.enableSwipeEvent()},removeEvents:function(){e(i.toggleElement).unbind(),e(i.multipleToggleElement).unbind(),a.unbind()},enableSwipeEvent:function(){var n,t,o,l,r,a=e("#"+f+"-outer-wrap");a.bind(i.gestures.start,function(e){o=(new Date).getTime(),n=e.originalEvent.touches[0].pageX,t=e.originalEvent.touches[0].clientY}),a.bind(i.gestures.move,function(e){l=e.originalEvent.touches[0].pageX,r=e.originalEvent.touches[0].clientY}),a.bind(i.gestures.end,function(){var e=l>n?"right":"left",a=r-t>40||-40>r-t,s=l-n>90||-90>l-n,d=(new Date).getTime();if(!(d-o>600||a)&&s)switch(e){case"left":"left"===i.direction?w.closeMenu():w.openMenu();break;case"right":"left"===i.direction?w.openMenu():w.closeMenu()}})},prevDefault:function(e){e.preventDefault(),e.stopPropagation()},scrolling:{scrollHandlers:{},addBouncyScroll:function(){c=document.getElementById(f+"-nav"),a.bind(i.gestures.start,function(e){v=b.scrolling.scrollHandlers.getTop(c);var n=e.originalEvent.touches[0].pageY;g=n}),a.bind(i.gestures.move,function(e){e.preventDefault(),b.scrolling.checkTouchMove(e)}),a.bind(i.gestures.end,function(){b.scrolling.checkScrollEffect()})},checkTouchMove:function(e){var n=e.originalEvent.touches[0].pageY;v=b.scrolling.scrollHandlers.getTop(),b.scrolling.scrollHandlers.setTop(n),g=n},checkScrollEffect:function(){b.scrolling.setScrollData(),b.scrolling.scrollHandlers.bounceBack()},setScrollHandlers:function(){b.scrolling.scrollHandlers=!b.utils.hasTranslate3d()||b.utils.androidVersionIsBelow(i.supportAndroidAbove)||b.utils.isIE()?{getTop:function(){return parseInt(getComputedStyle(c).top,10)},setTop:function(e){c.style.top=g>=e?v+1.1*(e-g)+"px":v-1.1*(g-e)+"px"},bounceBack:function(e,n,t){if(b.scrolling.isAtBottom()){var t=b.utils.isAndroid()?15:20;r.animate({top:-(d.navHeight-d.windowHeight-t)},i.transitionDuration)}else b.scrolling.isAtTop()&&r.animate({top:0},i.transitionDuration)}}:{getTop:function(){return new WebKitCSSMatrix(window.getComputedStyle(c).webkitTransform).m42},setTop:function(e){c.style.webkitTransform=g>=e?"translateY("+(v+(e-g)*i.scrollSpeed)+"px)":"translateY("+(v-(g-e)*i.scrollSpeed)+"px)"},bounceBack:function(e,n,t){if(b.scrolling.isAtBottom()){r.addClass(f+"-add-transition");var t=b.utils.isAndroid()?15:40;c.style.webkitTransform="translateY("+-(d.navHeight-d.windowHeight-t)+"px)",b.scrolling.removeTransitionClass(i.transitionDuration)}else b.scrolling.isAtTop()&&(r.addClass(f+"-add-transition"),c.style.webkitTransform="translateY(0px)",b.scrolling.removeTransitionClass(i.transitionDuration))}}},setScrollData:function(){d={navHeight:r.height(),windowHeight:e(window).height()}},isAtTop:function(){return v>0||0>v&&d.navHeight<d.windowHeight},isAtBottom:function(){return d.navHeight+v<d.windowHeight&&d.navHeight>d.windowHeight},removeTransitionClass:function(e){setTimeout(function(){r.removeClass(f+"-add-transition")},e)}},utils:{reset:function(){e("."+f+"-custom-top").hide(),e("#"+f+"-top").hide(),l.removeClass(f+"-add-padding"),n.show(),b.removeEvents(),w.closeMenu(),e("."+f+"-original-custom-fixed-header").show(),e(document).trigger("menufication-reset",["done"])},reapply:function(){e("."+f+"-custom-top").show(),e("#"+f+"-top").show(),l.addClass(f+"-add-padding"),i.hideDefaultMenu&&n.hide(),b.addEvents(),e("."+f+"-original-custom-fixed-header").hide(),e(document).trigger("menufication-reapply",["done"])},checkTriggerWidth:function(e){i.triggerWidth>=e&&!h?(m?b.utils.reapply():b.init(),h=!0):e>i.triggerWidth&&h&&(h=!1,b.utils.reset())},wrapBody:function(n){for(var t in n){var i=document.createElement("div");for(i.id=n[t];document.body.firstChild;)i.appendChild(document.body.firstChild);document.body.appendChild(i)}o=e("#"+f+"-inner-wrap"),l=e("#"+f+"-outer-wrap")},hasTranslate3d:function(){var e,n=document.createElement("p"),t={webkitTransform:"-webkit-transform",OTransform:"-o-transform",msTransform:"-ms-transform",MozTransform:"-moz-transform",transform:"transform"};document.body.insertBefore(n,null);for(var i in t)void 0!==n.style[i]&&(n.style[i]="translate3d(1px,1px,1px)",e=window.getComputedStyle(n).getPropertyValue(t[i]));return document.body.removeChild(n),void 0!==e&&e.length>0&&"none"!==e},isMobile:function(){return navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)},isAndroid:function(){return navigator.userAgent.match(/Android/i)},isIOS:function(){return navigator.userAgent.match(/iPhone|iPad|iPod/i)},isIE:function(){return navigator.userAgent.match(/IEMobile/i)||-1!=navigator.appVersion.indexOf("MSIE")},isBB:function(){return navigator.userAgent.match(/BlackBerry|BB10|RIM/i)},isOldIE:function(e){var n=-1!=navigator.appVersion.indexOf("MSIE");return n&&e>parseFloat(navigator.appVersion.split("MSIE")[1])},androidVersionIsBelow:function(e){var n=navigator.userAgent;if(n.indexOf("Android")>=0){var t=parseFloat(n.slice(n.indexOf("Android")+8));if(e>t)return!0}return!1}}}})(jQuery);
7003jQuery('#none').menufication({
7004 direction: 'left',
7005 theme: 'dark',
7006 hideDefaultMenu: true,
7007 enableMultiple: true,
7008 multipleContentElement: '#multiple-content',
7009 multipleToggleElement: '#togglebutton'
7010});
7011(function() {
7012 var mainHeader = document.getElementsByClassName('js-main-header')[0];
7013 if( mainHeader ) {
7014 var trigger = mainHeader.getElementsByClassName('js-main-header__nav-trigger')[0],
7015 nav = mainHeader.getElementsByClassName('js-main-header__nav')[0];
7016 //detect click on nav trigger
7017 trigger.addEventListener("click", function(event) {
7018 event.preventDefault();
7019 var ariaExpanded = !Util.hasClass(nav, 'main-header__nav--is-visible');
7020 //show nav and update button aria value
7021 Util.toggleClass(nav, 'main-header__nav--is-visible', ariaExpanded);
7022 trigger.setAttribute('aria-expanded', ariaExpanded);
7023 if(ariaExpanded) { //opening menu -> move focus to first element inside nav
7024 nav.querySelectorAll('[href], input:not([disabled]), button:not([disabled])')[0].focus();
7025 }
7026 });
7027 }
7028}());
7029
7030
7031
7032
7033(function() {
7034 var Modal = function(element) {
7035 this.element = element;
7036 this.triggers = document.querySelectorAll('[aria-controls="'+this.element.getAttribute('id')+'"]');
7037 this.firstFocusable = null;
7038 this.lastFocusable = null;
7039 this.selectedTrigger = null;
7040 this.showClass = "modal--is-visible";
7041 this.initModal();
7042 };
7043
7044 Modal.prototype.initModal = function() {
7045 var self = this;
7046 //open modal when clicking on trigger buttons
7047 if ( this.triggers ) {
7048 for(var i = 0; i < this.triggers.length; i++) {
7049 this.triggers[i].addEventListener('click', function(event) {
7050 event.preventDefault();
7051 self.selectedTrigger = event.target;
7052 self.showModal();
7053 self.initModalEvents();
7054 });
7055 }
7056 }
7057
7058 // listen to the openModal event -> open modal without a trigger button
7059 this.element.addEventListener('openModal', function(event){
7060 if(event.detail) self.selectedTrigger = event.detail;
7061 self.showModal();
7062 self.initModalEvents();
7063 });
7064 };
7065
7066 Modal.prototype.showModal = function() {
7067 var self = this;
7068 Util.addClass(this.element, this.showClass);
7069 this.getFocusableElements();
7070 this.firstFocusable.focus();
7071 // wait for the end of transitions before moving focus
7072 this.element.addEventListener("transitionend", function cb(event) {
7073 self.firstFocusable.focus();
7074 self.element.removeEventListener("transitionend", cb);
7075 });
7076 this.emitModalEvents('modalIsOpen');
7077 };
7078
7079 Modal.prototype.closeModal = function() {
7080 Util.removeClass(this.element, this.showClass);
7081 this.firstFocusable = null;
7082 this.lastFocusable = null;
7083 if(this.selectedTrigger) this.selectedTrigger.focus();
7084 //remove listeners
7085 this.cancelModalEvents();
7086 this.emitModalEvents('modalIsClose');
7087 };
7088
7089 Modal.prototype.initModalEvents = function() {
7090 //add event listeners
7091 this.element.addEventListener('keydown', this);
7092 this.element.addEventListener('click', this);
7093 };
7094
7095 Modal.prototype.cancelModalEvents = function() {
7096 //remove event listeners
7097 this.element.removeEventListener('keydown', this);
7098 this.element.removeEventListener('click', this);
7099 };
7100
7101 Modal.prototype.handleEvent = function (event) {
7102 switch(event.type) {
7103 case 'click': {
7104 this.initClick(event);
7105 }
7106 case 'keydown': {
7107 this.initKeyDown(event);
7108 }
7109 }
7110 };
7111
7112 Modal.prototype.initKeyDown = function(event) {
7113 if( event.keyCode && event.keyCode == 27 || event.key && event.key == 'Escape' ) {
7114 //close modal window on esc
7115 this.closeModal();
7116 } else if( event.keyCode && event.keyCode == 9 || event.key && event.key == 'Tab' ) {
7117 //trap focus inside modal
7118 this.trapFocus(event);
7119 }
7120 };
7121
7122 Modal.prototype.initClick = function(event) {
7123 //close modal when clicking on close button or modal bg layer
7124 if( !event.target.closest('.js-modal__close') && !Util.hasClass(event.target, 'js-modal') ) return;
7125 event.preventDefault();
7126 this.closeModal();
7127 };
7128
7129 Modal.prototype.trapFocus = function(event) {
7130 if( this.firstFocusable == document.activeElement && event.shiftKey) {
7131 //on Shift+Tab -> focus last focusable element when focus moves out of modal
7132 event.preventDefault();
7133 this.lastFocusable.focus();
7134 }
7135 if( this.lastFocusable == document.activeElement && !event.shiftKey) {
7136 //on Tab -> focus first focusable element when focus moves out of modal
7137 event.preventDefault();
7138 this.firstFocusable.focus();
7139 }
7140 }
7141
7142 Modal.prototype.getFocusableElements = function() {
7143 //get all focusable elements inside the modal
7144 var allFocusable = this.element.querySelectorAll('[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), iframe, object, embed, [tabindex]:not([tabindex="-1"]), [contenteditable], audio[controls], video[controls], summary');
7145 this.getFirstVisible(allFocusable);
7146 this.getLastVisible(allFocusable);
7147 };
7148
7149 Modal.prototype.getFirstVisible = function(elements) {
7150 //get first visible focusable element inside the modal
7151 for(var i = 0; i < elements.length; i++) {
7152 if( elements[i].offsetWidth || elements[i].offsetHeight || elements[i].getClientRects().length ) {
7153 this.firstFocusable = elements[i];
7154 return true;
7155 }
7156 }
7157 };
7158
7159 Modal.prototype.getLastVisible = function(elements) {
7160 //get last visible focusable element inside the modal
7161 for(var i = elements.length - 1; i >= 0; i--) {
7162 if( elements[i].offsetWidth || elements[i].offsetHeight || elements[i].getClientRects().length ) {
7163 this.lastFocusable = elements[i];
7164 return true;
7165 }
7166 }
7167 };
7168
7169 Modal.prototype.emitModalEvents = function(eventName) {
7170 var event = new CustomEvent(eventName, {detail: this.selectedTrigger});
7171 this.element.dispatchEvent(event);
7172 };
7173
7174 //initialize the Modal objects
7175 var modals = document.getElementsByClassName('js-modal');
7176 if( modals.length > 0 ) {
7177 for( var i = 0; i < modals.length; i++) {
7178 (function(i){new Modal(modals[i]);})(i);
7179 }
7180 }
7181}());
7182/**
7183 * Owl Carousel v2.3.4
7184 * Copyright 2013-2018 David Deutsch
7185 * Licensed under: SEE LICENSE IN https://github.com/OwlCarousel2/OwlCarousel2/blob/master/LICENSE
7186 */
7187/**
7188 * Owl carousel
7189 * @version 2.3.4
7190 * @author Bartosz Wojciechowski
7191 * @author David Deutsch
7192 * @license The MIT License (MIT)
7193 * @todo Lazy Load Icon
7194 * @todo prevent animationend bubling
7195 * @todo itemsScaleUp
7196 * @todo Test Zepto
7197 * @todo stagePadding calculate wrong active classes
7198 */
7199 ;(function($, window, document, undefined) {
7200
7201 /**
7202 * Creates a carousel.
7203 * @class The Owl Carousel.
7204 * @public
7205 * @param {HTMLElement|jQuery} element - The element to create the carousel for.
7206 * @param {Object} [options] - The options
7207 */
7208 function Owl(element, options) {
7209
7210 /**
7211 * Current settings for the carousel.
7212 * @public
7213 */
7214 this.settings = null;
7215
7216 /**
7217 * Current options set by the caller including defaults.
7218 * @public
7219 */
7220 this.options = $.extend({}, Owl.Defaults, options);
7221
7222 /**
7223 * Plugin element.
7224 * @public
7225 */
7226 this.$element = $(element);
7227
7228 /**
7229 * Proxied event handlers.
7230 * @protected
7231 */
7232 this._handlers = {};
7233
7234 /**
7235 * References to the running plugins of this carousel.
7236 * @protected
7237 */
7238 this._plugins = {};
7239
7240 /**
7241 * Currently suppressed events to prevent them from being retriggered.
7242 * @protected
7243 */
7244 this._supress = {};
7245
7246 /**
7247 * Absolute current position.
7248 * @protected
7249 */
7250 this._current = null;
7251
7252 /**
7253 * Animation speed in milliseconds.
7254 * @protected
7255 */
7256 this._speed = null;
7257
7258 /**
7259 * Coordinates of all items in pixel.
7260 * @todo The name of this member is missleading.
7261 * @protected
7262 */
7263 this._coordinates = [];
7264
7265 /**
7266 * Current breakpoint.
7267 * @todo Real media queries would be nice.
7268 * @protected
7269 */
7270 this._breakpoint = null;
7271
7272 /**
7273 * Current width of the plugin element.
7274 */
7275 this._width = null;
7276
7277 /**
7278 * All real items.
7279 * @protected
7280 */
7281 this._items = [];
7282
7283 /**
7284 * All cloned items.
7285 * @protected
7286 */
7287 this._clones = [];
7288
7289 /**
7290 * Merge values of all items.
7291 * @todo Maybe this could be part of a plugin.
7292 * @protected
7293 */
7294 this._mergers = [];
7295
7296 /**
7297 * Widths of all items.
7298 */
7299 this._widths = [];
7300
7301 /**
7302 * Invalidated parts within the update process.
7303 * @protected
7304 */
7305 this._invalidated = {};
7306
7307 /**
7308 * Ordered list of workers for the update process.
7309 * @protected
7310 */
7311 this._pipe = [];
7312
7313 /**
7314 * Current state information for the drag operation.
7315 * @todo #261
7316 * @protected
7317 */
7318 this._drag = {
7319 time: null,
7320 target: null,
7321 pointer: null,
7322 stage: {
7323 start: null,
7324 current: null
7325 },
7326 direction: null
7327 };
7328
7329 /**
7330 * Current state information and their tags.
7331 * @type {Object}
7332 * @protected
7333 */
7334 this._states = {
7335 current: {},
7336 tags: {
7337 'initializing': [ 'busy' ],
7338 'animating': [ 'busy' ],
7339 'dragging': [ 'interacting' ]
7340 }
7341 };
7342
7343 $.each([ 'onResize', 'onThrottledResize' ], $.proxy(function(i, handler) {
7344 this._handlers[handler] = $.proxy(this[handler], this);
7345 }, this));
7346
7347 $.each(Owl.Plugins, $.proxy(function(key, plugin) {
7348 this._plugins[key.charAt(0).toLowerCase() + key.slice(1)]
7349 = new plugin(this);
7350 }, this));
7351
7352 $.each(Owl.Workers, $.proxy(function(priority, worker) {
7353 this._pipe.push({
7354 'filter': worker.filter,
7355 'run': $.proxy(worker.run, this)
7356 });
7357 }, this));
7358
7359 this.setup();
7360 this.initialize();
7361 }
7362
7363 /**
7364 * Default options for the carousel.
7365 * @public
7366 */
7367 Owl.Defaults = {
7368 items: 3,
7369 loop: false,
7370 center: false,
7371 rewind: false,
7372 checkVisibility: true,
7373
7374 mouseDrag: true,
7375 touchDrag: true,
7376 pullDrag: true,
7377 freeDrag: false,
7378
7379 margin: 0,
7380 stagePadding: 0,
7381
7382 merge: false,
7383 mergeFit: true,
7384 autoWidth: false,
7385
7386 startPosition: 0,
7387 rtl: false,
7388
7389 smartSpeed: 250,
7390 fluidSpeed: false,
7391 dragEndSpeed: false,
7392
7393 responsive: {},
7394 responsiveRefreshRate: 200,
7395 responsiveBaseElement: window,
7396
7397 fallbackEasing: 'swing',
7398 slideTransition: '',
7399
7400 info: false,
7401
7402 nestedItemSelector: false,
7403 itemElement: 'div',
7404 stageElement: 'div',
7405
7406 refreshClass: 'owl-refresh',
7407 loadedClass: 'owl-loaded',
7408 loadingClass: 'owl-loading',
7409 rtlClass: 'owl-rtl',
7410 responsiveClass: 'owl-responsive',
7411 dragClass: 'owl-drag',
7412 itemClass: 'owl-item',
7413 stageClass: 'owl-stage',
7414 stageOuterClass: 'owl-stage-outer',
7415 grabClass: 'owl-grab'
7416 };
7417
7418 /**
7419 * Enumeration for width.
7420 * @public
7421 * @readonly
7422 * @enum {String}
7423 */
7424 Owl.Width = {
7425 Default: 'default',
7426 Inner: 'inner',
7427 Outer: 'outer'
7428 };
7429
7430 /**
7431 * Enumeration for types.
7432 * @public
7433 * @readonly
7434 * @enum {String}
7435 */
7436 Owl.Type = {
7437 Event: 'event',
7438 State: 'state'
7439 };
7440
7441 /**
7442 * Contains all registered plugins.
7443 * @public
7444 */
7445 Owl.Plugins = {};
7446
7447 /**
7448 * List of workers involved in the update process.
7449 */
7450 Owl.Workers = [ {
7451 filter: [ 'width', 'settings' ],
7452 run: function() {
7453 this._width = this.$element.width();
7454 }
7455 }, {
7456 filter: [ 'width', 'items', 'settings' ],
7457 run: function(cache) {
7458 cache.current = this._items && this._items[this.relative(this._current)];
7459 }
7460 }, {
7461 filter: [ 'items', 'settings' ],
7462 run: function() {
7463 this.$stage.children('.cloned').remove();
7464 }
7465 }, {
7466 filter: [ 'width', 'items', 'settings' ],
7467 run: function(cache) {
7468 var margin = this.settings.margin || '',
7469 grid = !this.settings.autoWidth,
7470 rtl = this.settings.rtl,
7471 css = {
7472 'width': 'auto',
7473 'margin-left': rtl ? margin : '',
7474 'margin-right': rtl ? '' : margin
7475 };
7476
7477 !grid && this.$stage.children().css(css);
7478
7479 cache.css = css;
7480 }
7481 }, {
7482 filter: [ 'width', 'items', 'settings' ],
7483 run: function(cache) {
7484 var width = (this.width() / this.settings.items).toFixed(3) - this.settings.margin,
7485 merge = null,
7486 iterator = this._items.length,
7487 grid = !this.settings.autoWidth,
7488 widths = [];
7489
7490 cache.items = {
7491 merge: false,
7492 width: width
7493 };
7494
7495 while (iterator--) {
7496 merge = this._mergers[iterator];
7497 merge = this.settings.mergeFit && Math.min(merge, this.settings.items) || merge;
7498
7499 cache.items.merge = merge > 1 || cache.items.merge;
7500
7501 widths[iterator] = !grid ? this._items[iterator].width() : width * merge;
7502 }
7503
7504 this._widths = widths;
7505 }
7506 }, {
7507 filter: [ 'items', 'settings' ],
7508 run: function() {
7509 var clones = [],
7510 items = this._items,
7511 settings = this.settings,
7512 // TODO: Should be computed from number of min width items in stage
7513 view = Math.max(settings.items * 2, 4),
7514 size = Math.ceil(items.length / 2) * 2,
7515 repeat = settings.loop && items.length ? settings.rewind ? view : Math.max(view, size) : 0,
7516 append = '',
7517 prepend = '';
7518
7519 repeat /= 2;
7520
7521 while (repeat > 0) {
7522 // Switch to only using appended clones
7523 clones.push(this.normalize(clones.length / 2, true));
7524 append = append + items[clones[clones.length - 1]][0].outerHTML;
7525 clones.push(this.normalize(items.length - 1 - (clones.length - 1) / 2, true));
7526 prepend = items[clones[clones.length - 1]][0].outerHTML + prepend;
7527 repeat -= 1;
7528 }
7529
7530 this._clones = clones;
7531
7532 $(append).addClass('cloned').appendTo(this.$stage);
7533 $(prepend).addClass('cloned').prependTo(this.$stage);
7534 }
7535 }, {
7536 filter: [ 'width', 'items', 'settings' ],
7537 run: function() {
7538 var rtl = this.settings.rtl ? 1 : -1,
7539 size = this._clones.length + this._items.length,
7540 iterator = -1,
7541 previous = 0,
7542 current = 0,
7543 coordinates = [];
7544
7545 while (++iterator < size) {
7546 previous = coordinates[iterator - 1] || 0;
7547 current = this._widths[this.relative(iterator)] + this.settings.margin;
7548 coordinates.push(previous + current * rtl);
7549 }
7550
7551 this._coordinates = coordinates;
7552 }
7553 }, {
7554 filter: [ 'width', 'items', 'settings' ],
7555 run: function() {
7556 var padding = this.settings.stagePadding,
7557 coordinates = this._coordinates,
7558 css = {
7559 'width': Math.ceil(Math.abs(coordinates[coordinates.length - 1])) + padding * 2,
7560 'padding-left': padding || '',
7561 'padding-right': padding || ''
7562 };
7563
7564 this.$stage.css(css);
7565 }
7566 }, {
7567 filter: [ 'width', 'items', 'settings' ],
7568 run: function(cache) {
7569 var iterator = this._coordinates.length,
7570 grid = !this.settings.autoWidth,
7571 items = this.$stage.children();
7572
7573 if (grid && cache.items.merge) {
7574 while (iterator--) {
7575 cache.css.width = this._widths[this.relative(iterator)];
7576 items.eq(iterator).css(cache.css);
7577 }
7578 } else if (grid) {
7579 cache.css.width = cache.items.width;
7580 items.css(cache.css);
7581 }
7582 }
7583 }, {
7584 filter: [ 'items' ],
7585 run: function() {
7586 this._coordinates.length < 1 && this.$stage.removeAttr('style');
7587 }
7588 }, {
7589 filter: [ 'width', 'items', 'settings' ],
7590 run: function(cache) {
7591 cache.current = cache.current ? this.$stage.children().index(cache.current) : 0;
7592 cache.current = Math.max(this.minimum(), Math.min(this.maximum(), cache.current));
7593 this.reset(cache.current);
7594 }
7595 }, {
7596 filter: [ 'position' ],
7597 run: function() {
7598 this.animate(this.coordinates(this._current));
7599 }
7600 }, {
7601 filter: [ 'width', 'position', 'items', 'settings' ],
7602 run: function() {
7603 var rtl = this.settings.rtl ? 1 : -1,
7604 padding = this.settings.stagePadding * 2,
7605 begin = this.coordinates(this.current()) + padding,
7606 end = begin + this.width() * rtl,
7607 inner, outer, matches = [], i, n;
7608
7609 for (i = 0, n = this._coordinates.length; i < n; i++) {
7610 inner = this._coordinates[i - 1] || 0;
7611 outer = Math.abs(this._coordinates[i]) + padding * rtl;
7612
7613 if ((this.op(inner, '<=', begin) && (this.op(inner, '>', end)))
7614 || (this.op(outer, '<', begin) && this.op(outer, '>', end))) {
7615 matches.push(i);
7616 }
7617 }
7618
7619 this.$stage.children('.active').removeClass('active');
7620 this.$stage.children(':eq(' + matches.join('), :eq(') + ')').addClass('active');
7621
7622 this.$stage.children('.center').removeClass('center');
7623 if (this.settings.center) {
7624 this.$stage.children().eq(this.current()).addClass('center');
7625 }
7626 }
7627} ];
7628
7629 /**
7630 * Create the stage DOM element
7631 */
7632 Owl.prototype.initializeStage = function() {
7633 this.$stage = this.$element.find('.' + this.settings.stageClass);
7634
7635 // if the stage is already in the DOM, grab it and skip stage initialization
7636 if (this.$stage.length) {
7637 return;
7638 }
7639
7640 this.$element.addClass(this.options.loadingClass);
7641
7642 // create stage
7643 this.$stage = $('<' + this.settings.stageElement + '>', {
7644 "class": this.settings.stageClass
7645 }).wrap( $( '<div/>', {
7646 "class": this.settings.stageOuterClass
7647 }));
7648
7649 // append stage
7650 this.$element.append(this.$stage.parent());
7651 };
7652
7653 /**
7654 * Create item DOM elements
7655 */
7656 Owl.prototype.initializeItems = function() {
7657 var $items = this.$element.find('.owl-item');
7658
7659 // if the items are already in the DOM, grab them and skip item initialization
7660 if ($items.length) {
7661 this._items = $items.get().map(function(item) {
7662 return $(item);
7663 });
7664
7665 this._mergers = this._items.map(function() {
7666 return 1;
7667 });
7668
7669 this.refresh();
7670
7671 return;
7672 }
7673
7674 // append content
7675 this.replace(this.$element.children().not(this.$stage.parent()));
7676
7677 // check visibility
7678 if (this.isVisible()) {
7679 // update view
7680 this.refresh();
7681 } else {
7682 // invalidate width
7683 this.invalidate('width');
7684 }
7685
7686 this.$element
7687 .removeClass(this.options.loadingClass)
7688 .addClass(this.options.loadedClass);
7689 };
7690
7691 /**
7692 * Initializes the carousel.
7693 * @protected
7694 */
7695 Owl.prototype.initialize = function() {
7696 this.enter('initializing');
7697 this.trigger('initialize');
7698
7699 this.$element.toggleClass(this.settings.rtlClass, this.settings.rtl);
7700
7701 if (this.settings.autoWidth && !this.is('pre-loading')) {
7702 var imgs, nestedSelector, width;
7703 imgs = this.$element.find('img');
7704 nestedSelector = this.settings.nestedItemSelector ? '.' + this.settings.nestedItemSelector : undefined;
7705 width = this.$element.children(nestedSelector).width();
7706
7707 if (imgs.length && width <= 0) {
7708 this.preloadAutoWidthImages(imgs);
7709 }
7710 }
7711
7712 this.initializeStage();
7713 this.initializeItems();
7714
7715 // register event handlers
7716 this.registerEventHandlers();
7717
7718 this.leave('initializing');
7719 this.trigger('initialized');
7720 };
7721
7722 /**
7723 * @returns {Boolean} visibility of $element
7724 * if you know the carousel will always be visible you can set `checkVisibility` to `false` to
7725 * prevent the expensive browser layout forced reflow the $element.is(':visible') does
7726 */
7727 Owl.prototype.isVisible = function() {
7728 return this.settings.checkVisibility
7729 ? this.$element.is(':visible')
7730 : true;
7731 };
7732
7733 /**
7734 * Setups the current settings.
7735 * @todo Remove responsive classes. Why should adaptive designs be brought into IE8?
7736 * @todo Support for media queries by using `matchMedia` would be nice.
7737 * @public
7738 */
7739 Owl.prototype.setup = function() {
7740 var viewport = this.viewport(),
7741 overwrites = this.options.responsive,
7742 match = -1,
7743 settings = null;
7744
7745 if (!overwrites) {
7746 settings = $.extend({}, this.options);
7747 } else {
7748 $.each(overwrites, function(breakpoint) {
7749 if (breakpoint <= viewport && breakpoint > match) {
7750 match = Number(breakpoint);
7751 }
7752 });
7753
7754 settings = $.extend({}, this.options, overwrites[match]);
7755 if (typeof settings.stagePadding === 'function') {
7756 settings.stagePadding = settings.stagePadding();
7757 }
7758 delete settings.responsive;
7759
7760 // responsive class
7761 if (settings.responsiveClass) {
7762 this.$element.attr('class',
7763 this.$element.attr('class').replace(new RegExp('(' + this.options.responsiveClass + '-)\\S+\\s', 'g'), '$1' + match)
7764 );
7765 }
7766 }
7767
7768 this.trigger('change', { property: { name: 'settings', value: settings } });
7769 this._breakpoint = match;
7770 this.settings = settings;
7771 this.invalidate('settings');
7772 this.trigger('changed', { property: { name: 'settings', value: this.settings } });
7773 };
7774
7775 /**
7776 * Updates option logic if necessery.
7777 * @protected
7778 */
7779 Owl.prototype.optionsLogic = function() {
7780 if (this.settings.autoWidth) {
7781 this.settings.stagePadding = false;
7782 this.settings.merge = false;
7783 }
7784 };
7785
7786 /**
7787 * Prepares an item before add.
7788 * @todo Rename event parameter `content` to `item`.
7789 * @protected
7790 * @returns {jQuery|HTMLElement} - The item container.
7791 */
7792 Owl.prototype.prepare = function(item) {
7793 var event = this.trigger('prepare', { content: item });
7794
7795 if (!event.data) {
7796 event.data = $('<' + this.settings.itemElement + '/>')
7797 .addClass(this.options.itemClass).append(item)
7798 }
7799
7800 this.trigger('prepared', { content: event.data });
7801
7802 return event.data;
7803 };
7804
7805 /**
7806 * Updates the view.
7807 * @public
7808 */
7809 Owl.prototype.update = function() {
7810 var i = 0,
7811 n = this._pipe.length,
7812 filter = $.proxy(function(p) { return this[p] }, this._invalidated),
7813 cache = {};
7814
7815 while (i < n) {
7816 if (this._invalidated.all || $.grep(this._pipe[i].filter, filter).length > 0) {
7817 this._pipe[i].run(cache);
7818 }
7819 i++;
7820 }
7821
7822 this._invalidated = {};
7823
7824 !this.is('valid') && this.enter('valid');
7825 };
7826
7827 /**
7828 * Gets the width of the view.
7829 * @public
7830 * @param {Owl.Width} [dimension=Owl.Width.Default] - The dimension to return.
7831 * @returns {Number} - The width of the view in pixel.
7832 */
7833 Owl.prototype.width = function(dimension) {
7834 dimension = dimension || Owl.Width.Default;
7835 switch (dimension) {
7836 case Owl.Width.Inner:
7837 case Owl.Width.Outer:
7838 return this._width;
7839 default:
7840 return this._width - this.settings.stagePadding * 2 + this.settings.margin;
7841 }
7842 };
7843
7844 /**
7845 * Refreshes the carousel primarily for adaptive purposes.
7846 * @public
7847 */
7848 Owl.prototype.refresh = function() {
7849 this.enter('refreshing');
7850 this.trigger('refresh');
7851
7852 this.setup();
7853
7854 this.optionsLogic();
7855
7856 this.$element.addClass(this.options.refreshClass);
7857
7858 this.update();
7859
7860 this.$element.removeClass(this.options.refreshClass);
7861
7862 this.leave('refreshing');
7863 this.trigger('refreshed');
7864 };
7865
7866 /**
7867 * Checks window `resize` event.
7868 * @protected
7869 */
7870 Owl.prototype.onThrottledResize = function() {
7871 window.clearTimeout(this.resizeTimer);
7872 this.resizeTimer = window.setTimeout(this._handlers.onResize, this.settings.responsiveRefreshRate);
7873 };
7874
7875 /**
7876 * Checks window `resize` event.
7877 * @protected
7878 */
7879 Owl.prototype.onResize = function() {
7880 if (!this._items.length) {
7881 return false;
7882 }
7883
7884 if (this._width === this.$element.width()) {
7885 return false;
7886 }
7887
7888 if (!this.isVisible()) {
7889 return false;
7890 }
7891
7892 this.enter('resizing');
7893
7894 if (this.trigger('resize').isDefaultPrevented()) {
7895 this.leave('resizing');
7896 return false;
7897 }
7898
7899 this.invalidate('width');
7900
7901 this.refresh();
7902
7903 this.leave('resizing');
7904 this.trigger('resized');
7905 };
7906
7907 /**
7908 * Registers event handlers.
7909 * @todo Check `msPointerEnabled`
7910 * @todo #261
7911 * @protected
7912 */
7913 Owl.prototype.registerEventHandlers = function() {
7914 if ($.support.transition) {
7915 this.$stage.on($.support.transition.end + '.owl.core', $.proxy(this.onTransitionEnd, this));
7916 }
7917
7918 if (this.settings.responsive !== false) {
7919 this.on(window, 'resize', this._handlers.onThrottledResize);
7920 }
7921
7922 if (this.settings.mouseDrag) {
7923 this.$element.addClass(this.options.dragClass);
7924 this.$stage.on('mousedown.owl.core', $.proxy(this.onDragStart, this));
7925 this.$stage.on('dragstart.owl.core selectstart.owl.core', function() { return false });
7926 }
7927
7928 if (this.settings.touchDrag){
7929 this.$stage.on('touchstart.owl.core', $.proxy(this.onDragStart, this));
7930 this.$stage.on('touchcancel.owl.core', $.proxy(this.onDragEnd, this));
7931 }
7932 };
7933
7934 /**
7935 * Handles `touchstart` and `mousedown` events.
7936 * @todo Horizontal swipe threshold as option
7937 * @todo #261
7938 * @protected
7939 * @param {Event} event - The event arguments.
7940 */
7941 Owl.prototype.onDragStart = function(event) {
7942 var stage = null;
7943
7944 if (event.which === 3) {
7945 return;
7946 }
7947
7948 if ($.support.transform) {
7949 stage = this.$stage.css('transform').replace(/.*\(|\)| /g, '').split(',');
7950 stage = {
7951 x: stage[stage.length === 16 ? 12 : 4],
7952 y: stage[stage.length === 16 ? 13 : 5]
7953 };
7954 } else {
7955 stage = this.$stage.position();
7956 stage = {
7957 x: this.settings.rtl ?
7958 stage.left + this.$stage.width() - this.width() + this.settings.margin :
7959 stage.left,
7960 y: stage.top
7961 };
7962 }
7963
7964 if (this.is('animating')) {
7965 $.support.transform ? this.animate(stage.x) : this.$stage.stop()
7966 this.invalidate('position');
7967 }
7968
7969 this.$element.toggleClass(this.options.grabClass, event.type === 'mousedown');
7970
7971 this.speed(0);
7972
7973 this._drag.time = new Date().getTime();
7974 this._drag.target = $(event.target);
7975 this._drag.stage.start = stage;
7976 this._drag.stage.current = stage;
7977 this._drag.pointer = this.pointer(event);
7978
7979 $(document).on('mouseup.owl.core touchend.owl.core', $.proxy(this.onDragEnd, this));
7980
7981 $(document).one('mousemove.owl.core touchmove.owl.core', $.proxy(function(event) {
7982 var delta = this.difference(this._drag.pointer, this.pointer(event));
7983
7984 $(document).on('mousemove.owl.core touchmove.owl.core', $.proxy(this.onDragMove, this));
7985
7986 if (Math.abs(delta.x) < Math.abs(delta.y) && this.is('valid')) {
7987 return;
7988 }
7989
7990 event.preventDefault();
7991
7992 this.enter('dragging');
7993 this.trigger('drag');
7994 }, this));
7995 };
7996
7997 /**
7998 * Handles the `touchmove` and `mousemove` events.
7999 * @todo #261
8000 * @protected
8001 * @param {Event} event - The event arguments.
8002 */
8003 Owl.prototype.onDragMove = function(event) {
8004 var minimum = null,
8005 maximum = null,
8006 pull = null,
8007 delta = this.difference(this._drag.pointer, this.pointer(event)),
8008 stage = this.difference(this._drag.stage.start, delta);
8009
8010 if (!this.is('dragging')) {
8011 return;
8012 }
8013
8014 event.preventDefault();
8015
8016 if (this.settings.loop) {
8017 minimum = this.coordinates(this.minimum());
8018 maximum = this.coordinates(this.maximum() + 1) - minimum;
8019 stage.x = (((stage.x - minimum) % maximum + maximum) % maximum) + minimum;
8020 } else {
8021 minimum = this.settings.rtl ? this.coordinates(this.maximum()) : this.coordinates(this.minimum());
8022 maximum = this.settings.rtl ? this.coordinates(this.minimum()) : this.coordinates(this.maximum());
8023 pull = this.settings.pullDrag ? -1 * delta.x / 5 : 0;
8024 stage.x = Math.max(Math.min(stage.x, minimum + pull), maximum + pull);
8025 }
8026
8027 this._drag.stage.current = stage;
8028
8029 this.animate(stage.x);
8030 };
8031
8032 /**
8033 * Handles the `touchend` and `mouseup` events.
8034 * @todo #261
8035 * @todo Threshold for click event
8036 * @protected
8037 * @param {Event} event - The event arguments.
8038 */
8039 Owl.prototype.onDragEnd = function(event) {
8040 var delta = this.difference(this._drag.pointer, this.pointer(event)),
8041 stage = this._drag.stage.current,
8042 direction = delta.x > 0 ^ this.settings.rtl ? 'left' : 'right';
8043
8044 $(document).off('.owl.core');
8045
8046 this.$element.removeClass(this.options.grabClass);
8047
8048 if (delta.x !== 0 && this.is('dragging') || !this.is('valid')) {
8049 this.speed(this.settings.dragEndSpeed || this.settings.smartSpeed);
8050 this.current(this.closest(stage.x, delta.x !== 0 ? direction : this._drag.direction));
8051 this.invalidate('position');
8052 this.update();
8053
8054 this._drag.direction = direction;
8055
8056 if (Math.abs(delta.x) > 3 || new Date().getTime() - this._drag.time > 300) {
8057 this._drag.target.one('click.owl.core', function() { return false; });
8058 }
8059 }
8060
8061 if (!this.is('dragging')) {
8062 return;
8063 }
8064
8065 this.leave('dragging');
8066 this.trigger('dragged');
8067 };
8068
8069 /**
8070 * Gets absolute position of the closest item for a coordinate.
8071 * @todo Setting `freeDrag` makes `closest` not reusable. See #165.
8072 * @protected
8073 * @param {Number} coordinate - The coordinate in pixel.
8074 * @param {String} direction - The direction to check for the closest item. Ether `left` or `right`.
8075 * @return {Number} - The absolute position of the closest item.
8076 */
8077 Owl.prototype.closest = function(coordinate, direction) {
8078 var position = -1,
8079 pull = 30,
8080 width = this.width(),
8081 coordinates = this.coordinates();
8082
8083 if (!this.settings.freeDrag) {
8084 // check closest item
8085 $.each(coordinates, $.proxy(function(index, value) {
8086 // on a left pull, check on current index
8087 if (direction === 'left' && coordinate > value - pull && coordinate < value + pull) {
8088 position = index;
8089 // on a right pull, check on previous index
8090 // to do so, subtract width from value and set position = index + 1
8091 } else if (direction === 'right' && coordinate > value - width - pull && coordinate < value - width + pull) {
8092 position = index + 1;
8093 } else if (this.op(coordinate, '<', value)
8094 && this.op(coordinate, '>', coordinates[index + 1] !== undefined ? coordinates[index + 1] : value - width)) {
8095 position = direction === 'left' ? index + 1 : index;
8096 }
8097 return position === -1;
8098 }, this));
8099 }
8100
8101 if (!this.settings.loop) {
8102 // non loop boundries
8103 if (this.op(coordinate, '>', coordinates[this.minimum()])) {
8104 position = coordinate = this.minimum();
8105 } else if (this.op(coordinate, '<', coordinates[this.maximum()])) {
8106 position = coordinate = this.maximum();
8107 }
8108 }
8109
8110 return position;
8111 };
8112
8113 /**
8114 * Animates the stage.
8115 * @todo #270
8116 * @public
8117 * @param {Number} coordinate - The coordinate in pixels.
8118 */
8119 Owl.prototype.animate = function(coordinate) {
8120 var animate = this.speed() > 0;
8121
8122 this.is('animating') && this.onTransitionEnd();
8123
8124 if (animate) {
8125 this.enter('animating');
8126 this.trigger('translate');
8127 }
8128
8129 if ($.support.transform3d && $.support.transition) {
8130 this.$stage.css({
8131 transform: 'translate3d(' + coordinate + 'px,0px,0px)',
8132 transition: (this.speed() / 1000) + 's' + (
8133 this.settings.slideTransition ? ' ' + this.settings.slideTransition : ''
8134 )
8135 });
8136 } else if (animate) {
8137 this.$stage.animate({
8138 left: coordinate + 'px'
8139 }, this.speed(), this.settings.fallbackEasing, $.proxy(this.onTransitionEnd, this));
8140 } else {
8141 this.$stage.css({
8142 left: coordinate + 'px'
8143 });
8144 }
8145 };
8146
8147 /**
8148 * Checks whether the carousel is in a specific state or not.
8149 * @param {String} state - The state to check.
8150 * @returns {Boolean} - The flag which indicates if the carousel is busy.
8151 */
8152 Owl.prototype.is = function(state) {
8153 return this._states.current[state] && this._states.current[state] > 0;
8154 };
8155
8156 /**
8157 * Sets the absolute position of the current item.
8158 * @public
8159 * @param {Number} [position] - The new absolute position or nothing to leave it unchanged.
8160 * @returns {Number} - The absolute position of the current item.
8161 */
8162 Owl.prototype.current = function(position) {
8163 if (position === undefined) {
8164 return this._current;
8165 }
8166
8167 if (this._items.length === 0) {
8168 return undefined;
8169 }
8170
8171 position = this.normalize(position);
8172
8173 if (this._current !== position) {
8174 var event = this.trigger('change', { property: { name: 'position', value: position } });
8175
8176 if (event.data !== undefined) {
8177 position = this.normalize(event.data);
8178 }
8179
8180 this._current = position;
8181
8182 this.invalidate('position');
8183
8184 this.trigger('changed', { property: { name: 'position', value: this._current } });
8185 }
8186
8187 return this._current;
8188 };
8189
8190 /**
8191 * Invalidates the given part of the update routine.
8192 * @param {String} [part] - The part to invalidate.
8193 * @returns {Array.<String>} - The invalidated parts.
8194 */
8195 Owl.prototype.invalidate = function(part) {
8196 if ($.type(part) === 'string') {
8197 this._invalidated[part] = true;
8198 this.is('valid') && this.leave('valid');
8199 }
8200 return $.map(this._invalidated, function(v, i) { return i });
8201 };
8202
8203 /**
8204 * Resets the absolute position of the current item.
8205 * @public
8206 * @param {Number} position - The absolute position of the new item.
8207 */
8208 Owl.prototype.reset = function(position) {
8209 position = this.normalize(position);
8210
8211 if (position === undefined) {
8212 return;
8213 }
8214
8215 this._speed = 0;
8216 this._current = position;
8217
8218 this.suppress([ 'translate', 'translated' ]);
8219
8220 this.animate(this.coordinates(position));
8221
8222 this.release([ 'translate', 'translated' ]);
8223 };
8224
8225 /**
8226 * Normalizes an absolute or a relative position of an item.
8227 * @public
8228 * @param {Number} position - The absolute or relative position to normalize.
8229 * @param {Boolean} [relative=false] - Whether the given position is relative or not.
8230 * @returns {Number} - The normalized position.
8231 */
8232 Owl.prototype.normalize = function(position, relative) {
8233 var n = this._items.length,
8234 m = relative ? 0 : this._clones.length;
8235
8236 if (!this.isNumeric(position) || n < 1) {
8237 position = undefined;
8238 } else if (position < 0 || position >= n + m) {
8239 position = ((position - m / 2) % n + n) % n + m / 2;
8240 }
8241
8242 return position;
8243 };
8244
8245 /**
8246 * Converts an absolute position of an item into a relative one.
8247 * @public
8248 * @param {Number} position - The absolute position to convert.
8249 * @returns {Number} - The converted position.
8250 */
8251 Owl.prototype.relative = function(position) {
8252 position -= this._clones.length / 2;
8253 return this.normalize(position, true);
8254 };
8255
8256 /**
8257 * Gets the maximum position for the current item.
8258 * @public
8259 * @param {Boolean} [relative=false] - Whether to return an absolute position or a relative position.
8260 * @returns {Number}
8261 */
8262 Owl.prototype.maximum = function(relative) {
8263 var settings = this.settings,
8264 maximum = this._coordinates.length,
8265 iterator,
8266 reciprocalItemsWidth,
8267 elementWidth;
8268
8269 if (settings.loop) {
8270 maximum = this._clones.length / 2 + this._items.length - 1;
8271 } else if (settings.autoWidth || settings.merge) {
8272 iterator = this._items.length;
8273 if (iterator) {
8274 reciprocalItemsWidth = this._items[--iterator].width();
8275 elementWidth = this.$element.width();
8276 while (iterator--) {
8277 reciprocalItemsWidth += this._items[iterator].width() + this.settings.margin;
8278 if (reciprocalItemsWidth > elementWidth) {
8279 break;
8280 }
8281 }
8282 }
8283 maximum = iterator + 1;
8284 } else if (settings.center) {
8285 maximum = this._items.length - 1;
8286 } else {
8287 maximum = this._items.length - settings.items;
8288 }
8289
8290 if (relative) {
8291 maximum -= this._clones.length / 2;
8292 }
8293
8294 return Math.max(maximum, 0);
8295 };
8296
8297 /**
8298 * Gets the minimum position for the current item.
8299 * @public
8300 * @param {Boolean} [relative=false] - Whether to return an absolute position or a relative position.
8301 * @returns {Number}
8302 */
8303 Owl.prototype.minimum = function(relative) {
8304 return relative ? 0 : this._clones.length / 2;
8305 };
8306
8307 /**
8308 * Gets an item at the specified relative position.
8309 * @public
8310 * @param {Number} [position] - The relative position of the item.
8311 * @return {jQuery|Array.<jQuery>} - The item at the given position or all items if no position was given.
8312 */
8313 Owl.prototype.items = function(position) {
8314 if (position === undefined) {
8315 return this._items.slice();
8316 }
8317
8318 position = this.normalize(position, true);
8319 return this._items[position];
8320 };
8321
8322 /**
8323 * Gets an item at the specified relative position.
8324 * @public
8325 * @param {Number} [position] - The relative position of the item.
8326 * @return {jQuery|Array.<jQuery>} - The item at the given position or all items if no position was given.
8327 */
8328 Owl.prototype.mergers = function(position) {
8329 if (position === undefined) {
8330 return this._mergers.slice();
8331 }
8332
8333 position = this.normalize(position, true);
8334 return this._mergers[position];
8335 };
8336
8337 /**
8338 * Gets the absolute positions of clones for an item.
8339 * @public
8340 * @param {Number} [position] - The relative position of the item.
8341 * @returns {Array.<Number>} - The absolute positions of clones for the item or all if no position was given.
8342 */
8343 Owl.prototype.clones = function(position) {
8344 var odd = this._clones.length / 2,
8345 even = odd + this._items.length,
8346 map = function(index) { return index % 2 === 0 ? even + index / 2 : odd - (index + 1) / 2 };
8347
8348 if (position === undefined) {
8349 return $.map(this._clones, function(v, i) { return map(i) });
8350 }
8351
8352 return $.map(this._clones, function(v, i) { return v === position ? map(i) : null });
8353 };
8354
8355 /**
8356 * Sets the current animation speed.
8357 * @public
8358 * @param {Number} [speed] - The animation speed in milliseconds or nothing to leave it unchanged.
8359 * @returns {Number} - The current animation speed in milliseconds.
8360 */
8361 Owl.prototype.speed = function(speed) {
8362 if (speed !== undefined) {
8363 this._speed = speed;
8364 }
8365
8366 return this._speed;
8367 };
8368
8369 /**
8370 * Gets the coordinate of an item.
8371 * @todo The name of this method is missleanding.
8372 * @public
8373 * @param {Number} position - The absolute position of the item within `minimum()` and `maximum()`.
8374 * @returns {Number|Array.<Number>} - The coordinate of the item in pixel or all coordinates.
8375 */
8376 Owl.prototype.coordinates = function(position) {
8377 var multiplier = 1,
8378 newPosition = position - 1,
8379 coordinate;
8380
8381 if (position === undefined) {
8382 return $.map(this._coordinates, $.proxy(function(coordinate, index) {
8383 return this.coordinates(index);
8384 }, this));
8385 }
8386
8387 if (this.settings.center) {
8388 if (this.settings.rtl) {
8389 multiplier = -1;
8390 newPosition = position + 1;
8391 }
8392
8393 coordinate = this._coordinates[position];
8394 coordinate += (this.width() - coordinate + (this._coordinates[newPosition] || 0)) / 2 * multiplier;
8395 } else {
8396 coordinate = this._coordinates[newPosition] || 0;
8397 }
8398
8399 coordinate = Math.ceil(coordinate);
8400
8401 return coordinate;
8402 };
8403
8404 /**
8405 * Calculates the speed for a translation.
8406 * @protected
8407 * @param {Number} from - The absolute position of the start item.
8408 * @param {Number} to - The absolute position of the target item.
8409 * @param {Number} [factor=undefined] - The time factor in milliseconds.
8410 * @returns {Number} - The time in milliseconds for the translation.
8411 */
8412 Owl.prototype.duration = function(from, to, factor) {
8413 if (factor === 0) {
8414 return 0;
8415 }
8416
8417 return Math.min(Math.max(Math.abs(to - from), 1), 6) * Math.abs((factor || this.settings.smartSpeed));
8418 };
8419
8420 /**
8421 * Slides to the specified item.
8422 * @public
8423 * @param {Number} position - The position of the item.
8424 * @param {Number} [speed] - The time in milliseconds for the transition.
8425 */
8426 Owl.prototype.to = function(position, speed) {
8427 var current = this.current(),
8428 revert = null,
8429 distance = position - this.relative(current),
8430 direction = (distance > 0) - (distance < 0),
8431 items = this._items.length,
8432 minimum = this.minimum(),
8433 maximum = this.maximum();
8434
8435 if (this.settings.loop) {
8436 if (!this.settings.rewind && Math.abs(distance) > items / 2) {
8437 distance += direction * -1 * items;
8438 }
8439
8440 position = current + distance;
8441 revert = ((position - minimum) % items + items) % items + minimum;
8442
8443 if (revert !== position && revert - distance <= maximum && revert - distance > 0) {
8444 current = revert - distance;
8445 position = revert;
8446 this.reset(current);
8447 }
8448 } else if (this.settings.rewind) {
8449 maximum += 1;
8450 position = (position % maximum + maximum) % maximum;
8451 } else {
8452 position = Math.max(minimum, Math.min(maximum, position));
8453 }
8454
8455 this.speed(this.duration(current, position, speed));
8456 this.current(position);
8457
8458 if (this.isVisible()) {
8459 this.update();
8460 }
8461 };
8462
8463 /**
8464 * Slides to the next item.
8465 * @public
8466 * @param {Number} [speed] - The time in milliseconds for the transition.
8467 */
8468 Owl.prototype.next = function(speed) {
8469 speed = speed || false;
8470 this.to(this.relative(this.current()) + 1, speed);
8471 };
8472
8473 /**
8474 * Slides to the previous item.
8475 * @public
8476 * @param {Number} [speed] - The time in milliseconds for the transition.
8477 */
8478 Owl.prototype.prev = function(speed) {
8479 speed = speed || false;
8480 this.to(this.relative(this.current()) - 1, speed);
8481 };
8482
8483 /**
8484 * Handles the end of an animation.
8485 * @protected
8486 * @param {Event} event - The event arguments.
8487 */
8488 Owl.prototype.onTransitionEnd = function(event) {
8489
8490 // if css2 animation then event object is undefined
8491 if (event !== undefined) {
8492 event.stopPropagation();
8493
8494 // Catch only owl-stage transitionEnd event
8495 if ((event.target || event.srcElement || event.originalTarget) !== this.$stage.get(0)) {
8496 return false;
8497 }
8498 }
8499
8500 this.leave('animating');
8501 this.trigger('translated');
8502 };
8503
8504 /**
8505 * Gets viewport width.
8506 * @protected
8507 * @return {Number} - The width in pixel.
8508 */
8509 Owl.prototype.viewport = function() {
8510 var width;
8511 if (this.options.responsiveBaseElement !== window) {
8512 width = $(this.options.responsiveBaseElement).width();
8513 } else if (window.innerWidth) {
8514 width = window.innerWidth;
8515 } else if (document.documentElement && document.documentElement.clientWidth) {
8516 width = document.documentElement.clientWidth;
8517 } else {
8518 console.warn('Can not detect viewport width.');
8519 }
8520 return width;
8521 };
8522
8523 /**
8524 * Replaces the current content.
8525 * @public
8526 * @param {HTMLElement|jQuery|String} content - The new content.
8527 */
8528 Owl.prototype.replace = function(content) {
8529 this.$stage.empty();
8530 this._items = [];
8531
8532 if (content) {
8533 content = (content instanceof jQuery) ? content : $(content);
8534 }
8535
8536 if (this.settings.nestedItemSelector) {
8537 content = content.find('.' + this.settings.nestedItemSelector);
8538 }
8539
8540 content.filter(function() {
8541 return this.nodeType === 1;
8542 }).each($.proxy(function(index, item) {
8543 item = this.prepare(item);
8544 this.$stage.append(item);
8545 this._items.push(item);
8546 this._mergers.push(item.find('[data-merge]').addBack('[data-merge]').attr('data-merge') * 1 || 1);
8547 }, this));
8548
8549 this.reset(this.isNumeric(this.settings.startPosition) ? this.settings.startPosition : 0);
8550
8551 this.invalidate('items');
8552 };
8553
8554 /**
8555 * Adds an item.
8556 * @todo Use `item` instead of `content` for the event arguments.
8557 * @public
8558 * @param {HTMLElement|jQuery|String} content - The item content to add.
8559 * @param {Number} [position] - The relative position at which to insert the item otherwise the item will be added to the end.
8560 */
8561 Owl.prototype.add = function(content, position) {
8562 var current = this.relative(this._current);
8563
8564 position = position === undefined ? this._items.length : this.normalize(position, true);
8565 content = content instanceof jQuery ? content : $(content);
8566
8567 this.trigger('add', { content: content, position: position });
8568
8569 content = this.prepare(content);
8570
8571 if (this._items.length === 0 || position === this._items.length) {
8572 this._items.length === 0 && this.$stage.append(content);
8573 this._items.length !== 0 && this._items[position - 1].after(content);
8574 this._items.push(content);
8575 this._mergers.push(content.find('[data-merge]').addBack('[data-merge]').attr('data-merge') * 1 || 1);
8576 } else {
8577 this._items[position].before(content);
8578 this._items.splice(position, 0, content);
8579 this._mergers.splice(position, 0, content.find('[data-merge]').addBack('[data-merge]').attr('data-merge') * 1 || 1);
8580 }
8581
8582 this._items[current] && this.reset(this._items[current].index());
8583
8584 this.invalidate('items');
8585
8586 this.trigger('added', { content: content, position: position });
8587 };
8588
8589 /**
8590 * Removes an item by its position.
8591 * @todo Use `item` instead of `content` for the event arguments.
8592 * @public
8593 * @param {Number} position - The relative position of the item to remove.
8594 */
8595 Owl.prototype.remove = function(position) {
8596 position = this.normalize(position, true);
8597
8598 if (position === undefined) {
8599 return;
8600 }
8601
8602 this.trigger('remove', { content: this._items[position], position: position });
8603
8604 this._items[position].remove();
8605 this._items.splice(position, 1);
8606 this._mergers.splice(position, 1);
8607
8608 this.invalidate('items');
8609
8610 this.trigger('removed', { content: null, position: position });
8611 };
8612
8613 /**
8614 * Preloads images with auto width.
8615 * @todo Replace by a more generic approach
8616 * @protected
8617 */
8618 Owl.prototype.preloadAutoWidthImages = function(images) {
8619 images.each($.proxy(function(i, element) {
8620 this.enter('pre-loading');
8621 element = $(element);
8622 $(new Image()).one('load', $.proxy(function(e) {
8623 element.attr('src', e.target.src);
8624 element.css('opacity', 1);
8625 this.leave('pre-loading');
8626 !this.is('pre-loading') && !this.is('initializing') && this.refresh();
8627 }, this)).attr('src', element.attr('src') || element.attr('data-src') || element.attr('data-src-retina'));
8628 }, this));
8629 };
8630
8631 /**
8632 * Destroys the carousel.
8633 * @public
8634 */
8635 Owl.prototype.destroy = function() {
8636
8637 this.$element.off('.owl.core');
8638 this.$stage.off('.owl.core');
8639 $(document).off('.owl.core');
8640
8641 if (this.settings.responsive !== false) {
8642 window.clearTimeout(this.resizeTimer);
8643 this.off(window, 'resize', this._handlers.onThrottledResize);
8644 }
8645
8646 for (var i in this._plugins) {
8647 this._plugins[i].destroy();
8648 }
8649
8650 this.$stage.children('.cloned').remove();
8651
8652 this.$stage.unwrap();
8653 this.$stage.children().contents().unwrap();
8654 this.$stage.children().unwrap();
8655 this.$stage.remove();
8656 this.$element
8657 .removeClass(this.options.refreshClass)
8658 .removeClass(this.options.loadingClass)
8659 .removeClass(this.options.loadedClass)
8660 .removeClass(this.options.rtlClass)
8661 .removeClass(this.options.dragClass)
8662 .removeClass(this.options.grabClass)
8663 .attr('class', this.$element.attr('class').replace(new RegExp(this.options.responsiveClass + '-\\S+\\s', 'g'), ''))
8664 .removeData('owl.carousel');
8665 };
8666
8667 /**
8668 * Operators to calculate right-to-left and left-to-right.
8669 * @protected
8670 * @param {Number} [a] - The left side operand.
8671 * @param {String} [o] - The operator.
8672 * @param {Number} [b] - The right side operand.
8673 */
8674 Owl.prototype.op = function(a, o, b) {
8675 var rtl = this.settings.rtl;
8676 switch (o) {
8677 case '<':
8678 return rtl ? a > b : a < b;
8679 case '>':
8680 return rtl ? a < b : a > b;
8681 case '>=':
8682 return rtl ? a <= b : a >= b;
8683 case '<=':
8684 return rtl ? a >= b : a <= b;
8685 default:
8686 break;
8687 }
8688 };
8689
8690 /**
8691 * Attaches to an internal event.
8692 * @protected
8693 * @param {HTMLElement} element - The event source.
8694 * @param {String} event - The event name.
8695 * @param {Function} listener - The event handler to attach.
8696 * @param {Boolean} capture - Wether the event should be handled at the capturing phase or not.
8697 */
8698 Owl.prototype.on = function(element, event, listener, capture) {
8699 if (element.addEventListener) {
8700 element.addEventListener(event, listener, capture);
8701 } else if (element.attachEvent) {
8702 element.attachEvent('on' + event, listener);
8703 }
8704 };
8705
8706 /**
8707 * Detaches from an internal event.
8708 * @protected
8709 * @param {HTMLElement} element - The event source.
8710 * @param {String} event - The event name.
8711 * @param {Function} listener - The attached event handler to detach.
8712 * @param {Boolean} capture - Wether the attached event handler was registered as a capturing listener or not.
8713 */
8714 Owl.prototype.off = function(element, event, listener, capture) {
8715 if (element.removeEventListener) {
8716 element.removeEventListener(event, listener, capture);
8717 } else if (element.detachEvent) {
8718 element.detachEvent('on' + event, listener);
8719 }
8720 };
8721
8722 /**
8723 * Triggers a public event.
8724 * @todo Remove `status`, `relatedTarget` should be used instead.
8725 * @protected
8726 * @param {String} name - The event name.
8727 * @param {*} [data=null] - The event data.
8728 * @param {String} [namespace=carousel] - The event namespace.
8729 * @param {String} [state] - The state which is associated with the event.
8730 * @param {Boolean} [enter=false] - Indicates if the call enters the specified state or not.
8731 * @returns {Event} - The event arguments.
8732 */
8733 Owl.prototype.trigger = function(name, data, namespace, state, enter) {
8734 var status = {
8735 item: { count: this._items.length, index: this.current() }
8736 }, handler = $.camelCase(
8737 $.grep([ 'on', name, namespace ], function(v) { return v })
8738 .join('-').toLowerCase()
8739 ), event = $.Event(
8740 [ name, 'owl', namespace || 'carousel' ].join('.').toLowerCase(),
8741 $.extend({ relatedTarget: this }, status, data)
8742 );
8743
8744 if (!this._supress[name]) {
8745 $.each(this._plugins, function(name, plugin) {
8746 if (plugin.onTrigger) {
8747 plugin.onTrigger(event);
8748 }
8749 });
8750
8751 this.register({ type: Owl.Type.Event, name: name });
8752 this.$element.trigger(event);
8753
8754 if (this.settings && typeof this.settings[handler] === 'function') {
8755 this.settings[handler].call(this, event);
8756 }
8757 }
8758
8759 return event;
8760 };
8761
8762 /**
8763 * Enters a state.
8764 * @param name - The state name.
8765 */
8766 Owl.prototype.enter = function(name) {
8767 $.each([ name ].concat(this._states.tags[name] || []), $.proxy(function(i, name) {
8768 if (this._states.current[name] === undefined) {
8769 this._states.current[name] = 0;
8770 }
8771
8772 this._states.current[name]++;
8773 }, this));
8774 };
8775
8776 /**
8777 * Leaves a state.
8778 * @param name - The state name.
8779 */
8780 Owl.prototype.leave = function(name) {
8781 $.each([ name ].concat(this._states.tags[name] || []), $.proxy(function(i, name) {
8782 this._states.current[name]--;
8783 }, this));
8784 };
8785
8786 /**
8787 * Registers an event or state.
8788 * @public
8789 * @param {Object} object - The event or state to register.
8790 */
8791 Owl.prototype.register = function(object) {
8792 if (object.type === Owl.Type.Event) {
8793 if (!$.event.special[object.name]) {
8794 $.event.special[object.name] = {};
8795 }
8796
8797 if (!$.event.special[object.name].owl) {
8798 var _default = $.event.special[object.name]._default;
8799 $.event.special[object.name]._default = function(e) {
8800 if (_default && _default.apply && (!e.namespace || e.namespace.indexOf('owl') === -1)) {
8801 return _default.apply(this, arguments);
8802 }
8803 return e.namespace && e.namespace.indexOf('owl') > -1;
8804 };
8805 $.event.special[object.name].owl = true;
8806 }
8807 } else if (object.type === Owl.Type.State) {
8808 if (!this._states.tags[object.name]) {
8809 this._states.tags[object.name] = object.tags;
8810 } else {
8811 this._states.tags[object.name] = this._states.tags[object.name].concat(object.tags);
8812 }
8813
8814 this._states.tags[object.name] = $.grep(this._states.tags[object.name], $.proxy(function(tag, i) {
8815 return $.inArray(tag, this._states.tags[object.name]) === i;
8816 }, this));
8817 }
8818 };
8819
8820 /**
8821 * Suppresses events.
8822 * @protected
8823 * @param {Array.<String>} events - The events to suppress.
8824 */
8825 Owl.prototype.suppress = function(events) {
8826 $.each(events, $.proxy(function(index, event) {
8827 this._supress[event] = true;
8828 }, this));
8829 };
8830
8831 /**
8832 * Releases suppressed events.
8833 * @protected
8834 * @param {Array.<String>} events - The events to release.
8835 */
8836 Owl.prototype.release = function(events) {
8837 $.each(events, $.proxy(function(index, event) {
8838 delete this._supress[event];
8839 }, this));
8840 };
8841
8842 /**
8843 * Gets unified pointer coordinates from event.
8844 * @todo #261
8845 * @protected
8846 * @param {Event} - The `mousedown` or `touchstart` event.
8847 * @returns {Object} - Contains `x` and `y` coordinates of current pointer position.
8848 */
8849 Owl.prototype.pointer = function(event) {
8850 var result = { x: null, y: null };
8851
8852 event = event.originalEvent || event || window.event;
8853
8854 event = event.touches && event.touches.length ?
8855 event.touches[0] : event.changedTouches && event.changedTouches.length ?
8856 event.changedTouches[0] : event;
8857
8858 if (event.pageX) {
8859 result.x = event.pageX;
8860 result.y = event.pageY;
8861 } else {
8862 result.x = event.clientX;
8863 result.y = event.clientY;
8864 }
8865
8866 return result;
8867 };
8868
8869 /**
8870 * Determines if the input is a Number or something that can be coerced to a Number
8871 * @protected
8872 * @param {Number|String|Object|Array|Boolean|RegExp|Function|Symbol} - The input to be tested
8873 * @returns {Boolean} - An indication if the input is a Number or can be coerced to a Number
8874 */
8875 Owl.prototype.isNumeric = function(number) {
8876 return !isNaN(parseFloat(number));
8877 };
8878
8879 /**
8880 * Gets the difference of two vectors.
8881 * @todo #261
8882 * @protected
8883 * @param {Object} - The first vector.
8884 * @param {Object} - The second vector.
8885 * @returns {Object} - The difference.
8886 */
8887 Owl.prototype.difference = function(first, second) {
8888 return {
8889 x: first.x - second.x,
8890 y: first.y - second.y
8891 };
8892 };
8893
8894 /**
8895 * The jQuery Plugin for the Owl Carousel
8896 * @todo Navigation plugin `next` and `prev`
8897 * @public
8898 */
8899 $.fn.owlCarousel = function(option) {
8900 var args = Array.prototype.slice.call(arguments, 1);
8901
8902 return this.each(function() {
8903 var $this = $(this),
8904 data = $this.data('owl.carousel');
8905
8906 if (!data) {
8907 data = new Owl(this, typeof option == 'object' && option);
8908 $this.data('owl.carousel', data);
8909
8910 $.each([
8911 'next', 'prev', 'to', 'destroy', 'refresh', 'replace', 'add', 'remove'
8912 ], function(i, event) {
8913 data.register({ type: Owl.Type.Event, name: event });
8914 data.$element.on(event + '.owl.carousel.core', $.proxy(function(e) {
8915 if (e.namespace && e.relatedTarget !== this) {
8916 this.suppress([ event ]);
8917 data[event].apply(this, [].slice.call(arguments, 1));
8918 this.release([ event ]);
8919 }
8920 }, data));
8921 });
8922 }
8923
8924 if (typeof option == 'string' && option.charAt(0) !== '_') {
8925 data[option].apply(data, args);
8926 }
8927 });
8928 };
8929
8930 /**
8931 * The constructor for the jQuery Plugin
8932 * @public
8933 */
8934 $.fn.owlCarousel.Constructor = Owl;
8935
8936 })(window.Zepto || window.jQuery, window, document);
8937
8938/**
8939 * AutoRefresh Plugin
8940 * @version 2.3.4
8941 * @author Artus Kolanowski
8942 * @author David Deutsch
8943 * @license The MIT License (MIT)
8944 */
8945 ;(function($, window, document, undefined) {
8946
8947 /**
8948 * Creates the auto refresh plugin.
8949 * @class The Auto Refresh Plugin
8950 * @param {Owl} carousel - The Owl Carousel
8951 */
8952 var AutoRefresh = function(carousel) {
8953 /**
8954 * Reference to the core.
8955 * @protected
8956 * @type {Owl}
8957 */
8958 this._core = carousel;
8959
8960 /**
8961 * Refresh interval.
8962 * @protected
8963 * @type {number}
8964 */
8965 this._interval = null;
8966
8967 /**
8968 * Whether the element is currently visible or not.
8969 * @protected
8970 * @type {Boolean}
8971 */
8972 this._visible = null;
8973
8974 /**
8975 * All event handlers.
8976 * @protected
8977 * @type {Object}
8978 */
8979 this._handlers = {
8980 'initialized.owl.carousel': $.proxy(function(e) {
8981 if (e.namespace && this._core.settings.autoRefresh) {
8982 this.watch();
8983 }
8984 }, this)
8985 };
8986
8987 // set default options
8988 this._core.options = $.extend({}, AutoRefresh.Defaults, this._core.options);
8989
8990 // register event handlers
8991 this._core.$element.on(this._handlers);
8992 };
8993
8994 /**
8995 * Default options.
8996 * @public
8997 */
8998 AutoRefresh.Defaults = {
8999 autoRefresh: true,
9000 autoRefreshInterval: 500
9001 };
9002
9003 /**
9004 * Watches the element.
9005 */
9006 AutoRefresh.prototype.watch = function() {
9007 if (this._interval) {
9008 return;
9009 }
9010
9011 this._visible = this._core.isVisible();
9012 this._interval = window.setInterval($.proxy(this.refresh, this), this._core.settings.autoRefreshInterval);
9013 };
9014
9015 /**
9016 * Refreshes the element.
9017 */
9018 AutoRefresh.prototype.refresh = function() {
9019 if (this._core.isVisible() === this._visible) {
9020 return;
9021 }
9022
9023 this._visible = !this._visible;
9024
9025 this._core.$element.toggleClass('owl-hidden', !this._visible);
9026
9027 this._visible && (this._core.invalidate('width') && this._core.refresh());
9028 };
9029
9030 /**
9031 * Destroys the plugin.
9032 */
9033 AutoRefresh.prototype.destroy = function() {
9034 var handler, property;
9035
9036 window.clearInterval(this._interval);
9037
9038 for (handler in this._handlers) {
9039 this._core.$element.off(handler, this._handlers[handler]);
9040 }
9041 for (property in Object.getOwnPropertyNames(this)) {
9042 typeof this[property] != 'function' && (this[property] = null);
9043 }
9044 };
9045
9046 $.fn.owlCarousel.Constructor.Plugins.AutoRefresh = AutoRefresh;
9047
9048 })(window.Zepto || window.jQuery, window, document);
9049
9050/**
9051 * Lazy Plugin
9052 * @version 2.3.4
9053 * @author Bartosz Wojciechowski
9054 * @author David Deutsch
9055 * @license The MIT License (MIT)
9056 */
9057 ;(function($, window, document, undefined) {
9058
9059 /**
9060 * Creates the lazy plugin.
9061 * @class The Lazy Plugin
9062 * @param {Owl} carousel - The Owl Carousel
9063 */
9064 var Lazy = function(carousel) {
9065
9066 /**
9067 * Reference to the core.
9068 * @protected
9069 * @type {Owl}
9070 */
9071 this._core = carousel;
9072
9073 /**
9074 * Already loaded items.
9075 * @protected
9076 * @type {Array.<jQuery>}
9077 */
9078 this._loaded = [];
9079
9080 /**
9081 * Event handlers.
9082 * @protected
9083 * @type {Object}
9084 */
9085 this._handlers = {
9086 'initialized.owl.carousel change.owl.carousel resized.owl.carousel': $.proxy(function(e) {
9087 if (!e.namespace) {
9088 return;
9089 }
9090
9091 if (!this._core.settings || !this._core.settings.lazyLoad) {
9092 return;
9093 }
9094
9095 if ((e.property && e.property.name == 'position') || e.type == 'initialized') {
9096 var settings = this._core.settings,
9097 n = (settings.center && Math.ceil(settings.items / 2) || settings.items),
9098 i = ((settings.center && n * -1) || 0),
9099 position = (e.property && e.property.value !== undefined ? e.property.value : this._core.current()) + i,
9100 clones = this._core.clones().length,
9101 load = $.proxy(function(i, v) { this.load(v) }, this);
9102 //TODO: Need documentation for this new option
9103 if (settings.lazyLoadEager > 0) {
9104 n += settings.lazyLoadEager;
9105 // If the carousel is looping also preload images that are to the "left"
9106 if (settings.loop) {
9107 position -= settings.lazyLoadEager;
9108 n++;
9109 }
9110 }
9111
9112 while (i++ < n) {
9113 this.load(clones / 2 + this._core.relative(position));
9114 clones && $.each(this._core.clones(this._core.relative(position)), load);
9115 position++;
9116 }
9117 }
9118 }, this)
9119 };
9120
9121 // set the default options
9122 this._core.options = $.extend({}, Lazy.Defaults, this._core.options);
9123
9124 // register event handler
9125 this._core.$element.on(this._handlers);
9126 };
9127
9128 /**
9129 * Default options.
9130 * @public
9131 */
9132 Lazy.Defaults = {
9133 lazyLoad: false,
9134 lazyLoadEager: 0
9135 };
9136
9137 /**
9138 * Loads all resources of an item at the specified position.
9139 * @param {Number} position - The absolute position of the item.
9140 * @protected
9141 */
9142 Lazy.prototype.load = function(position) {
9143 var $item = this._core.$stage.children().eq(position),
9144 $elements = $item && $item.find('.owl-lazy');
9145
9146 if (!$elements || $.inArray($item.get(0), this._loaded) > -1) {
9147 return;
9148 }
9149
9150 $elements.each($.proxy(function(index, element) {
9151 var $element = $(element), image,
9152 url = (window.devicePixelRatio > 1 && $element.attr('data-src-retina')) || $element.attr('data-src') || $element.attr('data-srcset');
9153
9154 this._core.trigger('load', { element: $element, url: url }, 'lazy');
9155
9156 if ($element.is('img')) {
9157 $element.one('load.owl.lazy', $.proxy(function() {
9158 $element.css('opacity', 1);
9159 this._core.trigger('loaded', { element: $element, url: url }, 'lazy');
9160 }, this)).attr('src', url);
9161 } else if ($element.is('source')) {
9162 $element.one('load.owl.lazy', $.proxy(function() {
9163 this._core.trigger('loaded', { element: $element, url: url }, 'lazy');
9164 }, this)).attr('srcset', url);
9165 } else {
9166 image = new Image();
9167 image.onload = $.proxy(function() {
9168 $element.css({
9169 'background-image': 'url("' + url + '")',
9170 'opacity': '1'
9171 });
9172 this._core.trigger('loaded', { element: $element, url: url }, 'lazy');
9173 }, this);
9174 image.src = url;
9175 }
9176 }, this));
9177
9178 this._loaded.push($item.get(0));
9179 };
9180
9181 /**
9182 * Destroys the plugin.
9183 * @public
9184 */
9185 Lazy.prototype.destroy = function() {
9186 var handler, property;
9187
9188 for (handler in this.handlers) {
9189 this._core.$element.off(handler, this.handlers[handler]);
9190 }
9191 for (property in Object.getOwnPropertyNames(this)) {
9192 typeof this[property] != 'function' && (this[property] = null);
9193 }
9194 };
9195
9196 $.fn.owlCarousel.Constructor.Plugins.Lazy = Lazy;
9197
9198 })(window.Zepto || window.jQuery, window, document);
9199
9200/**
9201 * AutoHeight Plugin
9202 * @version 2.3.4
9203 * @author Bartosz Wojciechowski
9204 * @author David Deutsch
9205 * @license The MIT License (MIT)
9206 */
9207 ;(function($, window, document, undefined) {
9208
9209 /**
9210 * Creates the auto height plugin.
9211 * @class The Auto Height Plugin
9212 * @param {Owl} carousel - The Owl Carousel
9213 */
9214 var AutoHeight = function(carousel) {
9215 /**
9216 * Reference to the core.
9217 * @protected
9218 * @type {Owl}
9219 */
9220 this._core = carousel;
9221
9222 this._previousHeight = null;
9223
9224 /**
9225 * All event handlers.
9226 * @protected
9227 * @type {Object}
9228 */
9229 this._handlers = {
9230 'initialized.owl.carousel refreshed.owl.carousel': $.proxy(function(e) {
9231 if (e.namespace && this._core.settings.autoHeight) {
9232 this.update();
9233 }
9234 }, this),
9235 'changed.owl.carousel': $.proxy(function(e) {
9236 if (e.namespace && this._core.settings.autoHeight && e.property.name === 'position'){
9237 this.update();
9238 }
9239 }, this),
9240 'loaded.owl.lazy': $.proxy(function(e) {
9241 if (e.namespace && this._core.settings.autoHeight
9242 && e.element.closest('.' + this._core.settings.itemClass).index() === this._core.current()) {
9243 this.update();
9244 }
9245 }, this)
9246 };
9247
9248 // set default options
9249 this._core.options = $.extend({}, AutoHeight.Defaults, this._core.options);
9250
9251 // register event handlers
9252 this._core.$element.on(this._handlers);
9253 this._intervalId = null;
9254 var refThis = this;
9255
9256 // These changes have been taken from a PR by gavrochelegnou proposed in #1575
9257 // and have been made compatible with the latest jQuery version
9258 $(window).on('load', function() {
9259 if (refThis._core.settings.autoHeight) {
9260 refThis.update();
9261 }
9262 });
9263
9264 // Autoresize the height of the carousel when window is resized
9265 // When carousel has images, the height is dependent on the width
9266 // and should also change on resize
9267 $(window).resize(function() {
9268 if (refThis._core.settings.autoHeight) {
9269 if (refThis._intervalId != null) {
9270 clearTimeout(refThis._intervalId);
9271 }
9272
9273 refThis._intervalId = setTimeout(function() {
9274 refThis.update();
9275 }, 250);
9276 }
9277 });
9278
9279 };
9280
9281 /**
9282 * Default options.
9283 * @public
9284 */
9285 AutoHeight.Defaults = {
9286 autoHeight: false,
9287 autoHeightClass: 'owl-height'
9288 };
9289
9290 /**
9291 * Updates the view.
9292 */
9293 AutoHeight.prototype.update = function() {
9294 var start = this._core._current,
9295 end = start + this._core.settings.items,
9296 lazyLoadEnabled = this._core.settings.lazyLoad,
9297 visible = this._core.$stage.children().toArray().slice(start, end),
9298 heights = [],
9299 maxheight = 0;
9300
9301 $.each(visible, function(index, item) {
9302 heights.push($(item).height());
9303 });
9304
9305 maxheight = Math.max.apply(null, heights);
9306
9307 if (maxheight <= 1 && lazyLoadEnabled && this._previousHeight) {
9308 maxheight = this._previousHeight;
9309 }
9310
9311 this._previousHeight = maxheight;
9312
9313 this._core.$stage.parent()
9314 .height(maxheight)
9315 .addClass(this._core.settings.autoHeightClass);
9316 };
9317
9318 AutoHeight.prototype.destroy = function() {
9319 var handler, property;
9320
9321 for (handler in this._handlers) {
9322 this._core.$element.off(handler, this._handlers[handler]);
9323 }
9324 for (property in Object.getOwnPropertyNames(this)) {
9325 typeof this[property] !== 'function' && (this[property] = null);
9326 }
9327 };
9328
9329 $.fn.owlCarousel.Constructor.Plugins.AutoHeight = AutoHeight;
9330
9331 })(window.Zepto || window.jQuery, window, document);
9332
9333/**
9334 * Video Plugin
9335 * @version 2.3.4
9336 * @author Bartosz Wojciechowski
9337 * @author David Deutsch
9338 * @license The MIT License (MIT)
9339 */
9340 ;(function($, window, document, undefined) {
9341
9342 /**
9343 * Creates the video plugin.
9344 * @class The Video Plugin
9345 * @param {Owl} carousel - The Owl Carousel
9346 */
9347 var Video = function(carousel) {
9348 /**
9349 * Reference to the core.
9350 * @protected
9351 * @type {Owl}
9352 */
9353 this._core = carousel;
9354
9355 /**
9356 * Cache all video URLs.
9357 * @protected
9358 * @type {Object}
9359 */
9360 this._videos = {};
9361
9362 /**
9363 * Current playing item.
9364 * @protected
9365 * @type {jQuery}
9366 */
9367 this._playing = null;
9368
9369 /**
9370 * All event handlers.
9371 * @todo The cloned content removale is too late
9372 * @protected
9373 * @type {Object}
9374 */
9375 this._handlers = {
9376 'initialized.owl.carousel': $.proxy(function(e) {
9377 if (e.namespace) {
9378 this._core.register({ type: 'state', name: 'playing', tags: [ 'interacting' ] });
9379 }
9380 }, this),
9381 'resize.owl.carousel': $.proxy(function(e) {
9382 if (e.namespace && this._core.settings.video && this.isInFullScreen()) {
9383 e.preventDefault();
9384 }
9385 }, this),
9386 'refreshed.owl.carousel': $.proxy(function(e) {
9387 if (e.namespace && this._core.is('resizing')) {
9388 this._core.$stage.find('.cloned .owl-video-frame').remove();
9389 }
9390 }, this),
9391 'changed.owl.carousel': $.proxy(function(e) {
9392 if (e.namespace && e.property.name === 'position' && this._playing) {
9393 this.stop();
9394 }
9395 }, this),
9396 'prepared.owl.carousel': $.proxy(function(e) {
9397 if (!e.namespace) {
9398 return;
9399 }
9400
9401 var $element = $(e.content).find('.owl-video');
9402
9403 if ($element.length) {
9404 $element.css('display', 'none');
9405 this.fetch($element, $(e.content));
9406 }
9407 }, this)
9408 };
9409
9410 // set default options
9411 this._core.options = $.extend({}, Video.Defaults, this._core.options);
9412
9413 // register event handlers
9414 this._core.$element.on(this._handlers);
9415
9416 this._core.$element.on('click.owl.video', '.owl-video-play-icon', $.proxy(function(e) {
9417 this.play(e);
9418 }, this));
9419 };
9420
9421 /**
9422 * Default options.
9423 * @public
9424 */
9425 Video.Defaults = {
9426 video: false,
9427 videoHeight: false,
9428 videoWidth: false
9429 };
9430
9431 /**
9432 * Gets the video ID and the type (YouTube/Vimeo/vzaar only).
9433 * @protected
9434 * @param {jQuery} target - The target containing the video data.
9435 * @param {jQuery} item - The item containing the video.
9436 */
9437 Video.prototype.fetch = function(target, item) {
9438 var type = (function() {
9439 if (target.attr('data-vimeo-id')) {
9440 return 'vimeo';
9441 } else if (target.attr('data-vzaar-id')) {
9442 return 'vzaar'
9443 } else {
9444 return 'youtube';
9445 }
9446 })(),
9447 id = target.attr('data-vimeo-id') || target.attr('data-youtube-id') || target.attr('data-vzaar-id'),
9448 width = target.attr('data-width') || this._core.settings.videoWidth,
9449 height = target.attr('data-height') || this._core.settings.videoHeight,
9450 url = target.attr('href');
9451
9452 if (url) {
9453
9454 /*
9455 Parses the id's out of the following urls (and probably more):
9456 https://www.youtube.com/watch?v=:id
9457 https://youtu.be/:id
9458 https://vimeo.com/:id
9459 https://vimeo.com/channels/:channel/:id
9460 https://vimeo.com/groups/:group/videos/:id
9461 https://app.vzaar.com/videos/:id
9462
9463 Visual example: https://regexper.com/#(http%3A%7Chttps%3A%7C)%5C%2F%5C%2F(player.%7Cwww.%7Capp.)%3F(vimeo%5C.com%7Cyoutu(be%5C.com%7C%5C.be%7Cbe%5C.googleapis%5C.com)%7Cvzaar%5C.com)%5C%2F(video%5C%2F%7Cvideos%5C%2F%7Cembed%5C%2F%7Cchannels%5C%2F.%2B%5C%2F%7Cgroups%5C%2F.%2B%5C%2F%7Cwatch%5C%3Fv%3D%7Cv%5C%2F)%3F(%5BA-Za-z0-9._%25-%5D*)(%5C%26%5CS%2B)%3F
9464 */
9465
9466 id = url.match(/(http:|https:|)\/\/(player.|www.|app.)?(vimeo\.com|youtu(be\.com|\.be|be\.googleapis\.com|be\-nocookie\.com)|vzaar\.com)\/(video\/|videos\/|embed\/|channels\/.+\/|groups\/.+\/|watch\?v=|v\/)?([A-Za-z0-9._%-]*)(\&\S+)?/);
9467
9468 if (id[3].indexOf('youtu') > -1) {
9469 type = 'youtube';
9470 } else if (id[3].indexOf('vimeo') > -1) {
9471 type = 'vimeo';
9472 } else if (id[3].indexOf('vzaar') > -1) {
9473 type = 'vzaar';
9474 } else {
9475 throw new Error('Video URL not supported.');
9476 }
9477 id = id[6];
9478 } else {
9479 throw new Error('Missing video URL.');
9480 }
9481
9482 this._videos[url] = {
9483 type: type,
9484 id: id,
9485 width: width,
9486 height: height
9487 };
9488
9489 item.attr('data-video', url);
9490
9491 this.thumbnail(target, this._videos[url]);
9492 };
9493
9494 /**
9495 * Creates video thumbnail.
9496 * @protected
9497 * @param {jQuery} target - The target containing the video data.
9498 * @param {Object} info - The video info object.
9499 * @see `fetch`
9500 */
9501 Video.prototype.thumbnail = function(target, video) {
9502 var tnLink,
9503 icon,
9504 path,
9505 dimensions = video.width && video.height ? 'width:' + video.width + 'px;height:' + video.height + 'px;' : '',
9506 customTn = target.find('img'),
9507 srcType = 'src',
9508 lazyClass = '',
9509 settings = this._core.settings,
9510 create = function(path) {
9511 icon = '<div class="owl-video-play-icon"></div>';
9512
9513 if (settings.lazyLoad) {
9514 tnLink = $('<div/>',{
9515 "class": 'owl-video-tn ' + lazyClass,
9516 "srcType": path
9517 });
9518 } else {
9519 tnLink = $( '<div/>', {
9520 "class": "owl-video-tn",
9521 "style": 'opacity:1;background-image:url(' + path + ')'
9522 });
9523 }
9524 target.after(tnLink);
9525 target.after(icon);
9526 };
9527
9528 // wrap video content into owl-video-wrapper div
9529 target.wrap( $( '<div/>', {
9530 "class": "owl-video-wrapper",
9531 "style": dimensions
9532 }));
9533
9534 if (this._core.settings.lazyLoad) {
9535 srcType = 'data-src';
9536 lazyClass = 'owl-lazy';
9537 }
9538
9539 // custom thumbnail
9540 if (customTn.length) {
9541 create(customTn.attr(srcType));
9542 customTn.remove();
9543 return false;
9544 }
9545
9546 if (video.type === 'youtube') {
9547 path = "//img.youtube.com/vi/" + video.id + "/hqdefault.jpg";
9548 create(path);
9549 } else if (video.type === 'vimeo') {
9550 $.ajax({
9551 type: 'GET',
9552 url: '//vimeo.com/api/v2/video/' + video.id + '.json',
9553 jsonp: 'callback',
9554 dataType: 'jsonp',
9555 success: function(data) {
9556 path = data[0].thumbnail_large;
9557 create(path);
9558 }
9559 });
9560 } else if (video.type === 'vzaar') {
9561 $.ajax({
9562 type: 'GET',
9563 url: '//vzaar.com/api/videos/' + video.id + '.json',
9564 jsonp: 'callback',
9565 dataType: 'jsonp',
9566 success: function(data) {
9567 path = data.framegrab_url;
9568 create(path);
9569 }
9570 });
9571 }
9572 };
9573
9574 /**
9575 * Stops the current video.
9576 * @public
9577 */
9578 Video.prototype.stop = function() {
9579 this._core.trigger('stop', null, 'video');
9580 this._playing.find('.owl-video-frame').remove();
9581 this._playing.removeClass('owl-video-playing');
9582 this._playing = null;
9583 this._core.leave('playing');
9584 this._core.trigger('stopped', null, 'video');
9585 };
9586
9587 /**
9588 * Starts the current video.
9589 * @public
9590 * @param {Event} event - The event arguments.
9591 */
9592 Video.prototype.play = function(event) {
9593 var target = $(event.target),
9594 item = target.closest('.' + this._core.settings.itemClass),
9595 video = this._videos[item.attr('data-video')],
9596 width = video.width || '100%',
9597 height = video.height || this._core.$stage.height(),
9598 html,
9599 iframe;
9600
9601 if (this._playing) {
9602 return;
9603 }
9604
9605 this._core.enter('playing');
9606 this._core.trigger('play', null, 'video');
9607
9608 item = this._core.items(this._core.relative(item.index()));
9609
9610 this._core.reset(item.index());
9611
9612 html = $( '<iframe frameborder="0" allowfullscreen mozallowfullscreen webkitAllowFullScreen ></iframe>' );
9613 html.attr( 'height', height );
9614 html.attr( 'width', width );
9615 if (video.type === 'youtube') {
9616 html.attr( 'src', '//www.youtube.com/embed/' + video.id + '?autoplay=1&rel=0&v=' + video.id );
9617 } else if (video.type === 'vimeo') {
9618 html.attr( 'src', '//player.vimeo.com/video/' + video.id + '?autoplay=1' );
9619 } else if (video.type === 'vzaar') {
9620 html.attr( 'src', '//view.vzaar.com/' + video.id + '/player?autoplay=true' );
9621 }
9622
9623 iframe = $(html).wrap( '<div class="owl-video-frame" />' ).insertAfter(item.find('.owl-video'));
9624
9625 this._playing = item.addClass('owl-video-playing');
9626 };
9627
9628 /**
9629 * Checks whether an video is currently in full screen mode or not.
9630 * @todo Bad style because looks like a readonly method but changes members.
9631 * @protected
9632 * @returns {Boolean}
9633 */
9634 Video.prototype.isInFullScreen = function() {
9635 var element = document.fullscreenElement || document.mozFullScreenElement ||
9636 document.webkitFullscreenElement;
9637
9638 return element && $(element).parent().hasClass('owl-video-frame');
9639 };
9640
9641 /**
9642 * Destroys the plugin.
9643 */
9644 Video.prototype.destroy = function() {
9645 var handler, property;
9646
9647 this._core.$element.off('click.owl.video');
9648
9649 for (handler in this._handlers) {
9650 this._core.$element.off(handler, this._handlers[handler]);
9651 }
9652 for (property in Object.getOwnPropertyNames(this)) {
9653 typeof this[property] != 'function' && (this[property] = null);
9654 }
9655 };
9656
9657 $.fn.owlCarousel.Constructor.Plugins.Video = Video;
9658
9659 })(window.Zepto || window.jQuery, window, document);
9660
9661/**
9662 * Animate Plugin
9663 * @version 2.3.4
9664 * @author Bartosz Wojciechowski
9665 * @author David Deutsch
9666 * @license The MIT License (MIT)
9667 */
9668 ;(function($, window, document, undefined) {
9669
9670 /**
9671 * Creates the animate plugin.
9672 * @class The Navigation Plugin
9673 * @param {Owl} scope - The Owl Carousel
9674 */
9675 var Animate = function(scope) {
9676 this.core = scope;
9677 this.core.options = $.extend({}, Animate.Defaults, this.core.options);
9678 this.swapping = true;
9679 this.previous = undefined;
9680 this.next = undefined;
9681
9682 this.handlers = {
9683 'change.owl.carousel': $.proxy(function(e) {
9684 if (e.namespace && e.property.name == 'position') {
9685 this.previous = this.core.current();
9686 this.next = e.property.value;
9687 }
9688 }, this),
9689 'drag.owl.carousel dragged.owl.carousel translated.owl.carousel': $.proxy(function(e) {
9690 if (e.namespace) {
9691 this.swapping = e.type == 'translated';
9692 }
9693 }, this),
9694 'translate.owl.carousel': $.proxy(function(e) {
9695 if (e.namespace && this.swapping && (this.core.options.animateOut || this.core.options.animateIn)) {
9696 this.swap();
9697 }
9698 }, this)
9699 };
9700
9701 this.core.$element.on(this.handlers);
9702 };
9703
9704 /**
9705 * Default options.
9706 * @public
9707 */
9708 Animate.Defaults = {
9709 animateOut: false,
9710 animateIn: false
9711 };
9712
9713 /**
9714 * Toggles the animation classes whenever an translations starts.
9715 * @protected
9716 * @returns {Boolean|undefined}
9717 */
9718 Animate.prototype.swap = function() {
9719
9720 if (this.core.settings.items !== 1) {
9721 return;
9722 }
9723
9724 if (!$.support.animation || !$.support.transition) {
9725 return;
9726 }
9727
9728 this.core.speed(0);
9729
9730 var left,
9731 clear = $.proxy(this.clear, this),
9732 previous = this.core.$stage.children().eq(this.previous),
9733 next = this.core.$stage.children().eq(this.next),
9734 incoming = this.core.settings.animateIn,
9735 outgoing = this.core.settings.animateOut;
9736
9737 if (this.core.current() === this.previous) {
9738 return;
9739 }
9740
9741 if (outgoing) {
9742 left = this.core.coordinates(this.previous) - this.core.coordinates(this.next);
9743 previous.one($.support.animation.end, clear)
9744 .css( { 'left': left + 'px' } )
9745 .addClass('animated owl-animated-out')
9746 .addClass(outgoing);
9747 }
9748
9749 if (incoming) {
9750 next.one($.support.animation.end, clear)
9751 .addClass('animated owl-animated-in')
9752 .addClass(incoming);
9753 }
9754 };
9755
9756 Animate.prototype.clear = function(e) {
9757 $(e.target).css( { 'left': '' } )
9758 .removeClass('animated owl-animated-out owl-animated-in')
9759 .removeClass(this.core.settings.animateIn)
9760 .removeClass(this.core.settings.animateOut);
9761 this.core.onTransitionEnd();
9762 };
9763
9764 /**
9765 * Destroys the plugin.
9766 * @public
9767 */
9768 Animate.prototype.destroy = function() {
9769 var handler, property;
9770
9771 for (handler in this.handlers) {
9772 this.core.$element.off(handler, this.handlers[handler]);
9773 }
9774 for (property in Object.getOwnPropertyNames(this)) {
9775 typeof this[property] != 'function' && (this[property] = null);
9776 }
9777 };
9778
9779 $.fn.owlCarousel.Constructor.Plugins.Animate = Animate;
9780
9781 })(window.Zepto || window.jQuery, window, document);
9782
9783/**
9784 * Autoplay Plugin
9785 * @version 2.3.4
9786 * @author Bartosz Wojciechowski
9787 * @author Artus Kolanowski
9788 * @author David Deutsch
9789 * @author Tom De Caluwé
9790 * @license The MIT License (MIT)
9791 */
9792 ;(function($, window, document, undefined) {
9793
9794 /**
9795 * Creates the autoplay plugin.
9796 * @class The Autoplay Plugin
9797 * @param {Owl} scope - The Owl Carousel
9798 */
9799 var Autoplay = function(carousel) {
9800 /**
9801 * Reference to the core.
9802 * @protected
9803 * @type {Owl}
9804 */
9805 this._core = carousel;
9806
9807 /**
9808 * The autoplay timeout id.
9809 * @type {Number}
9810 */
9811 this._call = null;
9812
9813 /**
9814 * Depending on the state of the plugin, this variable contains either
9815 * the start time of the timer or the current timer value if it's
9816 * paused. Since we start in a paused state we initialize the timer
9817 * value.
9818 * @type {Number}
9819 */
9820 this._time = 0;
9821
9822 /**
9823 * Stores the timeout currently used.
9824 * @type {Number}
9825 */
9826 this._timeout = 0;
9827
9828 /**
9829 * Indicates whenever the autoplay is paused.
9830 * @type {Boolean}
9831 */
9832 this._paused = true;
9833
9834 /**
9835 * All event handlers.
9836 * @protected
9837 * @type {Object}
9838 */
9839 this._handlers = {
9840 'changed.owl.carousel': $.proxy(function(e) {
9841 if (e.namespace && e.property.name === 'settings') {
9842 if (this._core.settings.autoplay) {
9843 this.play();
9844 } else {
9845 this.stop();
9846 }
9847 } else if (e.namespace && e.property.name === 'position' && this._paused) {
9848 // Reset the timer. This code is triggered when the position
9849 // of the carousel was changed through user interaction.
9850 this._time = 0;
9851 }
9852 }, this),
9853 'initialized.owl.carousel': $.proxy(function(e) {
9854 if (e.namespace && this._core.settings.autoplay) {
9855 this.play();
9856 }
9857 }, this),
9858 'play.owl.autoplay': $.proxy(function(e, t, s) {
9859 if (e.namespace) {
9860 this.play(t, s);
9861 }
9862 }, this),
9863 'stop.owl.autoplay': $.proxy(function(e) {
9864 if (e.namespace) {
9865 this.stop();
9866 }
9867 }, this),
9868 'mouseover.owl.autoplay': $.proxy(function() {
9869 if (this._core.settings.autoplayHoverPause && this._core.is('rotating')) {
9870 this.pause();
9871 }
9872 }, this),
9873 'mouseleave.owl.autoplay': $.proxy(function() {
9874 if (this._core.settings.autoplayHoverPause && this._core.is('rotating')) {
9875 this.play();
9876 }
9877 }, this),
9878 'touchstart.owl.core': $.proxy(function() {
9879 if (this._core.settings.autoplayHoverPause && this._core.is('rotating')) {
9880 this.pause();
9881 }
9882 }, this),
9883 'touchend.owl.core': $.proxy(function() {
9884 if (this._core.settings.autoplayHoverPause) {
9885 this.play();
9886 }
9887 }, this)
9888 };
9889
9890 // register event handlers
9891 this._core.$element.on(this._handlers);
9892
9893 // set default options
9894 this._core.options = $.extend({}, Autoplay.Defaults, this._core.options);
9895 };
9896
9897 /**
9898 * Default options.
9899 * @public
9900 */
9901 Autoplay.Defaults = {
9902 autoplay: false,
9903 autoplayTimeout: 5000,
9904 autoplayHoverPause: false,
9905 autoplaySpeed: false
9906 };
9907
9908 /**
9909 * Transition to the next slide and set a timeout for the next transition.
9910 * @private
9911 * @param {Number} [speed] - The animation speed for the animations.
9912 */
9913 Autoplay.prototype._next = function(speed) {
9914 this._call = window.setTimeout(
9915 $.proxy(this._next, this, speed),
9916 this._timeout * (Math.round(this.read() / this._timeout) + 1) - this.read()
9917 );
9918
9919 if (this._core.is('interacting') || document.hidden) {
9920 return;
9921 }
9922 this._core.next(speed || this._core.settings.autoplaySpeed);
9923 }
9924
9925 /**
9926 * Reads the current timer value when the timer is playing.
9927 * @public
9928 */
9929 Autoplay.prototype.read = function() {
9930 return new Date().getTime() - this._time;
9931 };
9932
9933 /**
9934 * Starts the autoplay.
9935 * @public
9936 * @param {Number} [timeout] - The interval before the next animation starts.
9937 * @param {Number} [speed] - The animation speed for the animations.
9938 */
9939 Autoplay.prototype.play = function(timeout, speed) {
9940 var elapsed;
9941
9942 if (!this._core.is('rotating')) {
9943 this._core.enter('rotating');
9944 }
9945
9946 timeout = timeout || this._core.settings.autoplayTimeout;
9947
9948 // Calculate the elapsed time since the last transition. If the carousel
9949 // wasn't playing this calculation will yield zero.
9950 elapsed = Math.min(this._time % (this._timeout || timeout), timeout);
9951
9952 if (this._paused) {
9953 // Start the clock.
9954 this._time = this.read();
9955 this._paused = false;
9956 } else {
9957 // Clear the active timeout to allow replacement.
9958 window.clearTimeout(this._call);
9959 }
9960
9961 // Adjust the origin of the timer to match the new timeout value.
9962 this._time += this.read() % timeout - elapsed;
9963
9964 this._timeout = timeout;
9965 this._call = window.setTimeout($.proxy(this._next, this, speed), timeout - elapsed);
9966 };
9967
9968 /**
9969 * Stops the autoplay.
9970 * @public
9971 */
9972 Autoplay.prototype.stop = function() {
9973 if (this._core.is('rotating')) {
9974 // Reset the clock.
9975 this._time = 0;
9976 this._paused = true;
9977
9978 window.clearTimeout(this._call);
9979 this._core.leave('rotating');
9980 }
9981 };
9982
9983 /**
9984 * Pauses the autoplay.
9985 * @public
9986 */
9987 Autoplay.prototype.pause = function() {
9988 if (this._core.is('rotating') && !this._paused) {
9989 // Pause the clock.
9990 this._time = this.read();
9991 this._paused = true;
9992
9993 window.clearTimeout(this._call);
9994 }
9995 };
9996
9997 /**
9998 * Destroys the plugin.
9999 */
10000 Autoplay.prototype.destroy = function() {
10001 var handler, property;
10002
10003 this.stop();
10004
10005 for (handler in this._handlers) {
10006 this._core.$element.off(handler, this._handlers[handler]);
10007 }
10008 for (property in Object.getOwnPropertyNames(this)) {
10009 typeof this[property] != 'function' && (this[property] = null);
10010 }
10011 };
10012
10013 $.fn.owlCarousel.Constructor.Plugins.autoplay = Autoplay;
10014
10015 })(window.Zepto || window.jQuery, window, document);
10016
10017/**
10018 * Navigation Plugin
10019 * @version 2.3.4
10020 * @author Artus Kolanowski
10021 * @author David Deutsch
10022 * @license The MIT License (MIT)
10023 */
10024 ;(function($, window, document, undefined) {
10025 'use strict';
10026
10027 /**
10028 * Creates the navigation plugin.
10029 * @class The Navigation Plugin
10030 * @param {Owl} carousel - The Owl Carousel.
10031 */
10032 var Navigation = function(carousel) {
10033 /**
10034 * Reference to the core.
10035 * @protected
10036 * @type {Owl}
10037 */
10038 this._core = carousel;
10039
10040 /**
10041 * Indicates whether the plugin is initialized or not.
10042 * @protected
10043 * @type {Boolean}
10044 */
10045 this._initialized = false;
10046
10047 /**
10048 * The current paging indexes.
10049 * @protected
10050 * @type {Array}
10051 */
10052 this._pages = [];
10053
10054 /**
10055 * All DOM elements of the user interface.
10056 * @protected
10057 * @type {Object}
10058 */
10059 this._controls = {};
10060
10061 /**
10062 * Markup for an indicator.
10063 * @protected
10064 * @type {Array.<String>}
10065 */
10066 this._templates = [];
10067
10068 /**
10069 * The carousel element.
10070 * @type {jQuery}
10071 */
10072 this.$element = this._core.$element;
10073
10074 /**
10075 * Overridden methods of the carousel.
10076 * @protected
10077 * @type {Object}
10078 */
10079 this._overrides = {
10080 next: this._core.next,
10081 prev: this._core.prev,
10082 to: this._core.to
10083 };
10084
10085 /**
10086 * All event handlers.
10087 * @protected
10088 * @type {Object}
10089 */
10090 this._handlers = {
10091 'prepared.owl.carousel': $.proxy(function(e) {
10092 if (e.namespace && this._core.settings.dotsData) {
10093 this._templates.push('<div class="' + this._core.settings.dotClass + '">' +
10094 $(e.content).find('[data-dot]').addBack('[data-dot]').attr('data-dot') + '</div>');
10095 }
10096 }, this),
10097 'added.owl.carousel': $.proxy(function(e) {
10098 if (e.namespace && this._core.settings.dotsData) {
10099 this._templates.splice(e.position, 0, this._templates.pop());
10100 }
10101 }, this),
10102 'remove.owl.carousel': $.proxy(function(e) {
10103 if (e.namespace && this._core.settings.dotsData) {
10104 this._templates.splice(e.position, 1);
10105 }
10106 }, this),
10107 'changed.owl.carousel': $.proxy(function(e) {
10108 if (e.namespace && e.property.name == 'position') {
10109 this.draw();
10110 }
10111 }, this),
10112 'initialized.owl.carousel': $.proxy(function(e) {
10113 if (e.namespace && !this._initialized) {
10114 this._core.trigger('initialize', null, 'navigation');
10115 this.initialize();
10116 this.update();
10117 this.draw();
10118 this._initialized = true;
10119 this._core.trigger('initialized', null, 'navigation');
10120 }
10121 }, this),
10122 'refreshed.owl.carousel': $.proxy(function(e) {
10123 if (e.namespace && this._initialized) {
10124 this._core.trigger('refresh', null, 'navigation');
10125 this.update();
10126 this.draw();
10127 this._core.trigger('refreshed', null, 'navigation');
10128 }
10129 }, this)
10130 };
10131
10132 // set default options
10133 this._core.options = $.extend({}, Navigation.Defaults, this._core.options);
10134
10135 // register event handlers
10136 this.$element.on(this._handlers);
10137 };
10138
10139 /**
10140 * Default options.
10141 * @public
10142 * @todo Rename `slideBy` to `navBy`
10143 */
10144 Navigation.Defaults = {
10145 nav: false,
10146 navText: [
10147 '<span aria-label="' + 'Previous' + '">‹</span>',
10148 '<span aria-label="' + 'Next' + '">›</span>'
10149 ],
10150 navSpeed: false,
10151 navElement: 'button type="button" role="presentation"',
10152 navContainer: false,
10153 navContainerClass: 'owl-nav',
10154 navClass: [
10155 'owl-prev',
10156 'owl-next'
10157 ],
10158 slideBy: 1,
10159 dotClass: 'owl-dot',
10160 dotsClass: 'owl-dots',
10161 dots: true,
10162 dotsEach: false,
10163 dotsData: false,
10164 dotsSpeed: false,
10165 dotsContainer: false
10166 };
10167
10168 /**
10169 * Initializes the layout of the plugin and extends the carousel.
10170 * @protected
10171 */
10172 Navigation.prototype.initialize = function() {
10173 var override,
10174 settings = this._core.settings;
10175
10176 // create DOM structure for relative navigation
10177 this._controls.$relative = (settings.navContainer ? $(settings.navContainer)
10178 : $('<div>').addClass(settings.navContainerClass).appendTo(this.$element)).addClass('disabled');
10179
10180 this._controls.$previous = $('<' + settings.navElement + '>')
10181 .addClass(settings.navClass[0])
10182 .html(settings.navText[0])
10183 .prependTo(this._controls.$relative)
10184 .on('click', $.proxy(function(e) {
10185 this.prev(settings.navSpeed);
10186 }, this));
10187 this._controls.$next = $('<' + settings.navElement + '>')
10188 .addClass(settings.navClass[1])
10189 .html(settings.navText[1])
10190 .appendTo(this._controls.$relative)
10191 .on('click', $.proxy(function(e) {
10192 this.next(settings.navSpeed);
10193 }, this));
10194
10195 // create DOM structure for absolute navigation
10196 if (!settings.dotsData) {
10197 this._templates = [ $('<button role="button">')
10198 .addClass(settings.dotClass)
10199 .append($('<span>'))
10200 .prop('outerHTML') ];
10201 }
10202
10203 this._controls.$absolute = (settings.dotsContainer ? $(settings.dotsContainer)
10204 : $('<div>').addClass(settings.dotsClass).appendTo(this.$element)).addClass('disabled');
10205
10206 this._controls.$absolute.on('click', 'button', $.proxy(function(e) {
10207 var index = $(e.target).parent().is(this._controls.$absolute)
10208 ? $(e.target).index() : $(e.target).parent().index();
10209
10210 e.preventDefault();
10211
10212 this.to(index, settings.dotsSpeed);
10213 }, this));
10214
10215 /*$el.on('focusin', function() {
10216 $(document).off(".carousel");
10217
10218 $(document).on('keydown.carousel', function(e) {
10219 if(e.keyCode == 37) {
10220 $el.trigger('prev.owl')
10221 }
10222 if(e.keyCode == 39) {
10223 $el.trigger('next.owl')
10224 }
10225 });
10226 });*/
10227
10228 // override public methods of the carousel
10229 for (override in this._overrides) {
10230 this._core[override] = $.proxy(this[override], this);
10231 }
10232 };
10233
10234 /**
10235 * Destroys the plugin.
10236 * @protected
10237 */
10238 Navigation.prototype.destroy = function() {
10239 var handler, control, property, override, settings;
10240 settings = this._core.settings;
10241
10242 for (handler in this._handlers) {
10243 this.$element.off(handler, this._handlers[handler]);
10244 }
10245 for (control in this._controls) {
10246 if (control === '$relative' && settings.navContainer) {
10247 this._controls[control].html('');
10248 } else {
10249 this._controls[control].remove();
10250 }
10251 }
10252 for (override in this.overides) {
10253 this._core[override] = this._overrides[override];
10254 }
10255 for (property in Object.getOwnPropertyNames(this)) {
10256 typeof this[property] != 'function' && (this[property] = null);
10257 }
10258 };
10259
10260 /**
10261 * Updates the internal state.
10262 * @protected
10263 */
10264 Navigation.prototype.update = function() {
10265 var i, j, k,
10266 lower = this._core.clones().length / 2,
10267 upper = lower + this._core.items().length,
10268 maximum = this._core.maximum(true),
10269 settings = this._core.settings,
10270 size = settings.center || settings.autoWidth || settings.dotsData
10271 ? 1 : settings.dotsEach || settings.items;
10272
10273 if (settings.slideBy !== 'page') {
10274 settings.slideBy = Math.min(settings.slideBy, settings.items);
10275 }
10276
10277 if (settings.dots || settings.slideBy == 'page') {
10278 this._pages = [];
10279
10280 for (i = lower, j = 0, k = 0; i < upper; i++) {
10281 if (j >= size || j === 0) {
10282 this._pages.push({
10283 start: Math.min(maximum, i - lower),
10284 end: i - lower + size - 1
10285 });
10286 if (Math.min(maximum, i - lower) === maximum) {
10287 break;
10288 }
10289 j = 0, ++k;
10290 }
10291 j += this._core.mergers(this._core.relative(i));
10292 }
10293 }
10294 };
10295
10296 /**
10297 * Draws the user interface.
10298 * @todo The option `dotsData` wont work.
10299 * @protected
10300 */
10301 Navigation.prototype.draw = function() {
10302 var difference,
10303 settings = this._core.settings,
10304 disabled = this._core.items().length <= settings.items,
10305 index = this._core.relative(this._core.current()),
10306 loop = settings.loop || settings.rewind;
10307
10308 this._controls.$relative.toggleClass('disabled', !settings.nav || disabled);
10309
10310 if (settings.nav) {
10311 this._controls.$previous.toggleClass('disabled', !loop && index <= this._core.minimum(true));
10312 this._controls.$next.toggleClass('disabled', !loop && index >= this._core.maximum(true));
10313 }
10314
10315 this._controls.$absolute.toggleClass('disabled', !settings.dots || disabled);
10316
10317 if (settings.dots) {
10318 difference = this._pages.length - this._controls.$absolute.children().length;
10319
10320 if (settings.dotsData && difference !== 0) {
10321 this._controls.$absolute.html(this._templates.join(''));
10322 } else if (difference > 0) {
10323 this._controls.$absolute.append(new Array(difference + 1).join(this._templates[0]));
10324 } else if (difference < 0) {
10325 this._controls.$absolute.children().slice(difference).remove();
10326 }
10327
10328 this._controls.$absolute.find('.active').removeClass('active');
10329 this._controls.$absolute.children().eq($.inArray(this.current(), this._pages)).addClass('active');
10330 }
10331 };
10332
10333 /**
10334 * Extends event data.
10335 * @protected
10336 * @param {Event} event - The event object which gets thrown.
10337 */
10338 Navigation.prototype.onTrigger = function(event) {
10339 var settings = this._core.settings;
10340
10341 event.page = {
10342 index: $.inArray(this.current(), this._pages),
10343 count: this._pages.length,
10344 size: settings && (settings.center || settings.autoWidth || settings.dotsData
10345 ? 1 : settings.dotsEach || settings.items)
10346 };
10347 };
10348
10349 /**
10350 * Gets the current page position of the carousel.
10351 * @protected
10352 * @returns {Number}
10353 */
10354 Navigation.prototype.current = function() {
10355 var current = this._core.relative(this._core.current());
10356 return $.grep(this._pages, $.proxy(function(page, index) {
10357 return page.start <= current && page.end >= current;
10358 }, this)).pop();
10359 };
10360
10361 /**
10362 * Gets the current succesor/predecessor position.
10363 * @protected
10364 * @returns {Number}
10365 */
10366 Navigation.prototype.getPosition = function(successor) {
10367 var position, length,
10368 settings = this._core.settings;
10369
10370 if (settings.slideBy == 'page') {
10371 position = $.inArray(this.current(), this._pages);
10372 length = this._pages.length;
10373 successor ? ++position : --position;
10374 position = this._pages[((position % length) + length) % length].start;
10375 } else {
10376 position = this._core.relative(this._core.current());
10377 length = this._core.items().length;
10378 successor ? position += settings.slideBy : position -= settings.slideBy;
10379 }
10380
10381 return position;
10382 };
10383
10384 /**
10385 * Slides to the next item or page.
10386 * @public
10387 * @param {Number} [speed=false] - The time in milliseconds for the transition.
10388 */
10389 Navigation.prototype.next = function(speed) {
10390 $.proxy(this._overrides.to, this._core)(this.getPosition(true), speed);
10391 };
10392
10393 /**
10394 * Slides to the previous item or page.
10395 * @public
10396 * @param {Number} [speed=false] - The time in milliseconds for the transition.
10397 */
10398 Navigation.prototype.prev = function(speed) {
10399 $.proxy(this._overrides.to, this._core)(this.getPosition(false), speed);
10400 };
10401
10402 /**
10403 * Slides to the specified item or page.
10404 * @public
10405 * @param {Number} position - The position of the item or page.
10406 * @param {Number} [speed] - The time in milliseconds for the transition.
10407 * @param {Boolean} [standard=false] - Whether to use the standard behaviour or not.
10408 */
10409 Navigation.prototype.to = function(position, speed, standard) {
10410 var length;
10411
10412 if (!standard && this._pages.length) {
10413 length = this._pages.length;
10414 $.proxy(this._overrides.to, this._core)(this._pages[((position % length) + length) % length].start, speed);
10415 } else {
10416 $.proxy(this._overrides.to, this._core)(position, speed);
10417 }
10418 };
10419
10420 $.fn.owlCarousel.Constructor.Plugins.Navigation = Navigation;
10421
10422 })(window.Zepto || window.jQuery, window, document);
10423
10424/**
10425 * Hash Plugin
10426 * @version 2.3.4
10427 * @author Artus Kolanowski
10428 * @author David Deutsch
10429 * @license The MIT License (MIT)
10430 */
10431 ;(function($, window, document, undefined) {
10432 'use strict';
10433
10434 /**
10435 * Creates the hash plugin.
10436 * @class The Hash Plugin
10437 * @param {Owl} carousel - The Owl Carousel
10438 */
10439 var Hash = function(carousel) {
10440 /**
10441 * Reference to the core.
10442 * @protected
10443 * @type {Owl}
10444 */
10445 this._core = carousel;
10446
10447 /**
10448 * Hash index for the items.
10449 * @protected
10450 * @type {Object}
10451 */
10452 this._hashes = {};
10453
10454 /**
10455 * The carousel element.
10456 * @type {jQuery}
10457 */
10458 this.$element = this._core.$element;
10459
10460 /**
10461 * All event handlers.
10462 * @protected
10463 * @type {Object}
10464 */
10465 this._handlers = {
10466 'initialized.owl.carousel': $.proxy(function(e) {
10467 if (e.namespace && this._core.settings.startPosition === 'URLHash') {
10468 $(window).trigger('hashchange.owl.navigation');
10469 }
10470 }, this),
10471 'prepared.owl.carousel': $.proxy(function(e) {
10472 if (e.namespace) {
10473 var hash = $(e.content).find('[data-hash]').addBack('[data-hash]').attr('data-hash');
10474
10475 if (!hash) {
10476 return;
10477 }
10478
10479 this._hashes[hash] = e.content;
10480 }
10481 }, this),
10482 'changed.owl.carousel': $.proxy(function(e) {
10483 if (e.namespace && e.property.name === 'position') {
10484 var current = this._core.items(this._core.relative(this._core.current())),
10485 hash = $.map(this._hashes, function(item, hash) {
10486 return item === current ? hash : null;
10487 }).join();
10488
10489 if (!hash || window.location.hash.slice(1) === hash) {
10490 return;
10491 }
10492
10493 window.location.hash = hash;
10494 }
10495 }, this)
10496 };
10497
10498 // set default options
10499 this._core.options = $.extend({}, Hash.Defaults, this._core.options);
10500
10501 // register the event handlers
10502 this.$element.on(this._handlers);
10503
10504 // register event listener for hash navigation
10505 $(window).on('hashchange.owl.navigation', $.proxy(function(e) {
10506 var hash = window.location.hash.substring(1),
10507 items = this._core.$stage.children(),
10508 position = this._hashes[hash] && items.index(this._hashes[hash]);
10509
10510 if (position === undefined || position === this._core.current()) {
10511 return;
10512 }
10513
10514 this._core.to(this._core.relative(position), false, true);
10515 }, this));
10516 };
10517
10518 /**
10519 * Default options.
10520 * @public
10521 */
10522 Hash.Defaults = {
10523 URLhashListener: false
10524 };
10525
10526 /**
10527 * Destroys the plugin.
10528 * @public
10529 */
10530 Hash.prototype.destroy = function() {
10531 var handler, property;
10532
10533 $(window).off('hashchange.owl.navigation');
10534
10535 for (handler in this._handlers) {
10536 this._core.$element.off(handler, this._handlers[handler]);
10537 }
10538 for (property in Object.getOwnPropertyNames(this)) {
10539 typeof this[property] != 'function' && (this[property] = null);
10540 }
10541 };
10542
10543 $.fn.owlCarousel.Constructor.Plugins.Hash = Hash;
10544
10545 })(window.Zepto || window.jQuery, window, document);
10546
10547/**
10548 * Support Plugin
10549 *
10550 * @version 2.3.4
10551 * @author Vivid Planet Software GmbH
10552 * @author Artus Kolanowski
10553 * @author David Deutsch
10554 * @license The MIT License (MIT)
10555 */
10556 ;(function($, window, document, undefined) {
10557
10558 var style = $('<support>').get(0).style,
10559 prefixes = 'Webkit Moz O ms'.split(' '),
10560 events = {
10561 transition: {
10562 end: {
10563 WebkitTransition: 'webkitTransitionEnd',
10564 MozTransition: 'transitionend',
10565 OTransition: 'oTransitionEnd',
10566 transition: 'transitionend'
10567 }
10568 },
10569 animation: {
10570 end: {
10571 WebkitAnimation: 'webkitAnimationEnd',
10572 MozAnimation: 'animationend',
10573 OAnimation: 'oAnimationEnd',
10574 animation: 'animationend'
10575 }
10576 }
10577 },
10578 tests = {
10579 csstransforms: function() {
10580 return !!test('transform');
10581 },
10582 csstransforms3d: function() {
10583 return !!test('perspective');
10584 },
10585 csstransitions: function() {
10586 return !!test('transition');
10587 },
10588 cssanimations: function() {
10589 return !!test('animation');
10590 }
10591 };
10592
10593 function test(property, prefixed) {
10594 var result = false,
10595 upper = property.charAt(0).toUpperCase() + property.slice(1);
10596
10597 $.each((property + ' ' + prefixes.join(upper + ' ') + upper).split(' '), function(i, property) {
10598 if (style[property] !== undefined) {
10599 result = prefixed ? property : true;
10600 return false;
10601 }
10602 });
10603
10604 return result;
10605 }
10606
10607 function prefixed(property) {
10608 return test(property, true);
10609 }
10610
10611 if (tests.csstransitions()) {
10612 /* jshint -W053 */
10613 $.support.transition = new String(prefixed('transition'))
10614 $.support.transition.end = events.transition.end[ $.support.transition ];
10615 }
10616
10617 if (tests.cssanimations()) {
10618 /* jshint -W053 */
10619 $.support.animation = new String(prefixed('animation'))
10620 $.support.animation.end = events.animation.end[ $.support.animation ];
10621 }
10622
10623 if (tests.csstransforms()) {
10624 /* jshint -W053 */
10625 $.support.transform = new String(prefixed('transform'));
10626 $.support.transform3d = tests.csstransforms3d();
10627 }
10628
10629 })(window.Zepto || window.jQuery, window, document);
10630
10631 $(document).ready(function() {
10632 $('.bestseller .owl-carousel').owlCarousel({
10633 loop: true,
10634 lazyLoad: true,
10635 margin: 10,
10636 responsiveClass: true,
10637 autoplay: true,
10638 responsive: {
10639 200: {
10640 items: 2,
10641 nav: false
10642 },
10643 600: {
10644 items: 3,
10645 nav: true,
10646 loop: true
10647 },
10648 768: {
10649 items: 4,
10650 nav: false,
10651 loop: true,
10652 margin: 20
10653 },
10654 1200: {
10655 items: 5,
10656 nav: false,
10657 loop: true,
10658 margin: 20
10659 },
10660 1380: {
10661 items: 6,
10662 nav: false,
10663 dots: true,
10664 loop: true,
10665 margin: 20
10666 }
10667 }
10668 });
10669 $('.product_detail_images .owl-carousel').owlCarousel({
10670 loop: true,
10671 lazyLoad: true,
10672 margin: 10,
10673 responsiveClass: true,
10674 autoplay: true,
10675 navText: ['<i class="fa fa-angle-left" aria-hidden="true"></i>',
10676 '<i class="fa fa-angle-right" aria-hidden="true"></i>'
10677 ],
10678 responsive: {
10679 200: {
10680 items: 1,
10681 nav: true,
10682 dots: true,
10683 nav: true
10684 },
10685 600: {
10686 items: 1,
10687 nav: true,
10688 dots: true,
10689 loop: true
10690 },
10691 768: {
10692 items: 1,
10693 nav: true,
10694 dots: true,
10695 loop: true,
10696 margin: 10
10697 },
10698 1200: {
10699 items: 1,
10700 nav: true,
10701 dots: true,
10702 loop: true,
10703 margin: 10
10704 },
10705 1380: {
10706 items: 1,
10707 nav: true,
10708 dots: true,
10709 loop: true,
10710 margin: 10
10711 }
10712 }
10713 });
10714 $('.main-banner .owl-carousel').owlCarousel({
10715 //navigation : true, Show next and prev buttons
10716 slideSpeed: 300,
10717 lazyLoad: true,
10718 paginationSpeed: 400,
10719 autoPlay: false,
10720 pagination: true,
10721 singleItem: true,
10722 navText: ["<i class='fa fa-chevron-left'></i>", "<i class='fa fa-chevron-right'></i>"],
10723 navigation: true
10724 });
10725 });
10726
10727
10728 $(function() {
10729 $('.owl-carousel').owlCarousel({
10730 loop: true,
10731 lazyLoad: true,
10732 margin: 10,
10733 dots: true,
10734 responsive: {
10735 0: {
10736 items: 1
10737 },
10738 600: {
10739 items: 1
10740 },
10741 1000: {
10742 items: 1
10743 }
10744 }
10745 })
10746 });
10747 (function(){
10748 // Responsive Tabbed Navigation - by CodyHouse.co
10749 function TabbedNavigation( element ) {
10750 this.element = element;
10751 this.navigation = this.element.getElementsByClassName("cd-tabs__navigation")[0];
10752 this.navigationElements = this.navigation.getElementsByClassName("cd-tabs__list")[0];
10753 this.content = this.element.getElementsByClassName("cd-tabs__panels")[0];
10754 this.activeTab;
10755 this.activeContent;
10756 this.init();
10757 };
10758
10759 TabbedNavigation.prototype.init = function() {
10760 var self = this;
10761 //listen for the click on the tabs navigation
10762 this.navigation.addEventListener("click", function(event){
10763 event.preventDefault();
10764 var selectedItem = event.target.closest('.cd-tabs__item');
10765 if(selectedItem && !Util.hasClass(selectedItem, "cd-tabs__item--selected")) {
10766 self.activeTab = selectedItem;
10767 self.activeContent = document.getElementById(self.activeTab.getAttribute("href").replace('#', ''));
10768 self.updateContent();
10769 }
10770 });
10771
10772 //listen for the scroll in the tabs navigation
10773 this.navigationElements.addEventListener('scroll', function(event){
10774 self.toggleNavShadow();
10775 });
10776};
10777
10778TabbedNavigation.prototype.updateContent = function() {
10779 var self = this;
10780 var actualHeight = this.content.offsetHeight;
10781 //update navigation classes
10782 Util.removeClass(this.navigation.querySelectorAll(".cd-tabs__item--selected")[0], "cd-tabs__item--selected");
10783 Util.addClass(this.activeTab, "cd-tabs__item--selected");
10784 //update content classes
10785 Util.removeClass(this.content.querySelectorAll(".cd-tabs__panel--selected")[0], "cd-tabs__panel--selected");
10786 Util.addClass(this.activeContent, "cd-tabs__panel--selected");
10787 //set new height for the content wrapper
10788 if(window.requestAnimationFrame && window.getComputedStyle(this.element).getPropertyValue('display') == 'block') {
10789 Util.setHeight(actualHeight, this.activeContent.offsetHeight, this.content, 200, function(){
10790 self.content.removeAttribute('style');
10791 });
10792 }
10793};
10794
10795TabbedNavigation.prototype.toggleNavShadow = function() {
10796 //show/hide tabs navigation gradient layer
10797 this.content.removeAttribute("style");
10798 var navItems = this.navigationElements.getElementsByClassName("cd-tabs__item"),
10799 navigationRight = Math.floor(this.navigationElements.getBoundingClientRect().right),
10800 lastItemRight = Math.ceil(navItems[navItems.length - 1].getBoundingClientRect().right);
10801 ( navigationRight >= lastItemRight )
10802 ? Util.addClass(this.element, "cd-tabs--scroll-ended")
10803 : Util.removeClass(this.element, "cd-tabs--scroll-ended");
10804};
10805
10806var tabs = document.getElementsByClassName("js-cd-tabs"),
10807tabsArray = [],
10808resizing = false;
10809if( tabs.length > 0 ) {
10810 for( var i = 0; i < tabs.length; i++) {
10811 (function(i){
10812 tabsArray.push(new TabbedNavigation(tabs[i]));
10813 })(i);
10814 }
10815
10816 window.addEventListener("resize", function(event) {
10817 if( !resizing ) {
10818 resizing = true;
10819 (!window.requestAnimationFrame) ? setTimeout(checkTabs, 250) : window.requestAnimationFrame(checkTabs);
10820 }
10821 });
10822}
10823
10824function checkTabs() {
10825 tabsArray.forEach(function(tab){
10826 tab.toggleNavShadow();
10827 });
10828 resizing = false;
10829};
10830})();