Advertisement
nrzmalik

ToolTips for Articulate Storyline Elements

Oct 25th, 2023 (edited)
478
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
JavaScript 5.79 KB | Source Code | 0 0
  1. class Tooltip {
  2.   constructor() {
  3.     this.tooltip = null;
  4.     this.showTimeout = null;
  5.     this.hideTimeout = null;
  6.     this.currentTarget = null;
  7.     this.touchStartX = 0;
  8.     this.touchStartY = 0;
  9.     this.init();
  10.   }
  11.  
  12.   init() {
  13.     this.createStyles();
  14.     this.createTooltipElement();
  15.     this.attachEventListeners();
  16.   }
  17.  
  18.   createStyles() {
  19.     const style = document.createElement('style');
  20.     style.textContent = `
  21.       .custom-tooltip {
  22.         position: fixed;
  23.         background-color: rgba(33, 33, 33, 0.95);
  24.         color: #fff;
  25.         padding: 10px 15px;
  26.         border-radius: 6px;
  27.         font-size: 14px;
  28.         font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
  29.         box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1), 0 1px 3px rgba(0, 0, 0, 0.08);
  30.         pointer-events: none;
  31.         opacity: 0;
  32.         transform: translateY(5px);
  33.         transition: opacity 0.2s ease, transform 0.2s ease;
  34.         z-index: 1000;
  35.         max-width: 250px;
  36.         word-wrap: break-word;
  37.         line-height: 1.4;
  38.       }
  39.       .custom-tooltip.visible {
  40.         opacity: 1;
  41.         transform: translateY(0);
  42.       }
  43.       .custom-tooltip::after {
  44.         content: '';
  45.         position: absolute;
  46.         border-style: solid;
  47.         border-width: 6px;
  48.       }
  49.       .custom-tooltip.top::after {
  50.         border-color: rgba(33, 33, 33, 0.95) transparent transparent transparent;
  51.         top: 100%;
  52.         left: 50%;
  53.         margin-left: -6px;
  54.       }
  55.       .custom-tooltip.bottom::after {
  56.         border-color: transparent transparent rgba(33, 33, 33, 0.95) transparent;
  57.         bottom: 100%;
  58.         left: 50%;
  59.         margin-left: -6px;
  60.       }
  61.     `;
  62.     document.head.appendChild(style);
  63.   }
  64.  
  65.   createTooltipElement() {
  66.     this.tooltip = document.createElement('div');
  67.     this.tooltip.className = 'custom-tooltip';
  68.     document.body.appendChild(this.tooltip);
  69.   }
  70.  
  71.   attachEventListeners() {
  72.     // Mouse events
  73.     document.body.addEventListener('mouseover', this.handleMouseOver.bind(this));
  74.     document.body.addEventListener('mouseout', this.handleMouseOut.bind(this));
  75.    
  76.     // Focus events
  77.     document.body.addEventListener('focusin', this.handleFocusIn.bind(this));
  78.     document.body.addEventListener('focusout', this.handleFocusOut.bind(this));
  79.    
  80.     // Touch events
  81.     document.body.addEventListener('touchstart', this.handleTouchStart.bind(this));
  82.     document.body.addEventListener('touchend', this.handleTouchEnd.bind(this));
  83.   }
  84.  
  85.   handleMouseOver(event) {
  86.     const target = event.target.closest('[data-acc-text]');
  87.     if (!target) return;
  88.     this.currentTarget = target;
  89.     this.showTimeout = setTimeout(() => this.showTooltip(target), 200);
  90.   }
  91.  
  92.   handleMouseOut() {
  93.     clearTimeout(this.showTimeout);
  94.     this.hideTooltip();
  95.   }
  96.  
  97.   handleFocusIn(event) {
  98.     const target = event.target.closest('[data-acc-text]');
  99.     if (!target) return;
  100.     this.currentTarget = target;
  101.     this.showTooltip(target);
  102.   }
  103.  
  104.   handleFocusOut() {
  105.     this.hideTooltip();
  106.   }
  107.  
  108.   handleTouchStart(event) {
  109.     const target = event.target.closest('[data-acc-text]');
  110.     if (!target) return;
  111.     this.currentTarget = target;
  112.     this.touchStartX = event.touches[0].clientX;
  113.     this.touchStartY = event.touches[0].clientY;
  114.     this.showTimeout = setTimeout(() => this.showTooltip(target), 200);
  115.   }
  116.  
  117.   handleTouchEnd(event) {
  118.     if (!this.currentTarget) return;
  119.    
  120.     const touchEndX = event.changedTouches[0].clientX;
  121.     const touchEndY = event.changedTouches[0].clientY;
  122.     const distance = Math.sqrt(
  123.       Math.pow(touchEndX - this.touchStartX, 2) +
  124.       Math.pow(touchEndY - this.touchStartY, 2)
  125.     );
  126.  
  127.     if (distance < 10) { // Threshold for considering it a tap, not a scroll
  128.       event.preventDefault(); // Prevent default click behavior
  129.       clearTimeout(this.showTimeout);
  130.       this.toggleTooltip(this.currentTarget);
  131.     } else {
  132.       this.hideTooltip();
  133.     }
  134.   }
  135.  
  136.   toggleTooltip(target) {
  137.     if (this.tooltip.classList.contains('visible')) {
  138.       this.hideTooltip();
  139.     } else {
  140.       this.showTooltip(target);
  141.     }
  142.   }
  143.  
  144.   showTooltip(target) {
  145.     const tooltipText = target.getAttribute('data-acc-text');
  146.     if (!tooltipText) return;
  147.  
  148.     this.tooltip.textContent = tooltipText;
  149.     this.positionTooltip(target);
  150.     this.tooltip.classList.add('visible');
  151.   }
  152.  
  153.   hideTooltip() {
  154.     clearTimeout(this.hideTimeout);
  155.     this.hideTimeout = setTimeout(() => {
  156.       this.tooltip.classList.remove('visible');
  157.       this.currentTarget = null;
  158.     }, 200);
  159.   }
  160.  
  161.   positionTooltip(target) {
  162.     const rect = target.getBoundingClientRect();
  163.     const tooltipRect = this.tooltip.getBoundingClientRect();
  164.  
  165.     let top, left;
  166.     const spacing = 10;
  167.  
  168.     // Attempt to position the tooltip below the target
  169.     top = rect.bottom + spacing;
  170.     left = rect.left + (rect.width - tooltipRect.width) / 2;
  171.  
  172.     // Check if tooltip goes off-screen to the right
  173.     if (left + tooltipRect.width > window.innerWidth) {
  174.       left = window.innerWidth - tooltipRect.width - spacing;
  175.     }
  176.  
  177.     // Check if tooltip goes off-screen to the left
  178.     if (left < spacing) {
  179.       left = spacing;
  180.     }
  181.  
  182.     // If tooltip goes off-screen at the bottom, position it above the target
  183.     if (top + tooltipRect.height > window.innerHeight) {
  184.       top = rect.top - tooltipRect.height - spacing;
  185.       this.tooltip.classList.add('top');
  186.       this.tooltip.classList.remove('bottom');
  187.     } else {
  188.       this.tooltip.classList.add('bottom');
  189.       this.tooltip.classList.remove('top');
  190.     }
  191.  
  192.     this.tooltip.style.top = `${top}px`;
  193.     this.tooltip.style.left = `${left}px`;
  194.   }
  195. }
  196.  
  197. // Initialize the tooltip
  198.  
  199.   new Tooltip();
  200.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement