'Empty List', ]; protected $_enabledHeaders = true; protected $_label; protected $_labelAttribs = []; protected $_startIndex = 0; protected $_itemName; protected $_itemsName; protected $_maxItems; protected $_itemClass; protected $_itemOptions = []; protected $_required; protected $_description; protected $_columnsCount; protected $_itemSubForm; protected $_tableAttribs = []; public function init() { $this->addScript('js/qs/form/subform/table.js'); return parent::init(); } public function getLabel() { return $this->_label; } public function setLabel($label) { $this->_label = $label; return $this; } public function getLabelAttribs() { return $this->_labelAttribs; } public function setLabelAttribs(array $labelAttribs) { $this->_labelAttribs = $labelAttribs; return $this; } public function setLabelAttrib($name, $value) { $this->_labelAttribs[$name] = $value; return $this; } public function setText($name, $text) { $this->_text[$name] = $text; return $this; } public function getText($name) { return Qs_Array::get($this->_text, $name); } public function isEnabledHeaders() { return $this->_enabledHeaders; } public function setEnabledHeaders($flag) { $this->_enabledHeaders = $flag; return $this; } public function getStartIndex() { return $this->_startIndex; } public function setStartIndex($itemStartIndex) { $this->_startIndex = $itemStartIndex; return $this; } public function getItemName() { return $this->_itemName; } public function setItemName($itemName) { $this->_itemName = $itemName; return $this; } public function getItemsName() { return $this->_itemsName; } public function getMaxItems() { return $this->_maxItems; } public function setMaxItems($maxItems) { $this->_maxItems = $maxItems; return $this; } public function setItemsName($itemsName) { $this->_itemsName = $itemsName; return $this; } public function getItemClass() { return $this->_itemClass; } public function setItemClass($itemClass) { $this->_itemClass = $itemClass; return $this; } public function getItemOptions() { return $this->_itemOptions; } public function setItemOptions(array $itemOptions) { $this->_itemOptions = $itemOptions; return $this; } public function isRequired() { return $this->_required; } public function setRequired($required = true) { $this->_required = $required; return $this; } public function getDescription() { return $this->_description; } public function setDescription($description) { $this->_description = $description; return $this; } protected function _initElements() { $index = $this->getStartIndex(); $i = 0; $count = count($this->getRows()); foreach ($this->getRows() as $name => $defaults) { $first = $i === 0; $last = $i === $count - 1; $this->addSubForm($this->createRow(compact('name', 'index', 'defaults', 'first', 'last')), $name); $index++; $i++; } $this->addAddNewButton(); return parent::_initElements(); } public function createRow(array $options, $itemClass = null) { $options = array_merge( $this->getItemOptions(), [ 'orientation' => $this->getOrientation(), 'sortable' => $this->isSortable(), 'numerable' => $this->isNumerable(), 'removable' => $this->isRemovable(), ], $options ); if (null === $itemClass) { $itemClass = $this->_itemClass; } return new $itemClass($options); } protected function getRows() { return $this->_defaults; } protected function addAddNewButton() { $decorators = [ 'ViewHelper', 'Errors', [ ['td' => 'HtmlTag'], [ 'tag' => 'td', 'class' => 'bottom-row', 'colspan' => $this->getColumnsCount(), 'id' => ['callback' => ['Zend_Form_Element', 'resolveElementId']], ], ], [['tr' => 'HtmlTag'], ['tag' => 'tr']], ]; $this->addElement( 'button', 'btnAddNew', [ 'label' => 'Add New ' . $this->getItemName(), 'data-action-add' => '', 'class' => 'btn btn-default btn-small', 'decorators' => $decorators, ] ); return $this; } protected function getColumnsCount() { if (null === $this->_columnsCount) { $this->_columnsCount = ($form = $this->getItemSubForm()) ? $form->count() : 1; } return $this->_columnsCount; } /** * @return Table\Row * @throws \Exception */ public function getItemSubForm() { if (null === $this->_itemSubForm) { $this->_itemSubForm = current($this->getSubForms()); if (!$this->_itemSubForm) { if (null === $this->_itemClass) { throw new Exception('itemClass is not deifned'); } $this->_itemSubForm = new $this->_itemClass(); if (!$this->_itemSubForm instanceof Table\Row) { throw new Exception('itemClass should be instance of ' . Table\Row::CLASS); } } } return $this->_itemSubForm; } public function loadDefaultDecorators() { if ($this->loadDefaultDecoratorsIsDisabled()) { return $this; } if (($decorators = $this->getDecorators())) { return $this; } $labelAttribs = $this->getLabelAttribs(); $labelAttribs['class'] .= ' ' . ($this->isRequired() ? 'required' : 'optional'); if (!$this->getLabel()) { $labelAttribs['class'] .= ' hidden'; } if ($this->getOrientation() == self::ORIENTATION_HORIZONTAL && $this->isEnabledHeaders()) { $this->addDecorator('TableHeader'); $this->addDecorator(['theadTr' => 'HtmlTag'], ['tag' => 'tr']); $this->addDecorator(['thead' => 'HtmlTag'], ['tag' => 'thead']); } $this->addDecorator(['tbodyOpen' => 'HtmlTag'], ['tag' => 'tbody', 'openOnly' => true, 'placement' => 'append']); $this->addDecorator('FormElements'); $this->addDecorator(['tbodyClose' => 'HtmlTag'], ['tag' => 'tbody', 'closeOnly' => true, 'placement' => 'append']); $self = $this; $tableAttribs = $this->getTableAttribs(); $tableAttribs['tag'] = 'table'; if (empty($tableAttribs['id'])) { $tableAttribs['id'] = ['callback' => function () use ($self) { return $self->getId(); }]; } $tableAttribs['class'] = trim( 'table table-bordered table-striped table-form ' . Qs_Array::get($tableAttribs, 'class', '') ); if (empty($this->getRows())) { $tableAttribs['class'] .= ' table-empty'; } $this->addDecorator(['table' => 'HtmlTag'], $tableAttribs); $this->addDecorator('Description'); $this->addDecorator('FormErrorMessages'); $this->addDecorator('DtDdWrapper', ['label' => $this->getLabel(), 'labelAttribs' => $labelAttribs]); return $this; } protected function _addResources() { parent::_addResources(); $options = [ 'id' => $this->getId(), 'name' => $this->getElementsBelongTo(), 'itemName' => $this->getItemName(), 'maxItems' => $this->getMaxItems(), 'sortable' => $this->isSortable(), 'numerable' => $this->isNumerable(), 'startIndex' => $this->getStartIndex(), 'removable' => $this->isRemovable(), 'nodes' => [ 'items' => '>tbody>[data-collection-item]', 'add' => '>tbody>tr>td>[data-action-add]', ], ]; if ($this->isSortable()) { $options['nodes']['moveUp'] = '>td>[data-action-up]'; $options['nodes']['moveDown'] = '>td>[data-action-down]'; } if ($this->isRemovable()) { $options['nodes']['delete'] = '>td>[data-action-delete]'; } if ($this->isNumerable()) { $options['nodes']['rowNumber'] = '>[data-row-number]'; } $this->getDoc()->addInitObject('qs.form.subform.Table', [$options]); // Add related scripts if table has no rows if (empty($this->_defaults)) { $this->_addRelatedResources($this->createRow([])); } return $this; } protected function _addRelatedResources($item) { if ($item instanceof ResourceInterface && ($scripts = $item->getScripts())) { $this->getDoc()->addScripts($scripts); } if ($item instanceof Row) { /** @var Zend_Form_Element $element */ foreach ($item->getElements() as $element) { foreach ($element->getDecorators() as $decorator) { if ($decorator instanceof ResourceInterface && ($scripts = $decorator->getScripts())) { $this->getDoc()->addScripts($scripts); } } } foreach ($item->getSubForms() as $subForm) { $this->_addRelatedResources($subForm); } } if ($item instanceof self) { $this->_addRelatedResources($item->getItemSubForm()); } return $this; } }