PluginProbe
WPVR – 360 Panorama viewer and Virtual Tour Builder for WordPress / 9.1.1
WPVR – 360 Panorama viewer and Virtual Tour Builder for WordPress v9.1.1
9.1.3 9.1.2 9.1.1 9.1.0 9.0.3 9.0.2 9.0.1 9.0.0 8.5.79 8.5.78 8.5.77 8.5.76 8.5.75 8.5.74 8.5.73 8.5.72 8.5.71 8.5.70 8.5.69 8.5.68 8.5.35 8.5.36 8.5.37 8.5.38 8.5.39 All 222 releases
wpvr / legacy / public / js / wpvr-public.js

wpvr-public.js in WPVR – 360 Panorama viewer and Virtual Tour Builder for WordPress 9.1.1, at legacy/public/js/wpvr-public.js

270 lines 9.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 (function($) {
2 'use strict';
3
4 /**
5 * All of the code for your public-facing JavaScript source
6 * should reside in this file.
7 *
8 * Note: It has been assumed you will write jQuery code here, so the
9 * $ function reference has been prepared for usage within the scope
10 * of this function.
11 *
12 * This enables you to define handlers, for when the DOM is ready:
13 *
14 * $(function() {
15 *
16 * });
17 *
18 * When the window is loaded:
19 *
20 * $( window ).load(function() {
21 *
22 * });
23 *
24 * ...and/or other possibilities.
25 *
26 * Ideally, it is not considered best practise to attach more than a
27 * single DOM-ready or window-load handler for a particular page.
28 * Although scripts in the WordPress core, Plugins and Themes may be
29 * practising this, we should strive to set a better example in our own work.
30 */
31
32 })(jQuery);
33
34 function wpvrSanitizeHtml(rawHtml) {
35 if (!rawHtml || typeof rawHtml !== 'string') return '';
36 var clean = rawHtml.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, '');
37 try {
38 var parser = new DOMParser();
39 var doc = parser.parseFromString(clean, 'text/html');
40 var elements = doc.body.querySelectorAll('*');
41 for (var i = 0; i < elements.length; i++) {
42 var el = elements[i];
43 var tag = el.tagName.toLowerCase();
44 if (['script', 'object', 'embed', 'applet', 'link', 'meta', 'base'].indexOf(tag) !== -1) {
45 el.parentNode && el.parentNode.removeChild(el);
46 continue;
47 }
48 var attrs = el.attributes;
49 for (var a = attrs.length - 1; a >= 0; a--) {
50 var attrName = attrs[a].name.toLowerCase();
51 var attrVal = attrs[a].value;
52 if (attrName.indexOf('on') === 0) {
53 el.removeAttribute(attrs[a].name);
54 } else if (['href', 'src', 'action', 'formaction', 'xlink:href'].indexOf(attrName) !== -1) {
55 if (/^\s*(javascript|vbscript|data:text\/html):/i.test(attrVal)) {
56 el.removeAttribute(attrs[a].name);
57 }
58 }
59 }
60 }
61 return doc.body.innerHTML;
62 } catch (e) {
63 return clean.replace(/\s*on\w+\s*=\s*["'][^"']*["']/gi, '').replace(/\s*on\w+\s*=\s*[^\s>]+/gi, '');
64 }
65 }
66 window.wpvrSanitizeHtml = wpvrSanitizeHtml;
67
68 function wpvrhotspot(hotSpotDiv, hotspotData) {
69 const args = (hotspotData && typeof hotspotData === 'object') ? (hotspotData.on_click_content || '') : (typeof hotspotData === 'string' ? hotspotData : '');
70
71 if (args) {
72 const hasTextContent = args.replace(/<[^>]*>/g, '').trim() !== '';
73 const hasMediaContent = /<(img|video|audio|iframe|embed|object)\b[^>]*>/i.test(args);
74 const hasOtherContent = args.replace(/<(p|br|div|span)\b[^>]*\/?>/gi, '').trim() !== '';
75
76 if (hasTextContent || hasMediaContent || hasOtherContent) {
77 const cleanArgs = wpvrSanitizeHtml(args.replace(/\\/g, ''));
78
79 const target = (hotSpotDiv && hotSpotDiv.target) ? hotSpotDiv.target : hotSpotDiv;
80 const $panoWrap = target ? jQuery(target).closest(".pano-wrap") : jQuery(".pano-wrap:first");
81 let $wrapper = $panoWrap.find(".custom-ifram-wrapper");
82 if (!$wrapper.length && target) {
83 $wrapper = jQuery(target).parent().siblings(".custom-ifram-wrapper");
84 }
85 $wrapper.find('.custom-ifram').html(cleanArgs);
86 $wrapper.fadeIn();
87 $panoWrap.addClass("show-modal");
88 }
89 }
90 }
91 window.wpvrhotspot = wpvrhotspot;
92
93 function wpvrtooltip(hotSpotDiv, args) {
94 if (args) {
95 const hasTextContent = args.replace(/<[^>]*>/g, '').trim() !== '';
96 const hasMediaContent = /<(img|video|audio|iframe|embed|object)\b[^>]*>/i.test(args);
97 const hasOtherContent = args.replace(/<(p|br|div|span)\b[^>]*\/?>/gi, '').trim() !== '';
98
99 if (hasTextContent || hasMediaContent || hasOtherContent) {
100 const cleanArgs = wpvrSanitizeHtml(args.replace(/\\/g, ''));
101
102 hotSpotDiv.classList.add('custom-tooltip');
103 const p = document.createElement('p');
104 const content = document.createElement('div');
105 content.className = 'wpvr-tooltip-content';
106 content.innerHTML = cleanArgs;
107 p.appendChild(content);
108 hotSpotDiv.appendChild(p);
109
110 p.style.marginLeft = -(p.scrollWidth - hotSpotDiv.offsetWidth) / 2 + 'px';
111 p.style.marginTop = -p.scrollHeight - 12 + 'px';
112
113 // Optional: inject style once
114 if (!document.getElementById('wpvr-tooltip-style')) {
115 const style = document.createElement('style');
116 style.id = 'wpvr-tooltip-style';
117 style.textContent = `
118 .table, .table td, .table th {
119 border: 1px solid #dee2e6;
120 border-collapse: collapse;
121 padding: 8px;
122 }
123 `;
124 document.head.appendChild(style);
125 }
126 }
127 }
128 }
129 window.wpvrtooltip = wpvrtooltip;
130
131 jQuery(document).ready(function($) {
132
133 $(".cross").on("click", function(e) {
134 e.preventDefault();
135 $(this).parent(".custom-ifram-wrapper").fadeOut();
136 $(this).parents(".pano-wrap").removeClass("show-modal");
137
138 $('.vr-iframe').attr('src', '');
139 // $('iframe').attr('src', $('iframe').attr('src'));
140 if ($('#wpvr-video').length != 0) {
141 $('#wpvr-video').get(0).pause();
142 }
143
144 $(this).parent(".custom-ifram-wrapper").find('.custom-ifram').empty();
145
146 });
147
148 });
149
150 jQuery(document).ready(function($) {
151
152 var notice_active = (typeof wpvr_public !== 'undefined') ? wpvr_public.notice_active : '';
153 var notice = (typeof wpvr_public !== 'undefined') ? wpvr_public.notice : '';
154 if (notice_active == "true") {
155 if (!$.cookie("wpvr_mobile_notice")) {
156 if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) {
157 if ($(".pano-wrap")[0]) {
158 $('body').append("<div class='wpvr-mobile-notice'><p>" + notice + "</p> <span class='notice-close'><i class='fa fa-times'></i></span></div>");
159 }
160 }
161 }
162 }
163
164 $('.wpvr-mobile-notice .notice-close').on('click', function() {
165 $('.wpvr-mobile-notice').fadeOut();
166 $.cookie('wpvr_mobile_notice', 'true');
167 });
168 });
169
170 // WPVR Hotspot Long-Press Mobile Support
171 jQuery(document).ready(function($) {
172 var isTouchDevice = ("ontouchstart" in window) || (navigator.maxTouchPoints > 0);
173 var disOnHover = (typeof wpvr_public !== 'undefined') ? wpvr_public.dis_on_hover : undefined;
174 var tipEnabled = (typeof wpvr_public !== 'undefined') ? wpvr_public.mobile_hotspot_tip : undefined;
175 var shouldShowAlert = isTouchDevice && (disOnHover !== "1");
176 if (shouldShowAlert) {
177 setTimeout(function() {
178 if (!$('.pnlm-container').length) {
179 return;
180 }
181 $('.pnlm-hotspot-base, .pnlm-hotspot').each(function() {
182 $(this).off('mouseenter mouseover mouseleave');
183
184 // Hide only the inner content <p>, not the hotspot pointer
185 $(this).find('p').hide();
186
187 var longPressTimer;
188 var isLongPress = false;
189
190 // Prevent click after long press
191 $(this).off('click._wpvrHotspotFix').on('click._wpvrHotspotFix', function(e) {
192 if ($(this).data('wpvr-longpress')) {
193 e.preventDefault();
194 e.stopImmediatePropagation();
195 $(this).data('wpvr-longpress', false);
196 return false;
197 }
198 });
199
200 $(this).on('touchstart', function(e) {
201 isLongPress = false;
202 var $hotspot = $(this);
203
204 // Hide inner content on touch start
205 $hotspot.find('p').hide();
206
207 longPressTimer = setTimeout(function() {
208 isLongPress = true;
209 $hotspot.data('wpvr-longpress', true);
210
211 // Hide all other hotspot contents first
212 $('.pnlm-hotspot-base p, .pnlm-hotspot p').hide();
213
214 // Show only this hotspot's content
215 $hotspot.find('p').show();
216 }, 600);
217 });
218
219 $(this).on('touchend', function(e) {
220 clearTimeout(longPressTimer);
221 if (isLongPress) {
222 e.preventDefault();
223 e.stopPropagation();
224 // Do NOT auto-hide after 2 seconds anymore
225 // Content will stay open until user taps elsewhere
226 } else {
227 // Short tap: hide inner content, let click fire
228 $(this).find('p').hide();
229 }
230 });
231
232 $(this).on('touchmove', function() {
233 clearTimeout(longPressTimer);
234 isLongPress = false;
235 // Hide inner content if user starts panning
236 $(this).find('p').hide();
237 });
238 });
239
240 // Hide hotspot content when tapping outside any hotspot
241 $(document).on('touchstart.wpvrHotspotOutside', function(e) {
242 // If the tap is not inside a hotspot or its content
243 if (!$(e.target).closest('.pnlm-hotspot-base, .pnlm-hotspot').length) {
244 $('.pnlm-hotspot-base p, .pnlm-hotspot p').hide();
245 }
246 });
247
248 // Hide other hotspot contents when another hotspot is long-pressed
249 $('.pnlm-hotspot-base, .pnlm-hotspot').on('touchstart', function(e) {
250 // Hide all other hotspot contents except the one being touched
251 var $current = $(this);
252 $('.pnlm-hotspot-base, .pnlm-hotspot').not($current).find('p').hide();
253 });
254
255 if (tipEnabled == '1') {
256 function showHotspotTip() {
257 if (window.sessionStorage && sessionStorage.getItem('wpvrHotspotTipShown')) return;
258 if (window.sessionStorage) {
259 sessionStorage.setItem('wpvrHotspotTipShown', '1');
260 }
261 alert('Tip: On mobile devices, long-press a hotspot to show its hover content.');
262 }
263 $('.pnlm-container').on('touchstart.wpvrTip touchmove.wpvrTip', showHotspotTip);
264 $('.pnlm-hotspot-base, .pnlm-hotspot').on('touchstart.wpvrTip', showHotspotTip);
265 }
266 }, 800);
267 }
268 });
269
270