PluginProbe
WPVR – 360 Panorama viewer and Virtual Tour Builder for WordPress / 9.0.0
WPVR – 360 Panorama viewer and Virtual Tour Builder for WordPress v9.0.0
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.0.0, at legacy/admin/classes/class-wpvr-scene.php

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