@@ -20,12 +20,19 @@ setTimeout(function () {
2020 } )
2121
2222 function copyToClipboard ( text ) {
23- let sampleTextarea = document . createElement ( "textarea" ) ;
24- document . body . appendChild ( sampleTextarea ) ;
25- sampleTextarea . value = text ;
26- sampleTextarea . select ( ) ;
27- document . execCommand ( "copy" ) ;
28- document . body . removeChild ( sampleTextarea ) ;
23+ if ( navigator . clipboard && navigator . clipboard . writeText ) {
24+ navigator . clipboard . writeText ( text ) . catch ( function ( ) { } ) ;
25+ } else {
26+ // Fallback for older browsers/non-HTTPS contexts
27+ let textarea = document . createElement ( 'textarea' ) ;
28+ textarea . value = text ;
29+ textarea . style . position = 'fixed' ;
30+ textarea . style . opacity = '0' ;
31+ document . body . appendChild ( textarea ) ;
32+ textarea . select ( ) ;
33+ try { document . execCommand ( 'copy' ) ; } catch ( e ) { }
34+ document . body . removeChild ( textarea ) ;
35+ }
2936 }
3037
3138 $ ( '.content-wrapper h2 a, .content-wrapper h3 a, .content-wrapper h4 a' ) . on ( 'click' , function ( ) {
@@ -36,7 +43,16 @@ setTimeout(function () {
3643
3744 $ ( '.content-wrapper .note td.icon' ) . append ( `<svg class="info-icon" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M9.99984 13.3334V10.0001M9.99984 6.66675H10.0082M18.3332 10.0001C18.3332 14.6025 14.6022 18.3334 9.99984 18.3334C5.39746 18.3334 1.6665 14.6025 1.6665 10.0001C1.6665 5.39771 5.39746 1.66675 9.99984 1.66675C14.6022 1.66675 18.3332 5.39771 18.3332 10.0001Z" stroke="#2970FF" stroke-width="1.66667" stroke-linecap="round" stroke-linejoin="round"/></svg>` ) ;
3845
39- $ ( '.content pre' ) . parent ( '.content' ) . prepend ( '<div class="copy-icon"><p></p><div class="copy-icon-container"><svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M5.0835 1.5H11.0002C12.867 1.5 13.8004 1.5 14.5135 1.86331C15.1407 2.18289 15.6506 2.69282 15.9702 3.32003C16.3335 4.03307 16.3335 4.96649 16.3335 6.83333V12.75M4.00016 16.5H10.7502C11.6836 16.5 12.1503 16.5 12.5068 16.3183C12.8204 16.1586 13.0754 15.9036 13.2352 15.59C13.4168 15.2335 13.4168 14.7668 13.4168 13.8333V7.08333C13.4168 6.14991 13.4168 5.6832 13.2352 5.32668C13.0754 5.01308 12.8204 4.75811 12.5068 4.59832C12.1503 4.41667 11.6836 4.41667 10.7502 4.41667H4.00016C3.06674 4.41667 2.60003 4.41667 2.24351 4.59832C1.92991 4.75811 1.67494 5.01308 1.51515 5.32668C1.3335 5.6832 1.3335 6.14991 1.3335 7.08333V13.8333C1.3335 14.7668 1.3335 15.2335 1.51515 15.59C1.67494 15.9036 1.92991 16.1586 2.24351 16.3183C2.60003 16.5 3.06674 16.5 4.00016 16.5Z" stroke="white" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg></div></div>' ) ;
46+ $ ( '.content pre' ) . each ( function ( ) {
47+ let codeEl = $ ( this ) . find ( 'code' ) ;
48+ let lang = codeEl . attr ( 'data-lang' )
49+ || ( codeEl . attr ( 'class' ) || '' ) . match ( / l a n g u a g e - ( \w + ) / ) ?. [ 1 ]
50+ || '' ;
51+ let label = lang ? lang . toUpperCase ( ) : '' ;
52+ $ ( this ) . parent ( '.content' ) . prepend (
53+ '<div class="copy-icon"><p>' + label + '</p><div class="copy-icon-container"><svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M5.0835 1.5H11.0002C12.867 1.5 13.8004 1.5 14.5135 1.86331C15.1407 2.18289 15.6506 2.69282 15.9702 3.32003C16.3335 4.03307 16.3335 4.96649 16.3335 6.83333V12.75M4.00016 16.5H10.7502C11.6836 16.5 12.1503 16.5 12.5068 16.3183C12.8204 16.1586 13.0754 15.9036 13.2352 15.59C13.4168 15.2335 13.4168 14.7668 13.4168 13.8333V7.08333C13.4168 6.14991 13.4168 5.6832 13.2352 5.32668C13.0754 5.01308 12.8204 4.75811 12.5068 4.59832C12.1503 4.41667 11.6836 4.41667 10.7502 4.41667H4.00016C3.06674 4.41667 2.60003 4.41667 2.24351 4.59832C1.92991 4.75811 1.67494 5.01308 1.51515 5.32668C1.3335 5.6832 1.3335 6.14991 1.3335 7.08333V13.8333C1.3335 14.7668 1.3335 15.2335 1.51515 15.59C1.67494 15.9036 1.92991 16.1586 2.24351 16.3183C2.60003 16.5 3.06674 16.5 4.00016 16.5Z" stroke="white" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg></div></div>'
54+ ) ;
55+ } ) ;
4056
4157 $ ( '.copy-icon svg' ) . on ( 'click' , function ( ) {
4258 let that = this ;
@@ -152,4 +168,147 @@ if (nextNav?.link) {
152168 }
153169} else {
154170 $ ( '#next-nav-link' ) . css ( 'display' , 'none' ) ;
155- }
171+ }
172+
173+ // Hide prev/next navigation on landing page
174+ if ( document . querySelector ( '.landing-page' ) ) {
175+ $ ( '.bottom-nav-links' ) . hide ( ) ;
176+ }
177+
178+ // ========================================
179+ // Insider Preview access gate
180+ // ========================================
181+
182+ ( function insiderPreviewGate ( ) {
183+ const INSIDER_PAGES = [
184+ 'aviate-approvals' ,
185+ 'aviate-contracts' ,
186+ 'aviate-error-handling' ,
187+ 'aviate-intents' ,
188+ 'aviate-product-catalog' ,
189+ 'aviate-quotes-orders' ,
190+ 'aviate-rbac' ,
191+ 'aviate-revenue-recognition' ,
192+ 'aviate-usage-rating'
193+ ] ;
194+
195+ const ACCESS_KEY = 'insider-access' ;
196+ const ACCESS_CODE = 'aviate2026' ;
197+
198+ function isInsiderPage ( ) {
199+ const path = window . location . pathname . toLowerCase ( ) ;
200+ return INSIDER_PAGES . some ( p => path . includes ( p ) ) ;
201+ }
202+
203+ function isAccessGranted ( ) {
204+ return localStorage . getItem ( ACCESS_KEY ) === 'granted' ;
205+ }
206+
207+ function grantAccess ( ) {
208+ localStorage . setItem ( ACCESS_KEY , 'granted' ) ;
209+ }
210+
211+ function markLinksLocked ( ) {
212+ // Add a small lock icon after each insider link label
213+ $ ( '.insider-link' ) . each ( function ( ) {
214+ $ ( this ) . addClass ( 'insider-locked' ) ;
215+ } ) ;
216+ }
217+
218+ function markLinksUnlocked ( ) {
219+ $ ( '.insider-link' ) . removeClass ( 'insider-locked' ) ;
220+ }
221+
222+ function showGateModal ( onSuccess ) {
223+ const overlay = $ ( `
224+ <div class="insider-gate-overlay">
225+ <div class="insider-gate-modal">
226+ <div class="insider-gate-icon">
227+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
228+ <rect x="3" y="11" width="18" height="11" rx="2" ry="2"/>
229+ <path d="M7 11V7a5 5 0 0 1 10 0v4"/>
230+ </svg>
231+ </div>
232+ <div class="insider-gate-title">Insider Preview</div>
233+ <div class="insider-gate-subtitle">This content is available exclusively to select partners and customers. Enter your access code if you have been granted access.</div>
234+ <div class="insider-gate-input-group">
235+ <input type="password" class="insider-gate-input" placeholder="Enter access code" autocomplete="off" autofocus>
236+ <button class="insider-gate-btn">Unlock</button>
237+ </div>
238+ <div class="insider-gate-error"></div>
239+ <div class="insider-gate-back"><a href="/latest/what_is_aviate.html">← Back to Aviate docs</a></div>
240+ </div>
241+ </div>
242+ ` ) ;
243+
244+ $ ( 'body' ) . append ( overlay ) ;
245+
246+ const input = overlay . find ( '.insider-gate-input' ) ;
247+ const errorEl = overlay . find ( '.insider-gate-error' ) ;
248+
249+ function attemptUnlock ( ) {
250+ const code = input . val ( ) . trim ( ) ;
251+ if ( code === ACCESS_CODE ) {
252+ grantAccess ( ) ;
253+ overlay . fadeOut ( 200 , function ( ) {
254+ overlay . remove ( ) ;
255+ markLinksUnlocked ( ) ;
256+ if ( onSuccess ) onSuccess ( ) ;
257+ } ) ;
258+ } else {
259+ errorEl . text ( 'Invalid access code. Please try again.' ) ;
260+ input . addClass ( 'error' ) ;
261+ setTimeout ( ( ) => input . removeClass ( 'error' ) , 500 ) ;
262+ }
263+ }
264+
265+ overlay . find ( '.insider-gate-btn' ) . on ( 'click' , attemptUnlock ) ;
266+ input . on ( 'keydown' , function ( e ) {
267+ if ( e . key === 'Enter' ) attemptUnlock ( ) ;
268+ } ) ;
269+
270+ // Close on overlay background click
271+ overlay . on ( 'click' , function ( e ) {
272+ if ( $ ( e . target ) . hasClass ( 'insider-gate-overlay' ) ) {
273+ overlay . fadeOut ( 200 , function ( ) { overlay . remove ( ) ; } ) ;
274+ // If we're on an insider page, go back
275+ if ( isInsiderPage ( ) ) {
276+ window . location . href = '/latest/what_is_aviate.html' ;
277+ }
278+ }
279+ } ) ;
280+
281+ setTimeout ( ( ) => input . focus ( ) , 350 ) ;
282+ }
283+
284+ // --- Sidebar: links are always visible ---
285+
286+ if ( isAccessGranted ( ) ) {
287+ // Unlocked — links work normally
288+ markLinksUnlocked ( ) ;
289+ } else {
290+ // Locked — show links but intercept clicks
291+ markLinksLocked ( ) ;
292+
293+ $ ( '.insider-link' ) . on ( 'click' , function ( e ) {
294+ if ( ! isAccessGranted ( ) ) {
295+ e . preventDefault ( ) ;
296+ const targetHref = $ ( this ) . attr ( 'href' ) ;
297+ showGateModal ( function ( ) {
298+ // On successful unlock, navigate to the clicked page
299+ window . location . href = targetHref ;
300+ } ) ;
301+ }
302+ } ) ;
303+
304+ // If user landed directly on an insider page, show the gate over the content
305+ if ( isInsiderPage ( ) ) {
306+ $ ( '.content-wrapper #content' ) . css ( 'visibility' , 'hidden' ) ;
307+ $ ( '.bottom-nav-links' ) . css ( 'visibility' , 'hidden' ) ;
308+ showGateModal ( function ( ) {
309+ $ ( '.content-wrapper #content' ) . css ( 'visibility' , 'visible' ) ;
310+ $ ( '.bottom-nav-links' ) . css ( 'visibility' , 'visible' ) ;
311+ } ) ;
312+ }
313+ }
314+ } ) ( ) ;
0 commit comments