diff --git a/bootstro.js b/bootstro.js
index b95ee02..94c42be 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(){
@@ -19,38 +18,143 @@ $(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 = {
- nextButton : 'Next » ',
- prevButton : '« Prev ',
- finishButton : ' Ok I got it, get back to the site ',
+ nextButtonText : 'Next »', //will be wrapped with button as below
+ //nextButton : 'Next » ',
+ prevButtonText : '« Prev',
+ //prevButton : '« Prev ',
+ finishButtonText : ' Ok I got it, get back to the site',
+ //finishButton : ' Ok I got it, get back to the site ',
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;
//===================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 = '' + $el.attr('data-bootstro-nextButtonText') + ' ';
+ }
+ else
+ {
+ if (typeof settings.nextButton != 'undefined' /*&& settings.nextButton != ''*/)
+ nextButton = settings.nextButton;
+ else
+ nextButton = '' + settings.nextButtonText + ' ';
+ }
+
+ if ($el.attr('data-bootstro-prevButton'))
+ {
+ prevButton = $el.attr('data-bootstro-prevButton');
+ }
+ else if ( $el.attr('data-bootstro-prevButtonText') )
+ {
+ prevButton = '' + $el.attr('data-bootstro-prevButtonText') + ' ';
+ }
+ else
+ {
+ if (typeof settings.prevButton != 'undefined' /*&& settings.prevButton != ''*/)
+ prevButton = settings.prevButton;
+ else
+ prevButton = '' + settings.prevButtonText + ' ';
+ }
+
+ if ($el.attr('data-bootstro-finishButton'))
+ {
+ finishButton = $el.attr('data-bootstro-finishButton');
+ }
+ else if ( $el.attr('data-bootstro-finishButtonText') )
+ {
+ finishButton = '' + $el.attr('data-bootstro-finishButtonText') + ' ';
+ }
+ else
+ {
+ if (typeof settings.finishButton != 'undefined' /*&& settings.finishButton != ''*/)
+ finishButton = settings.finishButton;
+ else
+ finishButton = '' + settings.finishButtonText + ' ';
+ }
+
+
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;
}
+
+ 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)
@@ -72,16 +176,20 @@ $(document).ready(function(){
*/
}
}
+
+ getStepCount = function(i){
+ return defaultOrder ? i : $.inArray(parseInt(i), indexes)
+ }
get_popup = function(i)
{
var p = {};
- $el = get_element(i);
+ var $el = get_element(i);
//p.selector = selector;
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 != '')
@@ -120,10 +228,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,9 +251,10 @@ $(document).ready(function(){
bootstro.destroy_popover(activeIndex);
bootstro.unbind();
$("div.bootstro-backdrop").remove();
+ if (typeof settings.onExit == 'function')
+ settings.onExit.call(this,{idx : getStepCount(activeIndex)});
};
-
//go to the popover number idx starting from 0
bootstro.go_to = function(idx)
{
@@ -153,55 +262,130 @@ $(document).ready(function(){
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)
+ indexToEnd = defaultOrder ? count-1 : indexes.get(-1)
+ if (activeIndex == indexToEnd)
{
- alert('End of introduction');
+ if (typeof settings.onComplete == 'function')
+ 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'});//
+ }
};
bootstro.prev = function()
{
- if (activeIndex == 0)
+ indexToEnd = defaultOrder ? 0 : indexes.get(0)
+ if (activeIndex == indexToEnd)
{
- alert('At start of intros');
+ /*
+ if (typeof settings.onRewind == 'function')
+ settings.onRewind.call(this, {idx : activeIndex, direction : 'prev'});//
+ */
+ }
+ else
+ {
+ 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'});//
+ }
+ };
+
+ bootstro._start = function(selector)
+ {
+ selector = selector || '.bootstro';
+
+ $elements = $(selector);
+ count = $elements.size();
+ if (count > 0 && $('div.bootstro-backdrop').length === 0)
+ {
+ // Prevents multiple copies
+ $('
').appendTo('body');
+ bootstro.bind();
+
+ 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);
}
- else
- bootstro.go_to(activeIndex -1);
};
bootstro.start = function(selector, options)
{
-
settings = $.extend(true, {}, defaults); //deep copy
- //TODO: if options specifies a URL, get the intro text array from URL
$.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);
+ }
- selector = selector || '.bootstro';
- $elements = $(selector);
- count = $elements.size();
-
- $('
').appendTo('body');
- bootstro.bind();
- bootstro.go_to(0);
};
//bind the nav buttons click event
@@ -253,4 +437,4 @@ $(document).ready(function(){
}
}( window.bootstro = window.bootstro || {}, jQuery ));
-});
+});
\ No newline at end of file
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"}]}
diff --git a/bootstro.min.js b/bootstro.min.js
index e1c308c..c6861c0 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:'Next » ',prevButton:'« Prev ',finishButton:' Ok I got it, get back to the site ',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 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=''+n.attr("data-bootstro-nextButtonText")+" "}else{if(typeof a.nextButton!="undefined")r=a.nextButton;else r=''+a.nextButtonText+" "}if(n.attr("data-bootstro-prevButton")){s=n.attr("data-bootstro-prevButton")}else if(n.attr("data-bootstro-prevButtonText")){s=''+n.attr("data-bootstro-prevButtonText")+" "}else{if(typeof a.prevButton!="undefined")s=a.prevButton;else s=''+a.prevButtonText+" "}if(n.attr("data-bootstro-finishButton")){o=n.attr("data-bootstro-finishButton")}else if(n.attr("data-bootstro-finishButtonText")){o=''+n.attr("data-bootstro-finishButtonText")+" "}else{if(typeof a.finishButton!="undefined")o=a.finishButton;else o=''+a.finishButtonText+" "}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)})