Skip to content

Commit e560808

Browse files
Steve Trantsrivishnu
Steve Tran
authored andcommitted
1. fixed issue clu3#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
1 parent 56dec67 commit e560808

File tree

2 files changed

+171
-79
lines changed

2 files changed

+171
-79
lines changed

bootstro.js

+170-71
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,9 @@
66
* Revealing Module Pattern from
77
* http://enterprisejquery.com/2010/10/how-good-c-habits-can-encourage-bad-javascript-habits-part-1/
88
*
9-
* Bootstrap popover variable width workaround
9+
* Bootstrap popover variable width
1010
* http://stackoverflow.com/questions/10028218/twitter-bootstrap-popovers-multiple-widths-and-other-css-properties
11-
*
12-
* Lisence : MIT . See accompanied LICENSE file.
11+
*
1312
*/
1413

1514
$(document).ready(function(){
@@ -21,37 +20,110 @@ $(document).ready(function(){
2120
var activeIndex = null; //index of active item
2221

2322
var defaults = {
24-
nextButton : '<button class="btn btn-primary btn-mini bootstro-next-btn">Next &raquo;</button>',
25-
prevButton : '<button class="btn btn-primary btn-mini bootstro-prev-btn">&laquo; Prev</button>',
26-
finishButton : '<button class="btn btn-mini btn-success bootstro-finish-btn" type="button"><i class="icon-ok"></i> Ok I got it, get back to the site</button>',
23+
nextButtonText : 'Next &raquo;', //will be wrapped with button as below
24+
//nextButton : '<button class="btn btn-primary btn-mini bootstro-next-btn">Next &raquo;</button>',
25+
prevButtonText : '&laquo; Prev',
26+
//prevButton : '<button class="btn btn-primary btn-mini bootstro-prev-btn">&laquo; Prev</button>',
27+
finishButtonText : '<i class="icon-ok"></i> Ok I got it, get back to the site',
28+
//finishButton : '<button class="btn btn-mini btn-success bootstro-finish-btn"><i class="icon-ok"></i> Ok I got it, get back to the site</button>',
2729
stopOnBackdropClick : true,
28-
stopOnEsc : true
30+
stopOnEsc : true,
31+
32+
//onComplete : function(params){} //params = {idx : activeIndex}
33+
//onExit : function(params){} //params = {idx : activeIndex}
34+
//onStep : function(params){} //params = {idx : activeIndex, direction : [next|prev]}
35+
//url : String // ajaxed url to get show data from
36+
37+
margin : 100, //if the currently shown element's margin is less than this value
38+
// the element should be scrolled so that i can be viewed properly. This is useful
39+
// for sites which have fixed top/bottom nav bar
2940
};
3041
var settings;
31-
var onCompleteFunc;
32-
var onExitFunc;
33-
var onStepFunc;
3442

3543

3644
//===================PRIVATE METHODS======================
45+
//http://stackoverflow.com/questions/487073/check-if-element-is-visible-after-scrolling
46+
function is_entirely_visible($elem)
47+
{
48+
var docViewTop = $(window).scrollTop();
49+
var docViewBottom = docViewTop + $(window).height();
50+
51+
var elemTop = $elem.offset().top;
52+
var elemBottom = elemTop + $elem.height();
53+
54+
return ((elemBottom >= docViewTop) && (elemTop <= docViewBottom)
55+
&& (elemBottom <= docViewBottom) && (elemTop >= docViewTop) );
56+
}
57+
3758
//add the nav buttons to the popover content;
3859

3960
function add_nav_btn(content, i)
4061
{
41-
count = $elements.size();
62+
var $el = get_element(i);
63+
var nextButton, prevButton, finishButton;
64+
4265
content = content + "<div class='bootstro-nav-wrapper'>";
66+
if ($el.attr('data-bootstro-nextButton'))
67+
{
68+
nextButton = $el.attr('data-bootstro-nextButton');
69+
}
70+
else if ( $el.attr('data-bootstro-nextButtonText') )
71+
{
72+
nextButton = '<button class="btn btn-primary btn-mini bootstro-next-btn">' + $el.attr('data-bootstro-nextButtonText') + '</button>';
73+
}
74+
else
75+
{
76+
if (typeof settings.nextButton != 'undefined' /*&& settings.nextButton != ''*/)
77+
nextButton = settings.nextButton;
78+
else
79+
nextButton = '<button class="btn btn-primary btn-mini bootstro-next-btn">' + settings.nextButtonText + '</button>';
80+
}
81+
82+
if ($el.attr('data-bootstro-prevButton'))
83+
{
84+
prevButton = $el.attr('data-bootstro-prevButton');
85+
}
86+
else if ( $el.attr('data-bootstro-prevButtonText') )
87+
{
88+
prevButton = '<button class="btn btn-primary btn-mini bootstro-prev-btn">' + $el.attr('data-bootstro-prevButtonText') + '</button>';
89+
}
90+
else
91+
{
92+
if (typeof settings.prevButton != 'undefined' /*&& settings.prevButton != ''*/)
93+
prevButton = settings.prevButton;
94+
else
95+
prevButton = '<button class="btn btn-primary btn-mini bootstro-prev-btn">' + settings.prevButtonText + '</button>';
96+
}
97+
98+
if ($el.attr('data-bootstro-finishButton'))
99+
{
100+
finishButton = $el.attr('data-bootstro-finishButton');
101+
}
102+
else if ( $el.attr('data-bootstro-finishButtonText') )
103+
{
104+
finishButton = '<button class="btn btn-primary btn-mini bootstro-finish-btn">' + $el.attr('data-bootstro-finishButtonText') + '</button>';
105+
}
106+
else
107+
{
108+
if (typeof settings.finishButton != 'undefined' /*&& settings.finishButton != ''*/)
109+
finishButton = settings.finishButton;
110+
else
111+
finishButton = '<button class="btn btn-primary btn-mini bootstro-finish-btn">' + settings.finishButtonText + '</button>';
112+
}
113+
114+
43115
if (count != 1)
44116
{
45117
if (i == 0)
46-
content = content + settings.nextButton;
118+
content = content + nextButton;
47119
else if (i == count -1 )
48-
content = content + settings.prevButton;
120+
content = content + prevButton;
49121
else
50-
content = content + settings.nextButton + settings.prevButton
122+
content = content + nextButton + prevButton
51123
}
52124
content = content + '</div>';
53125

54-
content = content +'<div class="bootstro-finish-btn-wrapper">' + settings.finishButton + '</div>';
126+
content = content +'<div class="bootstro-finish-btn-wrapper">' + finishButton + '</div>';
55127
return content;
56128
}
57129

@@ -79,7 +151,7 @@ $(document).ready(function(){
79151
get_popup = function(i)
80152
{
81153
var p = {};
82-
$el = get_element(i);
154+
var $el = get_element(i);
83155
//p.selector = selector;
84156
var t = '';
85157
if (count > 1)
@@ -123,10 +195,10 @@ $(document).ready(function(){
123195
//destroy popover at stack index i
124196
bootstro.destroy_popover = function(i)
125197
{
126-
i = i || 0;
198+
var i = i || 0;
127199
if (i != 'all')
128200
{
129-
$el = get_element(i);//$elements.eq(i);
201+
var $el = get_element(i);//$elements.eq(i);
130202
$el.popover('destroy').removeClass('bootstro-highlight');
131203
}
132204
/*
@@ -143,83 +215,131 @@ $(document).ready(function(){
143215
//destroy active popover and remove backdrop
144216
bootstro.stop = function()
145217
{
146-
//call onExit callback function if needed
147-
if (this.onExitFunc != undefined) {
148-
this.onExitFunc.call(this, { idx : activeIndex });
149-
}
150218
bootstro.destroy_popover(activeIndex);
151219
bootstro.unbind();
152220
$("div.bootstro-backdrop").remove();
221+
if (typeof settings.onExit == 'function')
222+
settings.onExit.call(this,{idx : activeIndex});
153223
};
154224

155-
156225
//go to the popover number idx starting from 0
157226
bootstro.go_to = function(idx)
158227
{
159-
//call onStep callback function if needed
160-
if (this.onStepFunc != undefined) {
161-
this.onStepFunc.call(this, { idx : idx });
162-
}
163228
//destroy current popover if any
164229
bootstro.destroy_popover(activeIndex);
165230
if (count != 0)
166231
{
167-
p = get_popup(idx);
168-
$el = get_element(idx);
232+
var p = get_popup(idx);
233+
var $el = get_element(idx);
169234

170235
$el.popover(p).popover('show');
171236

172-
min = Math.min($(".popover.in").offset().top, $el.offset().top);
173-
$('html,body').animate({
174-
scrollTop: min - 20},
175-
'slow');
237+
//scroll if neccessary
238+
var docviewTop = $(window).scrollTop();
239+
var top = Math.min($(".popover.in").offset().top, $el.offset().top);
240+
241+
//distance between docviewTop & min.
242+
var topDistance = top - docviewTop;
243+
244+
if (topDistance < settings.margin) //the element too up above
245+
$('html,body').animate({
246+
scrollTop: top - settings.margin},
247+
'slow');
248+
else if(!is_entirely_visible($(".popover.in")) || !is_entirely_visible($el))
249+
//the element is too down below
250+
$('html,body').animate({
251+
scrollTop: top - settings.margin},
252+
'slow');
176253
// html
177254

178255
$el.addClass('bootstro-highlight');
179256
activeIndex = idx;
180257
}
181258
};
259+
182260
bootstro.next = function()
183261
{
184262
if (activeIndex + 1 == count)
185263
{
186-
//call onComplete callback function if needed
187-
if (this.onCompleteFunc != undefined) {
188-
this.onCompleteFunc.call(this, { idx : activeIndex });
189-
}
264+
if (typeof settings.onComplete == 'function')
265+
settings.onComplete.call(this, {idx : activeIndex});//
190266
}
191267
else
268+
{
192269
bootstro.go_to(activeIndex + 1);
270+
if (typeof settings.onStep == 'function')
271+
settings.onStep.call(this, {idx : activeIndex, direction : 'next'});//
272+
}
193273
};
194274

195275
bootstro.prev = function()
196276
{
197277
if (activeIndex == 0)
198278
{
199-
alert('At start of intros');
279+
/*
280+
if (typeof settings.onRewind == 'function')
281+
settings.onRewind.call(this, {idx : activeIndex, direction : 'prev'});//
282+
*/
200283
}
201-
else
284+
else
285+
{
202286
bootstro.go_to(activeIndex -1);
287+
if (typeof settings.onStep == 'function')
288+
settings.onStep.call(this, {idx : activeIndex, direction : 'prev'});//
289+
}
203290
};
204291

205-
bootstro.start = function(selector, options)
292+
bootstro._start = function(selector)
206293
{
207-
208-
settings = $.extend(true, {}, defaults); //deep copy
209-
//TODO: if options specifies a URL, get the intro text array from URL
210-
$.extend(settings, options || {});
211-
212294
selector = selector || '.bootstro';
295+
213296
$elements = $(selector);
214297
count = $elements.size();
215-
216-
if ($('div.bootstro-backdrop').length === 0)
298+
if (count > 0 && $('div.bootstro-backdrop').length === 0)
217299
{
218300
// Prevents multiple copies
219301
$('<div class="bootstro-backdrop"></div>').appendTo('body');
220302
bootstro.bind();
221303
bootstro.go_to(0);
222-
}
304+
}
305+
};
306+
307+
bootstro.start = function(selector, options)
308+
{
309+
settings = $.extend(true, {}, defaults); //deep copy
310+
$.extend(settings, options || {});
311+
//if options specifies a URL, get the intro configuration from URL via ajax
312+
if (typeof settings.url != 'undefined')
313+
{
314+
//get config from ajax
315+
$.ajax({
316+
url : settings.url,
317+
success : function(data){
318+
if (data.success)
319+
{
320+
//result is an array of {selector:'','title':'','width', ...}
321+
var popover = data.result;
322+
//console.log(popover);
323+
var selectorArr = [];
324+
$.each(popover, function(t,e){
325+
//only deal with the visible element
326+
//build the selector
327+
$.each(e, function(j, attr){
328+
$(e.selector).attr('data-bootstro-' + j, attr);
329+
});
330+
if ($(e.selector).is(":visible"))
331+
selectorArr.push(e.selector);
332+
});
333+
selector = selectorArr.join(",");
334+
bootstro._start(selector);
335+
}
336+
}
337+
});
338+
}
339+
else
340+
{
341+
bootstro._start(selector);
342+
}
223343

224344
};
225345

@@ -269,28 +389,7 @@ $(document).ready(function(){
269389
{
270390
$("html").unbind('click.bootstro');
271391
$(document).unbind('keydown.bootstro');
272-
};
392+
}
273393

274-
bootstro.on_complete = function(callbackFunction)
275-
{
276-
if (Object.prototype.toString.call(callbackFunction) == '[object Function]') {
277-
this.onCompleteFunc = callbackFunction;
278-
}
279-
};
280-
281-
bootstro.on_exit = function(callbackFunction)
282-
{
283-
if (Object.prototype.toString.call(callbackFunction) == '[object Function]') {
284-
this.onExitFunc = callbackFunction;
285-
}
286-
};
287-
288-
bootstro.on_step = function(callbackFunction)
289-
{
290-
if (Object.prototype.toString.call(callbackFunction) == '[object Function]') {
291-
this.onStepFunc = callbackFunction;
292-
}
293-
};
294-
295394
}( window.bootstro = window.bootstro || {}, jQuery ));
296-
});
395+
});

0 commit comments

Comments
 (0)