Lançado Adianti Framework 7.6!
Clique aqui para saber mais
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 completo Meu Negócio Pronto
Use para si, ou transforme em um negócio: Inclui aulas e códigos-fontes
Gestor de conteúdo (SITE) + Loja Virtual (E-Commerce) + Emissor de Notas para infoprodutos


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