@@ -328,7 +328,7 @@ utils = {
328328 } ,
329329
330330 /**
331- * Helper function to get a single target DOM element. We will try to
331+ * Helper function to find a DOM element with an identifier . We will try to
332332 * locate the DOM element through several ways, in the following order:
333333 *
334334 * 1) Passing the string into document.querySelector
@@ -341,7 +341,7 @@ utils = {
341341 *
342342 * @private
343343 */
344- getStepTargetHelper : function ( target ) {
344+ getElementByIdentifier : function ( target ) {
345345 var result = document . getElementById ( target ) ;
346346
347347 //Backwards compatibility: assume the string is an id
@@ -370,6 +370,23 @@ utils = {
370370 return null ;
371371 } ,
372372
373+ /**
374+ * Returns the container DOM element where bubble elements will be added
375+ * as children. The container element can be specified by tourOpt.container
376+ * as either a string identifier (ID/selector) or directly as a JavaScript
377+ * DOM element. By default, or if the specified string identifier does not
378+ * match an element, the document's body is used.
379+ *
380+ * @private
381+ */
382+ getContainer : function ( tourOpt ) {
383+ if ( tourOpt . container ) {
384+ return typeof tourOpt . container === 'string' ? utils . getElementByIdentifier ( tourOpt . container ) || document . body : tourOpt . container ;
385+ }
386+
387+ return document . body ;
388+ } ,
389+
373390 /**
374391 * Given a step, returns the target DOM element associated with it. It is
375392 * recommended to only assign one target per step. However, there are
@@ -389,7 +406,7 @@ utils = {
389406
390407 if ( typeof step . target === 'string' ) {
391408 //Just one target to test. Check and return its results.
392- return utils . getStepTargetHelper ( step . target ) ;
409+ return utils . getElementByIdentifier ( step . target ) ;
393410 }
394411 else if ( Array . isArray ( step . target ) ) {
395412 // Multiple items to check. Check each and return the first success.
@@ -399,7 +416,7 @@ utils = {
399416
400417 for ( i = 0 , len = step . target . length ; i < len ; i ++ ) {
401418 if ( typeof step . target [ i ] === 'string' ) {
402- queriedTarget = utils . getStepTargetHelper ( step . target [ i ] ) ;
419+ queriedTarget = utils . getElementByIdentifier ( step . target [ i ] ) ;
403420
404421 if ( queriedTarget ) {
405422 return queriedTarget ;
@@ -596,6 +613,7 @@ HopscotchBubble.prototype = {
596613 left ,
597614 arrowOffset ,
598615 verticalLeftPosition ,
616+ containerElementOffset ,
599617 targetEl = utils . getStepTarget ( step ) ,
600618 el = this . element ,
601619 arrowEl = this . arrowEl ,
@@ -610,7 +628,6 @@ HopscotchBubble.prototype = {
610628
611629 // SET POSITION
612630 boundingRect = targetEl . getBoundingClientRect ( ) ;
613-
614631 verticalLeftPosition = step . isRtl ? boundingRect . right - bubbleBoundingWidth : boundingRect . left ;
615632
616633 if ( step . placement === 'top' ) {
@@ -672,6 +689,7 @@ HopscotchBubble.prototype = {
672689 else {
673690 left += utils . getPixelValue ( step . xOffset ) ;
674691 }
692+
675693 // VERTICAL OFFSET
676694 if ( step . yOffset === 'center' ) {
677695 top = ( boundingRect . top + targetEl . offsetHeight / 2 ) - ( bubbleBoundingHeight / 2 ) ;
@@ -686,6 +704,20 @@ HopscotchBubble.prototype = {
686704 left += utils . getScrollLeft ( ) ;
687705 }
688706
707+ // CONVERT TO CONTAINER COORDINATES
708+ el . style . top = '0' ;
709+ el . style . left = '0' ;
710+
711+ containerElementOffset = el . getBoundingClientRect ( ) ;
712+
713+ top -= containerElementOffset . top ;
714+ left -= containerElementOffset . left ;
715+
716+ if ( ! this . opt . fixedContainer ) {
717+ top -= utils . getScrollTop ( ) ;
718+ left -= utils . getScrollLeft ( ) ;
719+ }
720+
689721 // ACCOUNT FOR FIXED POSITION ELEMENTS
690722 el . style . position = ( step . fixedElement ? 'fixed' : 'absolute' ) ;
691723
@@ -1048,7 +1080,7 @@ HopscotchBubble.prototype = {
10481080 self = this ,
10491081 resizeCooldown = false , // for updating after window resize
10501082 onWinResize ,
1051- appendToBody ,
1083+ appendToContainer ,
10521084 children ,
10531085 numChildren ,
10541086 node ,
@@ -1117,18 +1149,18 @@ HopscotchBubble.prototype = {
11171149 //Hide the bubble by default
11181150 this . hide ( ) ;
11191151
1120- //Finally, append our new bubble to body once the DOM is ready.
1152+ //Finally, append our new bubble to the container once the DOM is ready.
1153+
11211154 if ( utils . documentIsReady ( ) ) {
1122- document . body . appendChild ( el ) ;
1155+ utils . getContainer ( opt ) . appendChild ( el ) ;
11231156 }
11241157 else {
11251158 // Moz, webkit, Opera
11261159 if ( document . addEventListener ) {
1127- appendToBody = function ( ) {
1128- document . removeEventListener ( 'DOMContentLoaded' , appendToBody ) ;
1129- window . removeEventListener ( 'load' , appendToBody ) ;
1130-
1131- document . body . appendChild ( el ) ;
1160+ appendToContainer = function ( ) {
1161+ document . removeEventListener ( 'DOMContentLoaded' , appendToContainer ) ;
1162+ window . removeEventListener ( 'load' , appendToContainer ) ;
1163+ utils . getContainer ( opt ) . appendChild ( el ) ;
11321164 } ;
11331165
11341166 document . addEventListener ( 'DOMContentLoaded' , appendToBody , false ) ;
@@ -1386,26 +1418,28 @@ Hopscotch = function(initOptions) {
13861418 adjustWindowScroll = function ( cb ) {
13871419 var bubble = getBubble ( ) ,
13881420
1421+ // Calculate the current viewport top and bottom
1422+ windowTop = utils . getScrollTop ( ) ,
1423+ windowBottom = windowTop + utils . getWindowHeight ( ) ,
1424+
1425+ containerTop = utils . getContainer ( opt ) . getBoundingClientRect ( ) . top + windowTop ,
1426+
13891427 // Calculate the bubble element top and bottom position
13901428 bubbleEl = bubble . element ,
1391- bubbleTop = utils . getPixelValue ( bubbleEl . style . top ) ,
1429+ bubbleTop = utils . getPixelValue ( bubbleEl . style . top ) + containerTop ,
13921430 bubbleBottom = bubbleTop + utils . getPixelValue ( bubbleEl . offsetHeight ) ,
13931431
13941432 // Calculate the target element top and bottom position
13951433 targetEl = utils . getStepTarget ( getCurrStep ( ) ) ,
13961434 targetBounds = targetEl . getBoundingClientRect ( ) ,
1397- targetElTop = targetBounds . top + utils . getScrollTop ( ) ,
1398- targetElBottom = targetBounds . bottom + utils . getScrollTop ( ) ,
1435+ targetElTop = targetBounds . top + windowTop ,
1436+ targetElBottom = targetBounds . bottom + windowTop ,
13991437
14001438 // The higher of the two: bubble or target
14011439 targetTop = ( bubbleTop < targetElTop ) ? bubbleTop : targetElTop ,
14021440 // The lower of the two: bubble or target
14031441 targetBottom = ( bubbleBottom > targetElBottom ) ? bubbleBottom : targetElBottom ,
14041442
1405- // Calculate the current viewport top and bottom
1406- windowTop = utils . getScrollTop ( ) ,
1407- windowBottom = windowTop + utils . getWindowHeight ( ) ,
1408-
14091443 // This is our final target scroll value.
14101444 scrollToVal = targetTop - getOption ( 'scrollTopMargin' ) ,
14111445
@@ -1414,7 +1448,6 @@ Hopscotch = function(initOptions) {
14141448 yuiEase ,
14151449 direction ,
14161450 scrollIncr ,
1417- scrollTimeout ,
14181451 scrollTimeoutFn ;
14191452
14201453 // Target and bubble are both visible in viewport
@@ -1763,7 +1796,7 @@ Hopscotch = function(initOptions) {
17631796
17641797 bubble . render ( step , stepNum , function ( adjustScroll ) {
17651798 // when done adjusting window scroll, call showBubble helper fn
1766- if ( adjustScroll ) {
1799+ if ( adjustScroll && ! getOption ( 'fixedContainer' ) ) {
17671800 adjustWindowScroll ( showBubble ) ;
17681801 }
17691802 else {
@@ -2403,9 +2436,7 @@ Hopscotch = function(initOptions) {
24032436 * @returns {Object } The Hopscotch object (for chaining).
24042437 */
24052438 this . setEscaper = function ( esc ) {
2406- if ( typeof esc === 'function' ) {
2407- customEscape = esc ;
2408- }
2439+ customEscape = esc ;
24092440 return this ;
24102441 } ;
24112442
@@ -2421,4 +2452,4 @@ winHopscotch = new Hopscotch();
24212452// @@include ('../../tmp/js/hopscotch_templates.js') //
24222453} . call ( winHopscotch ) ) ;
24232454
2424- export default winHopscotch ;
2455+ export default winHopscotch ;
0 commit comments