@@ -2905,58 +2905,61 @@ Page.PageUtils = class PageUtils extends Page.Base {
29052905 var is_valid = true ;
29062906
29072907 plugin . params . forEach ( function ( param ) {
2908+ if ( ! is_valid ) return ;
2909+ var elem_sel = '#fe_pp_' + plugin_id + '_' + CSS . escape ( param . id ) ;
2910+
29082911 switch ( param . type ) {
29092912 case 'hidden' :
29102913 params [ param . id ] = param . value ;
29112914 break ;
29122915
29132916 case 'checkbox' :
2914- params [ param . id ] = ! ! $ ( '#fe_pp_' + plugin_id + '_' + CSS . escape ( param . id ) ) . is ( ':checked' ) ;
2917+ params [ param . id ] = ! ! $ ( elem_sel ) . is ( ':checked' ) ;
29152918 break ;
29162919
29172920 case 'toolset' :
2918- var tool_id = params [ param . id ] = $ ( '#fe_pp_' + plugin_id + '_' + CSS . escape ( param . id ) ) . val ( ) ;
2921+ var tool_id = params [ param . id ] = $ ( elem_sel ) . val ( ) ;
29192922
29202923 if ( ! param . data || ! param . data . tools ) return ; // sanity
29212924 var tool = find_object ( param . data . tools , { id : tool_id } ) ;
29222925 if ( ! tool ) return ; // sanity
29232926
2924- var tool_values = self . getParamValues ( tool . fields || [ ] ) ;
2927+ var tool_values = self . getParamValues ( tool . fields || [ ] , ! force ) ;
29252928 if ( ! tool_values ) { is_valid = false ; return ; } // invalid
29262929
29272930 merge_hash_into ( params , tool_values ) ;
29282931 break ;
29292932
29302933 default :
2931- params [ param . id ] = $ ( '#fe_pp_' + plugin_id + '_' + CSS . escape ( param . id ) ) . val ( ) ;
2934+ params [ param . id ] = $ ( elem_sel ) . val ( ) ;
29322935 if ( param . required && ! params [ param . id ] . length && ! force ) {
2933- app . badField ( '#fe_pp_' + plugin_id + '_' + CSS . escape ( param . id ) , "The “" + param . title + "” field is required." ) ;
2936+ app . badField ( elem_sel , "The “" + param . title + "” field is required." ) ;
29342937 is_valid = false ;
29352938 }
2936- else if ( ! force && param . variant && ! param . variant . match ( / ^ ( p a s s w o r d | t e x t | t e l ) $ / ) && ! $ ( '#fe_pp_' + plugin_id + '_' + CSS . escape ( param . id ) ) [ 0 ] . validity . valid ) {
2937- app . badField ( '#fe_pp_' + plugin_id + '_' + CSS . escape ( param . id ) , "The “" + param . title + "” field is invalid." ) ;
2939+ else if ( ! force && param . variant && ! param . variant . match ( / ^ ( p a s s w o r d | t e x t | t e l ) $ / ) && ! $ ( elem_sel ) [ 0 ] . validity . valid ) {
2940+ app . badField ( elem_sel , "The “" + param . title + "” field is invalid." ) ;
29382941 is_valid = false ;
29392942 }
29402943 else if ( param . type == 'json' ) {
29412944 try { params [ param . id ] = JSON . parse ( params [ param . id ] ) ; }
29422945 catch ( err ) {
2943- app . badField ( '#fe_pp_' + plugin_id + '_' + CSS . escape ( param . id ) , "The “" + param . title + "” field is invalid." ) ;
2946+ app . badField ( elem_sel , "The “" + param . title + "” field is invalid." ) ;
29442947 is_valid = false ;
29452948 }
29462949 }
29472950 else if ( param . variant == 'number' ) {
29482951 if ( param . required || params [ param . id ] . length ) {
29492952 params [ param . id ] = parseFloat ( params [ param . id ] ) ;
29502953 if ( isNaN ( params [ param . id ] ) ) {
2951- app . badField ( '#fe_pp_' + plugin_id + '_' + CSS . escape ( param . id ) , "The “" + param . title + "” field is invalid." ) ;
2954+ app . badField ( elem_sel , "The “" + param . title + "” field is invalid." ) ;
29522955 is_valid = false ;
29532956 } // NaN
29542957 } // required or length
29552958 else params [ param . id ] = null ;
29562959 } // number
29572960
29582961 if ( param . regex && str_value ( params [ param . id ] ) . length && ! str_value ( params [ param . id ] ) . match ( new RegExp ( param . regex ) ) ) {
2959- app . badField ( '#fe_pp_' + plugin_id + '_' + CSS . escape ( param . id ) , "The “" + param . title + "” field is invalid." ) ;
2962+ app . badField ( elem_sel , "The “" + param . title + "” field is invalid." ) ;
29602963 is_valid = false ;
29612964 }
29622965 break ;
@@ -4699,7 +4702,7 @@ Page.PageUtils = class PageUtils extends Page.Base {
46994702 var show_lock = ! ! ( this . pluginType === 'event' ) ;
47004703
47014704 // prepare control type menu
4702- var ctypes = ( this . controlTypes || [ 'checkbox' , 'code' , 'json' , 'hidden' , 'select' , 'bucket' , 'system' , 'text' , 'textarea' , 'group' ] ) . map ( function ( key ) {
4705+ var ctypes = Object . keys ( config . ui . control_type_labels ) . map ( function ( key ) {
47034706 return {
47044707 id : key ,
47054708 title : config . ui . control_type_labels [ key ] ,
@@ -5066,7 +5069,7 @@ Page.PageUtils = class PageUtils extends Page.Base {
50665069 catch ( err ) { return app . doError ( "Failed to parse toolset JSON: " + err ) ; }
50675070
50685071 // validate tools (control types, etc.)
5069- if ( ! self . validateToolsetData ( param ) ) return false ;
5072+ if ( ! self . validateToolsetData ( param , self . params ) ) return false ;
50705073
50715074 delete param . required ;
50725075 delete param . value ;
@@ -5271,7 +5274,7 @@ Page.PageUtils = class PageUtils extends Page.Base {
52715274 this . triggerEditChange ( ) ;
52725275 }
52735276
5274- validateToolsetData ( param ) {
5277+ validateToolsetData ( param , params ) {
52755278 // ensure toolset data is properly formatted
52765279 var data = param . data ;
52775280 var err_prefix = "Toolset Data Error: " ;
@@ -5324,9 +5327,11 @@ Page.PageUtils = class PageUtils extends Page.Base {
53245327 if ( field . id . match ( app . MATCH_BAD_KEY ) ) { err_msg = `Tool '${ tool . id } ' field '${ field . id } ' ID is invalid (reserved word).` ; is_valid = false ; return ; }
53255328 if ( field . id == param . id ) { err_msg = `Tool '${ tool . id } ' field '${ field . id } ' ID is invalid (cannot reuse toolset param ID).` ; is_valid = false ; return ; }
53265329
5327- if ( fids [ field . id ] ) { err_msg = `Tool '${ tool . id } ' field ID ${ field . id } is duplicated (each must be unique per tool).` ; is_valid = false ; return ; }
5330+ if ( fids [ field . id ] ) { err_msg = `Tool '${ tool . id } ' field ID ' ${ field . id } ' is duplicated (each must be unique per tool).` ; is_valid = false ; return ; }
53285331 fids [ field . id ] = 1 ;
53295332
5333+ if ( find_object ( params , { id : field . id } ) ) { err_msg = `Tool '${ tool . id } ' field ID '${ field . id } ' is already in use as a parameter.` ; is_valid = false ; return ; }
5334+
53305335 // title
53315336 if ( ! field . title || ! field . title . length ) { err_msg = `Tool '${ tool . id } ' field '${ field . id } ' is missing a title.` ; is_valid = false ; return ; }
53325337 if ( typeof ( field . title ) != 'string' ) { err_msg = `Tool '${ tool . id } ' field '${ field . id } ' title is not a string.` ; is_valid = false ; return ; }
@@ -5427,6 +5432,9 @@ Page.PageUtils = class PageUtils extends Page.Base {
54275432 return ;
54285433 }
54295434
5435+ // toolset breaks out of a previous group
5436+ if ( ( param . type == 'toolset' ) && in_group ) { html += `</fieldset>` ; in_group = false ; }
5437+
54305438 if ( param . type != 'checkbox' ) {
54315439 if ( elem_dis ) html += '<div class="info_label" style="color:var(--red)"><i class="mdi mdi-lock"> </i>' + param . title + ' (Admin Locked)</div>' ;
54325440 else html += '<div class="info_label">' + param . title + '</div>' ;
@@ -5540,10 +5548,52 @@ Page.PageUtils = class PageUtils extends Page.Base {
55405548 }
55415549 break ;
55425550
5551+ case 'toolset' :
5552+ var data = param . data || { tools : [ ] } ;
5553+ if ( ! data . tools ) data . tools = [ ] ;
5554+ var tools = data . tools ;
5555+ if ( ! tools . length ) {
5556+ tools . push ( { id : '' , title : 'No Tools' , description : 'No tools defined in toolset.' , fields : [ ] } ) ;
5557+ elem_dis = true ;
5558+ }
5559+
5560+ var default_tool_id = data . default || tools [ 0 ] . id ;
5561+ elem_value = ( param . id in params ) ? params [ param . id ] : default_tool_id ;
5562+
5563+ // make sure tool exists (plugin may have changed), default to first tool
5564+ var tool = find_object ( tools , { id : elem_value } ) ;
5565+ if ( ! tool ) {
5566+ tool = tools [ 0 ] ;
5567+ elem_value = tool . id ;
5568+ }
5569+
5570+ // store toolset data hidden in the DOM, so changeParamTool can get access to it
5571+ html += self . getFormTextarea ( { id : elem_id + '_xy_tooldata' , value : JSON . stringify ( data ) , rows : 1 , style : 'display:none' } ) ;
5572+
5573+ html += self . getFormMenuSingle ( {
5574+ id : elem_id ,
5575+ value : elem_value ,
5576+ options : tools ,
5577+ disabled : elem_dis ,
5578+ title : param . title ,
5579+ onChange : `$P().changeParamTool('${ param . id } ',${ explore } )`
5580+ } ) ;
5581+
5582+ if ( param . caption ) html += '<div class="info_caption">' + inline_marked ( strip_html ( param . caption ) ) + '</div>' ;
5583+
5584+ html += `<fieldset id="fs_toolset_${ param . id } " class="info_fieldset">` ;
5585+ html += `<legend>${ strip_html ( tool . title ) } </legend>` ;
5586+ if ( tool . description ) html += `<div class="tool_desc">${ inline_marked ( strip_html ( tool . description ) ) } </div>` ;
5587+ if ( tool . fields && tool . fields . length ) html += self . getParamEditor ( tool . fields , params , explore ) ;
5588+ html += `</fieldset>` ;
5589+ break ;
5590+
55435591 } // switch type
55445592
5545- if ( param . caption ) html += '<div class="info_caption">' + inline_marked ( strip_html ( param . caption ) ) + '</div>' ;
5546- else if ( elem_dis ) html += '<div class="info_caption">This field is locked, and only editable by administrators.</div>' ;
5593+ if ( param . type != 'toolset' ) {
5594+ if ( param . caption ) html += '<div class="info_caption">' + inline_marked ( strip_html ( param . caption ) ) + '</div>' ;
5595+ else if ( elem_dis ) html += '<div class="info_caption">This field is locked, and only editable by administrators.</div>' ;
5596+ }
55475597
55485598 html += '</div>' ;
55495599 } ) ; // foreach param
@@ -5553,6 +5603,25 @@ Page.PageUtils = class PageUtils extends Page.Base {
55535603 return html ;
55545604 }
55555605
5606+ changeParamTool ( param_id , explore = false ) {
5607+ // change tool in toolset, redraw fields
5608+ var elem_id = 'fe_uf_' + CSS . escape ( param_id ) ;
5609+ var elem_value = $ ( '#' + elem_id ) . val ( ) ;
5610+
5611+ var data = JSON . parse ( $ ( '#' + elem_id + '_xy_tooldata' ) . val ( ) ) ;
5612+ var tool = find_object ( data . tools , { id : elem_value } ) ;
5613+ if ( ! tool ) return ; // sanity
5614+
5615+ var $fieldset = $ ( `#fs_toolset_${ CSS . escape ( param_id ) } ` ) ;
5616+ var html = '' ;
5617+
5618+ html += `<legend>${ strip_html ( tool . title ) } </legend>` ;
5619+ if ( tool . description ) html += `<div class="tool_desc">${ inline_marked ( strip_html ( tool . description ) ) } </div>` ;
5620+ if ( tool . fields && tool . fields . length ) html += this . getParamEditor ( tool . fields , { } , explore ) ;
5621+
5622+ $fieldset . html ( html ) . buttonize ( ) ;
5623+ }
5624+
55565625 viewParamCode ( param_id ) {
55575626 // show param code (no editing)
55585627 var elem_id = 'fe_uf_' + CSS . escape ( param_id ) ;
@@ -5586,43 +5655,59 @@ Page.PageUtils = class PageUtils extends Page.Base {
55865655
55875656 getParamValues ( fields , validate = true ) {
55885657 // get all values for params hash
5658+ var self = this ;
55895659 var params = { } ;
55905660 var is_valid = true ;
55915661 if ( ! fields || ! fields . length ) return { } ; // none defined
55925662
55935663 fields . forEach ( function ( param ) {
5664+ if ( ! is_valid ) return ;
5665+ var elem_sel = '#fe_uf_' + CSS . escape ( param . id ) ;
5666+
55945667 if ( param . type == 'hidden' ) params [ param . id ] = param . value ;
5595- else if ( param . type == 'checkbox' ) params [ param . id ] = ! ! $ ( '#fe_uf_' + CSS . escape ( param . id ) ) . is ( ':checked' ) ;
5668+ else if ( param . type == 'checkbox' ) params [ param . id ] = ! ! $ ( elem_sel ) . is ( ':checked' ) ;
5669+ else if ( param . type == 'toolset' ) {
5670+ var tool_id = params [ param . id ] = $ ( elem_sel ) . val ( ) ;
5671+
5672+ if ( ! param . data || ! param . data . tools ) return ; // sanity
5673+ var tool = find_object ( param . data . tools , { id : tool_id } ) ;
5674+ if ( ! tool ) return ; // sanity
5675+
5676+ var tool_values = self . getParamValues ( tool . fields || [ ] , validate ) ;
5677+ if ( ! tool_values ) { is_valid = false ; return ; } // invalid
5678+
5679+ merge_hash_into ( params , tool_values ) ;
5680+ }
55965681 else {
5597- params [ param . id ] = $ ( '#fe_uf_' + CSS . escape ( param . id ) ) . val ( ) ;
5682+ params [ param . id ] = $ ( elem_sel ) . val ( ) ;
55985683 if ( param . required && ! params [ param . id ] . length && validate ) {
5599- app . badField ( '#fe_uf_' + CSS . escape ( param . id ) , "The “" + param . title + "” field is required." ) ;
5684+ app . badField ( elem_sel , "The “" + param . title + "” field is required." ) ;
56005685 is_valid = false ;
56015686 }
5602- else if ( validate && param . variant && ! param . variant . match ( / ^ ( p a s s w o r d | t e x t | t e l ) $ / ) && ! $ ( '#fe_uf_' + param . id ) [ 0 ] . validity . valid ) {
5603- app . badField ( '#fe_uf_' + CSS . escape ( param . id ) , "The “" + param . title + "” field is invalid." ) ;
5687+ else if ( validate && param . variant && ! param . variant . match ( / ^ ( p a s s w o r d | t e x t | t e l ) $ / ) && ! $ ( elem_sel ) [ 0 ] . validity . valid ) {
5688+ app . badField ( elem_sel , "The “" + param . title + "” field is invalid." ) ;
56045689 is_valid = false ;
56055690 }
56065691 else if ( param . type == 'json' ) {
56075692 try { params [ param . id ] = JSON . parse ( params [ param . id ] ) ; }
56085693 catch ( err ) {
5609- app . badField ( '#fe_uf_' + CSS . escape ( param . id ) , "The “" + param . title + "” field is invalid." ) ;
5694+ app . badField ( elem_sel , "The “" + param . title + "” field is invalid." ) ;
56105695 is_valid = false ;
56115696 }
56125697 }
56135698 else if ( param . variant == 'number' ) {
56145699 if ( param . required || params [ param . id ] . length ) {
56155700 params [ param . id ] = parseFloat ( params [ param . id ] ) ;
56165701 if ( isNaN ( params [ param . id ] ) ) {
5617- app . badField ( '#fe_uf_' + CSS . escape ( param . id ) , "The “" + param . title + "” field is invalid." ) ;
5702+ app . badField ( elem_sel , "The “" + param . title + "” field is invalid." ) ;
56185703 is_valid = false ;
56195704 } // NaN
56205705 } // required or has length
56215706 else params [ param . id ] = null ;
56225707 } // number
56235708
56245709 if ( param . regex && str_value ( params [ param . id ] ) . length && ! str_value ( params [ param . id ] ) . match ( new RegExp ( param . regex ) ) ) {
5625- app . badField ( '#fe_uf_' + CSS . escape ( param . id ) , "The “" + param . title + "” field is invalid." ) ;
5710+ app . badField ( elem_sel , "The “" + param . title + "” field is invalid." ) ;
56265711 is_valid = false ;
56275712 }
56285713 } // textish
0 commit comments