PluginProbe
WPVR – 360 Panorama viewer and Virtual Tour Builder for WordPress / 9.1.3
WPVR – 360 Panorama viewer and Virtual Tour Builder for WordPress v9.1.3
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 / app / admin / tour-listing.js

tour-listing.js in WPVR – 360 Panorama viewer and Virtual Tour Builder for WordPress 9.1.3, at app/admin/tour-listing.js

342 lines 10.8 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 document.addEventListener( 'DOMContentLoaded', function () {
5 if ( ! document.body.classList.contains( 'wpvr-tour-list' ) ) {
6 return;
7 }
8
9 var wrap = document.querySelector( '#wpbody-content > .wrap' );
10 if ( ! wrap ) {
11 return;
12 }
13
14 prepareHeader( wrap );
15 prepareToolbar( wrap );
16 prepareSearch( wrap );
17 prepareCheckboxes( wrap );
18 prepareEmptyState( wrap );
19 prepareShortcodeCopy();
20 revealCompletedLayout();
21 } );
22
23 function prepareShortcodeCopy() {
24 document.addEventListener( 'click', function ( event ) {
25 var copyButton = event.target.closest( '.wpvr-copy-shortcode-listing' );
26
27 if ( ! copyButton ) {
28 return;
29 }
30
31 event.preventDefault();
32 event.stopPropagation();
33 event.stopImmediatePropagation();
34
35 copyShortcode( copyButton.getAttribute( 'data-shortcode' ) || '' )
36 .then( function () {
37 showListingToast( 'success', 'Shortcode copied.' );
38 } )
39 .catch( function () {
40 showListingToast( 'error', 'Unable to copy shortcode.' );
41 } );
42 }, true );
43 }
44
45 function copyShortcode( shortcode ) {
46 if ( navigator.clipboard && window.isSecureContext ) {
47 return navigator.clipboard.writeText( shortcode );
48 }
49
50 return new Promise( function ( resolve, reject ) {
51 var textArea = document.createElement( 'textarea' );
52
53 textArea.value = shortcode;
54 textArea.setAttribute( 'readonly', '' );
55 textArea.style.position = 'fixed';
56 textArea.style.top = '-9999px';
57 textArea.style.opacity = '0';
58 document.body.appendChild( textArea );
59 textArea.focus();
60 textArea.select();
61 textArea.setSelectionRange( 0, textArea.value.length );
62
63 try {
64 if ( document.execCommand( 'copy' ) ) {
65 resolve();
66 } else {
67 reject( new Error( 'Copy command failed.' ) );
68 }
69 } catch ( error ) {
70 reject( error );
71 } finally {
72 textArea.remove();
73 }
74 } );
75 }
76
77 function showListingToast( type, message ) {
78 var currentToast = document.querySelector( '.wpvr-listing-toast' );
79 if ( currentToast ) {
80 currentToast.remove();
81 }
82
83 var toast = document.createElement( 'div' );
84 toast.className = 'wpvr-toast wpvr-toast--' + type + ' wpvr-listing-toast';
85 toast.setAttribute( 'role', 'status' );
86 toast.setAttribute( 'aria-live', 'polite' );
87 toast.textContent = message;
88 document.body.appendChild( toast );
89
90 window.setTimeout( function () {
91 if ( toast.parentNode ) {
92 toast.remove();
93 }
94 }, 3200 );
95 }
96
97 function revealCompletedLayout() {
98 window.requestAnimationFrame( function () {
99 window.requestAnimationFrame( function () {
100 document.body.classList.add( 'wpvr-tour-list-ready' );
101 } );
102 } );
103 }
104
105 function prepareHeader( wrap ) {
106 var heading = wrap.querySelector( 'h1.wp-heading-inline' );
107 if ( ! heading ) {
108 return;
109 }
110
111 var header = document.createElement( 'div' );
112 header.className = 'wpvr-listing-header';
113 heading.parentNode.insertBefore( header, heading );
114 header.appendChild( heading );
115
116 Array.prototype.slice.call( wrap.children ).forEach( function ( child ) {
117 if ( child.classList && child.classList.contains( 'page-title-action' ) ) {
118 header.appendChild( child );
119 }
120 } );
121
122 var notices = document.querySelectorAll(
123 '#wpvr-promotional-banner, #wpvr-ui-mode-notice, #wpvr-license-fallback-notice, #wpvr-onboarding-notice, .wpvr-migration-notice'
124 );
125 if ( notices.length ) {
126 var noticeArea = document.createElement( 'div' );
127 noticeArea.className = 'wpvr-listing-notices';
128 wrap.insertBefore( noticeArea, header );
129 Array.prototype.forEach.call( notices, function ( notice ) {
130 noticeArea.appendChild( notice );
131 } );
132 }
133 }
134
135 function prepareToolbar( wrap ) {
136 var topNav = wrap.querySelector( '#posts-filter .tablenav.top' );
137 var search = wrap.querySelector( '#posts-filter .search-box' );
138 if ( topNav && search ) {
139 topNav.appendChild( search );
140 }
141 }
142
143 function prepareSearch( wrap ) {
144 var input = wrap.querySelector( '#post-search-input' );
145 var submit = wrap.querySelector( '#search-submit' );
146 var form = wrap.querySelector( '#posts-filter' );
147
148 if ( input ) {
149 input.placeholder = 'Search Tour';
150 input.setAttribute( 'aria-label', 'Search Tour' );
151 }
152
153 if ( submit ) {
154 submit.setAttribute( 'aria-label', 'Search Tour' );
155 }
156
157 if ( input && form ) {
158 bindLiveSearch( wrap, form, input );
159 }
160 }
161
162 function bindLiveSearch( wrap, form, input ) {
163 var debounceTimer = null;
164 var activeRequest = null;
165 var liveStatus = document.createElement( 'span' );
166
167 liveStatus.className = 'screen-reader-text';
168 liveStatus.setAttribute( 'aria-live', 'polite' );
169 form.appendChild( liveStatus );
170
171 input.addEventListener( 'input', function ( event ) {
172 if ( event.isComposing ) {
173 return;
174 }
175
176 window.clearTimeout( debounceTimer );
177 debounceTimer = window.setTimeout( function () {
178 requestSearchResults( wrap, form, input, liveStatus );
179 }, 350 );
180 } );
181
182 function requestSearchResults( listingWrap, listingForm, searchInput, status ) {
183 var requestUrl = buildSearchUrl( listingForm, searchInput.value );
184
185 if ( activeRequest ) {
186 activeRequest.abort();
187 }
188
189 activeRequest = new AbortController();
190 listingForm.classList.add( 'wpvr-listing-searching' );
191 listingForm.setAttribute( 'aria-busy', 'true' );
192
193 window.fetch( requestUrl.toString(), {
194 credentials: 'same-origin',
195 headers: {
196 'X-Requested-With': 'XMLHttpRequest',
197 },
198 signal: activeRequest.signal,
199 } )
200 .then( function ( response ) {
201 if ( ! response.ok ) {
202 throw new Error( 'Search request failed.' );
203 }
204
205 return response.text();
206 } )
207 .then( function ( html ) {
208 var parsedDocument = new window.DOMParser().parseFromString( html, 'text/html' );
209 var nextTable = parsedDocument.querySelector( 'table.wp-list-table' );
210 var nextBottomNav = parsedDocument.querySelector( '#posts-filter .tablenav.bottom' );
211 var currentTable = listingForm.querySelector( 'table.wp-list-table' );
212 var currentBottomNav = listingForm.querySelector( '.tablenav.bottom' );
213 var hasResults = ! nextTable || ! nextTable.querySelector( 'tbody .no-items' );
214
215 if ( ! nextTable || ! currentTable ) {
216 throw new Error( 'Search results were not found.' );
217 }
218
219 currentTable.replaceWith( nextTable );
220 if ( hasResults && nextBottomNav ) {
221 if ( currentBottomNav ) {
222 currentBottomNav.replaceWith( nextBottomNav );
223 } else {
224 nextTable.insertAdjacentElement( 'afterend', nextBottomNav );
225 }
226 } else if ( currentBottomNav ) {
227 currentBottomNav.remove();
228 }
229
230 window.history.replaceState( {}, '', requestUrl.toString() );
231 prepareCheckboxes( listingWrap );
232 prepareEmptyState( listingWrap );
233 status.textContent = 'Search results updated.';
234 } )
235 .catch( function ( error ) {
236 if ( error.name !== 'AbortError' ) {
237 status.textContent = 'Unable to update search results.';
238 }
239 } )
240 .finally( function () {
241 listingForm.classList.remove( 'wpvr-listing-searching' );
242 listingForm.removeAttribute( 'aria-busy' );
243 } );
244 }
245 }
246
247 function buildSearchUrl( form, searchTerm ) {
248 var url = new URL( window.location.href );
249 var formData = new window.FormData( form );
250 var ignoredFields = [ 'action', 'action2', 'post[]', '_wpnonce', '_wp_http_referer' ];
251
252 formData.forEach( function ( value, key ) {
253 if ( ignoredFields.indexOf( key ) === -1 && typeof value === 'string' ) {
254 url.searchParams.set( key, value );
255 }
256 } );
257
258 url.searchParams.set( 's', searchTerm );
259 url.searchParams.delete( 'paged' );
260
261 return url;
262 }
263
264 function prepareCheckboxes( wrap ) {
265 var table = wrap.querySelector( 'table.wp-list-table' );
266 if ( ! table ) {
267 return;
268 }
269
270 var selectAll = table.querySelectorAll(
271 'thead .check-column input[type="checkbox"], tfoot .check-column input[type="checkbox"]'
272 );
273
274 function rowCheckboxes() {
275 return table.querySelectorAll( 'tbody .check-column input[type="checkbox"][name="post[]"]' );
276 }
277
278 function updateSelectAll() {
279 var rows = rowCheckboxes();
280 var checked = table.querySelectorAll(
281 'tbody .check-column input[type="checkbox"][name="post[]"]:checked'
282 ).length;
283
284 Array.prototype.forEach.call( selectAll, function ( checkbox ) {
285 checkbox.checked = rows.length > 0 && checked === rows.length;
286 checkbox.indeterminate = checked > 0 && checked < rows.length;
287 } );
288 }
289
290 Array.prototype.forEach.call( selectAll, function ( checkbox ) {
291 checkbox.addEventListener( 'change', function () {
292 var shouldCheck = checkbox.checked;
293 Array.prototype.forEach.call( rowCheckboxes(), function ( rowCheckbox ) {
294 rowCheckbox.checked = shouldCheck;
295 } );
296 updateSelectAll();
297 } );
298 } );
299
300 table.addEventListener( 'change', function ( event ) {
301 if (
302 event.target.matches(
303 'tbody .check-column input[type="checkbox"][name="post[]"]'
304 )
305 ) {
306 updateSelectAll();
307 }
308 } );
309
310 updateSelectAll();
311 }
312
313 function prepareEmptyState( wrap ) {
314 var emptyCell = wrap.querySelector( 'table.wp-list-table tbody .no-items td' );
315 if ( ! emptyCell ) {
316 return;
317 }
318
319 var emptyState = document.createElement( 'div' );
320 emptyState.className = 'wpvr-listing-empty';
321 emptyState.innerHTML =
322 '<svg class="wpvr-listing-empty__icon" aria-hidden="true" width="65" height="52" viewBox="0 0 65 52" fill="none" xmlns="http://www.w3.org/2000/svg">' +
323 '<path d="M0.5 3.18066C0.500022 1.22699 2.42411 -0.0335511 3.95801 0.733398L3.99023 0.749023L4.02344 0.759766C9.84718 2.70101 19.5527 5.28906 32.167 5.28906C44.7758 5.28902 53.8382 3.02515 60.3164 0.757812L60.3467 0.74707L60.375 0.733398C61.9089 -0.0335512 63.833 1.22699 63.833 3.18066V48.2139C63.833 50.1557 62.202 51.4916 60.2959 50.9512C53.831 48.6897 44.7724 46.1055 32.167 46.1055C19.5455 46.1055 10.8021 48.6965 4.02344 50.9561C2.43759 51.4847 0.5 50.146 0.5 48.2139V3.18066Z" fill="white" stroke="black"/>' +
324 '<path d="M30.8906 18.7724C30.8906 18.1456 30.7687 17.5251 30.5318 16.9461C30.2949 16.367 29.9477 15.8409 29.5099 15.3978C29.0722 14.9546 28.5525 14.6031 27.9806 14.3633C27.4087 14.1234 26.7957 14 26.1767 14C25.5576 14 24.9447 14.1234 24.3727 14.3633C23.8008 14.6031 23.2811 14.9546 22.8434 15.3978C22.4057 15.8409 22.0585 16.367 21.8216 16.9461C21.5847 17.5251 21.4627 18.1456 21.4627 18.7724C21.4627 20.0381 21.9594 21.2519 22.8434 22.1469C23.7274 23.0419 24.9265 23.5447 26.1767 23.5447C27.4269 23.5447 28.6259 23.0419 29.5099 22.1469C30.394 21.2519 30.8906 20.0381 30.8906 18.7724ZM35.6093 21.3304L30.3143 29.6677L27.4436 25.0158L17.9273 37.8618H46L35.6093 21.3304Z" fill="black"/>' +
325 '</svg>' +
326 '<p>No tour created.</p>' +
327 '<button type="button" class="wpvr-listing-empty__button">Add Your First Tour</button>';
328
329 emptyCell.textContent = '';
330 emptyCell.appendChild( emptyState );
331
332 emptyState.querySelector( 'button' ).addEventListener( 'click', function () {
333 var addButton = wrap.querySelector(
334 '.wpvr-listing-header .page-title-action:not(.wpvr-import-button)'
335 );
336 if ( addButton ) {
337 addButton.click();
338 }
339 } );
340 }
341 } )();
342