1/** 2 * Read More Without Refresh - Frontend JavaScript (Free Version) 3 * 4 * @package ReadMoreWithoutRefresh 5 * @version 3.4.0 6 */ 7 8(function() { 9 'use strict'; 10 11 /** 12 * Main RMWR object (Free Version) 13 */ 14 window.RMWR = { 15 /** 16 * Toggle read more/less functionality 17 * 18 * @param {string} id - Unique ID of the read more instance 19 * @param {string} openText - Text to show when collapsed 20 * @param {string} closeText - Text to show when expanded 21 */ 22 toggle: function(id, openText, closeText) { 23 const link = document.getElementById('readlink' + id); 24 const content = document.getElementById('read' + id); 25 26 if (!link || !content) { 27 return; 28 } 29 30 const isExpanded = content.style.display !== 'none' && content.getAttribute('aria-hidden') !== 'true'; 31 32 // Get text element (free version doesn't have icons) 33 const textElement = link.querySelector('.rmwr-text') || link; 34 35 // Get wrapper for data attributes 36 const wrapper = link.closest('.rmwr-wrapper'); 37 38 // Toggle visibility with basic animation (free version - fade only) 39 if (isExpanded) { 40 this.collapse(content); 41 if (textElement === link) { 42 link.innerHTML = this.escapeHtml(openText); 43 } else { 44 textElement.textContent = openText; 45 } 46 link.setAttribute('aria-expanded', 'false'); 47 content.setAttribute('aria-hidden', 'true'); 48 } else { 49 this.expand(content); 50 if (textElement === link) { 51 link.innerHTML = this.escapeHtml(closeText); 52 } else { 53 textElement.textContent = closeText; 54 } 55 link.setAttribute('aria-expanded', 'true'); 56 content.setAttribute('aria-hidden', 'false'); 57 58 // Smooth scroll if enabled (Free feature) 59 if (wrapper && wrapper.dataset.smoothScroll !== 'false') { 60 const offset = parseInt(wrapper.dataset.scrollOffset || 0); 61 this.smoothScrollTo(content, offset); 62 } 63 } 64 }, 65 66 /** 67 * Expand content with basic fade animation (free version) 68 */ 69 expand: function(element) { 70 element.style.display = 'block'; 71 72 // Basic fade animation for free version 73 const animation = element.dataset.animation || 'fade'; 74 75 if (animation === 'fade') { 76 element.style.opacity = '0'; 77 element.style.overflow = 'hidden'; 78 79 // Trigger reflow 80 element.offsetHeight; 81 82 const duration = 300; // Fixed duration for free version 83 element.style.transition = `opacity ${duration}ms ease-in-out`; 84 element.style.opacity = '1'; 85 86 // Clean up after animation 87 setTimeout(function() { 88 element.style.overflow = ''; 89 element.style.transition = ''; 90 }, duration); 91 } else { 92 // Simple show 93 element.style.display = 'block'; 94 } 95 }, 96 97 /** 98 * Collapse content with basic animation (free version) 99 */ 100 collapse: function(element) { 101 const animation = element.dataset.animation || 'fade'; 102 103 if (animation === 'fade') { 104 const duration = 300; // Fixed duration for free version 105 element.style.transition = `opacity ${duration}ms ease-in-out`; 106 element.style.opacity = '0'; 107 element.style.overflow = 'hidden'; 108 109 setTimeout(function() { 110 element.style.display = 'none'; 111 element.style.overflow = ''; 112 element.style.transition = ''; 113 }, duration); 114 } else { 115 element.style.display = 'none'; 116 } 117 }, 118 119 /** 120 * Escape HTML to prevent XSS 121 */ 122 escapeHtml: function(text) { 123 const div = document.createElement('div'); 124 div.textContent = text; 125 return div.innerHTML; 126 }, 127 128 /** 129 * Smooth scroll to element (Free feature) 130 */ 131 smoothScrollTo: function(element, offset) { 132 if (!element) return; 133 134 const elementPosition = element.getBoundingClientRect().top; 135 const offsetPosition = elementPosition + window.pageYOffset - (offset || 0); 136 137 window.scrollTo({ 138 top: offsetPosition, 139 behavior: 'smooth' 140 }); 141 }, 142 143 /** 144 * Initialize all read more instances 145 */ 146 init: function() { 147 // Handle click events using event delegation 148 document.addEventListener('click', function(e) { 149 const link = e.target.closest('.read-link'); 150 if (!link) { 151 return; 152 } 153 154 e.preventDefault(); 155 e.stopPropagation(); 156 157 const id = link.id.replace('readlink', ''); 158 const openText = link.dataset.openText || link.getAttribute('data-open-text') || 'Read More'; 159 const closeText = link.dataset.closeText || link.getAttribute('data-close-text') || 'Read Less'; 160 161 RMWR.toggle(id, openText, closeText); 162 }); 163 164 // Handle keyboard navigation (Enter and Space keys) 165 document.addEventListener('keydown', function(e) { 166 const link = e.target.closest('.read-link'); 167 if (!link || (e.key !== 'Enter' && e.key !== ' ')) { 168 return; 169 } 170 171 e.preventDefault(); 172 e.stopPropagation(); 173 174 const id = link.id.replace('readlink', ''); 175 const openText = link.dataset.openText || link.getAttribute('data-open-text') || 'Read More'; 176 const closeText = link.dataset.closeText || link.getAttribute('data-close-text') || 'Read Less'; 177 178 RMWR.toggle(id, openText, closeText); 179 }); 180 181 // Handle print - auto-expand all (Free feature) 182 if (typeof rmwrSettings !== 'undefined' && rmwrSettings.printExpand !== false) { 183 window.addEventListener('beforeprint', function() { 184 const allContent = document.querySelectorAll('.read_div[style*="display: none"]'); 185 allContent.forEach(function(content) { 186 content.style.display = 'block'; 187 content.setAttribute('aria-hidden', 'false'); 188 const contentId = content.id.replace('read', ''); 189 const contentLink = document.getElementById('readlink' + contentId); 190 if (contentLink) { 191 contentLink.setAttribute('aria-expanded', 'true'); 192 } 193 }); 194 }); 195 } 196 } 197 }; 198 199 // Initialize when DOM is ready 200 if (document.readyState === 'loading') { 201 document.addEventListener('DOMContentLoaded', RMWR.init); 202 } else { 203 RMWR.init(); 204 } 205 206})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.