TMultiField com muitos campos Olá Pessoal! Achei o TMultiField formidável, porém precisei utilizar vários campos e o resultado não ficou nada agradável. Por isso surgiu a necessidade de ter controle dos elementos dessa classe e para não alterar a classe do framework eu criei uma outra classe adaptando o que já estava ótimo na original. Além disso eu precisava controlar o posicionamento do texto desses campos...
ES
TMultiField com muitos campos  
Fechado
Olá Pessoal!
Achei o TMultiField formidável, porém precisei utilizar vários campos e o resultado não ficou nada agradável.

Por isso surgiu a necessidade de ter controle dos elementos dessa classe e para não alterar a classe do framework eu criei uma outra classe adaptando o que já estava ótimo na original.

Além disso eu precisava controlar o posicionamento do texto desses campos.

Estou colocando, em anexo, uma imagem que mostra o uso da classe original e o uso da classe adaptada e em seguida postarei os códigos utilizados.

Caso tenham idéias de melhorias favor postar aqui para que todos tenham acesso.

abs.
Eliezer

Curso Dominando o Adianti Framework

O material mais completo de treinamento do Framework.
Curso em vídeo aulas + Livro completo + Códigos fontes do projeto ERPHouse.
Conteúdo Atualizado!


Dominando o Adianti Framework Quero me inscrever agora!

Comentários (7)


ES

