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

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