|
419 | 419 | *
|
420 | 420 | * @api private
|
421 | 421 | * @method _placeTooltip
|
422 |
| - * @param {Object} targetElement |
423 |
| - * @param {Object} tooltipLayer |
424 |
| - * @param {Object} arrowLayer |
| 422 | + * @param {HTMLElement} targetElement |
| 423 | + * @param {HTMLElement} tooltipLayer |
| 424 | + * @param {HTMLElement} arrowLayer |
| 425 | + * @param {HTMLElement} helperNumberLayer |
425 | 426 | */
|
426 | 427 | function _placeTooltip(targetElement, tooltipLayer, arrowLayer, helperNumberLayer) {
|
427 | 428 | var tooltipCssClass = '',
|
428 | 429 | currentStepObj,
|
429 | 430 | tooltipOffset,
|
430 |
| - targetElementOffset; |
| 431 | + targetOffset, |
| 432 | + windowSize, |
| 433 | + currentTooltipPosition; |
431 | 434 |
|
432 | 435 | //reset the old style
|
433 | 436 | tooltipLayer.style.top = null;
|
|
457 | 460 |
|
458 | 461 | tooltipLayer.className = ('introjs-tooltip ' + tooltipCssClass).replace(/^\s+|\s+$/g, '');
|
459 | 462 |
|
460 |
| - //custom css class for tooltip boxes |
461 |
| - var tooltipCssClass = this._options.tooltipClass; |
462 |
| - |
463 | 463 | currentTooltipPosition = this._introItems[this._currentStep].position;
|
464 | 464 | if ((currentTooltipPosition == "auto" || this._options.tooltipPosition == "auto")) {
|
465 | 465 | if (currentTooltipPosition != "floating") { // Floating is always valid, no point in calculating
|
466 | 466 | currentTooltipPosition = _determineAutoPosition.call(this, targetElement, tooltipLayer, currentTooltipPosition);
|
467 | 467 | }
|
468 | 468 | }
|
469 |
| - |
470 |
| - var targetOffset = _getOffset(targetElement); |
471 |
| - var tooltipHeight = _getOffset(tooltipLayer).height; |
472 |
| - var windowSize = _getWinSize(); |
473 |
| - |
| 469 | + targetOffset = _getOffset(targetElement); |
| 470 | + tooltipOffset = _getOffset(tooltipLayer); |
| 471 | + windowSize = _getWinSize(); |
474 | 472 | switch (currentTooltipPosition) {
|
475 | 473 | case 'top':
|
476 |
| - tooltipLayer.style.left = '15px'; |
477 |
| - tooltipLayer.style.top = '-' + (tooltipHeight + 10) + 'px'; |
478 | 474 | arrowLayer.className = 'introjs-arrow bottom';
|
| 475 | + |
| 476 | + var tooltipLayerStyleLeft = 15; |
| 477 | + _checkRight(targetOffset, tooltipLayerStyleLeft, tooltipOffset, windowSize, tooltipLayer); |
| 478 | + tooltipLayer.style.bottom = (targetOffset.height + 20) + 'px'; |
479 | 479 | break;
|
480 | 480 | case 'right':
|
481 |
| - tooltipLayer.style.left = (_getOffset(targetElement).width + 20) + 'px'; |
482 |
| - if (targetOffset.top + tooltipHeight > windowSize.height) { |
| 481 | + tooltipLayer.style.left = (targetOffset.width + 20) + 'px'; |
| 482 | + if (targetOffset.top + tooltipOffset.height > windowSize.height) { |
483 | 483 | // In this case, right would have fallen below the bottom of the screen.
|
484 | 484 | // Modify so that the bottom of the tooltip connects with the target
|
485 | 485 | arrowLayer.className = "introjs-arrow left-bottom";
|
486 |
| - tooltipLayer.style.top = "-" + (tooltipHeight - targetOffset.height - 20) + "px"; |
| 486 | + tooltipLayer.style.top = "-" + (tooltipOffset.height - targetOffset.height - 20) + "px"; |
487 | 487 | } else {
|
488 | 488 | arrowLayer.className = 'introjs-arrow left';
|
489 | 489 | }
|
|
493 | 493 | tooltipLayer.style.top = '15px';
|
494 | 494 | }
|
495 | 495 |
|
496 |
| - if (targetOffset.top + tooltipHeight > windowSize.height) { |
| 496 | + if (targetOffset.top + tooltipOffset.height > windowSize.height) { |
497 | 497 | // In this case, left would have fallen below the bottom of the screen.
|
498 | 498 | // Modify so that the bottom of the tooltip connects with the target
|
499 |
| - tooltipLayer.style.top = "-" + (tooltipHeight - targetOffset.height - 20) + "px"; |
| 499 | + tooltipLayer.style.top = "-" + (tooltipOffset.height - targetOffset.height - 20) + "px"; |
500 | 500 | arrowLayer.className = 'introjs-arrow right-bottom';
|
501 | 501 | } else {
|
502 | 502 | arrowLayer.className = 'introjs-arrow right';
|
|
508 | 508 | arrowLayer.style.display = 'none';
|
509 | 509 |
|
510 | 510 | //we have to adjust the top and left of layer manually for intro items without element
|
511 |
| - tooltipOffset = _getOffset(tooltipLayer); |
512 |
| - |
513 | 511 | tooltipLayer.style.left = '50%';
|
514 | 512 | tooltipLayer.style.top = '50%';
|
515 | 513 | tooltipLayer.style.marginLeft = '-' + (tooltipOffset.width / 2) + 'px';
|
|
523 | 521 | break;
|
524 | 522 | case 'bottom-right-aligned':
|
525 | 523 | arrowLayer.className = 'introjs-arrow top-right';
|
526 |
| - tooltipLayer.style.right = '0px'; |
527 |
| - tooltipLayer.style.bottom = '-' + (_getOffset(tooltipLayer).height + 10) + 'px'; |
| 524 | + |
| 525 | + var tooltipLayerStyleRight = 0; |
| 526 | + _checkLeft(targetOffset, tooltipLayerStyleRight, tooltipOffset, tooltipLayer); |
| 527 | + tooltipLayer.style.top = (targetOffset.height + 20) + 'px'; |
528 | 528 | break;
|
529 |
| - case 'bottom-middle-aligned': |
530 |
| - targetElementOffset = _getOffset(targetElement); |
531 |
| - tooltipOffset = _getOffset(tooltipLayer); |
532 | 529 |
|
| 530 | + case 'bottom-middle-aligned': |
533 | 531 | arrowLayer.className = 'introjs-arrow top-middle';
|
534 |
| - tooltipLayer.style.left = (targetElementOffset.width / 2 - tooltipOffset.width / 2) + 'px'; |
535 |
| - tooltipLayer.style.bottom = '-' + (tooltipOffset.height + 10) + 'px'; |
| 532 | + |
| 533 | + var tooltipLayerStyleLeftRight = targetOffset.width / 2 - tooltipOffset.width / 2; |
| 534 | + if (_checkLeft(targetOffset, tooltipLayerStyleLeftRight, tooltipOffset, tooltipLayer)) { |
| 535 | + tooltipLayer.style.right = null; |
| 536 | + _checkRight(targetOffset, tooltipLayerStyleLeftRight, tooltipOffset, windowSize, tooltipLayer); |
| 537 | + } |
| 538 | + tooltipLayer.style.top = (targetOffset.height + 20) + 'px'; |
536 | 539 | break;
|
| 540 | + |
537 | 541 | case 'bottom-left-aligned':
|
538 | 542 | // Bottom-left-aligned is the same as the default bottom
|
539 | 543 | case 'bottom':
|
540 | 544 | // Bottom going to follow the default behavior
|
541 | 545 | default:
|
542 |
| - tooltipLayer.style.bottom = '-' + (_getOffset(tooltipLayer).height + 10) + 'px'; |
543 |
| - tooltipLayer.style.left = (_getOffset(targetElement).width / 2 - _getOffset(tooltipLayer).width / 2) + 'px'; |
544 |
| - |
545 | 546 | arrowLayer.className = 'introjs-arrow top';
|
| 547 | + |
| 548 | + var tooltipLayerStyleLeft = 0; |
| 549 | + _checkRight(targetOffset, tooltipLayerStyleLeft, tooltipOffset, windowSize, tooltipLayer); |
| 550 | + tooltipLayer.style.top = (targetOffset.height + 20) + 'px'; |
546 | 551 | break;
|
547 | 552 | }
|
548 | 553 | }
|
549 | 554 |
|
| 555 | + /** |
| 556 | + * Set tooltip left so it doesn't go off the right side of the window |
| 557 | + * |
| 558 | + * @return boolean true, if tooltipLayerStyleLeft is ok. false, otherwise. |
| 559 | + */ |
| 560 | + function _checkRight(targetOffset, tooltipLayerStyleLeft, tooltipOffset, windowSize, tooltipLayer) { |
| 561 | + if (targetOffset.left + tooltipLayerStyleLeft + tooltipOffset.width > windowSize.width) { |
| 562 | + // off the right side of the window |
| 563 | + tooltipLayer.style.left = (windowSize.width - tooltipOffset.width - targetOffset.left) + 'px'; |
| 564 | + return false; |
| 565 | + } |
| 566 | + tooltipLayer.style.left = tooltipLayerStyleLeft + 'px'; |
| 567 | + return true; |
| 568 | + } |
| 569 | + |
| 570 | + /** |
| 571 | + * Set tooltip right so it doesn't go off the left side of the window |
| 572 | + * |
| 573 | + * @return boolean true, if tooltipLayerStyleRight is ok. false, otherwise. |
| 574 | + */ |
| 575 | + function _checkLeft(targetOffset, tooltipLayerStyleRight, tooltipOffset, tooltipLayer) { |
| 576 | + if (targetOffset.left + targetOffset.width - tooltipLayerStyleRight - tooltipOffset.width < 0) { |
| 577 | + // off the left side of the window |
| 578 | + tooltipLayer.style.left = (-targetOffset.left) + 'px'; |
| 579 | + return false; |
| 580 | + } |
| 581 | + tooltipLayer.style.right = tooltipLayerStyleRight + 'px'; |
| 582 | + return true; |
| 583 | + } |
| 584 | + |
550 | 585 | /**
|
551 | 586 | * Determines the position of the tooltip based on the position precedence and availability
|
552 | 587 | * of screen space.
|
|
0 commit comments