| | <style> |
| | .lx-highlight { position: relative; border-radius:3px; padding:1px 2px;} |
| | .lx-highlight .lx-tooltip { |
| | visibility: hidden; |
| | opacity: 0; |
| | transition: opacity 0.2s ease-in-out; |
| | background: #333; |
| | color: #fff; |
| | text-align: left; |
| | border-radius: 4px; |
| | padding: 6px 8px; |
| | position: absolute; |
| | z-index: 1000; |
| | bottom: 125%; |
| | left: 50%; |
| | transform: translateX(-50%); |
| | font-size: 12px; |
| | max-width: 240px; |
| | white-space: normal; |
| | box-shadow: 0 2px 6px rgba(0,0,0,0.3); |
| | } |
| | .lx-highlight:hover .lx-tooltip { visibility: visible; opacity:1; } |
| | .lx-animated-wrapper { max-width: 100%; font-family: Arial, sans-serif; } |
| | .lx-controls { |
| | background: #fafafa; border: 1px solid #90caf9; border-radius: 8px; |
| | padding: 12px; margin-bottom: 16px; |
| | } |
| | .lx-button-row { |
| | display: flex; justify-content: center; gap: 8px; margin-bottom: 12px; |
| | } |
| | .lx-control-btn { |
| | background: #4285f4; color: white; border: none; border-radius: 4px; |
| | padding: 8px 16px; cursor: pointer; font-size: 13px; font-weight: 500; |
| | transition: background-color 0.2s; |
| | } |
| | .lx-control-btn:hover { background: #3367d6; } |
| | .lx-progress-container { |
| | margin-bottom: 8px; |
| | } |
| | .lx-progress-slider { |
| | width: 100%; margin: 0; appearance: none; height: 6px; |
| | background: #ddd; border-radius: 3px; outline: none; |
| | } |
| | .lx-progress-slider::-webkit-slider-thumb { |
| | appearance: none; width: 18px; height: 18px; background: #4285f4; |
| | border-radius: 50%; cursor: pointer; |
| | } |
| | .lx-progress-slider::-moz-range-thumb { |
| | width: 18px; height: 18px; background: #4285f4; border-radius: 50%; |
| | cursor: pointer; border: none; |
| | } |
| | .lx-status-text { |
| | text-align: center; font-size: 12px; color: #666; margin-top: 4px; |
| | } |
| | .lx-text-window { |
| | font-family: monospace; white-space: pre-wrap; border: 1px solid #90caf9; |
| | padding: 12px; max-height: 260px; overflow-y: auto; margin-bottom: 12px; |
| | line-height: 1.6; |
| | } |
| | .lx-attributes-panel { |
| | background: #fafafa; border: 1px solid #90caf9; border-radius: 6px; |
| | padding: 8px 10px; margin-top: 8px; font-size: 13px; |
| | } |
| | .lx-current-highlight { |
| | border-bottom: 4px solid #ff4444; |
| | font-weight: bold; |
| | animation: lx-pulse 1s ease-in-out; |
| | } |
| | @keyframes lx-pulse { |
| | 0% { text-decoration-color: #ff4444; } |
| | 50% { text-decoration-color: #ff0000; } |
| | 100% { text-decoration-color: #ff4444; } |
| | } |
| | .lx-legend { |
| | font-size: 12px; margin-bottom: 8px; |
| | padding-bottom: 8px; border-bottom: 1px solid #e0e0e0; |
| | } |
| | .lx-label { |
| | display: inline-block; |
| | padding: 2px 4px; |
| | border-radius: 3px; |
| | margin-right: 4px; |
| | color: #000; |
| | } |
| | .lx-attr-key { |
| | font-weight: 600; |
| | color: #1565c0; |
| | letter-spacing: 0.3px; |
| | } |
| | .lx-attr-value { |
| | font-weight: 400; |
| | opacity: 0.85; |
| | letter-spacing: 0.2px; |
| | } |
| | |
| | |
| | .lx-gif-optimized .lx-text-window { font-size: 16px; line-height: 1.8; } |
| | .lx-gif-optimized .lx-attributes-panel { font-size: 15px; } |
| | .lx-gif-optimized .lx-current-highlight { text-decoration-thickness: 4px; } |
| | </style> |
| | <div class="lx-animated-wrapper lx-gif-optimized"> |
| | <div class="lx-attributes-panel"> |
| | <div class="lx-legend">Highlights Legend: <span class="lx-label" style="background-color:#D2E3FC;">character</span> <span class="lx-label" style="background-color:#C8E6C9;">emotion</span> <span class="lx-label" style="background-color:#FEF0C3;">relationship</span></div> |
| | <div id="attributesContainer"></div> |
| | </div> |
| | <div class="lx-text-window" id="textWindow"> |
| | <span class="lx-highlight lx-current-highlight" data-idx="0" style="background-color:#D2E3FC;">Lady Juliet</span> gazed longingly at the stars, her <span class="lx-highlight" data-idx="1" style="background-color:#C8E6C9;">heart aching</span> <span class="lx-highlight" data-idx="2" style="background-color:#FEF0C3;">for Romeo</span> |
| | </div> |
| | <div class="lx-controls"> |
| | <div class="lx-button-row"> |
| | <button class="lx-control-btn" onclick="playPause()">▶️ Play</button> |
| | <button class="lx-control-btn" onclick="prevExtraction()">⏮ Previous</button> |
| | <button class="lx-control-btn" onclick="nextExtraction()">⏭ Next</button> |
| | </div> |
| | <div class="lx-progress-container"> |
| | <input type="range" id="progressSlider" class="lx-progress-slider" |
| | min="0" max="2" value="0" |
| | onchange="jumpToExtraction(this.value)"> |
| | </div> |
| | <div class="lx-status-text"> |
| | Entity <span id="entityInfo">1/3</span> | |
| | Pos <span id="posInfo">[0-11]</span> |
| | </div> |
| | </div> |
| | </div> |
| |
|
| | <script> |
| | (function() { |
| | const extractions = [{"index": 0, "class": "character", "text": "Lady Juliet", "color": "#D2E3FC", "startPos": 0, "endPos": 11, "beforeText": "", "extractionText": "Lady Juliet", "afterText": " gazed longingly at the stars, her heart aching for Romeo", "attributesHtml": "<div><strong>class:</strong> character</div><div><strong>attributes:</strong> {<span class=\"lx-attr-key\">emotional_state</span>: <span class=\"lx-attr-value\">longing</span>}</div>"}, {"index": 1, "class": "emotion", "text": "heart aching", "color": "#C8E6C9", "startPos": 46, "endPos": 58, "beforeText": "Lady Juliet gazed longingly at the stars, her ", "extractionText": "heart aching", "afterText": " for Romeo", "attributesHtml": "<div><strong>class:</strong> emotion</div><div><strong>attributes:</strong> {<span class=\"lx-attr-key\">feeling</span>: <span class=\"lx-attr-value\">ache</span>}</div>"}, {"index": 2, "class": "relationship", "text": "for Romeo", "color": "#FEF0C3", "startPos": 59, "endPos": 68, "beforeText": "Lady Juliet gazed longingly at the stars, her heart aching ", "extractionText": "for Romeo", "afterText": "", "attributesHtml": "<div><strong>class:</strong> relationship</div><div><strong>attributes:</strong> {<span class=\"lx-attr-key\">type</span>: <span class=\"lx-attr-value\">love</span>}</div>"}]; |
| | let currentIndex = 0; |
| | let isPlaying = false; |
| | let animationInterval = null; |
| | let animationSpeed = 1.0; |
| | |
| | function updateDisplay() { |
| | const extraction = extractions[currentIndex]; |
| | if (!extraction) return; |
| | |
| | document.getElementById('attributesContainer').innerHTML = extraction.attributesHtml; |
| | document.getElementById('entityInfo').textContent = (currentIndex + 1) + '/' + extractions.length; |
| | document.getElementById('posInfo').textContent = '[' + extraction.startPos + '-' + extraction.endPos + ']'; |
| | document.getElementById('progressSlider').value = currentIndex; |
| | |
| | const playBtn = document.querySelector('.lx-control-btn'); |
| | if (playBtn) playBtn.textContent = isPlaying ? '⏸ Pause' : '▶️ Play'; |
| | |
| | const prevHighlight = document.querySelector('.lx-text-window .lx-current-highlight'); |
| | if (prevHighlight) prevHighlight.classList.remove('lx-current-highlight'); |
| | const currentSpan = document.querySelector('.lx-text-window span[data-idx="' + currentIndex + '"]'); |
| | if (currentSpan) { |
| | currentSpan.classList.add('lx-current-highlight'); |
| | currentSpan.scrollIntoView({block: 'center', behavior: 'smooth'}); |
| | } |
| | } |
| | |
| | function nextExtraction() { |
| | currentIndex = (currentIndex + 1) % extractions.length; |
| | updateDisplay(); |
| | } |
| | |
| | function prevExtraction() { |
| | currentIndex = (currentIndex - 1 + extractions.length) % extractions.length; |
| | updateDisplay(); |
| | } |
| | |
| | function jumpToExtraction(index) { |
| | currentIndex = parseInt(index); |
| | updateDisplay(); |
| | } |
| | |
| | function playPause() { |
| | if (isPlaying) { |
| | clearInterval(animationInterval); |
| | isPlaying = false; |
| | } else { |
| | animationInterval = setInterval(nextExtraction, animationSpeed * 1000); |
| | isPlaying = true; |
| | } |
| | updateDisplay(); |
| | } |
| | |
| | window.playPause = playPause; |
| | window.nextExtraction = nextExtraction; |
| | window.prevExtraction = prevExtraction; |
| | window.jumpToExtraction = jumpToExtraction; |
| | |
| | updateDisplay(); |
| | })(); |
| | </script> |