From 516303551aeb9f59bf6a4117371c0a5ae5316614 Mon Sep 17 00:00:00 2001 From: Tal Ater Date: Thu, 21 Mar 2013 21:47:42 +0200 Subject: [PATCH 1/9] Added bootstro.on_complete(), bootstro.on_exit() and bootstro.on_step() --- bootstro.js | 39 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/bootstro.js b/bootstro.js index b95ee02..3828a92 100644 --- a/bootstro.js +++ b/bootstro.js @@ -28,6 +28,9 @@ $(document).ready(function(){ stopOnEsc : true }; var settings; + var onCompleteFunc; + var onExitFunc; + var onStepFunc; //===================PRIVATE METHODS====================== @@ -140,6 +143,10 @@ $(document).ready(function(){ //destroy active popover and remove backdrop bootstro.stop = function() { + //call onExit callback function if needed + if (this.onExitFunc != undefined) { + this.onExitFunc.call(this); + } bootstro.destroy_popover(activeIndex); bootstro.unbind(); $("div.bootstro-backdrop").remove(); @@ -149,6 +156,10 @@ $(document).ready(function(){ //go to the popover number idx starting from 0 bootstro.go_to = function(idx) { + //call onStep callback function if needed + if (this.onStepFunc != undefined) { + this.onStepFunc.call(this); + } //destroy current popover if any bootstro.destroy_popover(activeIndex); if (count != 0) @@ -172,7 +183,10 @@ $(document).ready(function(){ { if (activeIndex + 1 == count) { - alert('End of introduction'); + //call onComplete callback function if needed + if (this.onCompleteFunc != undefined) { + this.onCompleteFunc.call(this); + } } else bootstro.go_to(activeIndex + 1); @@ -250,7 +264,28 @@ $(document).ready(function(){ { $("html").unbind('click.bootstro'); $(document).unbind('keydown.bootstro'); - } + }; + bootstro.on_complete = function(callbackFunction) + { + if (Object.prototype.toString.call(callbackFunction) == '[object Function]') { + this.onCompleteFunc = callbackFunction; + } + }; + + bootstro.on_exit = function(callbackFunction) + { + if (Object.prototype.toString.call(callbackFunction) == '[object Function]') { + this.onExitFunc = callbackFunction; + } + }; + + bootstro.on_step = function(callbackFunction) + { + if (Object.prototype.toString.call(callbackFunction) == '[object Function]') { + this.onStepFunc = callbackFunction; + } + }; + }( window.bootstro = window.bootstro || {}, jQuery )); }); From 8754d68960b9ca76899311dda974b23c4ba368ae Mon Sep 17 00:00:00 2001 From: Ivan Suftin Date: Sun, 21 Apr 2013 16:39:04 -0500 Subject: [PATCH 2/9] Passing object into handlers that has the current index in it - passing in an object so more can be added later without breaking the API --- bootstro.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bootstro.js b/bootstro.js index 3828a92..a397a51 100644 --- a/bootstro.js +++ b/bootstro.js @@ -145,7 +145,7 @@ $(document).ready(function(){ { //call onExit callback function if needed if (this.onExitFunc != undefined) { - this.onExitFunc.call(this); + this.onExitFunc.call(this, { idx : activeIndex }); } bootstro.destroy_popover(activeIndex); bootstro.unbind(); @@ -158,7 +158,7 @@ $(document).ready(function(){ { //call onStep callback function if needed if (this.onStepFunc != undefined) { - this.onStepFunc.call(this); + this.onStepFunc.call(this, { idx : idx }); } //destroy current popover if any bootstro.destroy_popover(activeIndex); From b5a688734f1db3dddc4b521d52b1e0ef64c7fecd Mon Sep 17 00:00:00 2001 From: Ivan Suftin Date: Sun, 21 Apr 2013 16:49:53 -0500 Subject: [PATCH 3/9] Missed a spot to pass in the index --- bootstro.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bootstro.js b/bootstro.js index a397a51..428874d 100644 --- a/bootstro.js +++ b/bootstro.js @@ -185,7 +185,7 @@ $(document).ready(function(){ { //call onComplete callback function if needed if (this.onCompleteFunc != undefined) { - this.onCompleteFunc.call(this); + this.onCompleteFunc.call(this, { idx : activeIndex }); } } else From 97b53d8122eab16fe7f266d8503436fb5475d5a4 Mon Sep 17 00:00:00 2001 From: Steve Tran Date: Mon, 22 Apr 2013 10:27:43 +0700 Subject: [PATCH 4/9] updated min.js --- bootstro.min.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bootstro.min.js b/bootstro.min.js index e1c308c..d5f40ee 100644 --- a/bootstro.min.js +++ b/bootstro.min.js @@ -1 +1 @@ -$(document).ready(function(){(function(e,t,n){function f(e,t){i=r.size();e=e+"
";if(i!=1){if(t==0)e=e+a.nextButton;else if(t==i-1)e=e+a.prevButton;else e=e+a.nextButton+a.prevButton}e=e+"
";e=e+'
'+a.finishButton+"
";return e}var r;var i;var s=[];var o=null;var u={nextButton:'',prevButton:'',finishButton:'',stopOnBackdropClick:true,stopOnEsc:true};var a;get_element=function(e){if(r.filter("[data-bootstro-step="+e+"]").size()>0)return r.filter("[data-bootstro-step="+e+"]");else{return r.eq(e)}};get_popup=function(e){var t={};$el=get_element(e);var n="";if(i>1){n=""+(e+1)+"/"+i+""}t.title=$el.attr("data-bootstro-title")||"";if(t.title!=""&&n!="")t.title=n+" - "+t.title;else if(t.title=="")t.title=n;t.content=$el.attr("data-bootstro-content")||"";t.content=f(t.content,e);t.placement=$el.attr("data-bootstro-placement")||"top";var r="";if($el.attr("data-bootstro-width")){t.width=$el.attr("data-bootstro-width");r=r+"width:"+$el.attr("data-bootstro-width")+";"}if($el.attr("data-bootstro-height")){t.height=$el.attr("data-bootstro-height");r=r+"height:"+$el.attr("data-bootstro-height")+";"}t.trigger="manual";t.html=$el.attr("data-bootstro-html")||"top";t.template='

'+"
";return t};e.destroy_popover=function(e){e=e||0;if(e!="all"){$el=get_element(e);$el.popover("destroy").removeClass("bootstro-highlight")}};e.stop=function(){e.destroy_popover(o);e.unbind();t("div.bootstro-backdrop").remove()};e.go_to=function(n){e.destroy_popover(o);if(i!=0){p=get_popup(n);$el=get_element(n);$el.popover(p).popover("show");min=Math.min(t(".popover.in").offset().top,$el.offset().top);t("html,body").animate({scrollTop:min-20},"slow");$el.addClass("bootstro-highlight");o=n}};e.next=function(){if(o+1==i){alert("End of introduction")}else e.go_to(o+1)};e.prev=function(){if(o==0){alert("At start of intros")}else e.go_to(o-1)};e.start=function(n,s){a=t.extend(true,{},u);t.extend(a,s||{});n=n||".bootstro";r=t(n);i=r.size();t('
').appendTo("body");e.bind();e.go_to(0)};e.bind=function(){e.unbind();t("html").on("click.bootstro",".bootstro-next-btn",function(t){e.next();t.preventDefault();return false});t("html").on("click.bootstro",".bootstro-prev-btn",function(t){e.prev();t.preventDefault();return false});t("html").on("click.bootstro",".bootstro-finish-btn",function(t){e.stop()});if(a.stopOnBackdropClick){t("html").on("click.bootstro","div.bootstro-backdrop",function(n){if(t(n.target).hasClass("bootstro-backdrop"))e.stop()})}t(document).on("keydown.bootstro",function(t){var n=t.keyCode?t.keyCode:t.which;if(n==39||n==40)e.next();else if(n==37||n==38)e.prev();else if(n==27&&a.stopOnEsc)e.stop()})};e.unbind=function(){t("html").unbind("click.bootstro");t(document).unbind("keydown.bootstro")}})(window.bootstro=window.bootstro||{},jQuery)}) +$(document).ready(function(){(function(e,t,n){function h(e,t){i=r.size();e=e+"
";if(i!=1){if(t==0)e=e+a.nextButton;else if(t==i-1)e=e+a.prevButton;else e=e+a.nextButton+a.prevButton}e=e+"
";e=e+'
'+a.finishButton+"
";return e}var r;var i;var s=[];var o=null;var u={nextButton:'',prevButton:'',finishButton:'',stopOnBackdropClick:true,stopOnEsc:true};var a;var f;var l;var c;get_element=function(e){if(r.filter("[data-bootstro-step="+e+"]").size()>0)return r.filter("[data-bootstro-step="+e+"]");else{return r.eq(e)}};get_popup=function(e){var t={};$el=get_element(e);var n="";if(i>1){n=""+(e+1)+"/"+i+""}t.title=$el.attr("data-bootstro-title")||"";if(t.title!=""&&n!="")t.title=n+" - "+t.title;else if(t.title=="")t.title=n;t.content=$el.attr("data-bootstro-content")||"";t.content=h(t.content,e);t.placement=$el.attr("data-bootstro-placement")||"top";var r="";if($el.attr("data-bootstro-width")){t.width=$el.attr("data-bootstro-width");r=r+"width:"+$el.attr("data-bootstro-width")+";"}if($el.attr("data-bootstro-height")){t.height=$el.attr("data-bootstro-height");r=r+"height:"+$el.attr("data-bootstro-height")+";"}t.trigger="manual";t.html=$el.attr("data-bootstro-html")||"top";t.template='

'+"
";return t};e.destroy_popover=function(e){e=e||0;if(e!="all"){$el=get_element(e);$el.popover("destroy").removeClass("bootstro-highlight")}};e.stop=function(){if(this.onExitFunc!=n){this.onExitFunc.call(this,{idx:o})}e.destroy_popover(o);e.unbind();t("div.bootstro-backdrop").remove()};e.go_to=function(r){if(this.onStepFunc!=n){this.onStepFunc.call(this,{idx:r})}e.destroy_popover(o);if(i!=0){p=get_popup(r);$el=get_element(r);$el.popover(p).popover("show");min=Math.min(t(".popover.in").offset().top,$el.offset().top);t("html,body").animate({scrollTop:min-20},"slow");$el.addClass("bootstro-highlight");o=r}};e.next=function(){if(o+1==i){if(this.onCompleteFunc!=n){this.onCompleteFunc.call(this,{idx:o})}}else e.go_to(o+1)};e.prev=function(){if(o==0){alert("At start of intros")}else e.go_to(o-1)};e.start=function(n,s){a=t.extend(true,{},u);t.extend(a,s||{});n=n||".bootstro";r=t(n);i=r.size();t('
').appendTo("body");e.bind();e.go_to(0)};e.bind=function(){e.unbind();t("html").on("click.bootstro",".bootstro-next-btn",function(t){e.next();t.preventDefault();return false});t("html").on("click.bootstro",".bootstro-prev-btn",function(t){e.prev();t.preventDefault();return false});t("html").on("click.bootstro",".bootstro-finish-btn",function(t){e.stop()});if(a.stopOnBackdropClick){t("html").on("click.bootstro","div.bootstro-backdrop",function(n){if(t(n.target).hasClass("bootstro-backdrop"))e.stop()})}t(document).on("keydown.bootstro",function(t){var n=t.keyCode?t.keyCode:t.which;if(n==39||n==40)e.next();else if(n==37||n==38)e.prev();else if(n==27&&a.stopOnEsc)e.stop()})};e.unbind=function(){t("html").unbind("click.bootstro");t(document).unbind("keydown.bootstro")};e.on_complete=function(e){if(Object.prototype.toString.call(e)=="[object Function]"){this.onCompleteFunc=e}};e.on_exit=function(e){if(Object.prototype.toString.call(e)=="[object Function]"){this.onExitFunc=e}};e.on_step=function(e){if(Object.prototype.toString.call(e)=="[object Function]"){this.onStepFunc=e}}})(window.bootstro=window.bootstro||{},jQuery)}) From 62545a397e07f029108f065000089fe3eaa709b3 Mon Sep 17 00:00:00 2001 From: Chance Ackley Date: Thu, 25 Apr 2013 13:32:06 -0400 Subject: [PATCH 5/9] Set finish button type to 'button' so that it doesn't cause a form submit. --- bootstro.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bootstro.js b/bootstro.js index 428874d..f3626cd 100644 --- a/bootstro.js +++ b/bootstro.js @@ -23,7 +23,7 @@ $(document).ready(function(){ var defaults = { nextButton : '', prevButton : '', - finishButton : '', + finishButton : '', stopOnBackdropClick : true, stopOnEsc : true }; From 56dec679e25a0f0e9c594ec70b62e46306ad362a Mon Sep 17 00:00:00 2001 From: crazirican Date: Wed, 22 May 2013 01:27:56 -0400 Subject: [PATCH 6/9] Fixed issue 22. Multiple backdrops. --- bootstro.js | 13 +++++++++---- bootstro.min.js | 9 ++++++++- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/bootstro.js b/bootstro.js index f3626cd..5d1482b 100644 --- a/bootstro.js +++ b/bootstro.js @@ -212,10 +212,15 @@ $(document).ready(function(){ selector = selector || '.bootstro'; $elements = $(selector); count = $elements.size(); - - $('
').appendTo('body'); - bootstro.bind(); - bootstro.go_to(0); + + if ($('div.bootstro-backdrop').length === 0) + { + // Prevents multiple copies + $('
').appendTo('body'); + bootstro.bind(); + bootstro.go_to(0); + } + }; //bind the nav buttons click event diff --git a/bootstro.min.js b/bootstro.min.js index d5f40ee..2d842b1 100644 --- a/bootstro.min.js +++ b/bootstro.min.js @@ -1 +1,8 @@ -$(document).ready(function(){(function(e,t,n){function h(e,t){i=r.size();e=e+"
";if(i!=1){if(t==0)e=e+a.nextButton;else if(t==i-1)e=e+a.prevButton;else e=e+a.nextButton+a.prevButton}e=e+"
";e=e+'
'+a.finishButton+"
";return e}var r;var i;var s=[];var o=null;var u={nextButton:'',prevButton:'',finishButton:'',stopOnBackdropClick:true,stopOnEsc:true};var a;var f;var l;var c;get_element=function(e){if(r.filter("[data-bootstro-step="+e+"]").size()>0)return r.filter("[data-bootstro-step="+e+"]");else{return r.eq(e)}};get_popup=function(e){var t={};$el=get_element(e);var n="";if(i>1){n=""+(e+1)+"/"+i+""}t.title=$el.attr("data-bootstro-title")||"";if(t.title!=""&&n!="")t.title=n+" - "+t.title;else if(t.title=="")t.title=n;t.content=$el.attr("data-bootstro-content")||"";t.content=h(t.content,e);t.placement=$el.attr("data-bootstro-placement")||"top";var r="";if($el.attr("data-bootstro-width")){t.width=$el.attr("data-bootstro-width");r=r+"width:"+$el.attr("data-bootstro-width")+";"}if($el.attr("data-bootstro-height")){t.height=$el.attr("data-bootstro-height");r=r+"height:"+$el.attr("data-bootstro-height")+";"}t.trigger="manual";t.html=$el.attr("data-bootstro-html")||"top";t.template='

'+"
";return t};e.destroy_popover=function(e){e=e||0;if(e!="all"){$el=get_element(e);$el.popover("destroy").removeClass("bootstro-highlight")}};e.stop=function(){if(this.onExitFunc!=n){this.onExitFunc.call(this,{idx:o})}e.destroy_popover(o);e.unbind();t("div.bootstro-backdrop").remove()};e.go_to=function(r){if(this.onStepFunc!=n){this.onStepFunc.call(this,{idx:r})}e.destroy_popover(o);if(i!=0){p=get_popup(r);$el=get_element(r);$el.popover(p).popover("show");min=Math.min(t(".popover.in").offset().top,$el.offset().top);t("html,body").animate({scrollTop:min-20},"slow");$el.addClass("bootstro-highlight");o=r}};e.next=function(){if(o+1==i){if(this.onCompleteFunc!=n){this.onCompleteFunc.call(this,{idx:o})}}else e.go_to(o+1)};e.prev=function(){if(o==0){alert("At start of intros")}else e.go_to(o-1)};e.start=function(n,s){a=t.extend(true,{},u);t.extend(a,s||{});n=n||".bootstro";r=t(n);i=r.size();t('
').appendTo("body");e.bind();e.go_to(0)};e.bind=function(){e.unbind();t("html").on("click.bootstro",".bootstro-next-btn",function(t){e.next();t.preventDefault();return false});t("html").on("click.bootstro",".bootstro-prev-btn",function(t){e.prev();t.preventDefault();return false});t("html").on("click.bootstro",".bootstro-finish-btn",function(t){e.stop()});if(a.stopOnBackdropClick){t("html").on("click.bootstro","div.bootstro-backdrop",function(n){if(t(n.target).hasClass("bootstro-backdrop"))e.stop()})}t(document).on("keydown.bootstro",function(t){var n=t.keyCode?t.keyCode:t.which;if(n==39||n==40)e.next();else if(n==37||n==38)e.prev();else if(n==27&&a.stopOnEsc)e.stop()})};e.unbind=function(){t("html").unbind("click.bootstro");t(document).unbind("keydown.bootstro")};e.on_complete=function(e){if(Object.prototype.toString.call(e)=="[object Function]"){this.onCompleteFunc=e}};e.on_exit=function(e){if(Object.prototype.toString.call(e)=="[object Function]"){this.onExitFunc=e}};e.on_step=function(e){if(Object.prototype.toString.call(e)=="[object Function]"){this.onStepFunc=e}}})(window.bootstro=window.bootstro||{},jQuery)}) +$(document).ready(function(){!function(t,o,n){function e(t,o){return r=i.size(),t+="
",1!=r&&(0==o?t+=s.nextButton:o==r-1?t+=s.prevButton:t=t+s.nextButton+s.prevButton),t+="
",t=t+'
'+s.finishButton+"
"}var i,r,s,l=null,a={nextButton:'',prevButton:'',finishButton:'',stopOnBackdropClick:!0,stopOnEsc:!0} +get_element=function(t){return i.filter("[data-bootstro-step="+t+"]").size()>0?i.filter("[data-bootstro-step="+t+"]"):i.eq(t)},get_popup=function(t){var o={} +$el=get_element(t) +var n="" +r>1&&(n=""+(t+1)+"/"+r+""),o.title=$el.attr("data-bootstro-title")||"",""!=o.title&&""!=n?o.title=n+" - "+o.title:""==o.title&&(o.title=n),o.content=$el.attr("data-bootstro-content")||"",o.content=e(o.content,t),o.placement=$el.attr("data-bootstro-placement")||"top" +var i="" +return $el.attr("data-bootstro-width")&&(o.width=$el.attr("data-bootstro-width"),i=i+"width:"+$el.attr("data-bootstro-width")+";"),$el.attr("data-bootstro-height")&&(o.height=$el.attr("data-bootstro-height"),i=i+"height:"+$el.attr("data-bootstro-height")+";"),o.trigger="manual",o.html=$el.attr("data-bootstro-html")||"top",o.template='

'+"
",o},t.destroy_popover=function(t){t=t||0,"all"!=t&&($el=get_element(t),$el.popover("destroy").removeClass("bootstro-highlight"))},t.stop=function(){this.onExitFunc!=n&&this.onExitFunc.call(this,{idx:l}),t.destroy_popover(l),t.unbind(),o("div.bootstro-backdrop").remove()},t.go_to=function(e){this.onStepFunc!=n&&this.onStepFunc.call(this,{idx:e}),t.destroy_popover(l),0!=r&&(p=get_popup(e),$el=get_element(e),$el.popover(p).popover("show"),min=Math.min(o(".popover.in").offset().top,$el.offset().top),o("html,body").animate({scrollTop:min-20},"slow"),$el.addClass("bootstro-highlight"),l=e)},t.next=function(){l+1==r?this.onCompleteFunc!=n&&this.onCompleteFunc.call(this,{idx:l}):t.go_to(l+1)},t.prev=function(){0==l?alert("At start of intros"):t.go_to(l-1)},t.start=function(n,e){s=o.extend(!0,{},a),o.extend(s,e||{}),n=n||".bootstro",i=o(n),r=i.size(),0===o("div.bootstro-backdrop").length&&(o('
').appendTo("body"),t.bind(),t.go_to(0))},t.bind=function(){t.unbind(),o("html").on("click.bootstro",".bootstro-next-btn",function(o){return t.next(),o.preventDefault(),!1}),o("html").on("click.bootstro",".bootstro-prev-btn",function(o){return t.prev(),o.preventDefault(),!1}),o("html").on("click.bootstro",".bootstro-finish-btn",function(){t.stop()}),s.stopOnBackdropClick&&o("html").on("click.bootstro","div.bootstro-backdrop",function(n){o(n.target).hasClass("bootstro-backdrop")&&t.stop()}),o(document).on("keydown.bootstro",function(o){var n=o.keyCode?o.keyCode:o.which +39==n||40==n?t.next():37==n||38==n?t.prev():27==n&&s.stopOnEsc&&t.stop()})},t.unbind=function(){o("html").unbind("click.bootstro"),o(document).unbind("keydown.bootstro")},t.on_complete=function(t){"[object Function]"==Object.prototype.toString.call(t)&&(this.onCompleteFunc=t)},t.on_exit=function(t){"[object Function]"==Object.prototype.toString.call(t)&&(this.onExitFunc=t)},t.on_step=function(t){"[object Function]"==Object.prototype.toString.call(t)&&(this.onStepFunc=t)}}(window.bootstro=window.bootstro||{},jQuery)}) \ No newline at end of file From e5608083e2fdb733e62674d42fae44f6160141ae Mon Sep 17 00:00:00 2001 From: Steve Tran Date: Mon, 27 May 2013 13:46:12 +0700 Subject: [PATCH 7/9] 1. fixed issue #2: Dont always scroll to top, if the element is entirely visible, do not scroll to top.\n 2. show data can be gotten from ajax to keep HTML clean \n 3. added a few more options: nextButtonText for a simpler nextButton,prevButtonText,finishButtonText. Those attributes can also be overridded by a specific element's corresponding attribute such as data-bootstro-nextButtonText.\n 4. Added a few function handlers in option: onComplete,onExit.\n 5. options.margin added to keep element nicely visible within a some top margin --- bootstro.js | 241 ++++++++++++++++++++++++++++++++++-------------- bootstro.min.js | 9 +- 2 files changed, 171 insertions(+), 79 deletions(-) diff --git a/bootstro.js b/bootstro.js index 5d1482b..638bfd4 100644 --- a/bootstro.js +++ b/bootstro.js @@ -6,10 +6,9 @@ * Revealing Module Pattern from * http://enterprisejquery.com/2010/10/how-good-c-habits-can-encourage-bad-javascript-habits-part-1/ * - * Bootstrap popover variable width workaround + * Bootstrap popover variable width * http://stackoverflow.com/questions/10028218/twitter-bootstrap-popovers-multiple-widths-and-other-css-properties - * - * Lisence : MIT . See accompanied LICENSE file. + * */ $(document).ready(function(){ @@ -21,37 +20,110 @@ $(document).ready(function(){ var activeIndex = null; //index of active item var defaults = { - nextButton : '', - prevButton : '', - finishButton : '', + nextButtonText : 'Next »', //will be wrapped with button as below + //nextButton : '', + prevButtonText : '« Prev', + //prevButton : '', + finishButtonText : ' Ok I got it, get back to the site', + //finishButton : '', stopOnBackdropClick : true, - stopOnEsc : true + stopOnEsc : true, + + //onComplete : function(params){} //params = {idx : activeIndex} + //onExit : function(params){} //params = {idx : activeIndex} + //onStep : function(params){} //params = {idx : activeIndex, direction : [next|prev]} + //url : String // ajaxed url to get show data from + + margin : 100, //if the currently shown element's margin is less than this value + // the element should be scrolled so that i can be viewed properly. This is useful + // for sites which have fixed top/bottom nav bar }; var settings; - var onCompleteFunc; - var onExitFunc; - var onStepFunc; //===================PRIVATE METHODS====================== + //http://stackoverflow.com/questions/487073/check-if-element-is-visible-after-scrolling + function is_entirely_visible($elem) + { + var docViewTop = $(window).scrollTop(); + var docViewBottom = docViewTop + $(window).height(); + + var elemTop = $elem.offset().top; + var elemBottom = elemTop + $elem.height(); + + return ((elemBottom >= docViewTop) && (elemTop <= docViewBottom) + && (elemBottom <= docViewBottom) && (elemTop >= docViewTop) ); + } + //add the nav buttons to the popover content; function add_nav_btn(content, i) { - count = $elements.size(); + var $el = get_element(i); + var nextButton, prevButton, finishButton; + content = content + "
"; + if ($el.attr('data-bootstro-nextButton')) + { + nextButton = $el.attr('data-bootstro-nextButton'); + } + else if ( $el.attr('data-bootstro-nextButtonText') ) + { + nextButton = ''; + } + else + { + if (typeof settings.nextButton != 'undefined' /*&& settings.nextButton != ''*/) + nextButton = settings.nextButton; + else + nextButton = ''; + } + + if ($el.attr('data-bootstro-prevButton')) + { + prevButton = $el.attr('data-bootstro-prevButton'); + } + else if ( $el.attr('data-bootstro-prevButtonText') ) + { + prevButton = ''; + } + else + { + if (typeof settings.prevButton != 'undefined' /*&& settings.prevButton != ''*/) + prevButton = settings.prevButton; + else + prevButton = ''; + } + + if ($el.attr('data-bootstro-finishButton')) + { + finishButton = $el.attr('data-bootstro-finishButton'); + } + else if ( $el.attr('data-bootstro-finishButtonText') ) + { + finishButton = ''; + } + else + { + if (typeof settings.finishButton != 'undefined' /*&& settings.finishButton != ''*/) + finishButton = settings.finishButton; + else + finishButton = ''; + } + + if (count != 1) { if (i == 0) - content = content + settings.nextButton; + content = content + nextButton; else if (i == count -1 ) - content = content + settings.prevButton; + content = content + prevButton; else - content = content + settings.nextButton + settings.prevButton + content = content + nextButton + prevButton } content = content + '
'; - content = content +'
' + settings.finishButton + '
'; + content = content +'
' + finishButton + '
'; return content; } @@ -79,7 +151,7 @@ $(document).ready(function(){ get_popup = function(i) { var p = {}; - $el = get_element(i); + var $el = get_element(i); //p.selector = selector; var t = ''; if (count > 1) @@ -123,10 +195,10 @@ $(document).ready(function(){ //destroy popover at stack index i bootstro.destroy_popover = function(i) { - i = i || 0; + var i = i || 0; if (i != 'all') { - $el = get_element(i);//$elements.eq(i); + var $el = get_element(i);//$elements.eq(i); $el.popover('destroy').removeClass('bootstro-highlight'); } /* @@ -143,83 +215,131 @@ $(document).ready(function(){ //destroy active popover and remove backdrop bootstro.stop = function() { - //call onExit callback function if needed - if (this.onExitFunc != undefined) { - this.onExitFunc.call(this, { idx : activeIndex }); - } bootstro.destroy_popover(activeIndex); bootstro.unbind(); $("div.bootstro-backdrop").remove(); + if (typeof settings.onExit == 'function') + settings.onExit.call(this,{idx : activeIndex}); }; - //go to the popover number idx starting from 0 bootstro.go_to = function(idx) { - //call onStep callback function if needed - if (this.onStepFunc != undefined) { - this.onStepFunc.call(this, { idx : idx }); - } //destroy current popover if any bootstro.destroy_popover(activeIndex); if (count != 0) { - p = get_popup(idx); - $el = get_element(idx); + var p = get_popup(idx); + var $el = get_element(idx); $el.popover(p).popover('show'); - min = Math.min($(".popover.in").offset().top, $el.offset().top); - $('html,body').animate({ - scrollTop: min - 20}, - 'slow'); + //scroll if neccessary + var docviewTop = $(window).scrollTop(); + var top = Math.min($(".popover.in").offset().top, $el.offset().top); + + //distance between docviewTop & min. + var topDistance = top - docviewTop; + + if (topDistance < settings.margin) //the element too up above + $('html,body').animate({ + scrollTop: top - settings.margin}, + 'slow'); + else if(!is_entirely_visible($(".popover.in")) || !is_entirely_visible($el)) + //the element is too down below + $('html,body').animate({ + scrollTop: top - settings.margin}, + 'slow'); // html $el.addClass('bootstro-highlight'); activeIndex = idx; } }; + bootstro.next = function() { if (activeIndex + 1 == count) { - //call onComplete callback function if needed - if (this.onCompleteFunc != undefined) { - this.onCompleteFunc.call(this, { idx : activeIndex }); - } + if (typeof settings.onComplete == 'function') + settings.onComplete.call(this, {idx : activeIndex});// } else + { bootstro.go_to(activeIndex + 1); + if (typeof settings.onStep == 'function') + settings.onStep.call(this, {idx : activeIndex, direction : 'next'});// + } }; bootstro.prev = function() { if (activeIndex == 0) { - alert('At start of intros'); + /* + if (typeof settings.onRewind == 'function') + settings.onRewind.call(this, {idx : activeIndex, direction : 'prev'});// + */ } - else + else + { bootstro.go_to(activeIndex -1); + if (typeof settings.onStep == 'function') + settings.onStep.call(this, {idx : activeIndex, direction : 'prev'});// + } }; - bootstro.start = function(selector, options) + bootstro._start = function(selector) { - - settings = $.extend(true, {}, defaults); //deep copy - //TODO: if options specifies a URL, get the intro text array from URL - $.extend(settings, options || {}); - selector = selector || '.bootstro'; + $elements = $(selector); count = $elements.size(); - - if ($('div.bootstro-backdrop').length === 0) + if (count > 0 && $('div.bootstro-backdrop').length === 0) { // Prevents multiple copies $('
').appendTo('body'); bootstro.bind(); bootstro.go_to(0); - } + } + }; + + bootstro.start = function(selector, options) + { + settings = $.extend(true, {}, defaults); //deep copy + $.extend(settings, options || {}); + //if options specifies a URL, get the intro configuration from URL via ajax + if (typeof settings.url != 'undefined') + { + //get config from ajax + $.ajax({ + url : settings.url, + success : function(data){ + if (data.success) + { + //result is an array of {selector:'','title':'','width', ...} + var popover = data.result; + //console.log(popover); + var selectorArr = []; + $.each(popover, function(t,e){ + //only deal with the visible element + //build the selector + $.each(e, function(j, attr){ + $(e.selector).attr('data-bootstro-' + j, attr); + }); + if ($(e.selector).is(":visible")) + selectorArr.push(e.selector); + }); + selector = selectorArr.join(","); + bootstro._start(selector); + } + } + }); + } + else + { + bootstro._start(selector); + } }; @@ -269,28 +389,7 @@ $(document).ready(function(){ { $("html").unbind('click.bootstro'); $(document).unbind('keydown.bootstro'); - }; + } - bootstro.on_complete = function(callbackFunction) - { - if (Object.prototype.toString.call(callbackFunction) == '[object Function]') { - this.onCompleteFunc = callbackFunction; - } - }; - - bootstro.on_exit = function(callbackFunction) - { - if (Object.prototype.toString.call(callbackFunction) == '[object Function]') { - this.onExitFunc = callbackFunction; - } - }; - - bootstro.on_step = function(callbackFunction) - { - if (Object.prototype.toString.call(callbackFunction) == '[object Function]') { - this.onStepFunc = callbackFunction; - } - }; - }( window.bootstro = window.bootstro || {}, jQuery )); -}); +}); \ No newline at end of file diff --git a/bootstro.min.js b/bootstro.min.js index 2d842b1..c6861c0 100644 --- a/bootstro.min.js +++ b/bootstro.min.js @@ -1,8 +1 @@ -$(document).ready(function(){!function(t,o,n){function e(t,o){return r=i.size(),t+="
",1!=r&&(0==o?t+=s.nextButton:o==r-1?t+=s.prevButton:t=t+s.nextButton+s.prevButton),t+="
",t=t+'
'+s.finishButton+"
"}var i,r,s,l=null,a={nextButton:'',prevButton:'',finishButton:'',stopOnBackdropClick:!0,stopOnEsc:!0} -get_element=function(t){return i.filter("[data-bootstro-step="+t+"]").size()>0?i.filter("[data-bootstro-step="+t+"]"):i.eq(t)},get_popup=function(t){var o={} -$el=get_element(t) -var n="" -r>1&&(n=""+(t+1)+"/"+r+""),o.title=$el.attr("data-bootstro-title")||"",""!=o.title&&""!=n?o.title=n+" - "+o.title:""==o.title&&(o.title=n),o.content=$el.attr("data-bootstro-content")||"",o.content=e(o.content,t),o.placement=$el.attr("data-bootstro-placement")||"top" -var i="" -return $el.attr("data-bootstro-width")&&(o.width=$el.attr("data-bootstro-width"),i=i+"width:"+$el.attr("data-bootstro-width")+";"),$el.attr("data-bootstro-height")&&(o.height=$el.attr("data-bootstro-height"),i=i+"height:"+$el.attr("data-bootstro-height")+";"),o.trigger="manual",o.html=$el.attr("data-bootstro-html")||"top",o.template='

'+"
",o},t.destroy_popover=function(t){t=t||0,"all"!=t&&($el=get_element(t),$el.popover("destroy").removeClass("bootstro-highlight"))},t.stop=function(){this.onExitFunc!=n&&this.onExitFunc.call(this,{idx:l}),t.destroy_popover(l),t.unbind(),o("div.bootstro-backdrop").remove()},t.go_to=function(e){this.onStepFunc!=n&&this.onStepFunc.call(this,{idx:e}),t.destroy_popover(l),0!=r&&(p=get_popup(e),$el=get_element(e),$el.popover(p).popover("show"),min=Math.min(o(".popover.in").offset().top,$el.offset().top),o("html,body").animate({scrollTop:min-20},"slow"),$el.addClass("bootstro-highlight"),l=e)},t.next=function(){l+1==r?this.onCompleteFunc!=n&&this.onCompleteFunc.call(this,{idx:l}):t.go_to(l+1)},t.prev=function(){0==l?alert("At start of intros"):t.go_to(l-1)},t.start=function(n,e){s=o.extend(!0,{},a),o.extend(s,e||{}),n=n||".bootstro",i=o(n),r=i.size(),0===o("div.bootstro-backdrop").length&&(o('
').appendTo("body"),t.bind(),t.go_to(0))},t.bind=function(){t.unbind(),o("html").on("click.bootstro",".bootstro-next-btn",function(o){return t.next(),o.preventDefault(),!1}),o("html").on("click.bootstro",".bootstro-prev-btn",function(o){return t.prev(),o.preventDefault(),!1}),o("html").on("click.bootstro",".bootstro-finish-btn",function(){t.stop()}),s.stopOnBackdropClick&&o("html").on("click.bootstro","div.bootstro-backdrop",function(n){o(n.target).hasClass("bootstro-backdrop")&&t.stop()}),o(document).on("keydown.bootstro",function(o){var n=o.keyCode?o.keyCode:o.which -39==n||40==n?t.next():37==n||38==n?t.prev():27==n&&s.stopOnEsc&&t.stop()})},t.unbind=function(){o("html").unbind("click.bootstro"),o(document).unbind("keydown.bootstro")},t.on_complete=function(t){"[object Function]"==Object.prototype.toString.call(t)&&(this.onCompleteFunc=t)},t.on_exit=function(t){"[object Function]"==Object.prototype.toString.call(t)&&(this.onExitFunc=t)},t.on_step=function(t){"[object Function]"==Object.prototype.toString.call(t)&&(this.onStepFunc=t)}}(window.bootstro=window.bootstro||{},jQuery)}) \ No newline at end of file +$(document).ready(function(){(function(e,t,n){function f(e){var n=t(window).scrollTop();var r=n+t(window).height();var i=e.offset().top;var s=i+e.height();return s>=n&&i<=r&&s<=r&&i>=n}function l(e,t){var n=get_element(t);var r,s,o;e=e+"
";if(n.attr("data-bootstro-nextButton")){r=n.attr("data-bootstro-nextButton")}else if(n.attr("data-bootstro-nextButtonText")){r='"}else{if(typeof a.nextButton!="undefined")r=a.nextButton;else r='"}if(n.attr("data-bootstro-prevButton")){s=n.attr("data-bootstro-prevButton")}else if(n.attr("data-bootstro-prevButtonText")){s='"}else{if(typeof a.prevButton!="undefined")s=a.prevButton;else s='"}if(n.attr("data-bootstro-finishButton")){o=n.attr("data-bootstro-finishButton")}else if(n.attr("data-bootstro-finishButtonText")){o='"}else{if(typeof a.finishButton!="undefined")o=a.finishButton;else o='"}if(i!=1){if(t==0)e=e+r;else if(t==i-1)e=e+s;else e=e+r+s}e=e+"
";e=e+'
'+o+"
";return e}var r;var i;var s=[];var o=null;var u={nextButtonText:"Next »",prevButtonText:"« Prev",finishButtonText:' Ok I got it, get back to the site',stopOnBackdropClick:true,stopOnEsc:true,margin:100};var a;get_element=function(e){if(r.filter("[data-bootstro-step="+e+"]").size()>0)return r.filter("[data-bootstro-step="+e+"]");else{return r.eq(e)}};get_popup=function(e){var t={};var n=get_element(e);var r="";if(i>1){r=""+(e+1)+"/"+i+""}t.title=n.attr("data-bootstro-title")||"";if(t.title!=""&&r!="")t.title=r+" - "+t.title;else if(t.title=="")t.title=r;t.content=n.attr("data-bootstro-content")||"";t.content=l(t.content,e);t.placement=n.attr("data-bootstro-placement")||"top";var s="";if(n.attr("data-bootstro-width")){t.width=n.attr("data-bootstro-width");s=s+"width:"+n.attr("data-bootstro-width")+";"}if(n.attr("data-bootstro-height")){t.height=n.attr("data-bootstro-height");s=s+"height:"+n.attr("data-bootstro-height")+";"}t.trigger="manual";t.html=n.attr("data-bootstro-html")||"top";t.template='

'+"
";return t};e.destroy_popover=function(e){var e=e||0;if(e!="all"){var t=get_element(e);t.popover("destroy").removeClass("bootstro-highlight")}};e.stop=function(){e.destroy_popover(o);e.unbind();t("div.bootstro-backdrop").remove();if(typeof a.onExit=="function")a.onExit.call(this,{idx:o})};e.go_to=function(n){e.destroy_popover(o);if(i!=0){var r=get_popup(n);var s=get_element(n);s.popover(r).popover("show");var u=t(window).scrollTop();var l=Math.min(t(".popover.in").offset().top,s.offset().top);var c=l-u;if(c0&&t("div.bootstro-backdrop").length===0){t('
').appendTo("body");e.bind();e.go_to(0)}};e.start=function(n,r){a=t.extend(true,{},u);t.extend(a,r||{});if(typeof a.url!="undefined"){t.ajax({url:a.url,success:function(r){if(r.success){var i=r.result;var s=[];t.each(i,function(e,n){t.each(n,function(e,r){t(n.selector).attr("data-bootstro-"+e,r)});if(t(n.selector).is(":visible"))s.push(n.selector)});n=s.join(",");e._start(n)}}})}else{e._start(n)}};e.bind=function(){e.unbind();t("html").on("click.bootstro",".bootstro-next-btn",function(t){e.next();t.preventDefault();return false});t("html").on("click.bootstro",".bootstro-prev-btn",function(t){e.prev();t.preventDefault();return false});t("html").on("click.bootstro",".bootstro-finish-btn",function(t){e.stop()});if(a.stopOnBackdropClick){t("html").on("click.bootstro","div.bootstro-backdrop",function(n){if(t(n.target).hasClass("bootstro-backdrop"))e.stop()})}t(document).on("keydown.bootstro",function(t){var n=t.keyCode?t.keyCode:t.which;if(n==39||n==40)e.next();else if(n==37||n==38)e.prev();else if(n==27&&a.stopOnEsc)e.stop()})};e.unbind=function(){t("html").unbind("click.bootstro");t(document).unbind("keydown.bootstro")}})(window.bootstro=window.bootstro||{},jQuery)}) From 221af3f1d7a40c5b8157a805ed7df1a13ebf1f41 Mon Sep 17 00:00:00 2001 From: Steve Tran Date: Mon, 27 May 2013 13:47:20 +0700 Subject: [PATCH 8/9] added bootstro.json for a sample ajax return from server --- bootstro.json | 1 + 1 file changed, 1 insertion(+) create mode 100644 bootstro.json diff --git a/bootstro.json b/bootstro.json new file mode 100644 index 0000000..98cdd92 --- /dev/null +++ b/bootstro.json @@ -0,0 +1 @@ +{"success":true,"result":[{"selector":"#demo_stopOn","title":"Ajaxed title from server","content":"I was found because I have selector=#demo_stopOn","width":"400px","placement":"right"},{"selector":"#demo_ajax","title":"Ajaxed Title 2","content":"I was found because I have selector=#demo_ajax","width":"400px","placement":"right"}]} From ec1e022aa83c676d313e1df2b0375cd5e745295a Mon Sep 17 00:00:00 2001 From: Sri Vishnu Totakura Date: Sat, 8 Jun 2013 16:23:13 +0530 Subject: [PATCH 9/9] fixing issue with steps when a intermediate step is missing in the DOM next popup with check for next available index rather than just incrementing going to previous popup will also now check for the available previous index rather than just decrementing 1 variable name changed to make it understandable removed unwanted gitignore --- bootstro.js | 61 ++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 53 insertions(+), 8 deletions(-) diff --git a/bootstro.js b/bootstro.js index 638bfd4..94c42be 100644 --- a/bootstro.js +++ b/bootstro.js @@ -18,6 +18,9 @@ $(document).ready(function(){ var count; var popovers = []; //contains array of the popovers data var activeIndex = null; //index of active item + var defaultOrder = true; + // if true the DOM order is followed. it is changed to false when step index is given for atleast one element. + // refer line #322 var defaults = { nextButtonText : 'Next »', //will be wrapped with button as below @@ -126,6 +129,32 @@ $(document).ready(function(){ content = content +'
' + finishButton + '
'; return content; } + + nextIndex = function(indexToTry){ + closestIndex = null + // loop and find the next available value less than or equal to the indexToTry + $.each(indexes, function(){ + if (parseInt(this) >= parseInt(indexToTry)) { + closestIndex = this; + return false; + } + }); + return closestIndex; + } + + prevIndex = function(indexToTry){ + closestIndex = null + reverseIndexes = $.makeArray(indexes).reverse() + // loop and find the previous available value less than or equal to the indexToTry + $.each(reverseIndexes, function(){ + if (parseInt(this) <= parseInt(indexToTry)) { + closestIndex = this; + return false; + } + }); + return closestIndex; + } + //get the element to intro at stack i get_element = function(i) @@ -147,6 +176,10 @@ $(document).ready(function(){ */ } } + + getStepCount = function(i){ + return defaultOrder ? i : $.inArray(parseInt(i), indexes) + } get_popup = function(i) { @@ -156,7 +189,7 @@ $(document).ready(function(){ var t = ''; if (count > 1) { - t = "" + (i +1) + "/" + count + ""; + t = "" + (getStepCount(i)+1) + "/" + count + ""; } p.title = $el.attr('data-bootstro-title') || ''; if (p.title != '' && t != '') @@ -219,7 +252,7 @@ $(document).ready(function(){ bootstro.unbind(); $("div.bootstro-backdrop").remove(); if (typeof settings.onExit == 'function') - settings.onExit.call(this,{idx : activeIndex}); + settings.onExit.call(this,{idx : getStepCount(activeIndex)}); }; //go to the popover number idx starting from 0 @@ -259,14 +292,16 @@ $(document).ready(function(){ bootstro.next = function() { - if (activeIndex + 1 == count) + indexToEnd = defaultOrder ? count-1 : indexes.get(-1) + if (activeIndex == indexToEnd) { if (typeof settings.onComplete == 'function') - settings.onComplete.call(this, {idx : activeIndex});// + settings.onComplete.call(this, {idx : getStepCount(activeIndex)});// } else { - bootstro.go_to(activeIndex + 1); + // bootstro.go_to(activeIndex + 1); + defaultOrder ? bootstro.go_to(activeIndex + 1) : bootstro.go_to(nextIndex(activeIndex + 1)); if (typeof settings.onStep == 'function') settings.onStep.call(this, {idx : activeIndex, direction : 'next'});// } @@ -274,7 +309,8 @@ $(document).ready(function(){ bootstro.prev = function() { - if (activeIndex == 0) + indexToEnd = defaultOrder ? 0 : indexes.get(0) + if (activeIndex == indexToEnd) { /* if (typeof settings.onRewind == 'function') @@ -283,7 +319,7 @@ $(document).ready(function(){ } else { - bootstro.go_to(activeIndex -1); + defaultOrder ? bootstro.go_to(activeIndex - 1) : bootstro.go_to(prevIndex(activeIndex - 1)); if (typeof settings.onStep == 'function') settings.onStep.call(this, {idx : activeIndex, direction : 'prev'});// } @@ -300,7 +336,16 @@ $(document).ready(function(){ // Prevents multiple copies $('
').appendTo('body'); bootstro.bind(); - bootstro.go_to(0); + + indexes = $elements.map(function(){ return parseInt($(this).attr('data-bootstro-step')) }) + defaultOrder = $.grep(indexes, function(x){ return !(isNaN(x)) }).length == 0 ? true : false + // set defaultOrder to true inorder to follow DOM order when all the elements are not provided with data-bootstro-step attr + + if (!defaultOrder) + indexes = indexes.sort(function(a, b){ return a - b }) + + defaultOrder ? bootstro.go_to(0) : bootstro.go_to(nextIndex(0)); + // bootstro.go_to(0); } };