@@ -39,6 +39,8 @@ var shared_custom_settings = {};
3939var ajax_custom_settings = {};
4040let isFormSubmitting = false ;
4141let FW_NewUpdateVersAvailable = ' ' ;
42+ var fwTimeInvalidFromConfig = false ;
43+ var fwTimeInvalidMsg = ' ' ;
4244
4345// Order of NVRAM keys to search for 'Model ID' and 'Product ID' //
4446const modelKeys = [" nvram_odmpid" , " nvram_wps_modelnum" , " nvram_model" , " nvram_build_name" ];
@@ -348,19 +350,67 @@ function ParseTimeHHMM(v){
348350 return { ok: true , h: h, m: m };
349351}
350352
353+ function ValidateHHMMUsingFwScheduleTime (hhmm ){
354+ var v = (hhmm || ' ' ).trim ();
355+ var parts = v .split (' :' );
356+ if (parts .length !== 2 ){
357+ return {
358+ ok: false ,
359+ msg: fwScheduleTime .ErrorMsgHOUR () + ' \n ' + fwScheduleTime .ErrorMsgMINS ()
360+ };
361+ }
362+ var H = parts[0 ], M = parts[1 ];
363+ var hOk = fwScheduleTime .ValidateHOUR (H );
364+ var mOk = fwScheduleTime .ValidateMINS (M );
365+ var msg = ' ' ;
366+ if (! hOk) msg += fwScheduleTime .ErrorMsgHOUR ();
367+ if (! mOk) msg += (msg ? ' \n ' : ' ' ) + fwScheduleTime .ErrorMsgMINS ();
368+ return { ok: (hOk && mOk), msg: msg };
369+ }
370+
371+ function MarkTimePickerInvalid (T , msg ){
372+ if (! T ) return ;
373+ fwTimeInvalidFromConfig = true ;
374+ fwTimeInvalidMsg = msg;
375+
376+ var $t = $ (T );
377+ $t .addClass (' Invalid' );
378+ // Remove ONLY namespaced handlers, then rebind
379+ $t .off (' .fwtime' );
380+ // Show tooltip ONLY on mouseover (no focus)
381+ $t .on (' mouseover.fwtime' , function (){ return overlib (msg,0 ,0 ); });
382+ // Hide tooltip as soon as user stops hovering or edits/leaves the field
383+ $t .on (' mouseleave.fwtime input.fwtime keydown.fwtime keyup.fwtime blur.fwtime' , function (){
384+ try { nd (); } catch (e){}
385+ });
386+ // if something already opened a tooltip, close it now
387+ try { nd (); } catch (e){}
388+ T .setAttribute (' aria-invalid' ,' true' );
389+ T .value = ' ' ;
390+ setTimeout (function (){ T .focus (); }, 0 ); // focus no longer triggers tooltip
391+ }
392+
393+ function ClearTimePickerInvalid (T ){
394+ if (! T ) return ;
395+ fwTimeInvalidFromConfig = false ;
396+ fwTimeInvalidMsg = ' ' ;
397+ var $t = $ (T );
398+ $t .removeClass (' Invalid' );
399+ $t .off (' .fwtime' ); // remove our handlers
400+ try { nd (); } catch (e){} // force-close any lingering overlib
401+ T .removeAttribute (' aria-invalid' );
402+ }
403+
351404function ValidateTimePicker (el ){
352405 if (! el) return false ;
353- var res = ParseTimeHHMM (el .value );
354- if (res .ok ){
355- $ (el). removeClass ( ' Invalid ' );
356- $ (el). off ( ' mouseover ' );
406+ var r = ValidateHHMMUsingFwScheduleTime (el .value );
407+ if (r .ok ){
408+ try { nd (); } catch (e){}
409+ ClearTimePickerInvalid (el);
357410 return true ;
358411 }else {
359- el .focus ();
360- $ (el).addClass (' Invalid' );
361- var msg = ' The schedule time is INVALID.<br>The Hour must be 0–23 and Minutes 0–59.' ;
362- $ (el).on (' mouseover' , function (){ return overlib (msg,0 ,0 ); });
363- $ (el)[0 ].onmouseout = nd;
412+ // keep newline-><br> for overlib formatting
413+ MarkTimePickerInvalid (el, (r .msg || ' ' ).replace (/ \n / g ,' <br>' ));
364414 return false ;
365415 }
366416}
@@ -522,6 +572,9 @@ function FWConvertCronScheduleToWebUISettings(rawCronSchedule){
522572
523573 if (! T ) return ;
524574
575+ // default UI state
576+ ClearTimePickerInvalid (T );
577+
525578 if (rawCronSchedule === ' TBD' || fwRaw .length < 5 ){
526579 ToggleDaysOfWeek (true , ' 1' );
527580 fwSchedD1 = document .getElementById (' fwSchedBoxDAYS1' );
@@ -533,23 +586,27 @@ function FWConvertCronScheduleToWebUISettings(rawCronSchedule){
533586
534587 let rawM = fwRaw[0 ], rawH = fwRaw[1 ], rawDM = fwRaw[2 ], rawMN = fwRaw[3 ], rawDW = fwRaw[4 ];
535588
536- // Set the time picker value (even if later disabled)
537- let h = parseInt (rawH,10 ), m = parseInt (rawM,10 );
538- if (isNaN (h) || h < 0 || h > 23 ) h = 0 ;
539- if (isNaN (m) || m < 0 || m > 59 ) m = 0 ;
540- var hh = (h < 10 ? ' 0' : ' ' ) + h;
541- var mm = (m < 10 ? ' 0' : ' ' ) + m;
542- T .value = hh + ' :' + mm;
589+ // ---- Time handling: use fwScheduleTime messages only ----
590+ let timeCheck = ValidateHHMMUsingFwScheduleTime (String (rawH) + ' :' + String (rawM));
591+ if (! timeCheck .ok ){
592+ MarkTimePickerInvalid (T , (timeCheck .msg || ' ' ).replace (/ \n / g ,' <br>' ));
593+ } else {
594+ let h = parseInt (rawH,10 ), m = parseInt (rawM,10 );
595+ var hh = (h < 10 ? ' 0' : ' ' ) + h;
596+ var mm = (m < 10 ? ' 0' : ' ' ) + m;
597+ T .value = hh + ' :' + mm;
598+ ClearTimePickerInvalid (T );
599+ }
543600
544- // Days logic — toggle the time input disabledness
601+ // Days logic
545602 if (rawDM .match (' [*]/([2-9]|1[0-5])' ) !== null ){
546603 ToggleDaysOfWeek (true , ' X' );
547604 fwSchedX = document .getElementById (' fwSchedBoxDAYSX' );
548605 if (fwSchedX){ fwSchedX .checked = true ; fwSchedX .disabled = false ; }
549606 fwXD = document .getElementById (' fwScheduleXDAYS' );
550607 let temp = rawDM .split (' /' );
551608 if (fwXD && temp .length > 1 ){ fwXD .value = temp[1 ]; }
552- T .disabled = false ; // allow time selection
609+ T .disabled = false ;
553610 return ;
554611 }
555612 else if (rawDW .match (' [*]/[2-3]' ) !== null ){
@@ -570,9 +627,9 @@ function FWConvertCronScheduleToWebUISettings(rawCronSchedule){
570627 return ;
571628 }
572629 else if (rawDM != ' *' || rawMN != ' *' ){
573- // Not handled in UI (DoM/Month intervals) — mirror prior behavior
630+ // Not handled in UI (DoM/Month intervals)
574631 ToggleDaysOfWeek (true , ' 0' ); // disable day checkboxes
575- T .disabled = false ; // still allow time
632+ T .disabled = false ;
576633 return ;
577634 }
578635
@@ -2096,11 +2153,25 @@ function SaveCombinedConfig()
20962153 alert (` ${ validationErrorMsg} \n\n ` + fwPostponedDays .ErrorMsg ());
20972154 return false ;
20982155 }
2156+ // ---- Time validation: also catch invalid time loaded from settings ----
20992157 var timeEl = document .getElementById (' fwScheduleTIME' );
2100- if (timeEl && timeEl .disabled === false && ! ValidateTimePicker (timeEl)){
2101- alert (validationErrorMsg + ' \n\n The schedule time is INVALID.\n The Hour must be between 0 and 23, and Minutes between 0 and 59.' );
2158+
2159+ // If loader marked it invalid
2160+ if (fwTimeInvalidFromConfig){
2161+ alert (validationErrorMsg + ' \n\n ' + fwTimeInvalidMsg .replace (/ <br>/ g , ' \n ' ));
2162+ if (timeEl) timeEl .focus ();
21022163 return false ;
21032164 }
2165+
2166+ // Normal validation of the control’s current value
2167+ if (timeEl && timeEl .disabled === false ){
2168+ var chk = ValidateHHMMUsingFwScheduleTime (timeEl .value );
2169+ if (! chk .ok ){
2170+ alert (validationErrorMsg + ' \n\n ' + chk .msg );
2171+ timeEl .focus ();
2172+ return false ;
2173+ }
2174+ }
21042175 if (document .getElementById (' fwSchedBoxDAYSX' ).checked &&
21052176 ! ValidateFWUpdateXDays (document .form .fwScheduleXDAYS , ' DAYS' ))
21062177 {
0 commit comments