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

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

3,721 lines 193.4 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
928 if (!empty($panodata["scene-list"])) {
929 foreach ($panodata["scene-list"] as $panoscenes) {
930 $scene_ititle = '';
931 if (isset($panoscenes["scene-ititle"])) {
932 $scene_ititle = sanitize_text_field($panoscenes["scene-ititle"]);
933 }
934
935 $scene_author = '';
936 if (isset($panoscenes["scene-author"])) {
937 $scene_author = sanitize_text_field($panoscenes["scene-author"]);
938 }
939
940 $scene_author_url = '';
941 if (isset($panoscenes["scene-author-url"])) {
942 $scene_author_url = esc_url($panoscenes["scene-author-url"]);
943 }
944
945 $scene_vaov = 180;
946 if (isset($panoscenes["scene-vaov"])) {
947 $scene_vaov = (float)$panoscenes["scene-vaov"];
948 }
949
950 $scene_haov = 360;
951 if (isset($panoscenes["scene-haov"])) {
952 $scene_haov = (float)$panoscenes["scene-haov"];
953 }
954
955
956 $scene_vertical_offset = 0;
957 if (isset($panoscenes["scene-vertical-offset"])) {
958 $scene_vertical_offset = (float)$panoscenes["scene-vertical-offset"];
959 }
960
961 $default_scene_pitch = null;
962 if (isset($panoscenes["scene-pitch"])) {
963 $default_scene_pitch = (float)$panoscenes["scene-pitch"];
964 }
965
966 $default_scene_yaw = null;
967 if (isset($panoscenes["scene-yaw"])) {
968 $default_scene_yaw = (float)$panoscenes["scene-yaw"];
969 }
970
971 $scene_max_pitch = '';
972 if (isset($panoscenes["scene-maxpitch"])) {
973 $scene_max_pitch = (float)$panoscenes["scene-maxpitch"];
974 }
975
976
977 $scene_min_pitch = '';
978 if (isset($panoscenes["scene-minpitch"])) {
979 $scene_min_pitch = (float)$panoscenes["scene-minpitch"];
980 }
981
982
983 $scene_max_yaw = '';
984 if (isset($panoscenes["scene-maxyaw"])) {
985 $scene_max_yaw = (float)$panoscenes["scene-maxyaw"];
986 }
987
988
989 $scene_min_yaw = '';
990 if (isset($panoscenes["scene-minyaw"])) {
991 $scene_min_yaw = (float)$panoscenes["scene-minyaw"];
992 }
993
994 $default_zoom = 100;
995 if (isset($panoscenes["scene-zoom"]) && $panoscenes["scene-zoom"] != "") {
996 $default_zoom = $panoscenes["scene-zoom"];
997 } else {
998 if ($default_global_zoom != '') {
999 $default_zoom = (int)$default_global_zoom;
1000 }
1001 }
1002
1003
1004 $max_zoom = 120;
1005 if (isset($panoscenes["scene-maxzoom"]) && $panoscenes["scene-maxzoom"] != '') {
1006 $max_zoom = (int)$panoscenes["scene-maxzoom"];
1007 } else {
1008 if ($max_global_zoom != '') {
1009 $max_zoom = (int)$max_global_zoom;
1010 }
1011 }
1012
1013
1014
1015 $min_zoom = 50;
1016 if (isset($panoscenes["scene-minzoom"]) && $panoscenes["scene-minzoom"] != '') {
1017 $min_zoom = (int)$panoscenes["scene-minzoom"];
1018 } else {
1019 if ($min_global_zoom != '') {
1020 $min_zoom = (int)$min_global_zoom;
1021 }
1022 }
1023
1024
1025 $hotspot_datas = array();
1026 if (isset($panoscenes["hotspot-list"])) {
1027 $hotspot_datas = $panoscenes["hotspot-list"];
1028 }
1029
1030 $hotspots = array();
1031
1032
1033 foreach ($hotspot_datas as $hotspot_data) {
1034 $status = get_option('wpvr_edd_license_status');
1035 if ($status !== false && $status == 'valid') {
1036 if (!empty($hotspot_data["hotspot-customclass-pro"]) && $hotspot_data["hotspot-customclass-pro"] != 'none') {
1037 $hotspot_data['hotspot-customclass'] = $hotspot_data["hotspot-customclass-pro"] . ' custom-' . $id.'-' . $panoscenes['scene-id'] .'-'. sanitize_html_class($hotspot_data['hotspot-title']);
1038 }
1039 if (isset($hotspot_data['hotspot-blink'])) {
1040 $hotspotblink = $hotspot_data['hotspot-blink'];
1041 }
1042 }
1043 $has_hotspot_scene_pitch = isset($hotspot_data["hotspot-scene-pitch"])
1044 && $hotspot_data["hotspot-scene-pitch"] !== '';
1045 $has_hotspot_scene_yaw = isset($hotspot_data["hotspot-scene-yaw"])
1046 && $hotspot_data["hotspot-scene-yaw"] !== '';
1047
1048 $hotspot_type = $hotspot_data["hotspot-type"] !== 'scene' ? 'info' : $hotspot_data["hotspot-type"];
1049 $hotspot_content = '';
1050
1051 ob_start();
1052 do_action('wpvr_hotspot_content', $hotspot_data);
1053 $hotspot_content = ob_get_clean();
1054
1055 if (!$hotspot_content) {
1056 $hotspot_content = $hotspot_data["hotspot-content"];
1057 }
1058
1059 $hotspot_url = $this->normalize_hotspot_external_url($hotspot_data["hotspot-url"] ?? '');
1060
1061 if (isset($hotspot_data["hotspot-url-open"])) {
1062 // New UI: "on" means new tab; legacy renderer: "on" means same tab.
1063 $wpvr_url_open = $hotspot_data["hotspot-url-open"] === 'on' ? 'off' : 'on';
1064 } elseif (isset($hotspot_data["wpvr_url_open"][0])) {
1065 $wpvr_url_open = $hotspot_data["wpvr_url_open"][0];
1066 } else {
1067 $wpvr_url_open = "off";
1068 }
1069 $on_hover_content = preg_replace_callback(
1070 '/<p>\s*(<img[^>]*>)\s*<br>\s*<\/p>/i',
1071 function ($matches) {
1072 return $matches[1];
1073 },
1074 $hotspot_data['hotspot-hover'] ?? ''
1075 );
1076
1077
1078 $is_fluent_form = isset($hotspot_data["hotspot-type"]) && 'fluent_form' === $hotspot_data["hotspot-type"];
1079 $on_hover_content = $this->sanitize_content_preserve_styles($on_hover_content ?? '', false);
1080 $on_click_content = preg_replace_callback('/<img[^>]*>/', "replace_callback", $hotspot_content ?? '');
1081 $on_click_content = $this->sanitize_content_preserve_styles($on_click_content ?? '', $is_fluent_form);
1082
1083 // Shape is independent of the optional custom icon in the
1084 // new editor, so it must always be included in the public
1085 // hotspot configuration.
1086 $hotspot_shape = isset( $hotspot_data['hotspot-shape'] )
1087 && in_array( $hotspot_data['hotspot-shape'], [ 'round', 'square', 'hexagon' ], true )
1088 ? $hotspot_data['hotspot-shape']
1089 : 'round';
1090 $hotspot_data_for_on_click=[];
1091 if( ('info' === $hotspot_type || 'fluent_form' === $hotspot_data["hotspot-type"]) && !empty($on_click_content)){
1092 $hotspot_data_for_on_click = [
1093 'on_click_content' => $on_click_content,
1094 'tour_id' => $id,
1095 'scene_id' => $panoscenes['scene-id'],
1096 'hotspot_id' => sanitize_html_class($hotspot_data['hotspot-title']),
1097 ];
1098 } elseif('info' === $hotspot_type && !empty($hotspot_url)){
1099 $hotspot_data_for_on_click = [
1100 'on_click_content' => '',
1101 'tour_id' => $id,
1102 'scene_id' => $panoscenes['scene-id'],
1103 'hotspot_id' => sanitize_html_class($hotspot_data['hotspot-title']),
1104 ];
1105 }
1106
1107 $hotspot_info = array(
1108 "text" => esc_html(sanitize_text_field($hotspot_data["hotspot-title"])),
1109 "pitch" => $hotspot_data["hotspot-pitch"],
1110 "yaw" => $hotspot_data["hotspot-yaw"],
1111 "type" => $hotspot_type,
1112 "cssClass" => $hotspot_data["hotspot-customclass"],
1113 "URL" => $hotspot_url,
1114 "wpvr_url_open" => $wpvr_url_open,
1115 "clickHandlerArgs" => $hotspot_data_for_on_click,
1116 'createTooltipArgs' => !empty(trim($on_hover_content)) ? trim($on_hover_content) : '',
1117 "sceneId" => $hotspot_data["hotspot-scene"],
1118 'hotspot_type' => $hotspot_data['hotspot-type'],
1119 'hotspot_target' => 'notBlank',
1120 'hotspot_shape' => $hotspot_shape,
1121 );
1122
1123 // An omitted entry angle lets Pannellum use the target
1124 // scene's own default face. Keep explicit zero values.
1125 if (!empty($hotspot_data["hotspot-scene"])) {
1126 if ($has_hotspot_scene_pitch) {
1127 $hotspot_info['targetPitch'] = (float)$hotspot_data["hotspot-scene-pitch"];
1128 }
1129 if ($has_hotspot_scene_yaw) {
1130 $hotspot_info['targetYaw'] = (float)$hotspot_data["hotspot-scene-yaw"];
1131 }
1132 }
1133 $hotspot_info['URL'] = ($hotspot_data['hotspot-type'] === 'fluent_form' || $hotspot_data['hotspot-type'] === 'wc_product') ? '' : $hotspot_info['URL'];
1134
1135 if ($hotspot_data["hotspot-customclass"] == 'none' || $hotspot_data["hotspot-customclass"] == '') {
1136 unset($hotspot_info["cssClass"]);
1137 }
1138 array_push($hotspots, $hotspot_info);
1139 }
1140
1141 $device_scene = $panoscenes['scene-attachment-url'];
1142 $mobile_media_resize = get_option('mobile_media_resize');
1143 $file_accessible = ini_get('allow_url_fopen');
1144 if ($mobile_media_resize == "true" && $device_scene ) {
1145 if ($file_accessible == "1") {
1146 $image_info = getimagesize($device_scene);
1147 if ( isset($image_info[0]) && $image_info[0] > 4096) {
1148 $src_to_id_for_mobile = '';
1149 $src_to_id_for_desktop = '';
1150 if (wpvr_isMobileDevice()) {
1151 $src_to_id_for_mobile = attachment_url_to_postid($panoscenes['scene-attachment-url']);
1152 if ($src_to_id_for_mobile) {
1153 $mobile_scene = wp_get_attachment_image_src($src_to_id_for_mobile, 'wpvr_mobile');
1154 if ($mobile_scene[3]) {
1155 $device_scene = $mobile_scene[0];
1156 }
1157 }
1158 } else {
1159 $src_to_id_for_desktop = attachment_url_to_postid($panoscenes['scene-attachment-url']);
1160 if ($src_to_id_for_desktop) {
1161 $desktop_scene = wp_get_attachment_image_src($src_to_id_for_mobile, 'full');
1162 if (isset($desktop_scene[0])) {
1163 $device_scene = $desktop_scene[0];
1164 }
1165 }
1166 }
1167 }
1168 }
1169 }
1170
1171 $scene_info = array();
1172
1173 if ($panoscenes["scene-type"] == 'cubemap') {
1174 $pano_attachment = array(
1175 $panoscenes["scene-attachment-url-face0"],
1176 $panoscenes["scene-attachment-url-face1"],
1177 $panoscenes["scene-attachment-url-face2"],
1178 $panoscenes["scene-attachment-url-face3"],
1179 $panoscenes["scene-attachment-url-face4"],
1180 $panoscenes["scene-attachment-url-face5"]
1181 );
1182
1183 $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);
1184 } else {
1185 $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);
1186 }
1187
1188
1189 if (isset($panoscenes["ptyscene"])) {
1190 if ($panoscenes["ptyscene"] == "off") {
1191 unset($scene_info['pitch']);
1192 unset($scene_info['yaw']);
1193 }
1194 }
1195
1196 if (!$show_scene_info || empty($panoscenes["scene-ititle"])) {
1197 unset($scene_info['title']);
1198 }
1199 if (!$show_scene_info || empty($panoscenes["scene-author"])) {
1200 unset($scene_info['author']);
1201 }
1202 if (!$show_scene_info || empty($panoscenes["scene-author-url"])) {
1203 unset($scene_info['authorURL']);
1204 }
1205
1206 if (empty($scene_vaov)) {
1207 unset($scene_info['vaov']);
1208 }
1209
1210 if (empty($scene_haov)) {
1211 unset($scene_info['haov']);
1212 }
1213
1214 if (empty($scene_vertical_offset)) {
1215 unset($scene_info['vOffset']);
1216 }
1217
1218 if (isset($panoscenes["cvgscene"])) {
1219 if ($panoscenes["cvgscene"] == "off") {
1220 unset($scene_info['maxPitch']);
1221 unset($scene_info['minPitch']);
1222 }
1223 }
1224 if (empty($panoscenes["scene-maxpitch"])) {
1225 unset($scene_info['maxPitch']);
1226 }
1227
1228 if (empty($panoscenes["scene-minpitch"])) {
1229 unset($scene_info['minPitch']);
1230 }
1231
1232 if (isset($panoscenes["chgscene"])) {
1233 if ($panoscenes["chgscene"] == "off") {
1234 unset($scene_info['maxYaw']);
1235 unset($scene_info['minYaw']);
1236 }
1237 }
1238 if (empty($panoscenes["scene-maxyaw"])) {
1239 unset($scene_info['maxYaw']);
1240 }
1241
1242 if (empty($panoscenes["scene-minyaw"])) {
1243 unset($scene_info['minYaw']);
1244 }
1245
1246 // if (isset($panoscenes["czscene"])) {
1247 // if ($panoscenes["czscene"] == "off") {
1248 // unset($scene_info['hfov']);
1249 // unset($scene_info['maxHfov']);
1250 // unset($scene_info['minHfov']);
1251 // }
1252 // }
1253
1254 $scene_array = array();
1255 $scene_array = array(
1256 $panoscenes["scene-id"] => $scene_info
1257 );
1258 $scene_data[$panoscenes["scene-id"]] = $scene_info;
1259 }
1260 }
1261
1262 $pano_id_array = array();
1263 $pano_id_array = array("panoid" => $panoid);
1264 $pano_response = array();
1265 $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);
1266 if (empty($autorotation)) {
1267 unset($pano_response['autoRotate']);
1268 unset($pano_response['autoRotateInactivityDelay']);
1269 unset($pano_response['autoRotateStopDelay']);
1270 }
1271 if (empty($autorotationinactivedelay)) {
1272 unset($pano_response['autoRotateInactivityDelay']);
1273 }
1274 if (empty($autorotationstopdelay)) {
1275 unset($pano_response['autoRotateStopDelay']);
1276 }
1277 $response = array();
1278 $response = array($pano_id_array, $pano_response);
1279 if (!empty($response)) {
1280 $response = json_encode($response);
1281 }
1282
1283
1284 if (empty($width)) {
1285 $width = '600px';
1286 }
1287 if (empty($height)) {
1288 $height = '400px';
1289 }
1290 $foreground_color = '#fff';
1291 $pulse_color = wpvr_hex2rgb($hotspoticoncolor);
1292 $rgb = wpvr_HTMLToRGB($hotspoticoncolor);
1293 $hsl = wpvr_RGBToHSL($rgb);
1294 if ($hsl->lightness > 200) {
1295 $foreground_color = '#000000';
1296 } else {
1297 $foreground_color = '#fff';
1298 }
1299 $html = '';
1300
1301 $html .= '<style>';
1302 if ($width == 'embed') {
1303 $html .= 'body{
1304 overflow: hidden;
1305 }';
1306 }
1307 $status = get_option('wpvr_edd_license_status');
1308 if ($status !== false && $status == 'valid') {
1309 if(isset($postdata['customcss_enable']) && $postdata['customcss_enable'] == 'on'){
1310 $html .= isset($postdata['customcss']) ? $postdata['customcss'] : '';
1311 }
1312 }
1313 $pano_suffix = (strpos($panoid, 'pano') === 0) ? substr($panoid, 4) : (string) $panoid;
1314 $panoid2 = 'pano2' . $pano_suffix;
1315 $master_container_id = ($panoid === 'pano' . $id) ? 'master-container' : ('master-container-' . $pano_suffix);
1316 $status = get_option('wpvr_edd_license_status');
1317 if ($status !== false && $status == 'valid' && ! empty( $panodata['scene-list'] ) && is_array( $panodata['scene-list'] )) {
1318 foreach ($panodata['scene-list'] as $panoscenes){
1319 if ( empty( $panoscenes['hotspot-list'] ) || ! is_array( $panoscenes['hotspot-list'] ) ) {
1320 continue;
1321 }
1322 foreach($panoscenes['hotspot-list'] as $hotspot){
1323 if (isset($hotspot['hotspot-customclass-color-icon-value']) && !empty($hotspot['hotspot-customclass-color-icon-value'])) {
1324 $hotspoticoncolor = $hotspot['hotspot-customclass-color-icon-value'];
1325 } else {
1326 $hotspoticoncolor = "#00b4ff";
1327 }
1328 $hotspot_border = '';
1329 if(isset($hotspot['hotspot-border']) && $hotspot['hotspot-border'] == 'on'){
1330 $border_width = $hotspot['hotspot-border-width'];
1331 $border_color = $hotspot['hotspot-border-color'];
1332 $border_style = $hotspot['hotspot-border-style'];
1333 $hotspot_border = 'border: '.$border_width.'px '.$border_style.' '.$border_color.';';
1334 }
1335 $hotspot_background_color = 'background-color: ' . $hotspoticoncolor . ';';
1336 $hotspot_animation = ' animation: icon-pulse' . $panoid . '-' . $panoscenes['scene-id'] . '-' . sanitize_html_class($hotspot['hotspot-title']) . ' 1.5s infinite cubic-bezier(.25, 0, 0, 1);
1337 '. $hotspot_border.'';
1338 $pulse_color = wpvr_hex2rgb($hotspoticoncolor);
1339 if (!empty($hotspot["hotspot-customclass-pro"]) && $hotspot["hotspot-customclass-pro"] != 'none') {
1340 $border_radius = ' border-radius: 100%;';
1341 $hotspot_shape = isset($hotspot["hotspot-shape"]) ? $hotspot["hotspot-shape"] : 'round';
1342 if($hotspot_shape === 'square'){
1343 $border_radius = '';
1344 }
1345 if ($hotspot_shape === 'hexagon') {
1346 $border_radius = '';
1347 $hotspot_background_color = 'background-color: transparent;';
1348 $hotspot_animation = '';
1349 }
1350
1351 if(isset($hotspot['hotspot-custom-icon-color-value']) && !empty($hotspot['hotspot-custom-icon-color-value'])){
1352 $foreground_color = $hotspot['hotspot-custom-icon-color-value'];
1353 }
1354
1355 $html .= '#' . $panoid . ' div.pnlm-hotspot-base.fas.custom-' . $id.'-' . $panoscenes['scene-id'] .'-'. sanitize_html_class($hotspot['hotspot-title']).',
1356 #' . $panoid . ' div.pnlm-hotspot-base.fab.custom-' . $id.'-' . $panoscenes['scene-id'] .'-'. sanitize_html_class($hotspot['hotspot-title']).',
1357 #' . $panoid . ' div.pnlm-hotspot-base.fa-solid.custom-' . $id.'-' . $panoscenes['scene-id'] .'-'. sanitize_html_class($hotspot['hotspot-title']).',
1358 #' . $panoid . ' div.pnlm-hotspot-base.fa.custom-' . $id.'-' . $panoscenes['scene-id'] .'-'. sanitize_html_class($hotspot['hotspot-title']).',
1359 #' . $panoid . ' div.pnlm-hotspot-base.far.custom-' . $id.'-' . $panoscenes['scene-id'] .'-'. sanitize_html_class($hotspot['hotspot-title']).' {
1360 display: block !important;
1361 '.$hotspot_background_color.'
1362 color: ' . $foreground_color . ';
1363 '.$border_radius.'
1364 width: 30px;
1365 height: 30px;
1366 font-size: 16px;
1367 line-height: 30px;
1368 '.$hotspot_animation.'
1369 }';
1370
1371 if($hotspot_shape === 'hexagon'){
1372
1373 $html .= '#' . $panoid . ' .custom-' . $id . '-' . $panoscenes['scene-id'] . '-' . sanitize_html_class($hotspot['hotspot-title']) . ' .hexagon-wrapper svg path {
1374 fill: ' . $hotspoticoncolor . ';
1375 }';
1376
1377 $html .= '#' . $panoid . ' .custom-' . $id . '-' . $panoscenes['scene-id'] . '-' . sanitize_html_class($hotspot['hotspot-title']) . '.pnlm-tooltip:after{
1378 content: "";
1379 position: absolute;
1380 left: 50%;
1381 top: 50%;
1382 transform: translate(-50%, -50%);
1383 width: 85%;
1384 height: 85%;
1385 animation: icon-pulse' . $panoid . '-' . $panoscenes['scene-id'] . '-' . sanitize_html_class($hotspot['hotspot-title']) . ' 1.5s infinite cubic-bezier(.25, 0, 0, 1);
1386 border-radius: 100%;
1387 z-index: -2;
1388 }';
1389
1390 }
1391
1392 $html .= '#' . $panoid2 . ' div.pnlm-hotspot-base.fas.custom-' . $id.'-' . $panoscenes['scene-id'] .'-'. sanitize_html_class($hotspot['hotspot-title']).',
1393 #' . $panoid2 . ' div.pnlm-hotspot-base.fab.custom-' . $id.'-' . $panoscenes['scene-id'] .'-'. sanitize_html_class($hotspot['hotspot-title']).',
1394 #' . $panoid2 . ' div.pnlm-hotspot-base.fa-solid.custom-' . $id.'-' . $panoscenes['scene-id'] .'-'. sanitize_html_class($hotspot['hotspot-title']).',
1395 #' . $panoid2 . ' div.pnlm-hotspot-base.fa.custom-' . $id.'-' . $panoscenes['scene-id'] .'-'. sanitize_html_class($hotspot['hotspot-title']).',
1396 #' . $panoid2 . ' div.pnlm-hotspot-base.far.custom-' . $id.'-' . $panoscenes['scene-id'] .'-'. sanitize_html_class($hotspot['hotspot-title']).' {
1397 display: block !important;
1398 '.$hotspot_background_color.'
1399 color: ' . $foreground_color . ';
1400 '.$border_radius.'
1401 width: 30px;
1402 height: 30px;
1403 font-size: 16px;
1404 line-height: 30px;
1405 '.$hotspot_animation.'
1406 }';
1407 }
1408 if (isset($hotspot['hotspot-blink'])) {
1409 $hotspotblink = $hotspot['hotspot-blink'];
1410 if ($hotspotblink == 'on') {
1411 $html .= '@-webkit-keyframes icon-pulse' .$panoid .'-'. $panoscenes['scene-id'] .'-'. sanitize_html_class($hotspot['hotspot-title']) .' {
1412 0% {
1413 box-shadow: 0 0 0 0px rgba(' . $pulse_color[0] . ', 1);
1414 }
1415 100% {
1416 box-shadow: 0 0 0 10px rgba(' . $pulse_color[0] . ', 0);
1417 }
1418 }
1419 @keyframes icon-pulse' . $panoid . ' {
1420 0% {
1421 box-shadow: 0 0 0 0px rgba(' . $pulse_color[0] . ', 1);
1422 }
1423 100% {
1424 box-shadow: 0 0 0 10px rgba(' . $pulse_color[0] . ', 0);
1425 }
1426 }';
1427 $html .= '@-webkit-keyframes icon-pulse' .$panoid2 .'-'. $panoscenes['scene-id'] .'-'. sanitize_html_class($hotspot['hotspot-title']) .' {
1428 0% {
1429 box-shadow: 0 0 0 0px rgba(' . $pulse_color[0] . ', 1);
1430 }
1431 100% {
1432 box-shadow: 0 0 0 10px rgba(' . $pulse_color[0] . ', 0);
1433 }
1434 }
1435 @keyframes icon-pulse' . $panoid . ' {
1436 0% {
1437 box-shadow: 0 0 0 0px rgba(' . $pulse_color[0] . ', 1);
1438 }
1439 100% {
1440 box-shadow: 0 0 0 10px rgba(' . $pulse_color[0] . ', 0);
1441 }
1442 }';
1443 }
1444 }
1445
1446 }
1447
1448 }
1449
1450 }
1451
1452 $status = get_option('wpvr_edd_license_status');
1453 if ($status !== false && $status == 'valid') {
1454 if (!$gyro) {
1455 $html .= '#' . $panoid . ' div.pnlm-orientation-button {
1456 display: none;
1457 }';
1458 }
1459 } else {
1460 $html .= '#' . $panoid . ' div.pnlm-orientation-button {
1461 display: none;
1462 }';
1463 }
1464 $floor_plan_custom_color = isset($postdata['floor_plan_custom_color']) ? $postdata['floor_plan_custom_color'] : '#cca92c';
1465 $foreground_color_pointer = '#fff';
1466 if($floor_plan_custom_color != ''){
1467 $pointer_pulse = wpvr_hex2rgb($floor_plan_custom_color);
1468 $floor_rgb = wpvr_HTMLToRGB($floor_plan_custom_color);
1469 $floor_hsl = wpvr_RGBToHSL($floor_rgb);
1470 if ($floor_hsl->lightness > 200) {
1471 $foreground_color_pointer = '#000000';
1472 }
1473 $html .= '
1474 .wpvr-floor-map .floor-plan-pointer.add-pulse:before {
1475 border: 17px solid '.$floor_plan_custom_color.';
1476 }
1477 @-webkit-keyframes pulse {
1478 0% {
1479 -webkit-box-shadow: 0 0 0 0 rgba('.$pointer_pulse[0].', 0.7);
1480 }
1481 70% {
1482 -webkit-box-shadow: 0 0 0 10px rgba('.$pointer_pulse[0].', 0);
1483 }
1484 100% {
1485 -webkit-box-shadow: 0 0 0 0 rgba('.$pointer_pulse[0].', 0);
1486 }
1487 }
1488 @keyframes pulse {
1489 0% {
1490 -moz-box-shadow: 0 0 0 0 rgba('.$pointer_pulse[0].', 0.7);
1491 box-shadow: 0 0 0 0 rgba('.$pointer_pulse[0].', 0.7);
1492 }
1493 70% {
1494 -moz-box-shadow: 0 0 0 10px rgba('.$pointer_pulse[0].', 0);
1495 box-shadow: 0 0 0 10px rgba('.$pointer_pulse[0].', 0);
1496 }
1497 100% {
1498 -moz-box-shadow: 0 0 0 0 rgba('.$pointer_pulse[0].', 0);
1499 box-shadow: 0 0 0 0 rgba('.$pointer_pulse[0].', 0);
1500 }
1501 }';
1502 }
1503
1504 $html .= '</style>';
1505
1506
1507 $scene_animation = isset($postdata['sceneAnimation']) ? $postdata['sceneAnimation'] : 'off';
1508 $scene_animation_enabled = in_array( $scene_animation, array( 'on', '1', 1, true ), true );
1509
1510 if( $scene_animation_enabled && is_plugin_active( 'wpvr-pro/wpvr-pro.php' ) ) {
1511 $animation_type = isset($postdata['sceneAnimationName']) ? $postdata['sceneAnimationName'] : 'none';
1512 $animation_type = $animation_type === 'fade' ? 'fade_in' : $animation_type;
1513 $animationDuration = isset($postdata['sceneAnimationTransitionDuration']) ? $postdata['sceneAnimationTransitionDuration'] : '500ms';
1514 $animationDelay = isset($postdata['sceneAnimationTransitionDelay']) ? $postdata['sceneAnimationTransitionDelay'] : '0ms';
1515 $animation_css = apply_filters('wpvr_tour_scene_animation',$animation_type,$animationDuration,$animationDelay,$postdata,$id);
1516 $html .= $animation_css;
1517 }
1518
1519 if ($width == 'fullwidth') {
1520 $width = "100%";
1521 }
1522
1523 if (wpvr_isMobileDevice()) {
1524 $html .= '<div id="' . $master_container_id . '" class="wpvr-master-container wpvr-cardboard '.$enable_cardboard.'" style="max-width:' . $width . '; width: 100%; height: ' . $mobile_height . '; border-radius:' . $radius . '; direction:ltr; ">';
1525 } else {
1526 $html .= '<div id="' . $master_container_id . '" class="wpvr-master-container wpvr-cardboard '.$enable_cardboard.'" style="max-width:' . $width . '; width: 100%; height: ' . $height . '; border-radius:' . $radius . '; direction:ltr; ">';
1527 }
1528 $is_pro = apply_filters('is_wpvr_pro_active',false);
1529 $status = get_option('wpvr_edd_license_status');
1530 $is_cardboard = get_option('wpvr_cardboard_disable');
1531 if ($status !== false && 'valid' == $status && $is_pro && wpvr_isMobileDevice() && $is_cardboard == 'true' ) {
1532 $html .= '<button class="fullscreen-button">';
1533 $html .= '<span class="expand">';
1534 $html .= '<i class="fas fa-expand" aria-hidden="true"></i>';
1535 $html .= '</span>';
1536
1537 $html .= '<span class="compress">';
1538 $html .= '<i class="fas fa-minimize" aria-hidden="true"></i>';
1539 $html .= '</span>';
1540 $html .= '</button>';
1541 $embed_mode = '';
1542 if($width == "embed"){
1543 $embed_mode = "vr-embade-mode";
1544 }
1545 $html .= '<label class="wpvr-cardboard-switcher '.$embed_mode.'">
1546 <input type="checkbox" class="vr_mode_change' . $pano_suffix . '" name="vr_mode_change" value="off">
1547 <span class="switcher-box">
1548 <span class="normal-mode-tooltip">Normal VR Mode</span>
1549 <svg width="78" height="60" viewBox="0 0 78 60" fill="none" xmlns="http://www.w3.org/2000/svg">
1550 <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"/>
1551 </svg>
1552 </span>
1553 </label>';
1554
1555 }
1556
1557 if ($width == 'fullwidth') {
1558 if (wpvr_isMobileDevice()) {
1559 $html .= '<div class="cardboard-vrfullwidth vrfullwidth">';
1560 $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>';
1561 $html .= '<div id="' . $panoid . '" class="pano-wrap pano-right pano' . $id . '" style="width: 100%; text-align:center; direction:ltr; border-radius:' . $radius . '" >';
1562 } else {
1563 $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>';
1564 if ($radius) {
1565 $html .= '<div id="' . $panoid . '" class="pano-wrap vrfullwidth pano' . $id . '" style=" text-align:center; height: ' . $height . '; border-radius:' . $radius . '; direction:ltr;" >';
1566 } else {
1567 $html .= '<div id="' . $panoid . '" class="pano-wrap vrfullwidth pano' . $id . '" style=" text-align:center; height: ' . $height . '; direction:ltr;" >';
1568 }
1569 }
1570 } elseif ($width == 'embed') {
1571 $html .= '<div class="cardboard-vrembed vrembed">';
1572 $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>';
1573 $html .= '<div id="' . $panoid . '" class="pano-wrap pano-right pano' . $id . '" style=" text-align:center; direction:ltr;" >';
1574 } else {
1575 if (wpvr_isMobileDevice()) {
1576 $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>';
1577 if ($radius) {
1578 $html .= '<div id="' . $panoid . '" class="pano-wrap pano-right pano' . $id . '" style=" width: 100%; border-radius:' . $radius . ';">';
1579 } else {
1580 $html .= '<div id="' . $panoid . '" class="pano-wrap pano-right pano' . $id . '" style=" width: 100%; ">';
1581 }
1582 } else {
1583 $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>';
1584
1585 if ($radius) {
1586 $html .= '<div id="' . $panoid . '" class="pano-wrap pano-right pano' . $id . '" style="width: 100%; border-radius:' . $radius . ';">';
1587 } else {
1588 $html .= '<div id="' . $panoid . '" class="pano-wrap pano-right pano' . $id . '" style="width: 100%;">';
1589 }
1590 }
1591 }
1592 // Vr mode transction scene to scene
1593 if ($status !== false && 'valid' == $status && $is_pro) {
1594 $html .= '<div id="center-pointer' . $pano_suffix . '" class="vr-pointer-container" style="display:none"><span class="center-pointer"></span></div>';
1595 }
1596 $social_logo_top = '';
1597 //===company logo===//
1598 if (isset($postdata['cpLogoSwitch'])) {
1599 $cpLogoImg = $postdata['cpLogoImg'] ?? '';
1600 $cpLogoContent = $postdata['cpLogoContent'] ?? '';
1601 if ($postdata['cpLogoSwitch'] == 'on' && 'valid' == $status && $is_pro) {
1602 $html .= '<div id="cp-logo-controls">';
1603 $html .= '<div class="cp-logo-ctrl" id="cp-logo">';
1604 if ($cpLogoImg) {
1605 $social_logo_top = '50px';
1606 $html .= '<img loading="lazy" src="' . $cpLogoImg . '" alt="Company Logo">';
1607 }
1608
1609 if ($cpLogoContent) {
1610 $html .= '<div class="cp-info">' . esc_attr($cpLogoContent) . '</div>';
1611 }
1612 $html .= '</div>';
1613 $html .= '</div>';
1614 }
1615 }
1616 //===company logo ends===//
1617
1618 //===Generic Form===//
1619 if (isset($postdata["genericform"]) && $postdata["genericform"] === 'on' && 'valid' == $status && $is_pro) {
1620 // Process shortcode with fallback handling
1621 $shortcode_content = '';
1622 if (isset($postdata["genericformshortcode"]) && !empty(trim($postdata["genericformshortcode"]))) {
1623 $shortcode_content = do_shortcode( $postdata["genericformshortcode"] );
1624 } else {
1625 $shortcode_content = '<p class="error-message">No shortcode found.</p>';
1626 }
1627
1628 // Generate the form trigger button
1629 $generic_form_icon = isset($postdata['genericformicon']) ? (string) $postdata['genericformicon'] : 'fab fa-wpforms';
1630 $generic_form_icon = implode(' ', array_filter(array_map('sanitize_html_class', preg_split('/\s+/', $generic_form_icon))));
1631 $generic_form_icon = $generic_form_icon ?: 'fab fa-wpforms';
1632 $generic_form_icon_color = sanitize_hex_color($postdata['genericformiconcolor'] ?? '') ?: '#f7fffb';
1633 $html .= '<div class="generic_form_button" id="generic_form_button_' . esc_attr($pano_suffix) . '">';
1634 $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>';
1635 $html .= '</div>';
1636
1637 // Generate the modal form container
1638 $html .= '<div class="wpvr-generic-form" id="wpvr-generic-form' . esc_attr($pano_suffix) . '" style="display: none">';
1639 $html .= '<span class="close-generic-form"><i class="fa fa-times"></i></span>';
1640 $html .= '<div class="generic-form-container">' . $shortcode_content . '</div>';
1641 $html .= '</div>';
1642 }
1643 //===Generic Form ends===//
1644
1645 //===Background Tour===//
1646 if (isset($postdata['bg_tour_enabler'])) {
1647
1648 $bg_tour_enabler = $postdata['bg_tour_enabler'];
1649 if ($bg_tour_enabler == 'on') {
1650 $bg_tour_navmenu = $postdata['bg_tour_navmenu'] ?? 'off';
1651 $bg_tour_title = $postdata['bg_tour_title'] ?? '';
1652 $bg_tour_subtitle = $postdata['bg_tour_subtitle'] ?? '';
1653
1654 if ($bg_tour_navmenu == 'on') {
1655 $menuLocations = get_nav_menu_locations();
1656 if (!empty($menuLocations['primary'])) {
1657 $menuID = $menuLocations['primary'];
1658 $primaryNav = wp_get_nav_menu_items($menuID);
1659 $html .= '<ul class="wpvr-navbar-container">';
1660 foreach ($primaryNav as $primaryNav_key => $primaryNav_value) {
1661 if ($primaryNav_value->menu_item_parent == "0") {
1662 $html .= '<li>';
1663 $html .= '<a href="' . $primaryNav_value->url . '">' . $primaryNav_value->title . '</a>';
1664 $html .= '<ul class="wpvr-navbar-dropdown">';
1665 foreach ($primaryNav as $pm_key => $pm_value) {
1666 if ($pm_value->menu_item_parent == $primaryNav_value->ID) {
1667 $html .= '<li>';
1668 $html .= '<a href="' . $pm_value->url . '">' . $pm_value->title . '</a>';
1669 $html .= '</li>';
1670 }
1671 }
1672 $html .= '</ul>';
1673 $html .= '</li>';
1674 }
1675 }
1676 $html .= '</ul>';
1677 }
1678 }
1679 if($is_pro && 'valid' == $status ){
1680 $html .= '<div class="wpvr-home-content">';
1681 $html .= '<div class="wpvr-home-title">' . $bg_tour_title . '</div>';
1682 $html .= '<div class="wpvr-home-subtitle">' . $bg_tour_subtitle . '</div>';
1683 $html .= '</div>';
1684 }
1685 }
1686 }
1687 //===Background Tour End===//
1688
1689 //===Custom Control===//
1690 if (isset($custom_control)) {
1691 $gyro_button_enabled = wpvr_isMobileDevice() && $custom_control['gyroSwitch'] == "on" && $custom_control['gyroscopeSwitch'] == "on";
1692 if ($custom_control['panZoomInSwitch'] == "on" || $custom_control['panZoomOutSwitch'] == "on" || $gyro_button_enabled || $custom_control['backToHomeSwitch'] == "on") {
1693 $html .= '<div id="zoom-in-out-controls' . $pano_suffix . '" class="zoom-in-out-controls">';
1694
1695 if ($custom_control['backToHomeSwitch'] == "on" && 'valid' == $status && $is_pro) {
1696 $html .= '<div class="ctrl" id="backToHome' . $pano_suffix . '"><i class="' . $custom_control['backToHomeIcon'] . '" style="color:' . $custom_control['backToHomeColor'] . ';"></i></div>';
1697 }
1698
1699 if ($custom_control['panZoomInSwitch'] == "on" && 'valid' == $status && $is_pro) {
1700 $html .= '<div class="ctrl" id="zoom-in' . $pano_suffix . '"><i class="' . $custom_control['panZoomInIcon'] . '" style="color:' . $custom_control['panZoomInColor'] . ';"></i></div>';
1701 }
1702
1703 if ($custom_control['panZoomOutSwitch'] == "on" && 'valid' == $status && $is_pro) {
1704 $html .= '<div class="ctrl" id="zoom-out' . $pano_suffix . '"><i class="' . $custom_control['panZoomOutIcon'] . '" style="color:' . $custom_control['panZoomOutColor'] . ';"></i></div>';
1705 }
1706 if ($gyro_button_enabled && 'valid' == $status && $is_pro) {
1707 $html .= '<div class="ctrl" id="gyroscope' . $pano_suffix . '" ><i class="' . $custom_control['gyroscopeIcon'] . '" style="color:' . $custom_control['gyroscopeColor'] . ';"></i></div>';
1708 }
1709 $html .= '</div>';
1710 }
1711 //===zoom in out Control===//
1712
1713 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) {
1714 //===Custom Control===//
1715 $html .= '<div class="controls" id="controls' . $pano_suffix . '">';
1716
1717 if ($custom_control['panupSwitch'] == "on") {
1718 $html .= '<div class="ctrl pan-up" id="pan-up' . $pano_suffix . '"><i class="' . $custom_control['panupIcon'] . '" style="color:' . $custom_control['panupColor'] . ';"></i></div>';
1719 }
1720
1721 if ($custom_control['panDownSwitch'] == "on") {
1722 $html .= '<div class="ctrl pan-down" id="pan-down' . $pano_suffix . '"><i class="' . $custom_control['panDownIcon'] . '" style="color:' . $custom_control['panDownColor'] . ';"></i></div>';
1723 }
1724
1725 if ($custom_control['panLeftSwitch'] == "on") {
1726 $html .= '<div class="ctrl pan-left" id="pan-left' . $pano_suffix . '"><i class="' . $custom_control['panLeftIcon'] . '" style="color:' . $custom_control['panLeftColor'] . ';"></i></div>';
1727 }
1728
1729 if ($custom_control['panRightSwitch'] == "on") {
1730 $html .= '<div class="ctrl pan-right" id="pan-right' . $pano_suffix . '"><i class="' . $custom_control['panRightIcon'] . '" style="color:' . $custom_control['panRightColor'] . ';"></i></div>';
1731 }
1732
1733 if ($custom_control['panFullscreenSwitch'] == "on") {
1734 $html .= '<div class="ctrl fullscreen" id="fullscreen' . $pano_suffix . '"><i class="' . $custom_control['panFullscreenIcon'] . '" style="color:' . $custom_control['panFullscreenColor'] . ';"></i></div>';
1735 }
1736 $html .= '</div>';
1737 }
1738 }
1739 //===Custom Control===//
1740
1741 //===explainer button===//
1742 $html .= wpvr_render_explainer_button(
1743 isset( $custom_control ) ? $custom_control : null,
1744 $postdata,
1745 $is_pro,
1746 $autoload,
1747 $explainer_right,
1748 $pano_suffix
1749 );
1750 //===explainer button end===//
1751
1752 //===Floor map button===//
1753 $status = get_option('wpvr_edd_license_status');
1754 if ($status !== false && 'valid' == $status && $is_pro){
1755 if ($floor_plan_enable == "on" && !empty($floor_plan_image)) {
1756 $html .= '<div class="floor_map_button" id="floor_map_button_' . $pano_suffix . '" style="right:'.$floor_map_right.'">';
1757 $html .= '<div class="ctrl" id="floor_map_target_' . $pano_suffix . '"><i class="fas fa-map" style="color:#f7fffb;"></i></div>';
1758 $html .= '</div>';
1759 }
1760 }
1761 //===floor map button===//
1762
1763 if ($vrgallery && 'valid' == $status && $is_pro ) {
1764 //===Carousal setup===//
1765 $size = '';
1766 if($vrgallery_icon_size){
1767 $size = 'vrg-icon-size-large';
1768 }
1769 $html .= '<div id="vrgcontrols' . $pano_suffix . '" class="vrgcontrols">';
1770
1771 $html .= '<div class="vrgctrl' . $pano_suffix . ' vrbounce '.$size.'">';
1772 $html .= '</div>';
1773 $html .= '</div>';
1774
1775 $gallery_layout_class = isset($postdata['tourLayout']['layout']) && 'layout1' === $postdata['tourLayout']['layout']
1776 ? 'wpvr-gallery--modern'
1777 : 'wpvr-gallery--classic';
1778 $html .= '<div id="sccontrols' . $pano_suffix . '" class="scene-gallery vrowl-carousel ' . esc_attr($gallery_layout_class) . '">';
1779 if (isset($panodata["scene-list"])) {
1780 foreach ($panodata["scene-list"] as $panoscenes) {
1781 $scene_key = $panoscenes['scene-id'];
1782
1783 if ($vrgallery_title == 'on') {
1784 $scene_key_title = isset($panoscenes['scene-ititle']) ? sanitize_text_field($panoscenes['scene-ititle']) : '';
1785 } else {
1786 $scene_key_title = "";
1787 }
1788
1789 if ($panoscenes['scene-type'] == 'cubemap') {
1790 $img_src_url = $panoscenes['scene-attachment-url-face0'];
1791 } else {
1792 $img_src_url = $panoscenes['scene-attachment-url'];
1793 }
1794
1795 $src_to_id = attachment_url_to_postid($img_src_url);
1796 $thumbnail_array = wp_get_attachment_image_src($src_to_id, 'thumbnail');
1797 if ($thumbnail_array) {
1798 $thumbnail = $thumbnail_array[0];
1799 } else {
1800 $thumbnail = $img_src_url;
1801 }
1802
1803 if( isset($postdata['tourLayout']['layout']) && 'layout1' !== $postdata['tourLayout']['layout']) {
1804 $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>';
1805 }else {
1806 $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>';
1807 }
1808 }
1809 }
1810
1811 $html .= '</div>';
1812
1813 $html .= '
1814 <div class="wpvr_slider_nav">
1815 <button type="button" role="presentation" class="wpvr_owl_prev">
1816 <div class="nav-btn prev-slide"><i class="fa fa-angle-left"></i></div>
1817 </button>
1818 <button type="button" role="presentation" class="wpvr_owl_next">
1819 <div class="nav-btn next-slide"><i class="fa fa-angle-right"></i></div>
1820 </button>
1821 </div>
1822 ';
1823
1824 //===Carousal setup end===//
1825 }
1826
1827 //===Call TO action Button===//
1828 $bg_music = isset($postdata['bg_music']) ? $postdata['bg_music'] : 'off';
1829 $bg_music_url = isset($postdata['bg_music_url']) ? $postdata['bg_music_url'] : '';
1830 $autoplay_bg_music = isset($postdata['autoplay_bg_music']) ? $postdata['autoplay_bg_music'] : 'off';
1831 $loop_bg_music = isset($postdata['loop_bg_music']) ? $postdata['loop_bg_music'] : 'off';
1832
1833 $bg_loop = ($loop_bg_music === 'on') ? 'loop' : '';
1834 $autoplay_attr = ($autoplay_bg_music === 'on') ? 'autoplay' : '';
1835 $audio_muted_attr = ($autoplay_bg_music === 'on') ? 'muted' : '';
1836 $audio_icon_class = 'fa-volume-mute'; // Always start with mute icon
1837
1838 if ($bg_music === 'on' && 'valid' == $status && $is_pro) {
1839 $html .= '<div id="adcontrol' . esc_attr( $pano_suffix ) . '" class="adcontrol" style="right:' . esc_attr( $audio_right ) . '">';
1840 $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 . '>
1841 <source src="' . esc_url($bg_music_url) . '" type="audio/mpeg">
1842 Your browser does not support the audio element.
1843 </audio>';
1844 $html .= '<button onclick="playPause' . esc_attr($pano_suffix) . '()" class="ctrl audio_control" id="audio_control' . esc_attr($pano_suffix) . '">
1845 <i id="vr-volume' . esc_attr($pano_suffix) . '" class="wpvrvolumeicon' . esc_attr($pano_suffix) . ' fas ' . esc_attr($audio_icon_class) . '" style="color:#fff;"></i>
1846 </button>';
1847 $html .= '</div>';
1848 }
1849 //===Explainer video section===//
1850 $explainerContent = "";
1851 if (isset($postdata['explainerContent'])) {
1852 $explainerContent = $this->wpvr_sanitize_iframe_only($postdata['explainerContent']);
1853 }
1854 $html .= '<div class="explainer" id="explainer' . $pano_suffix . '" style="display: none">';
1855 $html .= '<span class="close-explainer-video"><i class="fa fa-times"></i></span>';
1856 $html .= '' . $explainerContent . '';
1857 $html .= '</div>';
1858 //===Explainer video section End===//
1859
1860 //===Scene navigation Control===//
1861 if (isset($postdata['scene_navigation']) && $postdata['scene_navigation'] === 'on' && 'valid' == $status && $is_pro) {
1862 $scene_navigation_nav_class = 'custom-scene-navigation-nav' . ( $is_classic_layout ? ' wpvr-scene-navigation-nav--classic' : '' );
1863 $html .= '<style>
1864 #et-boc .et-l .pnlm-controls-container,
1865 .pnlm-controls-container{
1866 top: 33px;
1867 }
1868
1869 #et-boc .et-l .zoom-in-out-controls,
1870 .zoom-in-out-controls {
1871 top: 37px;
1872 }
1873 </style>';
1874 $html .= '<div id="custom-scene-navigation' . $pano_suffix . '" class="custom-scene-navigation">
1875 <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>
1876 </div>
1877
1878 <div id="custom-scene-navigation-nav' . $pano_suffix . '" class="' . esc_attr( $scene_navigation_nav_class ) . '">
1879 <ul></ul>
1880 </div>
1881 ';
1882 }
1883 //===Scene navigation Control===//
1884
1885
1886 if( 'embed' === $width){
1887 if(WPVR_Helper::is_enable_social_share($postdata) === 'on'){
1888 $html .= '<div id="wpvr-social-share-bg-box'.$pano_suffix.'" class="wpvr-social-share-bg-box" style="top:'.$social_logo_top.'">
1889 <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>
1890 <nav class="wpvr-share-nav">
1891 '.WPVR_Helper::social_media_share_links_display_in_embed(home_url().'/?embed_page='. $id).'
1892 </nav>
1893 </div>';
1894 }
1895 }
1896 //===Floor plan section===//
1897 $floor_map_image = "";
1898 $floor_map_pointer = array();
1899 $floor_map_scene_id = '';
1900 $floor_plan_custom_color = '#cca92c';
1901 $floor_plan_direction_indicator = isset($postdata['floor_plan_direction_indicator']) ? $postdata['floor_plan_direction_indicator'] : 'on';
1902
1903 if (isset($postdata['floor_plan_attachment_url'])) {
1904 $floor_map_image = $postdata['floor_plan_attachment_url'];
1905 $floor_map_pointer = $postdata['floor_plan_pointer_position'];
1906 $floor_map_scene_id = $postdata['floor_plan_data_list'];
1907 $floor_plan_custom_color = $postdata['floor_plan_custom_color'];
1908 }
1909 $html .= '<div class="wpvr-floor-map" id="wpvr-floor-map' . $pano_suffix . '" style="display: none">';
1910 $html .= '<span class="close-floor-map-plan"><i class="fa fa-times"></i></span>';
1911 $html .= '<img loading="lazy" src="'.$floor_map_image.'">';
1912 foreach($floor_map_pointer as $key=> $pointer_position){
1913 $html .= '<div class="floor-plan-pointer ui-draggable ui-draggable-handle" scene_id = "'.$floor_map_scene_id[$key]->value.'" id="'.$pointer_position->id.'" data-top="'.$pointer_position->data_top.'" data-left="'.$pointer_position->data_left.'" style="'.$pointer_position->style.'">
1914 <svg class="floor-pointer-circle" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
1915 <circle cx="12" cy="12" r="11.5" stroke="'.$floor_plan_custom_color.'"/>
1916 <circle cx="12" cy="12" r="5" fill="'.$foreground_color_pointer.'"/>
1917 </svg>';
1918
1919 // Only add the floor pointer flash SVG if floor_plan_direction_indicator is "on"
1920 if ($floor_plan_direction_indicator === "on") {
1921 $html .= '<svg class="floor-pointer-flash" width="54" height="35" viewBox="0 0 54 35" fill="none" xmlns="http://www.w3.org/2000/svg">
1922 <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)"/>
1923 <defs>
1924 <linearGradient id="paint0_linear_1_10" x1="27" y1="4.59807e-08" x2="26.5" y2="28" gradientUnits="userSpaceOnUse">
1925 <stop stop-color="' . esc_attr( $floor_plan_custom_color ) . '" stop-opacity="0"/>
1926 <stop offset="1" stop-color="' . esc_attr( $floor_plan_custom_color ) . '"/>
1927 </linearGradient>
1928 </defs>
1929 </svg>';
1930 }
1931 $html .= '</div>';
1932 }
1933 $html .= '</div>';
1934 //===Floor plan section===//
1935
1936 $html .= '<div class="wpvr-hotspot-tweak-contents-wrapper" style="display: none">';
1937 $html .= '<i class="fa fa-times cross" data-id="' . $id . '"></i>';
1938 $html .= '<div class="wpvr-hotspot-tweak-contents-flex">';
1939 $html .= '<div class="wpvr-hotspot-tweak-contents">';
1940 ob_start();
1941 do_action('wpvr_hotspot_tweak_contents', $scene_data);
1942 $hotspot_content = ob_get_clean();
1943 $html .= $hotspot_content;
1944 $html .= '</div>';
1945 $html .= '</div>';
1946 $html .= '</div>';
1947
1948 $html .= '<div class="custom-ifram-wrapper" style="display: none;">';
1949 $html .= '<i class="fa fa-times cross" data-id="' . $id . '"></i>';
1950
1951 $html .= '<div class="custom-ifram-flex">';
1952 $html .= '<div class="custom-ifram">';
1953 $html .= '</div>';
1954 $html .= '</div>';
1955 $html .= '</div>';
1956
1957 $html .= '</div>';
1958 $html .= '</div>';
1959 if( "embed" == $width ){
1960 $html .= '</div>';
1961 }
1962
1963
1964 if ($status !== false && 'valid' == $status && $is_pro) {
1965 $call_to_action = isset($postdata['calltoaction']) ? $postdata['calltoaction'] : 'off';
1966 if( 'on' == $call_to_action){
1967 $buttontext = isset($postdata['buttontext']) ? $postdata['buttontext'] : '';
1968 $buttonurl = isset($postdata['buttonurl']) ? $postdata['buttonurl'] : '';
1969 $cta_btn_style = isset($postdata['button_configuration']) ? $postdata['button_configuration'] : array();
1970
1971 $button_open_new_tab = isset($cta_btn_style['button_open_new_tab']) ? $cta_btn_style['button_open_new_tab'] : "off";
1972 $target = '_self';
1973 $button_position = isset($cta_btn_style['button_position']) ? $cta_btn_style['button_position'] : "";
1974 $background_color = isset($cta_btn_style['button_background_color']) ? $cta_btn_style['button_background_color'] : "";
1975 $color = isset($cta_btn_style['button_font_color']) ? $cta_btn_style['button_font_color'] : "";
1976 $font_size = isset($cta_btn_style['button_font_size']) ? $cta_btn_style['button_font_size'] : "";
1977 $font_weight = isset($cta_btn_style['button_font_weight']) ? $cta_btn_style['button_font_weight'] : "";
1978 $text_align = isset($cta_btn_style['button_alignment']) ? $cta_btn_style['button_alignment'] : "";
1979 $text_transform = isset($cta_btn_style['button_transform']) ? $cta_btn_style['button_transform'] : "";
1980 $font_style = isset($cta_btn_style['button_text_style']) ? $cta_btn_style['button_text_style'] : "";
1981 $text_decoration = isset($cta_btn_style['button_text_decoration']) ? $cta_btn_style['button_text_decoration'] : "";
1982 $line_height = isset($cta_btn_style['button_line_height']) ? $cta_btn_style['button_line_height'] : "";
1983 $letter_spacing = isset($cta_btn_style['button_letter_spacing']) ? $cta_btn_style['button_letter_spacing'] : "";
1984 $word_spacing = isset($cta_btn_style['button_word_spacing']) ? $cta_btn_style['button_word_spacing'] : "";
1985
1986 $border_width = isset($cta_btn_style['button_border_width']) ? $cta_btn_style['button_border_width'] : "";
1987 $border_style = isset($cta_btn_style['button_border_style']) ? $cta_btn_style['button_border_style'] : "";
1988 $border_color = isset($cta_btn_style['button_border_color']) ? $cta_btn_style['button_border_color'] : "";
1989 $border_radius = isset($cta_btn_style['button_border_radius']) ? $cta_btn_style['button_border_radius'] : "";
1990
1991 $button_pt = isset($cta_btn_style['button_pt']) ? $cta_btn_style['button_pt'] : "";
1992 $button_pr = isset($cta_btn_style['button_pr']) ? $cta_btn_style['button_pr'] : "";
1993 $button_pb = isset($cta_btn_style['button_pb']) ? $cta_btn_style['button_pb'] : "";
1994 $button_pl = isset($cta_btn_style['button_pl']) ? $cta_btn_style['button_pl'] : "";
1995
1996 if($button_open_new_tab == 'on'){
1997 $target = '_blank';
1998 }
1999 $style = 'background-color: '.$background_color.';
2000 color: '.$color.';
2001 font-size: '.$font_size.'px;
2002 font-weight: '.$font_weight.';
2003 text-align: center;
2004 display: inline-block;
2005 text-transform: '.$text_transform.';
2006 font-style: '.$font_style.';
2007 text-decoration: '.$text_decoration.';
2008 line-height: '.$line_height.';
2009 letter-spacing: '.$letter_spacing.'px;
2010 word-spacing: '.$word_spacing.'px;
2011 border: '.$border_width.'px '.$border_style.' '.$border_color.';
2012 border-radius: '.$border_radius.'px;
2013 padding: '.$button_pt.'px '.$button_pr.'px '.$button_pb.'px '.$button_pl.'px;
2014 ';
2015 $html .= '<div class="wpvr-call-to-action-button position-'.$text_align.'" style="max-width:' . $width.'">
2016 <a href="'.$buttonurl.'" style="'.$style.'" target="'.$target.'">'.$buttontext.'</a>
2017 </div>';
2018
2019 }
2020 }
2021
2022
2023 //script started
2024 $html .= '<script>';
2025 if (isset($postdata['bg_music']) && $bg_music == 'on' && 'valid' == $status && $is_pro) {
2026 $html .= '
2027 var x' . $pano_suffix . ' = document.getElementById("vrAudio' . $pano_suffix . '");
2028 var playing' . $pano_suffix . ' = false;
2029 var autoplaySupported' . $pano_suffix . ' = false;
2030 var alertShown' . $pano_suffix . ' = false;
2031 var autoplayChecked' . $pano_suffix . ' = false;
2032
2033 function playPause' . $pano_suffix . '() {
2034 if (playing' . $pano_suffix . ') {
2035 jQuery("#vr-volume' . $pano_suffix . '").removeClass("fas fa-volume-up").addClass("fas fa-volume-mute");
2036 x' . $pano_suffix . '.pause();
2037 jQuery("#audio_control' . $pano_suffix . '").attr("data-play", "off");
2038 playing' . $pano_suffix . ' = false;
2039 } else {
2040 x' . $pano_suffix . '.muted = false;
2041 x' . $pano_suffix . '.play().then(function() {
2042 jQuery("#vr-volume' . $pano_suffix . '").removeClass("fas fa-volume-mute").addClass("fas fa-volume-up");
2043 jQuery("#audio_control' . $pano_suffix . '").attr("data-play", "on");
2044 playing' . $pano_suffix . ' = true;
2045 }).catch(function(e) {
2046 console.log("Play failed:", e);
2047 });
2048 }
2049 }
2050
2051 function audionEnd' . $pano_suffix . '() {
2052 playing' . $pano_suffix . ' = false;
2053 jQuery("#vr-volume' . $pano_suffix . '").removeClass("fas fa-volume-up").addClass("fas fa-volume-mute");
2054 jQuery("#audio_control' . $pano_suffix . '").attr("data-play", "off");
2055 }
2056
2057 x' . $pano_suffix . '.addEventListener("ended", audionEnd' . $pano_suffix . ');';
2058
2059 if ($autoplay_bg_music == 'on') {
2060 $html .= '
2061
2062 x' . $pano_suffix . '.addEventListener("loadeddata", function() {
2063 if (!autoplayChecked' . $pano_suffix . ') {
2064 checkAutoplayStatus' . $pano_suffix . '();
2065 }
2066 });
2067
2068 x' . $pano_suffix . '.addEventListener("canplay", function() {
2069 if (!autoplayChecked' . $pano_suffix . ') {
2070 checkAutoplayStatus' . $pano_suffix . '();
2071 }
2072 });
2073
2074 x' . $pano_suffix . '.addEventListener("canplaythrough", function() {
2075 if (!autoplayChecked' . $pano_suffix . ') {
2076 checkAutoplayStatus' . $pano_suffix . '();
2077 }
2078 });
2079
2080 setTimeout(function() {
2081 if (!autoplayChecked' . $pano_suffix . ') {
2082 checkAutoplayStatus' . $pano_suffix . '();
2083 }
2084 }, 1000);
2085
2086 x' . $pano_suffix . '.addEventListener("play", function() {
2087 jQuery("#vr-volume' . $pano_suffix . '").removeClass("fas fa-volume-mute").addClass("fas fa-volume-up");
2088 jQuery("#audio_control' . $pano_suffix . '").attr("data-play", "on");
2089 playing' . $pano_suffix . ' = true;
2090 });
2091
2092 x' . $pano_suffix . '.addEventListener("pause", function() {
2093 if (!playing' . $pano_suffix . ') {
2094 jQuery("#vr-volume' . $pano_suffix . '").removeClass("fas fa-volume-up").addClass("fas fa-volume-mute");
2095 jQuery("#audio_control' . $pano_suffix . '").attr("data-play", "off");
2096 }
2097 });
2098
2099 function checkAutoplayStatus' . $pano_suffix . '() {
2100 autoplayChecked' . $pano_suffix . ' = true;
2101
2102 x' . $pano_suffix . '.muted = true;
2103 var playPromise = x' . $pano_suffix . '.play();
2104
2105 if (playPromise !== undefined) {
2106 playPromise.then(function () {
2107 if (x' . $pano_suffix . '.muted || x' . $pano_suffix . '.volume === 0) {
2108 handleAutoplayBlocked' . $pano_suffix . '();
2109 } else {
2110 autoplaySupported' . $pano_suffix . ' = true;
2111 jQuery("#vr-volume' . $pano_suffix . '").removeClass("fas fa-volume-mute").addClass("fas fa-volume-up");
2112 jQuery("#audio_control' . $pano_suffix . '").attr("data-play", "on");
2113 playing' . $pano_suffix . ' = true;
2114 }
2115 }).catch(function () {
2116 handleAutoplayBlocked' . $pano_suffix . '();
2117 });
2118 } else {
2119 setTimeout(function () {
2120 if (x' . $pano_suffix . '.paused || x' . $pano_suffix . '.currentTime === 0) {
2121 handleAutoplayBlocked' . $pano_suffix . '();
2122 } else {
2123 autoplaySupported' . $pano_suffix . ' = true;
2124 jQuery("#vr-volume' . $pano_suffix . '").removeClass("fas fa-volume-mute").addClass("fas fa-volume-up");
2125 jQuery("#audio_control' . $pano_suffix . '").attr("data-play", "on");
2126 playing' . $pano_suffix . ' = true;
2127 }
2128 }, 300);
2129 }
2130 }
2131
2132 function handleAutoplayBlocked' . $pano_suffix . '() {
2133 autoplaySupported' . $pano_suffix . ' = false;
2134 if (!alertShown' . $pano_suffix . ') {
2135 alert("Autoplay is not supported in your browser. Please click the audio button to play music.");
2136 alertShown' . $pano_suffix . ' = true;
2137 }
2138
2139 x' . $pano_suffix . '.pause();
2140 x' . $pano_suffix . '.currentTime = 0;
2141 x' . $pano_suffix . '.muted = true;
2142
2143 jQuery("#vr-volume' . $pano_suffix . '").removeClass("fas fa-volume-up").addClass("fas fa-volume-mute");
2144 jQuery("#audio_control' . $pano_suffix . '").attr("data-play", "off");
2145
2146 var musicTriggerElem = document.getElementById("' . $panoid . '");
2147 if (musicTriggerElem) {
2148 musicTriggerElem.addEventListener("click", musicPlay' . $pano_suffix . ');
2149 }
2150 document.addEventListener("touchstart", musicPlay' . $pano_suffix . ', { once: true });
2151 document.addEventListener("click", musicPlay' . $pano_suffix . ', { once: true });
2152 }
2153
2154 function musicPlay' . $pano_suffix . '() {
2155 x' . $pano_suffix . '.muted = false;
2156 var playPromise = x' . $pano_suffix . '.play();
2157
2158 if (playPromise !== undefined) {
2159 playPromise.then(function () {
2160 jQuery("#vr-volume' . $pano_suffix . '").removeClass("fas fa-volume-mute").addClass("fas fa-volume-up");
2161 jQuery("#audio_control' . $pano_suffix . '").attr("data-play", "on");
2162 playing' . $pano_suffix . ' = true;
2163 }).catch(function(e) {
2164 console.log("Play failed:", e);
2165 });
2166 } else {
2167 setTimeout(function () {
2168 if (!x' . $pano_suffix . '.paused) {
2169 jQuery("#vr-volume' . $pano_suffix . '").removeClass("fas fa-volume-mute").addClass("fas fa-volume-up");
2170 jQuery("#audio_control' . $pano_suffix . '").attr("data-play", "on");
2171 playing' . $pano_suffix . ' = true;
2172 }
2173 }, 100);
2174 }
2175
2176 var musicTriggerElem = document.getElementById("' . $panoid . '");
2177 if (musicTriggerElem) {
2178 musicTriggerElem.removeEventListener("click", musicPlay' . $pano_suffix . ');
2179 }
2180 document.removeEventListener("touchstart", musicPlay' . $pano_suffix . ');
2181 document.removeEventListener("click", musicPlay' . $pano_suffix . ');
2182 }
2183 ';
2184 }
2185 }
2186 $html .= '(function ($) {';
2187 $html .= 'jQuery(document).ready(function() {';
2188 $html .= 'var response = ' . $response . ';';
2189 $html .= 'var scenes = response[1];';
2190 $html .= 'if(scenes) {';
2191 $html .= 'var scenedata = scenes.scenes;';
2192 $html .= 'for(var scId in scenedata) {';
2193 $html .= 'if(!scenedata.hasOwnProperty(scId)) continue;';
2194 $html .= 'var scenehotspot = scenedata[scId].hotSpots;';
2195 $html .= 'if(scenehotspot && scenehotspot.length) {';
2196 $html .= 'for(var hIdx = 0; hIdx < scenehotspot.length; hIdx++) {';
2197 $html .= 'if(scenehotspot[hIdx].type === "info") {';
2198 $html .= ' scenehotspot[hIdx]["clickHandlerFunc"] = function(div, args) { if (typeof window.wpvrhotspot === "function") { window.wpvrhotspot(div, args); } };';
2199 $html .= '} else if(scenehotspot[hIdx].type === "scene") {';
2200 $html .= ' scenehotspot[hIdx]["clickHandlerArgs"] = scenehotspot[hIdx]["text"] || "";';
2201 $status = get_option('wpvr_edd_license_status');
2202 if ($status !== false && $status == 'valid') {
2203 $html .='if(typeof wpvr_public !== "undefined") {';
2204 $html .='if(wpvr_public.is_pro_active) {';
2205 $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); } };';
2206 $html .='}';
2207 $html .='}';
2208 }
2209 $html .= '}';
2210
2211 if (wpvr_isMobileDevice() && get_option('dis_on_hover') == "true") {
2212 } else {
2213 $html .= 'if(scenehotspot[hIdx]["createTooltipArgs"] != "") {';
2214 $html .= 'scenehotspot[hIdx]["createTooltipFunc"] = function(div, args) { if (typeof window.wpvrtooltip === "function") { window.wpvrtooltip(div, args); } };';
2215 $html .= '}';
2216 }
2217
2218 $html .= '}';
2219 $html .= '}';
2220 $html .= '}';
2221 $html .= '}';
2222 $html .= 'var panoshow' . $pano_suffix . ';';
2223 $html .= 'var panoshow2' . $pano_suffix . ';';
2224 $html .= 'function initWPVRViewer' . $pano_suffix . '() {';
2225 $html .= 'if (typeof pannellum === "undefined" || typeof jQuery === "undefined") { setTimeout(initWPVRViewer' . $pano_suffix . ', 50); return; }';
2226 $html .= 'panoshow' . $pano_suffix . ' = pannellum.viewer(response[0]["panoid"], scenes);';
2227 $html .= '
2228 window.wpvrViewers = window.wpvrViewers || {};
2229 window.wpvrViewers[response[0]["panoid"]] = panoshow' . $pano_suffix . ';
2230 document.dispatchEvent(new CustomEvent("wpvr:viewer-ready", {
2231 detail: { containerId: response[0]["panoid"], viewer: panoshow' . $pano_suffix . ' }
2232 }));
2233 ';
2234 if ( (float) $scene_fade_duration > 0 ) {
2235 $html .= '
2236 panoshow' . $pano_suffix . '.on("scenechange", function() {
2237 var fadeImage = document.querySelector("#' . $panoid . ' .pnlm-render-container > .pnlm-fade-img");
2238 if (fadeImage) {
2239 fadeImage.style.opacity = "1";
2240 void fadeImage.offsetWidth;
2241 }
2242 });';
2243 }
2244 $html .= '
2245
2246 if(typeof wpvr_public === "undefined" || !wpvr_public.is_pro_active || !wpvr_public.is_license_active) {
2247 panoshow' . $pano_suffix . '.on("load", function() {
2248 jQuery(".pnlm-panorama-info").hide();
2249 jQuery(".pnlm-compass").hide();
2250 });
2251
2252 panoshow' . $pano_suffix . '.on("scenechange", function() {
2253 jQuery(".pnlm-panorama-info").hide();
2254 jQuery(".pnlm-compass").hide();
2255 });
2256 }';
2257 $html .= '}';
2258 $html .= 'initWPVRViewer' . $pano_suffix . '();';
2259 //===Dplicate mode only for vr mode===//
2260 $response2 = json_decode($response);
2261 $response2[1]->compass = false;
2262 $response2[1]->autoRotate = false;
2263 $response = json_encode($response2);
2264 $html .= 'var response_duplicate = ' . $response . ';';
2265 $html .= 'var scenes_duplicate = response_duplicate[1];';
2266
2267 $html .= 'if(scenes_duplicate) {';
2268 $html .= 'var scenedata = scenes_duplicate.scenes;';
2269 $html .= 'for(var scId in scenedata) {';
2270 $html .= 'if(!scenedata.hasOwnProperty(scId)) continue;';
2271 $html .= 'var scenehotspot = scenedata[scId].hotSpots;';
2272 $html .= 'if(scenehotspot && scenehotspot.length) {';
2273 $html .= 'for(var hIdx = 0; hIdx < scenehotspot.length; hIdx++) {';
2274 $html .= 'if(scenehotspot[hIdx]["clickHandlerArgs"] != "") {';
2275 $html .= 'scenehotspot[hIdx]["clickHandlerFunc"] = function(div, args) { if (typeof window.wpvrhotspot === "function") { window.wpvrhotspot(div, args); } };';
2276 $html .= '}';
2277 if (wpvr_isMobileDevice() && get_option('dis_on_hover') == "true") {
2278 } else {
2279 $html .= 'if(scenehotspot[hIdx]["createTooltipArgs"] != "") {';
2280 $html .= 'scenehotspot[hIdx]["createTooltipFunc"] = function(div, args) { if (typeof window.wpvrtooltip === "function") { window.wpvrtooltip(div, args); } };';
2281 $html .= '}';
2282 }
2283 $html .= '}';
2284 $html .= '}';
2285 $html .= '}';
2286 $html .= '}';
2287
2288 $is_pro = apply_filters('is_wpvr_pro_active',false);
2289 $status = get_option('wpvr_edd_license_status');
2290 $html .= 'var vr_mode = "off";';
2291 if ($status !== false && 'valid' == $status && $is_pro) {
2292 $html .= 'function initWPVRViewer2' . $pano_suffix . '() {';
2293 $html .= 'if (typeof pannellum === "undefined" || typeof jQuery === "undefined") { setTimeout(initWPVRViewer2' . $pano_suffix . ', 50); return; }';
2294 $html .= 'panoshow2' . $pano_suffix . ' = pannellum.viewer("' . $panoid2 . '", scenes_duplicate);';
2295 $html .= '
2296 window.wpvrViewers = window.wpvrViewers || {};
2297 window.wpvrViewers["' . $panoid2 . '"] = panoshow2' . $pano_suffix . ';
2298 document.dispatchEvent(new CustomEvent("wpvr:viewer-ready", {
2299 detail: { containerId: "' . $panoid2 . '", viewer: panoshow2' . $pano_suffix . ' }
2300 }));
2301 ';
2302 $html .= '}';
2303 $html .= 'initWPVRViewer2' . $pano_suffix . '();';
2304 // Show Cardboard Mode in Tour
2305 $html .= '
2306 var tim;
2307 var im = 0;
2308 var active_scene = "'.$default_scene.'";
2309 var c_time;
2310 c_time = new Date();
2311 var timer = c_time.getTime() + 2000;
2312 function panoShowCardBoardOnTrigger(data){
2313 if(scenes_duplicate) {
2314 var scenedata = scenes_duplicate.scenes;
2315 for(var i in scenedata) {
2316 if(active_scene === i) {
2317 var scenehotspot = scenedata[i].hotSpots;
2318 if(scenehotspot && scenehotspot.length) {
2319 for(var j = 0; j < scenehotspot.length; j++) {
2320 var plusFiveYaw = Math.round(scenehotspot[j].yaw) + 5;
2321 var minusFiveYaw = Math.round(scenehotspot[j].yaw) - 5;
2322 var plusFivePitch = Math.round(scenehotspot[j].pitch) + 5;
2323 var minusFivePitch = Math.round(scenehotspot[j].pitch) - 5;
2324 if(Math.round(data.pitch) > minusFivePitch) {
2325 if(Math.round(data.pitch) < plusFivePitch) {
2326 if(Math.round(data.yaw) > minusFiveYaw) {
2327 if(Math.round(data.yaw) < plusFiveYaw) {
2328 jQuery(".center-pointer").addClass("wpvr-pluse-effect");
2329 var getScene = scenehotspot[j].sceneId;
2330 if(scenehotspot[j].type == "scene"){
2331 panoshow' . $pano_suffix . '.loadScene(getScene);
2332 panoshow2' . $pano_suffix . '.loadScene(getScene);
2333 }else{
2334 jQuery(".center-pointer").removeClass("wpvr-pluse-effect");
2335 }
2336 } else {
2337 jQuery(".center-pointer").removeClass("wpvr-pluse-effect");
2338 c_time = new Date();
2339 timer = c_time.getTime() + 2000;
2340 }
2341 } else {
2342 jQuery(".center-pointer").removeClass("wpvr-pluse-effect");
2343 c_time = new Date();
2344 timer = c_time.getTime() + 2000;
2345 }
2346 } else {
2347 c_time = new Date();
2348 timer = c_time.getTime() + 2000;
2349 }
2350 } else {
2351 c_time = new Date();
2352 timer = c_time.getTime() + 2000;
2353 }
2354 }
2355 }
2356 }
2357 }
2358 }
2359 };
2360 function vrDeviseOrientation(){
2361 var data = {
2362 pitch: panoshow' . $pano_suffix . '.getPitch(),
2363 yaw: panoshow' . $pano_suffix . '.getYaw(),
2364 };
2365 panoShowCardBoardOnTrigger(data);
2366 }';
2367 $html .= '
2368 function requestFullScreen(){
2369 var elem = document.getElementById("' . $master_container_id . '") || document.getElementById("master-container");
2370 if (elem) {
2371 if (elem.requestFullscreen) {
2372 elem.requestFullscreen();
2373 } else if (elem.webkitRequestFullscreen) { /* Safari */
2374 elem.webkitRequestFullscreen();
2375 } else if (elem.msRequestFullscreen) { /* IE11 */
2376 elem.msRequestFullscreen();
2377 }
2378 }
2379 }
2380 function requestExitFullscreen(){
2381 var elem = document.getElementById("' . $master_container_id . '") || document.getElementById("master-container");
2382 if (document.exitFullscreen) {
2383 document.exitFullscreen();
2384 } else if (document.webkitExitFullscreen) { /* Safari */
2385 document.webkitExitFullscreen();
2386 } else if (document.msExitFullscreen) { /* IE11 */
2387 document.msExitFullscreen();
2388 }
2389 }
2390 jQuery(document).on("click",".fullscreen-button .expand",function() {
2391 jQuery(this).hide()
2392 jQuery(this).parent().find(".compress").show()
2393 requestFullScreen()
2394 });
2395 jQuery(document).on("click",".fullscreen-button .compress",function() {
2396 jQuery(this).hide()
2397 jQuery(this).parent().find(".expand").show()
2398 requestExitFullscreen()
2399 screen.orientation.unlock();
2400 });
2401 let onLoadAnalytics = false;
2402 let sceneLoadAnalytics = false;
2403
2404 function storeAnalyticsData(data) {
2405 if (typeof wpvrAnalyticsObj !== "undefined") {
2406 if (typeof wpvr_public !== "undefined") {
2407 if (wpvr_public.is_pro_active) {
2408 jQuery.ajax({
2409 url: wpvrAnalyticsObj.ajaxUrl,
2410 type: "POST",
2411 data: {
2412 action: "store_scene_hotspot_data",
2413 scene_id: data.scene_id,
2414 tour_id: data.tour_id,
2415 type: data.type,
2416 hotspot_id: data.hotspot_id || "",
2417 user_agent: navigator.userAgent,
2418 device_type: getDeviceType() || "desktop",
2419 nonce: wpvrAnalyticsObj.nonce,
2420 },
2421 success: function (response) {
2422 console.log("Data stored successfully");
2423 },
2424 error: function (error) {
2425 console.log("Error in storing data");
2426 }
2427 });
2428 }
2429 }
2430 } else {
2431 console.warn("Analytics object not available or pro not active");
2432 }
2433 }
2434 function getDeviceType() {
2435 const userAgent = navigator.userAgent.toLowerCase();
2436 if (/mobile|android|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test(userAgent)) {
2437 return "mobile";
2438 } else if (/tablet|ipad/i.test(userAgent)) {
2439 return "tablet";
2440 } else {
2441 return "desktop";
2442 }
2443 }
2444 panoshow' . $pano_suffix . '.on("scenechange", function(scene) {
2445 onLoadAnalytics = true;
2446 sceneLoadAnalytics = true;
2447 let scene_id = scene;
2448 let tour_id = ' . $id . ';
2449 let type = "scene";
2450 let hotspot_id = "";
2451 let user_agent = navigator.userAgent;
2452 let device_type = getDeviceType() ? getDeviceType() : "desktop";
2453 storeAnalyticsData({
2454 scene_id: scene_id,
2455 tour_id: tour_id,
2456 type: type,
2457 hotspot_id: hotspot_id,
2458 user_agent: user_agent,
2459 device_type: device_type,
2460 });
2461 });
2462 panoshow' . $pano_suffix . '.on("load", function() {
2463 let scene_id = panoshow' . $pano_suffix . '.getScene();
2464 let tour_id = ' . $id . ';
2465 let type = "scene";
2466 let hotspot_id = "";
2467 let user_agent = navigator.userAgent;
2468 let device_type = getDeviceType() ? getDeviceType() : "desktop";
2469 if(!onLoadAnalytics) {
2470 if(!sceneLoadAnalytics) {
2471 storeAnalyticsData({
2472 scene_id: scene_id,
2473 tour_id: tour_id,
2474 type: type,
2475 hotspot_id: hotspot_id,
2476 user_agent: user_agent,
2477 device_type: device_type,
2478 });
2479 }
2480 }
2481 });
2482 function wpvrhotspotscene' . $pano_suffix . '(hotSpotDiv, args) {
2483 onLoadAnalytics = true;
2484 let scene_id = panoshow' . $pano_suffix . '.getScene();
2485 let tour_id = ' . $id . ';
2486 let type = "hotspot";
2487 let hotspot_id = args;
2488 let user_agent = navigator.userAgent;
2489 let device_type = getDeviceType() ? getDeviceType() : "desktop";
2490 storeAnalyticsData({
2491 scene_id: scene_id,
2492 tour_id: tour_id,
2493 type: type,
2494 hotspot_id: hotspot_id,
2495 user_agent: user_agent,
2496 device_type: device_type
2497 });
2498 }
2499 var wpvrhotspotscene = wpvrhotspotscene' . $pano_suffix . ';
2500 ';
2501 $html .= 'panoshow' . $pano_suffix . '.on("scenechange", function (scene){
2502 jQuery(".center-pointer").removeClass("wpvr-pluse-effect")
2503 active_scene = scene;
2504 // if(localStorage.getItem("vr_mode") == "on") {
2505 if(vr_mode == "on") {
2506 jQuery("#' . $panoid2 . ' .pnlm-compass.pnlm-controls.pnlm-control").css("display","none");
2507 jQuery("#' . $panoid . ' .pnlm-compass.pnlm-controls.pnlm-control").css("display","none");
2508 }
2509 });
2510 var compassBlock = "";
2511 var infoBlock = "";
2512 jQuery(document).on("click",".vr_mode_change' . $pano_suffix . '",function (){
2513 jQuery("#' . $panoid2 . ' .pnlm-load-button").trigger("click");
2514 jQuery("#' . $panoid . ' .pnlm-load-button").trigger("click");
2515 var getValue = jQuery(this).val();
2516 var getParent = jQuery(this).parent().parent();
2517 var compass = getParent.find("#' . $panoid2 . ' .pnlm-compass.pnlm-controls.pnlm-control").css("display");
2518 var panoInfo = getParent.find("#' . $panoid . ' .pnlm-panorama-info").css("display");
2519 if(compass == "block"){
2520 compassBlock = "block";
2521 }
2522 if(panoInfo == "block"){
2523 infoBlock = "block";
2524 }
2525 if (getValue == "off") {
2526 requestFullScreen()
2527 screen.orientation.lock("landscape-primary").then(function() {
2528 }).catch(function(error) {
2529 alert("VR Glass Mode not supported in this device");
2530 });
2531 // localStorage.setItem("vr_mode", "on");
2532 vr_mode = "on";
2533 jQuery(".vr-mode-title").show();
2534 jQuery(this).val("on");
2535 getParent.find("#' . $panoid2 . '").css({
2536 "opacity": "1",
2537 "visibility": "visible",
2538 "position": "relative",
2539 });
2540 gyroSwitch = true;
2541 panoshow' . $pano_suffix . '.startOrientation();
2542 panoshow2' . $pano_suffix . '.startOrientation();
2543 panoshow2' . $pano_suffix . '.setPitch(panoshow' . $pano_suffix . '.getPitch(), 0);
2544 panoshow2' . $pano_suffix . '.setYaw(panoshow' . $pano_suffix . '.getYaw(), 0);
2545 getParent.find(".pano-wrap").addClass("wpvr-cardboard-disable-event");
2546 getParent.find("#' . $panoid . ' #zoom-in-out-controls' . $pano_suffix . '").hide();
2547 getParent.find("#' . $panoid . ' #controls' . $pano_suffix . '").hide();
2548 getParent.find("#' . $panoid . ' #explainer_button_' . $pano_suffix . '").hide();
2549 getParent.find("#' . $panoid . ' #generic_form_button_' . $pano_suffix . '").hide();
2550 getParent.find("#' . $panoid . ' #floor_map_button_' . $pano_suffix . '").hide();
2551 getParent.find("#' . $panoid . ' #vrgcontrols' . $pano_suffix . '").hide();
2552 getParent.find("#' . $panoid . ' #sccontrols' . $pano_suffix . '").hide();
2553 getParent.find("#' . $panoid . ' #adcontrol' . $pano_suffix . '").hide();
2554 getParent.find("#' . $panoid . ' .wpvr_slider_nav").hide();
2555 getParent.find("#' . $panoid . ' #cp-logo-controls").hide();
2556 getParent.find("#' . $panoid . ' #wpvr-social-share-bg-box' . $pano_suffix . '").hide();
2557 getParent.find("#' . $panoid2 . ' .pnlm-controls-container").hide();
2558 getParent.find("#' . $panoid . ' .pnlm-controls-container").hide();
2559 getParent.find("#' . $panoid2 . ' .pnlm-compass.pnlm-controls.pnlm-control").hide();
2560 getParent.find("#' . $panoid . ' .pnlm-compass.pnlm-controls.pnlm-control").hide();
2561 getParent.find("#' . $panoid2 . ' .pnlm-panorama-info").hide();
2562 getParent.find("#' . $panoid . ' .pnlm-panorama-info").hide();
2563 getParent.find("#' . $panoid . '").addClass("cardboard-half");
2564 getParent.find("#center-pointer' . $pano_suffix . '").show();
2565 getParent.find(".fullscreen-button").hide();
2566 getParent.find("#' . $panoid . ' #custom-scene-navigation' . $pano_suffix . '").hide();
2567 if (window.DeviceOrientationEvent) {
2568 window.addEventListener("deviceorientation", vrDeviseOrientation);
2569 }
2570 panoshow' . $pano_suffix . '.on("zoomchange", function (data){
2571 panoshow2' . $pano_suffix . '.setHfov(data, 0);
2572 });
2573 panoshow2' . $pano_suffix . '.on("zoomchange", function (data){
2574 panoshow' . $pano_suffix . '.setHfov(data, 0);
2575 });
2576 jQuery(document).on("click","#' . $panoid2 . '",function(event) {
2577 panoshow' . $pano_suffix . '.startOrientation();
2578 panoshow2' . $pano_suffix . '.startOrientation();
2579 });
2580 jQuery(document).on("click","#' . $panoid . '",function(event) {
2581 panoshow' . $pano_suffix . '.startOrientation();
2582 panoshow2' . $pano_suffix . '.startOrientation();
2583 });
2584 panoshow' . $pano_suffix . '.on("mousemove", function (data){
2585 panoshow2' . $pano_suffix . '.setPitch(data.pitch, 0);
2586 panoshow2' . $pano_suffix . '.setYaw(data.yaw, 0);
2587 panoShowCardBoardOnTrigger(data);
2588 });
2589 panoshow2' . $pano_suffix . '.on("mousemove", function (data){
2590 panoshow' . $pano_suffix . '.setPitch(data.pitch, 0);
2591 panoshow' . $pano_suffix . '.setYaw(data.yaw, 0);
2592 panoShowCardBoardOnTrigger(data);
2593 });
2594 panoshow' . $pano_suffix . '.on("touchmove", function (data){
2595 panoshow' . $pano_suffix . '.stopOrientation();
2596 panoshow2' . $pano_suffix . '.stopOrientation();
2597 panoshow2' . $pano_suffix . '.setPitch(data.pitch, 0);
2598 panoshow2' . $pano_suffix . '.setYaw(data.yaw, 0);
2599 panoShowCardBoardOnTrigger(data);
2600 });
2601 panoshow2' . $pano_suffix . '.on("touchmove", function (data){
2602 panoshow' . $pano_suffix . '.stopOrientation();
2603 panoshow2' . $pano_suffix . '.stopOrientation();
2604 panoshow' . $pano_suffix . '.setPitch(data.pitch, 0);
2605 panoshow' . $pano_suffix . '.setYaw(data.yaw, 0);
2606 panoShowCardBoardOnTrigger(data);
2607 });
2608 } else if(getValue == "on") {
2609 screen.orientation.unlock();
2610 requestExitFullscreen();
2611 // localStorage.setItem("vr_mode", "off");
2612 vr_mode = "off";
2613 jQuery(".vr-mode-title").hide();
2614 jQuery(this).val("off");
2615 getParent.find("#' . $panoid2 . '").css({
2616 "opacity": "0",
2617 "visibility": "hidden",
2618 "position": "absolute",
2619 });
2620 getParent.find(".pano-wrap").removeClass("wpvr-cardboard-disable-event");
2621 getParent.find("#' . $panoid . ' #zoom-in-out-controls' . $pano_suffix . '").show();
2622 getParent.find("#' . $panoid . ' #controls' . $pano_suffix . '").show();
2623 getParent.find("#' . $panoid . ' #explainer_button_' . $pano_suffix . '").show();
2624 getParent.find("#' . $panoid . ' #generic_form_button_' . $pano_suffix . '").show();
2625 getParent.find("#' . $panoid . ' #floor_map_button_' . $pano_suffix . '").show();
2626 getParent.find("#' . $panoid2 . ' .pnlm-controls-container").show();
2627 getParent.find("#' . $panoid . ' .pnlm-controls-container").show();
2628 getParent.find("#' . $panoid . ' #vrgcontrols' . $pano_suffix . '").show();
2629 getParent.find("#' . $panoid . ' #sccontrols' . $pano_suffix . '").hide();
2630 getParent.find("#' . $panoid . ' #adcontrol' . $pano_suffix . '").show();
2631 getParent.find("#' . $panoid . ' .wpvr_slider_nav").hide();
2632 getParent.find("#' . $panoid . ' #cp-logo-controls").show();
2633 getParent.find("#' . $panoid . ' #wpvr-social-share-bg-box' . $pano_suffix . '").show();
2634 getParent.find("#' . $panoid . ' #custom-scene-navigation' . $pano_suffix . '").show();
2635 if(compassBlock == "block"){
2636 getParent.find("#' . $panoid2 . ' .pnlm-compass.pnlm-controls.pnlm-control").show();
2637 getParent.find("#' . $panoid . ' .pnlm-compass.pnlm-controls.pnlm-control").show();
2638 }
2639 if(infoBlock == "block"){
2640 getParent.find("#' . $panoid2 . ' .pnlm-panorama-info").show();
2641 getParent.find("#' . $panoid . ' .pnlm-panorama-info").show();
2642 }
2643 getParent.find("#' . $panoid . '").removeClass("cardboard-half");
2644 getParent.find("#center-pointer' . $pano_suffix . '").hide();
2645 getParent.find(".fullscreen-button").hide();
2646 panoshow' . $pano_suffix . '.off("mousemove");
2647 panoshow' . $pano_suffix . '.off("touchmove");
2648 panoshow2' . $pano_suffix . '.off("mousemove");
2649 panoshow2' . $pano_suffix . '.off("touchmove");
2650 if (window.DeviceOrientationEvent) {
2651 window.removeEventListener("deviceorientation", vrDeviseOrientation);
2652 }
2653 }
2654 });';
2655 $html .= 'panoshow2' . $pano_suffix . '.on("load", function (){
2656 // if(localStorage.getItem("vr_mode") == "off") {
2657 if( vr_mode == "off") {
2658 jQuery(".vr-mode-title").hide();
2659 }
2660 else {
2661 jQuery("#' . $panoid2 . ' .pnlm-compass.pnlm-controls.pnlm-control").css("display","none");
2662 jQuery("#' . $panoid . ' .pnlm-compass.pnlm-controls.pnlm-control").css("display","none");
2663 jQuery("#' . $panoid2 . ' .pnlm-panorama-info").hide();
2664 jQuery("#' . $panoid . ' .pnlm-panorama-info").hide();
2665 jQuery(".vr-mode-title").show();
2666 }
2667 });';
2668 }
2669 //=== end Dplicate mode only for vr mode===//
2670 $html .= 'jQuery("#' . $panoid . ' .wpvr-floor-map .floor-plan-pointer").on("click",function(){
2671 var scene_id = jQuery(this).attr("scene_id");
2672 panoshow' . $pano_suffix . '.loadScene(scene_id)
2673 jQuery(".floor-plan-pointer").removeClass("add-pulse")
2674 jQuery(this).addClass("add-pulse")
2675 });';
2676 if ($scene_animation_enabled && is_plugin_active('wpvr-pro/wpvr-pro.php')) {
2677 $animation_type = $postdata['sceneAnimationName'] ?? 'none';
2678 $animation_type = $animation_type === 'fade' ? 'fade_in' : $animation_type;
2679 $animationDuration = $postdata['sceneAnimationTransitionDuration'] ?? '500ms';
2680 $animationDelay = $postdata['sceneAnimationTransitionDelay'] ?? '0ms';
2681 $animation_js = apply_filters('wpvr_scene_animation_js', $id, $animation_type, $animationDuration, $animationDelay);
2682 if (!empty($animation_js)) {
2683 $html .= $animation_js;
2684 $html .= 'panoshow' . $pano_suffix . '.on("load", function (scene){
2685 if (typeof changeScene === "function") {
2686 changeScene();
2687 } else {
2688 console.warn("changeScene function is not defined.");
2689 }
2690 });';
2691 }
2692 }
2693
2694 $html .= 'panoshow' . $pano_suffix . '.on("mousemove", function (data){
2695 jQuery(".add-pulse").css({"transform":"rotate("+data.yaw+"deg)"});
2696 });
2697 ';
2698 $status = get_option('wpvr_edd_license_status');
2699 if ($status !== false && 'valid' == $status && $is_pro){
2700 $html .= 'panoshow' . $pano_suffix . '.on("scenechange", function (scene){
2701 jQuery(".center-pointer").removeClass("wpvr-pluse-effect")
2702 jQuery(".floor-plan-pointer").each(function(index ,element){
2703 var scene_id = jQuery(this).attr("scene_id");
2704 if( active_scene == scene_id ){
2705 jQuery(".floor-plan-pointer").removeClass("add-pulse")
2706 jQuery(this).addClass("add-pulse")
2707 }
2708 });
2709 });';
2710 $html .= 'panoshow' . $pano_suffix . '.on("load", function (){
2711 if(jQuery(".floor-plan-pointer").length > 0){
2712 jQuery(".floor-plan-pointer").each(function(index ,element){
2713 var scene_id = jQuery(this).attr("scene_id");
2714 if( active_scene == scene_id ){
2715 jQuery(".floor-plan-pointer").removeClass("add-pulse")
2716 jQuery(this).addClass("add-pulse")
2717 }
2718 });
2719 }
2720 });';
2721 }
2722 if ($status !== false && 'valid' == $status && $is_pro){
2723 $scene_navigation_content_type = isset($postdata['scene_navigation_content_type']) ? $postdata['scene_navigation_content_type'] : 'scene_id';
2724 $html .= 'jQuery("#' . $panoid . ' .custom-scene-navigation").on("click", function() {
2725 jQuery("#custom-scene-navigation-nav' . $pano_suffix . ' ul").empty();
2726 if (scenes) {
2727 var scene_navigation_content_type = "' . $scene_navigation_content_type . '";
2728 var sceneList = scenes.scenes;
2729 var getScene = panoshow' . $pano_suffix . '.getScene();
2730 for (const key in sceneList) {
2731 let title;
2732 if (scene_navigation_content_type === "scene_title") {
2733 if (sceneList[key].title) {
2734 title = sceneList[key].title;
2735 } else {
2736 if (title == "" || title == undefined) {
2737 if (sceneList[key].panorama) {
2738 title = getImageNameWithoutExtension(sceneList[key].panorama);
2739 }
2740 }
2741 }
2742 } else if (scene_navigation_content_type === "scene_image_name") {
2743 if (sceneList[key].panorama) {
2744 title = getImageNameWithoutExtension(sceneList[key].panorama);
2745 }
2746 } else {
2747 title = key;
2748 }
2749 if (sceneList.hasOwnProperty(key)) {
2750 let ulElement = document.querySelector("#custom-scene-navigation-nav' . $pano_suffix . ' ul");
2751 if (ulElement) {
2752 let liElement = document.createElement("li");
2753 liElement.className = "scene-navigation-list" + (key === getScene ? " active" : "");
2754 liElement.setAttribute("scene_id", key);
2755 liElement.textContent = title;
2756 ulElement.appendChild(liElement);
2757 }
2758 }
2759 }
2760 jQuery("#custom-scene-navigation-nav' . $pano_suffix . '").toggleClass("visible");
2761 }
2762 });';
2763 $html .='function getImageNameWithoutExtension(imageUrl) {
2764 // Split the URL by "/"
2765 var parts = imageUrl.split("/");
2766 // Get the last part which contains the image name
2767 var imageNameWithExtension = parts[parts.length - 1];
2768 // Split the image name by period (.)
2769 var imageNameParts = imageNameWithExtension.split(".");
2770 // Remove the last part (which is the extension) and join the remaining parts
2771 var imageNameWithoutExtension = imageNameParts.slice(0, -1).join(".");
2772 // Return the image name without extension
2773 return imageNameWithoutExtension;
2774 }';
2775 $html .= 'jQuery("#' . $panoid . ' #custom-scene-navigation-nav' . $pano_suffix . ' ul").on("click", "li.scene-navigation-list", function() {
2776 if (scenes) {
2777 jQuery(this).siblings("li").removeClass("active");
2778 jQuery(this).addClass("active");
2779 var scene_key = jQuery(this).attr("scene_id");
2780 panoshow' . $pano_suffix . '.loadScene(scene_key);
2781 }
2782 });';
2783 }
2784 $html .= 'const node = document.querySelector(".add-pulse");
2785 panoshow' . $pano_suffix . '.on("compasschange", function (data){
2786 // const node = document.querySelector(".add-pulse");
2787 // node.style.transform = data;
2788 // jQuery(".add-pulse").css({"transform":data});
2789 });';
2790 $html .= 'panoshow' . $pano_suffix . '.on("load", function (){
2791 // if(localStorage.getItem("vr_mode") == "off") {
2792 if(vr_mode == "off") {
2793 jQuery(".vr-mode-title").hide();
2794 } else {
2795 jQuery("#' . $panoid2 . ' .pnlm-compass.pnlm-controls.pnlm-control").css("display","none");
2796 jQuery("#' . $panoid . ' .pnlm-compass.pnlm-controls.pnlm-control").css("display","none");
2797 jQuery("#' . $panoid2 . ' .pnlm-panorama-info").hide();
2798 jQuery("#' . $panoid . ' .pnlm-panorama-info").hide();
2799 jQuery(".vr-mode-title").show();
2800 }
2801 setTimeout(() => {
2802 window.dispatchEvent(new Event("resize"));
2803 }, 200);
2804 if (jQuery("#' . $panoid . '").children().children(".pnlm-panorama-info:visible").length > 0) {
2805 jQuery("#controls' . $pano_suffix . '").css("bottom", "80px");
2806 }
2807 else {
2808 jQuery("#controls' . $pano_suffix . '").css("bottom", "5px");
2809 }
2810 });';
2811 $html .= 'panoshow' . $pano_suffix . '.on("render", function (){
2812 window.dispatchEvent(new Event("resize"));
2813 });';
2814 $html .= 'if (scenes.autoRotate) {
2815 var wpvrAutoRotateTimer' . $pano_suffix . ' = null;
2816 var wpvrAutoRotateStopDelay' . $pano_suffix . ' = parseInt(scenes.autoRotateStopDelay, 10) || 0;
2817 var wpvrScheduleAutoRotate' . $pano_suffix . ' = function () {
2818 clearTimeout(wpvrAutoRotateTimer' . $pano_suffix . ');
2819 if (wpvrAutoRotateStopDelay' . $pano_suffix . ' > 0) {
2820 wpvrAutoRotateTimer' . $pano_suffix . ' = setTimeout(function () {
2821 panoshow' . $pano_suffix . '.stopAutoRotate();
2822 }, wpvrAutoRotateStopDelay' . $pano_suffix . ');
2823 } else {
2824 wpvrAutoRotateTimer' . $pano_suffix . ' = setTimeout(function () {
2825 panoshow' . $pano_suffix . '.startAutoRotate(scenes.autoRotate, 0);
2826 }, 3000);
2827 }
2828 };
2829 panoshow' . $pano_suffix . '.on("load", wpvrScheduleAutoRotate' . $pano_suffix . ');
2830 panoshow' . $pano_suffix . '.on("scenechange", wpvrScheduleAutoRotate' . $pano_suffix . ');
2831 }';
2832 $html .= 'var touchtime = 0;';
2833 $html .= '
2834 var wpvrHotspotRoot' . $pano_suffix . ' = document.getElementById("' . $panoid . '");
2835 if (wpvrHotspotRoot' . $pano_suffix . ') {
2836 wpvrHotspotRoot' . $pano_suffix . '.addEventListener("click", function (event) {
2837 var hotspot = event.target.closest(".pnlm-hotspot-base");
2838
2839 if (!hotspot) {
2840 return;
2841 }
2842
2843 var hotspotLink = hotspot.closest("a[href]");
2844 if (!hotspotLink) {
2845 hotspotLink = hotspot.querySelector("a[href]");
2846 }
2847
2848 if (!hotspotLink) {
2849 return;
2850 }
2851
2852 event.preventDefault();
2853 event.stopImmediatePropagation();
2854
2855 if ((hotspotLink.getAttribute("target") || "_blank") === "_self") {
2856 window.location.assign(hotspotLink.href);
2857 } else {
2858 window.open(hotspotLink.href, "_blank", "noopener,noreferrer");
2859 }
2860 }, true);
2861 }
2862 ';
2863 if ($vrgallery) {
2864 $gallery_scene_ids = [];
2865 if (isset($panodata["scene-list"])) {
2866 foreach ($panodata["scene-list"] as $panoscenes) {
2867 $scene_key = $panoscenes['scene-id'];
2868 $gallery_scene_ids[] = (string) $scene_key;
2869 $scene_key_gallery = $panoscenes['scene-id'] . '_gallery_' . $pano_suffix;
2870 $html .= 'jQuery(document).on("click","#' . $scene_key_gallery . '",function() {
2871 panoshow' . $pano_suffix . '.loadScene("' . $scene_key . '");
2872 });';
2873 }
2874 }
2875
2876 $is_modern_gallery = isset($postdata['tourLayout']['layout']) && 'layout1' === $postdata['tourLayout']['layout'];
2877 $gallery_options = $is_modern_gallery
2878 ? '{
2879 loop: false,
2880 nav: false,
2881 dots: false,
2882 margin: 18,
2883 mouseDrag: false,
2884 responsive: {
2885 0: { items: 2 },
2886 320: { items: 3 },
2887 500: { items: 4 },
2888 690: { items: 5 }
2889 }
2890 }'
2891 : '{
2892 autoWidth: true,
2893 loop: false,
2894 nav: false,
2895 dots: false,
2896 margin: 10,
2897 stagePadding: 0
2898 }';
2899
2900 $html .= '
2901 var wpvrGallery' . $pano_suffix . ' = jQuery("#sccontrols' . $pano_suffix . '");
2902 var wpvrGalleryRoot' . $pano_suffix . ' = jQuery("#' . $panoid . '");
2903 var wpvrGalleryScenes' . $pano_suffix . ' = ' . wp_json_encode(array_values($gallery_scene_ids)) . ';
2904 var wpvrGalleryResizeTimer' . $pano_suffix . ';
2905 var wpvrGalleryVisibilityTimer' . $pano_suffix . ';
2906 var wpvrGalleryObserver' . $pano_suffix . ';
2907
2908 function wpvrPrepareSceneNavigation' . $pano_suffix . '() {
2909 var navigationDisabled = wpvrGalleryScenes' . $pano_suffix . '.length < 2;
2910 var previousButtons = wpvrGalleryRoot' . $pano_suffix . '.find(".wpvr_owl_prev");
2911 var nextButtons = wpvrGalleryRoot' . $pano_suffix . '.find(".wpvr_owl_next");
2912
2913 wpvrGallery' . $pano_suffix . '.removeClass("owl-theme");
2914 wpvrGalleryRoot' . $pano_suffix . '.find(".wpvr_slider_nav").removeClass("owl-nav");
2915 previousButtons
2916 .removeClass("owl-prev")
2917 .prop("disabled", navigationDisabled)
2918 .toggleClass("disabled", navigationDisabled);
2919 nextButtons
2920 .removeClass("owl-next")
2921 .prop("disabled", navigationDisabled)
2922 .toggleClass("disabled", navigationDisabled);
2923 }
2924
2925 function wpvrRefreshGallery' . $pano_suffix . '() {
2926 wpvrPrepareSceneNavigation' . $pano_suffix . '();
2927
2928 if (!wpvrGallery' . $pano_suffix . '.length || !wpvrGallery' . $pano_suffix . '.hasClass("owl-loaded") || !wpvrGallery' . $pano_suffix . '.is(":visible")) {
2929 return;
2930 }
2931
2932 if (wpvrGallery' . $pano_suffix . '.css("display") === "flex") {
2933 wpvrGallery' . $pano_suffix . '.css("display", "block");
2934 }
2935 wpvrGallery' . $pano_suffix . '.trigger("refresh.owl.carousel");
2936 wpvrUpdateGalleryNavigation' . $pano_suffix . '(panoshow' . $pano_suffix . '.getScene());
2937 }
2938
2939 function wpvrGallerySceneIndex' . $pano_suffix . '(sceneId) {
2940 return wpvrGalleryScenes' . $pano_suffix . '.indexOf(String(sceneId));
2941 }
2942
2943 function wpvrUpdateGalleryNavigation' . $pano_suffix . '(sceneId) {
2944 var currentIndex = wpvrGallerySceneIndex' . $pano_suffix . '(sceneId);
2945 var activeThumbnailId = String(sceneId) + "_gallery_' . $pano_suffix . '";
2946 var thumbnails = wpvrGallery' . $pano_suffix . '.find("img.scctrl");
2947 var activeThumbnail = thumbnails.filter(function () {
2948 return this.id === activeThumbnailId;
2949 });
2950
2951 wpvrPrepareSceneNavigation' . $pano_suffix . '();
2952 thumbnails.removeClass("wpvr-active-thumbnail");
2953 wpvrGallery' . $pano_suffix . '.find(".owl-item").removeClass("clicked");
2954 activeThumbnail.addClass("wpvr-active-thumbnail");
2955 activeThumbnail.closest(".owl-item").addClass("clicked");
2956
2957 if (currentIndex >= 0) {
2958 if (wpvrGallery' . $pano_suffix . '.hasClass("owl-loaded")) {
2959 wpvrGallery' . $pano_suffix . '.trigger("to.owl.carousel", [currentIndex, 300, true]);
2960 window.setTimeout(wpvrPrepareSceneNavigation' . $pano_suffix . ', 0);
2961 }
2962 }
2963 }
2964
2965 function wpvrLoadAdjacentGalleryScene' . $pano_suffix . '(direction) {
2966 var currentIndex = wpvrGallerySceneIndex' . $pano_suffix . '(panoshow' . $pano_suffix . '.getScene());
2967
2968 if (currentIndex < 0 || wpvrGalleryScenes' . $pano_suffix . '.length < 2) {
2969 return;
2970 }
2971
2972 var targetIndex = (currentIndex + direction + wpvrGalleryScenes' . $pano_suffix . '.length) % wpvrGalleryScenes' . $pano_suffix . '.length;
2973 panoshow' . $pano_suffix . '.loadScene(wpvrGalleryScenes' . $pano_suffix . '[targetIndex]);
2974 }
2975
2976 if (jQuery.fn.owlCarousel) {
2977 if (wpvrGallery' . $pano_suffix . '.length) {
2978 if (!wpvrGallery' . $pano_suffix . '.hasClass("owl-loaded")) {
2979 wpvrGallery' . $pano_suffix . '.owlCarousel(' . $gallery_options . ');
2980 }
2981 }
2982 }
2983
2984 wpvrGalleryRoot' . $pano_suffix . '
2985 .off("click.wpvrGalleryRefresh' . $pano_suffix . '", "#vrgcontrols' . $pano_suffix . '")
2986 .on("click.wpvrGalleryRefresh' . $pano_suffix . '", "#vrgcontrols' . $pano_suffix . '", function () {
2987 wpvrPrepareSceneNavigation' . $pano_suffix . '();
2988 window.setTimeout(wpvrRefreshGallery' . $pano_suffix . ', 450);
2989 });
2990
2991 if (wpvrGalleryRoot' . $pano_suffix . '.length) {
2992 wpvrGalleryRoot' . $pano_suffix . '[0].addEventListener("click", function (event) {
2993 var navigationButton = event.target.closest(".wpvr_owl_prev, .wpvr_owl_next");
2994
2995 if (!navigationButton) {
2996 return;
2997 }
2998
2999 if (!wpvrGalleryRoot' . $pano_suffix . '[0].contains(navigationButton)) {
3000 return;
3001 }
3002
3003 event.preventDefault();
3004 event.stopImmediatePropagation();
3005
3006 if (navigationButton.classList.contains("wpvr_owl_prev")) {
3007 wpvrLoadAdjacentGalleryScene' . $pano_suffix . '(-1);
3008 } else {
3009 wpvrLoadAdjacentGalleryScene' . $pano_suffix . '(1);
3010 }
3011 }, true);
3012 }
3013
3014 jQuery(window)
3015 .off("resize.wpvrGallery' . $pano_suffix . '")
3016 .on("resize.wpvrGallery' . $pano_suffix . '", function () {
3017 window.clearTimeout(wpvrGalleryResizeTimer' . $pano_suffix . ');
3018 wpvrGalleryResizeTimer' . $pano_suffix . ' = window.setTimeout(wpvrRefreshGallery' . $pano_suffix . ', 100);
3019 });
3020
3021 if (window.MutationObserver) {
3022 if (wpvrGallery' . $pano_suffix . '.length) {
3023 wpvrGalleryObserver' . $pano_suffix . ' = new MutationObserver(function () {
3024 window.clearTimeout(wpvrGalleryVisibilityTimer' . $pano_suffix . ');
3025 wpvrGalleryVisibilityTimer' . $pano_suffix . ' = window.setTimeout(wpvrRefreshGallery' . $pano_suffix . ', 50);
3026 });
3027 wpvrGalleryObserver' . $pano_suffix . '.observe(wpvrGallery' . $pano_suffix . '[0], {
3028 attributes: true,
3029 attributeFilter: ["style"]
3030 });
3031 }
3032 }
3033
3034 panoshow' . $pano_suffix . '.on("scenechange", function (sceneId) {
3035 wpvrUpdateGalleryNavigation' . $pano_suffix . '(sceneId);
3036 });
3037
3038 window.setTimeout(wpvrRefreshGallery' . $pano_suffix . ', 0);
3039 window.setTimeout(function () {
3040 wpvrUpdateGalleryNavigation' . $pano_suffix . '(panoshow' . $pano_suffix . '.getScene());
3041 }, 0);
3042 ';
3043 }
3044 //===Custom Control===//
3045 if (isset($custom_control)) {
3046 if ($custom_control['panupSwitch'] == "on" && 'valid' == $status && $is_pro) {
3047 $html .= 'document.getElementById("pan-up' . $pano_suffix . '").addEventListener("click", function(e) {';
3048 $html .= 'panoshow' . $pano_suffix . '.setPitch(panoshow' . $pano_suffix . '.getPitch() + 10);';
3049 $html .= '});';
3050 }
3051 if ($custom_control['panDownSwitch'] == "on" && 'valid' == $status && $is_pro) {
3052 $html .= 'document.getElementById("pan-down' . $pano_suffix . '").addEventListener("click", function(e) {';
3053 $html .= 'panoshow' . $pano_suffix . '.setPitch(panoshow' . $pano_suffix . '.getPitch() - 10);';
3054 $html .= '});';
3055 }
3056 if ($custom_control['panLeftSwitch'] == "on" && 'valid' == $status && $is_pro) {
3057 $html .= 'document.getElementById("pan-left' . $pano_suffix . '").addEventListener("click", function(e) {';
3058 $html .= 'panoshow' . $pano_suffix . '.setYaw(panoshow' . $pano_suffix . '.getYaw() - 10);';
3059 $html .= '});';
3060 }
3061 if ($custom_control['panRightSwitch'] == "on" && 'valid' == $status && $is_pro) {
3062 $html .= 'document.getElementById("pan-right' . $pano_suffix . '").addEventListener("click", function(e) {';
3063 $html .= 'panoshow' . $pano_suffix . '.setYaw(panoshow' . $pano_suffix . '.getYaw() + 10);';
3064 $html .= '});';
3065 }
3066 if ($custom_control['panZoomInSwitch'] == "on") {
3067 $html .= 'document.getElementById("zoom-in' . $pano_suffix . '").addEventListener("click", function(e) {';
3068 $html .= 'panoshow' . $pano_suffix . '.setHfov(panoshow' . $pano_suffix . '.getHfov() - 10);';
3069 $html .= '});';
3070 }
3071 if ($custom_control['panZoomOutSwitch'] == "on") {
3072 $html .= 'document.getElementById("zoom-out' . $pano_suffix . '").addEventListener("click", function(e) {';
3073 $html .= 'panoshow' . $pano_suffix . '.setHfov(panoshow' . $pano_suffix . '.getHfov() + 10);';
3074 $html .= '});';
3075 }
3076 if ($custom_control['panFullscreenSwitch'] == "on" && 'valid' == $status && $is_pro) {
3077 $html .= 'document.getElementById("fullscreen' . $pano_suffix . '").addEventListener("click", function(e) {';
3078 $html .= 'panoshow' . $pano_suffix . '.toggleFullscreen();';
3079 $html .= '});';
3080 $html .= '(function() {';
3081 $html .= 'function wpvrFsChange' . $pano_suffix . '() {';
3082 $html .= 'var fsIcon = document.querySelector("#fullscreen' . $pano_suffix . ' i");';
3083 $html .= 'if (!fsIcon) return;';
3084 $html .= 'if (document.fullscreenElement || document.webkitFullscreenElement || document.mozFullScreenElement || document.msFullscreenElement) {';
3085 $html .= 'fsIcon.classList.remove("fa-expand"); fsIcon.classList.add("fa-minimize");';
3086 $html .= '} else {';
3087 $html .= 'fsIcon.classList.remove("fa-minimize"); fsIcon.classList.add("fa-expand");';
3088 $html .= '}';
3089 $html .= '}';
3090 $html .= 'document.addEventListener("fullscreenchange", wpvrFsChange' . $pano_suffix . ');';
3091 $html .= 'document.addEventListener("webkitfullscreenchange", wpvrFsChange' . $pano_suffix . ');';
3092 $html .= 'document.addEventListener("mozfullscreenchange", wpvrFsChange' . $pano_suffix . ');';
3093 $html .= 'document.addEventListener("MSFullscreenChange", wpvrFsChange' . $pano_suffix . ');';
3094 $html .= '})();';
3095 }
3096 if ($custom_control['backToHomeSwitch'] == "on" && 'valid' == $status && $is_pro) {
3097 $html .= 'document.getElementById("backToHome' . $pano_suffix . '").addEventListener("click", function(e) {';
3098 $html .= 'panoshow' . $pano_suffix . '.loadScene("' . $default_scene . '");';
3099 $html .= '});';
3100 }
3101 if ($gyro_button_enabled && 'valid' == $status && $is_pro) {
3102 $html .= '
3103 (function() {
3104 var gyroButton = document.getElementById("gyroscope' . $pano_suffix . '");
3105 var gyroIcon = gyroButton ? gyroButton.querySelector("i") : null;
3106 var activeColor = ' . wp_json_encode($custom_control['gyroscopeColor']) . ';
3107 var permissionGranted = false;
3108
3109 if (!gyroButton || !gyroIcon) {
3110 return;
3111 }
3112
3113 function updateGyroscopeState() {
3114 gyroIcon.style.color = panoshow' . $pano_suffix . '.isOrientationActive()
3115 ? activeColor
3116 : "red";
3117 }
3118
3119 function startGyroscope() {
3120 if (!panoshow' . $pano_suffix . '.isOrientationSupported()) {
3121 updateGyroscopeState();
3122 return;
3123 }
3124
3125 panoshow' . $pano_suffix . '.startOrientation();
3126 window.setTimeout(updateGyroscopeState, 0);
3127 }
3128
3129 function requestGyroscopePermission() {
3130 var orientationEvent = window.DeviceOrientationEvent;
3131 if (orientationEvent) {
3132 if (typeof orientationEvent.requestPermission === "function") {
3133 if (!permissionGranted) {
3134 orientationEvent.requestPermission()
3135 .then(function(state) {
3136 permissionGranted = state === "granted";
3137 if (permissionGranted) {
3138 startGyroscope();
3139 } else {
3140 updateGyroscopeState();
3141 }
3142 })
3143 .catch(updateGyroscopeState);
3144 return;
3145 }
3146 }
3147 }
3148
3149 startGyroscope();
3150 }
3151
3152 panoshow' . $pano_suffix . '.on("load", updateGyroscopeState);
3153 panoshow' . $pano_suffix . '.on("scenechange", updateGyroscopeState);
3154
3155 gyroButton.addEventListener("click", function() {
3156 if (panoshow' . $pano_suffix . '.isOrientationActive()) {
3157 panoshow' . $pano_suffix . '.stopOrientation();
3158 updateGyroscopeState();
3159 return;
3160 }
3161
3162 requestGyroscopePermission();
3163 });
3164 })();';
3165 }
3166 }
3167 $angle_up = '<i class="fa fa-angle-up"></i>';
3168 $angle_down = '<i class="fa fa-angle-down"></i>';
3169 $sin_qout = "'";
3170
3171 //===Explainer Script===//
3172
3173 if ($autoplay_bg_music == 'on') {
3174 $html .= 'jQuery(document).on("click","#explainer_button_' . $pano_suffix . '",function() {
3175 jQuery("#explainer' . $pano_suffix . '").slideToggle();
3176 playing' . $pano_suffix . ' = false;
3177 var x' . $pano_suffix . ' = document.getElementById("vrAudio' . $pano_suffix . '");
3178 jQuery("#vr-volume' . $pano_suffix . '").removeClass("fas fa-volume-up");
3179 jQuery("#vr-volume' . $pano_suffix . '").addClass("fas fa-volume-mute");
3180 x' . $pano_suffix . '.pause();
3181 });
3182 jQuery(document).on("click",".close-explainer-video",function() {
3183 jQuery(this).parent(".explainer").hide();
3184 var el_src = jQuery(".vr-iframe").attr("src");
3185 jQuery(".vr-iframe").attr("src", el_src);
3186 });';
3187 } else {
3188 $html .= 'jQuery(document).on("click","#explainer_button_' . $pano_suffix . '",function() {
3189 jQuery("#explainer' . $pano_suffix . '").slideToggle(function(){
3190 var $explainerVideoId = jQuery("#explainer' . $pano_suffix . '");
3191 var $explainerVideoIframe = $explainerVideoId.find("iframe");
3192 var explainerVideoIframSrc = $explainerVideoIframe.attr("src");
3193 $explainerVideoIframe.attr("src", "");
3194 $explainerVideoIframe.attr("src", explainerVideoIframSrc);
3195 });
3196 });
3197 jQuery(document).on("click", ".close-explainer-video", function() {
3198 var $explainer = jQuery(this).parent(".explainer");
3199 var $iframe = $explainer.find("iframe");
3200 var el_src = $iframe.attr("src");
3201 $iframe.attr("src", "");
3202 $explainer.hide();
3203 $iframe.attr("src", el_src);
3204 });';
3205 }
3206
3207 $html .= '
3208 jQuery(document).on("click","#' . $panoid . '",function(event) {
3209 var isActiveModal = event.target.closest(".custom-ifram-wrapper");
3210 var isForm = event.target.closest(".wpvr-hotspot-tweak-contents");
3211 var isHotspot = event.target.closest(".pnlm-hotspot-base");
3212 if(isForm != null){
3213 jQuery(this).addClass("show-modal");
3214 }else if(isActiveModal == null){
3215 if(isHotspot == null){
3216 jQuery(".custom-ifram-wrapper .custom-ifram").empty();
3217 jQuery(".custom-ifram-wrapper").hide();
3218 jQuery(this).removeClass("show-modal");
3219 jQuery(".wpvr-hotspot-tweak-contents-wrapper").hide("show-modal");
3220 }
3221 }
3222 });';
3223
3224 //===Explainer Script End===//
3225
3226 //===generic form script===//
3227 if (isset($postdata["genericform"]) && $postdata["genericform"] === 'on') {
3228 $html .= '
3229 jQuery(document).on("click","#generic_form_button_' . $pano_suffix . '",function() {
3230 jQuery("#wpvr-generic-form' . $pano_suffix . '").fadeToggle();
3231 });
3232
3233 jQuery(document).on("click",".close-generic-form",function() {
3234 jQuery(this).parent(".wpvr-generic-form").fadeOut()
3235 });
3236 ';
3237 }
3238 //===generic from script===//
3239
3240 //===Floor map Script===//
3241 $html .= 'jQuery(document).on("click","#floor_map_button_' . $pano_suffix . '",function() {
3242 jQuery("#wpvr-floor-map' . $pano_suffix . '").toggle().removeClass("fullwindow");
3243 });
3244 jQuery(document).on("dblclick","#wpvr-floor-map' . $pano_suffix . '",function(){
3245 jQuery(this).addClass("fullwindow");
3246 jQuery(this).parents(".pano-wrap").addClass("show-modal");
3247 });
3248 jQuery(document).on("click",".close-floor-map-plan",function() {
3249 jQuery(this).parent(".wpvr-floor-map").hide();
3250 jQuery(this).parent(".wpvr-floor-map").removeClass("fullwindow");
3251 jQuery(this).parents(".pano-wrap").removeClass("show-modal");
3252 });';
3253 //===Floor map Script End===//
3254
3255 if ($vrgallery_display) {
3256
3257 if (!$autoload) {
3258 $html .= 'jQuery(document).ready(function($){
3259 jQuery("#sccontrols' . $pano_suffix . '").hide();
3260 jQuery(".vrgctrl' . $pano_suffix . '").html(' . $sin_qout . $angle_up . $sin_qout . ');
3261 jQuery("#sccontrols' . $pano_suffix . '").hide();
3262 jQuery("#' . $panoid . ' .wpvr_slider_nav").hide();
3263 });';
3264 $html .= 'var slide' . $pano_suffix . ' = "down";
3265 jQuery(document).on("click","#vrgcontrols' . $pano_suffix . '",function() {
3266 if (slide' . $pano_suffix . ' == "up") {
3267 jQuery(".vrgctrl' . $pano_suffix . '").empty();
3268 jQuery(".vrgctrl' . $pano_suffix . '").html(' . $sin_qout . $angle_up . $sin_qout . ');
3269 slide' . $pano_suffix . ' = "down";
3270 jQuery("#' . $panoid . ' .wpvr_slider_nav").slideToggle();
3271 jQuery("#sccontrols' . $pano_suffix . '").slideToggle(function(){
3272 if (jQuery(".elementor-edit-mode .elementor-widget-container").length) {
3273 if (jQuery(this).is(":visible")) {
3274 jQuery(".elementor-edit-mode .elementor-widget-container .wpvr-cardboard .pnlm-container #sccontrols' . $pano_suffix . '").css({
3275 "display": "flex",
3276 "justify-content": "center",
3277 "align-items": "center",
3278 "gap": "15px"
3279 });
3280 }
3281 }
3282 if (jQuery(".bricks-is-frontend").length) {
3283 if (jQuery(this).is(":visible")) {
3284 jQuery(".bricks-is-frontend .wpvr-cardboard .pnlm-container #sccontrols' . $pano_suffix . '").css({
3285 "display": "flex",
3286 "justify-content": "center",
3287 "align-items": "center"
3288 });
3289 }
3290 }
3291 });
3292 }
3293 else {
3294 jQuery(".vrgctrl' . $pano_suffix . '").empty();
3295 jQuery(".vrgctrl' . $pano_suffix . '").html(' . $sin_qout . $angle_down . $sin_qout . ');
3296 slide' . $pano_suffix . ' = "up";
3297 jQuery("#' . $panoid . ' .wpvr_slider_nav").slideToggle();
3298 jQuery("#sccontrols' . $pano_suffix . '").slideToggle(function(){
3299 if (jQuery(".elementor-edit-mode .elementor-widget-container").length) {
3300 if (jQuery(this).is(":visible")) {
3301 jQuery(".elementor-edit-mode .elementor-widget-container .wpvr-cardboard .pnlm-container #sccontrols' . $pano_suffix . '").css({
3302 "display": "flex",
3303 "justify-content": "center",
3304 "align-items": "center",
3305 "gap": "15px"
3306 });
3307 }
3308 }
3309 if (jQuery(".bricks-is-frontend").length) {
3310 if (jQuery(this).is(":visible")) {
3311 jQuery(".bricks-is-frontend .wpvr-cardboard .pnlm-container #sccontrols' . $pano_suffix . '").css({
3312 "display": "flex",
3313 "justify-content": "center",
3314 "align-items": "center"
3315 });
3316 }
3317 }
3318 });
3319 }
3320 });';
3321 } else {
3322 $html .= 'jQuery(document).ready(function($){
3323 jQuery("#sccontrols' . $pano_suffix . '").show();
3324 jQuery(".vrgctrl' . $pano_suffix . '").html(' . $sin_qout . $angle_down . $sin_qout . ');
3325 jQuery("#' . $panoid . ' .wpvr_slider_nav").show();
3326 });';
3327 $html .= 'var slide' . $pano_suffix . ' = "down";
3328 jQuery(document).on("click","#vrgcontrols' . $pano_suffix . '",function() {
3329 if (slide' . $pano_suffix . ' == "up") {
3330 jQuery(".vrgctrl' . $pano_suffix . '").empty();
3331 jQuery(".vrgctrl' . $pano_suffix . '").html(' . $sin_qout . $angle_down . $sin_qout . ');
3332 slide' . $pano_suffix . ' = "down";
3333 } else {
3334 jQuery(".vrgctrl' . $pano_suffix . '").empty();
3335 jQuery(".vrgctrl' . $pano_suffix . '").html(' . $sin_qout . $angle_up . $sin_qout . ');
3336 slide' . $pano_suffix . ' = "up";
3337 }
3338 jQuery("#' . $panoid . ' .wpvr_slider_nav").slideToggle();
3339 jQuery("#sccontrols' . $pano_suffix . '").slideToggle(function(){
3340 if (jQuery(".elementor-edit-mode .elementor-widget-container").length) {
3341 if (jQuery(this).is(":visible")) {
3342 jQuery(".elementor-edit-mode .elementor-widget-container .wpvr-cardboard .pnlm-container #sccontrols' . $pano_suffix . '").css({
3343 "display": "flex",
3344 "justify-content": "center",
3345 "align-items": "center",
3346 "gap": "15px"
3347 });
3348 }
3349 }
3350 if (jQuery(".bricks-is-frontend").length) {
3351 if (jQuery(this).is(":visible")) {
3352 jQuery(".bricks-is-frontend .wpvr-cardboard .pnlm-container #sccontrols' . $pano_suffix . '").css({
3353 "display": "flex",
3354 "justify-content": "center",
3355 "align-items": "center"
3356 });
3357 }
3358 }
3359 });
3360 });';
3361 }
3362 } else {
3363 $html .= 'jQuery(document).ready(function($){
3364 jQuery("#sccontrols' . $pano_suffix . '").hide();
3365 jQuery("#' . $panoid . ' .wpvr_slider_nav").hide();
3366 jQuery(".vrgctrl' . $pano_suffix . '").html(' . $sin_qout . $angle_up . $sin_qout . ');
3367 });';
3368 $html .= 'var slide' . $pano_suffix . ' = "down";
3369 jQuery(document).on("click","#vrgcontrols' . $pano_suffix . '",function() {
3370 if (slide' . $pano_suffix . ' == "up") {
3371 jQuery(".vrgctrl' . $pano_suffix . '").empty();
3372 jQuery(".vrgctrl' . $pano_suffix . '").html(' . $sin_qout . $angle_up . $sin_qout . ');
3373 slide' . $pano_suffix . ' = "down";
3374 }
3375 else {
3376 jQuery(".vrgctrl' . $pano_suffix . '").empty();
3377 jQuery(".vrgctrl' . $pano_suffix . '").html(' . $sin_qout . $angle_down . $sin_qout . ');
3378 slide' . $pano_suffix . ' = "up";
3379 }
3380 jQuery("#' . $panoid . ' .wpvr_slider_nav").slideToggle();
3381 jQuery("#sccontrols' . $pano_suffix . '").slideToggle(function(){
3382 if (jQuery(".elementor-edit-mode .elementor-widget-container").length) {
3383 if (jQuery(this).is(":visible")) {
3384 jQuery(".elementor-edit-mode .elementor-widget-container .wpvr-cardboard .pnlm-container #sccontrols' . $pano_suffix . '").css({
3385 "display": "flex",
3386 "justify-content": "center",
3387 "align-items": "center",
3388 "gap": "15px"
3389 });
3390 }
3391 }
3392 if (jQuery(".bricks-is-frontend").length) {
3393 if (jQuery(this).is(":visible")) {
3394 jQuery(".bricks-is-frontend .wpvr-cardboard .pnlm-container #sccontrols' . $pano_suffix . '").css({
3395 "display": "flex",
3396 "justify-content": "center",
3397 "align-items": "center"
3398 });
3399 }
3400 }
3401 });
3402 });';
3403 }
3404 if (!$autoload) {
3405 $html .= 'jQuery(document).ready(function(){
3406 jQuery("#controls' . $pano_suffix . '").hide();
3407 jQuery("#zoom-in-out-controls' . $pano_suffix . '").hide();
3408 jQuery("#adcontrol' . $pano_suffix . '").hide();
3409 jQuery("#explainer_button_' . $pano_suffix . '").hide();
3410 jQuery("#generic_form_button_' . $pano_suffix . '").hide();
3411 jQuery("#floor_map_button_' . $pano_suffix . '").hide();
3412 jQuery("#vrgcontrols' . $pano_suffix . '").hide();
3413 jQuery("#cp-logo-controls").hide();
3414 jQuery(".custom-scene-navigation").hide();
3415 jQuery("#' . $panoid . '").find(".pnlm-panorama-info").hide();
3416 });';
3417 if ($vrgallery_display) {
3418 $html .= 'var load_once' . $pano_suffix . ' = "true";';
3419 $html .= 'panoshow' . $pano_suffix . '.on("load", function (){
3420 if (load_once' . $pano_suffix . ' == "true") {
3421 load_once' . $pano_suffix . ' = "false";
3422 jQuery("#sccontrols' . $pano_suffix . '").slideToggle(function(){
3423 if (jQuery(".elementor-edit-mode .elementor-widget-container").length) {
3424 if (jQuery(this).is(":visible")) {
3425 jQuery(".elementor-edit-mode .elementor-widget-container .wpvr-cardboard .pnlm-container #sccontrols' . $pano_suffix . '").css("display", "flex");
3426 }
3427 }
3428 if (jQuery(".bricks-is-frontend").length) {
3429 if (jQuery(this).is(":visible")) {
3430 jQuery(".bricks-is-frontend .wpvr-cardboard .pnlm-container #sccontrols' . $pano_suffix . '").css({
3431 "display": "flex",
3432 "justify-content": "center",
3433 "align-items": "center"
3434 });
3435 }
3436 }
3437 });
3438 jQuery("#' . $panoid . ' .wpvr_slider_nav").slideToggle();
3439 }
3440 });';
3441 }
3442 $html .= 'panoshow' . $pano_suffix . '.on("load", function (){
3443 jQuery("#controls' . $pano_suffix . '").show();
3444 jQuery("#zoom-in-out-controls' . $pano_suffix . '").show();
3445 jQuery("#adcontrol' . $pano_suffix . '").show();
3446 jQuery("#explainer_button_' . $pano_suffix . '").show();
3447 jQuery("#generic_form_button_' . $pano_suffix . '").show();
3448 jQuery("#floor_map_button_' . $pano_suffix . '").show();
3449 jQuery("#vrgcontrols' . $pano_suffix . '").show();
3450 jQuery("#cp-logo-controls").show();
3451 jQuery(".custom-scene-navigation").show();
3452 jQuery("#' . $panoid . '").find(".pnlm-panorama-info").show();
3453 });';
3454 }
3455
3456 //==Old code working properly==//
3457
3458 $previeword = "Click to Load Panorama";
3459 if (isset($postdata['previewtext']) && $postdata['previewtext'] != '') {
3460 $previeword = $postdata['previewtext'];
3461 }
3462 $html .= 'jQuery(".elementor-tab-title").click(function(){
3463 var element_id;
3464 var pano_id;
3465 var element_id = this.id;
3466 element_id = element_id.split("-");
3467 element_id = element_id[3];
3468 jQuery("#elementor-tab-content-"+element_id).find("#' . $master_container_id . '").children("div").eq(1).addClass("awwww");
3469 var pano_id = jQuery(".awwww").attr("id");
3470 jQuery("#elementor-tab-content-"+element_id).find("#' . $master_container_id . '").children("div").eq(1).removeClass("awwww");;
3471 if (pano_id != undefined) {
3472 if (pano_id == "' . $panoid . '") {
3473 jQuery("#' . $panoid . '").children(".pnlm-render-container").remove();
3474 jQuery("#' . $panoid . '").children(".pnlm-ui").remove();
3475 panoshow' . $pano_suffix . ' = pannellum.viewer(response[0]["panoid"], scenes);
3476 window.wpvrViewers = window.wpvrViewers || {};
3477 window.wpvrViewers[response[0]["panoid"]] = panoshow' . $pano_suffix . ';
3478 document.dispatchEvent(new CustomEvent("wpvr:viewer-ready", {
3479 detail: { containerId: response[0]["panoid"], viewer: panoshow' . $pano_suffix . ' }
3480 }));
3481 jQuery("#' . $panoid . '").children(".pnlm-ui").find(".pnlm-load-button p").text("' . $previeword . '")
3482 setTimeout(function() {
3483 // panoshow' . $pano_suffix . '.loadScene("' . $default_scene . '");
3484 window.dispatchEvent(new Event("resize"));
3485 if (jQuery("#' . $panoid . '").children().children(".pnlm-panorama-info:visible").length > 0) {
3486 jQuery("#controls' . $pano_suffix . '").css("bottom", "55px");
3487 } else {
3488 jQuery("#controls' . $pano_suffix . '").css("bottom", "5px");
3489 }
3490 }, 200);
3491 }
3492 }
3493 });';
3494 $html .= 'jQuery(".geodir-tab-head dd, #vr-tour-tab").click(function(){
3495 jQuery("#' . $panoid . '").children(".pnlm-render-container").remove();
3496 jQuery("#' . $panoid . '").children(".pnlm-ui").remove();
3497 panoshow' . $pano_suffix . ' = pannellum.viewer(response[0]["panoid"], scenes);
3498 window.wpvrViewers = window.wpvrViewers || {};
3499 window.wpvrViewers[response[0]["panoid"]] = panoshow' . $pano_suffix . ';
3500 document.dispatchEvent(new CustomEvent("wpvr:viewer-ready", {
3501 detail: { containerId: response[0]["panoid"], viewer: panoshow' . $pano_suffix . ' }
3502 }));
3503 setTimeout(function() {
3504 panoshow' . $pano_suffix . '.loadScene("' . $default_scene . '");
3505 window.dispatchEvent(new Event("resize"));
3506 if (jQuery("#' . $panoid . '").children().children(".pnlm-panorama-info:visible").length > 0) {
3507 jQuery("#controls' . $pano_suffix . '").css("bottom", "55px");
3508 }
3509 else {
3510 jQuery("#controls' . $pano_suffix . '").css("bottom", "5px");
3511 }
3512 }, 200);
3513 });';
3514 if (isset($previeword) && $previeword != '') {
3515 $html .= '
3516 jQuery("#' . $panoid . '").children(".pnlm-ui").find(".pnlm-load-button p").text("' . $previeword . '")
3517 ';
3518 }
3519 if ($default_global_zoom != '' || $max_global_zoom != '' || $min_global_zoom != '') {
3520 $html .= 'jQuery(".globalzoom").val("on").change();';
3521 }
3522
3523 $html .= 'jQuery("#' . $panoid . ' .pnlm-title-box").on("mouseenter", function(){
3524 jQuery(this).attr("title", jQuery(this).text());
3525 });
3526 jQuery("#' . $panoid . ' .pnlm-title-box").on("mouseleave", function(){
3527 jQuery(this).removeAttr("title");
3528 });';
3529 $html .= '});';
3530 $html .= '})(jQuery);';
3531 $html .= '</script>';
3532 $tour_data = [];
3533 if(defined("WPVR_PRO_VERSION")){
3534 $tour_data = array(
3535 'explainerControlSwitch' => (
3536 isset( $postdata['explainerSwitch'] )
3537 && in_array( $postdata['explainerSwitch'], array( true, 1, '1', 'on' ), true )
3538 ) ? 'on' : 'off',
3539 'floor_plan_enable' => $floor_plan_enable ?? '',
3540 'floor_plan_image' => $floor_plan_image ?? '',
3541 'custom_control' => $custom_control ?? '',
3542 );
3543 }
3544 ob_start();
3545 // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
3546 echo $html;
3547 $output = ob_get_clean();
3548 return apply_filters('wpvr_generate_tour_layout_html', $output ,$postdata ,$id, $tour_data);
3549 }
3550
3551 function replace_callback($matches){
3552 foreach ($matches as $match){
3553 return str_replace('<img','<img decoding="async"',$match);
3554 }
3555
3556 }
3557
3558 private function sanitize_content_preserve_styles($content, $allow_forms = false) {
3559 // Decode HTML entities first (in case content was encoded in database)
3560 $content = html_entity_decode($content, ENT_QUOTES | ENT_HTML5, 'UTF-8');
3561
3562 // Escape <script> blocks to display as text instead of removing them
3563 $content = preg_replace_callback('/<script\b[^>]*>(.*?)<\/script>/si', function($matches) {
3564 return esc_html($matches[0]); // Convert to plain text
3565 }, $content);
3566
3567 // Strip dangerous URL-based attributes
3568 $content = preg_replace('/(href|action|formaction)\s*=\s*["\']?\s*(javascript|vbscript|data|about):/i', '$1=""', $content);
3569
3570 // Escape inline event handlers (onclick, onhover, etc.) to display as text
3571 $content = preg_replace_callback('/\s*(on\w+)\s*=\s*(["\'])([^"\']*)\2/i', function($matches) {
3572 // Escape the attribute value but keep the attribute name visible as text
3573 return ' ' . esc_html($matches[1]) . '=' . $matches[2] . esc_html($matches[3]) . $matches[2];
3574 }, $content);
3575 $content = preg_replace_callback('/\s*(on\w+)\s*=\s*([^>\s]+)/i', function($matches) {
3576 // Handle unquoted event handlers
3577 return ' ' . esc_html($matches[1]) . '=' . esc_html($matches[2]);
3578 }, $content);
3579
3580 // Remove unsafe embedded/interactive elements
3581 if ($allow_forms) {
3582 $content = preg_replace('/<(object|embed|applet|frame|frameset|meta|link|base)\b[^>]*>/i', '', $content);
3583 $content = preg_replace('/<\/(object|embed|applet|frame|frameset|meta|link|base)>/i', '', $content);
3584 } else {
3585 $content = preg_replace('/<(object|embed|applet|frame|frameset|meta|link|base|form|input|button|textarea|select|option)\b[^>]*>/i', '', $content);
3586 $content = preg_replace('/<\/(object|embed|applet|frame|frameset|meta|link|base|form|input|button|textarea|select|option)>/i', '', $content);
3587 }
3588
3589 // Clean style attributes safely
3590 $content = preg_replace_callback('/style\s*=\s*["\']([^"\']*)["\']/', function($matches) {
3591 $style = $matches[1];
3592 $style = preg_replace('/expression\s*\(/i', '', $style);
3593 $style = preg_replace('/(javascript|vbscript|data|about)\s*:/i', '', $style);
3594 $style = preg_replace('/url\s*\(\s*["\']?\s*(javascript|vbscript|data):/i', '', $style);
3595 $style = preg_replace('/behavior\s*:/i', '', $style);
3596 $style = preg_replace('/-moz-binding\s*:/i', '', $style);
3597 return 'style="' . esc_attr($style) . '"';
3598 }, $content);
3599
3600 // Sanitize <style> blocks
3601 $content = preg_replace_callback('/<style\b[^>]*>(.*?)<\/style>/si', function($matches) {
3602 $css = $matches[1];
3603 $css = preg_replace('/(expression|javascript|vbscript|data|about)\s*:/i', '', $css);
3604 $css = preg_replace('/url\s*\(\s*["\']?\s*(javascript|vbscript|data):/i', '', $css);
3605 $css = preg_replace('/behavior\s*:/i', '', $css);
3606 $css = preg_replace('/-moz-binding\s*:/i', '', $css);
3607 return '<style>' . esc_html($css) . '</style>';
3608 }, $content);
3609
3610 // Allow iframes from safe sources only (e.g., YouTube, Vimeo)
3611 $allowed_tags = wp_kses_allowed_html('post');
3612 $allowed_tags['iframe'] = [
3613 'src' => true,
3614 'width' => true,
3615 'height' => true,
3616 'frameborder' => true,
3617 'allowfullscreen' => true,
3618 'class' => true,
3619 'style' => true,
3620 'title' => true,
3621 'allow' => true,
3622 'name' => true,
3623 'referrerpolicy' => true,
3624 'loading' => true,
3625 'sandbox' => true,
3626 ];
3627 $allowed_tags['img'] = [
3628 'src' => true,
3629 'alt' => true,
3630 'title' => true,
3631 'width' => true,
3632 'height' => true,
3633 'class' => true,
3634 'id' => true,
3635 'style' => true,
3636 'loading' => true,
3637 'srcset' => true,
3638 'sizes' => true,
3639 ];
3640
3641 if ($allow_forms) {
3642 $form_attributes = [
3643 'id' => true,
3644 'class' => true,
3645 'style' => true,
3646 'name' => true,
3647 'value' => true,
3648 'type' => true,
3649 'placeholder' => true,
3650 'action' => true,
3651 'method' => true,
3652 'target' => true,
3653 'enctype' => true,
3654 'disabled' => true,
3655 'readonly' => true,
3656 'required' => true,
3657 'checked' => true,
3658 'selected' => true,
3659 'multiple' => true,
3660 'size' => true,
3661 'rows' => true,
3662 'cols' => true,
3663 'maxlength' => true,
3664 'minlength' => true,
3665 'min' => true,
3666 'max' => true,
3667 'step' => true,
3668 'pattern' => true,
3669 'autocomplete'=> true,
3670 'autofocus' => true,
3671 'for' => true,
3672 ];
3673 $allowed_tags['form'] = $form_attributes;
3674 $allowed_tags['input'] = $form_attributes;
3675 $allowed_tags['button'] = $form_attributes;
3676 $allowed_tags['textarea'] = $form_attributes;
3677 $allowed_tags['select'] = $form_attributes;
3678 $allowed_tags['option'] = $form_attributes;
3679 $allowed_tags['optgroup'] = $form_attributes;
3680 $allowed_tags['label'] = $form_attributes;
3681 $allowed_tags['fieldset'] = $form_attributes;
3682 $allowed_tags['legend'] = $form_attributes;
3683 }
3684
3685 // Apply wp_kses() to keep only allowed tags/attributes
3686 $content = wp_kses($content, $allowed_tags);
3687
3688 // Finally, validate iframe src for security (allow https only, block javascript: etc.)
3689 $content = preg_replace_callback('/<iframe[^>]+src=["\']([^"\']+)["\'][^>]*>(?:<\/iframe>)?/i', function($matches) {
3690 $src = $matches[1];
3691 // Allow any https:// or http:// URL, but block javascript:, data:, vbscript:, etc.
3692 if (preg_match('/^(https?:)?\/\//i', $src) && !preg_match('/^(javascript|data|vbscript|about):/i', $src)) {
3693 return $matches[0]; // keep safe iframe
3694 }
3695 // Strip unsafe iframe
3696 return '';
3697 }, $content);
3698
3699 return $content;
3700 }
3701
3702 private function normalize_hotspot_external_url($url) {
3703 $url = trim((string) $url);
3704
3705 if (
3706 $url === '' ||
3707 preg_match('/^[a-z][a-z0-9+.-]*:/i', $url) ||
3708 preg_match('/^[\/#?]/', $url)
3709 ) {
3710 return $url;
3711 }
3712
3713 if (preg_match('/^[^\s\/]+\.[^\s\/]+(?:[\/?#]|$)/i', $url)) {
3714 return 'https://' . $url;
3715 }
3716
3717 return $url;
3718 }
3719
3720 }
3721