PluginProbe
WPVR – 360 Panorama viewer and Virtual Tour Builder for WordPress / 8.5.70
WPVR – 360 Panorama viewer and Virtual Tour Builder for WordPress v8.5.70
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 8.5.4 All 221 releases
wpvr / admin / js / wpvr-admin.js

wpvr-admin.js in WPVR – 360 Panorama viewer and Virtual Tour Builder for WordPress 8.5.70, at admin/js/wpvr-admin.js

3,709 lines 167.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 (function ($) {
2 'use strict';
3 var j = 1;
4 var color = '#00b4ff';
5 var scene_parent = '';
6 var scene_uploader = null;
7 var scene_upload_parent = null;
8
9 window.jQuery.migrateMute = true;
10 /**
11 * All of the code for your admin-facing JavaScript source
12 * should reside in this file.
13 *
14 * Note: It has been assumed you will write jQuery code here, so the
15 * $ function reference has been prepared for usage within the scope
16 * of this function.
17 *
18 * This enables you to define handlers, for when the DOM is ready:
19 *
20 * $(function() {
21 *
22 * });
23 *
24 * When the window is loaded:
25 *
26 * $( window ).load(function() {
27 *
28 * });
29 *
30 * ...and/or other possibilities.
31 *
32 * Ideally, it is not considered best practise to attach more than a
33 * single DOM-ready or window-load handler for a particular page.
34 * Although scripts in the WordPress core, Plugins and Themes may be
35 * practising this, we should strive to set a better example in our own work.
36 */
37
38 let lastChildClicked = false;
39 $(document).ready(function () {
40 if($('#scene-1').find('input.sceneid').val()){
41 $('.scene-gallery').append('<ul style="width:150px;"><li class="owlscene owl" ></li><li title="Double click to Upload scene"><div class="upload-scene-wrapper"><img loading="lazy" class="scctrl upload-form-scene-gallery" src="'+window.wpvr_localize.WPVR_ASSET_PATH+'/icon/scene-upload.svg"><p>Upload Scene</p></div></li></ul>');
42 }else{
43 $('.scene-gallery').append('<ul style="width:150px;"><li class="owlscene owl" ></li><li title="Double click to Upload scene"><div class="upload-scene-wrapper-first"><img loading="lazy" class="scctrl upload-form-scene-gallery-first" src="'+window.wpvr_localize.WPVR_ASSET_PATH+'/icon/scene-upload.svg"><p>Upload Scene</p></div></li></ul>');
44 }
45
46 $(".vrowl-carousel").owlCarousel({
47 margin: 10,
48 autoWidth: true,
49 nav: true
50 });
51
52 var primary_markng = $('#scene-1').find('input.sceneid').val();
53 $('.owl' + primary_markng).parents('.owl-item').addClass('marked');
54
55 $('.meta-box-sortables').sortable({
56 items: '#wpvr_item_builder_box',
57 disabled: true
58 });
59
60 $('.postbox .hndle').css('cursor', 'pointer');
61
62 // Validate scene checkbox on page load
63 setTimeout(function() {
64 let sceneImageCount = $('.rex-pano-tab .single-scene .scene-left .scene-setting .form-group img')
65 .filter(function() {
66 return $(this).attr('src') && $(this).attr('src').trim() !== '';
67 })
68 .length;
69
70 var panovideo = $("input[name='panovideo']:checked").val();
71 var videourl = $("input[name='video-attachment-url']").val();
72 var hasContent = (panovideo === 'on' && videourl && videourl.trim() !== '') || sceneImageCount > 0;
73
74 if (sceneImageCount === 0) {
75 $('#wpvr-check-scene').prop('checked', false);
76 $('#wpvr-check-media').prop('checked', false);
77 $('#wpvr-check-scene').closest('.wpvr-checklist-item').css('color', '#73707D');
78 $('#wpvr-check-media').closest('.wpvr-checklist-item').css('color', '#73707D');
79 updateProgress();
80 }
81
82 // Hide Panellum loading box if no content
83 if (!hasContent) {
84 $('.pnlm-load-box').hide();
85 }
86 }, 100);
87
88
89 });
90
91 $(document).on("change", "input.vr-switcher-check", function (event) {
92 updateCheckboxStates();
93 $(this).val(this.checked ? 'on' : 'off');
94 });
95
96 updateCheckboxStates();
97 function updateCheckboxStates() {
98 // Check movement controls if wpvr_controls is checked
99 if ($('#wpvr_controls').prop('checked')) {
100 $('#wpvr-check-movement-controls').prop('checked', true);
101 $('#wpvr-check-movement-controls').closest('.wpvr-checklist-item').css('color', '#0E003C');
102 } else if (!$('#wpvr_controls').prop('checked')) {
103 $('#wpvr-check-movement-controls').prop('checked', false);
104 $('#wpvr-check-movement-controls').closest('.wpvr-checklist-item').css('color', '#73707D');
105 }
106
107 // Check zoom controls if either wpvr_mouseZoom or wpvr_keyboardzoom is checked
108 if (($('#wpvr_mouseZoom').prop('checked') || $('#wpvr_keyboardzoom').prop('checked'))) {
109 $('#wpvr-check-zoom-controls').prop('checked', true);
110 $('#wpvr-check-zoom-controls').closest('.wpvr-checklist-item').css('color', '#0E003C');
111 } else if (!$('#wpvr_mouseZoom').prop('checked') && !$('#wpvr_keyboardzoom').prop('checked')) {
112 $('#wpvr-check-zoom-controls').prop('checked', false);
113 $('#wpvr-check-zoom-controls').closest('.wpvr-checklist-item').css('color', '#73707D');
114 }
115
116 updateProgress();
117 }
118
119
120 // === Pro Preview: Sticky Banner & Watermark for Free Users on Advanced Controls ===
121 (function initProPreview() {
122 if (typeof wpvr_obj === 'undefined' || wpvr_obj.is_wpvr_pro_active) {
123 return;
124 }
125
126 var $banner = $('#wpvr-pro-preview-banner');
127 var $watermark = $('#wpvr-pro-preview-watermark');
128
129 // All toggleable IDs in the Advanced Controls tab
130 var advancedControlIds = [
131 'wpvr_diskeyboard', 'wpvr_keyboardzoom', 'wpvr_draggable',
132 'wpvr_mouseZoom', 'wpvr_gyro', 'wpvr_deviceorientationcontrol', 'wpvr_compass',
133 'wpvr_vrgallery', 'wpvr_vrgallery_title', 'wpvr_scene_navigation',
134 'wpvr_bg_music', 'wpvr_explainerSwitch', 'wpvr_globalzoom', 'wpvr_cpLogoSwitch'
135 ];
136
137 // Option A: IDs whose effect is visible via pannellum config (auto-trigger preview)
138 var pannellumConfigIds = [
139 'wpvr_compass', 'wpvr_diskeyboard', 'wpvr_keyboardzoom',
140 'wpvr_draggable', 'wpvr_mouseZoom'
141 ];
142
143 // Option B: IDs mapped to their mockup overlay elements
144 var mockupMap = {
145 'wpvr_vrgallery': '#wpvr-pro-mockup-gallery',
146 'wpvr_scene_navigation': '#wpvr-pro-mockup-navigation',
147 'wpvr_bg_music': '#wpvr-pro-mockup-audio',
148 'wpvr_gyro': '#wpvr-pro-mockup-gyro'
149 };
150
151 var previewDebounceTimer = null;
152
153 // Enable the disabled checkboxes in the advanced controls tab for Pro Preview
154 function enableAdvancedToggles() {
155 $('#gen-advanced input.vr-switcher-check[disabled]').each(function () {
156 $(this).prop('disabled', false).addClass('wpvr-pro-preview-toggle');
157 });
158 }
159
160 function hasAnyAdvancedToggleOn() {
161 for (var i = 0; i < advancedControlIds.length; i++) {
162 var $el = $('#' + advancedControlIds[i]);
163 if ($el.length && $el.prop('checked')) {
164 return true;
165 }
166 }
167 return false;
168 }
169
170 function updateProPreviewState() {
171 if (hasAnyAdvancedToggleOn()) {
172 $banner.slideDown(200);
173 $watermark.fadeIn(200);
174 } else {
175 $banner.slideUp(200);
176 $watermark.fadeOut(200);
177 }
178 }
179
180 // Option B: Show/hide CSS mockup overlays based on toggle state
181 function updateMockups() {
182 $.each(mockupMap, function (toggleId, mockupSelector) {
183 var $checkbox = $('#' + toggleId);
184 var $mockup = $(mockupSelector);
185 if ($checkbox.length && $checkbox.prop('checked')) {
186 $mockup.fadeIn(200);
187 } else {
188 $mockup.fadeOut(200);
189 }
190 });
191
192 // Adjust audio mockup position when gallery is also visible
193 var galleryOn = $('#wpvr_vrgallery').prop('checked');
194 var $audio = $('#wpvr-pro-mockup-audio');
195 if (galleryOn) {
196 $audio.addClass('wpvr-pro-mockup--has-gallery');
197 } else {
198 $audio.removeClass('wpvr-pro-mockup--has-gallery');
199 }
200 }
201
202 // Option A: Auto-trigger preview for features that work via pannellum config
203 function autoTriggerPreview(toggleId) {
204 if (pannellumConfigIds.indexOf(toggleId) === -1) {
205 return;
206 }
207 // Only auto-preview if a scene image exists
208 var hasScene = $('#scene-1').find('input.sceneid').val();
209 if (!hasScene) {
210 return;
211 }
212 clearTimeout(previewDebounceTimer);
213 previewDebounceTimer = setTimeout(function () {
214 $('.panolenspreview').trigger('click');
215 }, 600);
216 }
217
218 // Listen for toggle changes on advanced control checkboxes
219 $(document).on('change', '#gen-advanced input.vr-switcher-check', function () {
220 updateProPreviewState();
221 updateMockups();
222 autoTriggerPreview($(this).attr('id'));
223 });
224
225 // Update state when the Advanced Controls tab is shown
226 $(document).on('click', '.inner-nav li.gen-advanced', function () {
227 setTimeout(function () {
228 enableAdvancedToggles();
229 updateProPreviewState();
230 updateMockups();
231 }, 100);
232 });
233
234 // Initial check when DOM is ready
235 $(document).ready(function () {
236 enableAdvancedToggles();
237 if ($('#gen-advanced').is(':visible')) {
238 updateProPreviewState();
239 updateMockups();
240 }
241 });
242 })();
243 // === End Pro Preview ===
244
245
246 var specificeSceneID = ''
247 var newScene = ''
248 $(document).on("click", ".scene-nav ul li span", function (event) {
249 $('.owl-item').removeClass('marked');
250 setTimeout(function(){
251 var target = $('.scene-nav ul li.active span').attr("data-index");
252 if(target == undefined){
253 var currentLi = $(this).parent('li');
254 var previousLi = currentLi.prev();
255 if (previousLi.length > 0) {
256 newScene = previousLi.find('span').attr('data-index');
257 }
258 }
259 var data = $('#scene-' + target).find('input.sceneid').val();
260 if (data) {
261 specificeSceneID = data;
262 if(!lastChildClicked){
263 $('.panolenspreview').trigger('click')
264 }
265 $('.owl' + data).parents('.owl-item').addClass('marked');
266 }
267 lastChildClicked = false;
268 }, 500);
269 });
270
271 jQuery(document).ready(function ($) {
272
273 j = $('#scene-1').find('.hotspot-nav li').eq(-2).find('span').attr('data-index');
274 var ajaxurl = wpvr_obj.ajaxurl;
275 $('.panolenspreview').on('click', function (e) {
276 e.preventDefault();
277 $('.wpvr-loading').show();
278 var videourl = $("input[name='video-attachment-url']").val();
279 var autoplay = $("input[name='autoplay']:checked").val();
280 var loop = $("input[name='loop']:checked").val();
281
282 var panovideo = $("input[name='panovideo']:checked").val();
283
284 var postid = $("#post_ID").val();
285 var autoload = $("input[name='autoload']").is(':checked') ? 'on' : 'off';
286 var compass = $("input[name='compass']:checked").val();
287 var control = $("input[name='controls']").is(':checked') ? 'on' : 'off';
288 var rotation = $("input[name='autorotation']").is(':checked') ? 'on' : 'off';
289 var defaultscene = $("input[name='default-scene-id']").val();
290 var preview = $("input[name='preview-attachment-url']").val();
291 var scenefadeduration = $("input[name='scene-fade-duration']").val();
292
293 var autorotation = $("input[name='auto-rotation']").val();
294 var autorotationinactivedelay = $("input[name='auto-rotation-inactive-delay']").val();
295 var autorotationstopdelay = $("input[name='auto-rotation-stop-delay']").val();
296
297 var panodata = $('.scene-setup').repeaterVal();
298 const filteredPanodata = {
299 ...panodata,
300 "scene-list": panodata["scene-list"].filter(
301 scene => scene["scene-id"]?.trim()
302 )
303 };
304 var panolist = JSON.stringify(filteredPanodata);
305 var previewtext = $('.previewtext').val();
306
307 // Collect advanced control values for Pro Preview.
308 // draggable defaults to 'on' — it is a basic feature and must be
309 // enabled in the preview so pannellum can capture hotspot coordinates.
310 var diskeyboard = $('#wpvr_diskeyboard').is(':checked') ? 'on' : 'off';
311 var keyboardzoom = $('#wpvr_keyboardzoom').is(':checked') ? 'on' : 'off';
312 var draggable = 'on'; // always enabled; dragging is required for hotspot coordinate capture
313 var mouseZoom = $('#wpvr_mouseZoom').is(':checked') ? 'on' : 'off';
314 var gyro = $('#wpvr_gyro').is(':checked') ? 'on' : 'off';
315 var deviceorientationcontrol = $('#wpvr_deviceorientationcontrol').is(':checked') ? 'on' : 'off';
316
317 jQuery.ajax({
318 type: "POST",
319 url: ajaxurl,
320 data: {
321 action: "wpvr_preview",
322 nonce : wpvr_obj.ajax_nonce,
323 postid: postid,
324 compass: compass,
325 control: control,
326 autoload: autoload,
327 panodata: panolist,
328 defaultscene: defaultscene,
329 rotation: rotation,
330 autorotation: autorotation,
331 autorotationinactivedelay: autorotationinactivedelay,
332 autorotationstopdelay: autorotationstopdelay,
333 preview: preview,
334 scenefadeduration: scenefadeduration,
335 panovideo: panovideo,
336 videourl: videourl,
337 autoplay: autoplay,
338 loop: loop,
339 // vidautoplay: vidautoplay,
340 // vidcontrol: vidcontrol,
341 diskeyboard: diskeyboard,
342 keyboardzoom: keyboardzoom,
343 draggable: draggable,
344 mouseZoom: mouseZoom,
345 gyro: gyro,
346 deviceorientationcontrol: deviceorientationcontrol
347 },
348
349 success: function (response) {
350 $('.wpvr-loading').hide();
351 if (response.success == true) {
352 if(response.data[2] == 'off'){
353 $('#error_occured').hide();
354 $('#error_occuredpub').hide();
355 $('#' + response.data[0]["panoid"]).empty();
356 var scenes = response.data[1];
357
358 if (scenes) {
359 $.each(scenes.scenes, function (i) {
360 $.each(scenes.scenes[i]['hotSpots'], function (key, val) {
361 if (
362 val["clickHandlerArgs"] &&
363 val["clickHandlerArgs"].replace(/<[^>]*>/g, '').trim() !== ''
364 ) {
365 val["clickHandlerFunc"] = wpvrhotspot;
366 }
367 if (
368 val["createTooltipArgs"] &&
369 val["createTooltipArgs"].replace(/<[^>]*>/g, '').trim() !== ''
370 ) {
371 val["createTooltipFunc"] = wpvrtooltip;
372 }
373 });
374 });
375 }
376 if (scenes) {
377 $('.scene-gallery').trigger('destroy.owl.carousel');
378 $('.scene-gallery').empty();
379
380 $.each(scenes.scenes, function (key, val) {
381 $('.scene-gallery').append('<ul style="width:150px;"><li class="owlscene owl' + key + '">' + key + '</li><li title="Double click to view scene"><img loading="lazy" class="scctrl" id="' + key + '_gallery" src="' + val.panorama + '"></li></ul>');
382 });
383 $('.scene-gallery').append('<ul style="width:150px;"><li class="owlscene owl" ></li><li title="Double click to Upload scene"><div class="upload-scene-wrapper"><img loading="lazy" class="scctrl upload-form-scene-gallery" src="'+window.wpvr_localize.WPVR_ASSET_PATH+'/icon/scene-upload.svg"><p>Upload Image</p></div></li></ul>');
384
385 $(".vrowl-carousel").owlCarousel({
386 margin: 10,
387 autoWidth: true,
388 });
389 var active_owl_target = $('#wpvr_active_scenes').val();
390 var get_owl_target = $('#scene-' + active_owl_target).find('input.sceneid').val();
391 $('.owl' + get_owl_target).parents('.owl-item').addClass('marked');
392 }
393
394 if(!scenes.autoLoad){
395 jQuery('.pnlm-controls-container').hide();
396 }
397
398 var panoshow = pannellum.viewer(response.data[0]["panoid"], scenes);
399
400 panoshow.on('load', function(){
401 jQuery('.pnlm-controls-container').show();
402 });
403
404 if (scenes.autoRotate) {
405 panoshow.on('load', function () {
406 setTimeout(function () {
407 panoshow.startAutoRotate(scenes.autoRotate, 0);
408 }, 3000);
409 });
410 panoshow.on('scenechange', function () {
411 setTimeout(function () {
412 panoshow.startAutoRotate(scenes.autoRotate, 0);
413 }, 3000);
414 });
415 }
416 var touchtime = 0;
417 if (scenes) {
418 $.each(scenes.scenes, function (key, val) {
419 document.getElementById('' + key + '_gallery').addEventListener('click', function (e) {
420 if (touchtime == 0) {
421 touchtime = new Date().getTime();
422 } else {
423 if (((new Date().getTime()) - touchtime) < 800) {
424 panoshow.loadScene(key);
425 activateSceneTab(key)
426 touchtime = 0;
427 } else {
428 touchtime = new Date().getTime();
429 }
430 }
431 });
432 });
433 }
434 if( newScene){
435 var data = $('#scene-' + newScene).find('input.sceneid').val();
436 if(data){
437 panoshow.loadScene(data);
438 }
439 //newScene = ''
440 }
441 if(specificeSceneID){
442 setTimeout(() => {
443 panoshow.loadScene(specificeSceneID);
444 }, 500);
445 }
446 $('html, body').animate({
447 scrollTop: $("#wpvr_item_builder__box").offset().top
448 }, 500);
449 //set preview text
450 if ("" != previewtext) {
451 $('.pnlm-load-button p').text(previewtext);
452 }
453 }else{
454 $('#' + response.data["panoid"]).empty();
455 $('#' + response.data["panoid"]).html(response.data["panodata"]);
456 if (response.data['vidtype'] == 'selfhost') {
457 videojs(response.data["vidid"], {
458 plugins: {
459 pannellum: {}
460 }
461 });
462 }
463 $('html, body').animate({
464 scrollTop: $("#wpvr_item_builder__box").offset().top
465 }, 500);
466 }
467
468 } else {
469 $('#error_occured').show();
470 $('#error_occured .pano-error-message').html(response.data);
471 $('#error_occuredpub').show();
472 $('#error_occuredpub').html(response.data);
473 $('body').addClass('error-overlay');
474 $('html, body').animate({
475 scrollTop: $("#error_occured").offset().top
476 }, 500);
477 }
478
479 }
480 });
481 });
482 });
483
484
485 function sanitizeText(str) {
486 if (!str) return '';
487 // Remove all <script> tags and their content
488 str = str.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, '');
489 // Optional: remove all remaining HTML tags if you want plain text
490 str = str.replace(/<\/?[^>]+(>|$)/g, "");
491 return str;
492 }
493
494
495 function activateSceneTab(sceneId){
496 jQuery(".scene-nav ul li span").each(function() {
497 // Get the value of the data-href attribute
498 var dataHrefValue = jQuery(this).attr("data-href");
499 var currentScene = jQuery(dataHrefValue).find('input.sceneid').val();
500
501 if(sceneId == currentScene){
502 jQuery(this).trigger('click');
503 }
504 });
505 }
506
507 //-- Set Cookie--//
508
509 function setCookie(cName, cValue, expDays) {
510 let date = new Date();
511 date.setTime(date.getTime() + (expDays * 24 * 60 * 60 * 1000));
512 const expires = "expires=" + date.toUTCString();
513 document.cookie = cName + "=" + cValue + "; " + expires + "; path=/";
514 }
515 // Get a cookie
516
517 function getCookie(cName) {
518 const name = cName + "=";
519 const cDecoded = decodeURIComponent(document.cookie); //to be careful
520 const cArr = cDecoded .split('; ');
521 let res;
522 cArr.forEach(val => {
523 if (val.indexOf(name) === 0) res = val.substring(name.length);
524 })
525 return res;
526 }
527
528 function getParameterByName(name, url = window.location.href) {
529 name = name.replace(/[\[\]]/g, '\\$&');
530 var regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)'),
531 results = regex.exec(url);
532 if (!results) return null;
533 if (!results[2]) return '';
534 return decodeURIComponent(results[2].replace(/\+/g, ' '));
535 }
536 function findValueByName(name,dataArray) {
537 for (var i = 0; i < dataArray.length; i++) {
538 if (dataArray[i].name === name) {
539 return dataArray[i].value;
540 }
541 }
542 // Return a default value or handle the case when the name is not found
543 return '';
544 }
545
546 jQuery(document).ready(function ($) {
547 var getRedirectUrl = getCookie("redirectUrl");
548 var getCookiePostID = getCookie("postID");
549
550 const urlParams = getParameterByName("active_tab");
551 const action = wpvr_global_obj.url_info.param.action;
552 let getPostID = wpvr_global_obj.url_info.param.post;
553
554 if(getCookiePostID == getPostID){
555 if(urlParams == '' || urlParams == undefined){
556 if (action == 'edit' && getRedirectUrl != undefined){
557 window.location.replace(getRedirectUrl)
558 setCookie('postID', '', 1);
559 setCookie('redirectUrl', '', 1);
560 }
561 }
562 }
563 var flag_ok = false;
564 $('#publish').on('click', function (e) {
565 e.preventDefault();
566
567 var hidden_post_status = $('#hidden_post_status').val() || 'auto-draft';
568 var action_type = (hidden_post_status === 'publish') ? 'update' : 'publish';
569 $('#publish').prop('disabled', true);
570 $('.panolenspreview').trigger('click')
571 var data = $('form#post').serializeArray();
572 var post_status = findValueByName('post_status',data)
573 var hidden_post_status = findValueByName('hidden_post_status',data)
574 var hidden_post_password = findValueByName('hidden_post_password',data)
575 var hidden_post_visibility = findValueByName('hidden_post_visibility',data)
576 var visibility = findValueByName('visibility',data)
577 var post_password = findValueByName('post_password',data)
578 var post_title = findValueByName('post_title',data)
579 var x = $(this).val();
580 // if (!flag_ok) {
581 $('.wpvr-loading').show();
582 var postid = Number($("#post_ID").val() || 0);
583 var panovideo = $("input[name='panovideo']:checked").val();
584 var videourl = $("input[name='video-attachment-url']").val();
585 var autoload = $("input[name='autoload']").is(':checked') ? 'on' : 'off';
586 var control = $("input[name='controls']").is(':checked') ? 'on' : 'off';
587 var compass = $("input[name='compass']:checked").val();
588 var defaultscene = $("input[name='default-scene-id']").val();
589 var preview = $("input[name='preview-attachment-url']").val();
590 var rotation = $("input[name='autorotation']").is(':checked') ? 'on' : 'off'; // Auto Rotation checkbox value
591 var autorotation = $("input[name='auto-rotation']").val();
592 var autorotationinactivedelay = $("input[name='auto-rotation-inactive-delay']").val();
593 var autorotationstopdelay = $("input[name='auto-rotation-stop-delay']").val();
594
595 var scenefadeduration = $("input[name='scene-fade-duration']").val();
596 var previewtext = $('.previewtext').val();
597 if ($('.scene-setup')[0]) {
598 var panodata = $('.scene-setup').repeaterVal();
599
600 var panolist = JSON.stringify(panodata);
601 } else {
602 var panodata = '';
603 var panolist = '';
604 }
605
606
607 //get the checklist data
608 var checklistData = {};
609 var checklistKeys = [
610 'scene',
611 'media',
612 'default',
613 'hotspots',
614 'movement-controls',
615 'publish'
616 ];
617
618 if(wpvr_obj?.is_wpvr_pro_active){
619 checklistKeys.push('zoom-controls');
620 }
621
622 checklistKeys.forEach(function (key) {
623 checklistData['wpvr_check_' + key] = document.getElementById('wpvr-check-' + key).checked;
624 });
625
626 jQuery.ajax({
627
628 type: "POST",
629 url: ajaxurl,
630 data: {
631 action: "wpvr_save",
632 action_type: action_type,
633 nonce : wpvr_obj.ajax_nonce,
634 postid: postid,
635 panovideo: panovideo,
636 videourl: videourl,
637 control: control,
638 compass: compass,
639 autoload: autoload,
640 panodata: panolist,
641 defaultscene: defaultscene,
642 preview: preview,
643 rotation: rotation, // Auto Rotation checkbox value
644 autorotation: autorotation, // Rotatin speed
645 autorotationinactivedelay: autorotationinactivedelay,
646 autorotationstopdelay: autorotationstopdelay,
647 scenefadeduration: scenefadeduration,
648 previewtext: previewtext,
649
650 hidden_post_status: hidden_post_status,
651 post_status: post_status,
652 hidden_post_password: hidden_post_password,
653 hidden_post_visibility: hidden_post_visibility,
654 visibility: visibility,
655 post_password: post_password,
656 post_value: $('#publish').val(),
657 post_title: post_title,
658 checklistData: checklistData,
659 },
660
661 success: function (response) {
662
663 $('.wpvr-loading').hide();
664 $('#publish').prop('disabled', false);
665 if (response.success == false) {
666 $('#error_occured').show();
667 $('#error_occured .pano-error-message').html(response.data);
668 $('#error_occuredpub').show();
669 $('#error_occuredpub').html(response.data);
670
671 $('body').addClass('error-overlay');
672 $('html, body').animate({
673 scrollTop: $("#error_occured").offset().top
674 }, 500);
675 } else {
676 $('#hidden_post_status').val(response.data.post_status)
677 if(!$('#wpvr-check-publish').prop('checked')){
678 $('#wpvr-check-publish').prop('checked', true);
679 $('#wpvr-check-publish').closest('.wpvr-checklist-item').css('color', '#0E003C');
680 }
681 updateProgress();
682
683 flag_ok = true;
684 $("#publishing-action").prepend(
685 `<div class="success-message" id="wpvr-success-message">
686 <p>${wpvr_obj?.successfully_updated}</p>
687 </div>`
688 );
689 setTimeout(function(){
690 $("#wpvr-success-message").remove();
691 }, 3000 );
692 var url_info = wpvr_global_obj.url_info
693 var oldUrl = '';
694 let params = (new URL(document.location)).searchParams;
695 let active_tab = params.get('active_tab');
696 oldUrl = url_info.admin_url+"post.php?"+"post="+postid+"&action=edit"+"&active_tab="+active_tab;
697 if ( 'add' == url_info.screen ){
698 setCookie('redirectUrl', oldUrl, 1);
699 setCookie('postID', postid, 1);
700 }else{
701 setCookie('postID', postid, 1);
702
703 setCookie('redirectUrl', oldUrl, 1);
704 }
705 var published_label = wpvr_obj?.published_text || 'Published';
706 if ($("#post_status option[value='publish']").length === 0) {
707 $("#post_status").append('<option value="publish">' + published_label + '</option>');
708 }
709
710 if (response.data.post_status === 'publish') {
711 $("#post_status").val('publish');
712 $("#hidden_post_status").val('publish');
713 $("#post-status-display").text(published_label);
714 } else {
715 var statusText = $("#post_status option:selected").text();
716 $("#post-status-display").text(statusText);
717 }
718
719 var status = response.data.post_status;
720 var statusText = 'publish' == status ? 'Published' : $("#post_status").val()
721 $("#post-status-display").text(statusText);
722 let site_language = wpvr_obj?.site_language;
723 let translatedText = wpvr_obj?.translated_languages?.[site_language] ?? {};
724 if(response.data.post_status == 'draft'){
725 let publish_text = translatedText?.['Publish'] ?? 'Publish';
726 $('#publish').val(publish_text);
727 }else{
728 let update_text = translatedText?.['Update'] ?? 'Update';
729 $('#publish').val(update_text);
730 }
731 window.history.replaceState(null, '', url_info.admin_url+"post.php?"+"post="+postid+"&action=edit");
732 resetPostFormDirtyState();
733 }
734 }
735 });
736 // }
737 });
738 });
739
740 function resetPostFormDirtyState() {
741 const $form = $('#post');
742
743 if (!$form.length) {
744 return;
745 }
746
747 // Reset browser-level dirty tracking
748 $form.find('input, textarea, select').each(function () {
749 if (this.type !== 'checkbox' && this.type !== 'radio') {
750 this.defaultValue = this.value;
751 }
752 });
753
754 $form.find('input[type="checkbox"], input[type="radio"]').each(function () {
755 this.defaultChecked = this.checked;
756 });
757
758 // Reset WordPress dirty tracking
759 if (typeof wp !== 'undefined' && wp.autosave && wp.autosave.server) {
760 wp.autosave.server.postChanged = false;
761 }
762 }
763
764 jQuery(document).ready(function ($) {
765 $("body, .pano-error-close-btn").on("click", function (e) {
766 $("#error_occured").hide();
767 $('body').removeClass('error-overlay');
768 });
769
770 $(".panolenspreview, #error_occured").on("click", function (e) {
771 e.stopPropagation();
772 });
773 });
774
775 jQuery(document).ready(function ($) {
776 var previewtext = $('.previewtext').val();
777 if ("" != previewtext) {
778 $('.pnlm-load-button p').text(previewtext);
779 }
780 });
781
782 jQuery(document).ready(function ($) {
783
784 var flag_ok = false;
785 $('#save-post').on('click', function (e) {
786 var x = $(this).val();
787 if (!flag_ok) {
788 e.preventDefault();
789 $('.wpvr-loading').show();
790 var postid = $("#post_ID").val();
791 var panovideo = $("input[name='panovideo']:checked").val();
792 var videourl = $("input[name='video-attachment-url']").val();
793 var autoload = $("input[name='autoload']").is(':checked') ? 'on' : 'off';
794 var control = $("input[name='controls']").is(':checked') ? 'on' : 'off';
795 var compass = $("input[name='compass']:checked").val();
796 var defaultscene = $("input[name='default-scene-id']").val();
797 var preview = $("input[name='preview-attachment-url']").val();
798 var rotation = $("input[name='autorotation']").is(':checked') ? 'on' : 'off';
799 var autorotation = $("input[name='auto-rotation']").val();
800 var autorotationinactivedelay = $("input[name='auto-rotation-inactive-delay']").val();
801 var autorotationstopdelay = $("input[name='auto-rotation-stop-delay']").val();
802
803 var scenefadeduration = $("input[name='scene-fade-duration']").val();
804 var previewtext = $('.previewtext').val();
805
806 if ($('.scene-setup')[0]) {
807 var panodata = $('.scene-setup').repeaterVal();
808 var panolist = JSON.stringify(panodata);
809 } else {
810 var panodata = '';
811 var panolist = '';
812 }
813
814 //get the checklist data
815 var checklistData = {};
816 var checklistKeys = [
817 'scene',
818 'media',
819 'default',
820 'hotspots',
821 'movement-controls',
822 'publish'
823 ];
824
825 if(wpvr_localize?.is_wpvr_pro_active){
826 checklistKeys.push('zoom-controls');
827 }
828
829 checklistKeys.forEach(function (key) {
830 checklistData['wpvr_check_' + key] = document.getElementById('wpvr-check-' + key).checked;
831 });
832
833 updateProgress();
834
835 jQuery.ajax({
836
837 type: "POST",
838 url: ajaxurl,
839 data: {
840 action: "wpvr_save",
841 nonce : wpvr_obj.ajax_nonce,
842 postid: postid,
843 panovideo: panovideo,
844 videourl: videourl,
845 control: control,
846 compass: compass,
847 autoload: autoload,
848 panodata: panolist,
849 defaultscene: defaultscene,
850 preview: preview,
851 rotation: rotation,
852 autorotation: autorotation,
853 autorotationinactivedelay: autorotationinactivedelay,
854 autorotationstopdelay: autorotationstopdelay,
855 scenefadeduration: scenefadeduration,
856 previewtext: previewtext,
857 checklistData: checklistData
858 },
859
860 success: function (response) {
861 $('.wpvr-loading').hide();
862 if (response.success == false) {
863 $('#error_occured').show();
864 $('#error_occured').html(response.data);
865 $('#error_occuredpub').show();
866 $('#error_occuredpub').html(response.data);
867
868 $('body').addClass('error-overlay');
869 $('html, body').animate({
870 scrollTop: $("#error_occured").offset().top
871 }, 500);
872 } else {
873
874 // Only check publish checkbox if post is actually published
875 if (response.data.post_status === 'publish') {
876 if(!$('#wpvr-check-publish').prop('checked')){
877 $('#wpvr-check-publish').prop('checked', true);
878 $('#wpvr-check-publish').closest('.wpvr-checklist-item').css('color', '#0E003C');
879 }
880 } else {
881 // Uncheck if it's a draft
882 if($('#wpvr-check-publish').prop('checked')){
883 $('#wpvr-check-publish').prop('checked', false);
884 $('#wpvr-check-publish').closest('.wpvr-checklist-item').css('color', '#73707D');
885 }
886 }
887
888 // Validate scene checkbox state after save
889 let sceneImageCount = $('.rex-pano-tab .single-scene .scene-left .scene-setting .form-group img')
890 .filter(function() {
891 return $(this).attr('src') && $(this).attr('src').trim() !== '';
892 })
893 .length;
894
895 if (sceneImageCount === 0) {
896 $('#wpvr-check-scene').prop('checked', false);
897 $('#wpvr-check-media').prop('checked', false);
898 $('#wpvr-check-scene').closest('.wpvr-checklist-item').css('color', '#73707D');
899 $('#wpvr-check-media').closest('.wpvr-checklist-item').css('color', '#73707D');
900 }
901
902 updateProgress();
903
904 flag_ok = true;
905 $('#save-post').trigger('click');
906 }
907 }
908 });
909 }
910 });
911 });
912
913 function wpvrhotspot(hotSpotDiv, args) {
914 if (args) {
915 const hasTextContent = args.replace(/<[^>]*>/g, '').trim() !== '';
916 const hasMediaContent = /<(img|video|audio|iframe|embed|object)\b[^>]*>/i.test(args);
917 const hasOtherContent = args.replace(/<(p|br|div|span)\b[^>]*\/?>/gi, '').trim() !== '';
918
919 if (hasTextContent || hasMediaContent || hasOtherContent) {
920 const cleanArgs = args.replace(/\\/g, '');
921 $("#custom-ifram").html(cleanArgs);
922 $("#custom-ifram").fadeToggle();
923 $(".iframe-wrapper").toggleClass("show-modal");
924 }
925 }
926 }
927
928 function wpvrtooltip(hotSpotDiv, args) {
929 if (args) {
930 const hasTextContent = args.replace(/<[^>]*>/g, '').trim() !== '';
931 const hasMediaContent = /<(img|video|audio|iframe|embed|object)\b[^>]*>/i.test(args);
932 const hasOtherContent = args.replace(/<(p|br|div|span)\b[^>]*\/?>/gi, '').trim() !== '';
933
934 if (hasTextContent || hasMediaContent || hasOtherContent) {
935 const cleanArgs = args.replace(/\\/g, '');
936 hotSpotDiv.classList.add('custom-tooltip');
937
938 const span = document.createElement('p');
939 span.innerHTML = cleanArgs;
940 hotSpotDiv.appendChild(span);
941
942 span.style.marginLeft = -(span.scrollWidth - hotSpotDiv.offsetWidth) / 2 + 'px';
943 span.style.marginTop = -span.scrollHeight - 12 + 'px';
944
945 if (!document.getElementById('wpvr-tooltip-style')) {
946 const style = document.createElement('style');
947 style.id = 'wpvr-tooltip-style';
948 style.textContent = `
949 .table, .table td, .table th {
950 border: 1px solid #dee2e6;
951 border-collapse: collapse;
952 padding: 8px;
953 }
954 `;
955 document.head.appendChild(style);
956 }
957 }
958 }
959 }
960
961
962 jQuery(document).ready(function ($) {
963 $("#cross").on("click", function (e) {
964 e.preventDefault();
965 $("#custom-ifram").fadeOut();
966 $(".iframe-wrapper").removeClass("show-modal");
967 $('iframe').attr('src', $('iframe').attr('src'));
968 });
969 });
970
971 jQuery(document).ready(function ($) {
972
973 var i = $('.scene-nav li').eq(-2).find('span').attr('data-index');
974 i = parseInt(i);
975
976 $('.scene-setup').repeater({
977
978 defaultValues: {
979 'scene-type': 'equirectangular',
980 'dscene': 'off',
981 'ptyscene': 'off',
982 'cvgscene': 'off',
983 'chgscene': 'off',
984 'czscene': 'off',
985 },
986 show: function () {
987 $('textarea[name*=hotspot-content]').summernote({
988 toolbar: [
989 ['style', ['style']],
990 ['font', ['bold', 'underline', 'clear']],
991 ['fontname', ['fontname']],
992 ['color', ['color']],
993 ['para', ['ul', 'ol', 'paragraph']],
994 ['table', ['table']],
995 ['insert', ['link', 'picture', 'video']],
996 ['view', ['codeview', 'help']],
997 ],
998 callbacks: {
999 onInit: function() {
1000 var $editor = $(this);
1001 var $noteEditor = $editor.next('.note-editor');
1002
1003 // Intercept Video button click
1004 $noteEditor.on('click', 'button.note-btn[aria-label="Video"]', function(e) {
1005 // Small delay to check if cursor is on a video
1006 setTimeout(function() {
1007 // Get the current selection
1008 var range = $editor.summernote('createRange');
1009 if (range) {
1010 var $node = $(range.sc);
1011
1012 // Check if cursor is on a video iframe
1013 var $iframe = $node.closest('iframe.note-video-clip');
1014 if (!$iframe.length) {
1015 $iframe = $node.find('iframe.note-video-clip').first();
1016 }
1017
1018 if ($iframe.length && $iframe.attr('src')) {
1019 var embedUrl = $iframe.attr('src');
1020 var videoUrl = '';
1021
1022 // Extract YouTube URL
1023 if (embedUrl && (embedUrl.indexOf('youtube.com') > -1 || embedUrl.indexOf('youtu.be') > -1)) {
1024 var match = embedUrl.match(/embed\/([^?&]*)/);
1025 if (match && match[1]) {
1026 videoUrl = 'https://www.youtube.com/watch?v=' + match[1];
1027 }
1028 } else if (embedUrl) {
1029 videoUrl = embedUrl;
1030 }
1031
1032 // Show the video dialog
1033 $editor.summernote('videoDialog.show');
1034
1035 // Pre-populate the video URL in the dialog
1036 setTimeout(function() {
1037 var $urlInput = $('.note-video-url');
1038 if ($urlInput.length && videoUrl) {
1039 $urlInput.val(videoUrl);
1040 $urlInput.focus();
1041 }
1042 }, 150);
1043 }
1044 }
1045 }, 50);
1046 });
1047 },
1048 onKeyup: function(e) {
1049 var getHotspotContent = $(this).summernote('code').trim();
1050 var tempDiv = document.createElement('div');
1051 tempDiv.innerHTML = getHotspotContent;
1052 var plainText = tempDiv.textContent || tempDiv.innerText || '';
1053 plainText = plainText.replace(/\u00a0/g, '').trim();
1054 var getParent = $(this).parent();
1055 var getMainParent = getParent.parent();
1056 var getClickContent = getMainParent.find('.hotspot-url');
1057
1058 if (plainText.length > 0) {
1059 getClickContent.find('input[name*=hotspot-url]').val('');
1060 getClickContent.find('input[name*=hotspot-url]').attr('placeholder', 'You can set either a URL or an On-click content');
1061 getClickContent.find('input[name*=hotspot-url]').attr("disabled", true);
1062 } else {
1063 getClickContent.find('input[name*=hotspot-url]').attr("disabled", false);
1064 }
1065 }
1066 }
1067 });
1068 $('textarea[name*=hotspot-hover]').summernote({
1069 toolbar: [
1070 ['style', ['style']],
1071 ['font', ['bold', 'underline', 'clear']],
1072 ['fontname', ['fontname']],
1073 ['color', ['color']],
1074 ['para', ['ul', 'ol', 'paragraph']],
1075 ['table', ['table']],
1076 ['insert', ['link', 'picture', 'video']],
1077 ['view', ['codeview', 'help']],
1078 ],
1079 fontNames: ['Arial', 'Helvetica', 'Tahoma', 'Courier New', 'Verdana', 'Impact', 'Times New Roman', 'system-ui', 'Helvetica Neue'],
1080 callbacks: {
1081 onInit: function() {
1082 var $editor = $(this);
1083 var $noteEditor = $editor.next('.note-editor');
1084
1085 // Intercept Video button click
1086 $noteEditor.on('click', 'button.note-btn[aria-label="Video"]', function(e) {
1087 // Small delay to check if cursor is on a video
1088 setTimeout(function() {
1089 // Get the current selection
1090 var range = $editor.summernote('createRange');
1091 if (range) {
1092 var $node = $(range.sc);
1093
1094 // Check if cursor is on a video iframe
1095 var $iframe = $node.closest('iframe.note-video-clip');
1096 if (!$iframe.length) {
1097 $iframe = $node.find('iframe.note-video-clip').first();
1098 }
1099
1100 if ($iframe.length && $iframe.attr('src')) {
1101 var embedUrl = $iframe.attr('src');
1102 var videoUrl = '';
1103
1104 // Extract YouTube URL
1105 if (embedUrl && (embedUrl.indexOf('youtube.com') > -1 || embedUrl.indexOf('youtu.be') > -1)) {
1106 var match = embedUrl.match(/embed\/([^?&]*)/);
1107 if (match && match[1]) {
1108 videoUrl = 'https://www.youtube.com/watch?v=' + match[1];
1109 }
1110 } else if (embedUrl) {
1111 videoUrl = embedUrl;
1112 }
1113
1114 // Show the video dialog
1115 $editor.summernote('videoDialog.show');
1116
1117 // Pre-populate the video URL in the dialog
1118 setTimeout(function() {
1119 var $urlInput = $('.note-video-url');
1120 if ($urlInput.length && videoUrl) {
1121 $urlInput.val(videoUrl);
1122 $urlInput.focus();
1123 }
1124 }, 150);
1125 }
1126 }
1127 }, 50);
1128 });
1129
1130 // Override font name dropdown click handler for this specific editor
1131 $editor.next('.note-editor').find('.dropdown-fontname a').off('click').on('click', function(e) {
1132 e.preventDefault();
1133 var fontName = $(this).data('value') || $(this).text();
1134
1135 // Focus on the current editor
1136 $editor.summernote('focus');
1137
1138 // Use Summernote's built-in method to apply font
1139 try {
1140 // First, clear any existing font formatting
1141 var range = $editor.summernote('createRange');
1142 if (range && !range.isCollapsed()) {
1143 // Get selected text
1144 var selectedText = range.toString();
1145
1146 // Use Summernote's insertHTML to replace content
1147 var fontHtml = '<span style="font-family: ' + fontName + ';">' + selectedText + '</span>';
1148 $editor.summernote('insertHTML', fontHtml);
1149 } else {
1150 // No selection, use execCommand for typing
1151 $editor.summernote('focus');
1152 document.execCommand('fontName', false, fontName);
1153 }
1154 } catch (error) {
1155 console.log('Font application error, using fallback method');
1156 // Fallback method
1157 document.execCommand('fontName', false, fontName);
1158 }
1159
1160 // Update dropdown button text for this editor
1161 $(this).closest('.note-editor').find('.note-current-fontname').text(fontName);
1162
1163 // Close dropdown
1164 var $dropdownMenu = $(this).closest('.dropdown-menu');
1165 $dropdownMenu.removeClass('show').hide();
1166 $dropdownMenu.prev('.dropdown-toggle').removeClass('show').attr('aria-expanded', 'false');
1167
1168 // Trigger change event
1169 setTimeout(function() {
1170 $editor.trigger('summernote.change');
1171 }, 100);
1172 });
1173 },
1174
1175 // Clean up the content after any change
1176 onChange: function(contents, $editable) {
1177 // Debounce the cleanup to avoid conflicts
1178 clearTimeout(this.cleanupTimeout);
1179 this.cleanupTimeout = setTimeout(function() {
1180 // Remove all font-family styles from elements that shouldn't have them
1181 $editable.find('*:not(span)').each(function() {
1182 if (this.style && this.style.fontFamily) {
1183 this.style.fontFamily = '';
1184 }
1185 });
1186
1187 // Clean up empty spans
1188 $editable.find('span').each(function() {
1189 var $span = $(this);
1190 var text = $span.text().replace(/[\uFEFF\u200B-\u200D\u2060]/g, '').trim();
1191
1192 if (!text) {
1193 $span.remove();
1194 } else {
1195 // If span has other styles besides font-family, keep only font-family
1196 var fontFamily = $span.css('font-family');
1197 if (fontFamily && fontFamily !== 'inherit') {
1198 $span.attr('style', 'font-family: ' + fontFamily + ';');
1199 } else if (!fontFamily || fontFamily === 'inherit') {
1200 $span.contents().unwrap();
1201 }
1202 }
1203 });
1204
1205 // Remove nested spans with font-family
1206 $editable.find('span[style*="font-family"] span[style*="font-family"]').each(function() {
1207 $(this).contents().unwrap();
1208 });
1209 }, 200);
1210 }
1211 }
1212 });
1213 if ($(this).parents(".scene-setup").attr("data-limit").length > 0) {
1214 lastChildClicked = true;
1215 if ($(this).parents(".scene-setup").find("div[data-repeater-item]:not(.hotspot-setup div[data-repeater-item])").length <= $(this).parents(".scene-setup").attr("data-limit")) {
1216
1217 $(this).slideDown();
1218 $(this).removeClass('active');
1219
1220 i = i + 1;
1221 var scene = 'scene-' + i;
1222
1223 $(this).find(".title .scene-num").html(i);
1224
1225 $('<li><span data-index="' + i + '" data-href="#' + scene + '"><i class="fa fa-image"></i></span></li>').insertBefore($(this).parent().parent('.scene-setup').find('.scene-nav ul li:last-child'));
1226
1227 $(this).attr('id', scene);
1228 changehotspotid(i);
1229 $(this).siblings('.active').removeClass('active');
1230 $(this).addClass('active');
1231 $(this).find(".sceneid").val(generateRandomString(8));
1232 setTimeout(changeicon, 1000);
1233 } else {
1234 $('.pano-alert .pano-error-message').html('<span class="pano-error-title">Limit Reached</span><p> You can add up to 5 scenes on each tour in the Free version. Upgrade to Pro to create tours with unlimited scenes.</p>');
1235 $('body').addClass('error-overlay2');
1236 $('.pano-alert').addClass('pano-default-warning').show();
1237 $(this).remove();
1238 }
1239 } else {
1240 jQuery(this).slideDown();
1241 $(this).removeClass('active');
1242
1243 i = i + 1;
1244 var scene = 'scene-' + i;
1245 $(this).find(".title .scene-num").html(i);
1246 $('<li><span data-index="' + i + '" data-href="#' + scene + '"><i class="fa fa-image"></i></span></li>').insertBefore($(this).parent().parent('.scene-setup').find('.scene-nav ul li:last-child'));
1247 $(this).attr('id', scene);
1248 changehotspotid(i);
1249 }
1250
1251 $(this).hide();
1252
1253 //tab active setup
1254 $('#wpvr_active_scenes').val(i);
1255 $('#wpvr_active_hotspot').val(1);
1256 },
1257 hide: function (deleteElement) {
1258 var hide_id = $(this).attr("id");
1259 var _hide_id = hide_id.split('-').pop();
1260 hide_id = "#" + hide_id;
1261
1262 var current = $(this).attr('id');
1263 var fchild = $('.single-scene:nth-child(2)').attr('id');
1264 // var fchild = $(this).parent().children(":first").attr('id');
1265
1266
1267 var elementcontains = $(this).attr("id");
1268 var str1 = 'scene';
1269 var str2 = 'hotspot';
1270 if (elementcontains.indexOf(str1) != -1 && elementcontains.indexOf(str2) == -1) {
1271
1272 var _this = $(this);
1273
1274 if (confirm('Are you sure you want to delete?')) {
1275 jQuery(_this).slideUp(deleteElement);
1276 if (current == fchild) {
1277 $(_this).next().addClass("active");
1278 $(_this).parent().parent('.scene-setup').find('.scene-nav li span[data-href="' + hide_id + '"]').parent("li").next().addClass("active");
1279 $(_this).parent().parent('.scene-setup').find('.scene-nav li span[data-href="' + hide_id + '"]').parent("li").next().children("span").trigger("click");
1280 } else {
1281 $(_this).prev().addClass("active");
1282 $(_this).parent().parent('.scene-setup').find('.scene-nav li span[data-href="' + hide_id + '"]').parent("li").prev().addClass("active");
1283 $(_this).parent().parent('.scene-setup').find('.scene-nav li span[data-href="' + hide_id + '"]').parent("li").prev().children("span").trigger("click");
1284 }
1285 $(_this).parent().parent('.scene-setup').find('.scene-nav li span[data-href="' + hide_id + '"]').parent("li").remove();
1286 setTimeout(deleteinfodata, 1000);
1287
1288 //tab active setup
1289 if (parseInt(_hide_id) - 1 > 0) {
1290 $('#wpvr_active_scenes').val(parseInt(_hide_id) - 1);
1291 } else {
1292 $('#wpvr_active_scenes').val(1);
1293 }
1294 $('#wpvr_active_hotspot').val(1);
1295
1296
1297 setTimeout(function(){
1298 let sceneImageCount = $('.rex-pano-tab .single-scene .scene-left .scene-setting .form-group img')
1299 .filter(function() {
1300 return $(this).attr('src') && $(this).attr('src').trim() !== '';
1301 })
1302 .length;
1303
1304 let defaultScene = false;
1305 let hotspotCheck = false;
1306
1307 let $sceneCheckbox = $('#wpvr-check-scene');
1308 let $mediaCheckbox = $('#wpvr-check-media');
1309 let $hotspotCheck = $('#wpvr-check-hotspots');
1310 let $defaultCheck = $('#wpvr-check-default');
1311
1312 $('select').each(function() {
1313 if (/^scene-list\[\d+\]\[dscene\]$/.test($(this).attr('name'))) {
1314 let selectedValue = $(this).val();
1315 if('on' === selectedValue){
1316 defaultScene = true;
1317 }
1318 }
1319 });
1320
1321 if (sceneImageCount === 0) {
1322 $sceneCheckbox.prop('checked', false);
1323 $mediaCheckbox.prop('checked', false);
1324 $sceneCheckbox.closest('.wpvr-checklist-item').css('color', '#73707D');
1325 $mediaCheckbox.closest('.wpvr-checklist-item').css('color', '#73707D');
1326 }
1327
1328 if(!defaultScene){
1329 $defaultCheck.prop('checked', false);
1330 $defaultCheck.closest('.wpvr-checklist-item').css('color', '#73707D');
1331 }
1332
1333 let pitchInputs = document.querySelectorAll('.hotspot-pitch');
1334 for (let pitchInput of pitchInputs) {
1335 if (pitchInput.value.trim() !== '') {
1336 hotspotCheck = true;
1337 }
1338 }
1339
1340 if(!hotspotCheck)
1341 {
1342 $hotspotCheck.prop('checked', false);
1343 $hotspotCheck.closest('.wpvr-checklist-item').css('color', '#73707D');
1344 }
1345 updateProgress();
1346 }, 500);
1347 }
1348
1349 }
1350 },
1351 repeaters: [{
1352 selector: '.hotspot-setup',
1353 defaultValues: {
1354 'hotspot-type': 'info',
1355 'hotspot-customclass-pro': 'none',
1356 },
1357 show: function () {
1358 $('textarea[name*=hotspot-content]').summernote({
1359 toolbar: [
1360 ['style', ['style']],
1361 ['font', ['bold', 'underline', 'clear']],
1362 ['fontname', ['fontname']],
1363 ['color', ['color']],
1364 ['para', ['ul', 'ol', 'paragraph']],
1365 ['table', ['table']],
1366 ['insert', ['link', 'picture', 'video']],
1367 ['view', ['codeview', 'help']],
1368 ],
1369 callbacks: {
1370 onInit: function() {
1371 var $editor = $(this);
1372 var $noteEditor = $editor.next('.note-editor');
1373
1374 // Intercept Video button click
1375 $noteEditor.on('click', 'button.note-btn[aria-label="Video"]', function(e) {
1376 // Small delay to check if cursor is on a video
1377 setTimeout(function() {
1378 // Get the current selection
1379 var range = $editor.summernote('createRange');
1380 if (range) {
1381 var $node = $(range.sc);
1382
1383 // Check if cursor is on a video iframe
1384 var $iframe = $node.closest('iframe.note-video-clip');
1385 if (!$iframe.length) {
1386 $iframe = $node.find('iframe.note-video-clip').first();
1387 }
1388
1389 if ($iframe.length && $iframe.attr('src')) {
1390 var embedUrl = $iframe.attr('src');
1391 var videoUrl = '';
1392
1393 // Extract YouTube URL
1394 if (embedUrl && (embedUrl.indexOf('youtube.com') > -1 || embedUrl.indexOf('youtu.be') > -1)) {
1395 var match = embedUrl.match(/embed\/([^?&]*)/);
1396 if (match && match[1]) {
1397 videoUrl = 'https://www.youtube.com/watch?v=' + match[1];
1398 }
1399 } else if (embedUrl) {
1400 videoUrl = embedUrl;
1401 }
1402
1403 // Show the video dialog
1404 $editor.summernote('videoDialog.show');
1405
1406 // Pre-populate the video URL in the dialog
1407 setTimeout(function() {
1408 var $urlInput = $('.note-video-url');
1409 if ($urlInput.length && videoUrl) {
1410 $urlInput.val(videoUrl);
1411 $urlInput.focus();
1412 }
1413 }, 150);
1414 }
1415 }
1416 }, 50);
1417 });
1418 },
1419 onKeyup: function(e) {
1420 var getHotspotContent = $(this).summernote('code').trim();
1421 var tempDiv = document.createElement('div');
1422 tempDiv.innerHTML = getHotspotContent;
1423 var plainText = tempDiv.textContent || tempDiv.innerText || '';
1424 plainText = plainText.replace(/\u00a0/g, '').trim();
1425 var getParent = $(this).parent();
1426 var getMainParent = getParent.parent();
1427 var getClickContent = getMainParent.find('.hotspot-url');
1428
1429 if (plainText.length > 0) {
1430 getClickContent.find('input[name*=hotspot-url]').val('');
1431 getClickContent.find('input[name*=hotspot-url]').attr('placeholder', 'You can set either a URL or an On-click content');
1432 getClickContent.find('input[name*=hotspot-url]').attr("disabled", true);
1433 } else {
1434 getClickContent.find('input[name*=hotspot-url]').attr("disabled", false);
1435 }
1436 }
1437 }
1438 });
1439 $('textarea[name*=hotspot-hover]').summernote({
1440 toolbar: [
1441 ['style', ['style']],
1442 ['font', ['bold', 'underline', 'clear']],
1443 ['fontname', ['fontname']],
1444 ['color', ['color']],
1445 ['para', ['ul', 'ol', 'paragraph']],
1446 ['table', ['table']],
1447 ['insert', ['link', 'picture', 'video']],
1448 ['view', ['codeview', 'help']],
1449 ],
1450 fontNames: ['Arial', 'Helvetica', 'Tahoma', 'Courier New', 'Verdana', 'Impact', 'Times New Roman', 'system-ui', 'Helvetica Neue'],
1451 callbacks: {
1452 onInit: function() {
1453 var $editor = $(this);
1454 var $noteEditor = $editor.next('.note-editor');
1455
1456 // Intercept Video button click
1457 $noteEditor.on('click', 'button.note-btn[aria-label="Video"]', function(e) {
1458 // Small delay to check if cursor is on a video
1459 setTimeout(function() {
1460 // Get the current selection
1461 var range = $editor.summernote('createRange');
1462 if (range) {
1463 var $node = $(range.sc);
1464
1465 // Check if cursor is on a video iframe
1466 var $iframe = $node.closest('iframe.note-video-clip');
1467 if (!$iframe.length) {
1468 $iframe = $node.find('iframe.note-video-clip').first();
1469 }
1470
1471 if ($iframe.length && $iframe.attr('src')) {
1472 var embedUrl = $iframe.attr('src');
1473 var videoUrl = '';
1474
1475 // Extract YouTube URL
1476 if (embedUrl && (embedUrl.indexOf('youtube.com') > -1 || embedUrl.indexOf('youtu.be') > -1)) {
1477 var match = embedUrl.match(/embed\/([^?&]*)/);
1478 if (match && match[1]) {
1479 videoUrl = 'https://www.youtube.com/watch?v=' + match[1];
1480 }
1481 } else if (embedUrl) {
1482 videoUrl = embedUrl;
1483 }
1484
1485 // Show the video dialog
1486 $editor.summernote('videoDialog.show');
1487
1488 // Pre-populate the video URL in the dialog
1489 setTimeout(function() {
1490 var $urlInput = $('.note-video-url');
1491 if ($urlInput.length && videoUrl) {
1492 $urlInput.val(videoUrl);
1493 $urlInput.focus();
1494 }
1495 }, 150);
1496 }
1497 }
1498 }, 50);
1499 });
1500
1501 // Override font name dropdown click handler for this specific editor
1502 $editor.next('.note-editor').find('.dropdown-fontname a').off('click').on('click', function(e) {
1503 e.preventDefault();
1504 var fontName = $(this).data('value') || $(this).text();
1505
1506 // Focus on the current editor
1507 $editor.summernote('focus');
1508
1509 // Use Summernote's built-in method to apply font
1510 try {
1511 // First, clear any existing font formatting
1512 var range = $editor.summernote('createRange');
1513 if (range && !range.isCollapsed()) {
1514 // Get selected text
1515 var selectedText = range.toString();
1516
1517 // Use Summernote's insertHTML to replace content
1518 var fontHtml = '<span style="font-family: ' + fontName + ';">' + selectedText + '</span>';
1519 $editor.summernote('insertHTML', fontHtml);
1520 } else {
1521 // No selection, use execCommand for typing
1522 $editor.summernote('focus');
1523 document.execCommand('fontName', false, fontName);
1524 }
1525 } catch (error) {
1526 console.log('Font application error, using fallback method');
1527 // Fallback method
1528 document.execCommand('fontName', false, fontName);
1529 }
1530
1531 // Update dropdown button text for this editor
1532 $(this).closest('.note-editor').find('.note-current-fontname').text(fontName);
1533
1534 // Close dropdown
1535 var $dropdownMenu = $(this).closest('.dropdown-menu');
1536 $dropdownMenu.removeClass('show').hide();
1537 $dropdownMenu.prev('.dropdown-toggle').removeClass('show').attr('aria-expanded', 'false');
1538
1539 // Trigger change event
1540 setTimeout(function() {
1541 $editor.trigger('summernote.change');
1542 }, 100);
1543 });
1544 },
1545
1546 // Clean up the content after any change
1547 onChange: function(contents, $editable) {
1548 // Debounce the cleanup to avoid conflicts
1549 clearTimeout(this.cleanupTimeout);
1550 this.cleanupTimeout = setTimeout(function() {
1551 // Remove all font-family styles from elements that shouldn't have them
1552 $editable.find('*:not(span)').each(function() {
1553 if (this.style && this.style.fontFamily) {
1554 this.style.fontFamily = '';
1555 }
1556 });
1557
1558 // Clean up empty spans
1559 $editable.find('span').each(function() {
1560 var $span = $(this);
1561 var text = $span.text().replace(/[\uFEFF\u200B-\u200D\u2060]/g, '').trim();
1562
1563 if (!text) {
1564 $span.remove();
1565 } else {
1566 // If span has other styles besides font-family, keep only font-family
1567 var fontFamily = $span.css('font-family');
1568 if (fontFamily && fontFamily !== 'inherit') {
1569 $span.attr('style', 'font-family: ' + fontFamily + ';');
1570 } else if (!fontFamily || fontFamily === 'inherit') {
1571 $span.contents().unwrap();
1572 }
1573 }
1574 });
1575
1576 // Remove nested spans with font-family
1577 $editable.find('span[style*="font-family"] span[style*="font-family"]').each(function() {
1578 $(this).contents().unwrap();
1579 });
1580 }, 200);
1581 }
1582 }
1583 });
1584 if ($(this).parents(".hotspot-setup").attr("data-limit").length > 0) {
1585
1586 if ($(this).parents(".hotspot-setup").find("div[data-repeater-item]").length <= $(this).parents(".hotspot-setup").attr("data-limit")) {
1587
1588 $(this).slideDown();
1589 $(this).removeClass('active');
1590 $(this).siblings('.active').removeClass('active');
1591 $(this).addClass('active');
1592 j = parseInt(j);
1593 j = j + 1;
1594 var parent_scene = $(this).parent().parent().parent('.single-scene.active').attr('id');
1595 scene_parent = parent_scene;
1596 var hotspot = parent_scene + '-hotspot-' + j;
1597
1598 var replace_string = parent_scene.replace("scene-", "");
1599
1600 $(this).find(".title .hotspot-num").html(j);
1601 $(this).find(".title .scene-num").html(replace_string);
1602
1603 $('<li><span data-index="' + j + '" data-href="#' + hotspot + '"><i class="far fa-dot-circle"></i></span></li>').insertBefore($(this).parent().parent('.hotspot-setup').find('.hotspot-nav ul li:last-child'));
1604
1605 $(this).attr('id', hotspot);
1606
1607 setTimeout(changeicon, 1000);
1608 } else {
1609 $('.pano-alert .pano-error-message').html('<span class="pano-error-title">Limit Reached</span><p> You can add up to 5 hotspots on each scene in the Free version. <br> Upgrade to Pro to add an unlimited number of hotspots.</p>');
1610 $('body').addClass('error-overlay2');
1611 $('.pano-alert').addClass('pano-default-warning').show();
1612 $(this).remove();
1613 }
1614 } else {
1615 jQuery(this).slideDown();
1616 $(this).removeClass('active');
1617 j = parseInt(j);
1618 j = j + 1;
1619 var parent_scene = $(this).parent().parent().parent('.single-scene.active').attr('id');
1620 var hotspot = parent_scene + '-hotspot-' + j;
1621
1622 var replace_string = parent_scene.replace("scene-", "");
1623
1624 $(this).find(".title .hotspot-num").html(j);
1625 $(this).find(".title .scene-num").html(replace_string);
1626
1627 $('<li><span data-index="' + j + '" data-href="#' + hotspot + '"><i class="far fa-dot-circle"></i></span></li>').insertBefore($(this).parent().parent('.hotspot-setup').find('.hotspot-nav ul li:last-child'));
1628
1629 $(this).attr('id', hotspot);
1630 }
1631 $('#wpvr_active_hotspot').val(j);
1632 },
1633 hide: function (deleteElement) {
1634 var hotspot_hide_id = $(this).attr("id");
1635 var _hide_id = hotspot_hide_id.split('-').pop();
1636 hotspot_hide_id = "#" + hotspot_hide_id;
1637 var hotspot_current = $(this).attr('id');
1638 var hotspot_fchild = $(this).parent().children(":first").attr('id');
1639
1640 var hpelementcontains = $(this).attr("id");
1641 var hpstr1 = 'scene';
1642 var hpstr2 = 'hotspot';
1643 if (hpelementcontains.indexOf(hpstr1) != -1 && hpelementcontains.indexOf(hpstr2) != -1) {
1644
1645 var _this = $(this);
1646
1647 if (confirm('Are you sure you want to delete?')) {
1648 jQuery(_this).slideUp(deleteElement);
1649 if (hotspot_current == hotspot_fchild) {
1650 $(_this).next().addClass("active");
1651 $(_this).parent().parent('.hotspot-setup').find('.hotspot-nav li span[data-href="' + hotspot_hide_id + '"]').parent("li").next().addClass("active");
1652
1653 } else {
1654 $(_this).prev().addClass("active");
1655 $(_this).parent().parent('.hotspot-setup').find('.hotspot-nav li span[data-href="' + hotspot_hide_id + '"]').parent("li").prev().addClass("active");
1656 }
1657
1658 $(_this).parent().parent('.hotspot-setup').find('.hotspot-nav li:not(:last-child) span[data-href="' + hotspot_hide_id + '"]').parent("li").remove();
1659
1660 //tab active setup
1661 if (parseInt(_hide_id) - 1 > 0) {
1662 $('#wpvr_active_hotspot').val(parseInt(_hide_id) - 1);
1663 } else {
1664 $('#wpvr_active_hotspot').val(1);
1665 }
1666
1667 setTimeout(function(){
1668 let yawInputs = $('.hotspot-yaw');
1669 let pitchInputs = $('.hotspot-pitch');
1670 let hasYawValue = false;
1671 let hasPitchValue = false;
1672
1673 yawInputs.each(function() {
1674 if ($(this).val() && $(this).val().trim() !== '') {
1675 hasYawValue = true;
1676 return false; // break loop
1677 }
1678 });
1679 pitchInputs.each(function() {
1680 if ($(this).val() && $(this).val().trim() !== '') {
1681 hasPitchValue = true;
1682 return false; // break loop
1683 }
1684 });
1685
1686 let $hotspotCheckbox = $('#wpvr-check-hotspots');
1687
1688 if (!hasYawValue && !hasPitchValue) {
1689 $hotspotCheckbox.prop('checked', false);
1690 $hotspotCheckbox.closest('.wpvr-checklist-item').css('color', '#73707D');
1691 } else {
1692 $hotspotCheckbox.prop('checked', true);
1693 $hotspotCheckbox.closest('.wpvr-checklist-item').css('color', '#0E003C');
1694 }
1695 updateProgress();
1696 },500);
1697 }
1698 }
1699 },
1700
1701 }]
1702 });
1703 });
1704
1705 $(document).on("click", ".upload-scene-wrapper", function (event) {
1706 $(".scene-nav ul li:last-child span").trigger("click");
1707 $(".scene-upload").last().trigger("click");
1708 })
1709
1710 $(document).on("click", ".upload-scene-wrapper-first", function (event) {
1711 $(".scene-upload").trigger("click");
1712 })
1713
1714 $(document).on("click", ".scene-upload", function (event) {
1715 event.preventDefault();
1716 scene_upload_parent = $(this).parent('.form-group');
1717
1718 if (scene_uploader) {
1719 scene_uploader.open();
1720 return;
1721 }
1722
1723 scene_uploader = wp.media({
1724 title: $(this).data('uploader_title'),
1725 button: {
1726 text: $(this).data('uploader_button_text'),
1727 },
1728 library: {
1729 type: ['image']
1730 },
1731 multiple: false
1732 });
1733
1734 scene_uploader.on('select', function () {
1735
1736 var attachment = scene_uploader.state().get('selection').first().toJSON();
1737 scene_uploader.close();
1738
1739 var imageUrl = attachment.url;
1740 var siteProtocol = window.location.protocol;
1741 var imageProtocol = new URL(imageUrl).protocol;
1742
1743 $('.rex-add-coordinates .mixed-content-warning, .rex-add-coordinates .mixed-content-doc-link').remove();
1744
1745 if (siteProtocol !== imageProtocol) {
1746
1747 // Create warning message
1748 var $warningBox = $('<div>', {
1749 text: "You're loading an image over " + imageProtocol.replace(':', '').toUpperCase() +
1750 " on a site using " + siteProtocol.replace(':', '').toUpperCase() +
1751 ". This may cause a mixed content issue.",
1752 class: 'mixed-content-warning',
1753 css: {
1754 color: 'red',
1755 marginTop: '35px',
1756 }
1757 });
1758
1759 // Create doc link
1760 var $docLink = $('<a>', {
1761 href: 'https://rextheme.com/docs/wp-vr-tour-not-displaying/',
1762 text: 'View fix guide',
1763 target: '_blank',
1764 class: 'mixed-content-doc-link',
1765 css: {
1766 display: 'block',
1767 color: '#0073aa',
1768 textDecoration: 'underline'
1769 }
1770 }).on('click', function () {
1771 $(this).blur(); // Remove focus after click
1772 });
1773
1774 // Prepend warning and link to the top of the container
1775 $('.rex-add-coordinates').prepend($warningBox, $docLink);
1776 }
1777
1778 scene_upload_parent.find('.scene-attachment-url').val(attachment.url);
1779 scene_upload_parent.find('img').attr('src', attachment.url).show();
1780
1781 setTimeout(function () {
1782 if (!$('#wpvr-check-scene').is(':checked')) {
1783 $('#wpvr-check-scene').prop('checked', true);
1784 $('#wpvr-check-scene').closest('.wpvr-checklist-item').css('color', '#0E003C');
1785 }
1786
1787 if (!$('#wpvr-check-media').is(':checked')) {
1788 $('#wpvr-check-media').prop('checked', true);
1789 $('#wpvr-check-media').closest('.wpvr-checklist-item').css('color', '#0E003C');
1790 }
1791
1792 updateProgress();
1793
1794 $('.panolenspreview').trigger('click');
1795 }, 1000);
1796
1797
1798 });
1799
1800 scene_uploader.open();
1801 });
1802
1803 $(document).on("click", ".video-upload", function (event) {
1804 event.preventDefault();
1805
1806 var parent = $(this).parent('.form-group');
1807
1808 var video_uploader = wp.media({
1809 title: $(this).data('uploader_title'),
1810 button: {
1811 text: $(this).data('uploader_button_text'),
1812 },
1813 library: {
1814 type: ['video/mp4']
1815 },
1816 multiple: false
1817 });
1818
1819 video_uploader.on('select', function () {
1820 var attachment = video_uploader.state().get('selection').first().toJSON();
1821 parent.find('.video-attachment-url').val(attachment.url);
1822 });
1823
1824 video_uploader.open();
1825 });
1826
1827 $(document).on("click", ".preview-upload", function (event) {
1828 event.preventDefault();
1829 var parent = $(this).parent('.form-group');
1830
1831 var preview_uploader = wp.media({
1832 title: $(this).data('uploader_title'),
1833 button: {
1834 text: $(this).data('uploader_button_text'),
1835 },
1836 library: {
1837 type: ['image']
1838 },
1839 multiple: false
1840 });
1841
1842 preview_uploader.on('select', function () {
1843 var attachment = preview_uploader.state().get('selection').first().toJSON();
1844 parent.find('.preview-attachment-url').val(attachment.url);
1845 parent.find('.img-upload-frame').css('background-image', 'url(' + attachment.url + ')');
1846 parent.find('.img-upload-frame').addClass('img-uploaded');
1847 parent.find('.remove-attachment').show();
1848 });
1849
1850 preview_uploader.open();
1851 });
1852
1853 //----remove tour preview image----
1854 $(document).on("click", ".remove-attachment", function (event) {
1855 $(this).hide();
1856 parent = $(this).parents('.form-group');
1857
1858 parent.find('.preview-attachment-url').val('');
1859 parent.find('.img-upload-frame').css('background-image', '');
1860 parent.find('.img-upload-frame').removeClass('img-uploaded');
1861 });
1862
1863
1864 $(document).on("change", "select[name*=hotspot-type]", function (event) {
1865
1866 var getparent = $(this).parent();
1867 var getvalue = $(this).val();
1868 if (getvalue == 'info') {
1869 getparent.find('.hotspot-scene').hide();
1870 getparent.find('.hotspot-scene input').val('');
1871 getparent.find('.hotspot-scene .hotspotscene').val('none');
1872 getparent.find('.hotspot-url').show();
1873 getparent.find('.s_tab').show();
1874 getparent.find('.hotspot-content').show();
1875 getparent.find('input[name*=hotspot-url]').attr("disabled",false)
1876 getparent.find('textarea[name*=hotspot-content]').next().find(".note-editable").attr("contenteditable", true);
1877 } else {
1878 getparent.find('.hotspot-scene').show();
1879 getparent.find('.hotspot-url').hide();
1880 getparent.find('.hotspot-url input').val('');
1881 getparent.find('.s_tab').hide();
1882 getparent.find('.s_tab input').val('off');
1883 getparent.find('.s_tab input').removeAttr('checked');
1884 getparent.find('.hotspot-content').hide();
1885 getparent.find('.hotspot-content textarea').val('');
1886 getparent.find('textarea[name*=hotspot-content]').next().find(".note-editable").html('');
1887 }
1888 });
1889 $(document).ready(function ($){
1890 $(document).on("keyup","input[name*=hotspot-url]",function (){
1891 var getHotspotUrl = $(this).val();
1892 var getParent = $(this).parent();
1893 var getMainParent = getParent.parent()
1894 var getClickContent = getMainParent.find('.hotspot-content')
1895 if(getHotspotUrl.length > 0){
1896 getClickContent.find('textarea').val('')
1897 getClickContent.find('textarea').attr('placeholder','You can set either a URL or an On-click content')
1898 getClickContent.find('textarea').attr("disabled",true)
1899 getClickContent.find('textarea[name*=hotspot-content]').next().find(".note-editable").attr("contenteditable", false);
1900 getClickContent.find('textarea[name*=hotspot-content]').next().find(".note-editable").html('');
1901
1902 }else{
1903 getClickContent.find('textarea').attr("disabled",false)
1904 getClickContent.find('textarea[name*=hotspot-content]').next().find(".note-editable").attr("contenteditable", true);
1905 }
1906 })
1907
1908 $(document).on("keyup","textarea[name*=hotspot-content]",function (){
1909 var getHotspotContent = $(this).summernote('code').trim();
1910 if (getHotspotContent === '<br>' || getHotspotContent === '<p><br></p>') {
1911 getHotspotContent = '';
1912 }
1913 var getParent = $(this).parent();
1914 var getMainParent = getParent.parent()
1915 var getClickContent = getMainParent.find('.hotspot-url')
1916 if(getHotspotContent.length > 0){
1917 getClickContent.find('input[name*=hotspot-url').val('')
1918 getClickContent.find('input[name*=hotspot-url').attr('placeholder','You can set either a URL or an On-click content')
1919 getClickContent.find('input[name*=hotspot-url]').attr("disabled",true)
1920 }else{
1921 getClickContent.find('input[name*=hotspot-url]').attr("disabled",false)
1922 }
1923 })
1924 })
1925
1926
1927 $(document).on("click", ".pano-error-close-btn", function (e) {
1928 e.preventDefault();
1929 $('.wpvr-delete-alert-wrapper').css('display', 'none');
1930 $('.wpvr-delete-alert-wrapper').hide();
1931 });
1932
1933 $(document).on("change", "input[type=radio][name=panovideo]", function (event) {
1934 var getvalue = $(this).val();
1935
1936 if (getvalue == 'on') {
1937 $('#confirm_text').html(`${window.wpvr_localize.VideoTourNotice}`);
1938 $('.wpvr-delete-alert-wrapper').css('display', 'flex');
1939 } else {
1940 $('.wpvr-delete-alert-wrapper').css('display', 'none');
1941 // $(".video-setting").hide();
1942
1943 $("li.general").show();
1944 $("li.scene").show();
1945 $("li.hotspot").show();
1946 $("li.streetview").show();
1947 $(".video-setting").hide();
1948 toggleSceneGallery(null, 'off');
1949 }
1950
1951 $(document).on("click", ".wpvr-delete-confirm-btn .cancel,.wpvr-delete-alert-wrapper .cross", function (e) {
1952 e.preventDefault();
1953 $('.wpvr-delete-alert-wrapper').css('display', 'none');
1954 $('.wpvr-delete-alert-wrapper').hide();
1955
1956 $(".video_on").prop('checked', false);
1957 $(".video_off").prop('checked', true);
1958
1959 $("li.general").show();
1960 $("li.scene").show();
1961 $("li.hotspot").show();
1962 $("li.streetview").show();
1963 $(".video-setting").hide();
1964 toggleSceneGallery(null, 'off');
1965
1966 });
1967
1968 $(document).on("click", ".wpvr-delete-confirm-btn .yes", function (e) {
1969 e.preventDefault();
1970 $('.wpvr-delete-alert-wrapper').css('display', 'none');
1971 $('.wpvr-delete-alert-wrapper').hide();
1972
1973 $(".video_off").prop('checked', false);
1974 $(".video_on").prop('checked', true);
1975 $(".video-setting").show();
1976 $("li.general").hide();
1977 $("li.scene").hide();
1978 $("li.hotspot").hide();
1979 $("li.streetview").hide();
1980 toggleSceneGallery(null, 'on');
1981
1982 });
1983 });
1984
1985 jQuery(document).ready(function ($) {
1986 let detect_scene_1_data = $('#scene-1').find('.sceneid').val();
1987 if(detect_scene_1_data === "") {
1988 $('#scene-1').find('.sceneid').val(generateRandomString(8));
1989 }
1990 });
1991
1992 function generateRandomString(length) {
1993 var result = '';
1994 var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
1995 var charactersLength = characters.length;
1996
1997 for (var i = 0; i < length; i++) {
1998 var randomIndex = Math.floor(Math.random() * charactersLength);
1999 result += characters.charAt(randomIndex);
2000 }
2001
2002 return result;
2003 }
2004 function prepare_hotspot_configuration_data() {
2005 var datacoords = $('#panodata').text().split(',');
2006 var pitchsplit = datacoords[0];
2007 var pitch = pitchsplit.split(':');
2008 var yawsplit = datacoords[1];
2009 var yaw = yawsplit.split(':');
2010 let detect_active_hotspot_id = $('div.single-scene.rex-pano-tab.active').children('div.hotspot-setup.rex-pano-sub-tabs').children('div.rex-pano-tab-content').children('div.single-hotspot.rex-pano-tab.active.clearfix').find("#hotspot-title").val();
2011 if(detect_active_hotspot_id === "" || detect_active_hotspot_id == undefined) {
2012 $('div.single-scene.rex-pano-tab.active').children('div.hotspot-setup.rex-pano-sub-tabs').children('div.rex-pano-tab-content').children('div.single-hotspot.rex-pano-tab.active.clearfix').find("#hotspot-title").val(generateRandomString(8));
2013 }
2014 $('div.single-scene.rex-pano-tab.active').children('div.hotspot-setup.rex-pano-sub-tabs').children('div.rex-pano-tab-content').children('div.single-hotspot.rex-pano-tab.active.clearfix').find('.hotspot-pitch').val(pitch[1]);
2015 $('div.single-scene.rex-pano-tab.active').children('div.hotspot-setup.rex-pano-sub-tabs').children('div.rex-pano-tab-content').children('div.single-hotspot.rex-pano-tab.active.clearfix').find('.hotspot-yaw').val(yaw[1]);
2016 }
2017
2018 function register_hotspot() {
2019 $('.panolenspreview').trigger('click');
2020 }
2021
2022 $(document).on("click", ".toppitch", function (event) {
2023 $.when(prepare_hotspot_configuration_data()).done(function() {
2024 register_hotspot();
2025 });
2026 });
2027
2028 jQuery(document).ready(function ($) {
2029 var viddata = $("input[name='panovideo']:checked").val();
2030
2031 if (viddata == 'on') {
2032
2033 $("li.scene").removeClass('active');
2034 $(".rex-pano-tab.wpvr_scene").removeClass('active');
2035 $("li.videos").addClass('active');
2036 $(".rex-pano-tab.video").addClass('active');
2037 $(".video-setting").show();
2038 $("li.general").hide();
2039 $("li.scene").hide();
2040 $("li.hotspot").hide();
2041 } else {
2042 // $(".video-setting").hide();
2043 $("li.general").show();
2044 $("li.scene").show();
2045 $("li.hotspot").show();
2046 }
2047 });
2048
2049 $(document).on("change", "select[name*=hotspot-customclass-pro]", function (event) {
2050 var getval = $(this).val();
2051 $(this).parent('.hotspot-setting').children('span.change-icon').html('<i class="' + getval + '"></i>');
2052
2053 });
2054
2055 $(document).on("change", ".hotspot-customclass-color", function (event) {
2056 var getcolor = $(this).val();
2057 color = getcolor;
2058 $('.hotspot-customclass-color-icon-value').val(getcolor);
2059 $('.hotspot-customclass-color').val(getcolor);
2060 });
2061
2062 jQuery(document).ready(function ($) {
2063 if ($(".icon-found-value")[0]) {
2064 color = $('.hotspot-customclass-color-icon-value.icon-found-value').val();
2065 } else {
2066 color = '#00b4ff';
2067 }
2068 });
2069
2070 function changeicon() {
2071 $('.hotspot-customclass-color-icon-value').val(color);
2072 $('.hotspot-customclass-color').val(color);
2073 }
2074
2075 //------------panolens tab js------------------
2076
2077
2078 $(document).on("click", ".scene-nav ul li:not(:last-child) span", function () {
2079
2080 var scene_id = $(this).data('index');
2081 scene_id = '#scene-' + scene_id;
2082
2083 j = $(scene_id).find('.hotspot-nav li').eq(-2).find('span').attr('data-index');
2084
2085 $([$(this).parent()[0], $($(this).data('href'))[0]]).addClass('active').siblings('.active').removeClass('active');
2086 $('#wpvr_active_scenes').val($(this).data('index'));
2087 });
2088
2089 //add click
2090 $(document).on("click", ".scene-nav ul li:last-child span", function () {
2091 var scene_id = $(this).parent('li').prev().children("span").data('index');
2092 scene_id = '#scene-' + scene_id;
2093 $(scene_id).removeAttr("style");
2094 j = $(scene_id).find('.hotspot-nav li').eq(-2).find('span').attr('data-index');
2095 $('.scene-nav ul li.active').removeClass('active');
2096 $(this).parent('li').prev().addClass('active');
2097 var sceneinfo = $('.scene-setup').repeaterVal();
2098 var infodata = sceneinfo['scene-list'];
2099 $('.hotspotscene').find('option').remove();
2100 $('.hotspotscene').append("<option value='none'>None</option>");
2101 for (var i in infodata) {
2102 var optiondata = infodata[i]['scene-id'];
2103 if (optiondata != '') {
2104 $('.hotspotscene').append("<option value='" + optiondata + "'>" + optiondata + "</option>");
2105 }
2106 }
2107 $('.hotspot-customclass-pro-select').fontIconPicker();
2108 $('span.change-icon').hide();
2109 });
2110
2111 //end add click
2112 $(document).on("click", ".hotspot-nav ul li:not(:last-child) span", function () {
2113 $('#wpvr_active_hotspot').val($(this).data('index'));
2114 $([$(this).parent()[0], $($(this).data('href'))[0]]).addClass('active').siblings('.active').removeClass('active');
2115 });
2116
2117 $(document).on("click", ".hotspot-nav ul li:last-child span", function () {
2118 $(this).parent('li').siblings('.active').removeClass('active');
2119 $(this).parent('li').prev().addClass('active');
2120 var sceneinfo = $('.scene-setup').repeaterVal();
2121 var infodata = sceneinfo['scene-list'];
2122 $('.hotspotscene').find('option').remove();
2123 $('.hotspotscene').append("<option value='none'>None</option>");
2124 for (var i in infodata) {
2125 var optiondata = infodata[i]['scene-id'];
2126 if (optiondata != '') {
2127 $('.hotspotscene').append("<option value='" + optiondata + "'>" + optiondata + "</option>");
2128 }
2129 }
2130 $('.trtr').trigger('change');
2131 $('.hotspot-customclass-pro-select').fontIconPicker();
2132 $('span.change-icon').hide();
2133
2134 });
2135
2136 function changehotspotid(id) {
2137 var scene_id = '#scene-' + id;
2138 var hotspot_id = 'scene-' + id + '-hotspot-1';
2139 $(scene_id).find('.hotspot-nav li span').attr('data-href', '#' + hotspot_id + '');
2140 $(scene_id).find('.single-hotspot').attr('id', hotspot_id);
2141
2142 }
2143
2144 $(document).on("click", ".rex-pano-nav-menu.main-nav ul li span", function () {
2145 var screen = $(this).parent().attr('data-screen');
2146
2147 var url_info = wpvr_global_obj.url_info
2148 if ( 'add' == url_info.screen ){
2149 var newUrl = url_info.admin_url+"post-new.php?"+"post_type="+url_info.param.post_type+"&active_tab="+screen;
2150 }else{
2151 var newUrl = url_info.admin_url+"post.php?"+"post="+url_info.param.post+"&action=edit"+"&active_tab="+screen;
2152 }
2153
2154 handle_add_pitch_button(screen);
2155 toggleSceneGallery(screen);
2156
2157 if (window.history != 'undefined' && window.history.pushState != 'undefined') {
2158 window.history.pushState({ path: newUrl }, '', newUrl);
2159 }
2160
2161 $('#wpvr_active_tab').val(screen);
2162 if ('hotspot' == screen) {
2163 $('.active_scene_id').show();
2164 var id = $('.single-scene.active').attr('id');
2165 $('.active_scene_id p').text(`${window.wpvr_localize.AddingHotspotsOnScene}`);
2166 var scenceID = $('#' + id + ' .sceneid').val();
2167 var span = '<span>(' + scenceID + ')</span>'
2168 $('.active_scene_id p').append(span);
2169 $('.active_scene_id').css({ "background-color": "#E0E1F7", "width": "100%", "text-align": "center", "padding": "10px 15px" });
2170 $('.active_scene_id p').css({ "color": "black", "font-size": "15px" });
2171 $('.active_scene_id p span').css({ "color": "#004efa", "font-size": "15px" });
2172
2173 } else {
2174 $('.active_scene_id').hide();
2175 }
2176 $([$(this).parent()[0], $($(this).data('href'))[0]]).addClass('active').siblings('.active').removeClass('active');
2177 });
2178
2179 //-Get Started reloaded -//
2180 $(document).on("click",".tabs.rex-tabs li a",function(){
2181 var tab = $(this).attr('href');
2182 var url = window.location;
2183 var origin = url.origin;
2184 var pathname = url.pathname
2185 var search_perameter = window.location.search.split('&');
2186 var makeUrl = origin + pathname + search_perameter[0]
2187 var newUrl = makeUrl + tab;
2188
2189 if (window.history != 'undefined' && window.history.pushState != 'undefined') {
2190 window.history.pushState({ path: newUrl }, '', newUrl);
2191 }
2192 })
2193 //----------alert dismiss--------//
2194 $(document).on("click", "body", function () {
2195 $('body').removeClass('error-overlay2');
2196 $('.pano-alert').removeClass('pano-default-warning').hide();
2197 });
2198 $(document).on("click", ".pano-alert .pano-error-close-btn", function () {
2199 $('body').removeClass('error-overlay2');
2200 $('.pano-alert').removeClass('pano-default-warning').hide();
2201 });
2202 $(document).on("click", ".pano-alert, .rex-pano-sub-tabs .rex-pano-tab-nav li.add", function (e) {
2203 e.stopPropagation();
2204 });
2205
2206
2207 $(document).on("click", ".main-nav li.hotspot span", function () {
2208 $(".hotspot-setup.rex-pano-sub-tabs").show();
2209 $(".scene-setup > nav.scene-nav").hide();
2210 $(".scene-setup .single-scene > .scene-content").hide();
2211 $(".scene-setup .delete-scene").hide();
2212 });
2213
2214 $(document).on("click", ".main-nav li.scene span", function () {
2215 $(".hotspot-setup.rex-pano-sub-tabs").hide();
2216 $(".scene-setup > nav.scene-nav").show();
2217 $(".scene-setup .single-scene > .scene-content").show();
2218 $(".scene-setup .delete-scene").show();
2219 });
2220
2221 $(document).on("change", ".dscen", function () {
2222 var dscene = $(this).val();
2223 if('on' === dscene){
2224 $('#wpvr-check-default').prop('checked', true);
2225 $('#wpvr-check-default').closest('.wpvr-checklist-item').css('color', '#0E003C');
2226 }else{
2227 $('#wpvr-check-default').prop('checked', false);
2228 $('#wpvr-check-default').closest('.wpvr-checklist-item').css('color', '#73707D');
2229 }
2230 updateProgress()
2231 $(".dscen").not(this).each(function () {
2232 var oth_scene = $(this).val();
2233 if (dscene == 'on' && oth_scene == 'on') {
2234 $('#error_occured').show();
2235 $('#error_occured .pano-error-message').html('<span class="pano-error-title">Default scene has been updated</span>');
2236 $('body').addClass('error-overlay');
2237 $('html, body').animate({
2238 scrollTop: $("#error_occured").offset().top
2239 }, 500);
2240 $(this).val('off');
2241
2242 }
2243 });
2244 });
2245
2246 $(document).on("change", ".sceneid", function () {
2247 var sceneinfo = $('.scene-setup').repeaterVal();
2248 var infodata = sceneinfo['scene-list'];
2249 $('.hotspotscene').find('option').remove();
2250 $('.hotspotscene').append("<option value='none'>None</option>");
2251 for (var i in infodata) {
2252 var optiondata = infodata[i]['scene-id'];
2253 if (optiondata != '') {
2254 $('.hotspotscene').append("<option value='" + optiondata + "'>" + optiondata + "</option>");
2255 }
2256 }
2257 });
2258
2259
2260
2261 function deleteinfodata() {
2262 var sceneinfo = $('.scene-setup').repeaterVal();
2263 var infodata = sceneinfo['scene-list'];
2264 $('.hotspotscene').find('option').remove();
2265 $('.hotspotscene').append("<option value='none'>None</option>");
2266 for (var i in infodata) {
2267 var optiondata = infodata[i]['scene-id'];
2268 if (optiondata != '') {
2269 $('.hotspotscene').append("<option value='" + optiondata + "'>" + optiondata + "</option>");
2270 }
2271 }
2272 }
2273
2274 $(document).on("change", ".hotspotscene", function () {
2275
2276 var chanheghtptpval = $(this).val();
2277 if (chanheghtptpval != "none") {
2278 $(this).parent('.hotspot-scene').siblings('.hotspot-scene').children('.hotspotsceneinfodata').val(chanheghtptpval);
2279 } else {
2280 $(this).parent('.hotspot-scene').siblings('.hotspot-scene').children('.hotspotsceneinfodata').val('');
2281 }
2282 });
2283
2284 $(document).on("click", ".hotpitch", function (event) {
2285 var datacoords = $('#panodata').text().split(',');
2286 var pitchsplit = datacoords[0];
2287 var pitch = pitchsplit.split(':');
2288 $(this).parent().parent('.hotspot-setting').children('.hotspot-pitch').val(pitch[1]);
2289 });
2290
2291 $(document).on("click", ".hotyaw", function (event) {
2292 var datacoords = $('#panodata').text().split(',');
2293 var yawsplit = datacoords[1];
2294 var yaw = yawsplit.split(':');
2295 $(this).parent().parent('.hotspot-setting').children('.hotspot-yaw').val(yaw[1]);
2296 });
2297
2298 jQuery(document).ready(function ($) {
2299
2300 if ($(".scene-setup").length > 0) {
2301 var sceneinfo = $('.scene-setup').repeaterVal();
2302 var infodata = sceneinfo['scene-list'];
2303 $('.hotspotscene').find('option').remove();
2304 $('.hotspotscene').append("<option value='none'>None</option>");
2305 for (var i in infodata) {
2306 var optiondata = infodata[i]['scene-id'];
2307 if (optiondata != '') {
2308 $('.hotspotscene').append("<option value='" + optiondata + "'>" + optiondata + "</option>");
2309 }
2310 }
2311 }
2312 });
2313
2314 $(document).on("click", ".toppitch", function (event) {
2315 var datacoords = $('#panodata').text().split(',');
2316 var pitchsplit = datacoords[0];
2317 var pitch = pitchsplit.split(':');
2318 var yawsplit = datacoords[1];
2319 var yaw = yawsplit.split(':');
2320
2321 $('div.single-scene.rex-pano-tab.active').children('div.hotspot-setup.rex-pano-sub-tabs').children('div.rex-pano-tab-content').children('div.single-hotspot.rex-pano-tab.active.clearfix').find('.hotspot-pitch').val(pitch[1]);
2322 $('div.single-scene.rex-pano-tab.active').children('div.hotspot-setup.rex-pano-sub-tabs').children('div.rex-pano-tab-content').children('div.single-hotspot.rex-pano-tab.active.clearfix').find('.hotspot-yaw').val(yaw[1]);
2323 });
2324 jQuery(document).ready(function ($) {
2325 $('.hotspot-customclass-pro-select').fontIconPicker();
2326 });
2327 jQuery(document).ready(function ($) {
2328 $('span.change-icon').hide();
2329 });
2330
2331 jQuery(document).ready(function ($) {
2332 var autrotateset = $("input[name='autorotation']").is(':checked') ? 'on' : 'off';
2333 if (autrotateset == 'off') {
2334 $('.autorotationdata-wrapper').hide();
2335 $('.autorotationdata-wrapper input').prop('disabled', true);
2336 } else {
2337 $('.autorotationdata-wrapper').show();
2338 $('.autorotationdata-wrapper input').prop('disabled', false);
2339 }
2340
2341
2342 });
2343
2344 $(document).on("change", "input[name='autorotation']", function (event) {
2345 var autrotateset = $(this).is(':checked') ? 'on' : 'off';
2346
2347 if (autrotateset == 'on') {
2348 $('.autorotationdata-wrapper').show();
2349 $('.autorotationdata-wrapper input').prop('disabled', false);
2350 } else {
2351 $('.autorotationdata-wrapper').hide();
2352 $('.autorotationdata-wrapper input').prop('disabled', true);
2353 }
2354 });
2355
2356
2357 $(document).on("change", ".ptyscene", function (event) {
2358 var ptyscene = $(this).val();
2359 if (ptyscene == 'off') {
2360 $(this).parent('.single-settings').siblings('.ptyscenedata').hide();
2361 } else {
2362 $(this).parent('.single-settings').siblings('.ptyscenedata').show();
2363 }
2364 });
2365
2366 $(document).on("change", ".cvgscene", function (event) {
2367 var cvgscene = $(this).val();
2368 if (cvgscene == 'off') {
2369 $(this).parent('.single-settings').siblings('.cvgscenedata').hide();
2370 } else {
2371 $(this).parent('.single-settings').siblings('.cvgscenedata').show();
2372 }
2373 });
2374
2375 $(document).on("change", ".chgscene", function (event) {
2376 var chgscenedata = $(this).val();
2377 if (chgscenedata == 'off') {
2378 $(this).parent('.single-settings').siblings('.chgscenedata').hide();
2379 } else {
2380 $(this).parent('.single-settings').siblings('.chgscenedata').show();
2381 }
2382 });
2383
2384 $(document).on("change", ".czscene", function (event) {
2385 var czscene = $(this).val();
2386 if (czscene == 'off') {
2387 $(this).parent('.single-settings').siblings('.czscenedata').hide();
2388 } else {
2389 $(this).parent('.single-settings').siblings('.czscenedata').show();
2390 }
2391 });
2392
2393 /**
2394 * Nasim
2395 * enable script button on chnage action
2396 */
2397 $("#wpvr_script_control").change(function () {
2398
2399 if ($('#wpvr_script_control').is(':checked')) {
2400
2401 $(".wpvr_enqueue_script_list").show();
2402
2403 } else {
2404
2405 $(".wpvr_enqueue_script_list").hide();
2406 }
2407
2408 });
2409
2410 /**
2411 * Sakib
2412 * enable script button on chnage action
2413 */
2414 $("#wpvr_video_script_control").change(function () {
2415
2416 if ($('#wpvr_video_script_control').is(':checked')) {
2417
2418 $(".wpvr_enqueue_video_script_list").show();
2419
2420 } else {
2421
2422 $(".wpvr_enqueue_video_script_list").hide();
2423 }
2424
2425 });
2426
2427
2428 /**
2429 * Nasim
2430 * Check enable script button is on or not
2431 * if on then script list field will be show and if off then script list field will be hide
2432 */
2433 if ($('#wpvr_script_control').is(':checked')) {
2434
2435 $(".wpvr_enqueue_script_list").show();
2436
2437 } else {
2438
2439 $(".wpvr_enqueue_script_list").hide();
2440 }
2441
2442 /**
2443 * Sakib
2444 * Check enable script button is on or not
2445 * if on then script list field will be show and if off then script list field will be hide
2446 */
2447 if ($('#wpvr_video_script_control').is(':checked')) {
2448
2449 $(".wpvr_enqueue_video_script_list").show();
2450
2451 } else {
2452
2453 $(".wpvr_enqueue_video_script_list").hide();
2454 }
2455
2456 /**
2457 * Hides the alert in the settings footer area after a 2000ms delay.
2458 *
2459 * @return {void} No return value
2460 */
2461 function remove_alert(){
2462 setTimeout(function(){
2463 $('.settings-footer-area .wpvr-alert').hide();
2464 }, 2000);
2465 }
2466
2467 $(document).on("click", "#wpvr_role_submit", function (e) {
2468 e.preventDefault();
2469 var ajaxurl = wpvr_obj.ajaxurl;
2470 $(this).children().css('display', 'inline-block');
2471
2472 $('#wpvr_role_submit').attr('disabled', true);
2473 var editor = $('#wpvr_editor_active').is(':checked');
2474 var author = $('#wpvr_author_active').is(':checked');
2475 var fontawesome = $('#wpvr_fontawesome_disable').is(':checked');
2476 var mobile_media_resize = $('#mobile_media_resize').is(':checked');
2477 var wpvr_frontend_notice = $('#wpvr_frontend_notice').is(':checked');
2478 var wpvr_frontend_notice_area = $('#wpvr_frontend_notice_area').val();
2479 var wpvr_script_control = $('#wpvr_script_control').is(':checked');
2480 var wpvr_script_list = $('#wpvr_script_list').val();
2481 var wpvr_video_script_control = $('#wpvr_video_script_control').is(':checked');
2482 var wpvr_video_script_list = $('#wpvr_video_script_list').val();
2483 var high_res_image = $('#high_res_image').is(':checked');
2484 var dis_on_hover = $('#dis_on_hover').is(':checked');
2485 var wpvr_mobile_hotspot_tip = $('#wpvr_mobile_hotspot_tip').is(':checked');
2486 var dokan_vendor = $('#wpvr_dokan_vendor_active').is(':checked');
2487 var wpvr_usage_tracking = $('#wpvr_usage_tracking').is(':checked');
2488
2489 /**
2490 * check enable script button is on and script list field is not empty
2491 */
2492 if ( ($('#wpvr_video_script_control').is(':checked') && wpvr_video_script_list == '') || ($('#wpvr_script_control').is(':checked') && wpvr_script_list == '') ) {
2493 if(($('#wpvr_script_control').is(':checked') && wpvr_script_list == '')){
2494 if (confirm('The "List of Allowed Pages To Load WP VR Scripts " Field Is Empty. No Virtual Tours Will Show Up on Your Site.')) {
2495 if($('#wpvr_video_script_control').is(':checked') && wpvr_video_script_list == ''){
2496 if (confirm("The 'List of Allowed Pages To Load WPVR Video.js ' Field Is Empty. Any Self-hosted 360-degree videos won't function on your site.")) {
2497 jQuery.ajax({
2498 type: "POST",
2499 url: ajaxurl,
2500 data: {
2501 action: "wpvr_role_management",
2502 nonce : wpvr_obj.ajax_nonce,
2503 editor: editor,
2504 author: author,
2505 fontawesome: fontawesome,
2506 mobile_media_resize: mobile_media_resize,
2507 high_res_image: high_res_image,
2508 dis_on_hover: dis_on_hover,
2509 wpvr_mobile_hotspot_tip: wpvr_mobile_hotspot_tip,
2510 wpvr_frontend_notice: wpvr_frontend_notice,
2511 wpvr_frontend_notice_area: wpvr_frontend_notice_area,
2512 wpvr_script_control: wpvr_script_control,
2513 wpvr_script_list: wpvr_script_list,
2514 wpvr_video_script_control: wpvr_video_script_control,
2515 wpvr_video_script_list: wpvr_video_script_list,
2516 dokan_vendor: dokan_vendor,
2517 wpvr_usage_tracking: wpvr_usage_tracking,
2518 // woocommerce: woocommerce,
2519 },
2520 success: function (response) {
2521 $('#wpvr_role_submit .wpvr-loader').css('display', 'none');
2522 $('#wpvr_role_submit').attr('disabled', false);
2523
2524 if (response.status == 'success') {
2525 $('.settings-footer-area .wpvr-alert').text(response.message).show();
2526 }
2527
2528 remove_alert();
2529
2530 }
2531 });
2532 } else {
2533 $('#wpvr_role_submit .wpvr-loader').css('display', 'none');
2534 $('#wpvr_role_submit').attr('disabled', false);
2535 }
2536 }else{
2537 jQuery.ajax({
2538 type: "POST",
2539 url: ajaxurl,
2540 data: {
2541 action: "wpvr_role_management",
2542 nonce : wpvr_obj.ajax_nonce,
2543 editor: editor,
2544 author: author,
2545 fontawesome: fontawesome,
2546 mobile_media_resize: mobile_media_resize,
2547 high_res_image: high_res_image,
2548 wpvr_frontend_notice: wpvr_frontend_notice,
2549 wpvr_frontend_notice_area: wpvr_frontend_notice_area,
2550 wpvr_script_control: wpvr_script_control,
2551 wpvr_script_list: wpvr_script_list,
2552 wpvr_video_script_control: wpvr_video_script_control,
2553 wpvr_video_script_list: wpvr_video_script_list,
2554 dokan_vendor: dokan_vendor,
2555 wpvr_usage_tracking: wpvr_usage_tracking,
2556 // woocommerce: woocommerce,
2557 },
2558 success: function (response) {
2559 $('#wpvr_role_submit .wpvr-loader').css('display', 'none');
2560 $('#wpvr_role_submit').attr('disabled', false);
2561
2562 if (response.status == 'success') {
2563 $('.settings-footer-area .wpvr-alert').text(response.message).show();
2564 }
2565
2566 remove_alert();
2567
2568 }
2569 });
2570 }
2571 } else {
2572 $('#wpvr_role_submit .wpvr-loader').css('display', 'none');
2573 $('#wpvr_role_submit').attr('disabled', false);
2574 }
2575 }else if($('#wpvr_video_script_control').is(':checked') && wpvr_video_script_list == ''){
2576
2577 if (confirm("The 'List of Allowed Pages To Load WPVR Video.js ' Field Is Empty. Any Self-hosted 360-degree videos won't function on your site.")) {
2578 if(($('#wpvr_script_control').is(':checked') && wpvr_script_list == '')){
2579 if (confirm('The "List of Allowed Pages To Load WP VR Scripts " Field Is Empty. No Virtual Tours Will Show Up on Your Site.')) {
2580 jQuery.ajax({
2581 type: "POST",
2582 url: ajaxurl,
2583 data: {
2584 action: "wpvr_role_management",
2585 nonce : wpvr_obj.ajax_nonce,
2586 editor: editor,
2587 author: author,
2588 fontawesome: fontawesome,
2589 mobile_media_resize: mobile_media_resize,
2590 high_res_image: high_res_image,
2591 dis_on_hover: dis_on_hover,
2592 wpvr_mobile_hotspot_tip: wpvr_mobile_hotspot_tip,
2593 wpvr_frontend_notice: wpvr_frontend_notice,
2594 wpvr_frontend_notice_area: wpvr_frontend_notice_area,
2595 wpvr_script_control: wpvr_script_control,
2596 wpvr_script_list: wpvr_script_list,
2597 wpvr_video_script_control: wpvr_video_script_control,
2598 wpvr_video_script_list: wpvr_video_script_list,
2599 dokan_vendor: dokan_vendor,
2600 wpvr_usage_tracking: wpvr_usage_tracking,
2601 // woocommerce: woocommerce,
2602 },
2603 success: function (response) {
2604 $('#wpvr_role_submit .wpvr-loader').css('display', 'none');
2605 $('#wpvr_role_submit').attr('disabled', false);
2606
2607 if (response.status == 'success') {
2608 $('.settings-footer-area .wpvr-alert').text(response.message).show();
2609 }
2610 remove_alert();
2611
2612 }
2613 });
2614 }else {
2615 $('#wpvr_role_submit .wpvr-loader').css('display', 'none');
2616 $('#wpvr_role_submit').attr('disabled', false);
2617 }
2618 }else{
2619 jQuery.ajax({
2620 type: "POST",
2621 url: ajaxurl,
2622 data: {
2623 action: "wpvr_role_management",
2624 nonce : wpvr_obj.ajax_nonce,
2625 editor: editor,
2626 author: author,
2627 fontawesome: fontawesome,
2628 mobile_media_resize: mobile_media_resize,
2629 high_res_image: high_res_image,
2630 dis_on_hover: dis_on_hover,
2631 wpvr_mobile_hotspot_tip: wpvr_mobile_hotspot_tip,
2632 wpvr_frontend_notice: wpvr_frontend_notice,
2633 wpvr_frontend_notice_area: wpvr_frontend_notice_area,
2634 wpvr_script_control: wpvr_script_control,
2635 wpvr_script_list: wpvr_script_list,
2636 wpvr_video_script_control: wpvr_video_script_control,
2637 wpvr_video_script_list: wpvr_video_script_list,
2638 dokan_vendor: dokan_vendor,
2639 wpvr_usage_tracking: wpvr_usage_tracking,
2640 // woocommerce: woocommerce,
2641 },
2642 success: function (response) {
2643 $('#wpvr_role_submit .wpvr-loader').css('display', 'none');
2644 $('#wpvr_role_submit').attr('disabled', false);
2645
2646 if (response.status == 'success') {
2647 $('.settings-footer-area .wpvr-alert').text(response.message).show();
2648 }
2649
2650 remove_alert();
2651
2652 }
2653 });
2654 }
2655 } else {
2656 $('#wpvr_role_submit .wpvr-loader').css('display', 'none');
2657 $('#wpvr_role_submit').attr('disabled', false);
2658 }
2659 }
2660
2661 } else {
2662 jQuery.ajax({
2663 type: "POST",
2664 url: ajaxurl,
2665 data: {
2666 action: "wpvr_role_management",
2667 nonce : wpvr_obj.ajax_nonce,
2668 editor: editor,
2669 author: author,
2670 fontawesome: fontawesome,
2671 mobile_media_resize: mobile_media_resize,
2672 high_res_image: high_res_image,
2673 dis_on_hover: dis_on_hover,
2674 wpvr_mobile_hotspot_tip: wpvr_mobile_hotspot_tip,
2675 wpvr_frontend_notice: wpvr_frontend_notice,
2676 wpvr_frontend_notice_area: wpvr_frontend_notice_area,
2677 wpvr_script_control: wpvr_script_control,
2678 wpvr_script_list: wpvr_script_list,
2679 wpvr_video_script_control: wpvr_video_script_control,
2680 wpvr_video_script_list: wpvr_video_script_list,
2681 dokan_vendor: dokan_vendor,
2682 wpvr_usage_tracking: wpvr_usage_tracking,
2683 },
2684 success: function (response) {
2685 $('#wpvr_role_submit .wpvr-loader').css('display', 'none');
2686 $('#wpvr_role_submit').attr('disabled', false);
2687 if (response.status == 'success') {
2688 $('.settings-footer-area .wpvr-alert').text(response.message).show();
2689 }
2690
2691 remove_alert();
2692 }
2693 });
2694 }
2695
2696
2697
2698 });
2699
2700
2701 //-----------reset button----------
2702 $(document).on("click", "#wpvr_role_reset", function (e) {
2703 e.preventDefault();
2704 $(this).attr('disabled', true);
2705
2706 var confirmation = confirm('All settings will be reset to default. Are you sure?');
2707 // Code to reset settings to default if the user clicks "Yes"
2708 if (confirmation) {
2709 $('#wpvr_editor_active').prop('checked', false);
2710 $('#wpvr_author_active').prop('checked', false);
2711 $('#wpvr_fontawesome_disable').prop('checked', false);
2712 $('#mobile_media_resize').prop('checked', false);
2713 $('#wpvr_frontend_notice').prop('checked', false);
2714 $('#wpvr_script_control').prop('checked', false);
2715 $('#wpvr_video_script_control').prop('checked', false);
2716 $('#high_res_image').prop('checked', false);
2717 $('#dis_on_hover').prop('checked', false);
2718 $('#wpvr_mobile_hotspot_tip').prop('checked', false);
2719 $('#wpvr_dokan_vendor_active').prop('checked', false);
2720 $('#wpvr_usage_tracking').prop('checked', false);
2721 $(".wpvr_enqueue_video_script_list").hide();
2722 $(".wpvr_enqueue_script_list").hide();
2723
2724 $("#wpvr_role_submit").trigger('click');
2725 }
2726 $(this).attr('disabled', false);
2727
2728 });
2729
2730 //------general tab's inner tab-------
2731 jQuery(document).ready(function ($) {
2732
2733 $('.general-inner-tab .inner-nav li span').on('click', function () {
2734 var this_id = $(this).attr('data-href');
2735
2736 $(this).parent('li').addClass('active');
2737 $(this).parent('li').siblings().removeClass('active');
2738
2739 $(this_id).show();
2740 $(this_id).siblings().hide();
2741 });
2742 });
2743
2744 //------active tab scripts-------
2745 jQuery(document).ready(function ($) {
2746
2747 function getUrlVars() {
2748 var vars = [],
2749 hash;
2750 var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
2751 for (var i = 0; i < hashes.length; i++) {
2752 hash = hashes[i].split('=');
2753 vars.push(hash[0]);
2754 vars[hash[0]] = hash[1];
2755 }
2756 return vars;
2757 }
2758 var activeTab = 'general',
2759 vr_main_tab = $('#wpvr-main-nav'),
2760 var_main_tab_contents = $('#wpvr-main-tab-contents').find('.rex-pano-tab').not(".single-scene,.single-hotspot"),
2761 scene_content = $('.scene-content'),
2762 scene_nav = $('.scene-nav'),
2763 single_scene = $('.single-scene'),
2764 hotspot_content = $('.hotspot-setup'),
2765 single_hotspot = $('.single-hotspot'),
2766 delete_scene_btn = $('.delete-scene'),
2767 delete_hotspot_btn = $('.delete-hotspot');
2768
2769 var _q_activeTab = getUrlVars()["active_tab"];
2770 var _sceneID = getUrlVars()["scene"];
2771 var _hotspotID = getUrlVars()["hotspot"];
2772 var default_tabs = ['general', 'scene', 'hotspot', 'video'];
2773 if (_q_activeTab) {
2774 if (default_tabs.includes(_q_activeTab)) {
2775 activeTab = _q_activeTab;
2776 if(activeTab == "video" ){
2777 vr_main_tab.find('li:not(:first)').removeClass('active');
2778 vr_main_tab.find(".videos").addClass('active');
2779 }else{
2780 vr_main_tab.find('li:not(:first)').removeClass('active');
2781 vr_main_tab.find('.' + activeTab).addClass('active');
2782 }
2783
2784 // scene screens
2785 var_main_tab_contents.addClass('active');
2786 if (activeTab === 'scene' || activeTab === 'hotspot') {
2787 var_main_tab_contents.not('#scenes').removeClass('active');
2788 } else {
2789 var_main_tab_contents.not('#' + activeTab).removeClass('active');
2790 }
2791 if(activeTab === 'hotspot'){
2792 $(".rex-pano-nav-menu.main-nav ul li.hotspot span").trigger('click')
2793 }
2794
2795 // scene contents
2796 if (_sceneID) {
2797 var scenesIds = [];
2798 var sceneID = '#scene-' + _sceneID;
2799 var scene_nav_items = scene_nav.find('li');
2800 scene_nav.find('li').each(function () {
2801 var index = $(this).find('span').attr('data-index');
2802 if (index) {
2803 scenesIds.push(index);
2804 }
2805 });
2806 if (scenesIds.includes(_sceneID)) {
2807 scene_nav_items.removeClass('active');
2808 scene_nav.find('li').each(function () {
2809 var index = $(this).find('span').attr('data-index');
2810 if (_sceneID == index) {
2811 $(this).addClass('active');
2812 }
2813 });
2814 if (activeTab == 'scene' || _sceneID) {
2815 single_scene.removeClass('active');
2816 $(sceneID).addClass('active');
2817 }
2818 } else {
2819 scene_nav.find('li:first').addClass('active');
2820 }
2821
2822 if (activeTab === 'scene') {
2823 if (scenesIds.includes(_sceneID)) {
2824 $(single_scene).removeClass('active');
2825 $(sceneID).addClass('active');
2826 }
2827 } else {
2828 $(delete_scene_btn).hide();
2829 $(scene_nav).hide();
2830 $('.scene-content').hide();
2831 $(sceneID).find('.hotspot-setup').show();
2832 }
2833
2834 //hotspot contents
2835 var hotspot_nav = $('.single-scene.active').find('.hotspot-nav');
2836 var hotspotIds = [];
2837 var hotspot_nav_items = $('.single-scene.active').find('.hotspot-nav').find('li');
2838 var activeHotspotId = '#scene-' + _sceneID + 'hotspot-' + _hotspotID;
2839 hotspot_nav_items.each(function () {
2840 var index = $(this).find('span').attr('data-index');
2841 if (index) {
2842 hotspotIds.push(index);
2843 activeHotspotId = $(this).find('span').attr('data-href');
2844 }
2845 });
2846 if (hotspotIds.includes(_hotspotID)) {
2847 hotspot_nav_items.removeClass('active');
2848 hotspot_nav.find('li').each(function () {
2849 var index = $(this).find('span').attr('data-index');
2850 if (_hotspotID === index) {
2851 $(this).addClass('active');
2852 }
2853 });
2854 if (activeHotspotId) {
2855 $(sceneID).find('.single-hotspot').removeClass('active');
2856 $(activeHotspotId).addClass('active');
2857 }
2858 }
2859 }
2860 }
2861 }
2862
2863
2864 $(document).on("click", ".wpvr-help-resource__video-section", function () {
2865 $('#wpvr-help-video-iframe').attr('src', 'https://www.youtube.com/embed/kKHUlVKtesQ');
2866 if($('#wpvr-help-video-iframe').attr('src') != ''){
2867 $(".wpvr-iframe-modal").show();
2868 }
2869 });
2870
2871
2872 $(document).on("click", ".wpvr-iframe-modal__cross-icon", function () {
2873 $(".wpvr-iframe-modal").hide();
2874 var videoPlayer =$('#wpvr-help-video-iframe');
2875 videoPlayer.attr('src', '');
2876
2877 });
2878
2879
2880
2881 });
2882
2883 $(document).on("click", ".wpvr_url_open", function (event) {
2884 if ($(this).val() == 'off') {
2885 $(this).val('on');
2886 }
2887 else {
2888 $(this).val('off');
2889 }
2890 });
2891
2892 $(document).ready(function() {
2893 $('textarea[name*=hotspot-content]').summernote({
2894 toolbar: [
2895 ['style', ['style']],
2896 ['font', ['bold', 'underline', 'clear']],
2897 ['fontname', ['fontname']],
2898 ['color', ['color']],
2899 ['para', ['ul', 'ol', 'paragraph']],
2900 ['table', ['table']],
2901 ['insert', ['link', 'picture', 'video']],
2902 ['view', ['codeview', 'help']],
2903 ],
2904 callbacks: {
2905 onInit: function() {
2906 var $editor = $(this);
2907 var $noteEditor = $editor.next('.note-editor');
2908
2909 // Intercept Video button click
2910 $noteEditor.on('click', 'button.note-btn[aria-label="Video"]', function(e) {
2911 // Small delay to check if cursor is on a video
2912 setTimeout(function() {
2913 // Get the current selection
2914 var range = $editor.summernote('createRange');
2915 if (range) {
2916 var $node = $(range.sc);
2917
2918 // Check if cursor is on a video iframe
2919 var $iframe = $node.closest('iframe.note-video-clip');
2920 if (!$iframe.length) {
2921 $iframe = $node.find('iframe.note-video-clip').first();
2922 }
2923
2924 if ($iframe.length && $iframe.attr('src')) {
2925 var embedUrl = $iframe.attr('src');
2926 var videoUrl = '';
2927
2928 // Extract YouTube URL
2929 if (embedUrl && (embedUrl.indexOf('youtube.com') > -1 || embedUrl.indexOf('youtu.be') > -1)) {
2930 var match = embedUrl.match(/embed\/([^?&]*)/);
2931 if (match && match[1]) {
2932 videoUrl = 'https://www.youtube.com/watch?v=' + match[1];
2933 }
2934 } else if (embedUrl) {
2935 videoUrl = embedUrl;
2936 }
2937
2938 // Show the video dialog
2939 $editor.summernote('videoDialog.show');
2940
2941 // Pre-populate the video URL in the dialog
2942 setTimeout(function() {
2943 var $urlInput = $('.note-video-url');
2944 if ($urlInput.length && videoUrl) {
2945 $urlInput.val(videoUrl);
2946 $urlInput.focus();
2947 }
2948 }, 150);
2949 }
2950 }
2951 }, 50);
2952 });
2953 },
2954 onKeyup: function(e) {
2955 var getHotspotContent = $(this).summernote('code').trim();
2956 var tempDiv = document.createElement('div');
2957 tempDiv.innerHTML = getHotspotContent;
2958 var plainText = tempDiv.textContent || tempDiv.innerText || '';
2959 plainText = plainText.replace(/\u00a0/g, '').trim();
2960 var getParent = $(this).parent();
2961 var getMainParent = getParent.parent();
2962 var getClickContent = getMainParent.find('.hotspot-url');
2963
2964 if (plainText.length > 0) {
2965 getClickContent.find('input[name*=hotspot-url]').val('');
2966 getClickContent.find('input[name*=hotspot-url]').attr('placeholder', 'You can set either a URL or an On-click content');
2967 getClickContent.find('input[name*=hotspot-url]').attr("disabled", true);
2968 } else {
2969 getClickContent.find('input[name*=hotspot-url]').attr("disabled", false);
2970 }
2971 }
2972 }
2973 });
2974 $('textarea[name*=hotspot-hover]').summernote({
2975 toolbar: [
2976 ['style', ['style']],
2977 ['font', ['bold', 'underline', 'clear']],
2978 ['fontname', ['fontname']],
2979 ['color', ['color']],
2980 ['para', ['ul', 'ol', 'paragraph']],
2981 ['table', ['table']],
2982 ['insert', ['link', 'picture', 'video']],
2983 ['view', ['codeview', 'help']],
2984 ],
2985 fontNames: ['Arial', 'Helvetica', 'Tahoma', 'Courier New', 'Verdana', 'Impact', 'Times New Roman', 'system-ui', 'Helvetica Neue'],
2986 callbacks: {
2987 onInit: function() {
2988 var $editor = $(this);
2989 var $noteEditor = $editor.next('.note-editor');
2990
2991 // Intercept Video button click
2992 $noteEditor.on('click', 'button.note-btn[aria-label="Video"]', function(e) {
2993 // Small delay to check if cursor is on a video
2994 setTimeout(function() {
2995 // Get the current selection
2996 var range = $editor.summernote('createRange');
2997 if (range) {
2998 var $node = $(range.sc);
2999
3000 // Check if cursor is on a video iframe
3001 var $iframe = $node.closest('iframe.note-video-clip');
3002 if (!$iframe.length) {
3003 $iframe = $node.find('iframe.note-video-clip').first();
3004 }
3005
3006 if ($iframe.length && $iframe.attr('src')) {
3007 var embedUrl = $iframe.attr('src');
3008 var videoUrl = '';
3009
3010 // Extract YouTube URL
3011 if (embedUrl && (embedUrl.indexOf('youtube.com') > -1 || embedUrl.indexOf('youtu.be') > -1)) {
3012 var match = embedUrl.match(/embed\/([^?&]*)/);
3013 if (match && match[1]) {
3014 videoUrl = 'https://www.youtube.com/watch?v=' + match[1];
3015 }
3016 } else if (embedUrl) {
3017 videoUrl = embedUrl;
3018 }
3019
3020 // Show the video dialog
3021 $editor.summernote('videoDialog.show');
3022
3023 // Pre-populate the video URL in the dialog
3024 setTimeout(function() {
3025 var $urlInput = $('.note-video-url');
3026 if ($urlInput.length && videoUrl) {
3027 $urlInput.val(videoUrl);
3028 $urlInput.focus();
3029 }
3030 }, 150);
3031 }
3032 }
3033 }, 50);
3034 });
3035
3036 // Override font name dropdown click handler for this specific editor
3037 $editor.next('.note-editor').find('.dropdown-fontname a').off('click').on('click', function(e) {
3038 e.preventDefault();
3039 var fontName = $(this).data('value') || $(this).text();
3040
3041 // Focus on the current editor
3042 $editor.summernote('focus');
3043
3044 // Use Summernote's built-in method to apply font
3045 try {
3046 // First, clear any existing font formatting
3047 var range = $editor.summernote('createRange');
3048 if (range && !range.isCollapsed()) {
3049 // Get selected text
3050 var selectedText = range.toString();
3051
3052 // Use Summernote's insertHTML to replace content
3053 var fontHtml = '<span style="font-family: ' + fontName + ';">' + selectedText + '</span>';
3054 $editor.summernote('insertHTML', fontHtml);
3055 } else {
3056 // No selection, use execCommand for typing
3057 $editor.summernote('focus');
3058 document.execCommand('fontName', false, fontName);
3059 }
3060 } catch (error) {
3061 console.log('Font application error, using fallback method');
3062 // Fallback method
3063 document.execCommand('fontName', false, fontName);
3064 }
3065
3066 // Update dropdown button text for this editor
3067 $(this).closest('.note-editor').find('.note-current-fontname').text(fontName);
3068
3069 // Close dropdown
3070 var $dropdownMenu = $(this).closest('.dropdown-menu');
3071 $dropdownMenu.removeClass('show').hide();
3072 $dropdownMenu.prev('.dropdown-toggle').removeClass('show').attr('aria-expanded', 'false');
3073
3074 // Trigger change event
3075 setTimeout(function() {
3076 $editor.trigger('summernote.change');
3077 }, 100);
3078 });
3079 },
3080
3081 // Clean up the content after any change
3082 onChange: function(contents, $editable) {
3083 // Debounce the cleanup to avoid conflicts
3084 clearTimeout(this.cleanupTimeout);
3085 this.cleanupTimeout = setTimeout(function() {
3086 // Remove all font-family styles from elements that shouldn't have them
3087 $editable.find('*:not(span)').each(function() {
3088 if (this.style && this.style.fontFamily) {
3089 this.style.fontFamily = '';
3090 }
3091 });
3092
3093 // Clean up empty spans
3094 $editable.find('span').each(function() {
3095 var $span = $(this);
3096 var text = $span.text().replace(/[\uFEFF\u200B-\u200D\u2060]/g, '').trim();
3097
3098 if (!text) {
3099 $span.remove();
3100 } else {
3101 // If span has other styles besides font-family, keep only font-family
3102 var fontFamily = $span.css('font-family');
3103 if (fontFamily && fontFamily !== 'inherit') {
3104 $span.attr('style', 'font-family: ' + fontFamily + ';');
3105 } else if (!fontFamily || fontFamily === 'inherit') {
3106 $span.contents().unwrap();
3107 }
3108 }
3109 });
3110
3111 // Remove nested spans with font-family
3112 $editable.find('span[style*="font-family"] span[style*="font-family"]').each(function() {
3113 $(this).contents().unwrap();
3114 });
3115 }, 200);
3116 }
3117 }
3118 });
3119 });
3120
3121 $(document).on("submit", "#trigger-rollback", function (event) {
3122 event.preventDefault();
3123 if(confirm('Are you sure?')) {
3124 let version = $("#trigger-rollback").serialize();
3125 let redirectUrl = wpvr_global_obj.url_info.admin_url + 'admin.php?' + version;
3126 window.location.href = redirectUrl;
3127 }
3128 });
3129
3130 $(document).on("click", ".single-settings .wpvr-switcher input:disabled+label,.vr-export,#styled-radio-sv-off,#styled-radio-sv-on,#wpvr_floor_plan_enabler,.wpvr_cardboard_disable_label,.rex-import-disable,.single-settings.scene-animation", function (event) {
3131 event.preventDefault();
3132 $("#wpvr_premium_feature_popup").show();
3133 });
3134
3135
3136
3137 $(document).on("click", "#wpvr_premium_feature_close", function () {
3138 $("#wpvr_premium_feature_popup").hide();
3139 });
3140
3141
3142 $(document).on("click", ".wpvr-help-resource__dropdown-section", function () {
3143 // When an element with the class 'wpvr-help-resource__dropdown-section' is clicked,
3144 // toggle the 'show-dropdown' class on its siblings.
3145 $(this).siblings().toggleClass("show-dropdown");
3146 });
3147
3148 $(document).on("click", ".wpvr-layout__radio-container", function () {
3149 let findLayout = $(this).find('.wpvr-layout__radio-label').data('layout');
3150
3151 if(findLayout == 'layout1'){
3152 event.preventDefault();
3153
3154 $('#wpvr_premium_feature_popup').show();
3155 }
3156 });
3157
3158 // ------window on scroll add class to comparison table header------
3159 $(window).on('scroll', function() {
3160 var $header = $('.wpvr-compare .list-header');
3161
3162 if ($header.length > 0) {
3163 var headerOffset = $header.offset().top - $(window).scrollTop();
3164
3165 if (headerOffset < 27) {
3166 $header.addClass('sticked');
3167 } else {
3168 $header.removeClass('sticked');
3169 }
3170
3171 }
3172
3173 });
3174
3175 $(document).ready(function() {
3176 handle_add_pitch_button();
3177 });
3178
3179 $(document).on( 'mousedown', 'div.pnlm-dragfix', () => { handle_add_pitch_button() } );
3180
3181 function get_active_tab() {
3182 let activeTab = $('#wpvr_active_tab').val() ?? null;
3183 if ( !activeTab ) {
3184 activeTab = $(".rex-pano-tab-nav li.active").data('screen');
3185 }
3186 return activeTab;
3187 }
3188
3189 function handle_add_pitch_button( activeTab = null, panovideo = null ) {
3190 activeTab = activeTab === null ? get_active_tab() : activeTab;
3191
3192 if(handle_hotspot_tab(activeTab, true))
3193 return;
3194
3195 if( activeTab && 'hotspot' === activeTab && '' !== $( "#panodata" ).html().trim() ) {
3196 $(".add-pitch").removeClass('rex-hide-coordinates');
3197 }
3198 else {
3199 $(".add-pitch").addClass('rex-hide-coordinates');
3200 }
3201
3202 if('video' === activeTab){
3203 $(".rex-add-coordinates").addClass('rex-hide-coordinates');
3204 }else{
3205 $(".rex-add-coordinates").removeClass('rex-hide-coordinates');
3206 }
3207
3208 // Hide checklist for streetview tours in edit mode
3209 var isStreetViewTour = false;
3210 // Check by input (edit mode)
3211 if ($("input[name='wpvrStreetView']:checked").val() === 'on') {
3212 isStreetViewTour = true;
3213 }
3214 if( 'streetview' === activeTab || 'video' === activeTab || $('.videos.active').length || isStreetViewTour ) {
3215 $('#wpvr_item_tour_checklist__box').css('display', 'none');
3216 }else{
3217 $('#wpvr_item_tour_checklist__box').css('display', 'block');
3218 }
3219
3220 toggleSceneGallery(activeTab, panovideo);
3221 }
3222
3223 $(document).ready(function() {
3224 $(".rex-pano-tab-nav li").on( 'click', function() {
3225 var activeTab = jQuery(this).data('screen');
3226 if(handle_hotspot_tab(activeTab, false))
3227 return false;
3228 });
3229 });
3230
3231 function handle_hotspot_tab(activeTab, redirect) {
3232 let isReturn = false;
3233 if (activeTab && 'hotspot' === activeTab) {
3234 const activeScene = jQuery('.scene-nav li.active span').attr('data-index');
3235 const activeSceneId = $('#scene-' + activeScene).find(".form-group img").attr('src');
3236 let activeTabUrl = window?.wpvr_global_obj?.active_tab_url;
3237 if (!activeSceneId && redirect) {
3238 window.location.replace(activeTabUrl);
3239 isReturn = true;
3240 } else if(!activeSceneId && !redirect){
3241 alert(window?.wpvr_global_obj?.hotspot_warning_text);
3242 jQuery('.rex-pano-tab-nav li scene').addClass('active');
3243 isReturn = true;
3244 }
3245 }
3246 return isReturn;
3247 }
3248
3249
3250 function toggleSceneGallery(activeTab = null, panovideo = null) {
3251 activeTab = activeTab === null ? get_active_tab() : activeTab;
3252 panovideo = panovideo === null ? $("input[name='panovideo']:checked").val() : panovideo;
3253 if ((activeTab && ('video' === activeTab || 'streetview' === activeTab ) || ( panovideo === 'on' && ( 'floorPlan' === activeTab || 'backgroundTour' === activeTab || 'export' === activeTab)))) {
3254 jQuery('.scene-gallery').hide();
3255 } else {
3256 jQuery('.scene-gallery').show();
3257 }
3258 }
3259
3260 // Function to update the progress bar
3261 function updateProgress() {
3262 let totalItems = $('.wpvr-checklist-items').length; // Total number of checklist items
3263 let checkedItems = $('.wpvr-checklist-items:checked').length; // Number of checked items
3264
3265 // Calculate progress percentage
3266 let progress = Math.round((checkedItems / totalItems) * 100);
3267
3268 // Update progress bar
3269 $('#wpvr-progress-bar').css('width', progress + '%');
3270 $('#wpvr-progress-text').text(progress + '%');
3271
3272 // Change color of progress bar based on progress
3273 if (progress === 100) {
3274 $('#wpvr-progress-bar').css('background-color', 'green');
3275 $('#wpvr-progress-text').css('color', 'white');
3276 }else{
3277 $('#wpvr-progress-text').css('color', '#3F04FE');
3278 }
3279 }
3280
3281 updateProgress();
3282
3283 $(document).on("click", ".toppitch", function () {
3284 if (!$('#wpvr-check-hotspots').is(':checked')) {
3285 $('#wpvr-check-hotspots').prop('checked', true);
3286 $('#wpvr-check-hotspots').closest('.wpvr-checklist-item').css('color', '#0E003C');
3287 }
3288 updateProgress();
3289 });
3290
3291
3292 $(document).ready(function() {
3293 $(".rex-pano-tab .inner-nav-content .single-settings.has-children .vr-switcher-check").each(function() {
3294 if ($(this).is(':checked')) {
3295 $(this).parents('.single-settings').addClass('margin-bottom-remove');
3296 } else {
3297 $(this).parents('.single-settings').removeClass('margin-bottom-remove');
3298 }
3299 });
3300 });
3301
3302
3303
3304 $('.rex-pano-tab .inner-nav-content .single-settings.has-children .vr-switcher-check').on('change', function() {
3305 if ($(this).is(':checked')) {
3306 $(this).parents('.single-settings').addClass('margin-bottom-remove');
3307 } else {
3308 $(this).parents('.single-settings').removeClass('margin-bottom-remove');
3309 }
3310 });
3311
3312 // Function to handle visibility toggle based on checkbox state
3313 function toggleKeyboardZoom() {
3314 var isChecked = $("input[name='mouseZoom']").is(':checked');
3315 $('.mouse-zoom-control-settings-wrapper').toggle(isChecked);
3316 }
3317
3318 // Initial state setup on page load
3319 toggleKeyboardZoom();
3320
3321 // Event listener for checkbox changes using more specific selector
3322 $("input[name='mouseZoom']").on("change", toggleKeyboardZoom);
3323
3324
3325
3326
3327
3328 // Function to handle visibility toggle based on checkbox state
3329 function toggleKeyboardSettings() {
3330 var isChecked = $("input[name='draggable']").is(':checked');
3331 $('.mouse-dragable-control-settings-wrapper').toggle(isChecked);
3332 }
3333
3334 // Initial state setup on page load
3335 toggleKeyboardSettings();
3336
3337 // Event listener for checkbox changes using more specific selector
3338 $("input[name='draggable']").on("change", toggleKeyboardSettings);
3339
3340
3341
3342 // Function to handle visibility toggle based on checkbox state
3343 function toggleGallerySettings() {
3344 var isChecked = $("input[name='vrgallery']").is(':checked');
3345 $('.scene-gallery-settings-wrapper').toggle(isChecked);
3346 }
3347
3348 // Initial state setup on page load
3349 toggleGallerySettings();
3350
3351 // Event listener for checkbox changes using more specific selector
3352 $("input[name='vrgallery']").on("change", toggleGallerySettings);
3353
3354
3355
3356 // Function to handle visibility toggle based on checkbox state
3357 function toggleGyroSettings() {
3358 var isChecked = $("input[name='gyro']").is(':checked');
3359 $('.zyro-settings-wrapper').toggle(isChecked);
3360 }
3361
3362 // Initial state setup on page load
3363 toggleGyroSettings();
3364
3365 // Event listener for checkbox changes using more specific selector
3366 $("input[name='gyro']").on("change", toggleGyroSettings);
3367
3368
3369 // Function to handle visibility toggle based on checkbox state
3370 function toggleExplainerSwitch() {
3371 var isChecked = $("input[name='explainerSwitch']").is(':checked');
3372 $('.explainer-video-settings-wrapper').toggle(isChecked);
3373 }
3374
3375 // Initial state setup on page load
3376 toggleExplainerSwitch();
3377
3378 // Event listener for checkbox changes using more specific selector
3379 $("input[name='explainerSwitch']").on("change", toggleExplainerSwitch);
3380
3381
3382 // Function to handle visibility toggle based on checkbox state
3383 function toggleZoomSwitch() {
3384 var isChecked = $("input[name='globalzoom']").is(':checked');
3385 $('.set-zoom-perference-control-settings-wrapper').toggle(isChecked);
3386 }
3387
3388 // Initial state setup on page load
3389 toggleZoomSwitch();
3390
3391 // Event listener for checkbox changes using more specific selector
3392 $("input[name='globalzoom']").on("change", toggleZoomSwitch);
3393
3394
3395
3396
3397
3398 // Get initial checkbox value and convert to boolean
3399 var callToAction = $("input[name='calltoaction']").val();
3400 callToAction = callToAction == 'on' ? true : false;
3401
3402 // Show or hide the call-to-action section on page load
3403 if (callToAction) {
3404 $('.call-to-action').show();
3405 } else {
3406 $('.call-to-action').hide();
3407 }
3408
3409 // Toggle visibility of the call-to-action section on checkbox change
3410 $(document).on("change", "input[name='calltoaction']", function () {
3411 var calltoactionbutton = $(this).is(':checked') ? 'on' : 'off';
3412 if (calltoactionbutton == 'on') {
3413 $('.call-to-action').show();
3414 } else {
3415 $('.call-to-action').hide();
3416 }
3417 });
3418
3419
3420 // Toggle visibility of the ".custom-css-field" section based on the "customcss" checkbox state.
3421
3422 // 1. On page load:
3423 // - Get the current value of the "customcss" input.
3424 // - Convert 'on' to boolean true.
3425 // - Show or hide the ".custom-css-field" section accordingly.
3426
3427 var customCssEnable = $("input[name='customcss']").val();
3428 customCssEnable = customCssEnable == 'on' ? true : false;
3429
3430 if (customCssEnable) {
3431 $('.custom-css-field').show();
3432 } else {
3433 $('.custom-css-field').hide();
3434 }
3435
3436 // 2. On checkbox state change:
3437 // - Detect changes to the "customcss" checkbox.
3438 // - Use .is(':checked') to determine current state.
3439 // - Alert the value ('on' or 'off').
3440 // - Show or hide the ".custom-css-field" section accordingly.
3441
3442 $(document).on("change", "input[name='customcss']", function () {
3443 var custom_css_field = $(this).is(':checked') ? 'on' : 'off';
3444 alert(custom_css_field);
3445
3446 if (custom_css_field == 'on') {
3447 $('.custom-css-field').show();
3448 } else {
3449 $('.custom-css-field').hide();
3450 }
3451 });
3452
3453 // Run when the DOM is fully loaded
3454 $(document).ready(function() {
3455 // Only apply on admin panel
3456 if ($('body').hasClass('post-type-wpvr_item')) {
3457 // Apply fixes after preview is loaded
3458 $(document).on('click', '.panolenspreview', function() {
3459 setTimeout(fixFloorplanPointers, 2000);
3460 });
3461
3462 // Also apply when document is ready
3463 setTimeout(fixFloorplanPointers, 1000);
3464 }
3465 });
3466
3467 /**
3468 * Fix floorplan pointers to stay within image boundaries
3469 */
3470 function fixFloorplanPointers() {
3471 // Find all floorplan pointers in admin preview
3472 $('.wpvr-floor-map .floor-plan-pointer').each(function() {
3473 var $pointer = $(this);
3474 var $container = $pointer.closest('.wpvr-floor-map');
3475
3476 if ($container.length) {
3477 var containerWidth = $container.width();
3478 var containerHeight = $container.height();
3479 var pointerWidth = $pointer.outerWidth();
3480 var pointerHeight = $pointer.outerHeight();
3481
3482 // Get current position
3483 var currentLeft = parseInt($pointer.css('left'), 10);
3484 var currentTop = parseInt($pointer.css('top'), 10);
3485
3486 // Calculate safe boundaries
3487 var maxLeft = containerWidth - pointerWidth;
3488 var maxTop = containerHeight - pointerHeight;
3489
3490 // Store original position as custom properties for CSS clamp()
3491 $pointer.css('--x-pos', currentLeft + 'px');
3492 $pointer.css('--y-pos', currentTop + 'px');
3493
3494 // Ensure pointer stays within boundaries
3495 if (currentLeft < 0) {
3496 $pointer.css('left', '9px');
3497 } else if (currentLeft > maxLeft) {
3498 $pointer.css('left', (maxLeft - 9) + 'px');
3499 }
3500
3501 if (currentTop < 0) {
3502 $pointer.css('top', '9px');
3503 } else if (currentTop > maxTop) {
3504 $pointer.css('top', (maxTop - 9) + 'px');
3505 }
3506 }
3507 });
3508 }
3509
3510 // Check for floorplan pointers periodically in case they're added dynamically
3511 setInterval(fixFloorplanPointers, 3000);
3512
3513 $('.scene-setup').on('input', 'input[type="text"]', function () {
3514 // Escape < and > to prevent script execution when reading
3515 this.value = this.value.replace(/</g, "&lt;").replace(/>/g, "&gt;");
3516 });
3517
3518
3519 /**
3520 * WPVR Telemetry Tracking
3521 */
3522 $(document).ready(function() {
3523 // Global tracking helper
3524 window.wpvrTrackAdminEvent = function(eventName, properties = {}) {
3525 if (typeof wpvr_global_obj === 'undefined' || !wpvr_global_obj.ajaxurl) {
3526 return;
3527 }
3528
3529 $.ajax({
3530 url: wpvr_global_obj.ajaxurl,
3531 type: 'POST',
3532 data: {
3533 action: 'wpvr_track_telemetry_event',
3534 event_name: eventName,
3535 properties: properties,
3536 security: wpvr_global_obj.ajax_nonce
3537 }
3538 });
3539 };
3540
3541 // Track Upgrade Clicks
3542 $(document).on('click', 'a[href*="wpvr-pricing"], .go-pro-link, .wpvr-go-pro', function() {
3543 wpvrTrackAdminEvent('upgrade_clicked', { source: 'admin_link' });
3544 });
3545
3546 $(document).on('click', function(e) {
3547 var $target = $(e.target);
3548 var featureName = 'pro_feature';
3549 var isPaywall = false;
3550 var $context = null;
3551
3552 // Check 1: Wrapper with _is_pro class (e.g. wpvr_cardboard_disable_is_pro)
3553 var $proWrapper = $target.closest('[class*="_is_pro"]');
3554 if ($proWrapper.length > 0) {
3555 isPaywall = true;
3556 $context = $proWrapper;
3557 }
3558
3559 // Check 2: Standard Container with internal Pro badge (Nav menu, buttons, etc.)
3560 if (!isPaywall) {
3561 var $container = $target.closest('li, label, button, a, .wpvr-import-button');
3562 if ($container.length > 0) {
3563 var hasBadge = $container.find('.navigator-pro-tag, .pro-tag, .is-pro').length > 0 ||
3564 $container.hasClass('is-pro');
3565 if (hasBadge) {
3566 isPaywall = true;
3567 $context = $container;
3568 }
3569 }
3570 }
3571
3572 if (isPaywall && $context) {
3573 // 3. Extract Feature Name
3574 if ($context.attr('data-screen')) {
3575 featureName = $context.attr('data-screen');
3576 } else if ($context.find('input').length > 0) {
3577 featureName = $context.find('input').val();
3578 } else if ($context.hasClass('wpvr-import-button')) {
3579 featureName = 'import_tour';
3580 } else if ($context.attr('class') && $context.attr('class').match(/_is_pro/)) {
3581 // Try to find a label inside to get the feature name from 'for' attribute
3582 var $label = $context.find('label');
3583 if ($label.length > 0 && $label.attr('for')) {
3584 featureName = $label.attr('for');
3585 } else {
3586 // Fallback to class name minus _is_pro
3587 var match = $context.attr('class').match(/([a-zA-Z0-9_-]+)_is_pro/);
3588 if (match && match[1]) {
3589 featureName = match[1];
3590 }
3591 }
3592 }
3593
3594 // Normalize feature name
3595 featureName = featureName.replace(/-/g, '_').toLowerCase();
3596
3597 wpvrTrackAdminEvent('paywall_hit', { feature_name: featureName });
3598 }
3599 });
3600
3601 // Scene Pro Feature Image (Special Case)
3602 $(document).on('click', 'img[src*="scene-pro-feature.png"]', function() {
3603 wpvrTrackAdminEvent('paywall_hit', { feature_name: 'scene_pro_feature' });
3604 });
3605
3606 });
3607
3608 })(jQuery);
3609
3610
3611 // WPVR Hotspot Long-Press Mobile Support
3612 jQuery(document).ready(function($) {
3613 var isTouchDevice = ("ontouchstart" in window) || (navigator.maxTouchPoints > 0);
3614 var disOnHover = (typeof wpvr_obj !== 'undefined') ? wpvr_obj.dis_on_hover : undefined;
3615 var tipEnabled = (typeof wpvr_obj !== 'undefined') ? wpvr_obj.mobile_hotspot_tip : undefined;
3616 var shouldShowAlert = isTouchDevice && (disOnHover !== "1");
3617 if (shouldShowAlert) {
3618 setTimeout(function() {
3619 if (!$('.pnlm-container').length) {
3620 return;
3621 }
3622 $('.pnlm-hotspot-base, .pnlm-hotspot').each(function() {
3623 $(this).off('mouseenter mouseover mouseleave');
3624
3625 // Hide only the inner content <p>, not the hotspot pointer
3626 $(this).find('p').hide();
3627
3628 var longPressTimer;
3629 var isLongPress = false;
3630
3631 // Prevent click after long press
3632 $(this).off('click._wpvrHotspotFix').on('click._wpvrHotspotFix', function(e) {
3633 if ($(this).data('wpvr-longpress')) {
3634 e.preventDefault();
3635 e.stopImmediatePropagation();
3636 $(this).data('wpvr-longpress', false);
3637 return false;
3638 }
3639 });
3640
3641 $(this).on('touchstart', function(e) {
3642 isLongPress = false;
3643 var $hotspot = $(this);
3644
3645 // Hide inner content on touch start
3646 $hotspot.find('p').hide();
3647
3648 longPressTimer = setTimeout(function() {
3649 isLongPress = true;
3650 $hotspot.data('wpvr-longpress', true);
3651
3652 // Hide all other hotspot contents first
3653 $('.pnlm-hotspot-base p, .pnlm-hotspot p').hide();
3654
3655 // Show only this hotspot's content
3656 $hotspot.find('p').show();
3657 }, 600);
3658 });
3659
3660 $(this).on('touchend', function(e) {
3661 clearTimeout(longPressTimer);
3662 if (isLongPress) {
3663 e.preventDefault();
3664 e.stopPropagation();
3665 // Do NOT auto-hide after 2 seconds anymore
3666 // Content will stay open until user taps elsewhere
3667 } else {
3668 // Short tap: hide inner content, let click fire
3669 $(this).find('p').hide();
3670 }
3671 });
3672
3673 $(this).on('touchmove', function() {
3674 clearTimeout(longPressTimer);
3675 isLongPress = false;
3676 // Hide inner content if user starts panning
3677 $(this).find('p').hide();
3678 });
3679 });
3680
3681 // Hide hotspot content when tapping outside any hotspot
3682 $(document).on('touchstart.wpvrHotspotOutside', function(e) {
3683 // If the tap is not inside a hotspot or its content
3684 if (!$(e.target).closest('.pnlm-hotspot-base, .pnlm-hotspot').length) {
3685 $('.pnlm-hotspot-base p, .pnlm-hotspot p').hide();
3686 }
3687 });
3688
3689 // Hide other hotspot contents when another hotspot is long-pressed
3690 $('.pnlm-hotspot-base, .pnlm-hotspot').on('touchstart', function(e) {
3691 // Hide all other hotspot contents except the one being touched
3692 var $current = $(this);
3693 $('.pnlm-hotspot-base, .pnlm-hotspot').not($current).find('p').hide();
3694 });
3695
3696 if (tipEnabled == '1') {
3697 function showHotspotTip() {
3698 if (window.sessionStorage && sessionStorage.getItem('wpvrHotspotTipShown')) return;
3699 if (window.sessionStorage) {
3700 sessionStorage.setItem('wpvrHotspotTipShown', '1');
3701 }
3702 alert('Tip: On mobile devices, long-press a hotspot to show its hover content.');
3703 }
3704 $('.pnlm-container').on('touchstart.wpvrTip touchmove.wpvrTip', showHotspotTip);
3705 $('.pnlm-hotspot-base, .pnlm-hotspot').on('touchstart.wpvrTip', showHotspotTip);
3706 }
3707 }, 800);
3708 }
3709 });