diff --git a/application/dashboard.class.inc.php b/application/dashboard.class.inc.php index 29fef433a..0dd949b5d 100644 --- a/application/dashboard.class.inc.php +++ b/application/dashboard.class.inc.php @@ -1,7 +1,26 @@ add_linked_script('../js/dashlet.js'); + $oPage->add_linked_script('../js/property_field.js'); } } @@ -149,16 +169,29 @@ abstract class Dashboard $oPage->add('
'); foreach($this->aDashlets as $oDashlet) { - $oDashlet->RenderProperties($oPage); + $sId = $oDashlet->GetID(); + $sClass = get_class($oDashlet); + + $oPage->add(''); } $oPage->add('
'); $oPage->add(''); } + + abstract protected function SetFormParams($oForm); } class RuntimeDashboard extends Dashboard { + protected function SetFormParams($oForm) + { + $oForm->SetSubmitParams(utils::GetAbsoluteUrlAppRoot().'pages/ajax.render.php', array('operation' => 'update_dashlet_property')); + } public function Save() { diff --git a/application/dashlet.class.inc.php b/application/dashlet.class.inc.php index 1c2d6b6aa..c4c465d33 100644 --- a/application/dashlet.class.inc.php +++ b/application/dashlet.class.inc.php @@ -1,11 +1,37 @@ sId = $sId; + $this->bRedrawNeeded = true; // By default: redraw each time a property changes + $this->bFormRedrawNeeded = false; // By default: no need to redraw the form (independent fields) } public function FromDOMNode($oDOMNode) @@ -53,30 +79,27 @@ EOF } abstract public function Render($oPage, $bEditMode = false, $aExtraParams = array()); - - public function RenderProperties($oPage) - { - $sId = $this->GetID(); - $sClass = get_class($this); - $oPage->add(''); - } - + + abstract public function GetPropertiesFields(DesignerForm $oForm); public function ToXml(DOMNode $oContainerNode) { } - - public function GetForm() + + public function Update($aValues, $aUpdatedFields) { } - public function OnFieldUpdate($aParams, $sUpdatedFieldCode) + public function IsRedrawNeeded() { - + return $this->bRedrawNeeded; + } + + public function IsFormRedrawNeeded() + { + return $this->bFormRedrawNeeded; } static public function GetInfo() @@ -87,33 +110,71 @@ EOF 'description' => '', ); } + + public function GetForm($oPage, $bReturnHTML = false) + { + $oForm = new DesignerForm(); + $oForm->SetPrefix("dashlet_". $this->GetID()); + $oForm->SetParamsContainer('params'); + + $this->GetPropertiesFields($oForm); + + $oDashletClassField = new DesignerHiddenField('dashlet_class', '', get_class($this)); + $oForm->AddField($oDashletClassField); + + $oDashletIdField = new DesignerHiddenField('dashlet_id', '', $this->GetID()); + $oForm->AddField($oDashletIdField); + + return $oForm; + } } class DashletHelloWorld extends Dashlet { + protected $sText; + public function __construct($sId) { parent::__construct($sId); + $this->sText = 'Hello World'; } public function FromDOMNode($oDOMNode) { - + //$this->sText = 'Hello World!'; } public function FromXml($sXml) { - + //$this->sText = 'Hello World!'; } public function FromParams($aParams) { - + $this->sText = $aParams['text']; + } + + public function Update($aValues, $aUpdatedFields) + { + foreach($aUpdatedFields as $sProp) + { + switch($sProp) + { + case 'text': + $this->sText = $aValues['text']; + break; + } + } } public function Render($oPage, $bEditMode = false, $aExtraParams = array()) { - $oPage->add('
Hello World!
'); + $oPage->add('
'.$this->sText.'
'); + } + public function GetPropertiesFields(DesignerForm $oForm) + { + $oField = new DesignerTextField('text', 'Text', $this->sText); + $oForm->AddField($oField); } public function ToXml(DOMNode $oContainerNode) @@ -121,21 +182,7 @@ class DashletHelloWorld extends Dashlet $oNewNodeNode = $oContainerNode->ownerDocument->createElement('hello_world', 'test'); $oContainerNode->appendChild($oNewNodeNode); } - - public function GetForm() - { - - } - - public function OnFieldUpdate($aParams, $sUpdatedFieldCode) - { - return array( - 'status_ok' => true, - 'redraw' => false, - 'fields' => array(), - ); - } - + static public function GetInfo() { return array( @@ -174,26 +221,16 @@ class DashletFakeBarChart extends Dashlet $oPage->add('
Fake Bar Chart
'); } + public function GetPropertiesFields(DesignerForm $oForm, $oDashlet = null) + { + } + public function ToXml(DOMNode $oContainerNode) { $oNewNodeNode = $oContainerNode->ownerDocument->createElement('fake_bar_chart', 'test'); $oContainerNode->appendChild($oNewNodeNode); } - - public function GetForm() - { - - } - - public function OnFieldUpdate($aParams, $sUpdatedFieldCode) - { - return array( - 'status_ok' => true, - 'redraw' => false, - 'fields' => array(), - ); - } - + static public function GetInfo() { return array( @@ -232,26 +269,16 @@ class DashletFakePieChart extends Dashlet $oPage->add('
Fake Pie Chart
'); } + public function GetPropertiesFields(DesignerForm $oForm, $oDashlet = null) + { + } + public function ToXml(DOMNode $oContainerNode) { $oNewNodeNode = $oContainerNode->ownerDocument->createElement('fake_pie_chart', 'test'); $oContainerNode->appendChild($oNewNodeNode); } - public function GetForm() - { - - } - - public function OnFieldUpdate($aParams, $sUpdatedFieldCode) - { - return array( - 'status_ok' => true, - 'redraw' => false, - 'fields' => array(), - ); - } - static public function GetInfo() { return array( diff --git a/application/forms.class.inc.php b/application/forms.class.inc.php new file mode 100644 index 000000000..f927e40dc --- /dev/null +++ b/application/forms.class.inc.php @@ -0,0 +1,984 @@ +aFieldSets = array(); + $this->sCurrentFieldSet = ''; + $this->sScript = ''; + $this->sReadyScript = ''; + $this->sFormPrefix = ''; + $this->sParamsContainer = ''; + $this->sFormId = 'form_'.rand(); + $this->oParentForm = null; + $this->bReadOnly = false; + $this->StartFieldSet($this->sCurrentFieldSet); + } + + public function AddField(DesignerFormField $oField) + { + if (!is_array($this->aFieldSets[$this->sCurrentFieldSet])) + { + $this->aFieldSets[$this->sCurrentFieldSet] = array(); + } + $this->aFieldSets[$this->sCurrentFieldSet][] = $oField; + $oField->SetForm($this); + } + + public function StartFieldSet($sLabel) + { + $this->sCurrentFieldSet = $sLabel; + if (!array_key_exists($this->sCurrentFieldSet, $this->aFieldSets)) + { + $this->aFieldSets[$this->sCurrentFieldSet] = array(); + } + } + + public function Render($oP, $bReturnHTML = false) + { + $sReturn = ''; + if ($this->oParentForm == null) + { + $sFormId = $this->sFormId; + $sReturn = '
'; + } + else + { + $sFormId = $this->oParentForm->sFormId; + } + $sHiddenFields = ''; + foreach($this->aFieldSets as $sLabel => $aFields) + { + $aDetails = array(); + if ($sLabel != '') + { + $sReturn .= '
'; + $sReturn .= ''.$sLabel.''; + } + foreach($aFields as $oField) + { + $aRow = $oField->Render($oP, $sFormId); + if ($oField->IsVisible()) + { + $aDetails[] = array('label' => $aRow['label'], 'value' => $aRow['value']); + } + else + { + $sHiddenFields .= $aRow['value']; + } + } + $sReturn .= $oP->GetDetails($aDetails); + if ($sLabel != '') + { + $sReturn .= '
'; + } + } + $sReturn .= $sHiddenFields; + + if ($this->oParentForm == null) + { + $sReturn .= '
'; + } + if($this->sScript != '') + { + $oP->add_script($this->sScript); + } + if($this->sReadyScript != '') + { + $oP->add_ready_script($this->sReadyScript); + } + if ($bReturnHTML) + { + return $sReturn; + } + else + { + $oP->add($sReturn); + } + } + + public function SetSubmitParams($sSubmitToUrl, $aSubmitParams) + { + $this->sSubmitTo = $sSubmitToUrl; + $this->aSubmitParams = $aSubmitParams; + } + + public function CopySubmitParams($oParentForm) + { + $this->sSubmitTo = $oParentForm->sSubmitTo; + $this->aSubmitParams = $oParentForm->aSubmitParams; + } + + + public function RenderAsPropertySheet($oP, $bReturnHTML = false) + { + $sReturn = ''; + $sActionUrl = addslashes($this->sSubmitTo); + $sJSSubmitParams = json_encode($this->aSubmitParams); + if ($this->oParentForm == null) + { + $sFormId = $this->sFormId; + $sReturn = '
'; + $sReturn .= ''; + $sReturn .= ''; + } + else + { + $sFormId = $this->oParentForm->sFormId; + } + $sHiddenFields = ''; + foreach($this->aFieldSets as $sLabel => $aFields) + { + $aDetails = array(); + if ($sLabel != '') + { + $sReturn .= ''; + } + + + $sValidationFields = ''; + foreach($aFields as $oField) + { + $aRow = $oField->Render($oP, $sFormId, 'property'); + if ($oField->IsVisible()) + { + $sFieldId = $this->GetFieldId($oField->GetCode()); + $sReturn .= ''; + $sReturn .= '
PropertyValue 
'.$sLabel.'
'.$aRow['label'].''.$aRow['value']; + if (!($oField instanceof DesignerFormSelectorField)) + { + $sReturn .= $sValidationFields; + } + $this->AddReadyScript( +<<oParentForm == null) + { + $sFormId = $this->sFormId; + $sReturn .= '
'; + $sReturn .= $sHiddenFields; + $sReturn .= '
'; + $sReturn .= '
'; // for the return of the submit operation + } + else + { + $sReturn .= $sHiddenFields; + } + $this->AddReadyScript( +<<sScript != '') + { + $oP->add_script($this->sScript); + } + if($this->sReadyScript != '') + { + $oP->add_ready_script($this->sReadyScript); + } + if ($bReturnHTML) + { + return $sReturn; + } + else + { + $oP->add($sReturn); + } + } + public function RenderAsDialog($oPage, $sDialogId, $sDialogTitle, $iDialogWidth, $sOkButtonLabel) + { + $sDialogTitle = addslashes($sDialogTitle); + $sOkButtonLabel = addslashes($sOkButtonLabel); + $sCancelButtonLabel = 'Cancel'; //TODO: localize + $oPage->add("
"); + $this->Render($oPage); + $oPage->add('
'); + + $oPage->add_ready_script( +<<aFieldSets as $sLabel => $aFields) + { + foreach($aFields as $oField) + { + $oField->ReadParam($aValues); + } + } + return $aValues; + } + + public function SetPrefix($sPrefix) + { + $this->sFormPrefix = $sPrefix; + } + + public function GetPrefix() + { + return $this->sFormPrefix; + } + + public function SetReadOnly($bReadOnly = true) + { + $this->bReadOnly = $bReadOnly; + } + + public function IsReadOnly() + { + if ($this->oParentForm == null) + { + return $this->bReadOnly; + } + else + { + return $this->oParentForm->IsReadOnly(); + } + } + + public function SetParamsContainer($sParamsContainer) + { + $this->sParamsContainer = $sParamsContainer; + } + + public function GetParamsContainer() + { + if ($this->oParentForm == null) + { + return $this->sParamsContainer; + } + else + { + return $this->oParentForm->GetParamsContainer(); + } + } + + public function SetParentForm($oParentForm) + { + $this->oParentForm = $oParentForm; + } + + public function AddScript($sScript) + { + $this->sScript .= $sScript; + } + + public function AddReadyScript($sScript) + { + $this->sReadyScript .= $sScript; + } + + public function GetFieldId($sCode) + { + return $this->sFormPrefix.'attr_'.$sCode; + } + + public function GetFieldName($sCode) + { + return 'attr_'.$sCode; + } + + public function GetParamName($sCode) + { + return 'attr_'.$sCode; + } + + public function GetValidationArea($sCode) + { + return "sFormPrefix}attr_$sCode\">"; + } + public function GetAsyncActionClass() + { + return $this->sAsyncActionClass; + } +} + +class DesignerTabularForm extends DesignerForm +{ + protected $aTable; + + public function __construct() + { + parent::__construct(); + $this->aTable = array(); + } + public function AddRow($aRow) + { + $this->aTable[] = $aRow; + } + + public function Render($oP, $bReturnHTML = false) + { + $sReturn = ''; + if ($this->oParentForm == null) + { + $sFormId = $this->sFormId; + $sReturn = '
'; + } + else + { + $sFormId = $this->oParentForm->sFormId; + } + $sHiddenFields = ''; + $sReturn .= ''; + foreach($this->aTable as $aRow) + { + $sReturn .= ''; + foreach($aRow as $field) + { + if (!is_object($field)) + { + // Shortcut: pass a string for a cell containing just a label + $sReturn .= ''; + } + else + { + $field->SetForm($this); + $aFieldData = $field->Render($oP, $sFormId); + if ($field->IsVisible()) + { + // put the label and value separated by a non-breaking space if needed + $aData = array(); + foreach(array('label', 'value') as $sCode ) + { + if ($aFieldData[$sCode] != '') + { + $aData[] = $aFieldData[$sCode]; + } + } + $sReturn .= ''; + } + else + { + $sHiddenFields .= $aRow['value']; + } + } + } + $sReturn .= ''; + } + $sReturn .= '
'.$field.''.implode(' ', $aData).'
'; + + $sReturn .= $sHiddenFields; + + if($this->sScript != '') + { + $oP->add_script($this->sScript); + } + if($this->sReadyScript != '') + { + $oP->add_ready_script($this->sReadyScript); + } + if ($bReturnHTML) + { + return $sReturn; + } + else + { + $oP->add($sReturn); + } + } + + public function ReadParams(&$aValues = array()) + { + foreach($this->aTable as $aRow) + { + foreach($aRow as $field) + { + if (is_object($field)) + { + $field->SetForm($this); + $field->ReadParam($aValues); + } + } + } + return $aValues; + } +} + +class DesignerFormField +{ + protected $sLabel; + protected $sCode; + protected $defaultValue; + protected $oForm; + protected $bMandatory; + protected $bReadOnly; + + public function __construct($sCode, $sLabel, $defaultValue) + { + $this->sLabel = $sLabel; + $this->sCode = $sCode; + $this->defaultValue = $defaultValue; + $this->bMandatory = false; + $this->bReadOnly = false; + } + + public function GetCode() + { + return $this->sCode; + } + + public function SetForm($oForm) + { + $this->oForm = $oForm; + } + + + public function SetMandatory($bMandatory = true) + { + $this->bMandatory = $bMandatory; + } + + public function SetReadOnly($bReadOnly = true) + { + $this->bReadOnly = $bReadOnly; + } + + public function IsReadOnly() + { + return ($this->oForm->IsReadOnly() || $this->bReadOnly); + } + + public function Render(WebPage $oP, $sFormId, $sRenderMode='dialog') + { + $sId = $this->oForm->GetFieldId($this->sCode); + $sName = $this->oForm->GetFieldName($this->sCode); + return array('label' => $this->sLabel, 'value' => "defaultValue, ENT_QUOTES, 'UTF-8')."\">"); + } + + public function ReadParam(&$aValues) + { + if ($this->IsReadOnly()) + { + $aValues[$this->sCode] = $this->defaultValue; + } + else + { + if ($this->oForm->GetParamsContainer() != '') + { + $aParams = utils::ReadParam($this->oForm->GetParamsContainer(), array(), false, 'raw_data'); + if (array_key_exists($this->oForm->GetParamName($this->sCode), $aParams)) + { + $aValues[$this->sCode] = $aParams[$this->oForm->GetParamName($this->sCode)]; + } + else + { + $aValues[$this->sCode] = $this->defaultValue; + } + } + else + { + $aValues[$this->sCode] = utils::ReadParam($this->oForm->GetParamName($this->sCode), $this->defaultValue, false, 'raw_data'); + } + } + } + + public function IsVisible() + { + return true; + } +} + +class DesignerLabelField extends DesignerFormField +{ + protected $sDescription; + + public function __construct($sLabel, $sDescription) + { + parent::__construct('', $sLabel, ''); + $this->sDescription = $sDescription; + } + + public function Render(WebPage $oP, $sFormId, $sRenderMode='dialog') + { + $sId = $this->oForm->GetFieldId($this->sCode); + $sName = $this->oForm->GetFieldName($this->sCode); + return array('label' => $this->sLabel, 'value' => $sDescription); + } + + public function ReadParam(&$aValues) + { + } + + public function IsVisible() + { + return true; + } +} + +class DesignerTextField extends DesignerFormField +{ + protected $sValidationPattern; + public function __construct($sCode, $sLabel = '', $defaultValue = '') + { + parent::__construct($sCode, $sLabel, $defaultValue); + $this->sValidationPattern = ''; + } + + public function SetValidationPattern($sValidationPattern) + { + $this->sValidationPattern = $sValidationPattern; + } + + public function Render(WebPage $oP, $sFormId, $sRenderMode='dialog') + { + $sId = $this->oForm->GetFieldId($this->sCode); + $sName = $this->oForm->GetFieldName($this->sCode); + $sValidation = $this->oForm->GetValidationArea($this->sCode); + $sPattern = addslashes($this->sValidationPattern); + $sMandatory = $this->bMandatory ? 'true' : 'false'; + $sReadOnly = $this->IsReadOnly() ? 'readonly' : ''; + $oP->add_ready_script( +<< $this->sLabel, 'value' => "defaultValue, ENT_QUOTES, 'UTF-8')."\">".$sValidation); + } + + public function ReadParam(&$aValues) + { + parent::ReadParam($aValues); + + if (($this->sValidationPattern != '') &&(!preg_match('/'.$this->sValidationPattern.'/', $aValues[$this->sCode])) ) + { + $aValues[$this->sCode] = $this->defaultValue; + } + } +} + +class DesignerComboField extends DesignerFormField +{ + protected $aAllowedValues; + protected $bMultipleSelection; + protected $bOtherChoices; + + public function __construct($sCode, $sLabel = '', $defaultValue = '') + { + parent::__construct($sCode, $sLabel, $defaultValue); + $this->aAllowedValues = array(); + $this->bMultipleSelection = false; + $this->bOtherChoices = false; + } + + public function SetAllowedValues($aAllowedValues) + { + $this->aAllowedValues = $aAllowedValues; + } + + public function MultipleSelection($bMultipleSelection = true) + { + $this->bMultipleSelection = $bMultipleSelection; + } + + public function OtherChoices($bOtherChoices = true) + { + $this->bOtherChoices = $bOtherChoices; + } + + + public function Render(WebPage $oP, $sFormId, $sRenderMode='dialog') + { + + $sId = $this->oForm->GetFieldId($this->sCode); + $sName = $this->oForm->GetFieldName($this->sCode); + $sChecked = $this->defaultValue ? 'checked' : ''; + $sMandatory = $this->bMandatory ? 'true' : 'false'; + $sReadOnly = $this->IsReadOnly() ? 'disabled="disabled"' : ''; + $sValidation = $this->oForm->GetValidationArea($this->sCode); + if ($this->bMultipleSelection) + { + $sHtml = ""; + $sHtml .= ""; + } + foreach($this->aAllowedValues as $sKey => $sDisplayValue) + { + if ($this->bMultipleSelection) + { + $sSelected = in_array($sKey, $this->defaultValue) ? 'selected' : ''; + } + else + { + $sSelected = ($sKey == $this->defaultValue) ? 'selected' : ''; + } + // Quick and dirty: display the menu parents as a tree + $sHtmlValue = str_replace(' ', ' ', htmlentities($sDisplayValue, ENT_QUOTES, 'UTF-8')); + $sHtml .= ""; + } + $sHtml .= ""; + if ($this->bOtherChoices) + { + $sHtml .= '
 '; + } + $oP->add_ready_script( +<< $this->sLabel, 'value' => $sHtml.$sValidation); + } +} + +class DesignerBooleanField extends DesignerFormField +{ + public function __construct($sCode, $sLabel = '', $defaultValue = '') + { + parent::__construct($sCode, $sLabel, $defaultValue); + } + + public function Render(WebPage $oP, $sFormId, $sRenderMode='dialog') + { + $sId = $this->oForm->GetFieldId($this->sCode); + $sName = $this->oForm->GetFieldName($this->sCode); + $sValidation = $this->oForm->GetValidationArea($this->sCode); + $sChecked = $this->defaultValue ? 'checked' : ''; + $sReadOnly = $this->IsReadOnly() ? 'disabled' : ''; // readonly does not work as expected on checkboxes: + // readonly prevents the user from changing the input's value not its state (checked/unchecked) + return array('label' => $this->sLabel, 'value' => "".$sValidation); + } + + public function ReadParam(&$aValues) + { + if ($this->IsReadOnly()) + { + $aValues[$this->sCode] = $this->defaultValue; + } + else + { + $sParamsContainer = $this->oForm->GetParamsContainer(); + if ($sParamsContainer != '') + { + $aParams = utils::ReadParam($sParamsContainer, array(), false, 'raw_data'); + if (array_key_exists($this->oForm->GetParamName($this->sCode), $aParams)) + { + $sValue = $aParams[$this->oForm->GetParamName($this->sCode)]; + } + else + { + $sValue = 'false'; + } + } + else + { + $sValue = utils::ReadParam($this->oForm->GetParamName($this->sCode), 'false', false, 'raw_data'); + } + } + $aValues[$this->sCode] = ($sValue == 'true'); + } +} + + +class DesignerHiddenField extends DesignerFormField +{ + public function __construct($sCode, $sLabel = '', $defaultValue = '') + { + parent::__construct($sCode, $sLabel, $defaultValue); + } + + public function IsVisible() + { + return false; + } + + public function Render(WebPage $oP, $sFormId, $sRenderMode='dialog') + { + $sId = $this->oForm->GetFieldId($this->sCode); + $sName = $this->oForm->GetFieldName($this->sCode); + $sValidation = $this->oForm->GetValidationArea($this->sCode); + $sChecked = $this->defaultValue ? 'checked' : ''; + return array('label' =>'', 'value' => "defaultValue, ENT_QUOTES, 'UTF-8')."\">"); + } +} + + +class DesignerIconSelectionField extends DesignerFormField +{ + protected $aAllowedValues; + + public function __construct($sCode, $sLabel = '', $defaultValue = '') + { + parent::__construct($sCode, $sLabel, $defaultValue); + } + + public function SetAllowedValues($aAllowedValues) + { + $this->aAllowedValues = $aAllowedValues; + } + + public function Render(WebPage $oP, $sFormId, $sRenderMode='dialog') + { + $sId = $this->oForm->GetFieldId($this->sCode); + $sName = $this->oForm->GetFieldName($this->sCode); + $idx = 0; + foreach($this->aAllowedValues as $index => $aValue) + { + if ($aValue['value'] == $this->defaultValue) + { + $idx = $index; + break; + } + } + $sJSItems = json_encode($this->aAllowedValues); + if (!$this->IsReadOnly()) + { + $oP->add_ready_script( +<<IsReadOnly() ? 'disabled' : ''; + return array('label' =>$this->sLabel, 'value' => "defaultValue}\"/>"); + } +} + +class DesignerSortableField extends DesignerFormField +{ + protected $aAllowedValues; + + public function __construct($sCode, $sLabel = '', $defaultValue = '') + { + parent::__construct($sCode, $sLabel, $defaultValue); + $this->aAllowedValues = array(); + } + + public function SetAllowedValues($aAllowedValues) + { + $this->aAllowedValues = $aAllowedValues; + } + + public function Render(WebPage $oP, $sFormId, $sRenderMode='dialog') + { + $bOpen = false; + $sId = $this->oForm->GetFieldId($this->sCode); + $sName = $this->oForm->GetFieldName($this->sCode); + $sValidation = $this->oForm->GetValidationArea($this->sCode); + $sHtml = ""; + foreach($this->defaultValue as $sValue) + { + $sHtml .= "$sValue"; + } + $sHtml .=""; + $sIconClass = $bOpen ? 'ui-icon-circle-triangle-s' : 'ui-icon-circle-triangle-e'; + $sStyle = $bOpen ? '' : 'style="display:none"'; + $sHtml .= "
"; + $sHtml .="
Fields
"; + foreach($this->aAllowedValues as $sKey => $sDisplayValue) + { + $sHtml .= "$sDisplayValue"; + } + $sHtml .="
Trash
"; + $oP->add_ready_script( +<< $this->sLabel, 'value' => $sHtml.$sValidation); + } +} + +class DesignerFormSelectorField extends DesignerFormField +{ + protected $aSubForms; + protected $defaultRealValue; // What's stored as default value is actually the index + public function __construct($sCode, $sLabel = '', $defaultValue = '') + { + parent::__construct($sCode, $sLabel, 0); + $this->defaultRealValue = $defaultValue; + $this->aSubForms = array(); + } + + public function AddSubForm($oSubForm, $sLabel, $sValue) + { + $idx = count($this->aSubForms); + $this->aSubForms[] = array('form' => $oSubForm, 'label' => $sLabel, 'value' => $sValue); + if ($sValue == $this->defaultRealValue) + { + // Store the index of the selected/default form + $this->defaultValue = count($this->aSubForms) - 1; + } + } + + public function Render(WebPage $oP, $sFormId, $sRenderMode='dialog') + { + $sId = $this->oForm->GetFieldId($this->sCode); + $sName = $this->oForm->GetFieldName($this->sCode); + $sReadOnly = $this->IsReadOnly() ? 'disabled="disabled"' : ''; + + $sHtml = ""; + + if ($sRenderMode == 'property') + { + $sHtml .= ''; + } + + foreach($this->aSubForms as $sKey => $aFormData) + { + $sId = $this->oForm->GetFieldId($this->sCode); + $sStyle = ($sKey == $this->defaultValue) ? '' : 'style="display:none"'; + $oSubForm = $aFormData['form']; + $oSubForm->SetParentForm($this->oForm); + $oSubForm->CopySubmitParams($this->oForm); + $oSubForm->SetPrefix($this->oForm->GetPrefix().$sKey.'_'); + + if ($sRenderMode == 'property') + { + $sHtml .= ""; + $sHtml .= $oSubForm->RenderAsPropertySheet($oP, true); + } + else + { + $sHtml .= "
"; + $sHtml .= $oSubForm->Render($oP, true); + $sHtml .= "
"; + } + } + + $oP->add_ready_script( +<< $this->sLabel, 'value' => $sHtml); + } + + public function ReadParam(&$aValues) + { + parent::ReadParam($aValues); + $sKey = $aValues[$this->sCode]; + $aValues[$this->sCode] = $this->aSubForms[$sKey]['value']; + + $this->aSubForms[$sKey]['form']->SetPrefix($this->oForm->GetPrefix().$sKey.'_'); + $this->aSubForms[$sKey]['form']->SetParentForm($this->oForm); + $this->aSubForms[$sKey]['form']->ReadParams($aValues); + } +} + +class DesignerSubFormField extends DesignerFormField +{ + protected $oSubForm; + public function __construct($sLabel, $oSubForm) + { + parent::__construct('', $sLabel, ''); + $this->oSubForm = $oSubForm; + } + + public function Render(WebPage $oP, $sFormId, $sRenderMode='dialog') + { + $this->oSubForm->SetParentForm($this->oForm); + $oSubForm->CopySubmitParams($this->oForm); + + if ($sRenderMode == 'property') + { + $sHtml = $this->oSubForm->RenderAsPropertySheet($oP, true); + } + else + { + $sHtml = $this->oSubForm->Render($oP, true); + } + return array('label' => $this->sLabel, 'value' => $sHtml); + } + + public function ReadParam(&$aValues) + { + $this->oSubForm->SetParentForm($this->oForm); + $this->oSubForm->ReadParams($aValues); + } +} + +?> \ No newline at end of file