From fc91035b45a3842bb800e4773bffd8b498a2b3c0 Mon Sep 17 00:00:00 2001 From: Gordon Koo Date: Tue, 4 Sep 2012 10:06:13 -0700 Subject: [PATCH] add jquery checks back in make loadTour a private function so that only one call is needed to start tour add nextOnTargetClick option for a step --- css/hopscotch.css | 2 +- css/hopscotch.less | 5 ++ js/hopscotch-min.js | 2 +- js/hopscotch.js | 144 ++++++++++++++++++++++++++------------------ 4 files changed, 94 insertions(+), 59 deletions(-) diff --git a/css/hopscotch.css b/css/hopscotch.css index d021ad3d..0fcbb0f4 100644 --- a/css/hopscotch.css +++ b/css/hopscotch.css @@ -10,7 +10,7 @@ div#hopscotch-bubble h3,div#hopscotch-bubble #hopscotch-bubble-number{font-size: div#hopscotch-bubble h3{margin:0;padding:0;} div#hopscotch-bubble #hopscotch-bubble-container{padding:15px;position:relative;-webkit-font-smoothing:antialiased;}div#hopscotch-bubble #hopscotch-bubble-container p{margin:10px 0;padding:0;} div#hopscotch-bubble #hopscotch-bubble-content{margin:0 0 0 40px;}div#hopscotch-bubble #hopscotch-bubble-content h3{margin:0 15px 0 0;} -div#hopscotch-bubble #hopscotch-bubble-close{color:#000;background:transparent url(../img/sprite_li.png) -200px -100px no-repeat;display:block;margin:15px 10px 0 0;position:absolute;text-decoration:none;text-indent:-9999px;width:10px;height:10px;top:0;right:0;} +div#hopscotch-bubble #hopscotch-bubble-close{color:#000;background:transparent url(../img/sprite_li.png) -200px -100px no-repeat;display:block;margin:15px 10px 0 0;position:absolute;text-decoration:none;text-indent:-9999px;width:10px;height:10px;top:0;right:0;}div#hopscotch-bubble #hopscotch-bubble-close.hide,div#hopscotch-bubble #hopscotch-bubble-close.hide-all{display:none;} div#hopscotch-bubble #hopscotch-bubble-number{background:transparent url(../img/sprite_li.png) 0 0 no-repeat;color:#fff;display:block;float:left;line-height:33px;margin:0 10px 0 0;text-align:center;width:30px;height:30px;} div#hopscotch-bubble #hopscotch-bubble-arrow-container{position:absolute;width:40px;height:40px;}div#hopscotch-bubble #hopscotch-bubble-arrow-container .hopscotch-bubble-arrow,div#hopscotch-bubble #hopscotch-bubble-arrow-container .hopscotch-bubble-arrow-border{width:0;height:0;} div#hopscotch-bubble #hopscotch-bubble-arrow-container.up{top:-26px;left:10px;}div#hopscotch-bubble #hopscotch-bubble-arrow-container.up .hopscotch-bubble-arrow{border-bottom:20px solid #ffffff;border-left:20px solid transparent;border-right:20px solid transparent;position:relative;top:-10px;} diff --git a/css/hopscotch.less b/css/hopscotch.less index 331e8cec..a112cdc8 100644 --- a/css/hopscotch.less +++ b/css/hopscotch.less @@ -89,6 +89,11 @@ div#hopscotch-bubble { top: 0; right: 0; + + &.hide, + &.hide-all { + display: none; + } } #hopscotch-bubble-number { diff --git a/js/hopscotch-min.js b/js/hopscotch-min.js index 3a8d4dd2..e9bd29cb 100644 --- a/js/hopscotch-min.js +++ b/js/hopscotch-min.js @@ -1 +1 @@ -(function(c,d){var m,e,j,i,g,a,l=c[d],h="undefined",b=false,k=(typeof window.sessionStorage!==h),f=document.body.style;if(l){return}a=function(){if(b){l.startTour()}};if(window.addEventListener){window.addEventListener("load",a)}else{if(window.attachEvent){window.attachEvent("onload",a)}}i={addClass:function(p,r){var o,q,n;if(p.className.length===0){p.className=r}else{o=p.className.split(" ");for(q=0,n=o.length;q=0){i.addClass(u,"prev")}else{i.addClass(u,"next")}return u},p=function(v,u,x){var w="hide";if(x){w="hide-all"}if(typeof u===h){u=true}if(u){i.removeClass(v,w)}else{i.addClass(v,w)}},q=function(A,x){var D,u,B,w,C,y,z=6,G=i.getStepTarget(x),v=A.element,F=A.arrowEl,E=i.getPixelValue(x.arrowOffset);D=i.getPixelValue(x.width)||s.bubbleWidth;B=i.valOrDefault(x.padding,s.bubblePadding);i.removeClass(v,"fade-in-down fade-in-up fade-in-left fade-in-right");w=G.getBoundingClientRect();if(x.orientation==="top"){u=v.offsetHeight;C=(w.top-u)-s.arrowWidth;y=w.left}else{if(x.orientation==="bottom"){C=w.bottom+s.arrowWidth;y=w.left}else{if(x.orientation==="left"){C=w.top;y=w.left-D-2*B-2*z-s.arrowWidth}else{if(x.orientation==="right"){C=w.top;y=w.right+s.arrowWidth}}}}if(!E){F.style.top="";F.style.left=""}else{if(x.orientation==="top"||x.orientation==="bottom"){F.style.top="";F.style.left=E+"px"}else{if(x.orientation==="left"||x.orientation==="right"){F.style.left="";F.style.top=E+"px"}}}y+=i.getPixelValue(x.xOffset);C+=i.getPixelValue(x.yOffset);if(!x.fixedElement){C+=i.getScrollTop();y+=i.getScrollLeft()}v.style.position=(x.fixedElement?"fixed":"absolute");v.style.top=C+"px";v.style.left=y+"px"},t=function(){var y=document.createElement("div"),z=document.createElement("div"),x=document.createElement("div"),w=this,A=false,v,u;this.element=y;this.containerEl=z;this.titleEl=document.createElement("h3");this.numberEl=document.createElement("span");this.contentEl=document.createElement("p");y.id="hopscotch-bubble";i.addClass(y,"animated");z.id="hopscotch-bubble-container";this.numberEl.id="hopscotch-bubble-number";z.appendChild(this.numberEl);x.appendChild(this.titleEl);x.appendChild(this.contentEl);x.id="hopscotch-bubble-content";z.appendChild(x);y.appendChild(z);this.initNavButtons();this.initCloseButton();this.initArrow();v=function(){if(A||!o){return}A=true;u=setTimeout(function(){q(w,n,false);A=false},200)};if(window.addEventListener){window.addEventListener("resize",v)}else{if(window.attachEvent){window.attachEvent("onresize",v)}}this.hide();document.body.appendChild(y);return this};this.initNavButtons=function(){var u=document.createElement("div");this.prevBtnEl=r("hopscotch-prev",j.prevBtn);this.nextBtnEl=r("hopscotch-next",j.nextBtn);this.doneBtnEl=r("hopscotch-done",j.doneBtn);i.addClass(this.doneBtnEl,"hide");u.appendChild(this.prevBtnEl);u.appendChild(this.nextBtnEl);u.appendChild(this.doneBtnEl);i.addClickListener(this.prevBtnEl,function(v){l.prevStep()});i.addClickListener(this.nextBtnEl,function(v){l.nextStep()});i.addClickListener(this.doneBtnEl,l.endTour);u.id="hopscotch-actions";this.buttonsEl=u;this.containerEl.appendChild(u);return this};this.initCloseButton=function(){var u=document.createElement("a");u.id="hopscotch-bubble-close";u.href="#";u.title=j.closeTooltip;u.innerHTML=j.closeTooltip;i.addClickListener(u,function(w){var v=l.getCurrStepNum(),x=l.getCurrTour(),y=(v===x.steps.length-1);i.invokeCallbacks("close",[x.id,v]);l.endTour(true,y);if(w.preventDefault){w.preventDefault()}else{if(event){event.returnValue=false}}});this.closeBtnEl=u;this.containerEl.appendChild(u);return this};this.initArrow=function(){var u,v;this.arrowEl=document.createElement("div");this.arrowEl.id="hopscotch-bubble-arrow-container";v=document.createElement("div");v.className="hopscotch-bubble-arrow-border";u=document.createElement("div");u.className="hopscotch-bubble-arrow";this.arrowEl.appendChild(v);this.arrowEl.appendChild(u);this.element.appendChild(this.arrowEl);return this};this.renderStep=function(w,B,x,y,C){var D=this,v=i.valOrDefault(w.showNextButton,s.showNextButton),u=i.valOrDefault(w.showPrevButton,s.showPrevButton),A,z;n=w;this.setTitle(w.title?w.title:"");this.setContent(w.content?w.content:"");this.setNum(B);this.orientation=w.orientation;this.showPrevButton(this.prevBtnEl&&u&&(B>0||x>0));this.showNextButton(this.nextBtnEl&&v&&!y);this.nextBtnEl.value=w.showSkip?j.skipBtn:j.nextBtn;if(y){i.removeClass(this.doneBtnEl,"hide")}else{i.addClass(this.doneBtnEl,"hide")}this.setArrow(w.orientation);A=i.getPixelValue(w.width)||s.bubbleWidth;z=i.valOrDefault(w.padding,s.bubblePadding);this.containerEl.style.width=A+"px";this.containerEl.style.padding=z+"px";this.element.style.zIndex=(w.zindex?w.zindex:"");if(w.orientation==="top"){setTimeout(function(){q(D,w);if(C){if(!w.fixedElement){C()}else{D.show()}}},5)}else{q(this,w);if(C){if(!w.fixedElement){C()}else{D.show()}}}return this};this.setTitle=function(u){if(u){this.titleEl.innerHTML=u;i.removeClass(this.titleEl,"hide")}else{i.addClass(this.titleEl,"hide")}return this};this.setContent=function(u){if(u){this.contentEl.innerHTML=u;i.removeClass(this.contentEl,"hide")}else{i.addClass(this.contentEl,"hide")}return this};this.setNum=function(u){if(j.stepNums&&u0)?F[E]:F},y=function(){return w.steps[q].length>0},s=function(){var F=w.steps[q].length;if(E0){--E;return true}else{if(q>0){F=w.steps[--q].length;if(F){E=F-1}else{E=undefined}return true}}return false},p=function(Q){var O=u(),Y=O.element,U=i.getPixelValue(Y.style.top),T=U+i.getPixelValue(Y.offsetHeight),R=i.getStepTarget(z()),Z=R.getBoundingClientRect(),W=Z.top+i.getScrollTop(),S=Z.bottom+i.getScrollTop(),M=(US)?T:S,V=i.getScrollTop(),H=V+i.getWindowHeight(),I=M-o.scrollTopMargin,P=this,G,L,K,X,J,N;if(typeof YAHOO!==h&&typeof YAHOO.env!==h&&typeof YAHOO.env.ua!==h&&typeof YAHOO.util!==h&&typeof YAHOO.util.Scroll!==h){G=YAHOO.env.ua.webkit?document.body:document.documentElement;K=YAHOO.util.Easing?YAHOO.util.Easing.easeOut:undefined;L=new YAHOO.util.Scroll(G,{scroll:{to:[0,I]}},o.scrollDuration/1000,K);L.onComplete.subscribe(Q);L.animate();return}if(I<0){I=0}if(M>=V&&M<=V+o.scrollTopMargin){if(Q){Q()}return}if(MH){if(o.smoothScroll){X=(V>M)?-1:1;J=Math.abs(V-I)/(o.scrollDuration/10);N=setInterval(function(){var ab=i.getScrollTop(),aa=ab+(X*J);if((X>0&&aa>=I)||X<0&&aa<=I){aa=I;clearInterval(N);if(Q){Q()}window.scrollTo(0,aa);return}window.scrollTo(0,aa);if(i.getScrollTop()===ab){clearInterval(N);if(Q){Q()}}},10)}else{window.scrollTo(0,I);if(Q){Q()}}}else{if(Q){Q()}return}},A=function(){if(t){this.configure(t)}};this.loadTour=function(K){var I={},G,L,H,F,J;w=K;for(L in K){if(K.hasOwnProperty(L)&&L!=="id"&&L!=="steps"){I[L]=K[L]}}this.resetDefaultOptions();r.call(this,I,true);F=i.getState(o.cookieName);if(F){J=F.split(":");v=J[0];n=J[1];C=undefined;H=n.split("-");if(H.length>1){n=parseInt(H[0],10);C=parseInt(H[1],10)}else{n=parseInt(n,10)}if(J.length>2&&J[2]==="mp"){if(C&&C0){C=0}else{C=undefined}}}}}G=u();G.showPrevButton(o.showPrevButton,true);G.showNextButton(o.showNextButton,true);return this};this.startTour=function(I,H){var F,G;if(!w){throw"Need to load a tour before you start it!"}if(document.readyState!=="complete"){b=true;return this}if(typeof I!==h){q=I;E=H}else{if(w.id===v&&typeof n!==h){q=n;E=C;G=z();if(!i.getStepTarget(G)){D();G=z();if(!i.getStepTarget(G)){this.endTour(false,false);return this}}}else{q=0}}if(!E&&y()){E=0}i.invokeCallbacks("start",[w.id,q]);F=u();this.isActive=true;if(o.animate){F.initAnimate()}if(!i.getStepTarget(z())){i.invokeCallbacks("error",[w.id,q]);if(o.skipIfNoElement){this.nextStep(false)}}else{this.showStep(q,E)}return this};this.showStep=function(O,G){var I=w.steps,H=I[O],F=I.length,M=w.id+":"+O,L=u(),K=i.valOrDefault(H.delay,0),N=this,J;q=O;E=G;if(!o.animate){L.hide(false)}if(typeof G!==h&&y()){H=H[G];M+="-"+G}J=(O===F-1)||(G>=H.length-1);setTimeout(function(){L.renderStep(H,O,G,J,function(){p(function(){L.show.call(L)});if(H.onShow){H.onShow()}});i.invokeCallbacks("show",[w.id,q])},K);if(H.multipage){M+=":mp"}i.setState(o.cookieName,M,1);return this};this.prevStep=function(){var H=z(),G=false,F=u();if(H.onPrev){H.onPrev()}i.invokeCallbacks("prev",[w.id,q]);if(o.skipIfNoElement){while(!G&&D()){H=z();G=i.getStepTarget(H);if(!G){i.invokeCallbacks("error",[w.id,q])}}if(!G){return this.endTour(true,false)}}else{if(D()){H=z();if(!i.getStepTarget(H)){i.invokeCallbacks("error",[w.id,q]);return this.endTour(true,false)}}}this.showStep(q,E);return this};this.nextStep=function(J){var I=z(),H=q,G=false,F=u();J=i.valOrDefault(J,true);if(o.skipIfNoElement){while(!G&&s()){I=z();G=i.getStepTarget(I);if(!G){i.invokeCallbacks("error",[w.id,q])}}if(!G){return this.endTour(true,false)}}else{if(s()){I=z();if(!i.getStepTarget(I)){i.invokeCallbacks("error",[w.id,q]);return this.endTour(true,false)}}}if(J){if(I.onNext){I.onNext()}i.invokeCallbacks("next",[w.id,H])}this.showStep(q,E);return this};this.endTour=function(H,G){var F=u();H=i.valOrDefault(H,true);G=i.valOrDefault(G,true);q=0;E=undefined;n=undefined;F.hide();if(H){i.clearState(o.cookieName)}l.isActive=false;if(G){i.invokeCallbacks("end",[w.id])}l.removeCallbacks(true);return this};this.getCurrTour=function(){return w};this.getCurrStepNum=function(){return q};this.getCurrSubstepNum=function(){return E};this.addCallback=function(H,F,G){if(F){g[H].push({cb:F,fromTour:G})}return this};this.removeCallbacks=function(G){var J,H,F,I;for(I in g){if(G){J=g[I];for(H=0,F=J.length;H=0){k.addClass(w,"prev")}else{k.addClass(w,"next")}return w},r=function(x,w,z){var y="hide";if(z){y="hide-all"}if(typeof w===j){w=true}if(w){k.removeClass(x,y)}else{k.addClass(x,y)}},s=function(C,z){var F,w,D,y,E,A,B=6,I=k.getStepTarget(z),x=C.element,H=C.arrowEl,G=k.getPixelValue(z.arrowOffset);F=k.getPixelValue(z.width)||u.bubbleWidth;D=k.valOrDefault(z.padding,u.bubblePadding);k.removeClass(x,"fade-in-down fade-in-up fade-in-left fade-in-right");y=I.getBoundingClientRect();if(z.orientation==="top"){w=x.offsetHeight;E=(y.top-w)-u.arrowWidth;A=y.left}else{if(z.orientation==="bottom"){E=y.bottom+u.arrowWidth;A=y.left}else{if(z.orientation==="left"){E=y.top;A=y.left-F-2*D-2*B-u.arrowWidth}else{if(z.orientation==="right"){E=y.top;A=y.right+u.arrowWidth}}}}if(!G){H.style.top="";H.style.left=""}else{if(z.orientation==="top"||z.orientation==="bottom"){H.style.top="";H.style.left=G+"px"}else{if(z.orientation==="left"||z.orientation==="right"){H.style.left="";H.style.top=G+"px"}}}A+=k.getPixelValue(z.xOffset);E+=k.getPixelValue(z.yOffset);if(!z.fixedElement){E+=k.getScrollTop();A+=k.getScrollLeft()}x.style.position=(z.fixedElement?"fixed":"absolute");if(u.animate&&d&&!f){$(x).animate({top:E+"px",left:A+"px"})}else{x.style.top=E+"px";x.style.left=A+"px"}},v=function(){var A=document.createElement("div"),B=document.createElement("div"),z=document.createElement("div"),y=this,C=false,x,w;this.element=A;this.containerEl=B;this.titleEl=document.createElement("h3");this.numberEl=document.createElement("span");this.contentEl=document.createElement("p");A.id="hopscotch-bubble";k.addClass(A,"animated");B.id="hopscotch-bubble-container";this.numberEl.id="hopscotch-bubble-number";B.appendChild(this.numberEl);z.appendChild(this.titleEl);z.appendChild(this.contentEl);z.id="hopscotch-bubble-content";B.appendChild(z);A.appendChild(B);this.initNavButtons();this.initCloseButton();this.initArrow();x=function(){if(C||!q){return}C=true;w=setTimeout(function(){s(y,p,false);C=false},200)};if(window.addEventListener){window.addEventListener("resize",x)}else{if(window.attachEvent){window.attachEvent("onresize",x)}}this.hide();document.body.appendChild(A);return this};this.initNavButtons=function(){var w=document.createElement("div");this.prevBtnEl=t("hopscotch-prev",l.prevBtn);this.nextBtnEl=t("hopscotch-next",l.nextBtn);this.doneBtnEl=t("hopscotch-done",l.doneBtn);k.addClass(this.doneBtnEl,"hide");w.appendChild(this.prevBtnEl);w.appendChild(this.nextBtnEl);w.appendChild(this.doneBtnEl);k.addClickListener(this.prevBtnEl,function(x){n.prevStep()});k.addClickListener(this.nextBtnEl,function(x){n.nextStep()});k.addClickListener(this.doneBtnEl,n.endTour);w.id="hopscotch-actions";this.buttonsEl=w;this.containerEl.appendChild(w);return this};this.initCloseButton=function(){var w=document.createElement("a");w.id="hopscotch-bubble-close";w.href="#";w.title=l.closeTooltip;w.innerHTML=l.closeTooltip;k.addClickListener(w,function(y){var x=n.getCurrStepNum(),z=n.getCurrTour(),A=(x===z.steps.length-1);k.invokeCallbacks("close",[z.id,x]);n.endTour(true,A);if(y.preventDefault){y.preventDefault()}else{if(event){event.returnValue=false}}});this.closeBtnEl=w;this.containerEl.appendChild(w);return this};this.initArrow=function(){var w,x;this.arrowEl=document.createElement("div");this.arrowEl.id="hopscotch-bubble-arrow-container";x=document.createElement("div");x.className="hopscotch-bubble-arrow-border";w=document.createElement("div");w.className="hopscotch-bubble-arrow";this.arrowEl.appendChild(x);this.arrowEl.appendChild(w);this.element.appendChild(this.arrowEl);return this};this.renderStep=function(y,D,z,A,E){var F=this,x=k.valOrDefault(y.showNextButton,u.showNextButton),w=k.valOrDefault(y.showPrevButton,u.showPrevButton),C,B;p=y;this.setTitle(y.title?y.title:"");this.setContent(y.content?y.content:"");this.setNum(D);this.orientation=y.orientation;this.showPrevButton(this.prevBtnEl&&w&&(D>0||z>0));this.showNextButton(this.nextBtnEl&&x&&!A);this.nextBtnEl.value=y.showSkip?l.skipBtn:l.nextBtn;if(A){k.removeClass(this.doneBtnEl,"hide")}else{k.addClass(this.doneBtnEl,"hide")}this.setArrow(y.orientation);C=k.getPixelValue(y.width)||u.bubbleWidth;B=k.valOrDefault(y.padding,u.bubblePadding);this.containerEl.style.width=C+"px";this.containerEl.style.padding=B+"px";this.element.style.zIndex=(y.zindex?y.zindex:"");if(y.orientation==="top"){setTimeout(function(){s(F,y);if(E){if(!y.fixedElement){E()}else{F.show()}}},5)}else{s(this,y);if(E){if(!y.fixedElement){E()}else{F.show()}}}return this};this.setTitle=function(w){if(w){this.titleEl.innerHTML=w;k.removeClass(this.titleEl,"hide")}else{k.addClass(this.titleEl,"hide")}return this};this.setContent=function(w){if(w){this.contentEl.innerHTML=w;k.removeClass(this.contentEl,"hide")}else{k.addClass(this.contentEl,"hide")}return this};this.setNum=function(w){if(l.stepNums&&w0)?I[H]:I},B=function(){return z.steps[t].length>0},v=function(){var I=z.steps[t].length;if(H0){--H;return true}else{if(t>0){I=z.steps[--t].length;if(I){H=I-1}else{H=undefined}return true}}return false},s=function(T){var R=x(),ab=R.element,X=k.getPixelValue(ab.style.top),W=X+k.getPixelValue(ab.offsetHeight),U=k.getStepTarget(C()),ac=U.getBoundingClientRect(),Z=ac.top+k.getScrollTop(),V=ac.bottom+k.getScrollTop(),P=(XV)?W:V,Y=k.getScrollTop(),K=Y+k.getWindowHeight(),L=P-q.scrollTopMargin,S=this,J,O,N,aa,M,Q;if(P>=Y&&(P<=Y+q.scrollTopMargin||I<=K)){if(T){T()}return}else{if(!q.smoothScroll){window.scrollTo(0,L);if(T){T()}return}else{if(typeof YAHOO!==j&&typeof YAHOO.env!==j&&typeof YAHOO.env.ua!==j&&typeof YAHOO.util!==j&&typeof YAHOO.util.Scroll!==j){J=YAHOO.env.ua.webkit?document.body:document.documentElement;N=YAHOO.util.Easing?YAHOO.util.Easing.easeOut:undefined;O=new YAHOO.util.Scroll(J,{scroll:{to:[0,L]}},q.scrollDuration/1000,N);O.onComplete.subscribe(T);O.animate()}else{if(d){$("body, html").animate({scrollTop:L},q.scrollDuration,T)}else{if(L<0){L=0}aa=(Y>P)?-1:1;M=Math.abs(Y-L)/(q.scrollDuration/10);Q=setInterval(function(){var ae=k.getScrollTop(),ad=ae+(aa*M);if((aa>0&&ad>=L)||aa<0&&ad<=L){ad=L;clearInterval(Q);if(T){T()}window.scrollTo(0,ad);return}window.scrollTo(0,ad);if(k.getScrollTop()===ae){clearInterval(Q);if(T){T()}}},10)}}}}},r=function(N){var L={},J,O,K,I,M;z=N;for(O in N){if(N.hasOwnProperty(O)&&O!=="id"&&O!=="steps"){L[O]=N[O]}}this.resetDefaultOptions();u.call(this,L,true);I=k.getState(q.cookieName);if(I){M=I.split(":");y=M[0];p=M[1];F=undefined;K=p.split("-");if(K.length>1){p=parseInt(K[0],10);F=parseInt(K[1],10)}else{p=parseInt(p,10)}if(M.length>2&&M[2]==="mp"){if(F&&F0){F=0}else{F=undefined}}}}}return this},D=function(){if(w){this.configure(w)}};this.startTour=function(M,L,K){var I,J;if(!z){r.call(this,M)}if(document.readyState!=="complete"){b=true;return this}if(typeof L!==j){t=L;H=K}else{if(z.id===y&&typeof p!==j){t=p;H=F;J=C();if(!k.getStepTarget(J)){G();J=C();if(!k.getStepTarget(J)){this.endTour(false,false);return this}}}else{t=0}}if(!H&&B()){H=0}k.invokeCallbacks("start",[z.id,t]);I=x();I.hide(false);this.isActive=true;if(q.animate){I.initAnimate()}if(!k.getStepTarget(C())){k.invokeCallbacks("error",[z.id,t]);if(q.skipIfNoElement){this.nextStep(false)}}else{this.showStep(t,H)}return this};this.showStep=function(T,J){var L=z.steps,K=L[T],I=L.length,Q=z.id+":"+T,P=x(),N=k.valOrDefault(K.delay,0),S=this,R=k.getStepTarget(K),O,M;t=T;H=J;if(!q.animate){P.hide(false)}if(typeof J!==j&&B()){K=K[J];Q+="-"+J}if(K.nextOnTargetClick){O=function(){S.nextStep();return R.removeEventListener?R.removeEventListener("click",O):R.detachEvent("click",O)}}M=(T===I-1)||(J>=K.length-1);setTimeout(function(){P.renderStep(K,T,J,M,function(){s(function(){P.show()});if(K.onShow){K.onShow()}if(K.nextOnTargetClick){k.addClickListener(R,O)}});k.invokeCallbacks("show",[z.id,t])},N);if(K.multipage){Q+=":mp"}k.setState(q.cookieName,Q,1);return this};this.prevStep=function(){var K=C(),J=false,I=x();if(K.onPrev){K.onPrev()}k.invokeCallbacks("prev",[z.id,t]);if(q.skipIfNoElement){while(!J&&G()){K=C();J=k.getStepTarget(K);if(!J){k.invokeCallbacks("error",[z.id,t])}}if(!J){return this.endTour(true,false)}}else{if(G()){K=C();if(!k.getStepTarget(K)){k.invokeCallbacks("error",[z.id,t]);return this.endTour(true,false)}}}this.showStep(t,H);return this};this.nextStep=function(M){var L=C(),K=t,J=false,I=x();M=k.valOrDefault(M,true);if(q.skipIfNoElement){while(!J&&v()){L=C();J=k.getStepTarget(L);if(!J){k.invokeCallbacks("error",[z.id,t])}}if(!J){return this.endTour(true)}}else{if(v()){L=C();if(!k.getStepTarget(L)){k.invokeCallbacks("error",[z.id,t]);return this.endTour(true,false)}}}if(M){if(L.onNext){L.onNext()}k.invokeCallbacks("next",[z.id,K])}this.showStep(t,H);return this};this.endTour=function(K,J){var I=x();K=k.valOrDefault(K,true);J=k.valOrDefault(J,true);t=0;H=undefined;p=undefined;I.hide();if(K){k.clearState(q.cookieName)}n.isActive=false;if(z&&J){k.invokeCallbacks("end",[z.id])}n.removeCallbacks(true);z=null;return this};this.getCurrTour=function(){return z};this.getCurrStepNum=function(){return t};this.getCurrSubstepNum=function(){return H};this.addCallback=function(K,I,J){if(I){i[K].push({cb:I,fromTour:J})}return this};this.removeCallbacks=function(J){var M,K,I,L;for(L in i){if(J){M=i[L];for(K=0,I=M.length;K 1 bubble at a time? gahhhhhhhhh - * onShow, onHide callbacks? + * support > 1 bubble at a time? * */ @@ -31,8 +32,14 @@ undefinedStr = 'undefined', waitingToStart = false, // is a tour waiting for the document to finish // loading so that it can start? + hasJquery = (typeof window.jQuery !== undefinedStr), hasSessionStorage = (typeof window.sessionStorage !== undefinedStr), - docStyle = document.body.style; + docStyle = document.body.style, + hasCssTransitions = (typeof docStyle.MozTransition !== undefinedStr || + typeof docStyle.MsTransition !== undefinedStr || + typeof docStyle.webkitTransition !== undefinedStr || + typeof docStyle.OTransition !== undefinedStr || + typeof docStyle.transition !== undefinedStr); if (winHopscotch) { // Hopscotch already exists. @@ -374,8 +381,16 @@ // ACCOUNT FOR FIXED POSITION ELEMENTS el.style.position = (step.fixedElement ? 'fixed' : 'absolute'); - el.style.top = top + 'px'; - el.style.left = left + 'px'; + if (opt.animate && hasJquery && !hasCssTransitions) { + $(el).animate({ + top: top + 'px', + left: left + 'px' + }); + } + else { + el.style.top = top + 'px'; + el.style.left = left + 'px'; + } }, init = function() { @@ -837,32 +852,41 @@ scrollIncr, scrollInt; - if (typeof YAHOO !== undefinedStr && - typeof YAHOO.env !== undefinedStr && - typeof YAHOO.env.ua !== undefinedStr && - typeof YAHOO.util !== undefinedStr && - typeof YAHOO.util.Scroll !== undefinedStr) { - scrollEl = YAHOO.env.ua.webkit ? document.body : document.documentElement; - yuiEase = YAHOO.util.Easing ? YAHOO.util.Easing.easeOut : undefined; - yuiAnim = new YAHOO.util.Scroll(scrollEl, { - scroll: { to: [0, scrollToVal] } - }, opt.scrollDuration/1000, yuiEase); - yuiAnim.onComplete.subscribe(cb); - yuiAnim.animate(); + if (targetTop >= windowTop && (targetTop <= windowTop + opt.scrollTopMargin || targetBottom <= windowBottom)) { + // target and bubble are both visible in viewport + if (cb) { cb(); } // HopscotchBubble.show return; } + else if (!opt.smoothScroll) { + // Abrupt scroll to scroll target + window.scrollTo(0, scrollToVal); - if (scrollToVal < 0) { - scrollToVal = 0; - } - - if (targetTop >= windowTop && targetTop <= windowTop + opt.scrollTopMargin) { if (cb) { cb(); } // HopscotchBubble.show return; } + else { + // Smooth scroll to scroll target + if (typeof YAHOO !== undefinedStr && + typeof YAHOO.env !== undefinedStr && + typeof YAHOO.env.ua !== undefinedStr && + typeof YAHOO.util !== undefinedStr && + typeof YAHOO.util.Scroll !== undefinedStr) { + scrollEl = YAHOO.env.ua.webkit ? document.body : document.documentElement; + yuiEase = YAHOO.util.Easing ? YAHOO.util.Easing.easeOut : undefined; + yuiAnim = new YAHOO.util.Scroll(scrollEl, { + scroll: { to: [0, scrollToVal] } + }, opt.scrollDuration/1000, yuiEase); + yuiAnim.onComplete.subscribe(cb); + yuiAnim.animate(); + } + else if (hasJquery) { + $('body, html').animate({ scrollTop: scrollToVal }, opt.scrollDuration, cb); + } + else { + if (scrollToVal < 0) { + scrollToVal = 0; + } - if (targetTop < windowTop || targetBottom > windowBottom) { - if (opt.smoothScroll) { // 48 * 10 == 480ms scroll duration // make it slightly less than CSS transition duration because of // setInterval overhead. @@ -894,32 +918,16 @@ } }, 10); } - else { - window.scrollTo(0, scrollToVal); - - if (cb) { cb(); } // HopscotchBubble.show - } - } - else { - // I guess it's showing in the window. Just point to it then. - if (cb) { cb(); } // HopscotchBubble.show - return; } }, - init = function() { - if (initOptions) { - this.configure(initOptions); - } - }; - /** * loadTour * ======== * Loads, but does not display, tour. (Give the developer a chance to * override tour-specified configuration options before displaying) */ - this.loadTour = function(tour) { + loadTour = function(tour) { var tmpOpt = {}, bubble, prop, @@ -976,19 +984,21 @@ } } - // Initialize whether to show or hide nav buttons - bubble = getBubble(); - bubble.showPrevButton(opt.showPrevButton, true); - bubble.showNextButton(opt.showNextButton, true); return this; + }, + + init = function() { + if (initOptions) { + this.configure(initOptions); + } }; - this.startTour = function(stepNum, substepNum) { + this.startTour = function(tour, stepNum, substepNum) { var bubble, step; if (!currTour) { - throw "Need to load a tour before you start it!"; + loadTour.call(this, tour); } // If document isn't ready, wait for it to finish loading. @@ -1034,6 +1044,7 @@ utils.invokeCallbacks('start', [currTour.id, currStepNum]); bubble = getBubble(); + bubble.hide(false); // make invisible for boundingRect calculations when opt.animate == true this.isActive = true; if (opt.animate) { @@ -1062,6 +1073,8 @@ bubble = getBubble(), delay = utils.valOrDefault(step.delay, 0), self = this, + targetEl = utils.getStepTarget(step), + nextStepFn, isLast; // Update bubble for current step @@ -1078,15 +1091,29 @@ cookieVal += '-' + substepIdx; } + // When nextOnTargetClick is true, attach this function to the click event + // of the target element. + if (step.nextOnTargetClick) { + nextStepFn = function() { + self.nextStep(); + return targetEl.removeEventListener ? targetEl.removeEventListener('click', nextStepFn) : targetEl.detachEvent('click', nextStepFn); + }; + } + isLast = (stepIdx === numTourSteps - 1) || (substepIdx >= step.length - 1); setTimeout(function() { bubble.renderStep(step, stepIdx, substepIdx, isLast, function() { // when done adjusting window scroll, call bubble.show() adjustWindowScroll(function() { - bubble.show.call(bubble); + bubble.show(); }); if (step.onShow) { step.onShow(); } + + // If we want to advance to next step when user clicks on target. + if (step.nextOnTargetClick) { + utils.addClickListener(targetEl, nextStepFn); + } }); utils.invokeCallbacks('show', [currTour.id, currStepNum]); }, delay); @@ -1156,7 +1183,7 @@ } } if (!foundTarget) { - return this.endTour(true, false); + return this.endTour(true); } } else if (incrementStep()) { @@ -1185,7 +1212,8 @@ /** * endTour * ========== - * Cancels out of an active tour. No state is preserved. + * Cancels out of an active tour. If clearCookie is true, no state is + * preserved. If doCallback is false, the onEnd callback is not invoked. */ this.endTour = function(clearCookie, doCallback) { var bubble = getBubble(); @@ -1201,12 +1229,14 @@ } winHopscotch.isActive = false; - if (doCallback) { + if (currTour && doCallback) { utils.invokeCallbacks('end', [currTour.id]); } winHopscotch.removeCallbacks(true); + currTour = null; + return this; }; @@ -1409,9 +1439,9 @@ bubble.removeAnimate(); } - bubble.showPrevButton(opt.showPrevButton, true); - bubble.showNextButton(opt.showNextButton, true); - bubble.showCloseButton(opt.showCloseButton, true); + bubble.showPrevButton(options.showPrevButton, typeof options.showPrevButton !== undefinedStr); + bubble.showNextButton(options.showNextButton, typeof options.showNextButton !== undefinedStr); + bubble.showCloseButton(options.showCloseButton, typeof options.showCloseButton !== undefinedStr); return this; };