diff --git a/application/capturewebpage.class.inc.php b/application/capturewebpage.class.inc.php new file mode 100644 index 000000000..fff7d1f2c --- /dev/null +++ b/application/capturewebpage.class.inc.php @@ -0,0 +1,84 @@ + + +/** + * Adapter class: when an API requires WebPage and you want to produce something else + * + * @copyright Copyright (C) 2016 Combodo SARL + * @license http://opensource.org/licenses/AGPL-3.0 + */ + +require_once(APPROOT."/application/webpage.class.inc.php"); + +class CaptureWebPage extends WebPage +{ + protected $aReadyScripts; + + function __construct() + { + parent::__construct('capture web page'); + $this->aReadyScripts = array(); + } + + public function GetHtml() + { + $trash = $this->ob_get_clean_safe(); + return $this->s_content; + } + + public function GetJS() + { + $sRet = implode("\n", $this->a_scripts); + if (!empty($this->s_deferred_content)) + { + $sRet .= "\n\$('body').append('".addslashes(str_replace("\n", '', $this->s_deferred_content))."');"; + } + return $sRet; + } + + public function GetReadyJS() + { + return "\$(document).ready(function() {\n".implode("\n", $this->aReadyScripts)."\n});"; + } + + public function GetCSS() + { + return $this->a_styles; + } + + public function GetJSFiles() + { + return $this->a_linked_scripts; + } + + public function GetCSSFiles() + { + return $this->a_linked_stylesheets; + } + + public function output() + { + throw new Exception(__method__.' should not be called'); + } + + public function add_ready_script($sScript) + { + $this->aReadyScripts[] = $sScript; + } +} + diff --git a/sources/renderer/console/consoleformrenderer.class.inc.php b/sources/renderer/console/consoleformrenderer.class.inc.php index 95c6be45d..6090b58fc 100644 --- a/sources/renderer/console/consoleformrenderer.class.inc.php +++ b/sources/renderer/console/consoleformrenderer.class.inc.php @@ -23,6 +23,7 @@ use Combodo\iTop\Renderer\FormRenderer; use \Dict; require_once('fieldrenderer/consolesimplefieldrenderer.class.inc.php'); +require_once('fieldrenderer/consoleselectobjectfieldrenderer.class.inc.php'); require_once('fieldrenderer/consolesubformfieldrenderer.class.inc.php'); class ConsoleFormRenderer extends FormRenderer @@ -35,7 +36,7 @@ class ConsoleFormRenderer extends FormRenderer $this->AddSupportedField('HiddenField', 'ConsoleSimpleFieldRenderer'); $this->AddSupportedField('StringField', 'ConsoleSimpleFieldRenderer'); $this->AddSupportedField('SelectField', 'ConsoleSimpleFieldRenderer'); - $this->AddSupportedField('SelectObjectField', 'ConsoleSimpleFieldRenderer'); + $this->AddSupportedField('SelectObjectField', 'ConsoleSelectObjectFieldRenderer'); $this->AddSupportedField('SubFormField', 'ConsoleSubFormFieldRenderer'); } } \ No newline at end of file diff --git a/sources/renderer/console/fieldrenderer/consoleselectobjectfieldrenderer.class.inc.php b/sources/renderer/console/fieldrenderer/consoleselectobjectfieldrenderer.class.inc.php new file mode 100644 index 000000000..02342c0ca --- /dev/null +++ b/sources/renderer/console/fieldrenderer/consoleselectobjectfieldrenderer.class.inc.php @@ -0,0 +1,213 @@ + + +namespace Combodo\iTop\Renderer\Console\FieldRenderer; + +use Combodo\iTop\Form\Field\StringField; +use Combodo\iTop\Form\Validator\MandatoryValidator; +use Combodo\iTop\Form\Validator\Validator; +use \Dict; +use \DBObjectSet; +use Combodo\iTop\Renderer\FieldRenderer; +use Combodo\iTop\Renderer\RenderingOutput; + +class ConsoleSelectObjectFieldRenderer extends FieldRenderer +{ + public function Render() + { + $oOutput = new RenderingOutput(); + + $oOutput->AddHtml(''); + $oOutput->AddHtml(''); + if ($this->oField->GetLabel() != '') + { + $oOutput->AddHtml(''); + } + $oOutput->AddHtml(''); + + $oOutput->AddHtml(''); + $oOutput->AddHtml('
'); + $sEditType = 'none'; + if ($this->oField->GetReadOnly()) + { + $oSearch = $this->oField->GetSearch()->DeepClone(); + $oSearch->AddCondition('id', $this->oField->GetCurrentValue()); + $oSet = new DBObjectSet($oSearch); + $oObject = $oSet->Fetch(); + if ($oObject) + { + $sCurrentLabel = $oObject->Get('friendlyname'); + } + else + { + $sCurrentLabel = ''; + } + $oOutput->AddHtml(''); + $oOutput->AddHtml(''.htmlentities($sCurrentLabel, ENT_QUOTES, 'UTF-8').''); + } + else + { + $oSearch = $this->oField->GetSearch()->DeepClone(); + $oSearch->SetModifierProperty('UserRightsGetSelectFilter', 'bSearchMode', true); + + $oSet = new \DBObjectSet($oSearch); + $oSet->OptimizeColumnLoad(array($oSearch->GetClassAlias() => array('friendlyname'))); + + $sTargetClass = $oSearch->GetClass(); + $oAllowedValues = new DBObjectSet($oSearch); + + $iMaxComboLength = $this->oField->GetMaximumComboLength(); + $iCount = $oAllowedValues->Count(); + if ($iCount > $iMaxComboLength) + { + // Auto-complete + $sEditType = 'autocomplete'; + $aExtKeyParams = array(); + $aExtKeyParams['iFieldSize'] = 10; + $aExtKeyParams['iMinChars'] = $this->oField->GetMinAutoCompleteChars(); + $sFieldName = $this->oField->GetGlobalId(); + $sFieldId = $sFieldName; + $sFormPrefix = ''; + $oWidget = new \UIExtKeyWidget($sTargetClass, $sFieldId, '', true); + $aArgs = array(); + $sDisplayStyle = 'select'; + $sTitle = $this->oField->GetLabel(); + require_once(APPROOT.'application/capturewebpage.class.inc.php'); + $oPage = new \CaptureWebPage(); + $sHTMLValue = $oWidget->Display($oPage, $iMaxComboLength, false /* $bAllowTargetCreation */, $sTitle, $oSet, $this->oField->GetCurrentValue(), $sFieldId, $this->oField->GetMandatory(), $sFieldName, $sFormPrefix, $aArgs, null, $sDisplayStyle); + $oOutput->AddHtml($sHTMLValue); + $oOutput->AddHtml($oPage->GetHtml()); + $oOutput->AddJs($oPage->GetJS()); + $oOutput->AddJs($oPage->GetReadyJS()); + $oOutput->AddCss($oPage->GetCSS()); + foreach ($oPage->GetJSFiles() as $sFile) + { + $oOutput->AddJsFile($sFile); + } + foreach ($oPage->GetCSSFiles() as $sFile) + { + $oOutput->AddCssFile($sFile); + } + } + else + { + // Drop-down select + $sEditType = 'select'; + $oOutput->AddHtml(''); + } + $oOutput->AddJs( + <<oField->GetGlobalId()}").off("change").on("change", function(){ + var me = this; + + $(this).closest(".field_set").trigger("field_change", { + id: $(me).attr("id"), + name: $(me).closest(".form_field").attr("data-field-id"), + value: $(me).val() + }) + .closest('.form_handler').trigger('value_change'); + }); +EOF + ); + } + $oOutput->AddHtml(''); + $oOutput->AddHtml('
'); + + // JS Form field widget construct + $aValidators = array(); + foreach ($this->oField->GetValidators() as $oValidator) + { + if ($oValidator::GetName() == 'notemptyextkey') + { + // The autocomplete widget returns an empty string if the value is undefined (and the select has been aligned with this behavior) + $oValidator = new MandatoryValidator(); + } + $aValidators[$oValidator::GetName()] = array( + 'reg_exp' => $oValidator->GetRegExp(), + 'message' => Dict::S($oValidator->GetErrorMessage()) + ); + } + $sValidators = json_encode($aValidators); + $sFormFieldOptions = +<<'); + oValidationElement.tooltip({ + items: 'span', + tooltipClass: 'form_field_error', + content: function() { + return $(this).find('img').attr('data-tooltip'); // As opposed to the default 'content' handler, do not escape the contents of 'title' + } + }); + } + } +} +EOF + ; + + $oOutput->AddJs( + <<AddJs( + <<oField->GetGlobalId()}').val();}); +EOF + ); + break; + case 'select': + $oOutput->AddJs( + <<AddHtml(''); $oOutput->AddHtml(''); break; - - case 'Combodo\\iTop\\Form\\Field\\SelectObjectField': - $oOutput->AddHtml(''); - if ($this->oField->GetReadOnly()) - { - $oSearch = $this->oField->GetSearch()->DeepClone(); - $oSearch->AddCondition('id', $this->oField->GetCurrentValue()); - $oSet = new DBObjectSet($oSearch); - $oObject = $oSet->Fetch(); - if ($oObject) - { - $sCurrentLabel = $oObject->Get('friendlyname'); - } - else - { - $sCurrentLabel = ''; - } - $oOutput->AddHtml(''); - $oOutput->AddHtml(''.htmlentities($sCurrentLabel, ENT_QUOTES, 'UTF-8').''); - } - else - { - $oSearch = $this->oField->GetSearch()->DeepClone(); - $oSet = new \DBObjectSet($oSearch); - $oSet->OptimizeColumnLoad(array($oSearch->GetClassAlias() => array('friendlyname'))); - $oOutput->AddHtml(''); - } - $oOutput->AddHtml(''); - $oOutput->AddHtml(''); - break; } $oOutput->AddHtml(''); $oOutput->AddHtml(''); @@ -146,7 +105,6 @@ EOF ); break; case 'Combodo\\iTop\\Form\\Field\\SelectField': - case 'Combodo\\iTop\\Form\\Field\\SelectObjectField': $oOutput->AddJs( <<oField->GetGlobalId()}").off("change").on("change", function(){ @@ -210,21 +168,12 @@ EOF switch ($sFieldClass) { case 'Combodo\\iTop\\Form\\Field\\SelectField': - case 'Combodo\\iTop\\Form\\Field\\SelectObjectField': $oOutput->AddJs( <<