PluginProbe
WPVR – 360 Panorama viewer and Virtual Tour Builder for WordPress / 9.2.0
WPVR – 360 Panorama viewer and Virtual Tour Builder for WordPress v9.2.0
9.2.0 9.1.4 9.1.3 9.1.2 9.1.1 9.1.0 9.0.3 9.0.2 9.0.1 9.0.0 8.5.79 8.5.78 8.5.77 8.5.76 8.5.75 8.5.74 8.5.73 8.5.72 8.5.71 8.5.70 8.5.69 8.5.68 8.5.35 8.5.36 8.5.37 All 224 releases
wpvr / legacy / admin / classes / class-wpvr-scene.php

class-wpvr-scene.php in WPVR – 360 Panorama viewer and Virtual Tour Builder for WordPress 9.2.0, at legacy/admin/classes/class-wpvr-scene.php

4,007 lines 213.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 if (!defined('ABSPATH')) exit; // Exit if accessed directly
3 /**
4 * Responsible for managing Scene tab on Setup meta box
5 *
6 * @link http://rextheme.com/
7 * @since 8.0.0
8 *
9 * @package Wpvr
10 * @subpackage Wpvr/admin/classes
11 */
12
13 class WPVR_Scene {
14
15 /**
16 * Instance of WPVR_Hotspot class
17 *
18 * @var object
19 * @since 8.0.0
20 */
21 protected $hotspot;
22
23 /**
24 * Instance of WPVR_Format class
25 *
26 * @var object
27 * @since 8.0.0
28 */
29 protected $format;
30
31 /**
32 * Instance of WPVR_Validator class
33 *
34 * @var object
35 * @since 8.0.0
36 */
37 private $validator;
38
39 /**
40 * Number of scene or hotspot item
41 *
42 * @var integer
43 * @since 8.0.0
44 */
45 protected $data_limit;
46
47 /**
48 * Pro version license status
49 *
50 * @var string
51 * @since 8.0.0
52 */
53 protected $status;
54
55
56 function __construct()
57 {
58 $this->hotspot = new WPVR_Hotspot();
59 $this->format = new WPVR_Format();
60 $this->validator = new WPVR_Validator();
61
62 $this->status = apply_filters( 'check_pro_license_status', $this->status );
63
64 if ($this->status !== false && $this->status == 'valid') {
65 $this->data_limit = 999999999;
66 } else {
67 $this->data_limit = 5;
68 }
69 }
70
71 /**
72 * Render Scene Settings Content
73 *
74 * @param array $postdata
75 *
76 * @return void
77 * @since 8.0.0
78 */
79 public function render_scene($postdata)
80 {
81 ob_start();
82 ?>
83
84 <!-- Scene and Hotspot repeater -->
85 <div class="scene-setup rex-pano-sub-tabs" data-limit="<?php echo esc_attr( $this->data_limit + 1 ); ?>">
86 <?php $this->render_scene_repeater_list($postdata); ?>
87 </div>
88
89 <?php
90 // ob_end_flush();
91 }
92
93
94 /**
95 * Render scene setup data repeater list
96 *
97 * @param array $postdata
98 *
99 * @return void
100 * @since 8.0.0
101 */
102 private function render_scene_repeater_list($postdata)
103 {
104 ob_start();
105 ?>
106 <nav class="rex-pano-tab-nav rex-pano-nav-menu scene-nav">
107 <?php $this->render_nav_menu($postdata); // Will render scene navigation bar ?>
108 </nav>
109
110 <div data-repeater-list="scene-list" class="rex-pano-tab-content">
111
112 <!-- Default empty repeater -->
113 <div data-repeater-item class="single-scene rex-pano-tab" data-title="0" id="scene-0">
114 <?php $this->render_default_repeater_item(); ?>
115 </div>
116 <!-- Empty repeater end -->
117
118 <?php
119 if ( ! empty( $postdata['panodata']["scene-list"] ) && is_array( $postdata['panodata']["scene-list"] ) ) {
120 $s = 1; $firstvalue = reset($postdata['panodata']["scene-list"]);
121 $default_scene = $postdata['defaultscene'] ?? ($firstvalue['scene-id'] ?? '');
122 foreach ($postdata['panodata']["scene-list"] as $pano_scene) {
123 if ( ! is_array( $pano_scene ) ) {
124 continue;
125 }
126 if ( ! isset( $pano_scene['dscene'] ) ) {
127 $pano_scene['dscene'] = ( ! empty( $default_scene ) && ( $pano_scene['scene-id'] ?? '' ) === $default_scene ) ? 'on' : 'off';
128 }
129 $is_active = ( ( $pano_scene['scene-id'] ?? '' ) === ( $firstvalue['scene-id'] ?? '' ) );
130 ?>
131
132 <div data-repeater-item class="single-scene rex-pano-tab <?php if($is_active) { echo esc_attr('active'); }; ?>" data-title="1" id="scene-<?php echo esc_attr( $s ); ?>">
133 <?php $this->render_repeater_item_with_panodata($pano_scene, $s); ?>
134 </div>
135
136 <?php $s++; }
137 } ?>
138 </div>
139 <?php
140 // ob_end_flush();
141 }
142
143
144 /**
145 * Render scene nav menu
146 *
147 * @param array $postdata
148 *
149 * @return void
150 * @since 8.0.0
151 */
152 private function render_nav_menu($postdata)
153 {
154 ob_start();
155 ?>
156 <ul>
157 <?php
158 if ( ! empty( $postdata['panodata']["scene-list"] ) && is_array( $postdata['panodata']["scene-list"] ) ) {
159 $i = 1; $firstvalue = reset($postdata['panodata']["scene-list"]);
160 foreach ($postdata['panodata']["scene-list"] as $pano_scene) {
161 if ( ! is_array( $pano_scene ) ) {
162 continue;
163 }
164 $is_active = ( ( $pano_scene['scene-id'] ?? '' ) === ( $firstvalue['scene-id'] ?? '' ) );
165 ?>
166
167 <li class="<?php if ($is_active) {echo 'active';};?>">
168 <span data-index="<?php echo esc_attr( $i ); ?>" data-href="#scene-<?php echo esc_attr( $i ); ?>">
169 <i class="fa fa-image"></i>
170 </span>
171 </li>
172
173 <?php $i++; }
174 } ?>
175 <li class="add" data-repeater-create><span><i class="fa fa-plus-circle"></i></span></li>
176 </ul>
177 <?php
178 ob_end_flush();
179 }
180
181
182 /**
183 * Render repeater item for default scene
184 *
185 * @param int $data_limit
186 *
187 * @return void
188 * @since 8.0.0
189 */
190 private function render_default_repeater_item()
191 {
192 ob_start();
193 ?>
194 <div class="active_scene_id"><p></p></div>
195 <div class="scene-content">
196 <?php $this->render_default_repeater_item_scene_content(); ?>
197 </div>
198
199 <!-- hotspot setup -->
200 <div class="hotspot-setup rex-pano-sub-tabs" data-limit="<?php echo esc_attr( $this->data_limit ); ?>">
201 <?php $this->hotspot->render_hotspot($s = 0, $h =1)?>
202 </div>
203 <button data-repeater-delete type="button" title="Delete Scene" class="delete-scene"><i class="far fa-trash-alt"></i></button>
204 <?php
205 ob_end_flush();
206 }
207
208
209 /**
210 * Render repeater items while scene has panaromic data
211 *
212 * @param array $pano_scene
213 * @param int $s scene number increment var
214 *
215 * @return void
216 * @since 8.0.0
217 */
218 private function render_repeater_item_with_panodata($pano_scene, $s)
219 {
220 ob_start();
221 ?>
222 <div class="active_scene_id"><p></p></div>
223 <div class="scene-content">
224 <!--
225 - Render repeater item scene content
226 - If scene has panaromic data
227 -->
228 <?php $this->render_repeater_scene_content_with_data($pano_scene); ?>
229 </div>
230 <!--
231 - Render repeater item hotspot content
232 -->
233 <?php $this->render_repeater_item_hotspot_content($pano_scene, $s); ?>
234
235 <button data-repeater-delete type="button" title="Delete Scene" class="delete-scene"><i class="far fa-trash-alt"></i></button>
236 <?php
237 ob_end_flush();
238 }
239
240
241 /**
242 * Render scene content for default repeater item
243 *
244 * @return void
245 * @since 8.0.0
246 */
247 private function render_default_repeater_item_scene_content()
248 {
249 ob_start();
250 ?>
251
252 <h6 class="title"><i class="fa fa-cog"></i> <?php esc_html_e('Scene Settings','wpvr'); ?> </h6>
253
254 <div class="scene-left">
255 <?php WPVR_Meta_Field::render_scene_left_fields_empty_panodata(); ?>
256 </div>
257
258 <div class="scene-right">
259 <?php do_action( 'wpvr_pro_scene_empty_right_fields' ) ?>
260 </div>
261
262 <?php
263 ob_end_flush();
264 }
265
266
267 /**
268 * Render repeater item scene content is scene has panaromic data
269 *
270 * @param mixed $dscene
271 * @param mixed $scene_id
272 * @param mixed $scene_photo
273 *
274 * @return void
275 * @since 8.0.0
276 */
277 private function render_repeater_scene_content_with_data($pano_scene)
278 {
279 ob_start();
280 ?>
281 <h6 class="title"><i class="fa fa-cog"></i> <?php esc_html_e('Scene Settings','wpvr'); ?> </h6>
282
283 <div class="scene-left">
284 <?php WPVR_Meta_Field::render_scene_left_fields_with_panodata($pano_scene) ;?>
285 </div>
286
287 <div class="scene-right">
288 <?php do_action( 'wpvr_pro_scene_right_fields', $pano_scene ) ?>
289 </div>
290
291
292 <?php
293 ob_end_flush();
294 }
295
296
297 /**
298 * Render repeater item hotspot content
299 *
300 * @param array $pano_hotspots
301 * @param int $data_limit
302 * @param int $s
303 *
304 * @return void
305 * @since 8.0.0
306 */
307 private function render_repeater_item_hotspot_content($pano_scene, $s)
308 {
309 if (!empty($pano_scene['hotspot-list'])) { ?>
310 <div class="hotspot-setup rex-pano-sub-tabs" data-limit="<?php echo esc_attr( $this->data_limit ); ?>">
311
312 <?php $this->hotspot->render_hotspot_with_panodata($pano_scene['hotspot-list'], $s); //Render hotspot while scene has hotspot data ?>
313
314 </div>
315 <?php } else { ?>
316 <div class="hotspot-setup rex-pano-sub-tabs" data-limit="<?php echo esc_attr( $this->data_limit ); ?>">
317
318 <?php $this->hotspot->render_hotspot($s, $h = 1); //Render hotspot while scene has no hotspot data ?>
319
320 </div>
321 <?php }
322 }
323
324
325 /**
326 * Update post meta data
327 *
328 * @param integer $postid
329 * @param integer $panoid
330 * @param boolean $is_publish_action
331 *
332 * @return void
333 * @since 8.0.0
334 */
335 public function wpvr_update_meta_box($postid, $panoid, $is_publish_action = false)
336 {
337 $nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( wp_unslash( $_POST['nonce'] ) ) : '';
338 if ( ! wp_verify_nonce( $nonce, 'wpvr' ) ) {
339 wp_die( 'Permission denied.' );
340 }
341 $panodata = $this->format->prepare_panodata(isset($_POST['panodata']) ? wp_unslash( $_POST['panodata'] ) : ''); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
342 $default_scene = $this->format->prepare_default_scene($panodata);
343 $previewtext = isset($_POST['previewtext']) ? $this->validator->preview_text_validation(wp_unslash( $_POST['previewtext'] )) : ''; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
344
345 $gzoom = $this->format->set_pro_checkbox_value(@wp_unslash( $_POST['gzoom'] ));
346 $default_global_zoom = '';
347 $max_global_zoom = '';
348 $min_global_zoom = '';
349 if ($gzoom == 'on') {
350 $default_global_zoom = isset($_POST['dzoom']) ? wp_unslash( $_POST['dzoom'] ) : '';
351 $max_global_zoom = isset($_POST['maxzoom']) ? wp_unslash( $_POST['maxzoom'] ) : '';
352 $min_global_zoom = isset($_POST['minzoom']) ? wp_unslash( $_POST['minzoom'] ) : '';
353 }
354
355 $custom_control = isset($_POST['customcontrol']) ? wp_unslash( $_POST['customcontrol'] ) : null;
356
357 $vrgallery = $this->format->set_checkbox_value(@wp_unslash( $_POST['vrgallery'] ));
358 $vrgallery_title = $this->format->set_checkbox_value(@wp_unslash( $_POST['vrgallery_title'] ));
359 $vrgallery_display = $this->format->set_checkbox_value(@wp_unslash( $_POST['vrgallery_display'] ));
360 $vrgallery_icon_size = $this->format->set_checkbox_value(@wp_unslash( $_POST['vrgallery_icon_size'] ));
361
362 $existing_panodata = get_post_meta( $postid, 'panodata', true );
363 $existing_panodata = is_array( $existing_panodata ) ? $existing_panodata : array();
364 $mouseZoom = isset( $_POST['mouseZoom'] )
365 ? $this->format->set_pro_checkbox_value( wp_unslash( $_POST['mouseZoom'] ) )
366 : ( $existing_panodata['mouseZoom'] ?? 'on' );
367 $draggable = isset( $_POST['draggable'] )
368 ? $this->format->set_pro_checkbox_value( wp_unslash( $_POST['draggable'] ) )
369 : ( $existing_panodata['draggable'] ?? 'on' );
370 $diskeyboard = $this->format->set_pro_checkbox_value(@wp_unslash( $_POST['diskeyboard'] ));
371 $keyboardzoom = $this->format->set_checkbox_value(@wp_unslash( $_POST['keyboardzoom'] ));
372 $compass = $this->format->set_checkbox_on_value(@wp_unslash( $_POST['compass'] ));
373 //===Gyroscopre control===//
374 $gyro = $this->format->set_pro_checkbox_value(@wp_unslash( $_POST['gyro'] ));
375 if ($gyro == 'on') {
376 if (!is_ssl()) {
377 wp_send_json_error('<p><span>Warning:</span> Please add SSL to enable Gyroscope for WP VR. </p>');
378 die();
379 }
380 $gyro = true;
381 $deviceorientationcontrol = $this->format->set_checkbox_value(@wp_unslash( $_POST['deviceorientationcontrol'] ));
382 } else {
383 $gyro = false;
384 $deviceorientationcontrol = false;
385 }
386 //===Gyroscopre control===//
387
388 $autoload = $this->format->set_checkbox_value(isset($_POST['autoload']) ? wp_unslash( $_POST['autoload'] ) : '');
389 $control = $this->format->set_checkbox_value(isset($_POST['control']) ? wp_unslash( $_POST['control'] ) : '');
390
391 $scene_fade_duration = isset($_POST['scenefadeduration']) ? sanitize_text_field(wp_unslash( $_POST['scenefadeduration'] )) : '';
392 $preview = isset($_POST['preview']) ? esc_url(wp_unslash( $_POST['preview'] )) : '';
393 $rotation = isset($_POST['rotation']) ? sanitize_text_field(wp_unslash( $_POST['rotation'] )) : '';
394 $autorotation = isset($_POST['autorotation']) ? sanitize_text_field(wp_unslash( $_POST['autorotation'] )) : '';
395
396 $autorotationinactivedelay = isset($_POST['autorotationinactivedelay']) ? sanitize_text_field(wp_unslash( $_POST['autorotationinactivedelay'] )) : '';
397 $autorotationstopdelay = isset($_POST['autorotationstopdelay']) ? sanitize_text_field(wp_unslash( $_POST['autorotationstopdelay'] )) : '';
398
399 //===generic form===//
400 $genericform = sanitize_text_field(isset($_POST['genericform']) ? wp_unslash( $_POST['genericform'] ) : 'off');
401 $genericformshortcode = isset($_POST['genericformshortcode']) ? sanitize_text_field(wp_unslash( $_POST['genericformshortcode'] )) : '' ;
402 $genericformicon = isset($_POST['genericformicon'])
403 ? sanitize_text_field(wp_unslash($_POST['genericformicon']))
404 : ($existing_panodata['genericformicon'] ?? 'fab fa-wpforms');
405 $genericformiconcolor = isset($_POST['genericformiconcolor'])
406 ? sanitize_hex_color(wp_unslash($_POST['genericformiconcolor']))
407 : ($existing_panodata['genericformiconcolor'] ?? '#f7fffb');
408 $genericformiconcolor = $genericformiconcolor ?: '#f7fffb';
409 //===generic form===//
410
411
412 if(isset($_POST['rotation']) && sanitize_text_field(wp_unslash( $_POST['rotation'] )) === 'on' ) {
413 $this->validator->basic_setting_validation($autorotationinactivedelay, $autorotationstopdelay); // Basic setting error control and validation //
414 }
415
416 //===Company Logo===//
417 $cpLogoSwitch = isset($_POST['cpLogoSwitch']) ? wp_unslash( $_POST['cpLogoSwitch'] ) : 'off';
418 $cpLogoImg = isset($_POST['cpLogoImg']) ? wp_unslash( $_POST['cpLogoImg'] ) : '';
419 $cpLogoContent = isset($_POST['cpLogoContent']) ? sanitize_text_field(wp_unslash( $_POST['cpLogoContent'] )) : '';
420 //===Company Logo===//
421
422 //===Explainer video===//
423 $explainerSwitch = isset($_POST['explainerSwitch']) ? wp_unslash( $_POST['explainerSwitch'] ) : 'off';
424 $explainerContent = '';
425 $explainerContent = isset($_POST['explainerContent']) ? wp_unslash( $_POST['explainerContent'] ) : '';
426 //===Explainer video===//
427
428
429 $scene_fade_duration = '';
430 $scene_fade_duration = isset($_POST['scenefadeduration']) ? sanitize_text_field(wp_unslash( $_POST['scenefadeduration'] )) : '';
431
432 // Only validate when publishing, not when saving drafts
433 if ($is_publish_action) {
434 $this->validator->scene_validation($panodata); // Scene content error control and validation //
435
436 $this->validator->empty_scene_validation($panodata); // Empty scene content error control and validation //
437
438 $this->validator->duplicate_hotspot_validation($panodata); // Duplicate error control and validation //
439 }
440
441 $panodata = $this->format->remove_empty_scene_and_hotspot($panodata); // Remove Empty scene and hotspot //
442
443 //===audio===//
444 $bg_music = isset($_POST['bg_music']) ? sanitize_text_field(wp_unslash( $_POST['bg_music'] )) : 'off';
445 $bg_music_url = isset($_POST['bg_music_url']) ? esc_url_raw(wp_unslash( $_POST['bg_music_url'] )) : '';
446 $autoplay_bg_music = isset($_POST['autoplay_bg_music']) ? sanitize_text_field(wp_unslash( $_POST['autoplay_bg_music'] )) : 'off';
447 $loop_bg_music = isset($_POST['loop_bg_music']) ? sanitize_text_field(wp_unslash( $_POST['loop_bg_music'] )) : 'off';
448 if ($bg_music == 'on') {
449 if (empty($bg_music_url)) {
450 wp_send_json_error('<p><span>Warning:</span> Please add an audio file as you enabled audio for this tour </p>');
451 die();
452 }
453 }
454 //===audio===//
455 $advanced_control = array(
456 'keyboardzoom' => $keyboardzoom,
457 'diskeyboard' => $diskeyboard,
458 'draggable' => $draggable,
459 'mouseZoom' => $mouseZoom,
460 'gyro' => $gyro,
461 'deviceorientationcontrol' => $deviceorientationcontrol,
462 'compass' => $compass,
463 'vrgallery' => $vrgallery,
464 'vrgallery_title' => $vrgallery_title,
465 'vrgallery_display' => $vrgallery_display,
466 'vrgallery_icon_size' => $vrgallery_icon_size,
467 'bg_music' => $bg_music,
468 'bg_music_url' => $bg_music_url,
469 'autoplay_bg_music' => $autoplay_bg_music,
470 'loop_bg_music' => $loop_bg_music,
471 'cpLogoSwitch' => $cpLogoSwitch,
472 'cpLogoImg' => $cpLogoImg,
473 'cpLogoContent' => $cpLogoContent,
474 'hfov' => $default_global_zoom,
475 'maxHfov' => $max_global_zoom,
476 'minHfov' => $min_global_zoom,
477 'explainerSwitch' => $explainerSwitch,
478 'explainerContent' => $explainerContent,
479 );
480
481 $pano_array = array();
482 $pano_array = array(
483 "panoid" => $panoid,
484 "autoLoad" => $autoload,
485 "showControls" => $control,
486 "customcontrol" => $custom_control,
487 "autoRotate" => $autorotation,
488 "autoRotateInactivityDelay" => $autorotationinactivedelay,
489 "autoRotateStopDelay" => $autorotationstopdelay,
490 "genericform" => $genericform,
491 "genericformshortcode" => $genericformshortcode,
492 "genericformicon" => $genericformicon,
493 "genericformiconcolor" => $genericformiconcolor,
494 "preview" => $preview,
495 "defaultscene" => $default_scene,
496 "scenefadeduration" => $scene_fade_duration,
497 "panodata" => $panodata,
498 "previewtext" => $previewtext);
499 $pano_array = apply_filters( 'prepare_scene_pano_array_with_pro_version', $pano_array, $_POST, $advanced_control );
500 $pano_array = $this->format->prepare_rotation_wrapper_data($pano_array, $rotation);
501 // Prepare tour rotation wrapper data /
502 update_post_meta($postid, 'panodata', $pano_array);
503 do_action( 'wpvr_hotspot_saved', $postid, $pano_array );
504 $response = array(
505 'success' => true,
506 'data' => array(
507 'post_ID' => $postid,
508 'post_status' => get_post_status($postid)
509 )
510 );
511
512 do_action( 'wpvr_tour_settings_saved', $postid );
513
514
515 /**
516 * Delete orphaned analytics data
517 *
518 * @param integer $postid POST ID
519 *
520 * @return void
521 * @since 8.5.16
522 */
523 do_action('wpvr_pro_delete_orphaned_analytics_data', $postid);
524
525 wp_send_json($response);
526 die();
527
528 }
529
530
531 /**
532 * Allow iframe but disallow script tags in user input
533 * @since 8.5.16
534 */
535 public function wpvr_sanitize_iframe_only( $input ) {
536 if ( function_exists( 'wpvr_sanitize_iframe_only' ) ) {
537 return wpvr_sanitize_iframe_only( $input );
538 }
539
540 // Start with standard allowed post HTML (p, a, strong, etc.)
541 $allowed_tags = wp_kses_allowed_html( 'post' );
542
543 // Explicitly allow <iframe> with specific safe attributes
544 $allowed_tags['iframe'] = array(
545 'src' => true,
546 'width' => true,
547 'height' => true,
548 'title' => true,
549 'frameborder' => true,
550 'allow' => true,
551 'allowfullscreen' => true,
552 'referrerpolicy' => true,
553 );
554
555 // Sanitize input
556 return wp_kses( $input, $allowed_tags );
557 }
558
559
560
561 /**
562 * Responsible for showing Scene Preview
563 *
564 * @param string $panoid
565 * @param string $panovideo
566 *
567 * @return wp_send_json_success
568 * @since 8.0.0
569 */
570 public function wpvr_scene_preview($panoid, $panovideo)
571 {
572 $nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( wp_unslash( $_POST['nonce'] ) ) : '';
573 if ( ! wp_verify_nonce( $nonce, 'wpvr' ) ) {
574 wp_die( 'Permission denied.' );
575 }
576 $panodata = $this->format->prepare_panodata( isset( $_POST['panodata'] ) ? wp_unslash( $_POST['panodata'] ) : '' ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
577
578 $control = $this->format->set_checkbox_value(wp_unslash( $_POST['control'] ));
579 $autoload = $this->format->set_checkbox_value(wp_unslash( $_POST['autoload'] ));
580
581 $compass = $this->format->set_checkbox_on_value(@wp_unslash( $_POST['compass'] ));
582 $mouseZoom = $this->format->set_checkbox_value(@wp_unslash( $_POST['mouseZoom'] ));
583 $draggable = $this->format->set_checkbox_value(wp_unslash( $_POST['draggable'] ) ?? null);
584 $gzoom = $this->format->set_pro_checkbox_value(@wp_unslash( $_POST['gzoom'] ));
585 $diskeyboard = $this->format->set_checkbox_value(@wp_unslash( $_POST['diskeyboard'] ));
586 $keyboardzoom = $this->format->set_checkbox_value(@wp_unslash( $_POST['keyboardzoom'] ));
587
588 $gyro = $this->format->set_checkbox_on_value(@wp_unslash( $_POST['gyro'] ));
589 $deviceorientationcontrol = $this->format->set_checkbox_value(@wp_unslash( $_POST['deviceorientationcontrol'] ));
590
591 $floor_plan_enabler = $this->format->set_pro_checkbox_value(@wp_unslash( $_POST['wpvr_floor_plan_enabler'] ));
592 $floor_plan_image = isset($_POST['wpvr_floor_plan_image']) ? wp_unslash( $_POST['wpvr_floor_plan_image'] ) : '';
593
594 $scene_fade_duration = sanitize_text_field(wp_unslash( $_POST['scenefadeduration'] ));
595 $preview = esc_url(wp_unslash( $_POST['preview'] ));
596
597 $default_scene = '';
598
599 $rotation = sanitize_text_field(wp_unslash( $_POST['rotation'] ));
600 $autorotation = sanitize_text_field(wp_unslash( $_POST['autorotation'] ));
601 $autorotationinactivedelay = sanitize_text_field(wp_unslash( $_POST['autorotationinactivedelay'] ));
602 $autorotationstopdelay = sanitize_text_field(wp_unslash( $_POST['autorotationstopdelay'] ));
603
604 $default_global_zoom = '';
605 $max_global_zoom = '';
606 $min_global_zoom = '';
607 if ($gzoom == 'on') {
608 $default_global_zoom = wp_unslash( $_POST['dzoom'] );
609 $max_global_zoom = wp_unslash( $_POST['maxzoom'] );
610 $min_global_zoom = wp_unslash( $_POST['minzoom'] );
611 }
612
613 $default_scene = $this->format->prepare_default_scene($panodata);
614
615 if(isset($_POST['rotation']) && sanitize_text_field(wp_unslash( $_POST['rotation'] )) === 'on' ) {
616 $this->validator->basic_setting_validation($autorotationinactivedelay, $autorotationstopdelay); // Basic setting error control and validation //
617 }
618 $this->validator->scene_validation($panodata); // Scene content error control and validation //
619
620 $this->validator->empty_scene_validation($panodata); // Empty scene content error control and validation //
621
622 $this->validator->duplicate_hotspot_validation($panodata);
623 if($floor_plan_enabler == 'on'){
624 $this->validator->empty_floor_plan_image_validation($floor_plan_image);
625 }
626
627 $default_data = array();
628 if ($gzoom == 'on') {
629 $default_data = array("firstScene" => $default_scene, "sceneFadeDuration" => $scene_fade_duration, "hfov" => $default_global_zoom, "maxHfov" => $max_global_zoom, "minHfov" => $min_global_zoom);
630 } else {
631 $default_data = array("firstScene" => $default_scene, "sceneFadeDuration" => $scene_fade_duration);
632 }
633
634 $scene_data = $this->format->prepare_scene_data_for_preview($panodata);
635
636
637 $pano_id_array = array();
638 $pano_id_array = array("panoid" => $panoid);
639 $pano_response = array();
640 $pano_response = array("autoLoad" => $autoload, "defaultZoom" => $default_global_zoom, "minZoom" => $min_global_zoom, "maxZoom" => $max_global_zoom, "showControls" => $control, "compass" => $compass, "orientationOnByDefault" => $deviceorientationcontrol, "mouseZoom" => $mouseZoom, "draggable" => $draggable, "disableKeyboardCtrl" => $diskeyboard, 'keyboardZoom' => $keyboardzoom, "preview" => $preview, "autoRotate" => $autorotation, "autoRotateInactivityDelay" => $autorotationinactivedelay, "autoRotateStopDelay" => $autorotationstopdelay, "default" => $default_data, "scenes" => $scene_data);
641
642 $pano_response = $this->format->prepare_rotation_wrapper_data($pano_response, $rotation);
643
644 $is_pro = apply_filters('is_wpvr_pro_active',false);
645 $status = get_option('wpvr_edd_license_status');
646 $pano_floor_plan = array();
647 $call_to_action = array();
648 if ($status !== false && 'valid' == $status && $is_pro) {
649 $pano_floor_plan = array(
650 "floor_plan_tour_enabler" => $floor_plan_enabler,
651 "floor_plan_attachment_url" => $floor_plan_image
652 );
653 if ( 'on' === $floor_plan_enabler ) {
654 do_action( 'wpvr_floor_plan_configured', $postid, $pano_floor_plan );
655 }
656 $call_to_action = array(
657 'button_enable' =>sanitize_text_field(wp_unslash( $_POST['callToAction'] )),
658 'button_text' =>sanitize_text_field(wp_unslash( $_POST['buttontext'] )),
659 'button_url' =>sanitize_text_field(wp_unslash( $_POST['buttonurl'] ))
660 );
661 }
662
663 $response = array();
664 $response = array($pano_id_array, $pano_response, $panovideo,$pano_floor_plan,$call_to_action);
665 wp_send_json_success($response);
666 }
667
668
669 /**
670 * Render shortcode for scene and hotspot post data
671 *
672 * @param array $postdata
673 * @param string $panoid
674 * @param integer $id
675 * @param mixed $radius
676 * @param mixed $width
677 * @param mixed $height
678 *
679 * @return string
680 * @since 8.0.0
681 */
682 public function render_scene_shortcode($postdata, $panoid, $id, $radius, $width, $height, $mobile_height)
683 {
684 if ( function_exists( 'wpvr_enqueue_frontend_scripts' ) ) {
685 wpvr_enqueue_frontend_scripts( 'scene' );
686 }
687 $postdata = is_array( $postdata ) ? wpvr_get_effective_panodata( $postdata ) : [];
688 $show_scene_info = ( $postdata['scene-info-enabled'] ?? 'on' ) !== 'off';
689 $tour_layout = is_array( $postdata['tourLayout'] ?? null )
690 ? ( $postdata['tourLayout']['layout'] ?? 'default' )
691 : ( $postdata['tourLayout'] ?? 'default' );
692 $is_classic_layout = 'layout1' !== $tour_layout;
693
694 if (
695 ( isset( $_GET['bricks'] ) && wp_unslash( $_GET['bricks'] ) === 'run' ) ||
696 ( defined('DOING_AJAX') && DOING_AJAX && isset( $_REQUEST['action'] ) && wp_unslash( $_REQUEST['action'] ) === 'bricks_render_element' ) ||
697 ( defined('REST_REQUEST') && REST_REQUEST && isset($_SERVER['REQUEST_URI']) && strpos( sanitize_text_field( wp_unslash( $_SERVER['REQUEST_URI'] ) ), '/wp-json/bricks/v1/render_element') !== false )
698 ) {
699 return esc_html__('Bricks Editor Mode - WPVR Preview is not available.', 'wpvr');
700 }
701
702 do_action('rex_wpvr_embadded_tour', $id);
703
704 $control = false;
705 if (isset($postdata['showControls'])) {
706 $control = $postdata['showControls'];
707 }
708
709 if ($control) {
710 if (isset($postdata['customcontrol']) && is_array($postdata['customcontrol'])) {
711 $custom_control = $postdata['customcontrol'];
712 $gyro_enabled = isset($postdata['gyro']) && in_array($postdata['gyro'], array(true, 1, '1', 'on'), true);
713 $custom_control['gyroSwitch'] = $gyro_enabled ? 'on' : 'off';
714 $gyro_button_enabled = wpvr_isMobileDevice() && $custom_control['gyroSwitch'] == "on" && $custom_control['gyroscopeSwitch'] == "on";
715 if ($custom_control['panupSwitch'] == "on" || $custom_control['panDownSwitch'] == "on" || $custom_control['panLeftSwitch'] == "on" || $custom_control['panRightSwitch'] == "on" || $custom_control['panZoomInSwitch'] == "on" || $custom_control['panZoomOutSwitch'] == "on" || $custom_control['panFullscreenSwitch'] == "on" || $gyro_button_enabled || $custom_control['backToHomeSwitch'] == "on") {
716 $control = false;
717 }
718 }
719 }
720
721 $vrgallery = false;
722 if (isset($postdata['vrgallery'])) {
723 $vrgallery = $postdata['vrgallery'];
724 }
725
726 $vrgallery_title = false;
727 if (isset($postdata['vrgallery_title'])) {
728 $vrgallery_title = $postdata['vrgallery_title'];
729 }
730
731 $vrgallery_display = false;
732 if (isset($postdata['vrgallery_display'])) {
733 $vrgallery_display = $postdata['vrgallery_display'];
734 }
735 $vrgallery_icon_size = false;
736 if (isset($postdata['vrgallery_icon_size'])) {
737 $vrgallery_icon_size = $postdata['vrgallery_icon_size'];
738 }
739 $gyro = false;
740 $gyro_orientation = false;
741 if (isset($postdata['gyro'])) {
742 $gyro = in_array($postdata['gyro'], array(true, 1, '1', 'on'), true);
743 if ($gyro && isset($postdata['deviceorientationcontrol'])) {
744 $gyro_orientation = in_array($postdata['deviceorientationcontrol'], array(true, 1, '1', 'on'), true);
745 }
746 }
747 //== Floor plan handle ==//
748 $floor_plan_enable = 'off';
749 $floor_plan_image = '';
750 if (isset($postdata['floor_plan_tour_enabler']) && $postdata['floor_plan_tour_enabler'] == 'on'){
751 $floor_plan_enable = $postdata['floor_plan_tour_enabler'];
752 if(isset($postdata['floor_plan_attachment_url']) && !empty($postdata['floor_plan_attachment_url'])){
753 $floor_plan_image = $postdata['floor_plan_attachment_url'];
754 }
755 }
756
757 $compass = false;
758 $audio_right = "5px";
759 if (isset($postdata['compass'])) {
760 $compass = $postdata['compass'] == 'on' || $postdata['compass'] != null ? true : false;
761 if ($compass) {
762 $audio_right = "60px";
763 }
764 }
765 $floor_map_right = "25px";
766 if((isset($postdata['compass']) && $postdata['compass'] == 'on') && (isset($postdata['bg_music']) && $postdata['bg_music'] == 'on')){
767 $floor_map_right = "85px";
768 }elseif(isset($postdata['compass']) && $postdata['compass'] == 'on'){
769 $floor_map_right = "55px";
770 }elseif (isset($postdata['bg_music']) && $postdata['bg_music'] == "on") {
771 $floor_map_right = "25px";
772 }
773
774
775 //===explainer handle===//
776
777 $explainer_right = "10px";
778 if ((isset($postdata['compass']) && $postdata['compass'] == 'on') && (isset($postdata['bg_music']) && $postdata['bg_music'] == 'on') && ( $floor_plan_enable == 'on' && !empty($floor_plan_image) ) ) {
779 $explainer_right = "130px";
780 } elseif (isset($postdata['compass']) && $postdata['compass'] == 'on' && ($floor_plan_enable == 'on' && !empty($floor_plan_image) )) {
781 $explainer_right = "100px";
782 } elseif (isset($postdata['bg_music']) && $postdata['bg_music'] == "on" && ($floor_plan_enable == 'on' && !empty($floor_plan_image) )) {
783 $explainer_right = "55px";
784 } elseif((isset($postdata['compass']) && $postdata['compass'] == 'on') && (isset($postdata['bg_music']) && $postdata['bg_music'] == 'on') ) {
785 $explainer_right = "80px";
786 }elseif (isset($postdata['compass']) && $postdata['compass'] == 'on') {
787 $explainer_right = "55px";
788 } elseif (isset($postdata['bg_music']) && $postdata['bg_music'] == "on") {
789 $explainer_right = "30px";
790 } elseif ($floor_plan_enable == 'on' && !empty($floor_plan_image) ) {
791 $explainer_right = "70px";
792 }
793
794
795 $enable_cardboard = '';
796 $is_cardboard = get_option('wpvr_cardboard_disable');
797 if(wpvr_isMobileDevice() && $is_cardboard == 'true' ){
798 $enable_cardboard = 'enable-cardboard';
799 $audio_right = "73px";
800 if (isset($postdata['compass'])) {
801 $compass = $postdata['compass'] == 'on' || $postdata['compass'] != null ? true : false;
802 if ($compass) {
803 $audio_right = "130px";
804 }
805 }
806 //===Floor plan handle===//
807 $floor_map_right = "60px";
808 if((isset($postdata['compass']) && $postdata['compass'] == 'on') && (isset($postdata['bg_music']) && $postdata['bg_music'] == 'on')){
809 $floor_map_right = "150px";
810 }elseif(isset($postdata['compass']) && $postdata['compass'] == 'on'){
811 $floor_map_right = "120px";
812 }elseif (isset($postdata['bg_music']) && $postdata['bg_music'] == "on") {
813 $floor_map_right = "90px";
814 }
815
816 //===explainer handle===//
817 $explainer_right = "65px";
818
819 if ((isset($postdata['compass']) && $postdata['compass'] == true) && (isset($postdata['bg_music']) && $postdata['bg_music'] == 'on')) {
820 $explainer_right = "150px";
821 } elseif((isset($postdata['compass']) && $postdata['compass'] == true) && (isset($postdata['bg_music']) && $postdata['bg_music'] == 'on') && ($floor_plan_enable == 'on' && !empty($floor_plan_image) )) {
822 $explainer_right = "180px";
823 } elseif (isset($postdata['compass']) && $postdata['compass'] == true && ($floor_plan_enable == 'on' && !empty($floor_plan_image) )) {
824 $explainer_right = "150px";
825 } elseif (isset($postdata['bg_music']) && $postdata['bg_music'] == "on" && ($floor_plan_enable == 'on' && !empty($floor_plan_image) )) {
826 $explainer_right = "120px";
827 }elseif (isset($postdata['compass']) && $postdata['compass'] == true) {
828 $explainer_right = "130px";
829 } elseif (isset($postdata['bg_music']) && $postdata['bg_music'] == "on") {
830 $explainer_right = "90px";
831 }elseif ($floor_plan_enable == 'on' && !empty($floor_plan_image) ) {
832 $explainer_right = "90px";
833 }
834 }
835
836 //===explainer handle===//
837
838 $mouseZoom = true;
839 if (isset($postdata['mouseZoom'])) {
840 if($postdata['mouseZoom'] == "off") {
841 $mouseZoom = false;
842 }
843 else {
844 $mouseZoom = true;
845 }
846 }
847
848 $draggable = true;
849 if (isset($postdata['draggable'])) {
850 $draggable = ! in_array( $postdata['draggable'], array( 'off', 'false', false ), true );
851 }
852
853 $diskeyboard = false;
854 if (isset($postdata['diskeyboard'])) {
855 $diskeyboard = ! in_array( $postdata['diskeyboard'], array( 'off', 'false', false ), true );
856 }
857
858 $keyboardzoom = true;
859 if (isset($postdata['keyboardzoom'])) {
860 $keyboardzoom = ! in_array( $postdata['keyboardzoom'], array( 'off', 'false', false ), true );
861 }
862
863 $autoload = false;
864
865 if (isset($postdata['autoLoad'])) {
866 $autoload = in_array( $postdata['autoLoad'], array( true, 1, '1', 'on', 'true' ), true );
867 }
868
869 $default_scene = '';
870 if (isset($postdata['defaultscene'])) {
871 $default_scene = $postdata['defaultscene'];
872 }
873
874 $default_global_zoom = '';
875 if (isset($postdata['hfov'])) {
876 $default_global_zoom = $postdata['hfov'];
877 }
878
879 $max_global_zoom = '';
880 if (isset($postdata['maxHfov'])) {
881 $max_global_zoom = $postdata['maxHfov'];
882 }
883
884 $min_global_zoom = '';
885 if (isset($postdata['minHfov'])) {
886 $min_global_zoom = $postdata['minHfov'];
887 }
888
889 $preview = '';
890 if (isset($postdata['preview'])) {
891 $preview = $postdata['preview'];
892 }
893
894 $autorotation = '';
895 if (isset($postdata["autoRotate"])) {
896 $autorotation = $postdata["autoRotate"];
897 }
898 $autorotationinactivedelay = '';
899 if (isset($postdata["autoRotateInactivityDelay"])) {
900 $autorotationinactivedelay = $postdata["autoRotateInactivityDelay"];
901 }
902 $autorotationstopdelay = '';
903 if (isset($postdata["autoRotateStopDelay"])) {
904 $autorotationstopdelay = $postdata["autoRotateStopDelay"];
905 }
906
907 $scene_fade_duration = '';
908 if (isset($postdata['scenefadeduration'])) {
909 $scene_fade_duration = $postdata['scenefadeduration'];
910 }
911
912 $panodata = array();
913 if (isset($postdata['panodata']) && is_array($postdata['panodata'])) {
914 $panodata = $postdata['panodata'];
915 }
916
917 $hotspoticoncolor = '#00b4ff';
918 $hotspotblink = 'on';
919 $default_data = array();
920 if ($default_global_zoom != '' && $max_global_zoom != '' && $min_global_zoom != '') {
921 $default_data = array("firstScene" => $default_scene, "sceneFadeDuration" => $scene_fade_duration, "hfov" => $default_global_zoom, "maxHfov" => $max_global_zoom, "minHfov" => $min_global_zoom);
922 } else {
923 $default_data = array("firstScene" => $default_scene, "sceneFadeDuration" => $scene_fade_duration);
924 }
925
926 $scene_data = array();
927 $mobile_media_resize = get_option('mobile_media_resize');
928
929 if (!empty($panodata["scene-list"])) {
930 foreach ($panodata["scene-list"] as $panoscenes) {
931 $scene_ititle = '';
932 if (isset($panoscenes["scene-ititle"])) {
933 $scene_ititle = sanitize_text_field($panoscenes["scene-ititle"]);
934 }
935
936 $scene_author = '';
937 if (isset($panoscenes["scene-author"])) {
938 $scene_author = sanitize_text_field($panoscenes["scene-author"]);
939 }
940
941 $scene_author_url = '';
942 if (isset($panoscenes["scene-author-url"])) {
943 $scene_author_url = esc_url($panoscenes["scene-author-url"]);
944 }
945
946 $scene_vaov = 180;
947 if (isset($panoscenes["scene-vaov"])) {
948 $scene_vaov = (float)$panoscenes["scene-vaov"];
949 }
950
951 $scene_haov = 360;
952 if (isset($panoscenes["scene-haov"])) {
953 $scene_haov = (float)$panoscenes["scene-haov"];
954 }
955
956
957 $scene_vertical_offset = 0;
958 if (isset($panoscenes["scene-vertical-offset"])) {
959 $scene_vertical_offset = (float)$panoscenes["scene-vertical-offset"];
960 }
961
962 $default_scene_pitch = null;
963 if (isset($panoscenes["scene-pitch"])) {
964 $default_scene_pitch = (float)$panoscenes["scene-pitch"];
965 }
966
967 $default_scene_yaw = null;
968 if (isset($panoscenes["scene-yaw"])) {
969 $default_scene_yaw = (float)$panoscenes["scene-yaw"];
970 }
971
972 $scene_max_pitch = '';
973 if (isset($panoscenes["scene-maxpitch"])) {
974 $scene_max_pitch = (float)$panoscenes["scene-maxpitch"];
975 }
976
977
978 $scene_min_pitch = '';
979 if (isset($panoscenes["scene-minpitch"])) {
980 $scene_min_pitch = (float)$panoscenes["scene-minpitch"];
981 }
982
983
984 $scene_max_yaw = '';
985 if (isset($panoscenes["scene-maxyaw"])) {
986 $scene_max_yaw = (float)$panoscenes["scene-maxyaw"];
987 }
988
989
990 $scene_min_yaw = '';
991 if (isset($panoscenes["scene-minyaw"])) {
992 $scene_min_yaw = (float)$panoscenes["scene-minyaw"];
993 }
994
995 $default_zoom = 100;
996 if (isset($panoscenes["scene-zoom"]) && $panoscenes["scene-zoom"] != "") {
997 $default_zoom = $panoscenes["scene-zoom"];
998 } else {
999 if ($default_global_zoom != '') {
1000 $default_zoom = (int)$default_global_zoom;
1001 }
1002 }
1003
1004
1005 $max_zoom = 120;
1006 if (isset($panoscenes["scene-maxzoom"]) && $panoscenes["scene-maxzoom"] != '') {
1007 $max_zoom = (int)$panoscenes["scene-maxzoom"];
1008 } else {
1009 if ($max_global_zoom != '') {
1010 $max_zoom = (int)$max_global_zoom;
1011 }
1012 }
1013
1014
1015
1016 $min_zoom = 50;
1017 if (isset($panoscenes["scene-minzoom"]) && $panoscenes["scene-minzoom"] != '') {
1018 $min_zoom = (int)$panoscenes["scene-minzoom"];
1019 } else {
1020 if ($min_global_zoom != '') {
1021 $min_zoom = (int)$min_global_zoom;
1022 }
1023 }
1024
1025
1026 $hotspot_datas = array();
1027 if (isset($panoscenes["hotspot-list"])) {
1028 $hotspot_datas = $panoscenes["hotspot-list"];
1029 }
1030
1031 $hotspots = array();
1032
1033
1034 foreach ($hotspot_datas as $hotspot_data) {
1035 $status = get_option('wpvr_edd_license_status');
1036 if ($status !== false && $status == 'valid') {
1037 if (!empty($hotspot_data["hotspot-customclass-pro"]) && $hotspot_data["hotspot-customclass-pro"] != 'none') {
1038 $hotspot_data['hotspot-customclass'] = $hotspot_data["hotspot-customclass-pro"] . ' custom-' . $id.'-' . $panoscenes['scene-id'] .'-'. sanitize_html_class($hotspot_data['hotspot-title']);
1039 }
1040 if (isset($hotspot_data['hotspot-blink'])) {
1041 $hotspotblink = $hotspot_data['hotspot-blink'];
1042 }
1043 }
1044 $has_hotspot_scene_pitch = isset($hotspot_data["hotspot-scene-pitch"])
1045 && $hotspot_data["hotspot-scene-pitch"] !== '';
1046 $has_hotspot_scene_yaw = isset($hotspot_data["hotspot-scene-yaw"])
1047 && $hotspot_data["hotspot-scene-yaw"] !== '';
1048
1049 $hotspot_type = $hotspot_data["hotspot-type"] !== 'scene' ? 'info' : $hotspot_data["hotspot-type"];
1050 $hotspot_content = '';
1051
1052 ob_start();
1053 do_action('wpvr_hotspot_content', $hotspot_data);
1054 $hotspot_content = ob_get_clean();
1055
1056 $is_fluent_form = isset($hotspot_data["hotspot-type"]) && 'fluent_form' === $hotspot_data["hotspot-type"];
1057
1058 if ($is_fluent_form) {
1059 if (!empty($hotspot_content)) {
1060 $hotspot_content = preg_replace('/<script\b[^>]*>[\s\S]*?<\/script>/i', '', $hotspot_content);
1061 }
1062 } else {
1063 if (!$hotspot_content) {
1064 $hotspot_content = $hotspot_data["hotspot-content"] ?? '';
1065 }
1066 }
1067
1068 $hotspot_url = $this->normalize_hotspot_external_url($hotspot_data["hotspot-url"] ?? '');
1069
1070 if (isset($hotspot_data["hotspot-url-open"])) {
1071 // New UI: "on" means new tab; legacy renderer: "on" means same tab.
1072 $wpvr_url_open = $hotspot_data["hotspot-url-open"] === 'on' ? 'off' : 'on';
1073 } elseif (isset($hotspot_data["wpvr_url_open"][0])) {
1074 $wpvr_url_open = $hotspot_data["wpvr_url_open"][0];
1075 } else {
1076 $wpvr_url_open = "off";
1077 }
1078 $on_hover_content = preg_replace_callback(
1079 '/<p>\s*(<img[^>]*>)\s*<br>\s*<\/p>/i',
1080 function ($matches) {
1081 return $matches[1];
1082 },
1083 $hotspot_data['hotspot-hover'] ?? ''
1084 );
1085
1086
1087 $on_hover_content = $this->sanitize_content_preserve_styles($on_hover_content ?? '', false);
1088 $on_click_content = preg_replace_callback('/<img[^>]*>/', "replace_callback", $hotspot_content ?? '');
1089 $on_click_content = $this->sanitize_content_preserve_styles($on_click_content ?? '', $is_fluent_form);
1090
1091 // Shape is independent of the optional custom icon in the
1092 // new editor, so it must always be included in the public
1093 // hotspot configuration.
1094 $hotspot_shape = isset( $hotspot_data['hotspot-shape'] )
1095 && in_array( $hotspot_data['hotspot-shape'], [ 'round', 'square', 'hexagon' ], true )
1096 ? $hotspot_data['hotspot-shape']
1097 : 'round';
1098 $hotspot_data_for_on_click=[];
1099 if( ('info' === $hotspot_type || 'fluent_form' === $hotspot_data["hotspot-type"]) && !empty($on_click_content)){
1100 $hotspot_data_for_on_click = [
1101 'on_click_content' => $on_click_content,
1102 'tour_id' => $id,
1103 'scene_id' => $panoscenes['scene-id'],
1104 'hotspot_id' => sanitize_html_class($hotspot_data['hotspot-title']),
1105 ];
1106 } elseif('info' === $hotspot_type && !empty($hotspot_url)){
1107 $hotspot_data_for_on_click = [
1108 'on_click_content' => '',
1109 'tour_id' => $id,
1110 'scene_id' => $panoscenes['scene-id'],
1111 'hotspot_id' => sanitize_html_class($hotspot_data['hotspot-title']),
1112 ];
1113 }
1114
1115 $hotspot_info = array(
1116 "text" => esc_html(sanitize_text_field($hotspot_data["hotspot-title"])),
1117 "pitch" => $hotspot_data["hotspot-pitch"],
1118 "yaw" => $hotspot_data["hotspot-yaw"],
1119 "type" => $hotspot_type,
1120 "cssClass" => $hotspot_data["hotspot-customclass"],
1121 "URL" => $hotspot_url,
1122 "wpvr_url_open" => $wpvr_url_open,
1123 "clickHandlerArgs" => $hotspot_data_for_on_click,
1124 'createTooltipArgs' => !empty(trim($on_hover_content)) ? trim($on_hover_content) : '',
1125 "sceneId" => $hotspot_data["hotspot-scene"],
1126 'hotspot_type' => $hotspot_data['hotspot-type'],
1127 'hotspot_target' => 'notBlank',
1128 'hotspot_shape' => $hotspot_shape,
1129 );
1130
1131 // An omitted entry angle lets Pannellum use the target
1132 // scene's own default face. Keep explicit zero values.
1133 if (!empty($hotspot_data["hotspot-scene"])) {
1134 if ($has_hotspot_scene_pitch) {
1135 $hotspot_info['targetPitch'] = (float)$hotspot_data["hotspot-scene-pitch"];
1136 }
1137 if ($has_hotspot_scene_yaw) {
1138 $hotspot_info['targetYaw'] = (float)$hotspot_data["hotspot-scene-yaw"];
1139 }
1140 }
1141 $hotspot_info['URL'] = ($hotspot_data['hotspot-type'] === 'fluent_form' || $hotspot_data['hotspot-type'] === 'wc_product') ? '' : $hotspot_info['URL'];
1142
1143 $is_sticker = ( ( $hotspot_data['hotspot-type'] ?? '' ) === 'sticker' );
1144 if ( $is_sticker ) {
1145 $custom_class_pro = ! empty( $hotspot_data['hotspot-customclass'] ) && $hotspot_data['hotspot-customclass'] !== 'none'
1146 ? ' ' . $hotspot_data['hotspot-customclass']
1147 : '';
1148 $hotspot_info['cssClass'] = 'wpvr-hs-custom wpvr-hs-sticker' . $custom_class_pro;
1149 $hotspot_info['scale'] = true;
1150 $hotspot_info['stickerTemplate'] = $hotspot_data['hotspot-sticker-template'] ?? 'social_proof';
1151 $hotspot_info['stickerReviewText'] = $hotspot_data['hotspot-sticker-review-text'] ?? 'The support is super responsive and responds without worries to our requests and needs! Big up to the entire RexTheme team!';
1152 $hotspot_info['stickerClientName'] = $hotspot_data['hotspot-sticker-client-name'] ?? 'Elena R.';
1153 $hotspot_info['stickerClientAvatar'] = $hotspot_data['hotspot-sticker-client-avatar'] ?? '';
1154 $hotspot_info['stickerRating'] = isset( $hotspot_data['hotspot-sticker-rating'] ) ? (int) $hotspot_data['hotspot-sticker-rating'] : 5;
1155 $is_separate_icon = ( $hotspot_data['hotspot-sticker-template'] ?? '' ) === 'button_with_separate_icon';
1156 $is_add_to_cart = ( $hotspot_data['hotspot-sticker-template'] ?? '' ) === 'add_to_cart';
1157 $is_social_share = ( $hotspot_data['hotspot-sticker-template'] ?? '' ) === 'social_share';
1158 $hotspot_info['stickerBgColor'] = $hotspot_data['hotspot-sticker-bg-color'] ?? '#201b2c';
1159 $hotspot_info['stickerBgOpacity'] = isset( $hotspot_data['hotspot-sticker-bg-opacity'] ) ? (float) $hotspot_data['hotspot-sticker-bg-opacity'] : ( ( $is_separate_icon || $is_add_to_cart || $is_social_share ) ? 75 : 95 );
1160 $hotspot_info['stickerBlur'] = isset( $hotspot_data['hotspot-sticker-blur'] ) ? (float) $hotspot_data['hotspot-sticker-blur'] : 12;
1161 $hotspot_info['stickerBrightness'] = isset( $hotspot_data['hotspot-sticker-brightness'] ) ? (float) $hotspot_data['hotspot-sticker-brightness'] : 100;
1162 $hotspot_info['stickerTextColor'] = $hotspot_data['hotspot-sticker-text-color'] ?? '#ffffff';
1163 $hotspot_info['stickerBorderColor'] = $hotspot_data['hotspot-sticker-border-color'] ?? ( ( $is_separate_icon || $is_add_to_cart || $is_social_share ) ? '#40355a' : '#3a3051' );
1164 $default_radius = $is_separate_icon ? 135 : ( ( $is_add_to_cart || $is_social_share ) ? 15 : 20 );
1165 $hotspot_info['stickerBorderRadius'] = $hotspot_data['hotspot-sticker-border-radius'] ?? [
1166 'topLeft' => $default_radius,
1167 'topRight' => $default_radius,
1168 'bottomRight' => $default_radius,
1169 'bottomLeft' => $default_radius,
1170 ];
1171 $hotspot_info['stickerPadding'] = $hotspot_data['hotspot-sticker-padding'] ?? [
1172 'top' => 21,
1173 'right' => 21,
1174 'bottom' => 21,
1175 'left' => 21,
1176 ];
1177 $hotspot_info['stickerStarColor'] = $hotspot_data['hotspot-sticker-star-color'] ?? '#EF991F';
1178 // Text before button (for add_to_cart)
1179 $hotspot_info['stickerPrefixText'] = $hotspot_data['hotspot-sticker-prefix-text'] ?? '$1,090 -';
1180 $hotspot_info['stickerSubText'] = $hotspot_data['hotspot-sticker-sub-text'] ?? 'Ready to ship';
1181 // Discount button, add to cart & social share sticker fields
1182 $hotspot_info['stickerBtnText'] = $hotspot_data['hotspot-sticker-btn-text'] ?? ( $is_social_share ? 'SHARE EXPERIENCE' : ( $is_add_to_cart ? 'ADD TO CART' : ( $is_separate_icon ? 'Limited “Midnight Horizon” Edition' : 'GET 20% OFF NOW' ) ) );
1183 $hotspot_info['stickerBtnColor'] = $hotspot_data['hotspot-sticker-btn-color'] ?? ( $is_social_share ? '#201a2b' : ( $is_add_to_cart ? '#3f04fe' : ( $is_separate_icon ? '#ffffff' : '#EF991F' ) ) );
1184 $hotspot_info['stickerBtnTextColor'] = $hotspot_data['hotspot-sticker-btn-text-color'] ?? ( ( $is_add_to_cart || $is_social_share ) ? '#ffffff' : '#000000' );
1185 $hotspot_info['stickerBtnIconColor'] = $hotspot_data['hotspot-sticker-btn-icon-color'] ?? '#000000';
1186 $hotspot_info['stickerBtnUrl'] = $hotspot_data['hotspot-sticker-btn-url'] ?? '';
1187 $hotspot_info['stickerBtnNewTab'] = $hotspot_data['hotspot-sticker-btn-new-tab'] ?? 'off';
1188 $hotspot_info['stickerMainBg'] = $hotspot_data['hotspot-sticker-main-bg'] ?? ( $hotspot_data['hotspot-sticker-card-bg'] ?? 'on' );
1189 $hotspot_info['stickerCardBg'] = $hotspot_info['stickerMainBg'];
1190 $hotspot_info['stickerBtnBg'] = $hotspot_data['hotspot-sticker-btn-bg'] ?? 'on';
1191 $hotspot_info['stickerBtnWidth'] = isset( $hotspot_data['hotspot-sticker-btn-width'] ) && $hotspot_data['hotspot-sticker-btn-width'] !== '' ? $hotspot_data['hotspot-sticker-btn-width'] : ( $is_social_share ? 222 : ( $is_add_to_cart ? 163 : ( $is_separate_icon ? 356 : '' ) ) );
1192 $hotspot_info['stickerBtnHeight'] = isset( $hotspot_data['hotspot-sticker-btn-height'] ) && $hotspot_data['hotspot-sticker-btn-height'] !== '' ? $hotspot_data['hotspot-sticker-btn-height'] : ( ( $is_social_share || $is_add_to_cart || $is_separate_icon ) ? 60 : '' );
1193 $hotspot_info['stickerBtnRadius'] = isset( $hotspot_data['hotspot-sticker-btn-radius'] ) && $hotspot_data['hotspot-sticker-btn-radius'] !== '' ? (float) $hotspot_data['hotspot-sticker-btn-radius'] : ( $is_separate_icon ? 30 : 10 );
1194 $hotspot_info['stickerBtnBorder'] = isset( $hotspot_data['hotspot-sticker-btn-border'] ) && $hotspot_data['hotspot-sticker-btn-border'] !== '' ? (float) $hotspot_data['hotspot-sticker-btn-border'] : ( $is_social_share ? 1 : 0 );
1195 $hotspot_info['stickerBtnBorderColor'] = $hotspot_data['hotspot-sticker-btn-border-color'] ?? ( $is_social_share ? '#3a3051' : ( ( $is_add_to_cart || $is_separate_icon ) ? '#ffffff' : '#EF991F' ) );
1196 $hotspot_info['stickerBtnTextSize'] = isset( $hotspot_data['hotspot-sticker-btn-text-size'] ) && $hotspot_data['hotspot-sticker-btn-text-size'] !== '' ? (float) $hotspot_data['hotspot-sticker-btn-text-size'] : 18;
1197 $hotspot_info['stickerBtnTextWeight'] = $hotspot_data['hotspot-sticker-btn-text-weight'] ?? ( ( $is_social_share || $is_add_to_cart || $is_separate_icon ) ? '600' : '700' );
1198 $hotspot_info['stickerBtnIcon'] = ( $is_add_to_cart || $is_social_share ) ? 'none' : ( $hotspot_data['hotspot-sticker-btn-icon'] ?? 'fas fa-tag' );
1199 // Button with separate icon fields
1200 $hotspot_info['stickerIconBoxBgColor'] = $hotspot_data['hotspot-sticker-icon-box-bg-color'] ?? '#ffffff';
1201 $hotspot_info['stickerIconBoxRadius'] = isset( $hotspot_data['hotspot-sticker-icon-box-radius'] ) && $hotspot_data['hotspot-sticker-icon-box-radius'] !== '' ? (float) $hotspot_data['hotspot-sticker-icon-box-radius'] : 30;
1202 $hotspot_info['stickerIconBoxBorder'] = isset( $hotspot_data['hotspot-sticker-icon-box-border'] ) && $hotspot_data['hotspot-sticker-icon-box-border'] !== '' ? (float) $hotspot_data['hotspot-sticker-icon-box-border'] : 0;
1203 $hotspot_info['stickerIconBoxBorderColor'] = $hotspot_data['hotspot-sticker-icon-box-border-color'] ?? '#ffffff';
1204 $hotspot_info['stickerIconBoxSize'] = isset( $hotspot_data['hotspot-sticker-icon-box-size'] ) && $hotspot_data['hotspot-sticker-icon-box-size'] !== '' ? (float) $hotspot_data['hotspot-sticker-icon-box-size'] : 60;
1205 // Social share sticker fields
1206 $hotspot_info['stickerSocialColor'] = $hotspot_data['hotspot-sticker-social-color'] ?? '#ffffff';
1207 $hotspot_info['stickerSocialSize'] = isset( $hotspot_data['hotspot-sticker-social-size'] ) && $hotspot_data['hotspot-sticker-social-size'] !== '' ? (float) $hotspot_data['hotspot-sticker-social-size'] : 20;
1208 $hotspot_info['stickerSocialGap'] = isset( $hotspot_data['hotspot-sticker-social-gap'] ) && $hotspot_data['hotspot-sticker-social-gap'] !== '' ? (float) $hotspot_data['hotspot-sticker-social-gap'] : 16;
1209 $hotspot_info['stickerSocialLinks'] = isset( $hotspot_data['hotspot-sticker-social-links'] ) ? ( is_array( $hotspot_data['hotspot-sticker-social-links'] ) ? $hotspot_data['hotspot-sticker-social-links'] : json_decode( (string) $hotspot_data['hotspot-sticker-social-links'], true ) ) : [
1210 [ 'id' => '1', 'icon' => 'fab fa-linkedin-in', 'customSvg' => '', 'url' => 'https://linkedin.com', 'openNewTab' => 'on' ],
1211 [ 'id' => '2', 'icon' => 'fab fa-facebook-f', 'customSvg' => '', 'url' => 'https://facebook.com', 'openNewTab' => 'on' ],
1212 [ 'id' => '3', 'icon' => 'fab fa-instagram', 'customSvg' => '', 'url' => 'https://instagram.com', 'openNewTab' => 'on' ],
1213 [ 'id' => '4', 'icon' => 'fab fa-dribbble', 'customSvg' => '', 'url' => 'https://dribbble.com', 'openNewTab' => 'on' ],
1214 ];
1215 $hotspot_info['stickerShowPlaceholderText'] = $hotspot_data['hotspot-sticker-show-placeholder-text'] ?? 'on';
1216 } else {
1217 if ( isset( $hotspot_data['hotspot-scale'] ) && ( $hotspot_data['hotspot-scale'] === 'on' || $hotspot_data['hotspot-scale'] === true ) ) {
1218 $hotspot_info['scale'] = true;
1219 }
1220 if ($hotspot_data["hotspot-customclass"] == 'none' || $hotspot_data["hotspot-customclass"] == '') {
1221 unset($hotspot_info["cssClass"]);
1222 }
1223 }
1224 array_push($hotspots, $hotspot_info);
1225 }
1226
1227 $device_scene = $panoscenes['scene-attachment-url'];
1228 $mobile_scene_url = '';
1229 $desktop_scene_url = $device_scene;
1230
1231 if ($mobile_media_resize == "true" && !empty($device_scene)) {
1232 $attachment_id = !empty($panoscenes['scene-attachment-id'])
1233 ? (int) $panoscenes['scene-attachment-id']
1234 : $this->get_attachment_id_by_url($device_scene);
1235
1236 if ($attachment_id) {
1237 $image_width = 0;
1238 $image_meta = wp_get_attachment_metadata($attachment_id);
1239
1240 if (isset($image_meta['width'])) {
1241 $image_width = (int) $image_meta['width'];
1242 } elseif (function_exists('get_attached_file')) {
1243 // Local file fallback only if attachment metadata is missing (no network request)
1244 $file_path = get_attached_file($attachment_id);
1245 if ($file_path && file_exists($file_path)) {
1246 $image_info = @getimagesize($file_path);
1247 if (isset($image_info[0])) {
1248 $image_width = (int) $image_info[0];
1249 }
1250 }
1251 }
1252
1253 if ($image_width > 4096) {
1254 $mobile_scene = wp_get_attachment_image_src($attachment_id, 'wpvr_mobile');
1255 if (!empty($mobile_scene[3])) { // is_intermediate verifies resized image exists
1256 $mobile_scene_url = $mobile_scene[0];
1257 }
1258
1259 $desktop_scene = wp_get_attachment_image_src($attachment_id, 'full');
1260 if (isset($desktop_scene[0])) {
1261 $desktop_scene_url = $desktop_scene[0];
1262 $device_scene = $desktop_scene[0];
1263 }
1264
1265 if (wpvr_isMobileDevice() && !empty($mobile_scene_url)) {
1266 $device_scene = $mobile_scene_url;
1267 }
1268 }
1269 }
1270 }
1271
1272 $scene_info = array();
1273
1274 if ($panoscenes["scene-type"] == 'cubemap') {
1275 $pano_attachment = array(
1276 $panoscenes["scene-attachment-url-face0"],
1277 $panoscenes["scene-attachment-url-face1"],
1278 $panoscenes["scene-attachment-url-face2"],
1279 $panoscenes["scene-attachment-url-face3"],
1280 $panoscenes["scene-attachment-url-face4"],
1281 $panoscenes["scene-attachment-url-face5"]
1282 );
1283
1284 $scene_info = array("type" => $panoscenes["scene-type"], "cubeMap" => $pano_attachment, "pitch" => $default_scene_pitch, "maxPitch" => $scene_max_pitch, "minPitch" => $scene_min_pitch, "maxYaw" => $scene_max_yaw, "minYaw" => $scene_min_yaw, "yaw" => $default_scene_yaw, "hfov" => $default_zoom, "maxHfov" => $max_zoom, "minHfov" => $min_zoom, "title" => $scene_ititle, "author" => $scene_author, "authorURL" => $scene_author_url, "vaov" => $scene_vaov, "haov" => $scene_haov, "vOffset" => $scene_vertical_offset, "hotSpots" => $hotspots);
1285 } else {
1286 $scene_info = array("type" => $panoscenes["scene-type"], "panorama" => $device_scene, "pitch" => $default_scene_pitch, "maxPitch" => $scene_max_pitch, "minPitch" => $scene_min_pitch, "maxYaw" => $scene_max_yaw, "minYaw" => $scene_min_yaw, "yaw" => $default_scene_yaw, "hfov" => $default_zoom, "maxHfov" => $max_zoom, "minHfov" => $min_zoom, "title" => $scene_ititle, "author" => $scene_author, "authorURL" => $scene_author_url, "vaov" => $scene_vaov, "haov" => $scene_haov, "vOffset" => $scene_vertical_offset, "hotSpots" => $hotspots);
1287 if (!empty($mobile_scene_url)) {
1288 $scene_info['mobile_panorama'] = $mobile_scene_url;
1289 $scene_info['desktop_panorama'] = $desktop_scene_url;
1290 $scene_info['desktop_width'] = $image_width;
1291 }
1292 }
1293
1294
1295 if (isset($panoscenes["ptyscene"])) {
1296 if ($panoscenes["ptyscene"] == "off") {
1297 unset($scene_info['pitch']);
1298 unset($scene_info['yaw']);
1299 }
1300 }
1301
1302 if (!$show_scene_info || empty($panoscenes["scene-ititle"])) {
1303 unset($scene_info['title']);
1304 }
1305 if (!$show_scene_info || empty($panoscenes["scene-author"])) {
1306 unset($scene_info['author']);
1307 }
1308 if (!$show_scene_info || empty($panoscenes["scene-author-url"])) {
1309 unset($scene_info['authorURL']);
1310 }
1311
1312 if (empty($scene_vaov)) {
1313 unset($scene_info['vaov']);
1314 }
1315
1316 if (empty($scene_haov)) {
1317 unset($scene_info['haov']);
1318 }
1319
1320 if (empty($scene_vertical_offset)) {
1321 unset($scene_info['vOffset']);
1322 }
1323
1324 if (isset($panoscenes["cvgscene"])) {
1325 if ($panoscenes["cvgscene"] == "off") {
1326 unset($scene_info['maxPitch']);
1327 unset($scene_info['minPitch']);
1328 }
1329 }
1330 if (empty($panoscenes["scene-maxpitch"])) {
1331 unset($scene_info['maxPitch']);
1332 }
1333
1334 if (empty($panoscenes["scene-minpitch"])) {
1335 unset($scene_info['minPitch']);
1336 }
1337
1338 if (isset($panoscenes["chgscene"])) {
1339 if ($panoscenes["chgscene"] == "off") {
1340 unset($scene_info['maxYaw']);
1341 unset($scene_info['minYaw']);
1342 }
1343 }
1344 if (empty($panoscenes["scene-maxyaw"])) {
1345 unset($scene_info['maxYaw']);
1346 }
1347
1348 if (empty($panoscenes["scene-minyaw"])) {
1349 unset($scene_info['minYaw']);
1350 }
1351
1352 // if (isset($panoscenes["czscene"])) {
1353 // if ($panoscenes["czscene"] == "off") {
1354 // unset($scene_info['hfov']);
1355 // unset($scene_info['maxHfov']);
1356 // unset($scene_info['minHfov']);
1357 // }
1358 // }
1359
1360 $scene_array = array();
1361 $scene_array = array(
1362 $panoscenes["scene-id"] => $scene_info
1363 );
1364 $scene_data[$panoscenes["scene-id"]] = $scene_info;
1365 }
1366 }
1367
1368 $pano_id_array = array();
1369 $pano_id_array = array("panoid" => $panoid);
1370 $pano_response = array();
1371 $pano_response = array("autoLoad" => $autoload, "showControls" => $control, "orientationSupport" => 'false', "compass" => $compass, 'orientationOnByDefault' => $gyro_orientation, "mouseZoom" => $mouseZoom, "draggable" => $draggable, 'disableKeyboardCtrl' => $diskeyboard, 'keyboardZoom' => $keyboardzoom, "preview" => $preview, "autoRotate" => $autorotation, "autoRotateInactivityDelay" => $autorotationinactivedelay, "autoRotateStopDelay" => $autorotationstopdelay, "default" => $default_data, "scenes" => $scene_data);
1372 if (empty($autorotation)) {
1373 unset($pano_response['autoRotate']);
1374 unset($pano_response['autoRotateInactivityDelay']);
1375 unset($pano_response['autoRotateStopDelay']);
1376 }
1377 if (empty($autorotationinactivedelay)) {
1378 unset($pano_response['autoRotateInactivityDelay']);
1379 }
1380 if (empty($autorotationstopdelay)) {
1381 unset($pano_response['autoRotateStopDelay']);
1382 }
1383 $response = array();
1384 $response = array($pano_id_array, $pano_response);
1385 if (!empty($response)) {
1386 $response = json_encode($response);
1387 }
1388
1389
1390 if (empty($width)) {
1391 $width = '600px';
1392 }
1393 if (empty($height)) {
1394 $height = '400px';
1395 }
1396 $foreground_color = '#fff';
1397 $pulse_color = wpvr_hex2rgb($hotspoticoncolor);
1398 $rgb = wpvr_HTMLToRGB($hotspoticoncolor);
1399 $hsl = wpvr_RGBToHSL($rgb);
1400 if ($hsl->lightness > 200) {
1401 $foreground_color = '#000000';
1402 } else {
1403 $foreground_color = '#fff';
1404 }
1405 $html = '';
1406
1407 $html .= '<style>';
1408 if ($width == 'embed') {
1409 $html .= 'body{
1410 overflow: hidden;
1411 }';
1412 }
1413 $status = get_option('wpvr_edd_license_status');
1414 if ($status !== false && $status == 'valid') {
1415 if(isset($postdata['customcss_enable']) && $postdata['customcss_enable'] == 'on'){
1416 $html .= isset($postdata['customcss']) ? $postdata['customcss'] : '';
1417 }
1418 }
1419 $pano_suffix = (strpos($panoid, 'pano') === 0) ? substr($panoid, 4) : (string) $panoid;
1420 $panoid2 = 'pano2' . $pano_suffix;
1421 $master_container_id = ($panoid === 'pano' . $id) ? 'master-container' : ('master-container-' . $pano_suffix);
1422 $status = get_option('wpvr_edd_license_status');
1423 if ($status !== false && $status == 'valid' && ! empty( $panodata['scene-list'] ) && is_array( $panodata['scene-list'] )) {
1424 foreach ($panodata['scene-list'] as $panoscenes){
1425 if ( empty( $panoscenes['hotspot-list'] ) || ! is_array( $panoscenes['hotspot-list'] ) ) {
1426 continue;
1427 }
1428 foreach($panoscenes['hotspot-list'] as $hotspot){
1429 if ( ( $hotspot['hotspot-type'] ?? '' ) === 'sticker' ) {
1430 continue;
1431 }
1432 if (isset($hotspot['hotspot-customclass-color-icon-value']) && !empty($hotspot['hotspot-customclass-color-icon-value'])) {
1433 $hotspoticoncolor = $hotspot['hotspot-customclass-color-icon-value'];
1434 } else {
1435 $hotspoticoncolor = "#00b4ff";
1436 }
1437 $hotspot_border = '';
1438 if(isset($hotspot['hotspot-border']) && $hotspot['hotspot-border'] == 'on'){
1439 $border_width = $hotspot['hotspot-border-width'];
1440 $border_color = $hotspot['hotspot-border-color'];
1441 $border_style = $hotspot['hotspot-border-style'];
1442 $hotspot_border = 'border: '.$border_width.'px '.$border_style.' '.$border_color.';';
1443 }
1444 $hotspot_background_color = 'background-color: ' . $hotspoticoncolor . ';';
1445 $hotspot_animation = ' animation: icon-pulse' . $panoid . '-' . $panoscenes['scene-id'] . '-' . sanitize_html_class($hotspot['hotspot-title']) . ' 1.5s infinite cubic-bezier(.25, 0, 0, 1);
1446 '. $hotspot_border.'';
1447 $pulse_color = wpvr_hex2rgb($hotspoticoncolor);
1448 if (!empty($hotspot["hotspot-customclass-pro"]) && $hotspot["hotspot-customclass-pro"] != 'none') {
1449 $border_radius = ' border-radius: 100%;';
1450 $hotspot_shape = isset($hotspot["hotspot-shape"]) ? $hotspot["hotspot-shape"] : 'round';
1451 if($hotspot_shape === 'square'){
1452 $border_radius = '';
1453 }
1454 if ($hotspot_shape === 'hexagon') {
1455 $border_radius = '';
1456 $hotspot_background_color = 'background-color: transparent;';
1457 $hotspot_animation = '';
1458 }
1459
1460 if(isset($hotspot['hotspot-custom-icon-color-value']) && !empty($hotspot['hotspot-custom-icon-color-value'])){
1461 $foreground_color = $hotspot['hotspot-custom-icon-color-value'];
1462 }
1463
1464 $html .= '#' . $panoid . ' div.pnlm-hotspot-base.fas.custom-' . $id.'-' . $panoscenes['scene-id'] .'-'. sanitize_html_class($hotspot['hotspot-title']).',
1465 #' . $panoid . ' div.pnlm-hotspot-base.fab.custom-' . $id.'-' . $panoscenes['scene-id'] .'-'. sanitize_html_class($hotspot['hotspot-title']).',
1466 #' . $panoid . ' div.pnlm-hotspot-base.fa-solid.custom-' . $id.'-' . $panoscenes['scene-id'] .'-'. sanitize_html_class($hotspot['hotspot-title']).',
1467 #' . $panoid . ' div.pnlm-hotspot-base.fa.custom-' . $id.'-' . $panoscenes['scene-id'] .'-'. sanitize_html_class($hotspot['hotspot-title']).',
1468 #' . $panoid . ' div.pnlm-hotspot-base.far.custom-' . $id.'-' . $panoscenes['scene-id'] .'-'. sanitize_html_class($hotspot['hotspot-title']).' {
1469 display: block !important;
1470 '.$hotspot_background_color.'
1471 color: ' . $foreground_color . ';
1472 '.$border_radius.'
1473 width: 30px;
1474 height: 30px;
1475 font-size: 16px;
1476 line-height: 30px;
1477 '.$hotspot_animation.'
1478 }';
1479
1480 if($hotspot_shape === 'hexagon'){
1481
1482 $html .= '#' . $panoid . ' .custom-' . $id . '-' . $panoscenes['scene-id'] . '-' . sanitize_html_class($hotspot['hotspot-title']) . ' .hexagon-wrapper svg path {
1483 fill: ' . $hotspoticoncolor . ';
1484 }';
1485
1486 $html .= '#' . $panoid . ' .custom-' . $id . '-' . $panoscenes['scene-id'] . '-' . sanitize_html_class($hotspot['hotspot-title']) . '.pnlm-tooltip:after{
1487 content: "";
1488 position: absolute;
1489 left: 50%;
1490 top: 50%;
1491 transform: translate(-50%, -50%);
1492 width: 85%;
1493 height: 85%;
1494 animation: icon-pulse' . $panoid . '-' . $panoscenes['scene-id'] . '-' . sanitize_html_class($hotspot['hotspot-title']) . ' 1.5s infinite cubic-bezier(.25, 0, 0, 1);
1495 border-radius: 100%;
1496 z-index: -2;
1497 }';
1498
1499 }
1500
1501 $html .= '#' . $panoid2 . ' div.pnlm-hotspot-base.fas.custom-' . $id.'-' . $panoscenes['scene-id'] .'-'. sanitize_html_class($hotspot['hotspot-title']).',
1502 #' . $panoid2 . ' div.pnlm-hotspot-base.fab.custom-' . $id.'-' . $panoscenes['scene-id'] .'-'. sanitize_html_class($hotspot['hotspot-title']).',
1503 #' . $panoid2 . ' div.pnlm-hotspot-base.fa-solid.custom-' . $id.'-' . $panoscenes['scene-id'] .'-'. sanitize_html_class($hotspot['hotspot-title']).',
1504 #' . $panoid2 . ' div.pnlm-hotspot-base.fa.custom-' . $id.'-' . $panoscenes['scene-id'] .'-'. sanitize_html_class($hotspot['hotspot-title']).',
1505 #' . $panoid2 . ' div.pnlm-hotspot-base.far.custom-' . $id.'-' . $panoscenes['scene-id'] .'-'. sanitize_html_class($hotspot['hotspot-title']).' {
1506 display: block !important;
1507 '.$hotspot_background_color.'
1508 color: ' . $foreground_color . ';
1509 '.$border_radius.'
1510 width: 30px;
1511 height: 30px;
1512 font-size: 16px;
1513 line-height: 30px;
1514 '.$hotspot_animation.'
1515 }';
1516 }
1517 if (isset($hotspot['hotspot-blink'])) {
1518 $hotspotblink = $hotspot['hotspot-blink'];
1519 if ($hotspotblink == 'on') {
1520 $html .= '@-webkit-keyframes icon-pulse' .$panoid .'-'. $panoscenes['scene-id'] .'-'. sanitize_html_class($hotspot['hotspot-title']) .' {
1521 0% {
1522 box-shadow: 0 0 0 0px rgba(' . $pulse_color[0] . ', 1);
1523 }
1524 100% {
1525 box-shadow: 0 0 0 10px rgba(' . $pulse_color[0] . ', 0);
1526 }
1527 }
1528 @keyframes icon-pulse' . $panoid . ' {
1529 0% {
1530 box-shadow: 0 0 0 0px rgba(' . $pulse_color[0] . ', 1);
1531 }
1532 100% {
1533 box-shadow: 0 0 0 10px rgba(' . $pulse_color[0] . ', 0);
1534 }
1535 }';
1536 $html .= '@-webkit-keyframes icon-pulse' .$panoid2 .'-'. $panoscenes['scene-id'] .'-'. sanitize_html_class($hotspot['hotspot-title']) .' {
1537 0% {
1538 box-shadow: 0 0 0 0px rgba(' . $pulse_color[0] . ', 1);
1539 }
1540 100% {
1541 box-shadow: 0 0 0 10px rgba(' . $pulse_color[0] . ', 0);
1542 }
1543 }
1544 @keyframes icon-pulse' . $panoid . ' {
1545 0% {
1546 box-shadow: 0 0 0 0px rgba(' . $pulse_color[0] . ', 1);
1547 }
1548 100% {
1549 box-shadow: 0 0 0 10px rgba(' . $pulse_color[0] . ', 0);
1550 }
1551 }';
1552 }
1553 }
1554
1555 }
1556
1557 }
1558
1559 }
1560
1561 $status = get_option('wpvr_edd_license_status');
1562 if ($status !== false && $status == 'valid') {
1563 if (!$gyro) {
1564 $html .= '#' . $panoid . ' div.pnlm-orientation-button {
1565 display: none;
1566 }';
1567 }
1568 } else {
1569 $html .= '#' . $panoid . ' div.pnlm-orientation-button {
1570 display: none;
1571 }';
1572 }
1573 $floor_plan_custom_color = isset($postdata['floor_plan_custom_color']) ? $postdata['floor_plan_custom_color'] : '#cca92c';
1574 $foreground_color_pointer = '#fff';
1575 if($floor_plan_custom_color != ''){
1576 $pointer_pulse = wpvr_hex2rgb($floor_plan_custom_color);
1577 $floor_rgb = wpvr_HTMLToRGB($floor_plan_custom_color);
1578 $floor_hsl = wpvr_RGBToHSL($floor_rgb);
1579 if ($floor_hsl->lightness > 200) {
1580 $foreground_color_pointer = '#000000';
1581 }
1582 $html .= '
1583 .wpvr-floor-map .floor-plan-pointer.add-pulse:before {
1584 border: 17px solid '.$floor_plan_custom_color.';
1585 }
1586 @-webkit-keyframes pulse {
1587 0% {
1588 -webkit-box-shadow: 0 0 0 0 rgba('.$pointer_pulse[0].', 0.7);
1589 }
1590 70% {
1591 -webkit-box-shadow: 0 0 0 10px rgba('.$pointer_pulse[0].', 0);
1592 }
1593 100% {
1594 -webkit-box-shadow: 0 0 0 0 rgba('.$pointer_pulse[0].', 0);
1595 }
1596 }
1597 @keyframes pulse {
1598 0% {
1599 -moz-box-shadow: 0 0 0 0 rgba('.$pointer_pulse[0].', 0.7);
1600 box-shadow: 0 0 0 0 rgba('.$pointer_pulse[0].', 0.7);
1601 }
1602 70% {
1603 -moz-box-shadow: 0 0 0 10px rgba('.$pointer_pulse[0].', 0);
1604 box-shadow: 0 0 0 10px rgba('.$pointer_pulse[0].', 0);
1605 }
1606 100% {
1607 -moz-box-shadow: 0 0 0 0 rgba('.$pointer_pulse[0].', 0);
1608 box-shadow: 0 0 0 0 rgba('.$pointer_pulse[0].', 0);
1609 }
1610 }';
1611 }
1612
1613 $html .= '</style>';
1614
1615
1616 $scene_animation = isset($postdata['sceneAnimation']) ? $postdata['sceneAnimation'] : 'off';
1617 $scene_animation_enabled = in_array( $scene_animation, array( 'on', '1', 1, true ), true );
1618
1619 if( $scene_animation_enabled && is_plugin_active( 'wpvr-pro/wpvr-pro.php' ) ) {
1620 $animation_type = isset($postdata['sceneAnimationName']) ? $postdata['sceneAnimationName'] : 'none';
1621 $animation_type = $animation_type === 'fade' ? 'fade_in' : $animation_type;
1622 $animationDuration = isset($postdata['sceneAnimationTransitionDuration']) ? $postdata['sceneAnimationTransitionDuration'] : '500ms';
1623 $animationDelay = isset($postdata['sceneAnimationTransitionDelay']) ? $postdata['sceneAnimationTransitionDelay'] : '0ms';
1624 $animation_css = apply_filters('wpvr_tour_scene_animation',$animation_type,$animationDuration,$animationDelay,$postdata,$id);
1625 $html .= $animation_css;
1626 }
1627
1628 $container_width = $width;
1629 $container_height = $height;
1630 $container_mobile_height = $mobile_height;
1631
1632 if ($width == 'fullwidth') {
1633 $container_width = "100%";
1634 } elseif ($width == 'embed') {
1635 $container_width = "100%";
1636 $container_height = "100%";
1637 $container_mobile_height = "100%";
1638 }
1639
1640 if (wpvr_isMobileDevice()) {
1641 $html .= '<div id="' . $master_container_id . '" class="wpvr-master-container wpvr-cardboard '.$enable_cardboard.'" style="max-width:' . $container_width . '; width: 100%; height: ' . $container_mobile_height . '; border-radius:' . $radius . '; direction:ltr; ">';
1642 } else {
1643 $html .= '<div id="' . $master_container_id . '" class="wpvr-master-container wpvr-cardboard '.$enable_cardboard.'" style="max-width:' . $container_width . '; width: 100%; height: ' . $container_height . '; border-radius:' . $radius . '; direction:ltr; ">';
1644 }
1645 $is_pro = apply_filters('is_wpvr_pro_active',false);
1646 $status = get_option('wpvr_edd_license_status');
1647 $is_cardboard = get_option('wpvr_cardboard_disable');
1648 if ($status !== false && 'valid' == $status && $is_pro && wpvr_isMobileDevice() && $is_cardboard == 'true' ) {
1649 $html .= '<button class="fullscreen-button">';
1650 $html .= '<span class="expand">';
1651 $html .= '<i class="fas fa-expand" aria-hidden="true"></i>';
1652 $html .= '</span>';
1653
1654 $html .= '<span class="compress">';
1655 $html .= '<i class="fas fa-minimize" aria-hidden="true"></i>';
1656 $html .= '</span>';
1657 $html .= '</button>';
1658 $embed_mode = '';
1659 if($width == "embed"){
1660 $embed_mode = "vr-embade-mode";
1661 }
1662 $html .= '<label class="wpvr-cardboard-switcher '.$embed_mode.'">
1663 <input type="checkbox" class="vr_mode_change' . $pano_suffix . '" name="vr_mode_change" value="off">
1664 <span class="switcher-box">
1665 <span class="normal-mode-tooltip">Normal VR Mode</span>
1666 <svg width="78" height="60" viewBox="0 0 78 60" fill="none" xmlns="http://www.w3.org/2000/svg">
1667 <path d="M42.25 21.4286C42.25 22.2811 41.9076 23.0986 41.2981 23.7014C40.6886 24.3042 39.862 24.6429 39 24.6429C38.138 24.6429 37.3114 24.3042 36.7019 23.7014C36.0924 23.0986 35.75 22.2811 35.75 21.4286C35.75 20.5761 36.0924 19.7585 36.7019 19.1557C37.3114 18.5529 38.138 18.2143 39 18.2143C39.862 18.2143 40.6886 18.5529 41.2981 19.1557C41.9076 19.7585 42.25 20.5761 42.25 21.4286ZM19.5 30C18.9254 30 18.3743 30.2258 17.9679 30.6276C17.5616 31.0295 17.3333 31.5745 17.3333 32.1429C17.3333 32.7112 17.5616 33.2562 17.9679 33.6581C18.3743 34.06 18.9254 34.2857 19.5 34.2857H28.1667C28.7413 34.2857 29.2924 34.06 29.6987 33.6581C30.1051 33.2562 30.3333 32.7112 30.3333 32.1429C30.3333 31.5745 30.1051 31.0295 29.6987 30.6276C29.2924 30.2258 28.7413 30 28.1667 30H19.5ZM47.6667 32.1429C47.6667 31.5745 47.8949 31.0295 48.3013 30.6276C48.7076 30.2258 49.2587 30 49.8333 30H58.5C59.0746 30 59.6257 30.2258 60.0321 30.6276C60.4384 31.0295 60.6667 31.5745 60.6667 32.1429C60.6667 32.7112 60.4384 33.2562 60.0321 33.6581C59.6257 34.06 59.0746 34.2857 58.5 34.2857H49.8333C49.2587 34.2857 48.7076 34.06 48.3013 33.6581C47.8949 33.2562 47.6667 32.7112 47.6667 32.1429ZM32.5 0C31.9254 0 31.3743 0.225765 30.9679 0.627629C30.5616 1.02949 30.3333 1.57454 30.3333 2.14286V8.57143H18.4167C14.8693 8.57183 11.4528 9.89617 8.84994 12.2798C6.24706 14.6634 4.64954 17.9306 4.37667 21.4286H2.16667C1.59203 21.4286 1.04093 21.6543 0.634602 22.0562C0.228273 22.4581 0 23.0031 0 23.5714V36.4286C0 36.9969 0.228273 37.5419 0.634602 37.9438C1.04093 38.3457 1.59203 38.5714 2.16667 38.5714H4.33333V46.0714C4.33333 49.7655 5.81711 53.3083 8.45825 55.9204C11.0994 58.5325 14.6815 60 18.4167 60H25.3933C29.1269 59.9986 32.7071 58.5311 35.347 55.92L37.921 53.3786C38.0618 53.2393 38.229 53.1288 38.4131 53.0534C38.5971 52.978 38.7943 52.9392 38.9935 52.9392C39.1927 52.9392 39.3899 52.978 39.5739 53.0534C39.758 53.1288 39.9252 53.2393 40.066 53.3786L42.6357 55.92C45.2766 58.5322 48.8586 59.9998 52.5937 60H59.5833C63.3185 60 66.9006 58.5325 69.5418 55.9204C72.1829 53.3083 73.6667 49.7655 73.6667 46.0714V38.5714H75.8333C76.408 38.5714 76.9591 38.3457 77.3654 37.9438C77.7717 37.5419 78 36.9969 78 36.4286V23.5714C78 23.0031 77.7717 22.4581 77.3654 22.0562C76.9591 21.6543 76.408 21.4286 75.8333 21.4286H73.6233C73.3505 17.9306 71.753 14.6634 69.1501 12.2798C66.5472 9.89617 63.1307 8.57183 59.5833 8.57143H47.6667V2.14286C47.6667 1.57454 47.4384 1.02949 47.0321 0.627629C46.6257 0.225765 46.0746 0 45.5 0H32.5ZM69.3333 22.5V46.0714C69.3333 48.6289 68.3061 51.0816 66.4776 52.89C64.6491 54.6983 62.1692 55.7143 59.5833 55.7143H52.5937C50.0093 55.7132 47.5311 54.6973 45.7037 52.89L43.1297 50.3486C42.5864 49.8108 41.9413 49.3842 41.2312 49.0931C40.5211 48.8021 39.76 48.6522 38.9913 48.6522C38.2227 48.6522 37.4616 48.8021 36.7515 49.0931C36.0414 49.3842 35.3963 49.8108 34.853 50.3486L32.2833 52.89C30.4559 54.6973 27.9777 55.7132 25.3933 55.7143H18.4167C15.8308 55.7143 13.3509 54.6983 11.5224 52.89C9.6939 51.0816 8.66667 48.6289 8.66667 46.0714V22.5C8.66667 19.9426 9.6939 17.4899 11.5224 15.6815C13.3509 13.8731 15.8308 12.8571 18.4167 12.8571H59.5833C62.1692 12.8571 64.6491 13.8731 66.4776 15.6815C68.3061 17.4899 69.3333 19.9426 69.3333 22.5Z" fill="#216DF0"/>
1668 </svg>
1669 </span>
1670 </label>';
1671
1672 }
1673
1674 if ($width == 'fullwidth') {
1675 if (wpvr_isMobileDevice()) {
1676 $html .= '<div class="cardboard-vrfullwidth vrfullwidth">';
1677 $html .= '<div id="' . $panoid2 . '" class="pano-wrap pano-left cardboard-half pano2' . $id . '" style="width: 49%!important; border-radius:' . $radius . ' text-align:center; direction:ltr;" ><div id="center-pointer2' . $pano_suffix . '" class="vr-pointer-container"><span class="center-pointer"></span></div></div>';
1678 $html .= '<div id="' . $panoid . '" class="pano-wrap pano-right pano' . $id . '" style="width: 100%; text-align:center; direction:ltr; border-radius:' . $radius . '" >';
1679 } else {
1680 $html .= '<div id="' . $panoid2 . '" class="pano-wrap pano-left pano2' . $id . '" style="width: 49%; border-radius:' . $radius . '"><div id="center-pointer2' . $pano_suffix . '" class="vr-pointer-container"><span class="center-pointer"></span></div></div>';
1681 if ($radius) {
1682 $html .= '<div id="' . $panoid . '" class="pano-wrap vrfullwidth pano' . $id . '" style=" text-align:center; height: ' . $height . '; border-radius:' . $radius . '; direction:ltr;" >';
1683 } else {
1684 $html .= '<div id="' . $panoid . '" class="pano-wrap vrfullwidth pano' . $id . '" style=" text-align:center; height: ' . $height . '; direction:ltr;" >';
1685 }
1686 }
1687 } elseif ($width == 'embed') {
1688 $html .= '<div class="cardboard-vrembed vrembed">';
1689 $html .= '<div id="' . $panoid2 . '" class="pano-wrap pano-left pano2' . $id . '" style=" width: 49%!important; text-align:center; direction:ltr;" ><div id="center-pointer2' . $pano_suffix . '" class="vr-pointer-container"><span class="center-pointer"></span></div></div>';
1690 $html .= '<div id="' . $panoid . '" class="pano-wrap pano-right pano' . $id . '" style="width: 100%; height: 100%; text-align:center; direction:ltr;" >';
1691 } else {
1692 if (wpvr_isMobileDevice()) {
1693 $html .= '<div id="' . $panoid2 . '" class="pano-wrap pano-left cardboard-half pano2' . $id . '" style="width: 49%; border-radius:' . $radius . '"><div id="center-pointer2' . $pano_suffix . '" class="vr-pointer-container"><span class="center-pointer"></span></div></div>';
1694 if ($radius) {
1695 $html .= '<div id="' . $panoid . '" class="pano-wrap pano-right pano' . $id . '" style=" width: 100%; border-radius:' . $radius . ';">';
1696 } else {
1697 $html .= '<div id="' . $panoid . '" class="pano-wrap pano-right pano' . $id . '" style=" width: 100%; ">';
1698 }
1699 } else {
1700 $html .= '<div id="' . $panoid2 . '" class="pano-wrap pano-left pano2' . $id . '" style="width: 49%; border-radius:' . $radius . '"><div id="center-pointer2' . $pano_suffix . '" class="vr-pointer-container"><span class="center-pointer"></span></div></div>';
1701
1702 if ($radius) {
1703 $html .= '<div id="' . $panoid . '" class="pano-wrap pano-right pano' . $id . '" style="width: 100%; border-radius:' . $radius . ';">';
1704 } else {
1705 $html .= '<div id="' . $panoid . '" class="pano-wrap pano-right pano' . $id . '" style="width: 100%;">';
1706 }
1707 }
1708 }
1709 // Vr mode transction scene to scene
1710 if ($status !== false && 'valid' == $status && $is_pro) {
1711 $html .= '<div id="center-pointer' . $pano_suffix . '" class="vr-pointer-container" style="display:none"><span class="center-pointer"></span></div>';
1712 }
1713 $social_logo_top = '';
1714 //===company logo===//
1715 if (isset($postdata['cpLogoSwitch'])) {
1716 $cpLogoImg = $postdata['cpLogoImg'] ?? '';
1717 $cpLogoContent = $postdata['cpLogoContent'] ?? '';
1718 if ($postdata['cpLogoSwitch'] == 'on' && 'valid' == $status && $is_pro) {
1719 $html .= '<div id="cp-logo-controls">';
1720 $html .= '<div class="cp-logo-ctrl" id="cp-logo">';
1721 if ($cpLogoImg) {
1722 $social_logo_top = '50px';
1723 $html .= '<img loading="lazy" src="' . $cpLogoImg . '" alt="Company Logo">';
1724 }
1725
1726 if ($cpLogoContent) {
1727 $html .= '<div class="cp-info">' . esc_attr($cpLogoContent) . '</div>';
1728 }
1729 $html .= '</div>';
1730 $html .= '</div>';
1731 }
1732 }
1733 //===company logo ends===//
1734
1735 //===Generic Form===//
1736 if (isset($postdata["genericform"]) && $postdata["genericform"] === 'on' && 'valid' == $status && $is_pro) {
1737 // Process shortcode with fallback handling
1738 $shortcode_content = '';
1739 if (isset($postdata["genericformshortcode"]) && !empty(trim($postdata["genericformshortcode"]))) {
1740 $shortcode_content = do_shortcode( $postdata["genericformshortcode"] );
1741 } else {
1742 $shortcode_content = '<p class="error-message">No shortcode found.</p>';
1743 }
1744
1745 // Generate the form trigger button
1746 $generic_form_icon = isset($postdata['genericformicon']) ? (string) $postdata['genericformicon'] : 'fab fa-wpforms';
1747 $generic_form_icon = implode(' ', array_filter(array_map('sanitize_html_class', preg_split('/\s+/', $generic_form_icon))));
1748 $generic_form_icon = $generic_form_icon ?: 'fab fa-wpforms';
1749 $generic_form_icon_color = sanitize_hex_color($postdata['genericformiconcolor'] ?? '') ?: '#f7fffb';
1750 $html .= '<div class="generic_form_button" id="generic_form_button_' . esc_attr($pano_suffix) . '">';
1751 $html .= '<div class="generic-form-icon" title ="Generic Form" id="generic_form_target_' . esc_attr($pano_suffix) . '"><i class="' . esc_attr($generic_form_icon) . '" style="color:' . esc_attr($generic_form_icon_color) . ';"></i></div>';
1752 $html .= '</div>';
1753
1754 // Generate the modal form container
1755 $html .= '<div class="wpvr-generic-form" id="wpvr-generic-form' . esc_attr($pano_suffix) . '" style="display: none">';
1756 $html .= '<span class="close-generic-form"><i class="fa fa-times"></i></span>';
1757 $html .= '<div class="generic-form-container">' . $shortcode_content . '</div>';
1758 $html .= '</div>';
1759 }
1760 //===Generic Form ends===//
1761
1762 //===Background Tour===//
1763 if (isset($postdata['bg_tour_enabler'])) {
1764
1765 $bg_tour_enabler = $postdata['bg_tour_enabler'];
1766 if ($bg_tour_enabler == 'on') {
1767 $bg_tour_navmenu = $postdata['bg_tour_navmenu'] ?? 'off';
1768 $bg_tour_title = $postdata['bg_tour_title'] ?? '';
1769 $bg_tour_subtitle = $postdata['bg_tour_subtitle'] ?? '';
1770
1771 if ($bg_tour_navmenu == 'on') {
1772 $menuLocations = get_nav_menu_locations();
1773 if (!empty($menuLocations['primary'])) {
1774 $menuID = $menuLocations['primary'];
1775 $primaryNav = wp_get_nav_menu_items($menuID);
1776 $html .= '<ul class="wpvr-navbar-container">';
1777 foreach ($primaryNav as $primaryNav_key => $primaryNav_value) {
1778 if ($primaryNav_value->menu_item_parent == "0") {
1779 $html .= '<li>';
1780 $html .= '<a href="' . $primaryNav_value->url . '">' . $primaryNav_value->title . '</a>';
1781 $html .= '<ul class="wpvr-navbar-dropdown">';
1782 foreach ($primaryNav as $pm_key => $pm_value) {
1783 if ($pm_value->menu_item_parent == $primaryNav_value->ID) {
1784 $html .= '<li>';
1785 $html .= '<a href="' . $pm_value->url . '">' . $pm_value->title . '</a>';
1786 $html .= '</li>';
1787 }
1788 }
1789 $html .= '</ul>';
1790 $html .= '</li>';
1791 }
1792 }
1793 $html .= '</ul>';
1794 }
1795 }
1796 if($is_pro && 'valid' == $status ){
1797 $html .= '<div class="wpvr-home-content">';
1798 $html .= '<div class="wpvr-home-title">' . $bg_tour_title . '</div>';
1799 $html .= '<div class="wpvr-home-subtitle">' . $bg_tour_subtitle . '</div>';
1800 $html .= '</div>';
1801 }
1802 }
1803 }
1804 //===Background Tour End===//
1805
1806 //===Custom Control===//
1807 if (isset($custom_control)) {
1808 $gyro_button_enabled = wpvr_isMobileDevice() && $custom_control['gyroSwitch'] == "on" && $custom_control['gyroscopeSwitch'] == "on";
1809 if ($custom_control['panZoomInSwitch'] == "on" || $custom_control['panZoomOutSwitch'] == "on" || $gyro_button_enabled || $custom_control['backToHomeSwitch'] == "on") {
1810 $html .= '<div id="zoom-in-out-controls' . $pano_suffix . '" class="zoom-in-out-controls">';
1811
1812 if ($custom_control['backToHomeSwitch'] == "on" && 'valid' == $status && $is_pro) {
1813 $html .= '<div class="ctrl" id="backToHome' . $pano_suffix . '"><i class="' . $custom_control['backToHomeIcon'] . '" style="color:' . $custom_control['backToHomeColor'] . ';"></i></div>';
1814 }
1815
1816 if ($custom_control['panZoomInSwitch'] == "on" && 'valid' == $status && $is_pro) {
1817 $html .= '<div class="ctrl" id="zoom-in' . $pano_suffix . '"><i class="' . $custom_control['panZoomInIcon'] . '" style="color:' . $custom_control['panZoomInColor'] . ';"></i></div>';
1818 }
1819
1820 if ($custom_control['panZoomOutSwitch'] == "on" && 'valid' == $status && $is_pro) {
1821 $html .= '<div class="ctrl" id="zoom-out' . $pano_suffix . '"><i class="' . $custom_control['panZoomOutIcon'] . '" style="color:' . $custom_control['panZoomOutColor'] . ';"></i></div>';
1822 }
1823 if ($gyro_button_enabled && 'valid' == $status && $is_pro) {
1824 $html .= '<div class="ctrl" id="gyroscope' . $pano_suffix . '" ><i class="' . $custom_control['gyroscopeIcon'] . '" style="color:' . $custom_control['gyroscopeColor'] . ';"></i></div>';
1825 }
1826 $html .= '</div>';
1827 }
1828 //===zoom in out Control===//
1829
1830 if (($custom_control['panupSwitch'] == "on" || $custom_control['panDownSwitch'] == "on" || $custom_control['panLeftSwitch'] == "on" || $custom_control['panRightSwitch'] == "on" || $custom_control['panFullscreenSwitch'] == "on" ) && 'valid' == $status && $is_pro) {
1831 //===Custom Control===//
1832 $html .= '<div class="controls" id="controls' . $pano_suffix . '">';
1833
1834 if ($custom_control['panupSwitch'] == "on") {
1835 $html .= '<div class="ctrl pan-up" id="pan-up' . $pano_suffix . '"><i class="' . $custom_control['panupIcon'] . '" style="color:' . $custom_control['panupColor'] . ';"></i></div>';
1836 }
1837
1838 if ($custom_control['panDownSwitch'] == "on") {
1839 $html .= '<div class="ctrl pan-down" id="pan-down' . $pano_suffix . '"><i class="' . $custom_control['panDownIcon'] . '" style="color:' . $custom_control['panDownColor'] . ';"></i></div>';
1840 }
1841
1842 if ($custom_control['panLeftSwitch'] == "on") {
1843 $html .= '<div class="ctrl pan-left" id="pan-left' . $pano_suffix . '"><i class="' . $custom_control['panLeftIcon'] . '" style="color:' . $custom_control['panLeftColor'] . ';"></i></div>';
1844 }
1845
1846 if ($custom_control['panRightSwitch'] == "on") {
1847 $html .= '<div class="ctrl pan-right" id="pan-right' . $pano_suffix . '"><i class="' . $custom_control['panRightIcon'] . '" style="color:' . $custom_control['panRightColor'] . ';"></i></div>';
1848 }
1849
1850 if ($custom_control['panFullscreenSwitch'] == "on") {
1851 $html .= '<div class="ctrl fullscreen" id="fullscreen' . $pano_suffix . '"><i class="' . $custom_control['panFullscreenIcon'] . '" style="color:' . $custom_control['panFullscreenColor'] . ';"></i></div>';
1852 }
1853 $html .= '</div>';
1854 }
1855 }
1856 //===Custom Control===//
1857
1858 //===explainer button===//
1859 $html .= wpvr_render_explainer_button(
1860 isset( $custom_control ) ? $custom_control : null,
1861 $postdata,
1862 $is_pro,
1863 $autoload,
1864 $explainer_right,
1865 $pano_suffix
1866 );
1867 //===explainer button end===//
1868
1869 //===Floor map button===//
1870 $status = get_option('wpvr_edd_license_status');
1871 $has_floor_plan = ( $status !== false && 'valid' == $status && $is_pro && 'on' == $floor_plan_enable && ! empty( $floor_plan_image ) );
1872 if ( $has_floor_plan ) {
1873 $html .= '<div class="floor_map_button" id="floor_map_button_' . $pano_suffix . '" style="right:'.$floor_map_right.'">';
1874 $html .= '<div class="ctrl" id="floor_map_target_' . $pano_suffix . '"><i class="fas fa-map" style="color:#f7fffb;"></i></div>';
1875 $html .= '</div>';
1876 }
1877 //===floor map button===//
1878
1879 if ($vrgallery && 'valid' == $status && $is_pro ) {
1880 //===Carousal setup===//
1881 $size = '';
1882 if($vrgallery_icon_size){
1883 $size = 'vrg-icon-size-large';
1884 }
1885 $html .= '<div id="vrgcontrols' . $pano_suffix . '" class="vrgcontrols">';
1886
1887 $html .= '<div class="vrgctrl' . $pano_suffix . ' vrbounce '.$size.'">';
1888 $html .= '</div>';
1889 $html .= '</div>';
1890
1891 $gallery_layout_class = isset($postdata['tourLayout']['layout']) && 'layout1' === $postdata['tourLayout']['layout']
1892 ? 'wpvr-gallery--modern'
1893 : 'wpvr-gallery--classic';
1894 $html .= '<div id="sccontrols' . $pano_suffix . '" class="scene-gallery vrowl-carousel ' . esc_attr($gallery_layout_class) . '">';
1895 if (isset($panodata["scene-list"])) {
1896 foreach ($panodata["scene-list"] as $panoscenes) {
1897 $scene_key = $panoscenes['scene-id'];
1898
1899 if ($vrgallery_title == 'on') {
1900 $scene_key_title = isset($panoscenes['scene-ititle']) ? sanitize_text_field($panoscenes['scene-ititle']) : '';
1901 } else {
1902 $scene_key_title = "";
1903 }
1904
1905 if ($panoscenes['scene-type'] == 'cubemap') {
1906 $img_src_url = $panoscenes['scene-attachment-url-face0'];
1907 } else {
1908 $img_src_url = $panoscenes['scene-attachment-url'];
1909 }
1910
1911 $src_to_id = attachment_url_to_postid($img_src_url);
1912 $thumbnail_array = wp_get_attachment_image_src($src_to_id, 'thumbnail');
1913 if ($thumbnail_array) {
1914 $thumbnail = $thumbnail_array[0];
1915 } else {
1916 $thumbnail = $img_src_url;
1917 }
1918
1919 if( isset($postdata['tourLayout']['layout']) && 'layout1' !== $postdata['tourLayout']['layout']) {
1920 $html .= '<ul><li title="Click to view scene"><span class="scene-title" title="' . esc_attr($scene_key_title) . '">' . $scene_key_title . '</span><img loading="lazy" class="scctrl" id="' . $scene_key . '_gallery_' . $pano_suffix . '" src="' . $thumbnail . '"></li></ul>';
1921 }else {
1922 $html .= '<ul><li title="Click to view scene"><img loading="lazy" class="scctrl" id="' . $scene_key . '_gallery_' . $pano_suffix . '" src="' . $thumbnail . '"><span class="scene-title" title="' . esc_attr($scene_key_title) . '">' . $scene_key_title . '</span></li></ul>';
1923 }
1924 }
1925 }
1926
1927 $html .= '</div>';
1928
1929 $html .= '
1930 <div class="wpvr_slider_nav">
1931 <button type="button" role="presentation" class="wpvr_owl_prev">
1932 <div class="nav-btn prev-slide"><i class="fa fa-angle-left"></i></div>
1933 </button>
1934 <button type="button" role="presentation" class="wpvr_owl_next">
1935 <div class="nav-btn next-slide"><i class="fa fa-angle-right"></i></div>
1936 </button>
1937 </div>
1938 ';
1939
1940 //===Carousal setup end===//
1941 }
1942
1943 //===Call TO action Button===//
1944 $bg_music = isset($postdata['bg_music']) ? $postdata['bg_music'] : 'off';
1945 $bg_music_url = isset($postdata['bg_music_url']) ? $postdata['bg_music_url'] : '';
1946 $autoplay_bg_music = isset($postdata['autoplay_bg_music']) ? $postdata['autoplay_bg_music'] : 'off';
1947 $loop_bg_music = isset($postdata['loop_bg_music']) ? $postdata['loop_bg_music'] : 'off';
1948
1949 $bg_loop = ($loop_bg_music === 'on') ? 'loop' : '';
1950 $autoplay_attr = ($autoplay_bg_music === 'on') ? 'autoplay' : '';
1951 $audio_muted_attr = ($autoplay_bg_music === 'on') ? 'muted' : '';
1952 $audio_icon_class = 'fa-volume-mute'; // Always start with mute icon
1953
1954 if ($bg_music === 'on' && 'valid' == $status && $is_pro) {
1955 $html .= '<div id="adcontrol' . esc_attr( $pano_suffix ) . '" class="adcontrol" style="right:' . esc_attr( $audio_right ) . '">';
1956 $html .= '<audio id="vrAudio' . esc_attr($pano_suffix) . '" class="vrAudioDefault" data-autoplay="' . esc_attr($autoplay_bg_music) . '" onended="audionEnd' . esc_attr($pano_suffix) . '()" ' . $autoplay_attr . ' ' . $audio_muted_attr . ' ' . $bg_loop . '>
1957 <source src="' . esc_url($bg_music_url) . '" type="audio/mpeg">
1958 Your browser does not support the audio element.
1959 </audio>';
1960 $html .= '<button onclick="playPause' . esc_attr($pano_suffix) . '()" class="ctrl audio_control" id="audio_control' . esc_attr($pano_suffix) . '">
1961 <i id="vr-volume' . esc_attr($pano_suffix) . '" class="wpvrvolumeicon' . esc_attr($pano_suffix) . ' fas ' . esc_attr($audio_icon_class) . '" style="color:#fff;"></i>
1962 </button>';
1963 $html .= '</div>';
1964 }
1965 //===Explainer video section===//
1966 $explainerContent = "";
1967 if (isset($postdata['explainerContent'])) {
1968 $explainerContent = $this->wpvr_sanitize_iframe_only($postdata['explainerContent']);
1969 }
1970 $html .= '<div class="explainer" id="explainer' . $pano_suffix . '" style="display: none">';
1971 $html .= '<span class="close-explainer-video"><i class="fa fa-times"></i></span>';
1972 $html .= '' . $explainerContent . '';
1973 $html .= '</div>';
1974 //===Explainer video section End===//
1975
1976 //===Scene navigation Control===//
1977 if (isset($postdata['scene_navigation']) && $postdata['scene_navigation'] === 'on' && 'valid' == $status && $is_pro) {
1978 $scene_navigation_nav_class = 'custom-scene-navigation-nav' . ( $is_classic_layout ? ' wpvr-scene-navigation-nav--classic' : '' );
1979 $html .= '<style>
1980 #et-boc .et-l .pnlm-controls-container,
1981 .pnlm-controls-container{
1982 top: 33px;
1983 }
1984
1985 #et-boc .et-l .zoom-in-out-controls,
1986 .zoom-in-out-controls {
1987 top: 37px;
1988 }
1989 </style>';
1990 $html .= '<div id="custom-scene-navigation' . $pano_suffix . '" class="custom-scene-navigation">
1991 <span class="hamburger-menu"><svg width="16" height="10" fill="none" viewBox="0 0 22 15" xmlns="http://www.w3.org/2000/svg"><rect width="21.177" height="2.647" fill="#f7fffb" rx="1.324"/><rect width="21.177" height="2.647" y="6.177" fill="#f7fffb" rx="1.324"/><rect width="21.177" height="2.647" y="12.352" fill="#f7fffb" rx="1.324"/></svg></span>
1992 </div>
1993
1994 <div id="custom-scene-navigation-nav' . $pano_suffix . '" class="' . esc_attr( $scene_navigation_nav_class ) . '">
1995 <ul></ul>
1996 </div>
1997 ';
1998 }
1999 //===Scene navigation Control===//
2000
2001
2002 if( 'embed' === $width){
2003 if(WPVR_Helper::is_enable_social_share($postdata) === 'on'){
2004 $html .= '<div id="wpvr-social-share-bg-box'.$pano_suffix.'" class="wpvr-social-share-bg-box" style="top:'.$social_logo_top.'">
2005 <span class="share-btn-svg"><svg fill="none" viewBox="0 0 24 24" width="24" height="24" ><path fill="#1F1CF4" d="M18.4 2.4a3.2 3.2 0 00-3.2 3.2 3.2 3.2 0 00.075.67L8.01 9.901A3.2 3.2 0 005.6 8.8a3.2 3.2 0 101.325 6.112 3.2 3.2 0 001.086-.812l7.261 3.632a3.2 3.2 0 101.803-2.242c-.415.189-.786.466-1.085.81l-7.261-3.63A3.2 3.2 0 008.8 12a3.2 3.2 0 00-.075-.667L15.991 7.7a3.2 3.2 0 002.41 1.1 3.2 3.2 0 100-6.4z"/></svg></span>
2006 <nav class="wpvr-share-nav">
2007 '.WPVR_Helper::social_media_share_links_display_in_embed(home_url().'/?embed_page='. $id).'
2008 </nav>
2009 </div>';
2010 }
2011 }
2012 //===Floor plan section===//
2013 if ( $has_floor_plan ) {
2014 $floor_map_image = $floor_plan_image;
2015 $floor_map_pointer = isset($postdata['floor_plan_pointer_position']) && is_array($postdata['floor_plan_pointer_position']) ? $postdata['floor_plan_pointer_position'] : array();
2016 $floor_map_scene_id = isset($postdata['floor_plan_data_list']) && is_array($postdata['floor_plan_data_list']) ? $postdata['floor_plan_data_list'] : array();
2017 $floor_plan_custom_color = isset($postdata['floor_plan_custom_color']) && ! empty($postdata['floor_plan_custom_color']) ? $postdata['floor_plan_custom_color'] : '#cca92c';
2018 $floor_plan_direction_indicator = isset($postdata['floor_plan_direction_indicator']) ? $postdata['floor_plan_direction_indicator'] : 'on';
2019
2020 $media_alt = '';
2021 $attachment_id = attachment_url_to_postid( $floor_map_image );
2022
2023 if ( $attachment_id ) {
2024 $media_alt = sanitize_text_field( get_post_meta( $attachment_id, '_wp_attachment_image_alt', true ) );
2025 }
2026
2027 if ( ! empty( $media_alt ) ) {
2028 $floor_map_alt = $media_alt;
2029 } else {
2030 $tour_title = sanitize_text_field( get_the_title( $id ) );
2031
2032 $floor_map_alt = ! empty( $tour_title )
2033 /* translators: %s: tour title */
2034 ? sprintf( __( '%s - Floor Plan', 'wpvr' ), $tour_title )
2035 : __( 'Floor Plan', 'wpvr' );
2036 }
2037
2038 $html .= '<div class="wpvr-floor-map" id="wpvr-floor-map' . $pano_suffix . '" style="display: none">';
2039 $html .= '<span class="close-floor-map-plan"><i class="fa fa-times"></i></span>';
2040 $html .= '<img loading="lazy" src="' . esc_url( $floor_map_image ) . '" alt="' . esc_attr( $floor_map_alt ) . '">';
2041 foreach ( $floor_map_pointer as $key => $pointer_position ) {
2042 $pointer_id = '';
2043 $data_top = '';
2044 $data_left = '';
2045 $style = '';
2046
2047 if ( is_object( $pointer_position ) ) {
2048 $pointer_id = isset( $pointer_position->id ) ? (string) $pointer_position->id : '';
2049 $data_top = isset( $pointer_position->data_top ) ? (string) $pointer_position->data_top : '';
2050 $data_left = isset( $pointer_position->data_left ) ? (string) $pointer_position->data_left : '';
2051 $style = isset( $pointer_position->style ) ? (string) $pointer_position->style : '';
2052 } elseif ( is_array( $pointer_position ) ) {
2053 $pointer_id = isset( $pointer_position['id'] ) ? (string) $pointer_position['id'] : '';
2054 $data_top = isset( $pointer_position['data_top'] ) ? (string) $pointer_position['data_top'] : '';
2055 $data_left = isset( $pointer_position['data_left'] ) ? (string) $pointer_position['data_left'] : '';
2056 $style = isset( $pointer_position['style'] ) ? (string) $pointer_position['style'] : '';
2057 }
2058
2059 $scene_id_val = '';
2060 if ( isset( $floor_map_scene_id[ $key ] ) ) {
2061 $scene_item = $floor_map_scene_id[ $key ];
2062 if ( is_object( $scene_item ) && isset( $scene_item->value ) ) {
2063 $scene_id_val = (string) $scene_item->value;
2064 } elseif ( is_array( $scene_item ) && isset( $scene_item['value'] ) ) {
2065 $scene_id_val = (string) $scene_item['value'];
2066 } elseif ( is_scalar( $scene_item ) ) {
2067 $scene_id_val = (string) $scene_item;
2068 }
2069 }
2070
2071 $html .= '<div class="floor-plan-pointer ui-draggable ui-draggable-handle" scene_id="' . esc_attr( $scene_id_val ) . '" id="' . esc_attr( $pointer_id ) . '" data-top="' . esc_attr( $data_top ) . '" data-left="' . esc_attr( $data_left ) . '" style="' . esc_attr( $style ) . '">
2072 <svg class="floor-pointer-circle" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
2073 <circle cx="12" cy="12" r="11.5" stroke="' . esc_attr( $floor_plan_custom_color ) . '"/>
2074 <circle cx="12" cy="12" r="5" fill="' . esc_attr( $foreground_color_pointer ) . '"/>
2075 </svg>';
2076
2077 // Only add the floor pointer flash SVG if floor_plan_direction_indicator is "on"
2078 if ( $floor_plan_direction_indicator === 'on' ) {
2079 $html .= '<svg class="floor-pointer-flash" width="54" height="35" viewBox="0 0 54 35" fill="none" xmlns="http://www.w3.org/2000/svg">
2080 <path d="M0.454054 1.32433L11.7683 34.3243C11.9069 34.7285 12.287 35 12.7143 35H41.2857C41.713 35 42.0931 34.7285 42.2317 34.3243L53.5459 1.32432C53.7685 0.675257 53.2862 0 52.6 0H1.4C0.713843 0 0.231517 0.675258 0.454054 1.32433Z" fill="url(#paint0_linear_1_10)"/>
2081 <defs>
2082 <linearGradient id="paint0_linear_1_10" x1="27" y1="4.59807e-08" x2="26.5" y2="28" gradientUnits="userSpaceOnUse">
2083 <stop stop-color="' . esc_attr( $floor_plan_custom_color ) . '" stop-opacity="0"/>
2084 <stop offset="1" stop-color="' . esc_attr( $floor_plan_custom_color ) . '"/>
2085 </linearGradient>
2086 </defs>
2087 </svg>';
2088 }
2089 $html .= '</div>';
2090 }
2091 $html .= '</div>';
2092 }
2093 //===Floor plan section===//
2094
2095 $html .= '<div class="wpvr-hotspot-tweak-contents-wrapper" style="display: none">';
2096 $html .= '<i class="fa fa-times cross" data-id="' . $id . '"></i>';
2097 $html .= '<div class="wpvr-hotspot-tweak-contents-flex">';
2098 $html .= '<div class="wpvr-hotspot-tweak-contents">';
2099 ob_start();
2100 do_action('wpvr_hotspot_tweak_contents', $scene_data);
2101 $hotspot_content = ob_get_clean();
2102 $html .= $hotspot_content;
2103 $html .= '</div>';
2104 $html .= '</div>';
2105 $html .= '</div>';
2106
2107 $html .= '<div class="custom-ifram-wrapper" style="display: none;">';
2108 $html .= '<i class="fa fa-times cross" data-id="' . $id . '"></i>';
2109
2110 $html .= '<div class="custom-ifram-flex">';
2111 $html .= '<div class="custom-ifram">';
2112 $html .= '</div>';
2113 $html .= '</div>';
2114 $html .= '</div>';
2115
2116 $html .= '</div>';
2117 $html .= '</div>';
2118 if( "embed" == $width ){
2119 $html .= '</div>';
2120 }
2121
2122
2123 if ($status !== false && 'valid' == $status && $is_pro) {
2124 $call_to_action = isset($postdata['calltoaction']) ? $postdata['calltoaction'] : 'off';
2125 if( 'on' == $call_to_action){
2126 $buttontext = isset($postdata['buttontext']) ? $postdata['buttontext'] : '';
2127 $buttonurl = isset($postdata['buttonurl']) ? $postdata['buttonurl'] : '';
2128 $cta_btn_style = isset($postdata['button_configuration']) ? $postdata['button_configuration'] : array();
2129
2130 $button_open_new_tab = isset($cta_btn_style['button_open_new_tab']) ? $cta_btn_style['button_open_new_tab'] : "off";
2131 $target = '_self';
2132 $button_position = isset($cta_btn_style['button_position']) ? $cta_btn_style['button_position'] : "";
2133 $background_color = isset($cta_btn_style['button_background_color']) ? $cta_btn_style['button_background_color'] : "";
2134 $color = isset($cta_btn_style['button_font_color']) ? $cta_btn_style['button_font_color'] : "";
2135 $font_size = isset($cta_btn_style['button_font_size']) ? $cta_btn_style['button_font_size'] : "";
2136 $font_weight = isset($cta_btn_style['button_font_weight']) ? $cta_btn_style['button_font_weight'] : "";
2137 $text_align = isset($cta_btn_style['button_alignment']) ? $cta_btn_style['button_alignment'] : "";
2138 $text_transform = isset($cta_btn_style['button_transform']) ? $cta_btn_style['button_transform'] : "";
2139 $font_style = isset($cta_btn_style['button_text_style']) ? $cta_btn_style['button_text_style'] : "";
2140 $text_decoration = isset($cta_btn_style['button_text_decoration']) ? $cta_btn_style['button_text_decoration'] : "";
2141 $line_height = isset($cta_btn_style['button_line_height']) ? $cta_btn_style['button_line_height'] : "";
2142 $letter_spacing = isset($cta_btn_style['button_letter_spacing']) ? $cta_btn_style['button_letter_spacing'] : "";
2143 $word_spacing = isset($cta_btn_style['button_word_spacing']) ? $cta_btn_style['button_word_spacing'] : "";
2144
2145 $border_width = isset($cta_btn_style['button_border_width']) ? $cta_btn_style['button_border_width'] : "";
2146 $border_style = isset($cta_btn_style['button_border_style']) ? $cta_btn_style['button_border_style'] : "";
2147 $border_color = isset($cta_btn_style['button_border_color']) ? $cta_btn_style['button_border_color'] : "";
2148 $border_radius = isset($cta_btn_style['button_border_radius']) ? $cta_btn_style['button_border_radius'] : "";
2149
2150 $button_pt = isset($cta_btn_style['button_pt']) ? $cta_btn_style['button_pt'] : "";
2151 $button_pr = isset($cta_btn_style['button_pr']) ? $cta_btn_style['button_pr'] : "";
2152 $button_pb = isset($cta_btn_style['button_pb']) ? $cta_btn_style['button_pb'] : "";
2153 $button_pl = isset($cta_btn_style['button_pl']) ? $cta_btn_style['button_pl'] : "";
2154
2155 if($button_open_new_tab == 'on'){
2156 $target = '_blank';
2157 }
2158 $style = 'background-color: '.$background_color.';
2159 color: '.$color.';
2160 font-size: '.$font_size.'px;
2161 font-weight: '.$font_weight.';
2162 text-align: center;
2163 display: inline-block;
2164 text-transform: '.$text_transform.';
2165 font-style: '.$font_style.';
2166 text-decoration: '.$text_decoration.';
2167 line-height: '.$line_height.';
2168 letter-spacing: '.$letter_spacing.'px;
2169 word-spacing: '.$word_spacing.'px;
2170 border: '.$border_width.'px '.$border_style.' '.$border_color.';
2171 border-radius: '.$border_radius.'px;
2172 padding: '.$button_pt.'px '.$button_pr.'px '.$button_pb.'px '.$button_pl.'px;
2173 ';
2174 $cta_width = ( $width === 'fullwidth' || $width === 'embed' ) ? '100%' : $width;
2175 $html .= '<div class="wpvr-call-to-action-button position-'.$text_align.'" style="max-width:' . $cta_width . '">
2176 <a href="'.$buttonurl.'" style="'.$style.'" target="'.$target.'">'.$buttontext.'</a>
2177 </div>';
2178
2179 }
2180 }
2181
2182
2183 //script started
2184 $html .= '<script>';
2185 if (isset($postdata['bg_music']) && $bg_music == 'on' && 'valid' == $status && $is_pro) {
2186 $html .= '
2187 var x' . $pano_suffix . ' = document.getElementById("vrAudio' . $pano_suffix . '");
2188 var playing' . $pano_suffix . ' = false;
2189 var autoplaySupported' . $pano_suffix . ' = false;
2190 var alertShown' . $pano_suffix . ' = false;
2191 var autoplayChecked' . $pano_suffix . ' = false;
2192
2193 function playPause' . $pano_suffix . '() {
2194 if (playing' . $pano_suffix . ') {
2195 jQuery("#vr-volume' . $pano_suffix . '").removeClass("fas fa-volume-up").addClass("fas fa-volume-mute");
2196 x' . $pano_suffix . '.pause();
2197 jQuery("#audio_control' . $pano_suffix . '").attr("data-play", "off");
2198 playing' . $pano_suffix . ' = false;
2199 } else {
2200 x' . $pano_suffix . '.muted = false;
2201 x' . $pano_suffix . '.play().then(function() {
2202 jQuery("#vr-volume' . $pano_suffix . '").removeClass("fas fa-volume-mute").addClass("fas fa-volume-up");
2203 jQuery("#audio_control' . $pano_suffix . '").attr("data-play", "on");
2204 playing' . $pano_suffix . ' = true;
2205 }).catch(function(e) {
2206 console.log("Play failed:", e);
2207 });
2208 }
2209 }
2210
2211 function audionEnd' . $pano_suffix . '() {
2212 playing' . $pano_suffix . ' = false;
2213 jQuery("#vr-volume' . $pano_suffix . '").removeClass("fas fa-volume-up").addClass("fas fa-volume-mute");
2214 jQuery("#audio_control' . $pano_suffix . '").attr("data-play", "off");
2215 }
2216
2217 x' . $pano_suffix . '.addEventListener("ended", audionEnd' . $pano_suffix . ');';
2218
2219 if ($autoplay_bg_music == 'on') {
2220 $html .= '
2221
2222 x' . $pano_suffix . '.addEventListener("loadeddata", function() {
2223 if (!autoplayChecked' . $pano_suffix . ') {
2224 checkAutoplayStatus' . $pano_suffix . '();
2225 }
2226 });
2227
2228 x' . $pano_suffix . '.addEventListener("canplay", function() {
2229 if (!autoplayChecked' . $pano_suffix . ') {
2230 checkAutoplayStatus' . $pano_suffix . '();
2231 }
2232 });
2233
2234 x' . $pano_suffix . '.addEventListener("canplaythrough", function() {
2235 if (!autoplayChecked' . $pano_suffix . ') {
2236 checkAutoplayStatus' . $pano_suffix . '();
2237 }
2238 });
2239
2240 setTimeout(function() {
2241 if (!autoplayChecked' . $pano_suffix . ') {
2242 checkAutoplayStatus' . $pano_suffix . '();
2243 }
2244 }, 1000);
2245
2246 x' . $pano_suffix . '.addEventListener("play", function() {
2247 jQuery("#vr-volume' . $pano_suffix . '").removeClass("fas fa-volume-mute").addClass("fas fa-volume-up");
2248 jQuery("#audio_control' . $pano_suffix . '").attr("data-play", "on");
2249 playing' . $pano_suffix . ' = true;
2250 });
2251
2252 x' . $pano_suffix . '.addEventListener("pause", function() {
2253 if (!playing' . $pano_suffix . ') {
2254 jQuery("#vr-volume' . $pano_suffix . '").removeClass("fas fa-volume-up").addClass("fas fa-volume-mute");
2255 jQuery("#audio_control' . $pano_suffix . '").attr("data-play", "off");
2256 }
2257 });
2258
2259 function checkAutoplayStatus' . $pano_suffix . '() {
2260 autoplayChecked' . $pano_suffix . ' = true;
2261
2262 x' . $pano_suffix . '.muted = true;
2263 var playPromise = x' . $pano_suffix . '.play();
2264
2265 if (playPromise !== undefined) {
2266 playPromise.then(function () {
2267 if (x' . $pano_suffix . '.muted || x' . $pano_suffix . '.volume === 0) {
2268 handleAutoplayBlocked' . $pano_suffix . '();
2269 } else {
2270 autoplaySupported' . $pano_suffix . ' = true;
2271 jQuery("#vr-volume' . $pano_suffix . '").removeClass("fas fa-volume-mute").addClass("fas fa-volume-up");
2272 jQuery("#audio_control' . $pano_suffix . '").attr("data-play", "on");
2273 playing' . $pano_suffix . ' = true;
2274 }
2275 }).catch(function () {
2276 handleAutoplayBlocked' . $pano_suffix . '();
2277 });
2278 } else {
2279 setTimeout(function () {
2280 if (x' . $pano_suffix . '.paused || x' . $pano_suffix . '.currentTime === 0) {
2281 handleAutoplayBlocked' . $pano_suffix . '();
2282 } else {
2283 autoplaySupported' . $pano_suffix . ' = true;
2284 jQuery("#vr-volume' . $pano_suffix . '").removeClass("fas fa-volume-mute").addClass("fas fa-volume-up");
2285 jQuery("#audio_control' . $pano_suffix . '").attr("data-play", "on");
2286 playing' . $pano_suffix . ' = true;
2287 }
2288 }, 300);
2289 }
2290 }
2291
2292 function handleAutoplayBlocked' . $pano_suffix . '() {
2293 autoplaySupported' . $pano_suffix . ' = false;
2294 if (!alertShown' . $pano_suffix . ') {
2295 alert("Autoplay is not supported in your browser. Please click the audio button to play music.");
2296 alertShown' . $pano_suffix . ' = true;
2297 }
2298
2299 x' . $pano_suffix . '.pause();
2300 x' . $pano_suffix . '.currentTime = 0;
2301 x' . $pano_suffix . '.muted = true;
2302
2303 jQuery("#vr-volume' . $pano_suffix . '").removeClass("fas fa-volume-up").addClass("fas fa-volume-mute");
2304 jQuery("#audio_control' . $pano_suffix . '").attr("data-play", "off");
2305
2306 var musicTriggerElem = document.getElementById("' . $panoid . '");
2307 if (musicTriggerElem) {
2308 musicTriggerElem.addEventListener("click", musicPlay' . $pano_suffix . ');
2309 }
2310 document.addEventListener("touchstart", musicPlay' . $pano_suffix . ', { once: true });
2311 document.addEventListener("click", musicPlay' . $pano_suffix . ', { once: true });
2312 }
2313
2314 function musicPlay' . $pano_suffix . '() {
2315 x' . $pano_suffix . '.muted = false;
2316 var playPromise = x' . $pano_suffix . '.play();
2317
2318 if (playPromise !== undefined) {
2319 playPromise.then(function () {
2320 jQuery("#vr-volume' . $pano_suffix . '").removeClass("fas fa-volume-mute").addClass("fas fa-volume-up");
2321 jQuery("#audio_control' . $pano_suffix . '").attr("data-play", "on");
2322 playing' . $pano_suffix . ' = true;
2323 }).catch(function(e) {
2324 console.log("Play failed:", e);
2325 });
2326 } else {
2327 setTimeout(function () {
2328 if (!x' . $pano_suffix . '.paused) {
2329 jQuery("#vr-volume' . $pano_suffix . '").removeClass("fas fa-volume-mute").addClass("fas fa-volume-up");
2330 jQuery("#audio_control' . $pano_suffix . '").attr("data-play", "on");
2331 playing' . $pano_suffix . ' = true;
2332 }
2333 }, 100);
2334 }
2335
2336 var musicTriggerElem = document.getElementById("' . $panoid . '");
2337 if (musicTriggerElem) {
2338 musicTriggerElem.removeEventListener("click", musicPlay' . $pano_suffix . ');
2339 }
2340 document.removeEventListener("touchstart", musicPlay' . $pano_suffix . ');
2341 document.removeEventListener("click", musicPlay' . $pano_suffix . ');
2342 }
2343 ';
2344 }
2345 }
2346 $html .= '(function ($) {';
2347 $html .= 'jQuery(document).ready(function() {';
2348 $html .= 'var response = ' . $response . ';';
2349 $html .= 'var scenes = response[1];';
2350 $html .= 'function wpvrResolveDevicePanorama(scenesConfig) {';
2351 $html .= ' if (!scenesConfig || !scenesConfig.scenes) return;';
2352 $html .= ' var isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) || (navigator.platform === "MacIntel" && navigator.maxTouchPoints > 1);';
2353 $html .= ' var isSmallScreen = (window.innerWidth <= 768);';
2354 $html .= ' if (typeof window.wpvrMaxTexture === "undefined") {';
2355 $html .= ' window.wpvrMaxTexture = 16384;';
2356 $html .= ' try {';
2357 $html .= ' var testCanvas = document.createElement("canvas");';
2358 $html .= ' var gl = testCanvas.getContext("webgl") || testCanvas.getContext("experimental-webgl");';
2359 $html .= ' if (gl) {';
2360 $html .= ' window.wpvrMaxTexture = gl.getParameter(gl.MAX_TEXTURE_SIZE) || 16384;';
2361 $html .= ' var ext = gl.getExtension("WEBGL_lose_context");';
2362 $html .= ' if (ext) { ext.loseContext(); }';
2363 $html .= ' }';
2364 $html .= ' } catch (e) {}';
2365 $html .= ' }';
2366 $html .= ' var maxTexture = window.wpvrMaxTexture;';
2367 $html .= ' for (var scId in scenesConfig.scenes) {';
2368 $html .= ' if (!scenesConfig.scenes.hasOwnProperty(scId)) continue;';
2369 $html .= ' var sc = scenesConfig.scenes[scId];';
2370 $html .= ' if (!sc) continue;';
2371 $html .= ' var exceedsGpu = sc.desktop_width && (sc.desktop_width > maxTexture);';
2372 $html .= ' if (isMobile || isSmallScreen || exceedsGpu) {';
2373 $html .= ' if (sc.mobile_panorama) {';
2374 $html .= ' sc.panorama = sc.mobile_panorama;';
2375 $html .= ' }';
2376 $html .= ' } else if (sc.desktop_panorama) {';
2377 $html .= ' sc.panorama = sc.desktop_panorama;';
2378 $html .= ' }';
2379 $html .= ' }';
2380 $html .= '}';
2381 $html .= 'wpvrResolveDevicePanorama(scenes);';
2382 $html .= 'if(scenes) {';
2383 $html .= 'var scenedata = scenes.scenes;';
2384 $html .= 'for(var scId in scenedata) {';
2385 $html .= 'if(!scenedata.hasOwnProperty(scId)) continue;';
2386 $html .= 'var scenehotspot = scenedata[scId].hotSpots;';
2387 $html .= 'if(scenehotspot && scenehotspot.length) {';
2388 $html .= 'for(var hIdx = 0; hIdx < scenehotspot.length; hIdx++) {';
2389 $html .= 'if(scenehotspot[hIdx].type === "info") {';
2390 $html .= ' scenehotspot[hIdx]["clickHandlerFunc"] = function(div, args) { if (typeof window.wpvrhotspot === "function") { window.wpvrhotspot(div, args); } };';
2391 $html .= '} else if(scenehotspot[hIdx].type === "scene") {';
2392 $html .= ' scenehotspot[hIdx]["clickHandlerArgs"] = scenehotspot[hIdx]["text"] || "";';
2393 $status = get_option('wpvr_edd_license_status');
2394 if ($status !== false && $status == 'valid') {
2395 $html .='if(typeof wpvr_public !== "undefined") {';
2396 $html .='if(wpvr_public.is_pro_active) {';
2397 $html .= ' scenehotspot[hIdx]["clickHandlerFunc"] = function(div, args) { if (typeof wpvrhotspotscene' . $pano_suffix . ' === "function") { wpvrhotspotscene' . $pano_suffix . '(div, args); } else if (typeof wpvrhotspotscene === "function") { wpvrhotspotscene(div, args); } else if (typeof window.wpvrhotspotscene === "function") { window.wpvrhotspotscene(div, args); } };';
2398 $html .='}';
2399 $html .='}';
2400 }
2401 $html .= '}';
2402
2403 $html .= 'if(scenehotspot[hIdx].hotspot_type === "sticker" || scenehotspot[hIdx].type === "sticker" || scenehotspot[hIdx].stickerTemplate) {';
2404 $html .= ' (function(hs) {';
2405 $html .= ' hs["createTooltipFunc"] = function(div) {';
2406 $html .= ' if (typeof window.wpvrRenderStickerHotspot === "function") {';
2407 $html .= ' window.wpvrRenderStickerHotspot(div, hs);';
2408 $html .= ' }';
2409 $html .= ' };';
2410 $html .= ' })(scenehotspot[hIdx]);';
2411 $html .= '}';
2412
2413 if (wpvr_isMobileDevice() && get_option('dis_on_hover') == "true") {
2414 } else {
2415 $html .= 'else if(scenehotspot[hIdx]["createTooltipArgs"] != "") {';
2416 $html .= ' scenehotspot[hIdx]["createTooltipFunc"] = function(div, args) { if (typeof window.wpvrtooltip === "function") { window.wpvrtooltip(div, args); } };';
2417 $html .= '}';
2418 }
2419
2420 $html .= '}';
2421 $html .= '}';
2422 $html .= '}';
2423 $html .= '}';
2424 $html .= 'var panoshow' . $pano_suffix . ';';
2425 $html .= 'var panoshow2' . $pano_suffix . ';';
2426 $html .= 'function initWPVRViewer' . $pano_suffix . '() {';
2427 $html .= 'if (typeof pannellum === "undefined" || typeof jQuery === "undefined") { setTimeout(initWPVRViewer' . $pano_suffix . ', 50); return; }';
2428 $html .= 'panoshow' . $pano_suffix . ' = pannellum.viewer(response[0]["panoid"], scenes);';
2429 $html .= '
2430 window.wpvrViewers = window.wpvrViewers || {};
2431 window.wpvrViewers[response[0]["panoid"]] = panoshow' . $pano_suffix . ';
2432 document.dispatchEvent(new CustomEvent("wpvr:viewer-ready", {
2433 detail: { containerId: response[0]["panoid"], viewer: panoshow' . $pano_suffix . ' }
2434 }));
2435 ';
2436 if ( (float) $scene_fade_duration > 0 ) {
2437 $html .= '
2438 panoshow' . $pano_suffix . '.on("scenechange", function() {
2439 var fadeImage = document.querySelector("#' . $panoid . ' .pnlm-render-container > .pnlm-fade-img");
2440 if (fadeImage) {
2441 fadeImage.style.opacity = "1";
2442 void fadeImage.offsetWidth;
2443 }
2444 });';
2445 }
2446 $html .= '
2447
2448 if(typeof wpvr_public === "undefined" || !wpvr_public.is_pro_active || !wpvr_public.is_license_active) {
2449 panoshow' . $pano_suffix . '.on("load", function() {
2450 jQuery(".pnlm-panorama-info").hide();
2451 jQuery(".pnlm-compass").hide();
2452 });
2453
2454 panoshow' . $pano_suffix . '.on("scenechange", function() {
2455 jQuery(".pnlm-panorama-info").hide();
2456 jQuery(".pnlm-compass").hide();
2457 });
2458 }';
2459 $html .= '}';
2460 $html .= 'initWPVRViewer' . $pano_suffix . '();';
2461 //===Dplicate mode only for vr mode===//
2462 $response2 = json_decode($response);
2463 $response2[1]->compass = false;
2464 $response2[1]->autoRotate = false;
2465 $response = json_encode($response2);
2466 $html .= 'var response_duplicate = ' . $response . ';';
2467 $html .= 'var scenes_duplicate = response_duplicate[1];';
2468 $html .= 'wpvrResolveDevicePanorama(scenes_duplicate);';
2469
2470 $html .= 'if(scenes_duplicate) {';
2471 $html .= 'var scenedata = scenes_duplicate.scenes;';
2472 $html .= 'for(var scId in scenedata) {';
2473 $html .= 'if(!scenedata.hasOwnProperty(scId)) continue;';
2474 $html .= 'var scenehotspot = scenedata[scId].hotSpots;';
2475 $html .= 'if(scenehotspot && scenehotspot.length) {';
2476 $html .= 'for(var hIdx = 0; hIdx < scenehotspot.length; hIdx++) {';
2477 $html .= 'if(scenehotspot[hIdx]["clickHandlerArgs"] != "") {';
2478 $html .= 'scenehotspot[hIdx]["clickHandlerFunc"] = function(div, args) { if (typeof window.wpvrhotspot === "function") { window.wpvrhotspot(div, args); } };';
2479 $html .= '}';
2480 $html .= 'if(scenehotspot[hIdx].hotspot_type === "sticker" || scenehotspot[hIdx].type === "sticker" || scenehotspot[hIdx].stickerTemplate) {';
2481 $html .= ' (function(hs) {';
2482 $html .= ' hs["createTooltipFunc"] = function(div) {';
2483 $html .= ' if (typeof window.wpvrRenderStickerHotspot === "function") {';
2484 $html .= ' window.wpvrRenderStickerHotspot(div, hs);';
2485 $html .= ' }';
2486 $html .= ' };';
2487 $html .= ' })(scenehotspot[hIdx]);';
2488 $html .= '}';
2489
2490 if (wpvr_isMobileDevice() && get_option('dis_on_hover') == "true") {
2491 } else {
2492 $html .= 'else if(scenehotspot[hIdx]["createTooltipArgs"] != "") {';
2493 $html .= ' scenehotspot[hIdx]["createTooltipFunc"] = function(div, args) { if (typeof window.wpvrtooltip === "function") { window.wpvrtooltip(div, args); } };';
2494 $html .= '}';
2495 }
2496 $html .= '}';
2497 $html .= '}';
2498 $html .= '}';
2499 $html .= '}';
2500
2501 $is_pro = apply_filters('is_wpvr_pro_active',false);
2502 $status = get_option('wpvr_edd_license_status');
2503 $html .= 'var vr_mode = "off";';
2504 if ($status !== false && 'valid' == $status && $is_pro) {
2505 $html .= 'function initWPVRViewer2' . $pano_suffix . '() {';
2506 $html .= 'if (typeof pannellum === "undefined" || typeof jQuery === "undefined") { setTimeout(initWPVRViewer2' . $pano_suffix . ', 50); return; }';
2507 $html .= 'panoshow2' . $pano_suffix . ' = pannellum.viewer("' . $panoid2 . '", scenes_duplicate);';
2508 $html .= '
2509 window.wpvrViewers = window.wpvrViewers || {};
2510 window.wpvrViewers["' . $panoid2 . '"] = panoshow2' . $pano_suffix . ';
2511 document.dispatchEvent(new CustomEvent("wpvr:viewer-ready", {
2512 detail: { containerId: "' . $panoid2 . '", viewer: panoshow2' . $pano_suffix . ' }
2513 }));
2514 ';
2515 $html .= '}';
2516 $html .= 'initWPVRViewer2' . $pano_suffix . '();';
2517 // Show Cardboard Mode in Tour
2518 $html .= '
2519 var tim;
2520 var im = 0;
2521 var active_scene = "'.$default_scene.'";
2522 var c_time;
2523 c_time = new Date();
2524 var timer = c_time.getTime() + 2000;
2525 function panoShowCardBoardOnTrigger(data){
2526 if(scenes_duplicate) {
2527 var scenedata = scenes_duplicate.scenes;
2528 for(var i in scenedata) {
2529 if(active_scene === i) {
2530 var scenehotspot = scenedata[i].hotSpots;
2531 if(scenehotspot && scenehotspot.length) {
2532 for(var j = 0; j < scenehotspot.length; j++) {
2533 var plusFiveYaw = Math.round(scenehotspot[j].yaw) + 5;
2534 var minusFiveYaw = Math.round(scenehotspot[j].yaw) - 5;
2535 var plusFivePitch = Math.round(scenehotspot[j].pitch) + 5;
2536 var minusFivePitch = Math.round(scenehotspot[j].pitch) - 5;
2537 if(Math.round(data.pitch) > minusFivePitch) {
2538 if(Math.round(data.pitch) < plusFivePitch) {
2539 if(Math.round(data.yaw) > minusFiveYaw) {
2540 if(Math.round(data.yaw) < plusFiveYaw) {
2541 jQuery(".center-pointer").addClass("wpvr-pluse-effect");
2542 var getScene = scenehotspot[j].sceneId;
2543 if(scenehotspot[j].type == "scene"){
2544 panoshow' . $pano_suffix . '.loadScene(getScene);
2545 panoshow2' . $pano_suffix . '.loadScene(getScene);
2546 }else{
2547 jQuery(".center-pointer").removeClass("wpvr-pluse-effect");
2548 }
2549 } else {
2550 jQuery(".center-pointer").removeClass("wpvr-pluse-effect");
2551 c_time = new Date();
2552 timer = c_time.getTime() + 2000;
2553 }
2554 } else {
2555 jQuery(".center-pointer").removeClass("wpvr-pluse-effect");
2556 c_time = new Date();
2557 timer = c_time.getTime() + 2000;
2558 }
2559 } else {
2560 c_time = new Date();
2561 timer = c_time.getTime() + 2000;
2562 }
2563 } else {
2564 c_time = new Date();
2565 timer = c_time.getTime() + 2000;
2566 }
2567 }
2568 }
2569 }
2570 }
2571 }
2572 };
2573 function vrDeviseOrientation(){
2574 var data = {
2575 pitch: panoshow' . $pano_suffix . '.getPitch(),
2576 yaw: panoshow' . $pano_suffix . '.getYaw(),
2577 };
2578 panoShowCardBoardOnTrigger(data);
2579 }';
2580 $html .= '
2581 function requestFullScreen(){
2582 var elem = document.getElementById("' . $master_container_id . '") || document.getElementById("master-container");
2583 if (elem) {
2584 if (elem.requestFullscreen) {
2585 elem.requestFullscreen();
2586 } else if (elem.webkitRequestFullscreen) { /* Safari */
2587 elem.webkitRequestFullscreen();
2588 } else if (elem.msRequestFullscreen) { /* IE11 */
2589 elem.msRequestFullscreen();
2590 }
2591 }
2592 }
2593 function requestExitFullscreen(){
2594 var elem = document.getElementById("' . $master_container_id . '") || document.getElementById("master-container");
2595 if (document.exitFullscreen) {
2596 document.exitFullscreen();
2597 } else if (document.webkitExitFullscreen) { /* Safari */
2598 document.webkitExitFullscreen();
2599 } else if (document.msExitFullscreen) { /* IE11 */
2600 document.msExitFullscreen();
2601 }
2602 }
2603 jQuery(document).on("click",".fullscreen-button .expand",function() {
2604 jQuery(this).hide()
2605 jQuery(this).parent().find(".compress").show()
2606 requestFullScreen()
2607 });
2608 jQuery(document).on("click",".fullscreen-button .compress",function() {
2609 jQuery(this).hide()
2610 jQuery(this).parent().find(".expand").show()
2611 requestExitFullscreen()
2612 screen.orientation.unlock();
2613 });
2614 let onLoadAnalytics = false;
2615 let sceneLoadAnalytics = false;
2616
2617 function storeAnalyticsData(data) {
2618 if (typeof wpvrAnalyticsObj !== "undefined") {
2619 if (typeof wpvr_public !== "undefined") {
2620 if (wpvr_public.is_pro_active) {
2621 jQuery.ajax({
2622 url: wpvrAnalyticsObj.ajaxUrl,
2623 type: "POST",
2624 data: {
2625 action: "store_scene_hotspot_data",
2626 scene_id: data.scene_id,
2627 tour_id: data.tour_id,
2628 type: data.type,
2629 hotspot_id: data.hotspot_id || "",
2630 user_agent: navigator.userAgent,
2631 device_type: getDeviceType() || "desktop",
2632 nonce: wpvrAnalyticsObj.nonce,
2633 },
2634 success: function (response) {
2635 console.log("Data stored successfully");
2636 },
2637 error: function (error) {
2638 console.log("Error in storing data");
2639 }
2640 });
2641 }
2642 }
2643 } else {
2644 console.warn("Analytics object not available or pro not active");
2645 }
2646 }
2647 function getDeviceType() {
2648 const userAgent = navigator.userAgent.toLowerCase();
2649 if (/mobile|android|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test(userAgent)) {
2650 return "mobile";
2651 } else if (/tablet|ipad/i.test(userAgent)) {
2652 return "tablet";
2653 } else {
2654 return "desktop";
2655 }
2656 }
2657 panoshow' . $pano_suffix . '.on("scenechange", function(scene) {
2658 onLoadAnalytics = true;
2659 sceneLoadAnalytics = true;
2660 let scene_id = scene;
2661 let tour_id = ' . $id . ';
2662 let type = "scene";
2663 let hotspot_id = "";
2664 let user_agent = navigator.userAgent;
2665 let device_type = getDeviceType() ? getDeviceType() : "desktop";
2666 storeAnalyticsData({
2667 scene_id: scene_id,
2668 tour_id: tour_id,
2669 type: type,
2670 hotspot_id: hotspot_id,
2671 user_agent: user_agent,
2672 device_type: device_type,
2673 });
2674 });
2675 panoshow' . $pano_suffix . '.on("load", function() {
2676 let scene_id = panoshow' . $pano_suffix . '.getScene();
2677 let tour_id = ' . $id . ';
2678 let type = "scene";
2679 let hotspot_id = "";
2680 let user_agent = navigator.userAgent;
2681 let device_type = getDeviceType() ? getDeviceType() : "desktop";
2682 if(!onLoadAnalytics) {
2683 if(!sceneLoadAnalytics) {
2684 storeAnalyticsData({
2685 scene_id: scene_id,
2686 tour_id: tour_id,
2687 type: type,
2688 hotspot_id: hotspot_id,
2689 user_agent: user_agent,
2690 device_type: device_type,
2691 });
2692 }
2693 }
2694 });
2695 function wpvrhotspotscene' . $pano_suffix . '(hotSpotDiv, args) {
2696 onLoadAnalytics = true;
2697 let scene_id = panoshow' . $pano_suffix . '.getScene();
2698 let tour_id = ' . $id . ';
2699 let type = "hotspot";
2700 let hotspot_id = args;
2701 let user_agent = navigator.userAgent;
2702 let device_type = getDeviceType() ? getDeviceType() : "desktop";
2703 storeAnalyticsData({
2704 scene_id: scene_id,
2705 tour_id: tour_id,
2706 type: type,
2707 hotspot_id: hotspot_id,
2708 user_agent: user_agent,
2709 device_type: device_type
2710 });
2711 }
2712 var wpvrhotspotscene = wpvrhotspotscene' . $pano_suffix . ';
2713 ';
2714 $html .= 'panoshow' . $pano_suffix . '.on("scenechange", function (scene){
2715 jQuery(".center-pointer").removeClass("wpvr-pluse-effect")
2716 active_scene = scene;
2717 // if(localStorage.getItem("vr_mode") == "on") {
2718 if(vr_mode == "on") {
2719 jQuery("#' . $panoid2 . ' .pnlm-compass.pnlm-controls.pnlm-control").css("display","none");
2720 jQuery("#' . $panoid . ' .pnlm-compass.pnlm-controls.pnlm-control").css("display","none");
2721 }
2722 });
2723 var compassBlock = "";
2724 var infoBlock = "";
2725 jQuery(document).on("click",".vr_mode_change' . $pano_suffix . '",function (){
2726 jQuery("#' . $panoid2 . ' .pnlm-load-button").trigger("click");
2727 jQuery("#' . $panoid . ' .pnlm-load-button").trigger("click");
2728 var getValue = jQuery(this).val();
2729 var getParent = jQuery(this).parent().parent();
2730 var compass = getParent.find("#' . $panoid2 . ' .pnlm-compass.pnlm-controls.pnlm-control").css("display");
2731 var panoInfo = getParent.find("#' . $panoid . ' .pnlm-panorama-info").css("display");
2732 if(compass == "block"){
2733 compassBlock = "block";
2734 }
2735 if(panoInfo == "block"){
2736 infoBlock = "block";
2737 }
2738 if (getValue == "off") {
2739 requestFullScreen()
2740 screen.orientation.lock("landscape-primary").then(function() {
2741 }).catch(function(error) {
2742 alert("VR Glass Mode not supported in this device");
2743 });
2744 // localStorage.setItem("vr_mode", "on");
2745 vr_mode = "on";
2746 jQuery(".vr-mode-title").show();
2747 jQuery(this).val("on");
2748 getParent.find("#' . $panoid2 . '").css({
2749 "opacity": "1",
2750 "visibility": "visible",
2751 "position": "relative",
2752 });
2753 gyroSwitch = true;
2754 panoshow' . $pano_suffix . '.startOrientation();
2755 panoshow2' . $pano_suffix . '.startOrientation();
2756 panoshow2' . $pano_suffix . '.setPitch(panoshow' . $pano_suffix . '.getPitch(), 0);
2757 panoshow2' . $pano_suffix . '.setYaw(panoshow' . $pano_suffix . '.getYaw(), 0);
2758 getParent.find(".pano-wrap").addClass("wpvr-cardboard-disable-event");
2759 getParent.find("#' . $panoid . ' #zoom-in-out-controls' . $pano_suffix . '").hide();
2760 getParent.find("#' . $panoid . ' #controls' . $pano_suffix . '").hide();
2761 getParent.find("#' . $panoid . ' #explainer_button_' . $pano_suffix . '").hide();
2762 getParent.find("#' . $panoid . ' #generic_form_button_' . $pano_suffix . '").hide();
2763 getParent.find("#' . $panoid . ' #floor_map_button_' . $pano_suffix . '").hide();
2764 getParent.find("#' . $panoid . ' #vrgcontrols' . $pano_suffix . '").hide();
2765 getParent.find("#' . $panoid . ' #sccontrols' . $pano_suffix . '").hide();
2766 getParent.find("#' . $panoid . ' #adcontrol' . $pano_suffix . '").hide();
2767 getParent.find("#' . $panoid . ' .wpvr_slider_nav").hide();
2768 getParent.find("#' . $panoid . ' #cp-logo-controls").hide();
2769 getParent.find("#' . $panoid . ' #wpvr-social-share-bg-box' . $pano_suffix . '").hide();
2770 getParent.find("#' . $panoid2 . ' .pnlm-controls-container").hide();
2771 getParent.find("#' . $panoid . ' .pnlm-controls-container").hide();
2772 getParent.find("#' . $panoid2 . ' .pnlm-compass.pnlm-controls.pnlm-control").hide();
2773 getParent.find("#' . $panoid . ' .pnlm-compass.pnlm-controls.pnlm-control").hide();
2774 getParent.find("#' . $panoid2 . ' .pnlm-panorama-info").hide();
2775 getParent.find("#' . $panoid . ' .pnlm-panorama-info").hide();
2776 getParent.find("#' . $panoid . '").addClass("cardboard-half");
2777 getParent.find("#center-pointer' . $pano_suffix . '").show();
2778 getParent.find(".fullscreen-button").hide();
2779 getParent.find("#' . $panoid . ' #custom-scene-navigation' . $pano_suffix . '").hide();
2780 if (window.DeviceOrientationEvent) {
2781 window.addEventListener("deviceorientation", vrDeviseOrientation);
2782 }
2783 panoshow' . $pano_suffix . '.on("zoomchange", function (data){
2784 panoshow2' . $pano_suffix . '.setHfov(data, 0);
2785 });
2786 panoshow2' . $pano_suffix . '.on("zoomchange", function (data){
2787 panoshow' . $pano_suffix . '.setHfov(data, 0);
2788 });
2789 jQuery(document).on("click","#' . $panoid2 . '",function(event) {
2790 panoshow' . $pano_suffix . '.startOrientation();
2791 panoshow2' . $pano_suffix . '.startOrientation();
2792 });
2793 jQuery(document).on("click","#' . $panoid . '",function(event) {
2794 panoshow' . $pano_suffix . '.startOrientation();
2795 panoshow2' . $pano_suffix . '.startOrientation();
2796 });
2797 panoshow' . $pano_suffix . '.on("mousemove", function (data){
2798 panoshow2' . $pano_suffix . '.setPitch(data.pitch, 0);
2799 panoshow2' . $pano_suffix . '.setYaw(data.yaw, 0);
2800 panoShowCardBoardOnTrigger(data);
2801 });
2802 panoshow2' . $pano_suffix . '.on("mousemove", function (data){
2803 panoshow' . $pano_suffix . '.setPitch(data.pitch, 0);
2804 panoshow' . $pano_suffix . '.setYaw(data.yaw, 0);
2805 panoShowCardBoardOnTrigger(data);
2806 });
2807 panoshow' . $pano_suffix . '.on("touchmove", function (data){
2808 panoshow' . $pano_suffix . '.stopOrientation();
2809 panoshow2' . $pano_suffix . '.stopOrientation();
2810 panoshow2' . $pano_suffix . '.setPitch(data.pitch, 0);
2811 panoshow2' . $pano_suffix . '.setYaw(data.yaw, 0);
2812 panoShowCardBoardOnTrigger(data);
2813 });
2814 panoshow2' . $pano_suffix . '.on("touchmove", function (data){
2815 panoshow' . $pano_suffix . '.stopOrientation();
2816 panoshow2' . $pano_suffix . '.stopOrientation();
2817 panoshow' . $pano_suffix . '.setPitch(data.pitch, 0);
2818 panoshow' . $pano_suffix . '.setYaw(data.yaw, 0);
2819 panoShowCardBoardOnTrigger(data);
2820 });
2821 } else if(getValue == "on") {
2822 screen.orientation.unlock();
2823 requestExitFullscreen();
2824 // localStorage.setItem("vr_mode", "off");
2825 vr_mode = "off";
2826 jQuery(".vr-mode-title").hide();
2827 jQuery(this).val("off");
2828 getParent.find("#' . $panoid2 . '").css({
2829 "opacity": "0",
2830 "visibility": "hidden",
2831 "position": "absolute",
2832 });
2833 getParent.find(".pano-wrap").removeClass("wpvr-cardboard-disable-event");
2834 getParent.find("#' . $panoid . ' #zoom-in-out-controls' . $pano_suffix . '").show();
2835 getParent.find("#' . $panoid . ' #controls' . $pano_suffix . '").show();
2836 getParent.find("#' . $panoid . ' #explainer_button_' . $pano_suffix . '").show();
2837 getParent.find("#' . $panoid . ' #generic_form_button_' . $pano_suffix . '").show();
2838 getParent.find("#' . $panoid . ' #floor_map_button_' . $pano_suffix . '").show();
2839 getParent.find("#' . $panoid2 . ' .pnlm-controls-container").show();
2840 getParent.find("#' . $panoid . ' .pnlm-controls-container").show();
2841 getParent.find("#' . $panoid . ' #vrgcontrols' . $pano_suffix . '").show();
2842 getParent.find("#' . $panoid . ' #sccontrols' . $pano_suffix . '").hide();
2843 getParent.find("#' . $panoid . ' #adcontrol' . $pano_suffix . '").show();
2844 getParent.find("#' . $panoid . ' .wpvr_slider_nav").hide();
2845 getParent.find("#' . $panoid . ' #cp-logo-controls").show();
2846 getParent.find("#' . $panoid . ' #wpvr-social-share-bg-box' . $pano_suffix . '").show();
2847 getParent.find("#' . $panoid . ' #custom-scene-navigation' . $pano_suffix . '").show();
2848 if(compassBlock == "block"){
2849 getParent.find("#' . $panoid2 . ' .pnlm-compass.pnlm-controls.pnlm-control").show();
2850 getParent.find("#' . $panoid . ' .pnlm-compass.pnlm-controls.pnlm-control").show();
2851 }
2852 if(infoBlock == "block"){
2853 getParent.find("#' . $panoid2 . ' .pnlm-panorama-info").show();
2854 getParent.find("#' . $panoid . ' .pnlm-panorama-info").show();
2855 }
2856 getParent.find("#' . $panoid . '").removeClass("cardboard-half");
2857 getParent.find("#center-pointer' . $pano_suffix . '").hide();
2858 getParent.find(".fullscreen-button").hide();
2859 panoshow' . $pano_suffix . '.off("mousemove");
2860 panoshow' . $pano_suffix . '.off("touchmove");
2861 panoshow2' . $pano_suffix . '.off("mousemove");
2862 panoshow2' . $pano_suffix . '.off("touchmove");
2863 if (window.DeviceOrientationEvent) {
2864 window.removeEventListener("deviceorientation", vrDeviseOrientation);
2865 }
2866 }
2867 });';
2868 $html .= 'panoshow2' . $pano_suffix . '.on("load", function (){
2869 // if(localStorage.getItem("vr_mode") == "off") {
2870 if( vr_mode == "off") {
2871 jQuery(".vr-mode-title").hide();
2872 }
2873 else {
2874 jQuery("#' . $panoid2 . ' .pnlm-compass.pnlm-controls.pnlm-control").css("display","none");
2875 jQuery("#' . $panoid . ' .pnlm-compass.pnlm-controls.pnlm-control").css("display","none");
2876 jQuery("#' . $panoid2 . ' .pnlm-panorama-info").hide();
2877 jQuery("#' . $panoid . ' .pnlm-panorama-info").hide();
2878 jQuery(".vr-mode-title").show();
2879 }
2880 });';
2881 }
2882 //=== end Dplicate mode only for vr mode===//
2883 $html .= 'jQuery("#' . $panoid . ' .wpvr-floor-map .floor-plan-pointer").on("click",function(){
2884 var scene_id = jQuery(this).attr("scene_id");
2885 panoshow' . $pano_suffix . '.loadScene(scene_id)
2886 jQuery(".floor-plan-pointer").removeClass("add-pulse")
2887 jQuery(this).addClass("add-pulse")
2888 });';
2889 if ($scene_animation_enabled && is_plugin_active('wpvr-pro/wpvr-pro.php')) {
2890 $animation_type = $postdata['sceneAnimationName'] ?? 'none';
2891 $animation_type = $animation_type === 'fade' ? 'fade_in' : $animation_type;
2892 $animationDuration = $postdata['sceneAnimationTransitionDuration'] ?? '500ms';
2893 $animationDelay = $postdata['sceneAnimationTransitionDelay'] ?? '0ms';
2894 $animation_js = apply_filters('wpvr_scene_animation_js', $id, $animation_type, $animationDuration, $animationDelay);
2895 if (!empty($animation_js)) {
2896 $html .= $animation_js;
2897 $html .= 'panoshow' . $pano_suffix . '.on("load", function (scene){
2898 if (typeof changeScene === "function") {
2899 changeScene();
2900 } else {
2901 console.warn("changeScene function is not defined.");
2902 }
2903 });';
2904 }
2905 }
2906
2907 $html .= 'panoshow' . $pano_suffix . '.on("mousemove", function (data){
2908 jQuery(".add-pulse").css({"transform":"rotate("+data.yaw+"deg)"});
2909 });
2910 ';
2911 $status = get_option('wpvr_edd_license_status');
2912 if ($status !== false && 'valid' == $status && $is_pro){
2913 $html .= 'panoshow' . $pano_suffix . '.on("scenechange", function (scene){
2914 jQuery(".center-pointer").removeClass("wpvr-pluse-effect")
2915 jQuery(".floor-plan-pointer").each(function(index ,element){
2916 var scene_id = jQuery(this).attr("scene_id");
2917 if( active_scene == scene_id ){
2918 jQuery(".floor-plan-pointer").removeClass("add-pulse")
2919 jQuery(this).addClass("add-pulse")
2920 }
2921 });
2922 });';
2923 $html .= 'panoshow' . $pano_suffix . '.on("load", function (){
2924 if(jQuery(".floor-plan-pointer").length > 0){
2925 jQuery(".floor-plan-pointer").each(function(index ,element){
2926 var scene_id = jQuery(this).attr("scene_id");
2927 if( active_scene == scene_id ){
2928 jQuery(".floor-plan-pointer").removeClass("add-pulse")
2929 jQuery(this).addClass("add-pulse")
2930 }
2931 });
2932 }
2933 });';
2934 }
2935 if ($status !== false && 'valid' == $status && $is_pro){
2936 $scene_navigation_content_type = isset($postdata['scene_navigation_content_type']) ? $postdata['scene_navigation_content_type'] : 'scene_id';
2937 $html .= 'jQuery("#' . $panoid . ' .custom-scene-navigation").on("click", function() {
2938 jQuery("#custom-scene-navigation-nav' . $pano_suffix . ' ul").empty();
2939 if (scenes) {
2940 var scene_navigation_content_type = "' . $scene_navigation_content_type . '";
2941 var sceneList = scenes.scenes;
2942 var getScene = panoshow' . $pano_suffix . '.getScene();
2943 for (const key in sceneList) {
2944 let title;
2945 if (scene_navigation_content_type === "scene_title") {
2946 if (sceneList[key].title) {
2947 title = sceneList[key].title;
2948 } else {
2949 if (title == "" || title == undefined) {
2950 if (sceneList[key].panorama) {
2951 title = getImageNameWithoutExtension(sceneList[key].panorama);
2952 }
2953 }
2954 }
2955 } else if (scene_navigation_content_type === "scene_image_name") {
2956 if (sceneList[key].panorama) {
2957 title = getImageNameWithoutExtension(sceneList[key].panorama);
2958 }
2959 } else {
2960 title = key;
2961 }
2962 if (sceneList.hasOwnProperty(key)) {
2963 let ulElement = document.querySelector("#custom-scene-navigation-nav' . $pano_suffix . ' ul");
2964 if (ulElement) {
2965 let liElement = document.createElement("li");
2966 liElement.className = "scene-navigation-list" + (key === getScene ? " active" : "");
2967 liElement.setAttribute("scene_id", key);
2968 liElement.textContent = title;
2969 ulElement.appendChild(liElement);
2970 }
2971 }
2972 }
2973 jQuery("#custom-scene-navigation-nav' . $pano_suffix . '").toggleClass("visible");
2974 }
2975 });';
2976 $html .='function getImageNameWithoutExtension(imageUrl) {
2977 // Split the URL by "/"
2978 var parts = imageUrl.split("/");
2979 // Get the last part which contains the image name
2980 var imageNameWithExtension = parts[parts.length - 1];
2981 // Split the image name by period (.)
2982 var imageNameParts = imageNameWithExtension.split(".");
2983 // Remove the last part (which is the extension) and join the remaining parts
2984 var imageNameWithoutExtension = imageNameParts.slice(0, -1).join(".");
2985 // Return the image name without extension
2986 return imageNameWithoutExtension;
2987 }';
2988 $html .= 'jQuery("#' . $panoid . ' #custom-scene-navigation-nav' . $pano_suffix . ' ul").on("click", "li.scene-navigation-list", function() {
2989 if (scenes) {
2990 jQuery(this).siblings("li").removeClass("active");
2991 jQuery(this).addClass("active");
2992 var scene_key = jQuery(this).attr("scene_id");
2993 panoshow' . $pano_suffix . '.loadScene(scene_key);
2994 }
2995 });';
2996 }
2997 $html .= 'const node = document.querySelector(".add-pulse");
2998 panoshow' . $pano_suffix . '.on("compasschange", function (data){
2999 // const node = document.querySelector(".add-pulse");
3000 // node.style.transform = data;
3001 // jQuery(".add-pulse").css({"transform":data});
3002 });';
3003 $html .= 'panoshow' . $pano_suffix . '.on("load", function (){
3004 // if(localStorage.getItem("vr_mode") == "off") {
3005 if(vr_mode == "off") {
3006 jQuery(".vr-mode-title").hide();
3007 } else {
3008 jQuery("#' . $panoid2 . ' .pnlm-compass.pnlm-controls.pnlm-control").css("display","none");
3009 jQuery("#' . $panoid . ' .pnlm-compass.pnlm-controls.pnlm-control").css("display","none");
3010 jQuery("#' . $panoid2 . ' .pnlm-panorama-info").hide();
3011 jQuery("#' . $panoid . ' .pnlm-panorama-info").hide();
3012 jQuery(".vr-mode-title").show();
3013 }
3014 setTimeout(() => {
3015 window.dispatchEvent(new Event("resize"));
3016 }, 200);
3017 if (jQuery("#' . $panoid . '").children().children(".pnlm-panorama-info:visible").length > 0) {
3018 jQuery("#controls' . $pano_suffix . '").css("bottom", "80px");
3019 }
3020 else {
3021 jQuery("#controls' . $pano_suffix . '").css("bottom", "5px");
3022 }
3023 });';
3024 $html .= 'panoshow' . $pano_suffix . '.on("render", function (){
3025 window.dispatchEvent(new Event("resize"));
3026 });';
3027 $html .= 'if (scenes.autoRotate) {
3028 var wpvrAutoRotateTimer' . $pano_suffix . ' = null;
3029 var wpvrAutoRotateStopDelay' . $pano_suffix . ' = parseInt(scenes.autoRotateStopDelay, 10) || 0;
3030 var wpvrScheduleAutoRotate' . $pano_suffix . ' = function () {
3031 clearTimeout(wpvrAutoRotateTimer' . $pano_suffix . ');
3032 if (wpvrAutoRotateStopDelay' . $pano_suffix . ' > 0) {
3033 wpvrAutoRotateTimer' . $pano_suffix . ' = setTimeout(function () {
3034 panoshow' . $pano_suffix . '.stopAutoRotate();
3035 }, wpvrAutoRotateStopDelay' . $pano_suffix . ');
3036 } else {
3037 wpvrAutoRotateTimer' . $pano_suffix . ' = setTimeout(function () {
3038 panoshow' . $pano_suffix . '.startAutoRotate(scenes.autoRotate, 0);
3039 }, 3000);
3040 }
3041 };
3042 panoshow' . $pano_suffix . '.on("load", wpvrScheduleAutoRotate' . $pano_suffix . ');
3043 panoshow' . $pano_suffix . '.on("scenechange", wpvrScheduleAutoRotate' . $pano_suffix . ');
3044 }';
3045 $html .= 'var touchtime = 0;';
3046 $html .= '
3047 var wpvrHotspotRoot' . $pano_suffix . ' = document.getElementById("' . $panoid . '");
3048 if (wpvrHotspotRoot' . $pano_suffix . ') {
3049 wpvrHotspotRoot' . $pano_suffix . '.addEventListener("click", function (event) {
3050 var hotspot = event.target.closest(".pnlm-hotspot-base");
3051
3052 if (!hotspot) {
3053 return;
3054 }
3055
3056 // Social share icons navigate independently using their own links and targets.
3057 if (hotspot.querySelector(".wpvr-sticker-card--social-share")) {
3058 return;
3059 }
3060
3061 var hotspotLink = hotspot.closest("a[href]");
3062 if (!hotspotLink) {
3063 hotspotLink = hotspot.querySelector("a[href]");
3064 }
3065
3066 if (!hotspotLink) {
3067 return;
3068 }
3069
3070 event.preventDefault();
3071 event.stopImmediatePropagation();
3072
3073 if ((hotspotLink.getAttribute("target") || "_blank") === "_self") {
3074 window.location.assign(hotspotLink.href);
3075 } else {
3076 window.open(hotspotLink.href, "_blank", "noopener,noreferrer");
3077 }
3078 }, true);
3079 }
3080 ';
3081 if ($vrgallery) {
3082 $gallery_scene_ids = [];
3083 if (isset($panodata["scene-list"])) {
3084 foreach ($panodata["scene-list"] as $panoscenes) {
3085 $scene_key = $panoscenes['scene-id'];
3086 $gallery_scene_ids[] = (string) $scene_key;
3087 $scene_key_gallery = $panoscenes['scene-id'] . '_gallery_' . $pano_suffix;
3088 $html .= 'jQuery(document).on("click","#' . $scene_key_gallery . '",function() {
3089 panoshow' . $pano_suffix . '.loadScene(' . wp_json_encode( (string) $scene_key ) . ');
3090 });';
3091 }
3092 }
3093
3094 $is_modern_gallery = isset($postdata['tourLayout']['layout']) && 'layout1' === $postdata['tourLayout']['layout'];
3095 $gallery_options = $is_modern_gallery
3096 ? '{
3097 loop: false,
3098 nav: false,
3099 dots: false,
3100 margin: 18,
3101 mouseDrag: false,
3102 responsive: {
3103 0: { items: 2 },
3104 320: { items: 3 },
3105 500: { items: 4 },
3106 690: { items: 5 }
3107 }
3108 }'
3109 : '{
3110 autoWidth: true,
3111 loop: false,
3112 nav: false,
3113 dots: false,
3114 margin: 10,
3115 stagePadding: 0
3116 }';
3117
3118 $html .= '
3119 var wpvrGallery' . $pano_suffix . ' = jQuery("#sccontrols' . $pano_suffix . '");
3120 var wpvrGalleryRoot' . $pano_suffix . ' = jQuery("#' . $panoid . '");
3121 var wpvrGalleryScenes' . $pano_suffix . ' = ' . wp_json_encode(array_values($gallery_scene_ids)) . ';
3122 var wpvrGalleryResizeTimer' . $pano_suffix . ';
3123 var wpvrGalleryVisibilityTimer' . $pano_suffix . ';
3124 var wpvrGalleryObserver' . $pano_suffix . ';
3125
3126 function wpvrPrepareSceneNavigation' . $pano_suffix . '() {
3127 var navigationDisabled = wpvrGalleryScenes' . $pano_suffix . '.length < 2;
3128 var previousButtons = wpvrGalleryRoot' . $pano_suffix . '.find(".wpvr_owl_prev");
3129 var nextButtons = wpvrGalleryRoot' . $pano_suffix . '.find(".wpvr_owl_next");
3130
3131 wpvrGallery' . $pano_suffix . '.removeClass("owl-theme");
3132 wpvrGalleryRoot' . $pano_suffix . '.find(".wpvr_slider_nav").removeClass("owl-nav");
3133 previousButtons
3134 .removeClass("owl-prev")
3135 .prop("disabled", navigationDisabled)
3136 .toggleClass("disabled", navigationDisabled);
3137 nextButtons
3138 .removeClass("owl-next")
3139 .prop("disabled", navigationDisabled)
3140 .toggleClass("disabled", navigationDisabled);
3141 }
3142
3143 function wpvrRefreshGallery' . $pano_suffix . '() {
3144 wpvrPrepareSceneNavigation' . $pano_suffix . '();
3145
3146 if (!wpvrGallery' . $pano_suffix . '.length || !wpvrGallery' . $pano_suffix . '.hasClass("owl-loaded") || !wpvrGallery' . $pano_suffix . '.is(":visible")) {
3147 return;
3148 }
3149
3150 if (wpvrGallery' . $pano_suffix . '.css("display") === "flex") {
3151 wpvrGallery' . $pano_suffix . '.css("display", "block");
3152 }
3153 wpvrGallery' . $pano_suffix . '.trigger("refresh.owl.carousel");
3154 wpvrUpdateGalleryNavigation' . $pano_suffix . '(panoshow' . $pano_suffix . '.getScene());
3155 }
3156
3157 function wpvrGallerySceneIndex' . $pano_suffix . '(sceneId) {
3158 return wpvrGalleryScenes' . $pano_suffix . '.indexOf(String(sceneId));
3159 }
3160
3161 function wpvrUpdateGalleryNavigation' . $pano_suffix . '(sceneId) {
3162 var currentIndex = wpvrGallerySceneIndex' . $pano_suffix . '(sceneId);
3163 var activeThumbnailId = String(sceneId) + "_gallery_' . $pano_suffix . '";
3164 var thumbnails = wpvrGallery' . $pano_suffix . '.find("img.scctrl");
3165 var activeThumbnail = thumbnails.filter(function () {
3166 return this.id === activeThumbnailId;
3167 });
3168
3169 wpvrPrepareSceneNavigation' . $pano_suffix . '();
3170 thumbnails.removeClass("wpvr-active-thumbnail");
3171 wpvrGallery' . $pano_suffix . '.find(".owl-item").removeClass("clicked");
3172 activeThumbnail.addClass("wpvr-active-thumbnail");
3173 activeThumbnail.closest(".owl-item").addClass("clicked");
3174
3175 if (currentIndex >= 0) {
3176 if (wpvrGallery' . $pano_suffix . '.hasClass("owl-loaded")) {
3177 wpvrGallery' . $pano_suffix . '.trigger("to.owl.carousel", [currentIndex, 300, true]);
3178 window.setTimeout(wpvrPrepareSceneNavigation' . $pano_suffix . ', 0);
3179 }
3180 }
3181 }
3182
3183 function wpvrLoadAdjacentGalleryScene' . $pano_suffix . '(direction) {
3184 var currentIndex = wpvrGallerySceneIndex' . $pano_suffix . '(panoshow' . $pano_suffix . '.getScene());
3185
3186 if (currentIndex < 0 || wpvrGalleryScenes' . $pano_suffix . '.length < 2) {
3187 return;
3188 }
3189
3190 var targetIndex = (currentIndex + direction + wpvrGalleryScenes' . $pano_suffix . '.length) % wpvrGalleryScenes' . $pano_suffix . '.length;
3191 panoshow' . $pano_suffix . '.loadScene(wpvrGalleryScenes' . $pano_suffix . '[targetIndex]);
3192 }
3193
3194 if (jQuery.fn.owlCarousel) {
3195 if (wpvrGallery' . $pano_suffix . '.length) {
3196 if (!wpvrGallery' . $pano_suffix . '.hasClass("owl-loaded")) {
3197 wpvrGallery' . $pano_suffix . '.owlCarousel(' . $gallery_options . ');
3198 }
3199 }
3200 }
3201
3202 wpvrGalleryRoot' . $pano_suffix . '
3203 .off("click.wpvrGalleryRefresh' . $pano_suffix . '", "#vrgcontrols' . $pano_suffix . '")
3204 .on("click.wpvrGalleryRefresh' . $pano_suffix . '", "#vrgcontrols' . $pano_suffix . '", function () {
3205 wpvrPrepareSceneNavigation' . $pano_suffix . '();
3206 window.setTimeout(wpvrRefreshGallery' . $pano_suffix . ', 450);
3207 });
3208
3209 if (wpvrGalleryRoot' . $pano_suffix . '.length) {
3210 wpvrGalleryRoot' . $pano_suffix . '[0].addEventListener("click", function (event) {
3211 var navigationButton = event.target.closest(".wpvr_owl_prev, .wpvr_owl_next");
3212
3213 if (!navigationButton) {
3214 return;
3215 }
3216
3217 if (!wpvrGalleryRoot' . $pano_suffix . '[0].contains(navigationButton)) {
3218 return;
3219 }
3220
3221 event.preventDefault();
3222 event.stopImmediatePropagation();
3223
3224 if (navigationButton.classList.contains("wpvr_owl_prev")) {
3225 wpvrLoadAdjacentGalleryScene' . $pano_suffix . '(-1);
3226 } else {
3227 wpvrLoadAdjacentGalleryScene' . $pano_suffix . '(1);
3228 }
3229 }, true);
3230 }
3231
3232 jQuery(window)
3233 .off("resize.wpvrGallery' . $pano_suffix . '")
3234 .on("resize.wpvrGallery' . $pano_suffix . '", function () {
3235 window.clearTimeout(wpvrGalleryResizeTimer' . $pano_suffix . ');
3236 wpvrGalleryResizeTimer' . $pano_suffix . ' = window.setTimeout(wpvrRefreshGallery' . $pano_suffix . ', 100);
3237 });
3238
3239 if (window.MutationObserver) {
3240 if (wpvrGallery' . $pano_suffix . '.length) {
3241 wpvrGalleryObserver' . $pano_suffix . ' = new MutationObserver(function () {
3242 window.clearTimeout(wpvrGalleryVisibilityTimer' . $pano_suffix . ');
3243 wpvrGalleryVisibilityTimer' . $pano_suffix . ' = window.setTimeout(wpvrRefreshGallery' . $pano_suffix . ', 50);
3244 });
3245 wpvrGalleryObserver' . $pano_suffix . '.observe(wpvrGallery' . $pano_suffix . '[0], {
3246 attributes: true,
3247 attributeFilter: ["style"]
3248 });
3249 }
3250 }
3251
3252 panoshow' . $pano_suffix . '.on("scenechange", function (sceneId) {
3253 wpvrUpdateGalleryNavigation' . $pano_suffix . '(sceneId);
3254 });
3255
3256 window.setTimeout(wpvrRefreshGallery' . $pano_suffix . ', 0);
3257 window.setTimeout(function () {
3258 wpvrUpdateGalleryNavigation' . $pano_suffix . '(panoshow' . $pano_suffix . '.getScene());
3259 }, 0);
3260 ';
3261 }
3262 //===Custom Control===//
3263 if (isset($custom_control)) {
3264 if ($custom_control['panupSwitch'] == "on" && 'valid' == $status && $is_pro) {
3265 $html .= 'document.getElementById("pan-up' . $pano_suffix . '").addEventListener("click", function(e) {';
3266 $html .= 'panoshow' . $pano_suffix . '.setPitch(panoshow' . $pano_suffix . '.getPitch() + 10);';
3267 $html .= '});';
3268 }
3269 if ($custom_control['panDownSwitch'] == "on" && 'valid' == $status && $is_pro) {
3270 $html .= 'document.getElementById("pan-down' . $pano_suffix . '").addEventListener("click", function(e) {';
3271 $html .= 'panoshow' . $pano_suffix . '.setPitch(panoshow' . $pano_suffix . '.getPitch() - 10);';
3272 $html .= '});';
3273 }
3274 if ($custom_control['panLeftSwitch'] == "on" && 'valid' == $status && $is_pro) {
3275 $html .= 'document.getElementById("pan-left' . $pano_suffix . '").addEventListener("click", function(e) {';
3276 $html .= 'panoshow' . $pano_suffix . '.setYaw(panoshow' . $pano_suffix . '.getYaw() - 10);';
3277 $html .= '});';
3278 }
3279 if ($custom_control['panRightSwitch'] == "on" && 'valid' == $status && $is_pro) {
3280 $html .= 'document.getElementById("pan-right' . $pano_suffix . '").addEventListener("click", function(e) {';
3281 $html .= 'panoshow' . $pano_suffix . '.setYaw(panoshow' . $pano_suffix . '.getYaw() + 10);';
3282 $html .= '});';
3283 }
3284 if ($custom_control['panZoomInSwitch'] == "on") {
3285 $html .= 'document.getElementById("zoom-in' . $pano_suffix . '").addEventListener("click", function(e) {';
3286 $html .= 'panoshow' . $pano_suffix . '.setHfov(panoshow' . $pano_suffix . '.getHfov() - 10);';
3287 $html .= '});';
3288 }
3289 if ($custom_control['panZoomOutSwitch'] == "on") {
3290 $html .= 'document.getElementById("zoom-out' . $pano_suffix . '").addEventListener("click", function(e) {';
3291 $html .= 'panoshow' . $pano_suffix . '.setHfov(panoshow' . $pano_suffix . '.getHfov() + 10);';
3292 $html .= '});';
3293 }
3294 if ($custom_control['panFullscreenSwitch'] == "on" && 'valid' == $status && $is_pro) {
3295 $html .= 'document.getElementById("fullscreen' . $pano_suffix . '").addEventListener("click", function(e) {';
3296 $html .= 'panoshow' . $pano_suffix . '.toggleFullscreen();';
3297 $html .= '});';
3298 $html .= '(function() {';
3299 $html .= 'function wpvrFsChange' . $pano_suffix . '() {';
3300 $html .= 'var fsIcon = document.querySelector("#fullscreen' . $pano_suffix . ' i");';
3301 $html .= 'if (!fsIcon) return;';
3302 $html .= 'if (document.fullscreenElement || document.webkitFullscreenElement || document.mozFullScreenElement || document.msFullscreenElement) {';
3303 $html .= 'fsIcon.classList.remove("fa-expand"); fsIcon.classList.add("fa-minimize");';
3304 $html .= '} else {';
3305 $html .= 'fsIcon.classList.remove("fa-minimize"); fsIcon.classList.add("fa-expand");';
3306 $html .= '}';
3307 $html .= '}';
3308 $html .= 'document.addEventListener("fullscreenchange", wpvrFsChange' . $pano_suffix . ');';
3309 $html .= 'document.addEventListener("webkitfullscreenchange", wpvrFsChange' . $pano_suffix . ');';
3310 $html .= 'document.addEventListener("mozfullscreenchange", wpvrFsChange' . $pano_suffix . ');';
3311 $html .= 'document.addEventListener("MSFullscreenChange", wpvrFsChange' . $pano_suffix . ');';
3312 $html .= '})();';
3313 }
3314 if ($custom_control['backToHomeSwitch'] == "on" && 'valid' == $status && $is_pro) {
3315 $html .= 'document.getElementById("backToHome' . $pano_suffix . '").addEventListener("click", function(e) {';
3316 $html .= 'panoshow' . $pano_suffix . '.loadScene(' . wp_json_encode( (string) $default_scene ) . ');';
3317 $html .= '});';
3318 }
3319 if ($gyro_button_enabled && 'valid' == $status && $is_pro) {
3320 $html .= '
3321 (function() {
3322 var gyroButton = document.getElementById("gyroscope' . $pano_suffix . '");
3323 var gyroIcon = gyroButton ? gyroButton.querySelector("i") : null;
3324 var activeColor = ' . wp_json_encode($custom_control['gyroscopeColor']) . ';
3325 var permissionGranted = false;
3326
3327 if (!gyroButton || !gyroIcon) {
3328 return;
3329 }
3330
3331 function updateGyroscopeState() {
3332 gyroIcon.style.color = panoshow' . $pano_suffix . '.isOrientationActive()
3333 ? activeColor
3334 : "red";
3335 }
3336
3337 function startGyroscope() {
3338 if (!panoshow' . $pano_suffix . '.isOrientationSupported()) {
3339 updateGyroscopeState();
3340 return;
3341 }
3342
3343 panoshow' . $pano_suffix . '.startOrientation();
3344 window.setTimeout(updateGyroscopeState, 0);
3345 }
3346
3347 function requestGyroscopePermission() {
3348 var orientationEvent = window.DeviceOrientationEvent;
3349 if (orientationEvent) {
3350 if (typeof orientationEvent.requestPermission === "function") {
3351 if (!permissionGranted) {
3352 orientationEvent.requestPermission()
3353 .then(function(state) {
3354 permissionGranted = state === "granted";
3355 if (permissionGranted) {
3356 startGyroscope();
3357 } else {
3358 updateGyroscopeState();
3359 }
3360 })
3361 .catch(updateGyroscopeState);
3362 return;
3363 }
3364 }
3365 }
3366
3367 startGyroscope();
3368 }
3369
3370 panoshow' . $pano_suffix . '.on("load", updateGyroscopeState);
3371 panoshow' . $pano_suffix . '.on("scenechange", updateGyroscopeState);
3372
3373 gyroButton.addEventListener("click", function() {
3374 if (panoshow' . $pano_suffix . '.isOrientationActive()) {
3375 panoshow' . $pano_suffix . '.stopOrientation();
3376 updateGyroscopeState();
3377 return;
3378 }
3379
3380 requestGyroscopePermission();
3381 });
3382 })();';
3383 }
3384 }
3385 $angle_up = '<i class="fa fa-angle-up"></i>';
3386 $angle_down = '<i class="fa fa-angle-down"></i>';
3387 $sin_qout = "'";
3388
3389 //===Explainer Script===//
3390
3391 if ($autoplay_bg_music == 'on') {
3392 $html .= 'jQuery(document).on("click","#explainer_button_' . $pano_suffix . '",function() {
3393 jQuery("#explainer' . $pano_suffix . '").slideToggle();
3394 playing' . $pano_suffix . ' = false;
3395 var x' . $pano_suffix . ' = document.getElementById("vrAudio' . $pano_suffix . '");
3396 jQuery("#vr-volume' . $pano_suffix . '").removeClass("fas fa-volume-up");
3397 jQuery("#vr-volume' . $pano_suffix . '").addClass("fas fa-volume-mute");
3398 x' . $pano_suffix . '.pause();
3399 });
3400 jQuery(document).on("click",".close-explainer-video",function() {
3401 jQuery(this).parent(".explainer").hide();
3402 var el_src = jQuery(".vr-iframe").attr("src");
3403 jQuery(".vr-iframe").attr("src", el_src);
3404 });';
3405 } else {
3406 $html .= 'jQuery(document).on("click","#explainer_button_' . $pano_suffix . '",function() {
3407 jQuery("#explainer' . $pano_suffix . '").slideToggle(function(){
3408 var $explainerVideoId = jQuery("#explainer' . $pano_suffix . '");
3409 var $explainerVideoIframe = $explainerVideoId.find("iframe");
3410 var explainerVideoIframSrc = $explainerVideoIframe.attr("src");
3411 $explainerVideoIframe.attr("src", "");
3412 $explainerVideoIframe.attr("src", explainerVideoIframSrc);
3413 });
3414 });
3415 jQuery(document).on("click", ".close-explainer-video", function() {
3416 var $explainer = jQuery(this).parent(".explainer");
3417 var $iframe = $explainer.find("iframe");
3418 var el_src = $iframe.attr("src");
3419 $iframe.attr("src", "");
3420 $explainer.hide();
3421 $iframe.attr("src", el_src);
3422 });';
3423 }
3424
3425 $html .= '
3426 jQuery(document).on("click","#' . $panoid . '",function(event) {
3427 var isCross = event.target.closest(".cross");
3428 var isActiveModal = event.target.closest(".custom-ifram-wrapper");
3429 var isForm = event.target.closest(".wpvr-hotspot-tweak-contents-wrapper");
3430 var isHotspot = event.target.closest(".pnlm-hotspot-base");
3431 if(isCross != null){
3432 return;
3433 }
3434 if(isForm != null){
3435 jQuery(this).addClass("show-modal");
3436 }else if(isActiveModal == null){
3437 if(isHotspot == null){
3438 jQuery(".custom-ifram-wrapper .custom-ifram").empty();
3439 jQuery(".custom-ifram-wrapper").hide();
3440 jQuery(this).removeClass("show-modal");
3441 jQuery(".wpvr-hotspot-tweak-contents-wrapper").hide();
3442 }
3443 }
3444 });';
3445
3446 //===Explainer Script End===//
3447
3448 //===generic form script===//
3449 if (isset($postdata["genericform"]) && $postdata["genericform"] === 'on') {
3450 $html .= '
3451 jQuery(document).on("click","#generic_form_button_' . $pano_suffix . '",function() {
3452 jQuery("#wpvr-generic-form' . $pano_suffix . '").fadeToggle();
3453 });
3454
3455 jQuery(document).on("click",".close-generic-form",function() {
3456 jQuery(this).parent(".wpvr-generic-form").fadeOut()
3457 });
3458 ';
3459 }
3460 //===generic from script===//
3461
3462 //===Floor map Script===//
3463 $html .= 'jQuery(document).on("click","#floor_map_button_' . $pano_suffix . '",function() {
3464 jQuery("#wpvr-floor-map' . $pano_suffix . '").toggle().removeClass("fullwindow");
3465 });
3466 jQuery(document).on("dblclick","#wpvr-floor-map' . $pano_suffix . '",function(){
3467 jQuery(this).addClass("fullwindow");
3468 jQuery(this).parents(".pano-wrap").addClass("show-modal");
3469 });
3470 jQuery(document).on("click",".close-floor-map-plan",function() {
3471 jQuery(this).parent(".wpvr-floor-map").hide();
3472 jQuery(this).parent(".wpvr-floor-map").removeClass("fullwindow");
3473 jQuery(this).parents(".pano-wrap").removeClass("show-modal");
3474 });';
3475 //===Floor map Script End===//
3476
3477 if ($vrgallery_display) {
3478
3479 if (!$autoload) {
3480 $html .= 'jQuery(document).ready(function($){
3481 jQuery("#sccontrols' . $pano_suffix . '").hide();
3482 jQuery(".vrgctrl' . $pano_suffix . '").html(' . $sin_qout . $angle_up . $sin_qout . ');
3483 jQuery("#sccontrols' . $pano_suffix . '").hide();
3484 jQuery("#' . $panoid . ' .wpvr_slider_nav").hide();
3485 });';
3486 $html .= 'var slide' . $pano_suffix . ' = "down";
3487 jQuery(document).on("click","#vrgcontrols' . $pano_suffix . '",function() {
3488 if (slide' . $pano_suffix . ' == "up") {
3489 jQuery(".vrgctrl' . $pano_suffix . '").empty();
3490 jQuery(".vrgctrl' . $pano_suffix . '").html(' . $sin_qout . $angle_up . $sin_qout . ');
3491 slide' . $pano_suffix . ' = "down";
3492 jQuery("#' . $panoid . ' .wpvr_slider_nav").slideToggle();
3493 jQuery("#sccontrols' . $pano_suffix . '").slideToggle(function(){
3494 if (jQuery(".elementor-edit-mode .elementor-widget-container").length) {
3495 if (jQuery(this).is(":visible")) {
3496 jQuery(".elementor-edit-mode .elementor-widget-container .wpvr-cardboard .pnlm-container #sccontrols' . $pano_suffix . '").css({
3497 "display": "flex",
3498 "justify-content": "center",
3499 "align-items": "center",
3500 "gap": "15px"
3501 });
3502 }
3503 }
3504 if (jQuery(".bricks-is-frontend").length) {
3505 if (jQuery(this).is(":visible")) {
3506 jQuery(".bricks-is-frontend .wpvr-cardboard .pnlm-container #sccontrols' . $pano_suffix . '").css({
3507 "display": "flex",
3508 "justify-content": "center",
3509 "align-items": "center"
3510 });
3511 }
3512 }
3513 });
3514 }
3515 else {
3516 jQuery(".vrgctrl' . $pano_suffix . '").empty();
3517 jQuery(".vrgctrl' . $pano_suffix . '").html(' . $sin_qout . $angle_down . $sin_qout . ');
3518 slide' . $pano_suffix . ' = "up";
3519 jQuery("#' . $panoid . ' .wpvr_slider_nav").slideToggle();
3520 jQuery("#sccontrols' . $pano_suffix . '").slideToggle(function(){
3521 if (jQuery(".elementor-edit-mode .elementor-widget-container").length) {
3522 if (jQuery(this).is(":visible")) {
3523 jQuery(".elementor-edit-mode .elementor-widget-container .wpvr-cardboard .pnlm-container #sccontrols' . $pano_suffix . '").css({
3524 "display": "flex",
3525 "justify-content": "center",
3526 "align-items": "center",
3527 "gap": "15px"
3528 });
3529 }
3530 }
3531 if (jQuery(".bricks-is-frontend").length) {
3532 if (jQuery(this).is(":visible")) {
3533 jQuery(".bricks-is-frontend .wpvr-cardboard .pnlm-container #sccontrols' . $pano_suffix . '").css({
3534 "display": "flex",
3535 "justify-content": "center",
3536 "align-items": "center"
3537 });
3538 }
3539 }
3540 });
3541 }
3542 });';
3543 } else {
3544 $html .= 'jQuery(document).ready(function($){
3545 jQuery("#sccontrols' . $pano_suffix . '").show();
3546 jQuery(".vrgctrl' . $pano_suffix . '").html(' . $sin_qout . $angle_down . $sin_qout . ');
3547 jQuery("#' . $panoid . ' .wpvr_slider_nav").show();
3548 });';
3549 $html .= 'var slide' . $pano_suffix . ' = "down";
3550 jQuery(document).on("click","#vrgcontrols' . $pano_suffix . '",function() {
3551 if (slide' . $pano_suffix . ' == "up") {
3552 jQuery(".vrgctrl' . $pano_suffix . '").empty();
3553 jQuery(".vrgctrl' . $pano_suffix . '").html(' . $sin_qout . $angle_down . $sin_qout . ');
3554 slide' . $pano_suffix . ' = "down";
3555 } else {
3556 jQuery(".vrgctrl' . $pano_suffix . '").empty();
3557 jQuery(".vrgctrl' . $pano_suffix . '").html(' . $sin_qout . $angle_up . $sin_qout . ');
3558 slide' . $pano_suffix . ' = "up";
3559 }
3560 jQuery("#' . $panoid . ' .wpvr_slider_nav").slideToggle();
3561 jQuery("#sccontrols' . $pano_suffix . '").slideToggle(function(){
3562 if (jQuery(".elementor-edit-mode .elementor-widget-container").length) {
3563 if (jQuery(this).is(":visible")) {
3564 jQuery(".elementor-edit-mode .elementor-widget-container .wpvr-cardboard .pnlm-container #sccontrols' . $pano_suffix . '").css({
3565 "display": "flex",
3566 "justify-content": "center",
3567 "align-items": "center",
3568 "gap": "15px"
3569 });
3570 }
3571 }
3572 if (jQuery(".bricks-is-frontend").length) {
3573 if (jQuery(this).is(":visible")) {
3574 jQuery(".bricks-is-frontend .wpvr-cardboard .pnlm-container #sccontrols' . $pano_suffix . '").css({
3575 "display": "flex",
3576 "justify-content": "center",
3577 "align-items": "center"
3578 });
3579 }
3580 }
3581 });
3582 });';
3583 }
3584 } else {
3585 $html .= 'jQuery(document).ready(function($){
3586 jQuery("#sccontrols' . $pano_suffix . '").hide();
3587 jQuery("#' . $panoid . ' .wpvr_slider_nav").hide();
3588 jQuery(".vrgctrl' . $pano_suffix . '").html(' . $sin_qout . $angle_up . $sin_qout . ');
3589 });';
3590 $html .= 'var slide' . $pano_suffix . ' = "down";
3591 jQuery(document).on("click","#vrgcontrols' . $pano_suffix . '",function() {
3592 if (slide' . $pano_suffix . ' == "up") {
3593 jQuery(".vrgctrl' . $pano_suffix . '").empty();
3594 jQuery(".vrgctrl' . $pano_suffix . '").html(' . $sin_qout . $angle_up . $sin_qout . ');
3595 slide' . $pano_suffix . ' = "down";
3596 }
3597 else {
3598 jQuery(".vrgctrl' . $pano_suffix . '").empty();
3599 jQuery(".vrgctrl' . $pano_suffix . '").html(' . $sin_qout . $angle_down . $sin_qout . ');
3600 slide' . $pano_suffix . ' = "up";
3601 }
3602 jQuery("#' . $panoid . ' .wpvr_slider_nav").slideToggle();
3603 jQuery("#sccontrols' . $pano_suffix . '").slideToggle(function(){
3604 if (jQuery(".elementor-edit-mode .elementor-widget-container").length) {
3605 if (jQuery(this).is(":visible")) {
3606 jQuery(".elementor-edit-mode .elementor-widget-container .wpvr-cardboard .pnlm-container #sccontrols' . $pano_suffix . '").css({
3607 "display": "flex",
3608 "justify-content": "center",
3609 "align-items": "center",
3610 "gap": "15px"
3611 });
3612 }
3613 }
3614 if (jQuery(".bricks-is-frontend").length) {
3615 if (jQuery(this).is(":visible")) {
3616 jQuery(".bricks-is-frontend .wpvr-cardboard .pnlm-container #sccontrols' . $pano_suffix . '").css({
3617 "display": "flex",
3618 "justify-content": "center",
3619 "align-items": "center"
3620 });
3621 }
3622 }
3623 });
3624 });';
3625 }
3626 if (!$autoload) {
3627 $html .= 'jQuery(document).ready(function(){
3628 jQuery("#controls' . $pano_suffix . '").hide();
3629 jQuery("#zoom-in-out-controls' . $pano_suffix . '").hide();
3630 jQuery("#adcontrol' . $pano_suffix . '").hide();
3631 jQuery("#explainer_button_' . $pano_suffix . '").hide();
3632 jQuery("#generic_form_button_' . $pano_suffix . '").hide();
3633 jQuery("#floor_map_button_' . $pano_suffix . '").hide();
3634 jQuery("#vrgcontrols' . $pano_suffix . '").hide();
3635 jQuery("#cp-logo-controls").hide();
3636 jQuery(".custom-scene-navigation").hide();
3637 jQuery("#' . $panoid . '").find(".pnlm-panorama-info").hide();
3638 });';
3639 if ($vrgallery_display) {
3640 $html .= 'var load_once' . $pano_suffix . ' = "true";';
3641 $html .= 'panoshow' . $pano_suffix . '.on("load", function (){
3642 if (load_once' . $pano_suffix . ' == "true") {
3643 load_once' . $pano_suffix . ' = "false";
3644 jQuery("#sccontrols' . $pano_suffix . '").slideToggle(function(){
3645 if (jQuery(".elementor-edit-mode .elementor-widget-container").length) {
3646 if (jQuery(this).is(":visible")) {
3647 jQuery(".elementor-edit-mode .elementor-widget-container .wpvr-cardboard .pnlm-container #sccontrols' . $pano_suffix . '").css("display", "flex");
3648 }
3649 }
3650 if (jQuery(".bricks-is-frontend").length) {
3651 if (jQuery(this).is(":visible")) {
3652 jQuery(".bricks-is-frontend .wpvr-cardboard .pnlm-container #sccontrols' . $pano_suffix . '").css({
3653 "display": "flex",
3654 "justify-content": "center",
3655 "align-items": "center"
3656 });
3657 }
3658 }
3659 });
3660 jQuery("#' . $panoid . ' .wpvr_slider_nav").slideToggle();
3661 }
3662 });';
3663 }
3664 $html .= 'panoshow' . $pano_suffix . '.on("load", function (){
3665 jQuery("#controls' . $pano_suffix . '").show();
3666 jQuery("#zoom-in-out-controls' . $pano_suffix . '").show();
3667 jQuery("#adcontrol' . $pano_suffix . '").show();
3668 jQuery("#explainer_button_' . $pano_suffix . '").show();
3669 jQuery("#generic_form_button_' . $pano_suffix . '").show();
3670 jQuery("#floor_map_button_' . $pano_suffix . '").show();
3671 jQuery("#vrgcontrols' . $pano_suffix . '").show();
3672 jQuery("#cp-logo-controls").show();
3673 jQuery(".custom-scene-navigation").show();
3674 jQuery("#' . $panoid . '").find(".pnlm-panorama-info").show();
3675 });';
3676 }
3677
3678 //==Old code working properly==//
3679
3680 $previeword = "Click to Load Panorama";
3681 if (isset($postdata['previewtext']) && $postdata['previewtext'] != '') {
3682 $previeword = $postdata['previewtext'];
3683 }
3684 $html .= 'jQuery(".elementor-tab-title").click(function(){
3685 var element_id;
3686 var pano_id;
3687 var element_id = this.id;
3688 element_id = element_id.split("-");
3689 element_id = element_id[3];
3690 jQuery("#elementor-tab-content-"+element_id).find("#' . $master_container_id . '").children("div").eq(1).addClass("awwww");
3691 var pano_id = jQuery(".awwww").attr("id");
3692 jQuery("#elementor-tab-content-"+element_id).find("#' . $master_container_id . '").children("div").eq(1).removeClass("awwww");;
3693 if (pano_id != undefined) {
3694 if (pano_id == "' . $panoid . '") {
3695 jQuery("#' . $panoid . '").children(".pnlm-render-container").remove();
3696 jQuery("#' . $panoid . '").children(".pnlm-ui").remove();
3697 panoshow' . $pano_suffix . ' = pannellum.viewer(response[0]["panoid"], scenes);
3698 window.wpvrViewers = window.wpvrViewers || {};
3699 window.wpvrViewers[response[0]["panoid"]] = panoshow' . $pano_suffix . ';
3700 document.dispatchEvent(new CustomEvent("wpvr:viewer-ready", {
3701 detail: { containerId: response[0]["panoid"], viewer: panoshow' . $pano_suffix . ' }
3702 }));
3703 jQuery("#' . $panoid . '").children(".pnlm-ui").find(".pnlm-load-button p").text(' . wp_json_encode( (string) $previeword ) . ')
3704 setTimeout(function() {
3705 // panoshow' . $pano_suffix . '.loadScene("' . $default_scene . '");
3706 window.dispatchEvent(new Event("resize"));
3707 if (jQuery("#' . $panoid . '").children().children(".pnlm-panorama-info:visible").length > 0) {
3708 jQuery("#controls' . $pano_suffix . '").css("bottom", "55px");
3709 } else {
3710 jQuery("#controls' . $pano_suffix . '").css("bottom", "5px");
3711 }
3712 }, 200);
3713 }
3714 }
3715 });';
3716 $html .= 'jQuery(".geodir-tab-head dd, #vr-tour-tab").click(function(){
3717 jQuery("#' . $panoid . '").children(".pnlm-render-container").remove();
3718 jQuery("#' . $panoid . '").children(".pnlm-ui").remove();
3719 panoshow' . $pano_suffix . ' = pannellum.viewer(response[0]["panoid"], scenes);
3720 window.wpvrViewers = window.wpvrViewers || {};
3721 window.wpvrViewers[response[0]["panoid"]] = panoshow' . $pano_suffix . ';
3722 document.dispatchEvent(new CustomEvent("wpvr:viewer-ready", {
3723 detail: { containerId: response[0]["panoid"], viewer: panoshow' . $pano_suffix . ' }
3724 }));
3725 setTimeout(function() {
3726 panoshow' . $pano_suffix . '.loadScene(' . wp_json_encode( (string) $default_scene ) . ');
3727 window.dispatchEvent(new Event("resize"));
3728 if (jQuery("#' . $panoid . '").children().children(".pnlm-panorama-info:visible").length > 0) {
3729 jQuery("#controls' . $pano_suffix . '").css("bottom", "55px");
3730 }
3731 else {
3732 jQuery("#controls' . $pano_suffix . '").css("bottom", "5px");
3733 }
3734 }, 200);
3735 });';
3736 if (isset($previeword) && $previeword != '') {
3737 $html .= '
3738 jQuery("#' . $panoid . '").children(".pnlm-ui").find(".pnlm-load-button p").text(' . wp_json_encode( (string) $previeword ) . ')
3739 ';
3740 }
3741 if ($default_global_zoom != '' || $max_global_zoom != '' || $min_global_zoom != '') {
3742 $html .= 'jQuery(".globalzoom").val("on").change();';
3743 }
3744
3745 $html .= 'jQuery("#' . $panoid . ' .pnlm-title-box").on("mouseenter", function(){
3746 jQuery(this).attr("title", jQuery(this).text());
3747 });
3748 jQuery("#' . $panoid . ' .pnlm-title-box").on("mouseleave", function(){
3749 jQuery(this).removeAttr("title");
3750 });';
3751 $html .= '});';
3752 $html .= '})(jQuery);';
3753 $html .= '</script>';
3754 $tour_data = [];
3755 if(defined("WPVR_PRO_VERSION")){
3756 $tour_data = array(
3757 'explainerControlSwitch' => (
3758 isset( $postdata['explainerSwitch'] )
3759 && in_array( $postdata['explainerSwitch'], array( true, 1, '1', 'on' ), true )
3760 ) ? 'on' : 'off',
3761 'floor_plan_enable' => $floor_plan_enable ?? '',
3762 'floor_plan_image' => $floor_plan_image ?? '',
3763 'custom_control' => $custom_control ?? '',
3764 );
3765 }
3766 ob_start();
3767 // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
3768 echo $html;
3769 $output = ob_get_clean();
3770 return apply_filters('wpvr_generate_tour_layout_html', $output ,$postdata ,$id, $tour_data);
3771 }
3772
3773 function replace_callback($matches){
3774 foreach ($matches as $match){
3775 return str_replace('<img','<img decoding="async"',$match);
3776 }
3777
3778 }
3779
3780 private function sanitize_content_preserve_styles($content, $allow_forms = false) {
3781 // Decode HTML entities first (in case content was encoded in database)
3782 $content = html_entity_decode($content, ENT_QUOTES | ENT_HTML5, 'UTF-8');
3783
3784 // Escape or strip <script> blocks
3785 if ($allow_forms) {
3786 $content = preg_replace('/<script\b[^>]*>[\s\S]*?<\/script>/i', '', $content);
3787 } else {
3788 $content = preg_replace_callback('/<script\b[^>]*>(.*?)<\/script>/si', function($matches) {
3789 return esc_html($matches[0]); // Convert to plain text
3790 }, $content);
3791 }
3792
3793 // Strip dangerous URL-based attributes
3794 $content = preg_replace('/(href|action|formaction)\s*=\s*["\']?\s*(javascript|vbscript|data|about):/i', '$1=""', $content);
3795
3796 // Escape inline event handlers (onclick, onhover, etc.) to display as text
3797 $content = preg_replace_callback('/\s*(on\w+)\s*=\s*(["\'])([^"\']*)\2/i', function($matches) {
3798 // Escape the attribute value but keep the attribute name visible as text
3799 return ' ' . esc_html($matches[1]) . '=' . $matches[2] . esc_html($matches[3]) . $matches[2];
3800 }, $content);
3801 $content = preg_replace_callback('/\s*(on\w+)\s*=\s*([^>\s]+)/i', function($matches) {
3802 // Handle unquoted event handlers
3803 return ' ' . esc_html($matches[1]) . '=' . esc_html($matches[2]);
3804 }, $content);
3805
3806 // Remove unsafe embedded/interactive elements
3807 if ($allow_forms) {
3808 $content = preg_replace('/<(object|embed|applet|frame|frameset|meta|link|base)\b[^>]*>/i', '', $content);
3809 $content = preg_replace('/<\/(object|embed|applet|frame|frameset|meta|link|base)>/i', '', $content);
3810 } else {
3811 $content = preg_replace('/<(object|embed|applet|frame|frameset|meta|link|base|form|input|button|textarea|select|option)\b[^>]*>/i', '', $content);
3812 $content = preg_replace('/<\/(object|embed|applet|frame|frameset|meta|link|base|form|input|button|textarea|select|option)>/i', '', $content);
3813 }
3814
3815 // Clean style attributes safely
3816 $content = preg_replace_callback('/style\s*=\s*["\']([^"\']*)["\']/', function($matches) {
3817 $style = $matches[1];
3818 $style = preg_replace('/expression\s*\(/i', '', $style);
3819 $style = preg_replace('/(javascript|vbscript|data|about)\s*:/i', '', $style);
3820 $style = preg_replace('/url\s*\(\s*["\']?\s*(javascript|vbscript|data):/i', '', $style);
3821 $style = preg_replace('/behavior\s*:/i', '', $style);
3822 $style = preg_replace('/-moz-binding\s*:/i', '', $style);
3823 return 'style="' . esc_attr($style) . '"';
3824 }, $content);
3825
3826 // Sanitize <style> blocks
3827 $content = preg_replace_callback('/<style\b[^>]*>(.*?)<\/style>/si', function($matches) {
3828 $css = $matches[1];
3829 $css = preg_replace('/(expression|javascript|vbscript|data|about)\s*:/i', '', $css);
3830 $css = preg_replace('/url\s*\(\s*["\']?\s*(javascript|vbscript|data):/i', '', $css);
3831 $css = preg_replace('/behavior\s*:/i', '', $css);
3832 $css = preg_replace('/-moz-binding\s*:/i', '', $css);
3833 return '<style>' . esc_html($css) . '</style>';
3834 }, $content);
3835
3836 // Allow iframes and styles from safe sources only
3837 $allowed_tags = wp_kses_allowed_html('post');
3838 $allowed_tags['style'] = [
3839 'type' => true,
3840 'id' => true,
3841 'class' => true,
3842 'media' => true,
3843 ];
3844 $allowed_tags['iframe'] = [
3845 'src' => true,
3846 'width' => true,
3847 'height' => true,
3848 'frameborder' => true,
3849 'allowfullscreen' => true,
3850 'class' => true,
3851 'style' => true,
3852 'title' => true,
3853 'allow' => true,
3854 'name' => true,
3855 'referrerpolicy' => true,
3856 'loading' => true,
3857 'sandbox' => true,
3858 ];
3859 $allowed_tags['img'] = [
3860 'src' => true,
3861 'alt' => true,
3862 'title' => true,
3863 'width' => true,
3864 'height' => true,
3865 'class' => true,
3866 'id' => true,
3867 'style' => true,
3868 'loading' => true,
3869 'srcset' => true,
3870 'sizes' => true,
3871 ];
3872
3873 if ($allow_forms) {
3874 $form_attributes = [
3875 'id' => true,
3876 'class' => true,
3877 'style' => true,
3878 'name' => true,
3879 'value' => true,
3880 'type' => true,
3881 'placeholder' => true,
3882 'action' => true,
3883 'method' => true,
3884 'target' => true,
3885 'enctype' => true,
3886 'disabled' => true,
3887 'readonly' => true,
3888 'required' => true,
3889 'checked' => true,
3890 'selected' => true,
3891 'multiple' => true,
3892 'size' => true,
3893 'rows' => true,
3894 'cols' => true,
3895 'maxlength' => true,
3896 'minlength' => true,
3897 'min' => true,
3898 'max' => true,
3899 'step' => true,
3900 'pattern' => true,
3901 'autocomplete' => true,
3902 'autofocus' => true,
3903 'for' => true,
3904 'data-*' => true,
3905 'data-form_id' => true,
3906 'data-form_instance' => true,
3907 'data-name' => true,
3908 'data-type' => true,
3909 'aria-invalid' => true,
3910 'aria-required' => true,
3911 'aria-label' => true,
3912 'aria-describedby' => true,
3913 'aria-labelledby' => true,
3914 ];
3915 $allowed_tags['form'] = $form_attributes;
3916 $allowed_tags['input'] = $form_attributes;
3917 $allowed_tags['button'] = $form_attributes;
3918 $allowed_tags['textarea'] = $form_attributes;
3919 $allowed_tags['select'] = $form_attributes;
3920 $allowed_tags['option'] = $form_attributes;
3921 $allowed_tags['optgroup'] = $form_attributes;
3922 $allowed_tags['label'] = $form_attributes;
3923 $allowed_tags['fieldset'] = $form_attributes;
3924 $allowed_tags['legend'] = $form_attributes;
3925 if (!isset($allowed_tags['div'])) {
3926 $allowed_tags['div'] = [];
3927 }
3928 $allowed_tags['div']['data-*'] = true;
3929 $allowed_tags['div']['data-form_id'] = true;
3930 $allowed_tags['div']['data-form_instance'] = true;
3931 if (!isset($allowed_tags['span'])) {
3932 $allowed_tags['span'] = [];
3933 }
3934 $allowed_tags['span']['data-*'] = true;
3935 }
3936
3937 // Apply wp_kses() to keep only allowed tags/attributes
3938 $content = wp_kses($content, $allowed_tags);
3939
3940 // Finally, validate iframe src for security (allow https only, block javascript: etc.)
3941 $content = preg_replace_callback('/<iframe[^>]+src=["\']([^"\']+)["\'][^>]*>(?:<\/iframe>)?/i', function($matches) {
3942 $src = $matches[1];
3943 // Allow any https:// or http:// URL, but block javascript:, data:, vbscript:, etc.
3944 if (preg_match('/^(https?:)?\/\//i', $src) && !preg_match('/^(javascript|data|vbscript|about):/i', $src)) {
3945 return $matches[0]; // keep safe iframe
3946 }
3947 // Strip unsafe iframe
3948 return '';
3949 }, $content);
3950
3951 return $content;
3952 }
3953
3954 private function normalize_hotspot_external_url($url) {
3955 $url = trim((string) $url);
3956
3957 if (
3958 $url === '' ||
3959 preg_match('/^[a-z][a-z0-9+.-]*:/i', $url) ||
3960 preg_match('/^[\/#?]/', $url)
3961 ) {
3962 return $url;
3963 }
3964
3965 if (preg_match('/^[^\s\/]+\.[^\s\/]+(?:[\/?#]|$)/i', $url)) {
3966 return 'https://' . $url;
3967 }
3968
3969 return $url;
3970 }
3971
3972 /**
3973 * Get attachment ID from URL with in-memory static cache and WordPress object cache.
3974 *
3975 * @param string $url Image URL.
3976 * @return int Attachment ID or 0.
3977 */
3978 private function get_attachment_id_by_url($url)
3979 {
3980 static $memory_cache = array();
3981
3982 if (empty($url) || !is_string($url)) {
3983 return 0;
3984 }
3985
3986 if (isset($memory_cache[$url])) {
3987 return $memory_cache[$url];
3988 }
3989
3990 $cache_key = 'wpvr_att_id_' . md5($url);
3991 $cached_id = wp_cache_get($cache_key, 'wpvr');
3992 if (false !== $cached_id) {
3993 $memory_cache[$url] = (int) $cached_id;
3994 return (int) $cached_id;
3995 }
3996
3997 $attachment_id = attachment_url_to_postid($url);
3998 $attachment_id = $attachment_id ? (int) $attachment_id : 0;
3999
4000 wp_cache_set($cache_key, $attachment_id, 'wpvr', HOUR_IN_SECONDS);
4001 $memory_cache[$url] = $attachment_id;
4002
4003 return $attachment_id;
4004 }
4005
4006 }
4007