Use classmap autoloader for stapibas classes
[stapibas.git] / www / js / jquery-0.6.1.smallipop.js
1 /*!
2 Smallipop (06/21/2013)
3 Copyright (c) 2011-2013 Small Improvements (http://www.small-improvements.com)
4
5 Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) license.
6
7 @author Sebastian Helzle (sebastian@helzle.net)
8 */
9
10 (function(factory) {
11   if (typeof define === 'function' && define.amd) {
12     return define(['jquery'], factory);
13   } else {
14     return factory(jQuery);
15   }
16 })(function($) {
17   var $document, $overlay, $window, classAlignLeft, classAlignRight, classBase, classBottom, classContent, classHint, classInitialized, classInstance, classLeft, classRight, classTheme, classTour, classTourClose, classTourCloseIcon, classTourContent, classTourFooter, classTourNext, classTourOverlay, classTourPrev, classTourProgress, cssAnimationsEnabled, currentTour, dataBeingShown, dataIsTour, dataPopupHovered, dataPosition, dataShown, dataTimerHide, dataTimerShow, dataTriggerHovered, dataXDistance, dataYDistance, dataZIndex, destroy, eventBlur, eventClick, eventFocus, eventKeyUp, eventMouseOut, eventMouseOver, eventResize, eventScroll, eventTouchEnd, fadeInPopup, fadeInPopupFinished, filterAlignmentClass, filterBaseClass, filterClass, forceRefreshPosition, getInstance, getOverlay, getTrigger, hideSmallipop, hideTourOverlay, instances, isElementFixed, killTimers, lastId, lastScrollCheck, nextInstanceId, onWindowKeyUp, onWindowScroll, popupTemplate, queueRefreshPosition, reAlignmentClass, reBaseClass, refreshPosition, refreshQueueTimer, resetTourZIndices, runTour, scrollTimer, setContent, showPopup, showSmallipop, showWhenVisible, sip, touchEnabled, tourClose, tourNext, tourPrev, tourShow, tours, triggerMouseout, triggerMouseover;
18   classBase = 'smallipop';
19   classHint = classBase + '-hint';
20   classInstance = classBase + '-instance';
21   classContent = classBase + '-content';
22   classLeft = classBase + '-left';
23   classRight = classBase + '-right';
24   classBottom = classBase + '-bottom';
25   classAlignLeft = classBase + '-align-left';
26   classAlignRight = classBase + '-align-right';
27   classInitialized = classBase + '-initialized';
28   classTheme = classBase + '-theme-';
29   classTour = classBase + '-tour';
30   classTourContent = classTour + '-content';
31   classTourOverlay = classTour + '-overlay';
32   classTourFooter = classTour + '-footer';
33   classTourCloseIcon = classTour + '-close-icon';
34   classTourProgress = classTour + '-progress';
35   classTourClose = classTour + '-close';
36   classTourPrev = classTour + '-prev';
37   classTourNext = classTour + '-next';
38   eventFocus = 'focus.' + classBase;
39   eventClick = 'click.' + classBase;
40   eventBlur = 'blur.' + classBase;
41   eventMouseOut = 'mouseout.' + classBase;
42   eventMouseOver = 'mouseover.' + classBase;
43   eventTouchEnd = 'touchend.' + classBase;
44   eventResize = 'resize.' + classBase;
45   eventScroll = 'scroll.' + classBase;
46   eventKeyUp = 'keyup.' + classBase;
47   dataZIndex = classBase + 'OriginalZIndex';
48   dataBeingShown = classBase + 'BeingShown';
49   dataTimerHide = classBase + 'HideDelayTimer';
50   dataTimerShow = classBase + 'ShowDelayTimer';
51   dataTriggerHovered = classBase + 'TriggerHovered';
52   dataPopupHovered = classBase + 'PopupHovered';
53   dataShown = classBase + 'Shown';
54   dataPosition = classBase + 'Position';
55   dataXDistance = classBase + 'XDistance';
56   dataYDistance = classBase + 'YDistance';
57   dataIsTour = classBase + 'IsTour';
58   reAlignmentClass = new RegExp(classBase + '-(align|bottom)\w*', "g");
59   reBaseClass = new RegExp(classBase + '\w+', "g");
60   $document = $(document);
61   $window = $(window);
62   $overlay = null;
63   instances = {};
64   tours = {};
65   currentTour = null;
66   lastId = 1;
67   nextInstanceId = 1;
68   scrollTimer = null;
69   lastScrollCheck = 0;
70   refreshQueueTimer = null;
71   popupTemplate = "<div class='" + classInstance + "'><div class='" + classContent + "'/></div>";
72   $.smallipop = sip = {
73     version: '0.6.1',
74     defaults: {
75       autoscrollPadding: 200,
76       contentAnimationSpeed: 150,
77       cssAnimations: {
78         enabled: false,
79         show: 'animated fadeIn',
80         hide: 'animated fadeOut'
81       },
82       funcEase: 'easeInOutQuad',
83       handleInputs: true,
84       hideDelay: 500,
85       hideTrigger: false,
86       hideOnPopupClick: true,
87       hideOnTriggerClick: true,
88       infoClass: classHint,
89       invertAnimation: false,
90       popupId: '',
91       popupOffset: 31,
92       popupYOffset: 0,
93       popupDistance: 20,
94       popupDelay: 100,
95       popupAnimationSpeed: 200,
96       preferredPosition: 'top',
97       referencedContent: null,
98       theme: 'default',
99       touchSupport: true,
100       tourHighlight: false,
101       tourHighlightColor: '#222',
102       tourHighlightFadeDuration: 200,
103       tourHighlightOpacity: .5,
104       tourHighlightZIndex: 9997,
105       tourNavigationEnabled: true,
106       triggerAnimationSpeed: 150,
107       triggerOnClick: false,
108       onAfterHide: null,
109       onAfterShow: null,
110       onBeforeHide: null,
111       onBeforeShow: null,
112       onTourClose: null,
113       onTourNext: null,
114       onTourPrev: null,
115       windowPadding: 30,
116       labels: {
117         prev: 'Prev',
118         next: 'Next',
119         close: 'Close',
120         of: 'of'
121       }
122     }
123   };
124   if (!$.easing.easeInOutQuad) {
125     $.easing.easeInOutQuad = function(x, t, b, c, d) {
126       if ((t /= d / 2) < 1) {
127         return c / 2 * t * t + b;
128       } else {
129         return -c / 2 * ((--t) * (t - 2) - 1) + b;
130       }
131     };
132   }
133   resetTourZIndices = function() {
134     var step, steps, tour, tourTrigger, _results;
135     _results = [];
136     for (tour in tours) {
137       steps = tours[tour];
138       _results.push((function() {
139         var _i, _len, _results1;
140         _results1 = [];
141         for (_i = 0, _len = steps.length; _i < _len; _i++) {
142           step = steps[_i];
143           tourTrigger = step.trigger;
144           if (tourTrigger.data(dataZIndex)) {
145             _results1.push(tourTrigger.css('zIndex', tourTrigger.data(dataZIndex)));
146           } else {
147             _results1.push(void 0);
148           }
149         }
150         return _results1;
151       })());
152     }
153     return _results;
154   };
155   touchEnabled = typeof Modernizr !== "undefined" && Modernizr !== null ? Modernizr.touch : void 0;
156   cssAnimationsEnabled = typeof Modernizr !== "undefined" && Modernizr !== null ? Modernizr.cssanimations : void 0;
157   getTrigger = function(id) {
158     return $("." + (classBase + id));
159   };
160   getOverlay = function() {
161     if (!$overlay) {
162       $overlay = $("<div id='" + classTourOverlay + "'/>").appendTo($('body')).fadeOut(0);
163     }
164     return $overlay;
165   };
166   hideTourOverlay = function(options) {
167     getOverlay().fadeOut(options.tourHighlightFadeDuration);
168     return resetTourZIndices();
169   };
170   hideSmallipop = function(e) {
171     var direction, ignorePopupClick, ignoreTriggerClick, popup, popupData, popupId, shownId, target, trigger, triggerData, triggerIsTarget, triggerOptions, xDistance, yDistance, _base, _ref, _ref1, _results;
172     clearTimeout(scrollTimer);
173     target = (e != null ? e.target : void 0) ? $(e.target) : e;
174     _results = [];
175     for (popupId in instances) {
176       popup = instances[popupId];
177       popupData = popup.data();
178       if (!(shownId = popupData[dataShown])) {
179         continue;
180       }
181       trigger = getTrigger(shownId);
182       triggerIsTarget = trigger.is(target);
183       triggerData = trigger.data(classBase);
184       triggerOptions = triggerData.options || sip.defaults;
185       if ((popupData[dataIsTour] || triggerData.isFormElement) && !popup.is(target) && !(triggerIsTarget && popup.is(triggerOptions.popupInstance))) {
186         continue;
187       }
188       if (popupData[dataIsTour]) {
189         currentTour = null;
190         if ((_ref = trigger.data(classBase)) != null) {
191           if (typeof (_base = _ref.options).onTourClose === "function") {
192             _base.onTourClose();
193           }
194         }
195         hideTourOverlay(triggerOptions);
196       }
197       ignoreTriggerClick = !triggerOptions.hideOnTriggerClick && triggerIsTarget;
198       ignorePopupClick = !triggerOptions.hideOnPopupClick && popup.find(target).length;
199       if (target && trigger.length && ((_ref1 = e != null ? e.type : void 0) === 'click' || _ref1 === 'touchend') && (ignoreTriggerClick || ignorePopupClick)) {
200         continue;
201       }
202       if (shownId && triggerOptions.hideTrigger) {
203         trigger.stop(true).fadeTo(triggerOptions.triggerAnimationSpeed, 1);
204       }
205       popup.data(dataTimerHide, null).data(dataBeingShown, false);
206       if (triggerOptions.cssAnimations.enabled) {
207         popup.removeClass(triggerOptions.cssAnimations.show).addClass(triggerOptions.cssAnimations.hide).data(dataShown, '');
208         if (triggerOptions.onAfterHide) {
209           _results.push(window.setTimeout(triggerOptions.onAfterHide, triggerOptions.popupAnimationSpeed));
210         } else {
211           _results.push(void 0);
212         }
213       } else {
214         direction = triggerOptions.invertAnimation ? -1 : 1;
215         xDistance = popupData[dataXDistance] * direction;
216         yDistance = popupData[dataYDistance] * direction;
217         _results.push(popup.stop(true).animate({
218           top: "-=" + yDistance,
219           left: "+=" + xDistance,
220           opacity: 0
221         }, triggerOptions.popupAnimationSpeed, triggerOptions.funcEase, function() {
222           var self;
223           self = $(this);
224           if (!self.data(dataBeingShown)) {
225             self.css('display', 'none').data(dataShown, '');
226           }
227           return typeof triggerOptions.onAfterHide === "function" ? triggerOptions.onAfterHide() : void 0;
228         }));
229       }
230     }
231     return _results;
232   };
233   showSmallipop = function(e) {
234     var triggerData, _ref;
235     triggerData = $(this).data(classBase);
236     if (!triggerData) {
237       return;
238     }
239     if (triggerData.popupInstance.data(dataShown) !== triggerData.id && ((_ref = !triggerData.type) === 'checkbox' || _ref === 'radio')) {
240       if (e != null) {
241         e.preventDefault();
242       }
243     }
244     return triggerMouseover.call(this);
245   };
246   killTimers = function(popup) {
247     clearTimeout(popup.data(dataTimerHide));
248     return clearTimeout(popup.data(dataTimerShow));
249   };
250   queueRefreshPosition = function(delay) {
251     if (delay == null) {
252       delay = 50;
253     }
254     clearTimeout(refreshQueueTimer);
255     return refreshQueueTimer = setTimeout(refreshPosition, delay);
256   };
257   filterClass = function(classStr, re) {
258     if (classStr) {
259       return (classStr.match(re) || []).join(' ');
260     }
261   };
262   filterAlignmentClass = function(idx, classStr) {
263     return filterClass(classStr, reAlignmentClass);
264   };
265   filterBaseClass = function(idx, classStr) {
266     return filterClass(classStr, reBaseClass);
267   };
268   refreshPosition = function(resetTheme) {
269     var isFixed, offset, opacity, options, popup, popupCenter, popupData, popupDistanceBottom, popupDistanceLeft, popupDistanceRight, popupDistanceTop, popupH, popupId, popupOffsetLeft, popupOffsetTop, popupW, popupY, preferredPosition, selfHeight, selfWidth, selfY, shownId, themes, trigger, triggerData, win, winHeight, winScrollLeft, winScrollTop, winWidth, windowPadding, xDistance, xOffset, xOverflow, yDistance, yOffset, yOverflow, _results;
270     if (resetTheme == null) {
271       resetTheme = true;
272     }
273     _results = [];
274     for (popupId in instances) {
275       popup = instances[popupId];
276       popupData = popup.data();
277       shownId = popupData[dataShown];
278       if (!shownId) {
279         continue;
280       }
281       trigger = getTrigger(shownId);
282       triggerData = trigger.data(classBase);
283       options = triggerData.options;
284       popup.removeClass(filterAlignmentClass);
285       if (resetTheme) {
286         themes = classTheme + options.theme.split(' ').join(" " + classTheme);
287         popup.attr('class', "" + classInstance + " " + themes);
288       }
289       win = $(window);
290       xDistance = yDistance = options.popupDistance;
291       xOffset = options.popupOffset;
292       yOffset = options.popupYOffset;
293       isFixed = popup.data(dataPosition) === 'fixed';
294       popupH = popup.outerHeight();
295       popupW = popup.outerWidth();
296       popupCenter = popupW / 2;
297       winWidth = win.width();
298       winHeight = win.height();
299       winScrollTop = win.scrollTop();
300       winScrollLeft = win.scrollLeft();
301       windowPadding = options.windowPadding;
302       offset = trigger.offset();
303       selfWidth = trigger.outerWidth();
304       selfHeight = trigger.outerHeight();
305       selfY = offset.top - winScrollTop;
306       popupOffsetLeft = offset.left + selfWidth / 2;
307       popupOffsetTop = offset.top - popupH + yOffset;
308       popupY = popupH + options.popupDistance - yOffset;
309       popupDistanceTop = selfY - popupY;
310       popupDistanceBottom = winHeight - selfY - selfHeight - popupY;
311       popupDistanceLeft = offset.left - popupW - xOffset;
312       popupDistanceRight = winWidth - offset.left - selfWidth - popupW;
313       preferredPosition = options.preferredPosition;
314       if (preferredPosition === 'left' || preferredPosition === 'right') {
315         yDistance = 0;
316         popupOffsetTop += selfHeight / 2 + popupH / 2;
317         if ((preferredPosition === 'right' && popupDistanceRight > windowPadding) || popupDistanceLeft < windowPadding) {
318           popup.addClass(classRight);
319           popupOffsetLeft = offset.left + selfWidth + xOffset;
320         } else {
321           popup.addClass(classLeft);
322           popupOffsetLeft = offset.left - popupW - xOffset;
323           xDistance = -xDistance;
324         }
325       } else {
326         xDistance = 0;
327         if (popupOffsetLeft + popupCenter > winWidth - windowPadding) {
328           popupOffsetLeft -= popupCenter * 2 - xOffset;
329           popup.addClass(classAlignLeft);
330         } else if (popupOffsetLeft - popupCenter < windowPadding) {
331           popupOffsetLeft -= xOffset;
332           popup.addClass(classAlignRight);
333         } else {
334           popupOffsetLeft -= popupCenter;
335         }
336         if (popupOffsetLeft < windowPadding) {
337           popupOffsetLeft = windowPadding;
338         }
339         if ((preferredPosition === 'bottom' && popupDistanceBottom > windowPadding) || popupDistanceTop < windowPadding) {
340           yDistance = -yDistance;
341           popupOffsetTop += popupH + selfHeight - 2 * yOffset;
342           popup.addClass(classBottom);
343         }
344       }
345       if (popupH < selfHeight) {
346         yOverflow = popupOffsetTop + popupH + windowPadding - yDistance + yOffset - winScrollTop - winHeight;
347         if (yOverflow > 0) {
348           popupOffsetTop = Math.max(popupOffsetTop - yOverflow - windowPadding, offset.top + yOffset + windowPadding + yDistance);
349         }
350       }
351       if (popupW < selfWidth) {
352         xOverflow = popupOffsetLeft + popupW + windowPadding + xDistance + xOffset - winScrollLeft - winWidth;
353         if (xOverflow > 0) {
354           popupOffsetLeft = Math.max(popupOffsetLeft - xOverflow + windowPadding, offset.left + xOffset + windowPadding - xDistance);
355         }
356       }
357       if (options.hideTrigger) {
358         trigger.stop(true).fadeTo(options.triggerAnimationSpeed, 0);
359       }
360       opacity = 0;
361       if (!popupData[dataBeingShown] || options.cssAnimations.enabled) {
362         popupOffsetTop -= yDistance;
363         popupOffsetLeft += xDistance;
364         xDistance = yDistance = 0;
365         opacity = 1;
366       }
367       if (isFixed) {
368         popupOffsetLeft -= winScrollLeft;
369         popupOffsetTop -= winScrollTop;
370       }
371       popup.data(dataXDistance, xDistance).data(dataYDistance, yDistance).css({
372         top: popupOffsetTop,
373         left: popupOffsetLeft,
374         display: 'block',
375         opacity: opacity
376       });
377       _results.push(fadeInPopup(popup, {
378         top: "-=" + yDistance,
379         left: "+=" + xDistance,
380         opacity: 1
381       }));
382     }
383     return _results;
384   };
385   forceRefreshPosition = function() {
386     return refreshPosition(false);
387   };
388   fadeInPopup = function(popup, animationTarget) {
389     var options, _ref;
390     options = ((_ref = getTrigger(popup.data(dataShown)).data(classBase)) != null ? _ref.options : void 0) || sip.defaults;
391     if (options.cssAnimations.enabled) {
392       popup.addClass(options.cssAnimations.show);
393       return window.setTimeout(function() {
394         return fadeInPopupFinished(popup, options);
395       }, options.popupAnimationSpeed);
396     } else {
397       return popup.stop(true).animate(animationTarget, options.popupAnimationSpeed, options.funcEase, function() {
398         return fadeInPopupFinished(popup, options);
399       });
400     }
401   };
402   fadeInPopupFinished = function(popup, options) {
403     var popupData;
404     popupData = popup.data();
405     if (popupData[dataBeingShown]) {
406       popup.data(dataBeingShown, false);
407       return typeof options.onAfterShow === "function" ? options.onAfterShow(getTrigger(popupData[dataShown])) : void 0;
408     }
409   };
410   showPopup = function(trigger, content) {
411     var lastTrigger, lastTriggerOpt, popup, popupContent, popupPosition, shownId, tourOverlay, triggerData, triggerOptions;
412     if (content == null) {
413       content = '';
414     }
415     triggerData = trigger.data(classBase);
416     triggerOptions = triggerData.options;
417     popup = triggerData.popupInstance;
418     if (!popup.data(dataTriggerHovered)) {
419       return;
420     }
421     shownId = popup.data(dataShown);
422     if (shownId) {
423       lastTrigger = getTrigger(shownId);
424       if (lastTrigger.length) {
425         lastTriggerOpt = lastTrigger.data(classBase).options || sip.defaults;
426         if (lastTriggerOpt.hideTrigger) {
427           lastTrigger.stop(true).fadeTo(lastTriggerOpt.fadeSpeed, 1);
428         }
429       }
430     }
431     if (triggerOptions.tourHighlight && triggerOptions.tourIndex) {
432       tourOverlay = getOverlay().css({
433         backgroundColor: triggerOptions.tourHighlightColor,
434         zIndex: triggerOptions.tourHighlightZIndex
435       });
436       resetTourZIndices();
437       if (trigger.css('position') === 'static') {
438         trigger.css('position', 'relative');
439       }
440       if (!trigger.data(dataZIndex)) {
441         trigger.data(dataZIndex, trigger.css('zIndex'));
442       }
443       trigger.css('zIndex', triggerOptions.tourHighlightZIndex + 1);
444       tourOverlay.fadeTo(triggerOptions.tourHighlightFadeDuration, triggerOptions.tourHighlightOpacity);
445     } else if ($overlay) {
446       hideTourOverlay(triggerOptions);
447     }
448     popupContent = content || triggerData.hint;
449     if (triggerOptions.referencedContent && !content) {
450       popupContent = $(triggerOptions.referencedContent).clone(true, true) || popupContent;
451     }
452     popupPosition = isElementFixed(trigger) ? 'fixed' : 'absolute';
453     if (shownId !== triggerData.id) {
454       popup.hide(0);
455     }
456     popup.data(dataBeingShown, true).data(dataShown, triggerData.id).data(dataPosition, popupPosition).find('.' + classContent).empty().append(popupContent);
457     popup.css('position', popupPosition);
458     return queueRefreshPosition(0);
459   };
460   isElementFixed = function(element) {
461     var elemToCheck;
462     elemToCheck = element;
463     while (elemToCheck.length && elemToCheck[0].nodeName.toUpperCase() !== 'HTML') {
464       if (elemToCheck.css('position') === 'fixed') {
465         return true;
466       }
467       elemToCheck = elemToCheck.parent();
468     }
469     return false;
470   };
471   triggerMouseover = function() {
472     var isTrigger, popup, shownId, trigger, triggerData, _base;
473     trigger = popup = $(this);
474     isTrigger = trigger.hasClass(classInitialized);
475     if (!isTrigger) {
476       trigger = getTrigger(popup.data(dataShown));
477     }
478     if (!trigger.length) {
479       return;
480     }
481     triggerData = trigger.data(classBase);
482     popup = triggerData.popupInstance.data((isTrigger ? dataTriggerHovered : dataPopupHovered), true);
483     killTimers(popup);
484     shownId = popup.data(dataShown);
485     if (shownId !== triggerData.id || popup.css('opacity') === 0) {
486       if (typeof (_base = triggerData.options).onBeforeShow === "function") {
487         _base.onBeforeShow(trigger);
488       }
489       return popup.data(dataTimerShow, setTimeout(function() {
490         return showPopup(trigger);
491       }, triggerData.options.popupDelay));
492     }
493   };
494   triggerMouseout = function() {
495     var isTrigger, popup, popupData, trigger, triggerData, _base;
496     trigger = popup = $(this);
497     isTrigger = trigger.hasClass(classInitialized);
498     if (!isTrigger) {
499       trigger = getTrigger(popup.data(dataShown));
500     }
501     if (!trigger.length) {
502       return;
503     }
504     triggerData = trigger.data(classBase);
505     popup = triggerData.popupInstance.data((isTrigger ? dataTriggerHovered : dataPopupHovered), false);
506     killTimers(popup);
507     popupData = popup.data();
508     if (!(popupData[dataPopupHovered] || popupData[dataTriggerHovered])) {
509       if (typeof (_base = triggerData.options).onBeforeHide === "function") {
510         _base.onBeforeHide(trigger);
511       }
512       return popup.data(dataTimerHide, setTimeout(function() {
513         return hideSmallipop(popup);
514       }, triggerData.options.hideDelay));
515     }
516   };
517   onWindowScroll = function(e) {
518     clearTimeout(scrollTimer);
519     return scrollTimer = setTimeout(forceRefreshPosition, 250);
520   };
521   setContent = function(trigger, content) {
522     var partOfTour, popupContent, triggerData;
523     if (!(trigger != null ? trigger.length : void 0)) {
524       return;
525     }
526     triggerData = trigger.data(classBase);
527     partOfTour = triggerData.tourTitle;
528     if (partOfTour) {
529       popupContent = triggerData.popupInstance.find('.' + classTourContent);
530     } else {
531       popupContent = triggerData.popupInstance.find('.' + classContent);
532     }
533     if (popupContent.html() !== content) {
534       return popupContent.stop(true).fadeTo(triggerData.options.contentAnimationSpeed, 0, function() {
535         $(this).html(content).fadeTo(triggerData.options.contentAnimationSpeed, 1);
536         return refreshPosition();
537       });
538     }
539   };
540   runTour = function(trigger, step) {
541     var currentTourItems, i, tourTitle, triggerData, _i, _ref;
542     triggerData = trigger.data(classBase);
543     tourTitle = triggerData != null ? triggerData.tourTitle : void 0;
544     if (!(tourTitle && tours[tourTitle])) {
545       return;
546     }
547     tours[tourTitle].sort(function(a, b) {
548       return a.index - b.index;
549     });
550     if (!(typeof step === 'number' && step % 1 === 0)) {
551       step = -1;
552     } else {
553       step -= 1;
554     }
555     currentTour = tourTitle;
556     currentTourItems = tours[tourTitle];
557     for (i = _i = 0, _ref = currentTourItems.length - 1; 0 <= _ref ? _i <= _ref : _i >= _ref; i = 0 <= _ref ? ++_i : --_i) {
558       if ((step >= 0 && i === step) || (step < 0 && currentTourItems[i].id === triggerData.id)) {
559         return tourShow(tourTitle, i);
560       }
561     }
562   };
563   tourShow = function(title, index) {
564     var $content, $trigger, currentTourItems, navigation, navigationEnabled, options, triggerData;
565     currentTourItems = tours[title];
566     if (!currentTourItems) {
567       return;
568     }
569     $trigger = currentTourItems[index].trigger;
570     triggerData = $trigger.data(classBase);
571     options = triggerData.options;
572     navigationEnabled = options.tourNavigationEnabled;
573     navigation = '';
574     if (navigationEnabled) {
575       navigation += ("<div class='" + classTourProgress + "'>") + ("" + (index + 1) + " " + options.labels.of + " " + currentTourItems.length + "</div>");
576       if (index > 0) {
577         navigation += "<a href='#' class='" + classTourPrev + "'>" + options.labels.prev + "</a>";
578       }
579       if (index < currentTourItems.length - 1) {
580         navigation += "<a href='#' class='" + classTourNext + "'>" + options.labels.next + "</a>";
581       }
582     }
583     if (!navigationEnabled || index === currentTourItems.length - 1) {
584       navigation += "<a href='#' class='" + classTourClose + "'>" + options.labels.close + "</a>";
585     }
586     $content = $(("<div class='" + classTourContent + "'/>") + ("<a href='#' class='" + classTourCloseIcon + "'>&Chi;</a>") + ("<div class='" + classTourFooter + "'>" + navigation + "</div>"));
587     $content.eq(0).append(triggerData.hint);
588     killTimers(triggerData.popupInstance);
589     triggerData.popupInstance.data(dataTriggerHovered, true);
590     return showWhenVisible($trigger, $content);
591   };
592   showWhenVisible = function($trigger, content) {
593     var offset, targetPosition, triggerOptions, windowHeight;
594     targetPosition = $trigger.offset().top;
595     offset = targetPosition - $document.scrollTop();
596     windowHeight = $window.height();
597     triggerOptions = $trigger.data(classBase).options;
598     if (!isElementFixed($trigger) && (offset < triggerOptions.autoscrollPadding || offset > windowHeight - triggerOptions.autoscrollPadding)) {
599       return $('html, body').animate({
600         scrollTop: targetPosition - windowHeight / 2
601       }, 800, 'swing', function() {
602         return showPopup($trigger, content);
603       });
604     } else {
605       return showPopup($trigger, content);
606     }
607   };
608   tourNext = function(e) {
609     var $popup, currentTourItems, i, shownId, triggerOptions, _i, _ref;
610     if (e != null) {
611       e.preventDefault();
612     }
613     currentTourItems = tours[currentTour];
614     if (!currentTourItems) {
615       return;
616     }
617     $popup = currentTourItems[0].popupInstance;
618     shownId = $popup.data(dataShown) || currentTourItems[0].id;
619     for (i = _i = 0, _ref = currentTourItems.length - 2; 0 <= _ref ? _i <= _ref : _i >= _ref; i = 0 <= _ref ? ++_i : --_i) {
620       if (!(currentTourItems[i].id === shownId)) {
621         continue;
622       }
623       triggerOptions = currentTourItems[i].trigger.data(classBase).options;
624       if (triggerOptions.tourNavigationEnabled) {
625         if (typeof triggerOptions.onTourNext === "function") {
626           triggerOptions.onTourNext(currentTourItems[i + 1].trigger);
627         }
628         return tourShow(currentTour, i + 1);
629       }
630     }
631   };
632   tourPrev = function(e) {
633     var $popup, currentTourItems, i, shownId, triggerOptions, _i, _ref;
634     if (e != null) {
635       e.preventDefault();
636     }
637     currentTourItems = tours[currentTour];
638     if (!currentTourItems) {
639       return;
640     }
641     $popup = currentTourItems[0].popupInstance;
642     shownId = $popup.data(dataShown) || currentTourItems[0].id;
643     for (i = _i = 1, _ref = currentTourItems.length - 1; 1 <= _ref ? _i <= _ref : _i >= _ref; i = 1 <= _ref ? ++_i : --_i) {
644       if (!(currentTourItems[i].id === shownId)) {
645         continue;
646       }
647       triggerOptions = currentTourItems[i].trigger.data(classBase).options;
648       if (triggerOptions.tourNavigationEnabled) {
649         if (typeof triggerOptions.onTourPrev === "function") {
650           triggerOptions.onTourPrev(currentTourItems[i - 1].trigger);
651         }
652         return tourShow(currentTour, i - 1);
653       }
654     }
655   };
656   tourClose = function(e) {
657     var $popup;
658     if (e != null) {
659       e.preventDefault();
660     }
661     $popup = $(e.target).closest("." + classInstance);
662     return hideSmallipop($popup);
663   };
664   destroy = function(instances) {
665     return instances.each(function() {
666       var data, self;
667       self = $(this);
668       data = self.data(classBase);
669       if (data) {
670         return self.unbind("." + classBase).data(classBase, {}).removeClass(filterBaseClass);
671       }
672     });
673   };
674   onWindowKeyUp = function(e) {
675     var popup, popupId, targetIsInput, _ref, _results;
676     targetIsInput = (_ref = e != null ? e.target.tagName.toLowerCase() : void 0) === 'input' || _ref === 'textarea';
677     switch (e.which) {
678       case 27:
679         _results = [];
680         for (popupId in instances) {
681           popup = instances[popupId];
682           _results.push(hideSmallipop(popup));
683         }
684         return _results;
685         break;
686       case 37:
687         if (!targetIsInput) {
688           return tourPrev();
689         }
690         break;
691       case 39:
692         if (!targetIsInput) {
693           return tourNext();
694         }
695     }
696   };
697   getInstance = function(id, isTour) {
698     var instance;
699     if (id == null) {
700       id = 'default';
701     }
702     if (isTour == null) {
703       isTour = false;
704     }
705     if (instances[id]) {
706       return instances[id];
707     }
708     instance = $(popupTemplate).css('opacity', 0).attr('id', "" + (classBase + nextInstanceId++)).addClass(classInstance).data(dataXDistance, 0).data(dataYDistance, 0).data(dataIsTour, isTour).bind(eventMouseOver, triggerMouseover).bind(eventMouseOut, triggerMouseout);
709     $('body').append(instance);
710     if (isTour) {
711       instance.delegate("." + classTourPrev, eventClick, tourPrev).delegate("." + classTourNext, eventClick, tourNext).delegate("." + classTourClose + ", ." + classTourCloseIcon, eventClick, tourClose);
712     } else {
713       instance.delegate('a', eventClick, hideSmallipop);
714     }
715     if (nextInstanceId === 2) {
716       $document.bind("" + eventClick + " " + eventTouchEnd, hideSmallipop);
717       $window.bind(eventResize, queueRefreshPosition).bind(eventScroll, onWindowScroll).bind(eventKeyUp, onWindowKeyUp);
718     }
719     return instances[id] = instance;
720   };
721   return $.fn.smallipop = function(options, hint) {
722     var $popup;
723     if (options == null) {
724       options = {};
725     }
726     if (hint == null) {
727       hint = '';
728     }
729     if (typeof options === 'string') {
730       switch (options.toLowerCase()) {
731         case 'show':
732           showSmallipop.call(this.first().get(0));
733           break;
734         case 'hide':
735           hideSmallipop(this.first().get(0));
736           break;
737         case 'destroy':
738           destroy(this);
739           break;
740         case 'tour':
741           runTour(this.first(), hint);
742           break;
743         case 'update':
744           setContent(this.first(), hint);
745       }
746       return this;
747     }
748     options = $.extend(true, {}, sip.defaults, options);
749     if (!cssAnimationsEnabled) {
750       options.cssAnimations.enabled = false;
751     }
752     $popup = getInstance(options.popupId);
753     return this.each(function() {
754       var $objInfo, $self, isFormElement, newId, objHint, option, optionName, tagName, touchTrigger, tourTitle, triggerData, triggerEvents, triggerOptions, triggerPopupInstance, type, value;
755       $self = $(this);
756       tagName = $self[0].tagName.toLowerCase();
757       type = $self.attr('type');
758       triggerData = $self.data();
759       objHint = hint || $self.attr('title');
760       $objInfo = $("> ." + options.infoClass + ":first", $self);
761       if ($objInfo.length) {
762         objHint = $objInfo.clone(true, true).removeClass(options.infoClass);
763       }
764       if (objHint && !$self.hasClass(classInitialized)) {
765         newId = lastId++;
766         triggerEvents = {};
767         triggerPopupInstance = $popup;
768         triggerOptions = $.extend(true, {}, options);
769         if (typeof triggerData[classBase] === 'object') {
770           $.extend(true, triggerOptions, triggerData[classBase]);
771         }
772         for (option in triggerData) {
773           value = triggerData[option];
774           if (!(option.indexOf(classBase) >= 0)) {
775             continue;
776           }
777           optionName = option.replace(classBase, '');
778           if (optionName) {
779             optionName = optionName.substr(0, 1).toLowerCase() + optionName.substr(1);
780             triggerOptions[optionName] = value;
781           }
782         }
783         isFormElement = triggerOptions.handleInputs && (tagName === 'input' || tagName === 'select' || tagName === 'textarea');
784         if (triggerOptions.tourIndex) {
785           tourTitle = triggerOptions.tourTitle || 'defaultTour';
786           triggerOptions.hideOnTriggerClick = triggerOptions.hideOnPopupClick = false;
787           triggerPopupInstance = getInstance(tourTitle, true);
788           if (!tours[tourTitle]) {
789             tours[tourTitle] = [];
790           }
791           tours[tourTitle].push({
792             index: triggerOptions.tourIndex || 0,
793             id: newId,
794             trigger: $self,
795             popupInstance: triggerPopupInstance
796           });
797         } else {
798           touchTrigger = triggerOptions.touchSupport && touchEnabled;
799           if (isFormElement) {
800             triggerOptions.hideOnTriggerClick = false;
801             triggerEvents[eventFocus] = triggerMouseover;
802             triggerEvents[eventBlur] = triggerMouseout;
803           } else if (!touchTrigger) {
804             triggerEvents[eventMouseOut] = triggerMouseout;
805           }
806           if (triggerOptions.triggerOnClick || touchTrigger) {
807             triggerEvents[eventClick] = showSmallipop;
808           } else {
809             triggerEvents[eventClick] = triggerMouseout;
810             triggerEvents[eventMouseOver] = triggerMouseover;
811           }
812         }
813         $self.addClass("" + classInitialized + " " + classBase + newId).attr('title', '').data(classBase, {
814           id: newId,
815           hint: objHint,
816           options: triggerOptions,
817           tagName: tagName,
818           type: type,
819           tourTitle: tourTitle,
820           popupInstance: triggerPopupInstance,
821           isFormElement: isFormElement
822         }).bind(triggerEvents);
823         if (!triggerOptions.hideOnTriggerClick) {
824           return $self.delegate('a', eventClick, hideSmallipop);
825         }
826       }
827     });
828   };
829 });