/** * @param string $name The name of the form element * @param string $value The value of the element * @param SimpleXMLElement $node The xml element for the parameter * @param string $control_name The control name * @return string The html for the element */ function _form_ordering( $name, $value, &$node, $control_name ) { global $_CB_database; $onclick = $node->attributes( 'onclick' ); if ( $onclick ) { $onclickValues = explode( ',', $onclick ); $additionalConditionOrderUp = true; $additionalConditionOrderDown = true; $orderinggroups = $node->getElementByPath( 'orderinggroups'); if ( $orderinggroups ) { $orderings = array(); foreach ( $orderinggroups->children() as $group ) { /** @var $group SimpleXMLElement */ if ( $group->getName() == 'ordering' ) { $orderings[] = $group->attributes( 'name' ); // ignore $group->attributes( 'type' ) here } } if ( count( $orderings ) > 0 ) { foreach ( $orderings as $typeField ) { if ( $this->_modelOfDataRows[$this->_modelOfDataRowsNumber]->get( $typeField ) !== null ) { if ( isset( $this->_modelOfDataRows[$this->_modelOfDataRowsNumber - 1] ) && $this->_modelOfDataRows[$this->_modelOfDataRowsNumber]->get( $typeField ) != $this->_modelOfDataRows[$this->_modelOfDataRowsNumber - 1]->get( $typeField ) ) { $additionalConditionOrderUp = false; } if ( isset( $this->_modelOfDataRows[$this->_modelOfDataRowsNumber + 1] ) && $this->_modelOfDataRows[$this->_modelOfDataRowsNumber]->get( $typeField ) != $this->_modelOfDataRows[$this->_modelOfDataRowsNumber + 1]->get( $typeField ) ) { $additionalConditionOrderDown = false; } } } } } $noordering = ( $node->attributes( 'noordering' ) == 'true' ); $content = ''; if ( in_array( 'arrows', $onclickValues ) && ( ! $noordering ) ) { $content .= $this->_controllerView->pageNav->orderUpIcon( null, ( $value > -10000 && $value < 10000 && $additionalConditionOrderUp ), 'orderup/' . $name ); $content .= ' '; $content .= $this->_controllerView->pageNav->orderDownIcon( null, null, ( $value > -10000 && $value < 10000 && $additionalConditionOrderDown ), 'orderdown/' . $name ); } if ( ( in_array( 'arrows', $onclickValues ) && ( ! $noordering ) ) && in_array( 'number', $onclickValues ) ) { $content .= ' '; } if ( in_array( 'number', $onclickValues ) || $noordering ) { $content .= '<input type="text" name="' . $this->_controllerView->fieldName( $name . '[]' ) . '" size="5" value="' . $value . '" class="form-control text-center"' . ( $noordering ? ' readonly="readonly"' : null ) . ' />'; } } elseif ( $this->_view ) { $content = htmlspecialchars( $value ); } else { if ( ( $value > -10000 ) && ( $value < 10000 ) ) { $dataStorage = $this->_modelOfData[0]->getStorage(); if ( $dataStorage instanceof TableInterface ) { $dataTable = $dataStorage->getTableName(); } else { /** @var \StdClass $dataStorage */ $dataTable = $dataStorage->_tbl; } $xmlsql = new XmlQuery( $_CB_database, $dataTable, $this->_pluginParams ); $xmlsql->setExternalDataTypeValues( 'modelofdata', $this->_modelOfData[0] ); $text = $node->attributes( 'value' ); if ( ! $text ) { $text = $name; } $data = $node->getElementByPath( 'data' ); if ( ! $data ) { $defaultData = '<?xml version="1.0" encoding="UTF-8"?>' . '<data table="' . htmlspecialchars( $dataTable ) . '">' . '<rows>' . '<field name="' . htmlspecialchars( $name ) . '" as="value" />' . '<field name="' . htmlspecialchars( $text ) . '" as="text" />' . '</rows>' . '<orderby>' . '<field name="' . htmlspecialchars( $name ) . '" ordering="ASC" />' . '</orderby>' . '</data>'; $data = new SimpleXMLElement( $defaultData ); $xmlsql->prepare_query( $data ); $xmlsql->addWhere( $name, '>', '-10000', 'sql:int' ); $xmlsql->addWhere( $name, '<', '10000', 'sql:int' ); $orderinggroups = $node->getElementByPath( 'orderinggroups'); if ( $orderinggroups ) { foreach ( $orderinggroups->children() as $group ) { /** @var SimpleXMLElement $group */ $orderingFieldName = $group->attributes( 'name' ); if ( ( $group->getName() == 'ordering' ) && $orderingFieldName && ( $this->_modelOfData[0]->get( $orderingFieldName ) !== null ) ) { $xmlsql->addWhere( $orderingFieldName, '=', $this->_modelOfData[0]->get( $orderingFieldName ), $group->attributes( 'type' ) ); } } } } else { $xmlsql->prepare_query( $data ); } $options = $this->_getOrderingList( $xmlsql->_buildSQLquery() ); if ( $value === '' ) { $value = $options[count( $options ) - 1]->value; } $value = (int) $value; $content = $this->selectList( $options, $node, $control_name, $name, $value ); } else { $content = '<input type="hidden" name="ordering" value="'. $value .'" />' . CBTxt::T( 'This entry cannot be reordered' ); } } return $content; }
/** * Renders as ECHO HTML code of a table * * @param SimpleXMLElement $modelView * @param array $modelRows * @param DrawController $controllerView * @param array $options * @param string $viewType ( 'view', 'param', 'depends': means: <param> tag => param, <field> tag => view ) */ protected function renderList(&$modelView, &$modelRows, &$controllerView, &$options, $viewType = 'view') { global $_CB_framework; static $JS_loaded = 0; $pluginParams = $this->_pluginParams; $renderer = new RegistryEditView($this->input, $this->_db, $pluginParams, $this->_types, $this->_actions, $this->_views, $this->_pluginObject, $this->_tabid); $renderer->setParentView($modelView); $renderer->setModelOfDataRows($modelRows); $name = $modelView->attributes('name'); $listFieldsRows = $modelView->getElementByPath('listfields/rows'); $listFieldsPager = $modelView->getElementByPath('listfields/paging'); $filtersArray = $controllerView->filters($renderer, 'table'); $batchArray = $controllerView->batchprocess($renderer, 'table'); outputCbJs(); $tableLabel = trim(CBTxt::Th($modelView->attributes('label'))); $tableMenu = $modelView->getElementByPath('tablemenu'); if (!$JS_loaded++) { if ($controllerView->pageNav !== null) { $searchButtonJs = $controllerView->pageNav->limitstartJs(0); } else { $searchButtonJs = 'cbParentForm( this ).submit();'; } $js = "\$( '.cbTableHeader' ).on( 'click', '.cbTableHeaderExpand', function() {" . "\$( this ).removeClass( 'btn-default cbTableHeaderExpand' ).addClass( 'btn-primary cbTableHeaderCollapse' );" . "\$( this ).find( '.fa' ).removeClass( 'fa-caret-down' ).addClass( 'fa-caret-up' );" . "\$( '.' + \$( this ).data( 'toggle' ) ).slideDown();" . "});" . "\$( '.cbTableHeader' ).on( 'click', '.cbTableHeaderCollapse', function() {" . "var toggle = \$( this ).data( 'toggle' );" . "\$( this ).removeClass( 'btn-primary cbTableHeaderCollapse' ).addClass( 'btn-default cbTableHeaderExpand' );" . "\$( this ).find( '.fa' ).removeClass( 'fa-caret-up' ).addClass( 'fa-caret-down' );" . "\$( '.' + toggle ).slideUp();" . "if ( toggle == 'cbBatchTools' ) {" . "\$( '.' + toggle ).find( 'input,textarea,select' ).val( '' );" . "if ( \$.fn.cbselect ) {" . "\$( '.' + toggle ).find( 'select.cbSelect2' ).each( function() {" . "\$( this ).cbselect( 'set', '' );" . "});" . "}" . "} else {" . "\$( '.' + toggle ).find( 'input,textarea,select' ).each( function() {" . "var value = null;" . "if ( \$( this ).hasClass( 'cbSelect2' ) ) {" . "if ( \$.fn.cbselect ) {" . "value = \$( this ).cbselect( 'get' );" . "} else {" . "value = \$( this ).val();" . "}" . "} else {" . "value = \$( this ).val();" . "}" . "if ( ( value != null ) && ( value != '' ) ) {" . "\$( '.cbTableHeaderClear' ).click(); return;" . "}" . "});" . "}" . "});" . "\$( '.cbTableHeader' ).on( 'click', '.cbTableHeaderClear', function() {" . "\$( '.cbTableHeader' ).find( 'input,textarea,select' ).val( '' );" . "if ( \$.fn.cbselect ) {" . "\$( '.cbTableHeader' ).find( 'select.cbSelect2' ).each( function() {" . "\$( this ).cbselect( 'set', '' );" . "});" . "}" . $searchButtonJs . "});" . "\$( '.cbTableBrowserRowsHeader' ).on( 'click', '.cbTableBrowserSort', function() {" . "\$( '.cbTableHeader' ).find( '.cbTableBrowserSorting > select' ).val( \$( this ).data( 'table-sort' ) ).change();" . "});" . ($this->_filtered ? "\$( '.cbSearchToolsToggle' ).click();" : null); $_CB_framework->outputCbJQuery($js); } $return = '<div class="table-responsive cbTableBrowserDiv' . ($name ? ' cbDIV' . htmlspecialchars($name) : null) . '">'; if ($tableLabel || $tableMenu || $controllerView->hasSearchFields() || $controllerView->hasOrderbyFields() || count($filtersArray) > 0 || count($batchArray) > 0) { $return .= '<table class="table table-noborder cbTableBrowserHeader' . ($name ? ' cbTA' . htmlspecialchars($name) : null) . '">' . '<thead>' . '<tr class="cbTableHeader">'; if ($tableLabel || $tableMenu) { $return .= '<th style="width: 10%;" class="text-left cbTableBrowserLabel' . ($name ? ' cbTH' . htmlspecialchars($name) : null) . '">' . ($tableLabel ? $tableLabel : null); if ($tableMenu) { $menuIndex = 1; $return .= $tableLabel ? '<div><small>[ ' : null; foreach ($tableMenu->children() as $menu) { /** @var SimpleXMLElement $menu */ $menuAction = $menu->attributes('action'); $menuLabelHtml = trim(CBTxt::Th(htmlspecialchars($menu->attributes('label')))); $menuDesc = $menu->attributes('description'); if ($menuDesc) { $menuDesc = ' title="' . trim(htmlspecialchars(CBTxt::T($menuDesc))) . '"'; } $return .= $menuIndex > 1 ? ' - ' : null; if ($menuAction) { $data = null; $link = $controllerView->drawUrl($menuAction, $menu, $data, 0, true); if ($link) { $return .= '<a href="' . $link . '"' . $menuDesc . '>' . $menuLabelHtml . '</a>'; } } elseif ($menuDesc) { $return .= '<span' . $menuDesc . '>' . $menuLabelHtml . '</span>'; } else { $return .= $menuLabelHtml; } $menuIndex++; } $return .= $tableLabel ? ' ]</small></div>' : null; } $return .= '</th>'; } if ($controllerView->hasSearchFields() || $controllerView->hasOrderbyFields() || count($filtersArray) > 0 || count($batchArray) > 0) { $return .= '<th class="cbTableHeaderTools">' . '<div class="text-left clearfix cbTableBrowserTools">'; if ($controllerView->hasSearchFields()) { $return .= $controllerView->quicksearchfields(); } if (count($filtersArray) > 0) { if ($controllerView->hasSearchFields()) { $return .= ' '; } $return .= '<button type="button" class="btn btn-default cbSearchToolsToggle cbTableHeaderExpand" data-toggle="cbSearchTools">' . CBTxt::Th('Search Tools') . ' <span class="fa fa-caret-down"></span></button>'; } if (count($batchArray) > 0) { if (count($filtersArray) > 0 || $controllerView->hasSearchFields()) { $return .= ' '; } $return .= '<button type="button" class="btn btn-default cbBatchToolsToggle cbTableHeaderExpand" data-toggle="cbBatchTools">' . CBTxt::Th('Batch Tools') . ' <span class="fa fa-caret-down"></span></button>'; } $return .= ' <button type="button" class="btn btn-default cbTableHeaderClear">' . CBTxt::Th('Clear') . '</button>'; if ($controllerView->hasOrderbyFields()) { if (count($filtersArray) > 0 || count($batchArray) > 0 || $controllerView->hasSearchFields()) { $return .= ' '; } $return .= '<span class="text-right pull-right cbTableBrowserSorting">' . $controllerView->orderbyfields() . '</span>'; } $return .= '</div>'; if (count($filtersArray) > 0) { $return .= '<fieldset class="cbFilters cbSearchTools cbFieldset">' . '<legend>' . CBTxt::Th('Search Tools') . '</legend>' . implode(' ', $filtersArray) . '</fieldset>'; } if (count($batchArray) > 0) { $return .= '<fieldset class="cbBatchProcess cbBatchTools cbFieldset">' . '<legend>' . CBTxt::Th('Batch Tools') . '</legend>' . implode(' ', $batchArray) . '</fieldset>'; } $return .= '</th>'; } $return .= '</tr>' . '</thead>' . '</table>'; } if ($listFieldsRows) { $columnCount = 0; $return .= '<table class="table table-hover cbTableBrowserRows' . ($name ? ' cbTL' . htmlspecialchars($name) : null) . '">' . '<thead>' . '<tr class="cbTableBrowserRowsHeader">'; foreach ($listFieldsRows->children() as $field) { /** @var SimpleXMLElement $field */ if ($field->attributes('type') != 'hidden' && Access::authorised($field)) { $classes = RegistryEditView::buildClasses($field); $attributes = ($classes ? ' class="' . htmlspecialchars($classes) . '"' : null) . ($field->attributes('width') || $field->attributes('align') ? ' style="' . ($field->attributes('width') ? 'width: ' . htmlspecialchars($field->attributes('width')) . ';' : null) . ($field->attributes('align') ? 'text-align: ' . htmlspecialchars($field->attributes('align')) . ';' : null) . '"' : null) . ($field->attributes('nowrap') ? ' nowrap="nowrap"' : null); $fieldName = $field->attributes('name'); $fieldOrdering = $field->attributes('allowordering'); $return .= '<th' . $attributes . '>'; if ($field->attributes('type') == 'primarycheckbox') { $jsToggleAll = "cbToggleAll( this, " . count($modelRows) . ", '" . $controllerView->fieldId('id') . "' );"; $return .= '<input type="checkbox" id="' . $controllerView->fieldId('toggle') . '" name="' . $controllerView->fieldName('toggle') . '" value="" onclick="' . $jsToggleAll . '" />'; } else { $fieldIcon = null; if ($fieldOrdering) { $fieldSort = explode(',', $fieldOrdering); $fieldAsc = in_array('ascending', $fieldSort); $fieldDesc = in_array('descending', $fieldSort); if ($fieldAsc && $this->orderby == $fieldName . '_asc') { // If ascending is allowed and is already active then set click to descending if descending is allowed: if ($fieldDesc) { $return .= '<a href="javascript: void(0);" class="text-nowrap cbTableBrowserSort cbTableBrowserSortDesc" data-table-sort="' . htmlspecialchars($fieldName . '_desc') . '">'; } else { $return .= '<a href="javascript: void(0);">'; } $fieldIcon = ' <span class="fa fa-sort-alpha-asc text-default"></span>'; } elseif ($fieldDesc && $this->orderby == $fieldName . '_desc') { // If descending is allowed and is already active then set click to ascending if ascending is allowed: if ($fieldAsc) { $return .= '<a href="javascript: void(0);" class="text-nowrap cbTableBrowserSort cbTableBrowserSortAsc" data-table-sort="' . htmlspecialchars($fieldName . '_asc') . '">'; } else { $return .= '<a href="javascript: void(0);">'; } $fieldIcon = ' <span class="fa fa-sort-alpha-desc text-default"></span>'; } elseif ($fieldSort[0] == 'ascending') { // Default to ascending if this field allows it: $return .= '<a href="javascript: void(0);" class="cbTableBrowserSort cbTableBrowserSortAsc" data-table-sort="' . htmlspecialchars($fieldName . '_asc') . '">'; } elseif ($fieldSort[0] == 'descending') { // Default to descending if this field allows it: $return .= '<a href="javascript: void(0);" class="cbTableBrowserSort cbTableBrowserSortDesc" data-table-sort="' . htmlspecialchars($fieldName . '_desc') . '">'; } else { $return .= '<a href="javascript: void(0);">'; } } $return .= $field->attributes('description') ? cbTooltip(2, CBTxt::Th($field->attributes('description')), null, null, null, CBTxt::Th($field->attributes('label')), null, 'data-hascbtooltip="true"') : CBTxt::Th($field->attributes('label')); if ($fieldOrdering) { $return .= $fieldIcon . '</a>'; } } if ($field->attributes('type') == 'ordering') { if (!$fieldOrdering || in_array($this->orderby, array($fieldName . '_asc', $fieldName . '_desc', $fieldName))) { if ($fieldOrdering) { $field->addAttribute('noordering', 'false'); } if (strpos($field->attributes('onclick'), 'number') !== false) { $jsOrderSave = "cbsaveorder( this, " . count($modelRows) . ", '" . $controllerView->fieldId('id', null, false) . "', '" . $controllerView->taskName(false) . "', '" . $controllerView->subtaskName(false) . "', '" . $controllerView->subtaskValue('saveorder/' . $field->attributes('name'), false) . "' );"; $return .= ' <a href="javascript: void(0);" onclick="' . $jsOrderSave . '">' . '<span class="fa fa-save fa-lg text-default" title="' . htmlspecialchars(CBTxt::T('Save Order')) . '"></span>' . '</a>'; } } else { if ($fieldOrdering) { $field->addAttribute('noordering', 'true'); } } } $return .= '</th>'; $columnCount++; } } $return .= '</tr>' . '</thead>' . '</tbody>'; $total = count($modelRows); $controllerView->pageNav->setRowsNumber($total); if ($total) { for ($i = 0; $i < $total; $i++) { $controllerView->pageNav->setRowIndex($i); $renderer->setModelOfDataRowsNumber($i); $row = $modelRows[$i]; $rowlink = $listFieldsRows->attributes('link'); if ($rowlink) { $hrefRowEdit = $controllerView->drawUrl($rowlink, $listFieldsRows, $row, $row->id, false); if ($hrefRowEdit) { if ($listFieldsRows->attributes('target') == '_blank') { $onclickJS = 'window.open(\'' . htmlspecialchars(cbUnHtmlspecialchars($hrefRowEdit)) . '\', \'cbinvoice\', \'status=no,toolbar=no,scrollbars=yes,titlebar=no,menubar=no,resizable=yes,width=640,height=480,directories=no,location=no\'); return false;'; } else { $onclickJS = "window.location='" . htmlspecialchars(cbUnHtmlspecialchars($hrefRowEdit)) . "'"; } $rowOnclickHtml = ' onclick="' . $onclickJS . '"'; } else { $rowOnclickHtml = null; } } else { $rowOnclickHtml = null; } $controllerView->setControl_name($this->name . '[rows][' . $i . ']'); $return .= '<tr class="cbTableBrowserRow"' . $rowOnclickHtml . '>' . $renderer->renderEditRowView($listFieldsRows, $row, $controllerView, $options, $viewType, 'td') . '</tr>'; } } $controllerView->setControl_name($this->name); $return .= '</tbody>'; if ($total && (!$listFieldsPager || $listFieldsPager && $listFieldsPager->attributes('type') != 'none')) { if ($listFieldsPager) { $showPageLinks = strpos($listFieldsPager->attributes('type'), 'nopagelinks') === false; $showLimitBox = strpos($listFieldsPager->attributes('type'), 'nolimitbox') === false; $showPagesCount = strpos($listFieldsPager->attributes('type'), 'nopagescount') === false; } else { $showPageLinks = true; $showLimitBox = true; $showPagesCount = true; } if ($controllerView->pageNav->total <= $controllerView->pageNav->limit) { $showPageLinks = false; } $return .= '<tfoot>' . '<tr class="cbTableBrowserRowsPaging">' . '<th colspan="' . (int) $columnCount . '" class="text-center">' . $controllerView->pageNav->getListFooter($showPageLinks, $showLimitBox, $showPagesCount) . '</th>' . '</tr>' . '</tfoot>' . '</table>'; } elseif ($controllerView->pageNav !== null) { $return .= '</table>' . $controllerView->pageNav->getLimitBox(false); } else { $return .= '</table>'; } } elseif ($controllerView->pageNav !== null) { $return .= $controllerView->pageNav->getLimitBox(false); } $return .= '<input type="hidden" name="' . $controllerView->fieldName('subtask') . '" value="" />'; $statistics = $controllerView->getStatistics(); if ($statistics) { foreach ($statistics as $stat) { $return .= $renderer->renderEditRowView($stat['view'], $stat['values'], $controllerView, $options, 'view', 'table'); } } $return .= '</div>'; echo $return; }