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

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

229 lines 13.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 (function ($) {
2 'use strict';
3
4 function readJSON(value, fallback) {
5 try { return JSON.parse(value); } catch (e) { return fallback; }
6 }
7
8 function enhanceIcon(input) {
9 input.addClass('wpvr-sticker-icon-value');
10 var control = input.parent().find('> .wpvr-sticker-icon-control');
11 if (!control.length) {
12 control = $('<div class="wpvr-sticker-icon-control"><button type="button" class="wpvr-sticker-icon-trigger" aria-expanded="false"><i></i><span></span></button><div class="wpvr-sticker-icon-menu" hidden><input type="search" class="wpvr-sticker-icon-search" placeholder="Search icons" aria-label="Search icons"><div class="wpvr-sticker-icon-grid"></div></div></div>');
13 input.after(control);
14 }
15 var icon = input.val() || 'none';
16 control.find('.wpvr-sticker-icon-trigger i').attr('class', icon === 'none' ? '' : icon);
17 control.find('.wpvr-sticker-icon-trigger span').text(icon === 'none' ? 'No icon' : icon.split(' ').pop().replace(/^fa-/, '').replace(/-/g, ' '));
18 }
19
20 function enhanceField(field) {
21 var input = field.find('.wpvr-sticker-value');
22 var name = input.attr('name') || '';
23 var kind = field.attr('data-kind');
24 if (/-color\]?$/i.test(name)) {
25 if (!field.find('.wpvr-sticker-color-control').length) {
26 input.wrap('<div class="wpvr-sticker-color-control"></div>');
27 $('<input type="color" class="wpvr-sticker-color-swatch" aria-label="Choose color">').insertBefore(input);
28 }
29 var color = /^#[0-9a-f]{6}$/i.test(input.val()) ? input.val() : '#ffffff';
30 field.find('.wpvr-sticker-color-swatch').val(color);
31 }
32 var numberInput = field.find('.wpvr-sticker-number');
33 if (kind === 'number') numberInput.val(input.val());
34 if (kind === 'number' && /(?:rating|bg-opacity|blur|brightness)\]?$/.test(name)) {
35 if (!field.find('.wpvr-sticker-range-control').length) {
36 numberInput.wrap('<div class="wpvr-sticker-range-control"></div>');
37 $('<input type="range" class="wpvr-sticker-range" aria-label="Adjust value">')
38 .attr('min', numberInput.attr('min')).attr('max', numberInput.attr('max')).attr('step', numberInput.attr('step')).insertBefore(numberInput);
39 }
40 field.find('.wpvr-sticker-range').val(input.val());
41 }
42 if (kind === 'toggle') {
43 input.addClass('wpvr-sticker-toggle-value');
44 if (!field.find('.wpvr-sticker-switch').length) {
45 $('<button type="button" role="switch" class="wpvr-sticker-switch"></button><span class="wpvr-sticker-switch-state"></span>').insertAfter(input);
46 }
47 var on = input.val() === 'on';
48 field.find('.wpvr-sticker-switch').attr('aria-checked', String(on)).attr('aria-label', field.find('.wpvr-sticker-field-label').text());
49 field.find('.wpvr-sticker-switch-state').text(on ? 'On' : 'Off');
50 }
51 if (kind === 'media') {
52 if (!field.find('.wpvr-sticker-avatar-preview').length) $('<img class="wpvr-sticker-avatar-preview" alt="Client avatar">').insertBefore(field.find('.wpvr-sticker-avatar-select'));
53 field.find('.wpvr-sticker-avatar-preview').attr('src', input.val() || '').toggle(!!input.val());
54 }
55 if (/btn-icon\]?$/.test(name)) enhanceIcon(input);
56 }
57
58 $(document).on('input change', '.wpvr-sticker-color-swatch, .wpvr-sticker-range, .wpvr-sticker-number', function () {
59 $(this).closest('.wpvr-sticker-field').find('.wpvr-sticker-value').val($(this).val()).trigger('change');
60 });
61 $(document).on('change input', '.wpvr-sticker-value', function () { enhanceField($(this).closest('.wpvr-sticker-field')); });
62 $(document).on('click', '.wpvr-sticker-switch', function () {
63 var input = $(this).closest('.wpvr-sticker-field').find('.wpvr-sticker-value');
64 input.val(input.val() === 'on' ? 'off' : 'on').trigger('change');
65 });
66 function iconChoices() {
67 var icons = ['none', 'fas fa-tag', 'fas fa-shopping-cart', 'fas fa-arrow-right', 'fas fa-link', 'fas fa-star', 'fas fa-heart', 'fas fa-info-circle', 'fas fa-play', 'fas fa-phone', 'fas fa-envelope', 'fas fa-map-marker-alt', 'fas fa-gift', 'fas fa-ticket-alt', 'fas fa-share-alt', 'fab fa-facebook-f', 'fab fa-instagram', 'fab fa-linkedin-in', 'fab fa-twitter', 'fab fa-dribbble', 'fab fa-youtube', 'fab fa-whatsapp'];
68 $('.hotspot-customclass-pro-select').first().find('option').each(function () {
69 if (this.value && icons.indexOf(this.value) === -1) icons.push(this.value);
70 });
71 return icons;
72 }
73 function filterIcons(control) {
74 var term = control.find('.wpvr-sticker-icon-search').val().toLowerCase();
75 var input = control.prev('input');
76 var grid = control.find('.wpvr-sticker-icon-grid').empty();
77 iconChoices().filter(function (icon) { return icon.indexOf(term) !== -1; }).forEach(function (icon) {
78 var button = $('<button type="button" class="wpvr-sticker-icon-option"></button>').attr('data-icon', icon).attr('title', icon).attr('aria-label', icon).attr('aria-pressed', String(input.val() === icon));
79 if (icon === 'none') button.text('×'); else $('<i></i>').attr('class', icon).appendTo(button);
80 grid.append(button);
81 });
82 }
83 $(document).on('click', '.wpvr-sticker-icon-trigger', function () {
84 var control = $(this).closest('.wpvr-sticker-icon-control');
85 var open = $(this).attr('aria-expanded') !== 'true';
86 $(this).attr('aria-expanded', String(open));
87 control.find('.wpvr-sticker-icon-menu').prop('hidden', !open);
88 if (open) { filterIcons(control); control.find('.wpvr-sticker-icon-search').focus(); }
89 });
90 $(document).on('input', '.wpvr-sticker-icon-search', function () { filterIcons($(this).closest('.wpvr-sticker-icon-control')); });
91 $(document).on('click', '.wpvr-sticker-icon-option', function () {
92 var control = $(this).closest('.wpvr-sticker-icon-control');
93 var input = control.prev('input');
94 input.val($(this).attr('data-icon')).trigger('input').trigger('change');
95 enhanceIcon(input);
96 control.find('.wpvr-sticker-icon-menu').prop('hidden', true);
97 control.find('.wpvr-sticker-icon-trigger').attr('aria-expanded', 'false').focus();
98 });
99 $(document).on('keydown', '.wpvr-sticker-icon-control', function (event) {
100 if (event.key === 'Escape') {
101 $(this).find('.wpvr-sticker-icon-menu').prop('hidden', true);
102 $(this).find('.wpvr-sticker-icon-trigger').attr('aria-expanded', 'false').focus();
103 }
104 });
105
106 function renderLinks(field) {
107 var links = readJSON(field.find('.wpvr-sticker-value').val(), []);
108 var list = field.find('.wpvr-sticker-links').empty();
109 links.forEach(function (link) {
110 var row = $('<div class="wpvr-sticker-link" style="margin:10px 0"></div>').appendTo(list);
111 [['icon', 'Icon class'], ['customSvg', 'Custom SVG'], ['url', 'URL']].forEach(function (item) {
112 $('<input type="text" style="width:100%;margin-bottom:5px">')
113 .attr('data-link-key', item[0]).attr('aria-label', item[1]).attr('placeholder', item[1])
114 .val(link[item[0]] || '').appendTo(row);
115 });
116 $('<select data-link-key="openNewTab" aria-label="Open in new tab"><option value="on">New tab</option><option value="off">Same tab</option></select>')
117 .val(link.openNewTab || 'on').appendTo(row);
118 $('<button type="button" class="button wpvr-sticker-link-remove" aria-label="Remove social link">×</button>').appendTo(row);
119 row.data('link-id', link.id);
120 enhanceIcon(row.find('[data-link-key=icon]'));
121 });
122 }
123
124 function syncCompound(field) {
125 var kind = field.attr('data-kind');
126 var value = readJSON(field.find('.wpvr-sticker-value').val(), {});
127 if (kind === 'corners' || kind === 'sides') {
128 field.find('[data-part]').each(function () {
129 $(this).val(value[$(this).attr('data-part')] || 0);
130 });
131 } else if (kind === 'links') {
132 renderLinks(field);
133 }
134 }
135
136 function updateSettings(hotspot, changeTemplate) {
137 var panel = hotspot.find('.wpvr-legacy-sticker-settings');
138 var type = hotspot.find('select[name*="hotspot-type"]').val();
139 var select = panel.find('.wpvr-sticker-template');
140 var template = select.val() || 'social_proof';
141 var previous = panel.data('active-template') || 'social_proof';
142 var fresh = !select.val();
143 select.val(template);
144 panel.toggle(type === 'sticker');
145 if (type === 'sticker') {
146 hotspot.find('.hotspot-scene, .hotspot-url, .s_tab, .hotspot-content, .hotspot-products, .hotspot-fluent-forms, .hotspot-hover').hide();
147 } else {
148 hotspot.find('.hotspot-hover').show();
149 }
150 panel.find('.wpvr-sticker-field').each(function () {
151 var field = $(this);
152 var defaults = readJSON(field.attr('data-defaults'), {});
153 var input = field.find('.wpvr-sticker-value');
154 var oldDefault = typeof defaults[previous] === 'object' ? JSON.stringify(defaults[previous]) : String(defaults[previous]);
155 var newDefault = typeof defaults[template] === 'object' ? JSON.stringify(defaults[template]) : defaults[template];
156 if (fresh || (changeTemplate && String(input.val()) === oldDefault)) input.val(newDefault);
157 var applies = field.attr('data-templates');
158 field.toggle(!applies || applies.split(' ').indexOf(template) !== -1);
159 syncCompound(field);
160 enhanceField(field);
161 });
162 panel.find('.wpvr-sticker-section').each(function () {
163 var applies = $(this).attr('data-templates');
164 $(this).toggle(!applies || applies.split(' ').indexOf(template) !== -1);
165 });
166 panel.data('active-template', template);
167 }
168
169 // Runs after either Free or Pro's legacy handler, which handles the other types.
170 $(document).on('change', 'select[name*="hotspot-type"], .wpvr-sticker-template', function () {
171 updateSettings($(this).closest('.single-hotspot'), $(this).hasClass('wpvr-sticker-template'));
172 });
173 $(document).on('input change', '.wpvr-sticker-field [data-part]', function () {
174 var field = $(this).closest('.wpvr-sticker-field');
175 var value = {};
176 field.find('[data-part]').each(function () { value[$(this).attr('data-part')] = Math.max(0, Number($(this).val()) || 0); });
177 field.find('.wpvr-sticker-value').val(JSON.stringify(value));
178 });
179 function saveLinks(field) {
180 var links = [];
181 field.find('.wpvr-sticker-link').each(function () {
182 var row = $(this);
183 var link = { id: row.data('link-id') || String(Date.now()) + '-' + links.length };
184 row.find('[data-link-key]').each(function () { link[$(this).attr('data-link-key')] = $(this).val(); });
185 links.push(link);
186 });
187 field.find('.wpvr-sticker-value').val(JSON.stringify(links));
188 }
189 $(document).on('input change', '.wpvr-sticker-field [data-link-key]', function () {
190 saveLinks($(this).closest('.wpvr-sticker-field'));
191 });
192 $(document).on('click', '.wpvr-sticker-link-add, .wpvr-sticker-link-remove', function () {
193 var field = $(this).closest('.wpvr-sticker-field');
194 if ($(this).hasClass('wpvr-sticker-link-remove')) {
195 $(this).closest('.wpvr-sticker-link').remove();
196 saveLinks(field);
197 } else {
198 var input = field.find('.wpvr-sticker-value');
199 var links = readJSON(input.val(), []);
200 links.push({ id: String(Date.now()), icon: 'fab fa-facebook-f', customSvg: '', url: '', openNewTab: 'on' });
201 input.val(JSON.stringify(links));
202 renderLinks(field);
203 }
204 });
205 $(document).on('click', '.wpvr-sticker-avatar-select, .wpvr-sticker-avatar-remove', function () {
206 var input = $(this).closest('.wpvr-sticker-field').find('.wpvr-sticker-value');
207 if ($(this).hasClass('wpvr-sticker-avatar-remove')) { input.val('').trigger('change'); return; }
208 var frame = wp.media({ library: { type: 'image' }, multiple: false });
209 frame.on('select', function () { input.val(frame.state().get('selection').first().toJSON().url).trigger('change'); });
210 frame.open();
211 });
212 $(function () {
213 $('.single-hotspot').each(function () { updateSettings($(this), false); });
214 var root = document.querySelector('.scene-setup');
215 if (!root) return;
216 // Repeaters clear cloned fields; initialize each new hotspot after that reset.
217 new MutationObserver(function (mutations) {
218 mutations.forEach(function (mutation) {
219 mutation.addedNodes.forEach(function (node) {
220 if (node.nodeType !== 1) return;
221 $(node).find('.single-hotspot').addBack('.single-hotspot').each(function () {
222 updateSettings($(this), false);
223 });
224 });
225 });
226 }).observe(root, { childList: true, subtree: true });
227 });
228 })(jQuery);
229