TMultiFieldPanel.class
 
  1. <?php
  2. /**
  3. * MultiField Widget: Takes a group of input fields and gives them the possibility to register many occurrences
  4. *
  5. * @version 1.0
  6. * @package widget_web
  7. * @subpackage form
  8. * @author Pablo Dall'Oglio
  9. * @author Eliezer de Morais Silva - Alteração
  10. * @copyright Copyright (c) 2006-2012 Adianti Solutions Ltd. (http://www.adianti.com.br)
  11. * @license http://www.adianti.com.br/framework-license
  12. * === Alteração ===
  13. * Possibilidade de controlar os campos de entrada do form
  14. */
  15. class TMultiFieldPanel extends TField
  16. {
  17. private $fields;
  18. private $objects;
  19. private $height;
  20. private $width;
  21. private $className;
  22. private $formName;
  23. private $widthPanel;//Tamanho do painel
  24. private $heightPanel;
  25. private $posPanelx;//posição da Grade multifield
  26. private $posPanely;
  27. private $posPanelBtx;//Posição dos botões
  28. private $posPanelBty;
  29. /**
  30. * Class Constructor
  31. * @param $name Name of the widget
  32. */
  33. public function __construct($name)
  34. {
  35. // define some default properties
  36. self::setEditable(TRUE);
  37. self::setName($name);
  38. $this->fields = array();
  39. $this->height = 100;
  40. }
  41. /**
  42. * Define the name of the form to wich the multifield is attached
  43. * @param $name A string containing the name of the form
  44. * @ignore-autocomplete on
  45. */
  46. public function setFormName($name)
  47. {
  48. $this->formName = $name;
  49. if ($this->fields)
  50. {
  51. foreach($this->fields as $name => $field)
  52. {
  53. $obj = $field->{'field'};
  54. if ($obj instanceof TSeekButton)
  55. {
  56. $obj->setFormName($this->formName);
  57. }
  58. }
  59. }
  60. }
  61. /**
  62. * Add a field to the MultiField
  63. * @param $name Widget's name
  64. * @param $text Widget's label
  65. * @param $object Widget
  66. * @param $size Widget's size
  67. * @param $inform Show the Widget in the form
  68. * @param $x alinhamento de linha
  69. * @param $y alinhamento de coluna
  70. */
  71. public function addField($name, $text,$lblx,$lbly, TField $object, $size,$x,$y, $align = 'left', $inform = TRUE)
  72. {
  73. $obj = new StdClass;
  74. $obj-> name = $name;
  75. $obj-> text = $text;
  76. $obj-> lblx = $lblx;
  77. $obj-> lbly = $lbly;
  78. $obj-> field = $object;
  79. $obj-> size = $size;
  80. $obj-> inform = $inform;
  81. $obj-> align = $align;
  82. $obj-> px = $x;
  83. $obj-> py = $y;
  84. $this->width += $size;
  85. $this->fields[$name] = $obj;
  86. }
  87. /**
  88. * Define the class for the Active Records returned by this component
  89. * @param $class Class Name
  90. */
  91. public function setClass($class)
  92. {
  93. $this->className = $class;
  94. }
  95. /**
  96. * Returns the class defined by the setClass() method
  97. * @return the class for the Active Records returned by this component
  98. */
  99. public function getClass()
  100. {
  101. return $this->className;
  102. }
  103. /**
  104. * Define the MultiField content
  105. * @param $objects A Collection of Active Records
  106. */
  107. public function setValue($objects)
  108. {
  109. $this->objects = $objects;
  110. // This block is executed just to call the
  111. // getters like get_virtual_property()
  112. // inside the transaction (when the attribute)
  113. // is set, and not after all (during the show())
  114. if ($objects)
  115. {
  116. foreach ($this->objects as $object)
  117. {
  118. foreach($this->fields as $name => $obj)
  119. {
  120. $object->$name; // regular attribute
  121. if ($obj-> field instanceof TComboCombined)
  122. {
  123. $attribute = $obj-> field->getTextName();
  124. $object->$attribute; // auxiliar attribute
  125. }
  126. }
  127. }
  128. }
  129. }
  130. /**
  131. * Return the post data
  132. */
  133. public function getPostData()
  134. {
  135. if (isset($_POST[$this->name]))
  136. {
  137. $val = $_POST[$this->name];
  138. $className = $this->getClass() ? $this->getClass() : 'stdClass';
  139. $decoded = JSON_decode(stripslashes($val));
  140. unset($items);
  141. unset($obj_item);
  142. $items = array();
  143. foreach ($decoded as $std_object)
  144. {
  145. $obj_item = new $className;
  146. foreach ($std_object as $subkey=>$value)
  147. {
  148. //substitui pq o ttable gera com quebra de linha no multifield
  149. //$obj_item->$subkey = URLdecode($value);
  150. $obj_item->$subkey = str_replace("\n",'',URLdecode($value));
  151. }
  152. $items[] = $obj_item;
  153. }
  154. return $items;
  155. }
  156. else
  157. {
  158. return '';
  159. }
  160. }
  161. /**
  162. * Define the MultiField height
  163. * @param $height Height in pixels
  164. */
  165. public function setHeight($height)
  166. {
  167. $this->height = $height;
  168. }
  169. /**
  170. * Define the MultiField heightPanel
  171. * @param $height Height in pixels
  172. */
  173. public function setHeightPanel($height)
  174. {
  175. $this->heightPanel = $height;
  176. }
  177. /**
  178. * Define the MultiField widthPanel
  179. * @param $width Width in pixels
  180. */
  181. public function setWidthPanel($width)
  182. {
  183. $this->widthPanel = $width;
  184. }
  185. /**
  186. * Define the MultiField position
  187. * @param $posx position in pixels
  188. * @param $posy position in pixels
  189. */
  190. public function setPosPanelxy($posx, $posy)
  191. {
  192. $this->posPanelx = $posx;
  193. $this->posPanely = $posy;
  194. }
  195. /**
  196. * Define the button's position
  197. * @param $posx position in pixels
  198. * @param $posy position in pixels
  199. */
  200. public function setPosPanelBtxy($posx, $posy)
  201. {
  202. $this->posPanelBtx = $posx;
  203. $this->posPanelBty = $posy;
  204. }
  205. /**
  206. * Show the widget at the screen
  207. */
  208. public function show()
  209. {
  210. // include the needed libraries and styles
  211. TPage::include_css('lib/adianti/include/tmultifield/tmultifield.css');
  212. TPage::include_js('lib/adianti/include/tmultifield/tmultifield.js');
  213. if ($this->fields)
  214. {
  215. $table = new TTable;//Para receber os dados de Entrada
  216. $panelCp = new TElement('div');
  217. $panelCp->id = 'multiHead';
  218. $panelCp->style = '
  219. position: relative;
  220. width: '.$this->widthPanel.'px;
  221. height: '.$this->heightPanel.'px;
  222. border-style: solid;
  223. border-width: 1px;
  224. border-color:#4682B4;
  225. ';
  226. $mdr=array(); // mandatory
  227. $fields=array();
  228. $i=0;
  229. foreach($this->fields as $name => $obj)
  230. {
  231. $label = new TLabel($obj-> text);
  232. if ($obj-> inform)
  233. {
  234. /** Define o estilo do Label **/
  235. $label->setProperty('style', '
  236. position: absolute;
  237. left: '.$obj->lblx.'px;
  238. top: '.$obj->lbly.'px;
  239. ');
  240. $panelCp->add($label);
  241. /** Define o estilo do input **/
  242. $div = new TElement('div');
  243. $div->style = '
  244. position: absolute;
  245. left: '.$obj->px.'px;
  246. top: '.$obj->py.'px;
  247. ';
  248. $obj-> field->setProperty('align',$obj-> align);
  249. $div->add($obj-> field);
  250. $panelCp->add($div);
  251. }
  252. $fields[] = $name;
  253. $post_fields[$name] = 1;
  254. $obj-> field->setName($this->name.'_'.$name);
  255. $obj-> field->setSize($obj-> size);
  256. if (get_class($obj-> field) == 'TComboCombined')
  257. {
  258. $fields[] = $obj-> field->getTextName();
  259. $obj-> field->setTextName($this->name.'_'.$obj-> field->getTextName());
  260. $i++;
  261. }
  262. $i++;
  263. }
  264. $row=$table->addRow();
  265. $row->addCell($panelCp);
  266. $table->show();
  267. }
  268. // check whether the widget is non-editable
  269. if (parent::getEditable())
  270. {
  271. // create three buttons to control the MultiField
  272. $add = new TButton("{$this->name}btnStore");
  273. $add->setLabel(TAdiantiCoreTranslator::translate('Register'));
  274. //$add->setName("{$this->name}btnStore");
  275. $add->setImage('ico_save2.png');
  276. $add->addFunction("mtf{$this->name}.addRowFromFormFields()");
  277. $del = new TButton("{$this->name}btnDelete");
  278. $del->setLabel(TAdiantiCoreTranslator::translate('Delete'));
  279. $del->setImage('remove.png');
  280. $can = new TButton("{$this->name}btnCancel");
  281. $can->setLabel(TAdiantiCoreTranslator::translate('Cancel'));
  282. $can->setImage('ico_close.png');
  283. /** div para controlar posição dos botões **/
  284. $divPosBt = new TElement('div');
  285. $divPosBt->style = '
  286. position: absolute;
  287. left: '.$this->posPanelBtx.'px;
  288. top: '.$this->posPanelBty.'px;
  289. ';
  290. $table = new TTable;
  291. $row=$table->addRow();
  292. $row->addCell($add);
  293. $row->addCell($del);
  294. $row->addCell($can);
  295. /** Coloca os botões na div **/
  296. $divPosBt->add($table);
  297. $divPosBt->show();
  298. }
  299. /** div para controlar posição de TMultifield **/
  300. $divPos = new TElement('div');
  301. $divPos->style = '
  302. position: absolute;
  303. left: '.$this->posPanelx.'px;
  304. top: '.$this->posPanely.'px;
  305. ';
  306. // create the MultiField Panel
  307. $panel = new TElement('div');
  308. $panel->{'class'} = "multifieldDiv";
  309. $divPos->add($panel);
  310. $input = new THidden($this->name);
  311. $panel->add($input);
  312. // create the MultiField DataGrid Header
  313. $table = new TTable;
  314. $table-> id="{$this->name}mfTable";
  315. $head = new TElement('thead');
  316. $table->add($head);
  317. $row = new TTableRow;
  318. $head->add($row);
  319. // fill the MultiField DataGrid
  320. foreach($this->fields as $obj)
  321. {
  322. $c = $obj-> text;
  323. if (get_class($obj-> field) == 'TComboCombined')
  324. {
  325. $row->addCell('ID');
  326. }
  327. $cell = $row->addCell($c);
  328. $cell-> width=$obj-> size.'px';
  329. }
  330. $body = new TElement('tbody');
  331. $table->add($body);
  332. if ($this->objects)
  333. {
  334. foreach($this->objects as $obj)
  335. {
  336. if (isset($obj-> id))
  337. {
  338. $row = new TTableRow;
  339. $row-> dbId=$obj-> id;
  340. $body->add($row);
  341. }
  342. else
  343. {
  344. $row = new TTableRow;
  345. $body->add($row);
  346. }
  347. foreach($fields as $name)
  348. {
  349. $cell = $row->addCell($obj->$name);
  350. if (isset($obj-> size))
  351. {
  352. $cell-> width=$obj-> size.'px';
  353. }
  354. }
  355. }
  356. }
  357. $panel->add($table);
  358. $divPos->show();
  359. echo '<script type="text/javascript">';
  360. echo "var mtf{$this->name};";
  361. //echo '$(document).ready(function() {';
  362. echo "mtf{$this->name} = new MultiField('{$this->name}mfTable',{$this->width},{$this->height});\n";
  363. $s = implode("','",$fields);
  364. echo "mtf{$this->name}.formFieldsAlias = Array('{$s}');\n";
  365. $fields = implode("','{$this->name}_",$fields);
  366. echo "mtf{$this->name}.formFieldsName = Array('{$this->name}_{$fields}');\n";
  367. echo "mtf{$this->name}.formPostFields = Array();\n";
  368. foreach ($post_fields as $col =>$value)
  369. {
  370. echo "mtf{$this->name}.formPostFields['{$col}'] = '$value';\n";
  371. }
  372. $mdr = implode(',',$mdr);
  373. echo "mtf{$this->name}.formFieldsMandatory = Array({$mdr});\n";
  374. echo "mtf{$this->name}.storeButton = document.getElementsByName('{$this->name}btnStore')[0];\n";
  375. echo "mtf{$this->name}.deleteButton = document.getElementsByName('{$this->name}btnDelete')[0];\n";
  376. echo "mtf{$this->name}.cancelButton = document.getElementsByName('{$this->name}btnCancel')[0];\n";
  377. echo "mtf{$this->name}.inputResult = document.getElementsByName('{$this->name}')[0];\n";
  378. //echo '});';
  379. echo '</script>';
  380. }
  381. }
  382. ?>
ES

funcoesGerais.jquery: nesse arquivo estou adicionando funções jquery de uso geral em meus formulários e talvez sirva para alguém também. Nele temos funções como: Enter funcionando com Tab, Transformar texto digitado em maiúsculo, alinhamento dos input gerados pelo Designer e aplicação de css em tempo real
$(document).ready(function(){
/** código a executar quando o DOM estiver pronto para receber instruções.
*
FAZ ENTER FUNCIONAR COMO TAB **/
textboxes = $("input, select, textarea");

if ($.browser.mozilla) {
$(textboxes).keypress (checkForEnter);
} else {
$(textboxes).keydown (checkForEnter);
}

/** Transforma todas as letras em maiúscula após digitar */
$('input').keyup(function() {
$(this).val($(this).val().toUpperCase());
});

/** Aplica estilo em todos input select*/
$("input").each(function(){
var inputAlign = $(this).attr("align");
$(this).css({"font-size":"11px","text-align":inputAlign});
});

$("select").css({"font-size":"11px"});

/** Aplica estilo em todas label */
$("label").css({"color":"#1567FB","font-size":"11px"});

/** Aplica estilo em todas fieldset */
$("legend label").css({"font-weight":"bold"});
});

function checkForEnter (event) {
console.log(this);
if (event.keyCode == 13 || event.keyCode == 9) {
currentBoxNumber = textboxes.index(this);

//Desenvolvido para códigos de barras que precisam continuar no mesmo campo e executar a ação
if(textboxes[currentBoxNumber].name == "COD_BARRAS"){
//Verifica se o valor é nulo, se for vai para o proximo campo
if (textboxes[currentBoxNumber].value == "") {
nextBox = textboxes[currentBoxNumber + 1];
nextBox.focus();
event.preventDefault();
return false;
} else {
//Continua no próprio campo e executa a ação no focus do outro campo
nextBox = textboxes[currentBoxNumber + 1];
nextBox.focus();
nextBox = textboxes[currentBoxNumber];
event.preventDefault();
nextBox.focus();
return false;
}
} else {
if (textboxes[currentBoxNumber + 1] != null) {
nextBox = textboxes[currentBoxNumber + 1];
nextBox.focus();
event.preventDefault();
return false;
} else {
//Será o próprio campo
nextBox = textboxes[currentBoxNumber];
event.preventDefault();
nextBox.focus();
return false;
}
}

}
}
ES

CORREÇÃO

Depois da atualização do framework ocorreu um erro em virtude das alterações provocadas pela referida atualização, que segue:

alterar <php private $formName; ?>
para <php protect $formName; ?></php></php>
ES

alterar
 
  1. <?php private $formName; ?>

para
 
  1. <?php protect $formName; ?>
AN

Parabéns Eliezer,
sua implementação ficou muito bacana, o tema escolhido para seu TWindow ficou show de bola tbm. Vamos continuar contribuindo.

Forte abraço.
PD

Eliezer,

Muito legal meu amigo. Se não for pedir muito, você poderia postar sua contribuição na aba "Contribuições" no formato de componente?

Seguindo as diretrizes de criação de novos componentes:
www.adianti.com.br/framework-extensibility

Assim, você poderia postar um único ZIP contendo o necessário para descompactar o componente e sair usando.

Um exemplo para compactar um componente que precisa de uma classe PHP e de um arquivo JS:
zip -r TMultiFieldPanel.zip app/lib/widget/TMultiFieldPanel.clas.php app/lib/include/tmultifieldpanel/tmultifieldpanel.js


Assim, poderia usar o corpo da postagem para colocar as instruções de instalação, exemplo:

cd diretório-da-aplicação unzip TMultiFieldPanel.zip


abraços!
Pablo
AN

Algum link para download da nova aplicação?
Obrigado!