11< html >
22< head >
33 < script src ="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js "> </ script >
4- < script src =" https://js. puter.com/v2/ "> </ script >
4+ < script id =" puter-script "> </ script >
55 < script src ="./kv.test.js "> </ script >
66 < script src ="./fs.test.js "> </ script >
77 < script src ="./ai.test.js "> </ script >
3737 font-size : 16px ;
3838 cursor : pointer;
3939 }
40+ # settings-btn {
41+ margin-left : 10px ;
42+ margin-top : 20px ;
43+ margin-bottom : 20px ;
44+ background-color : # 666 ;
45+ border : none;
46+ color : white;
47+ padding : 10px 20px ;
48+ text-align : center;
49+ text-decoration : none;
50+ display : inline-block;
51+ font-size : 16px ;
52+ cursor : pointer;
53+ }
54+ # settings-btn : hover {
55+ background-color : # 555 ;
56+ }
4057 # unselect-all {
4158 margin-left : 20px ;
4259 cursor : pointer;
261278 color : # 333 ;
262279 text-decoration : none;
263280 }
281+
282+ /* Modal styles */
283+ .modal {
284+ display : none;
285+ position : fixed;
286+ z-index : 2000 ;
287+ left : 0 ;
288+ top : 0 ;
289+ width : 100% ;
290+ height : 100% ;
291+ background-color : rgba (0 , 0 , 0 , 0.5 );
292+ }
293+
294+ .modal-content {
295+ background-color : # fefefe ;
296+ margin : 10% auto;
297+ padding : 20px ;
298+ border : 1px solid # 888 ;
299+ border-radius : 8px ;
300+ width : 500px ;
301+ max-width : 90% ;
302+ position : relative;
303+ }
304+
305+ .close {
306+ color : # aaa ;
307+ float : right;
308+ font-size : 28px ;
309+ font-weight : bold;
310+ cursor : pointer;
311+ line-height : 1 ;
312+ }
313+
314+ .close : hover ,
315+ .close : focus {
316+ color : black;
317+ text-decoration : none;
318+ }
319+
320+ .modal h2 {
321+ margin-top : 0 ;
322+ margin-bottom : 20px ;
323+ color : # 333 ;
324+ }
325+
326+ .setting-group {
327+ margin-bottom : 15px ;
328+ }
329+
330+ .setting-group label {
331+ display : block;
332+ margin-bottom : 5px ;
333+ font-weight : bold;
334+ color : # 555 ;
335+ }
336+
337+ .setting-group input {
338+ width : 100% ;
339+ padding : 8px ;
340+ border : 1px solid # ddd ;
341+ border-radius : 4px ;
342+ font-size : 14px ;
343+ box-sizing : border-box;
344+ }
345+
346+ .modal-buttons {
347+ margin-top : 20px ;
348+ text-align : right;
349+ }
350+
351+ .modal-buttons button {
352+ margin-left : 10px ;
353+ padding : 8px 16px ;
354+ border : none;
355+ border-radius : 4px ;
356+ cursor : pointer;
357+ font-size : 14px ;
358+ }
359+
360+ .btn-cancel {
361+ background-color : # ccc ;
362+ color : # 333 ;
363+ }
364+
365+ .btn-cancel : hover {
366+ background-color : # bbb ;
367+ }
368+
369+ .btn-save {
370+ background-color : # 4c84af ;
371+ color : white;
372+ }
373+
374+ .btn-save : hover {
375+ background-color : # 3a6a8a ;
376+ }
264377 </ style >
265378 < script >
266- document . addEventListener ( "DOMContentLoaded" , ( ) => {
267-
379+ // Settings management
380+ const DEFAULT_SETTINGS = {
381+ puterJsUrl : 'https://js.puter.com/v2/' ,
382+ apiOrigin : 'https://api.puter.com'
383+ } ;
384+
385+ let currentSettings = { ...DEFAULT_SETTINGS } ;
386+
387+ // Load settings from localStorage or use defaults
388+ function loadSettings ( ) {
389+ const saved = localStorage . getItem ( 'puter-test-settings' ) ;
390+ if ( saved ) {
391+ try {
392+ currentSettings = { ...DEFAULT_SETTINGS , ...JSON . parse ( saved ) } ;
393+ } catch ( e ) {
394+ console . warn ( 'Failed to parse saved settings, using defaults' ) ;
395+ currentSettings = { ...DEFAULT_SETTINGS } ;
396+ }
397+ }
398+ }
399+
400+ // Save settings to localStorage
401+ function saveSettings ( ) {
402+ localStorage . setItem ( 'puter-test-settings' , JSON . stringify ( currentSettings ) ) ;
403+ }
404+
405+ // Load Puter.js script dynamically
406+ function loadPuterScript ( ) {
407+ return new Promise ( ( resolve , reject ) => {
408+ const script = document . getElementById ( 'puter-script' ) ;
409+
410+ // Remove existing script if any
411+ if ( script . src ) {
412+ script . remove ( ) ;
413+ const newScript = document . createElement ( 'script' ) ;
414+ newScript . id = 'puter-script' ;
415+ document . head . insertBefore ( newScript , script . nextSibling ) ;
416+ }
417+
418+ const puterScript = document . getElementById ( 'puter-script' ) ;
419+ puterScript . onload = resolve ;
420+ puterScript . onerror = reject ;
421+ puterScript . src = currentSettings . puterJsUrl ;
422+ } ) ;
423+ }
424+
425+ // Initialize Puter with settings
426+ async function initializePuter ( ) {
427+ try {
428+ await loadPuterScript ( ) ;
429+
430+ // Wait a bit for the script to initialize
431+ await new Promise ( resolve => setTimeout ( resolve , 100 ) ) ;
432+
433+ // Set API origin if puter object exists
434+ if ( typeof puter !== 'undefined' && puter . setAPIOrigin ) {
435+ puter . setAPIOrigin ( currentSettings . apiOrigin ) ;
436+ }
437+ } catch ( error ) {
438+ console . error ( 'Failed to load Puter.js:' , error ) ;
439+ alert ( 'Failed to load Puter.js. Please check the URL in settings.' ) ;
440+ }
441+ }
442+
443+ // Initialize on page load
444+ document . addEventListener ( "DOMContentLoaded" , async ( ) => {
445+ loadSettings ( ) ;
446+ await initializePuter ( ) ;
447+
268448 // Progress tracking variables
269449 let testProgress = {
270450 total : 0 ,
776956 // Initialize the counter display
777957 updateMasterCheckboxState ( ) ;
778958
959+ // Settings modal functionality
960+ $ ( '#settings-btn' ) . click ( ( ) => {
961+ // Populate modal with current settings
962+ $ ( '#puter-js-url' ) . val ( currentSettings . puterJsUrl ) ;
963+ $ ( '#api-origin' ) . val ( currentSettings . apiOrigin ) ;
964+ $ ( '#settings-modal' ) . show ( ) ;
965+ } ) ;
966+
967+ // Close modal
968+ $ ( '.close, .btn-cancel' ) . click ( ( ) => {
969+ $ ( '#settings-modal' ) . hide ( ) ;
970+ } ) ;
971+
972+ // Save settings
973+ $ ( '.btn-save' ) . click ( async ( ) => {
974+ const newSettings = {
975+ puterJsUrl : $ ( '#puter-js-url' ) . val ( ) . trim ( ) ,
976+ apiOrigin : $ ( '#api-origin' ) . val ( ) . trim ( )
977+ } ;
978+
979+ // Validate URLs
980+ if ( ! newSettings . puterJsUrl || ! newSettings . apiOrigin ) {
981+ alert ( 'Please provide both Puter.js URL and API Origin' ) ;
982+ return ;
983+ }
984+
985+ // Update current settings
986+ currentSettings = { ...newSettings } ;
987+ saveSettings ( ) ;
988+
989+ // Reinitialize Puter with new settings
990+ await initializePuter ( ) ;
991+
992+ $ ( '#settings-modal' ) . hide ( ) ;
993+ } ) ;
994+
995+ // Close modal when clicking outside
996+ $ ( window ) . click ( ( event ) => {
997+ if ( event . target === $ ( '#settings-modal' ) [ 0 ] ) {
998+ $ ( '#settings-modal' ) . hide ( ) ;
999+ }
1000+ } ) ;
7791001 } ) ;
7801002
7811003 </ script >
7891011 < span id ="test-counter "> </ span >
7901012 < div style ="flex: 1; text-align: right; ">
7911013 < span id ="reset-results " style ="margin-right: 20px; cursor: pointer; color: #666; text-decoration: underline; font-size: 14px; "> Reset results</ span >
792- < button id ="run-tests " style ="margin-right: 30px; "> Run Tests</ button >
1014+ < button id ="run-tests " style ="margin-right: 10px; "> Run Tests</ button >
1015+ < button id ="settings-btn "> Settings</ button >
7931016 </ div >
7941017 </ nav >
7951018
8221045 </ div >
8231046 </ div >
8241047
1048+ <!-- Settings Modal -->
1049+ < div id ="settings-modal " class ="modal ">
1050+ < div class ="modal-content ">
1051+ < span class ="close "> ×</ span >
1052+ < h2 > Settings</ h2 >
1053+
1054+ < div class ="setting-group ">
1055+ < label for ="puter-js-url "> Puter.js URL:</ label >
1056+ < input type ="text " id ="puter-js-url " placeholder ="https://js.puter.com/v2/ ">
1057+ </ div >
1058+
1059+ < div class ="setting-group ">
1060+ < label for ="api-origin "> API Origin:</ label >
1061+ < input type ="text " id ="api-origin " placeholder ="https://api.puter.com ">
1062+ </ div >
1063+
1064+ < div class ="modal-buttons ">
1065+ < button class ="btn-cancel "> Cancel</ button >
1066+ < button class ="btn-save "> Save</ button >
1067+ </ div >
1068+ </ div >
1069+ </ div >
1070+
8251071 < div id ="tests "> </ div >
8261072</ body >
8271073</ html >
0 commit comments