%PDF-1.5 %���� ºaâÚÎΞ-ÌE1ÍØÄ÷{òò2ÿ ÛÖ^ÔÀá TÎ{¦?§®¥kuµùÕ5sLOšuY
| Server IP : 14.207.165.8 / Your IP : 216.73.216.26 Web Server : Apache/2.4.18 (Ubuntu) System : Linux 246 4.4.0-210-generic #242-Ubuntu SMP Fri Apr 16 09:57:56 UTC 2021 x86_64 User : root ( 0) PHP Version : 7.0.33-0ubuntu0.16.04.16 Disable Function : exec,passthru,shell_exec,system,proc_open,popen,pcntl_exec MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : ON | Sudo : ON | Pkexec : ON Directory : /var/www/html/egp/vendor/kartik-v/yii2-grid/src/ |
Upload File : |
<?php
/**
* @package yii2-grid
* @author Kartik Visweswaran <kartikv2@gmail.com>
* @copyright Copyright © Kartik Visweswaran, Krajee.com, 2014 - 2020
* @version 3.3.6
*/
namespace kartik\grid;
use Closure;
use kartik\base\BootstrapInterface;
use kartik\base\BootstrapTrait;
use kartik\base\Config;
use kartik\dialog\Dialog;
use Yii;
use yii\base\InvalidConfigException;
use yii\grid\Column;
use yii\grid\GridView as YiiGridView;
use yii\helpers\ArrayHelper;
use yii\helpers\Html;
use yii\helpers\Inflector;
use yii\helpers\Json;
use yii\helpers\Url;
use yii\web\JsExpression;
use yii\web\Request;
use yii\widgets\Pjax;
/**
* The GridView widget is used to display data in a grid. It provides features like [[sorter|sorting]], [[pager|paging]]
* and also [[filterModel|filtering]] the data. The [[GridView]] widget extends and modifies [[YiiGridView]] with
* various new enhancements.
*
* The columns of the grid are configured in terms of [[Column]] classes, which are configured via [[columns]]. The look
* and feel of a grid view can be customized using the large amount of properties.
*
* The GridView is available and configurable as part of the Krajee grid [[Module]] with various new additional grid
* columns and enhanced settings. The extension also incorporates various Bootstrap 3.x styling options, inbuilt
* additional jQuery plugins and has embedded support for Pjax based rendering.
*
* A basic usage of the widget looks like the following:
*
* ~~~
* <?= GridView::widget([
* 'dataProvider' => $dataProvider,
* 'columns' => [
* 'id',
* 'name',
* 'created_at:datetime',
* // ...
* ]
* ]) ?>
* ~~~
*
* @see http://demos.krajee.com/grid
* @author Kartik Visweswaran <kartikv2@gmail.com>
* @since 1.0
*/
class GridView extends YiiGridView implements BootstrapInterface
{
use BootstrapTrait;
/**
* @var string the top part of the table after the header (used for location of the page summary row)
*/
const POS_TOP = 'top';
/**
* @var string the bottom part of the table before the footer (used for location of the page summary row)
*/
const POS_BOTTOM = 'bottom';
/**
* @var string the **default** bootstrap contextual color type (applicable only for panel contextual style)
*/
const TYPE_DEFAULT = 'default';
/**
* @var string the **primary** bootstrap contextual color type
*/
const TYPE_PRIMARY = 'primary';
/**
* @var string the **information** bootstrap contextual color type
*/
const TYPE_INFO = 'info';
/**
* @var string the **danger** bootstrap contextual color type
*/
const TYPE_DANGER = 'danger';
/**
* @var string the **warning** bootstrap contextual color type
*/
const TYPE_WARNING = 'warning';
/**
* @var string the **success** bootstrap contextual color type
*/
const TYPE_SUCCESS = 'success';
/**
* @var string the **active** bootstrap contextual color type (applicable only for table row contextual style)
*/
const TYPE_ACTIVE = 'active';
/**
* @var string the Bootstrap 3.x **active** icon markup for [[BooleanColumn]]
*/
const ICON_ACTIVE = '<span class="glyphicon glyphicon-ok text-success"></span>';
/**
* @var string the **inactive** icon markup for [[BooleanColumn]]
*/
const ICON_INACTIVE = '<span class="glyphicon glyphicon-remove text-danger"></span>';
/**
* @var string the Bootstrap 3.x **expanded** icon markup for [[ExpandRowColumn]]
*/
const ICON_EXPAND = '<span class="glyphicon glyphicon-expand"></span>';
/**
* @var string the Bootstrap 3.x **collapsed** icon markup for [[ExpandRowColumn]]
*/
const ICON_COLLAPSE = '<span class="glyphicon glyphicon-collapse-down"></span>';
/**
* @var string the Bootstrap 4.x **active** icon markup for [[BooleanColumn]]
*/
const ICON_ACTIVE_BS4 = '<span class="fas fa-check text-success"></span>';
/**
* @var string the Bootstrap 4.x **inactive** icon markup for [[BooleanColumn]]
*/
const ICON_INACTIVE_BS4 = '<span class="fas fa-times text-danger"></span>';
/**
* @var string the Bootstrap 4.x **expanded** icon markup for [[ExpandRowColumn]]
*/
const ICON_EXPAND_BS4 = '<span class="far fa-plus-square"></span>';
/**
* @var string the Bootstrap 4.x **collapsed** icon markup for [[ExpandRowColumn]]
*/
const ICON_COLLAPSE_BS4 = '<span class="far fa-minus-square"></span>';
/**
* @var string the status for a **default** row in [[ExpandRowColumn]]
*/
const ROW_NONE = -1;
/**
* @var string the status for an **expanded** row in [[ExpandRowColumn]]
*/
const ROW_EXPANDED = 0;
/**
* @var string the status for a **collapsed** row in [[ExpandRowColumn]]
*/
const ROW_COLLAPSED = 1;
/**
* @var string horizontal **right** alignment for grid cells
*/
const ALIGN_RIGHT = 'right';
/**
* @var string horizontal **center** alignment for grid cells
*/
const ALIGN_CENTER = 'center';
/**
* @var string horizontal **left** alignment for grid cells
*/
const ALIGN_LEFT = 'left';
/**
* @var string vertical **top** alignment for grid cells
*/
const ALIGN_TOP = 'top';
/**
* @var string vertical **middle** alignment for grid cells
*/
const ALIGN_MIDDLE = 'middle';
/**
* @var string vertical **bottom** alignment for grid cells
*/
const ALIGN_BOTTOM = 'bottom';
/**
* @var string CSS to apply to prevent wrapping of grid cell data
*/
const NOWRAP = 'kv-nowrap';
/**
* @var string grid filter input type for [[Html::checkbox]]
*/
const FILTER_CHECKBOX = 'checkbox';
/**
* @var string grid filter input type for [[Html::radio]]
*/
const FILTER_RADIO = 'radio';
/**
* @var string grid filter input type for [[\kartik\select2\Select2]] widget
*/
const FILTER_SELECT2 = '\kartik\select2\Select2';
/**
* @var string grid filter input type for [[\kartik\typeahead\Typeahead]] widget
*/
const FILTER_TYPEAHEAD = '\kartik\typeahead\Typeahead';
/**
* @var string grid filter input type for [[\kartik\switchinput\SwitchInput]] widget
*/
const FILTER_SWITCH = '\kartik\switchinput\SwitchInput';
/**
* @var string grid filter input type for [[\kartik\touchspin\TouchSpin]] widget
*/
const FILTER_SPIN = '\kartik\touchspin\TouchSpin';
/**
* @var string grid filter input type for [[\kartik\rating\StarRating]] widget
*/
const FILTER_STAR = '\kartik\rating\StarRating';
/**
* @var string grid filter input type for [[\kartik\date\DatePicker]] widget
*/
const FILTER_DATE = '\kartik\date\DatePicker';
/**
* @var string grid filter input type for [[\kartik\time\TimePicker]] widget
*/
const FILTER_TIME = '\kartik\time\TimePicker';
/**
* @var string grid filter input type for [[\kartik\datetime\DateTimePicker]] widget
*/
const FILTER_DATETIME = '\kartik\datetime\DateTimePicker';
/**
* @var string grid filter input type for [[\kartik\daterange\DateRangePicker]] widget
*/
const FILTER_DATE_RANGE = '\kartik\daterange\DateRangePicker';
/**
* @var string grid filter input type for [[\kartik\sortinput\SortableInput]] widget
*/
const FILTER_SORTABLE = '\kartik\sortinput\SortableInput';
/**
* @var string grid filter input type for [[\kartik\range\RangeInput]] widget
*/
const FILTER_RANGE = '\kartik\range\RangeInput';
/**
* @var string grid filter input type for [[\kartik\color\ColorInput]] widget
*/
const FILTER_COLOR = '\kartik\color\ColorInput';
/**
* @var string grid filter input type for [[\kartik\slider\Slider]] widget
*/
const FILTER_SLIDER = '\kartik\slider\Slider';
/**
* @var string grid filter input type for [[\kartik\money\MaskMoney]] widget
*/
const FILTER_MONEY = '\kartik\money\MaskMoney';
/**
* @var string grid filter input type for [[\kartik\number\NumberControl]] widget
*/
const FILTER_NUMBER = '\kartik\number\NumberControl';
/**
* @var string grid filter input type for [[\kartik\checkbox\CheckboxX]] widget
*/
const FILTER_CHECKBOX_X = '\kartik\checkbox\CheckboxX';
/**
* @var string identifier for the `COUNT` summary function
*/
const F_COUNT = 'f_count';
/**
* @var string identifier for the `SUM` summary function
*/
const F_SUM = 'f_sum';
/**
* @var string identifier for the `MAX` summary function
*/
const F_MAX = 'f_max';
/**
* @var string identifier for the `MIN` summary function
*/
const F_MIN = 'f_min';
/**
* @var string identifier for the `AVG` summary function
*/
const F_AVG = 'f_avg';
/**
* @var string HTML (Hyper Text Markup Language) export format
*/
const HTML = 'html';
/**
* @var string CSV (comma separated values) export format
*/
const CSV = 'csv';
/**
* @var string Text export format
*/
const TEXT = 'txt';
/**
* @var string Microsoft Excel 95+ export format
*/
const EXCEL = 'xls';
/**
* @var string PDF (Portable Document Format) export format
*/
const PDF = 'pdf';
/**
* @var string JSON (Javascript Object Notation) export format
*/
const JSON = 'json';
/**
* @var string set download target for grid export to a popup browser window
*/
const TARGET_POPUP = '_popup';
/**
* @var string set download target for grid export to the same open document on the browser
*/
const TARGET_SELF = '_self';
/**
* @var string set download target for grid export to a new window that auto closes after download
*/
const TARGET_BLANK = '_blank';
/**
* @var string the module identifier if this widget is part of a module. If not set, the module identifier will
* be auto derived based on the \yii\base\Module::getInstance method. This can be useful, if you are setting
* multiple module identifiers for the same module in your Yii configuration file. To specify children or grand
* children modules you can specify the module identifiers relative to the parent module (e.g. `admin/content`).
*/
public $moduleId;
/**
* @var array configuration settings for the Krajee dialog widget that will be used to render alerts and
* confirmation dialog prompts
* @see http://demos.krajee.com/dialog
*/
public $krajeeDialogSettings = [];
/**
* @var string the layout that determines how different sections of the list view should be organized.
* The layout template will be automatically set based on the [[panel]] setting. If [[panel]] is a valid
* array, then the [[layout]] will default to the [[panelTemplate]] property. If the [[panel]] property
* is set to `false`, then the [[layout]] will default to `{summary}\n{items}\n{pager}`.
*
* The following tokens will be replaced with the corresponding section contents:
*
* - `{summary}`: the summary section. See [[renderSummary()]].
* - `{errors}`: the filter model error summary. See [[renderErrors()]].
* - `{items}`: the list items. See [[renderItems()]].
* - `{sorter}`: the sorter. See [[renderSorter()]].
* - `{pager}`: the pager. See [[renderPager()]].
* - `{export}`: the grid export button menu. See [[renderExport()]].
* - `{toolbar}`: the grid panel toolbar. See [[renderToolbar()]].
* - `{toolbarContainer}`: the toolbar container. See [[renderToolbarContainer()]].
*
* In addition to the above tokens, refer the [[panelTemplate]] property for other tokens supported as
* part of the bootstrap styled panel.
*
*/
public $layout = "{summary}\n{items}\n{pager}";
/**
* @var string the default label shown for each record in the grid (singular). This label will replace the singular
* word `item` within the grid summary text as well as ActionColumn default delete confirmation message.
*/
public $itemLabelSingle;
/**
* @var string the default label shown for each record in the grid (plural). This label will replace the plural word
* `items` within the grid summary text.
*/
public $itemLabelPlural;
/**
* @var string the default label shown for each record in the grid (plural). Similar to [[itemLabelPlural]] but
* this is applicable for languages like russian, where the plural label can be different for fewer item count.
* This label will replace the plural word `items-few` within the grid summary text.
*/
public $itemLabelFew;
/**
* @var string the default label shown for each record in the grid (plural). Similar to [[itemLabelPlural]] but
* this is applicable for languages like russian, where the plural label can be different for many item count.
* This label will replace the plural word `items-many` within the grid summary text.
*/
public $itemLabelMany;
/**
* @var string the default label shown for each record in the grid (accusative case). This is applicable for few
* languages like German.
*/
public $itemLabelAccusative;
/**
* @var string the template for rendering the grid within a bootstrap styled panel.
* The following special tokens are recognized and will be replaced:
* - `{prefix}`: _string_, the CSS prefix name as set in [[panelPrefix]]. Defaults to `panel panel-`.
* - `{type}`: _string_, the panel type that will append the bootstrap contextual CSS.
* - `{panelHeading}`: _string_, which will render the panel heading block.
* - `{panelBefore}`: _string_, which will render the panel before block.
* - `{panelAfter}`: _string_, which will render the panel after block.
* - `{panelFooter}`: _string_, which will render the panel footer block.
* - `{items}`: _string_, which will render the grid items.
* - `{summary}`: _string_, which will render the grid results summary.
* - `{pager}`: _string_, which will render the grid pagination links.
* - `{toolbar}`: _string_, which will render the [[toolbar]] property passed
* - `{toolbarContainer}`: _string_, which will render the toolbar container. See [[renderToolbarContainer()]].
* - `{export}`: _string_, which will render the [[export]] menu button content.
*/
public $panelTemplate = <<< HTML
{panelHeading}
{panelBefore}
{items}
{panelAfter}
{panelFooter}
HTML;
/**
* @var string the template for rendering the panel heading. The following special tokens are
* recognized and will be replaced:
* - `{title}`: _string_, which will render the panel heading title content.
* - `{summary}`: _string_, which will render the grid results summary.
* - `{items}`: _string_, which will render the grid items.
* - `{pager}`: _string_, which will render the grid pagination links.
* - `{sort}`: _string_, which will render the grid sort links.
* - `{toolbar}`: _string_, which will render the [[toolbar]] property passed
* - `{toolbarContainer}`: _string_, which will render the toolbar container. See [[renderToolbarContainer()]].
* - `{export}`: _string_, which will render the [[export]] menu button content.
*/
public $panelHeadingTemplate = <<< HTML
{summary}
{title}
<div class="clearfix"></div>
HTML;
/**
* @var string the template for rendering the panel footer. The following special tokens are
* recognized and will be replaced:
* - `{title}`: _string_, which will render the panel heading title content.
* - `{footer}`: _string_, which will render the panel footer content.
* - `{summary}`: _string_, which will render the grid results summary.
* - `{items}`: _string_, which will render the grid items.
* - `{sort}`: _string_, which will render the grid sort links.
* - `{pager}`: _string_, which will render the grid pagination links.
* - `{toolbar}`: _string_, which will render the [[toolbar]] property passed
* - `{export}`: _string_, which will render the [[export]] menu button content
*/
public $panelFooterTemplate = <<< HTML
<div class="kv-panel-pager">
{pager}
</div>
{footer}
<div class="clearfix"></div>
HTML;
/**
* @var string the template for rendering the `{before} part in the layout templates.
* The following special tokens are recognized and will be replaced:
* - `{before}`: _string_, which will render the [[before]] text passed in the panel settings
* - `{summary}`: _string_, which will render the grid results summary.
* - `{items}`: _string_, which will render the grid items.
* - `{sort}`: _string_, which will render the grid sort links.
* - `{pager}`: _string_, which will render the grid pagination links.
* - `{toolbar}`: _string_, which will render the [[toolbar]] property passed
* - `{toolbarContainer}`: _string_, which will render the toolbar container. See [[renderToolbarContainer()]].
* - `{export}`: _string_, which will render the [[export]] menu button content
*/
public $panelBeforeTemplate = <<< HTML
{toolbarContainer}
{before}
<div class="clearfix"></div>
HTML;
/**
* @var string the template for rendering the `{after} part in the layout templates. The following special
* variables are recognized and will be replaced:
* - `{after}`: _string_, which will render the `after` text passed within the [[panel]] settings
* - `{summary}`: _string_, which will render the grid results summary.
* - `{items}`: _string_, which will render the grid items.
* - `{sort}`: _string_, which will render the grid sort links.
* - `{pager}`: _string_, which will render the grid pagination links.
* - `{toolbar}`: _string_, which will render the [[toolbar]] property passed
* - `{toolbarContainer}`: _string_, which will render the toolbar container. See [[renderToolbarContainer()]].
* - `{export}`: _string_, which will render the [[export]] menu button content
*/
public $panelAfterTemplate = '{after}';
/**
* @var string the panel CSS prefix that will be applied to the panel container for rendering the grid
* within a bootstrap styled panel. This can be set to a different value to generate different styles for
* other bootstrap themes. For example, this can be set to `box box-` for rendering boxes in AdminLTE theme.
*/
public $panelPrefix;
/**
* @var array the panel settings for displaying the grid view within a bootstrap styled panel. This property is
* therefore applicable only if [[bootstrap]] property is `true`. The following array keys can be configured:
* - `type`: _string_, the panel contextual type. Set it to one of the TYPE constants. If not set, will default to
* [[TYPE_DEFAULT]].
* - `options`: _array_, the HTML attributes for the panel container. If the `class` is not set, it will be auto
* derived using the panel `type` and [[panelPrefix]]
* - `heading`: `string`|`boolean`, the panel heading. If set to `false`, will not be displayed.
* - `headingOptions`: _array_, HTML attributes for the panel heading container. Defaults to:
* - `['class'=>'panel-heading']` when [[bsVersion]] = `3.x`, and
* - `['class'=>'card-heading <COLOR>']` when [[bsVersion]] = `4.x` - the color will be auto calculated based on
* the `type` setting
* - `titleOptions`: _array_, HTML attributes for the panel title container. The following tags are specially
* parsed:
* - `tag`: _string_, the HTML tag to render the title. Defaults to `h3` when [[bsVersion]] = `3.x` and `span`
* when [[bsVersion]] = `4.x`
* The `titleOptions` defaults to:
* - `['class'=>'panel-title']` when [[bsVersion]] = `3.x`, and
* - `[]` when [[bsVersion]] = `4.x`
* - `summaryOptions`: _array_, HTML attributes for the panel summary section container. Defaults to:
* - `['class'=>'pull-right']` when [[bsVersion]] = `3.x`, and
* - `['class'=>'float-right']` when [[bsVersion]] = `4.x`, and
* - `footer`: `string`|`boolean`, the panel footer. If set to `false` will not be displayed.
* - `footerOptions`: _array_, HTML attributes for the panel footer container. Defaults to:
* - `['class'=>'panel-footer']` when [[bsVersion]] = `3.x`, and
* - `['class'=>'card-footer']` when [[bsVersion]] = `4.x`
* - 'before': `string`|`boolean`, content to be placed before/above the grid (after the header). To not display
* this section, set this to `false`.
* - `beforeOptions`: _array_, HTML attributes for the `before` text. If the `class` is not set, it will default to
* `kv-panel-before`.
* - 'after': `string`|`boolean`, any content to be placed after/below the grid (before the footer). To not
* display this section, set this to `false`.
* - `afterOptions`: _array_, HTML attributes for the `after` text. If the `class` is not set, it will default to
* `kv-panel-after`.
*/
public $panel = [];
/**
* @var array|string configuration of additional header table rows that will be rendered before the default grid
* header row. If set as a _string_, it will be displayed as is, without any HTML encoding. If set as an _array_,
* each row in this array corresponds to a HTML table row, where you can configure the columns with these properties:
* - `columns`: _array_, the header row columns configuration where you can set the following properties:
* - `content`: _string_, the grid cell content for the column
* - `tag`: _string_, the tag for rendering the grid cell. If not set, defaults to `th`.
* - `options`: _array_, the HTML attributes for the grid cell
* - `options`: _array_, the HTML attributes for the table row
*/
public $beforeHeader = [];
/**
* @var array|string configuration of additional header table rows that will be rendered after default grid header
* row. If set as a _string_, it will be displayed as is, without any HTML encoding. If set as an _array_, each
* row in this array corresponds to a HTML table row, where you can configure the columns with these properties:
* - `columns`: _array_, the header row columns configuration where you can set the following properties:
* - `content`: _string_, the grid cell content for the column
* - `tag`: _string_, the tag for rendering the grid cell. If not set, defaults to `th`.
* - `options`: _array_, the HTML attributes for the grid cell
* - `options`: _array_, the HTML attributes for the table row
*/
public $afterHeader = [];
/**
* @var array|string configuration of additional footer table rows that will be rendered before the default grid
* footer row. If set as a _string_, it will be displayed as is, without any HTML encoding. If set as an _array_,
* each row in this array corresponds to a HTML table row, where you can configure the columns with these properties:
* - `columns`: _array_, the footer row columns configuration where you can set the following properties:
* - `content`: _string_, the grid cell content for the column
* - `tag`: _string_, the tag for rendering the grid cell. If not set, defaults to `th`.
* - `options`: _array_, the HTML attributes for the grid cell
* - `options`: _array_, the HTML attributes for the table row
*/
public $beforeFooter = [];
/**
* @var array|string configuration of additional footer table rows that will be rendered after the default grid
* footer row. If set as a _string_, it will be displayed as is, without any HTML encoding. If set as an _array_,
* each row in this array corresponds to a HTML table row, where you can configure the columns with these properties:
* - `columns`: _array_, the footer row columns configuration where you can set the following properties:
* - `content`: _string_, the grid cell content for the column
* - `tag`: _string_, the tag for rendering the grid cell. If not set, defaults to `th`.
* - `options`: _array_, the HTML attributes for the grid cell
* - `options`: _array_, the HTML attributes for the table row
*/
public $afterFooter = [];
/**
* @var array|string the toolbar content configuration. Can be setup as a string or an array. When set as a
* _string_, it will be rendered as is. When set as an _array_, each line item will be considered as per the
* following rules:
* - if the line item is setup as a _string_, it will be rendered as is
* - if the line item is an _array_, the following keys can be setup to control the rendering of the toolbar:
* - `content`: _string_, the content to be rendered as a bootstrap button group. The following special tags
* in the content are recognized and will be replaced:
* - `{export}`, _string_ which will render the [[export]] menu button content.
* - `{toggleData}`, _string_ which will render the button to toggle between page data and all data.
* - `options`: _array_, the HTML attributes for the button group div container. By default the CSS class
* `btn-group` will be attached to this container if no class is set.
*/
public $toolbar = [
'{toggleData}',
'{export}',
];
/**
* @var array the HTML attributes for the toolbar container. The following special attributes are recognized:
*
* - `tag`: _string_, the HTML tag to render the toolbar container. Defaults to `div`.
*/
public $toolbarContainerOptions = ['class' => 'btn-toolbar kv-grid-toolbar toolbar-container'];
/**
* @var array tags to replace in the rendered layout. Enter this as `$key => $value` pairs, where:
* - `$key`: _string_, defines the flag.
* - `$value`: _string_|_Closure_, the value that will be replaced. You can set it as a callback function to return
* a string of the signature: `function ($widget) { return 'custom'; }`.
*
* For example, a custom tag like `{star}` can be set as:
*
* ```php
* [
* '{star}' => '<span class="glyphicon glyphicon-asterisk"></span>'
* ]
* ```
*/
public $replaceTags = [];
/**
* @var string the default data column class if the class name is not explicitly specified when configuring a data
* column. Defaults to 'kartik\grid\DataColumn'.
*/
public $dataColumnClass = 'kartik\grid\DataColumn';
/**
* @var array the HTML attributes for the grid footer row
*/
public $footerRowOptions = ['class' => 'kv-table-footer'];
/**
* @var array the HTML attributes for the grid caption
*/
public $captionOptions = ['class' => 'kv-table-caption'];
/**
* @var array the HTML attributes for the grid element
*/
public $tableOptions = [];
/**
* @var boolean whether the grid view will be rendered within a pjax container. Defaults to `false`. If set to
* `true`, the entire GridView widget will be parsed via Pjax and auto-rendered inside a yii\widgets\Pjax
* widget container. If set to `false` pjax will be disabled and none of the pjax settings will be applied.
*/
public $pjax = false;
/**
* @var array the pjax settings for the widget. This will be considered only when [[pjax]] is set to true. The
* following settings are recognized:
* - `neverTimeout`: `boolean`, whether the pjax request should never timeout. Defaults to `true`. The pjax:timeout
* event will be configured to disable timing out of pjax requests for the pjax container.
* - `options`: _array_, the options for the [[\yii\widgets\Pjax]] widget.
* - `loadingCssClass`: boolean/string, the CSS class to be applied to the grid when loading via pjax. If set to
* `false` - no css class will be applied. If it is empty, null, or set to `true`, will default to
* `kv-grid-loading`.
* - `beforeGrid`: _string_, any content to be embedded within pjax container before the Grid widget.
* - `afterGrid`: _string_, any content to be embedded within pjax container after the Grid widget.
*/
public $pjaxSettings = [];
/**
* @var boolean whether to allow resizing of columns
*/
public $resizableColumns = true;
/**
* @var boolean whether to hide resizable columns for smaller screen sizes (< 768px). Defaults to `true`.
*/
public $hideResizeMobile = true;
/**
* @var array the resizableColumns plugin options
*/
public $resizableColumnsOptions = ['resizeFromBody' => false];
/**
* @var boolean whether to store resized column state using local storage persistence (supported by most modern
* browsers).
*/
public $persistResize = false;
/**
* @var string resizable unique storage prefix to append to the grid id. If empty or not set it will default to
* `Yii::$app->user->id`.
*/
public $resizeStorageKey;
/**
* @var boolean whether the grid view will have Bootstrap table styling.
*/
public $bootstrap = true;
/**
* @var boolean whether the grid will have a `bordered` style. Applicable only if `bootstrap` is `true`.
*/
public $bordered = true;
/**
* @var boolean whether the grid will have a `striped` style. Applicable only if `bootstrap` is `true`.
*/
public $striped = true;
/**
* @var boolean whether the grid will have a `condensed` style. Applicable only if `bootstrap` is `true`.
*/
public $condensed = false;
/**
* @var boolean whether the grid will have a `responsive` style. Applicable only if `bootstrap` is `true`.
*/
public $responsive = true;
/**
* @var boolean whether the grid will automatically wrap to fit columns for smaller display sizes.
*/
public $responsiveWrap = true;
/**
* @var boolean whether the grid will highlight row on `hover`. Applicable only if `bootstrap` is `true`.
*/
public $hover = false;
/**
* @var boolean whether the grid will have a floating table header.
*/
public $floatHeader = false;
/**
* @var boolean whether the table header will float and sticks around as you scroll within a container. If
* `responsive` is true then this is auto set to `true`.
*/
public $floatOverflowContainer = false;
/**
* @var array the plugin options for the floatThead plugin that would render the floating/sticky table header
* behavior. The default offset from the top of the window where the floating header will 'stick' when scrolling
* down is set to `50` assuming a fixed bootstrap navbar on top. You can set this to `0` or any javascript
* function / expression.
* @see http://mkoryak.github.io/floatThead#options
*/
public $floatHeaderOptions = ['top' => 50];
/**
* @var boolean whether pretty perfect scrollbars using perfect scrollbar plugin is to be used. Defaults to
* `false`. If this is set to true, the `floatOverflowContainer` property will be auto set to `true`, if
* `floatHeader` is `true`.
* @see https://github.com/utatti/perfect-scrollbar
*/
public $perfectScrollbar = false;
/**
* @var array the plugin options for the perfect scrollbar plugin.
* @see https://github.com/noraesae/perfect-scrollbar
*/
public $perfectScrollbarOptions = [];
/**
* @var boolean whether to show the page summary row for the table. This will be displayed above the footer.
*/
public $showPageSummary = false;
/**
* @var string location of the page summary row (whether [[POS_TOP]] or [[POS_BOTTOM]])
*/
public $pageSummaryPosition = self::POS_BOTTOM;
/**
* @array the HTML attributes for the page summary container. The following special options are recognized:
*
* - `tag`: _string_, the tag used to render the page summary. Defaults to `tbody`.
*/
public $pageSummaryContainer = ['class' => 'kv-page-summary-container'];
/**
* @array the HTML attributes for the summary row.
*/
public $pageSummaryRowOptions = [];
/**
* @var string the default pagination that will be read by toggle data. Should be one of 'page' or 'all'. If not
* set to 'all', it will always defaults to 'page'.
*/
public $defaultPagination = 'page';
/**
* @var boolean whether to enable toggling of grid data. Defaults to `true`.
*/
public $toggleData = true;
/**
* @var array the settings for the toggle data button for the toggle data type. This will be setup as an
* associative array of $key => $value pairs, where $key can be:
* - `maxCount`: `int`|`boolean`, the maximum number of records uptil which the toggle button will be rendered. If
* the dataProvider records exceed this setting, the toggleButton will not be displayed. Defaults to `10000` if
* not set. If you set this to `true`, the toggle button will always be displayed. If you set this to `false
* the toggle button will not be displayed (similar to `toggleData` setting).
* - `minCount`: `int`|`boolean`, the minimum number of records beyond which a confirmation message will be
* displayed when toggling all records. If the dataProvider record count exceeds this setting, a confirmation
* message will be alerted to the user. Defaults to `500` if not set. If you set this to `true`, the
* confirmation message will always be displayed. If set to `false` no confirmation message will be displayed.
* - `confirmMsg`: _string_, the confirmation message for the toggle data when `minCount` threshold is exceeded.
* Defaults to `'There are {totalCount} records. Are you sure you want to display them all?'`.
* - `all`: _array_, configuration for showing all grid data and the value is the HTML attributes for the button.
* (refer `page` for understanding the default options).
* - `page`: _array_, configuration for showing first page data and $options is the HTML attributes for the button.
* The following special options are recognized:
* - `icon`: _string_, the glyphicon suffix name. If not set or empty will not be displayed.
* - `label`: _string_, the label for the button.
*
* This defaults to the following setting:
*
* ```php
* [
* 'maxCount' => 10000,
* 'minCount' => 1000
* 'confirmMsg' => Yii::t(
* 'kvgrid',
* 'There are {totalCount} records. Are you sure you want to display them all?',
* ['totalCount' => number_format($this->dataProvider->getTotalCount())]
* ),
* 'all' => [
* 'icon' => 'resize-full',
* 'label' => 'All',
* 'class' => 'btn btn-default', // 'btn btn-secondary' for BS4.x
* 'title' => 'Show all data'
* ],
* 'page' => [
* 'icon' => 'resize-small',
* 'label' => 'Page',
* 'class' => 'btn btn-default', // 'btn btn-secondary' for BS4.x
* 'title' => 'Show first page data'
* ],
* ]
* ```
*/
public $toggleDataOptions = [];
/**
* @var array the HTML attributes for the toggle data button group container. By default this will always have the
* `class = btn-group` automatically added, if no class is set.
*/
public $toggleDataContainer = [];
/**
* @var array the HTML attributes for the export button group container. By default this will always have the
* `class = btn-group` automatically added, if no class is set.
*/
public $exportContainer = [];
/**
* @var array|boolean the grid export menu settings. Displays a Bootstrap dropdown menu that allows you to export the
* grid as either html, csv, or excel. If set to `false`, will not be displayed. The following options can be
* set:
* - `icon`: _string_,the glyphicon suffix to be displayed before the export menu label. If not set or is an empty
* string, this will not be displayed. Defaults to `export` if `fontAwesome` is `false` and `share-square-o` if
* fontAwesome is `true`.
* - `label`: _string_,the export menu label (this is not HTML encoded). Defaults to ''.
* - `showConfirmAlert`: bool, whether to show a confirmation alert dialog before download. This confirmation
* dialog will notify user about the type of exported file for download and to disable popup blockers.
* Defaults to `true`.
* - `target`: _string_, the target for submitting the export form, which will trigger
* the download of the exported file. Must be one of the `TARGET_` constants.
* Defaults to `GridView::TARGET_POPUP`.
* - `messages`: _array_, the configuration of various messages that will be displayed at runtime:
* - `allowPopups`: _string_, the message to be shown to disable browser popups for download.
* Defaults to `Disable any popup blockers in your browser to ensure proper download.`.
* - `confirmDownload`: _string_, the message to be shown for confirming to proceed with the download. Defaults
* to `Ok to proceed?`.
* - `downloadProgress`: _string_, the message to be shown in a popup dialog when download request is
* triggered. Defaults to `Generating file. Please wait...`.
* - `downloadComplete`: _string_, the message to be shown in a popup dialog when download request is completed.
* Defaults to `All done! Click anywhere here to close this window, once you have downloaded the file.`.
* - `header`: _string_, the header for the page data export dropdown. If set to empty string will not be
* displayed. Defaults to: `<li role="presentation" class="dropdown-header">Export Page Data</li>`.
* - `fontAwesome`: bool, whether to use font awesome file type icons. Defaults to `false`. If you set it to
* `true`, then font awesome icons css class will be applied instead of glyphicons.
* - `itemsBefore`: _array_, any additional items that will be merged/prepended before with the export dropdown
* list. This should be similar to the `items` property as supported by `\yii\bootstrap\ButtonDropdown` widget.
* Note the page export items will be automatically generated based on settings in the `exportConfig` property.
* - `itemsAfter`: _array_, any additional items that will be merged/appended after with the export dropdown list.
* This should be similar to the `items` property as supported by `\yii\bootstrap\ButtonDropdown` widget. Note
* the page export items will be automatically generated based on settings in the `exportConfig` property.
* - `options`: _array_, HTML attributes for the export menu button. Defaults to
* - `['class' => 'btn btn-default']` for [[bsVersion]] = '3.x' or .
* - `['class' => 'btn btn-secondary']` for [[bsVersion]] = '4.x'
* - `encoding`: _string_, the export output file encoding. If not set, defaults to `utf-8`.
* - `bom`: `boolean`, whether a BOM is to be embedded for text or CSV files with utf-8 encoding. Defaults to
* `true`.
* - `menuOptions`: _array_, HTML attributes for the export dropdown menu. Defaults to `['class' => 'dropdown-menu
* dropdown-menu-right']`. This property is to be setup exactly as the `options` property required by the
* [[\yii\bootstrap\Dropdown]] widget.
* - `skipExportElements`: _array_, the list of jQuery element selectors that will be skipped and removed from
* export. Defaults to `['.sr-only', '.hide']`.
*/
public $export = [];
/**
* @var array the configuration for each export format. The array keys must be the one of the `format` constants
* (CSV, HTML, TEXT, EXCEL, PDF, JSON) and the array value is a configuration array consisiting of these settings:
* - `label`: _string_,the label for the export format menu item displayed
* - `icon`: _string_,the glyphicon or font-awesome name suffix to be displayed before the export menu item label.
* If set to an empty string, this will not be displayed. Refer `defaultConfig` in `initExport` method for
* default settings.
* - `showHeader`: `boolean`, whether to show table header row in the output. Defaults to `true`.
* - `showPageSummary`: `boolean`, whether to show table page summary row in the output. Defaults to `true`.
* - `showFooter`: `boolean`, whether to show table footer row in the output. Defaults to `true`.
* - `showCaption`: `boolean`, whether to show table caption in the output (only for HTML). Defaults to `true`.
* - `filename`: the base file name for the generated file. Defaults to 'grid-export'. This will be used to
* generate a default file name for downloading (extension will be one of csv, html, or xls - `based on the
* format setting).
* - `alertMsg`: _string_, the message prompt to show before saving. If this is empty or not set it will not be
* displayed.
* - `options`: _array_, HTML attributes for the export format menu item.
* - `mime`: _string_, the mime type (for the file format) to be set before downloading.
* - `config`: _array_, the special configuration settings specific to each file format/type. The following
* configuration options are read specific to each file type:
* - `HTML`: The following properties can be set as array key-value pairs:
* - `cssFile`: _string_, the css file that will be used in the exported HTML file. Defaults to:
* `https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css`.
* - `CSV` and `TEXT`: The following properties can be set as array key-value pairs:
* - `colDelimiter`: _string_, the column delimiter string for TEXT and CSV downloads.
* - `rowDelimiter`: _string_, the row delimiter string for TEXT and CSV downloads.
* - `EXCEL`: The following properties can be set as array key-value pairs:
* - `worksheet`: _string_, the name of the worksheet, when saved as EXCEL file.
* - `PDF`: Supports all configuration properties as required in [[\kartik\mpdf\Pdf]] extension. In addition, the
* following additional special options are recognized:
* - `contentBefore`: _string_, any HTML formatted content that will be embedded in the PDF output before
* the grid.
* - `contentAfter`: _string_, any HTML formatted content that will be embedded in the PDF output after
* the grid.
* - `JSON`: The following properties can be set as array key-value pairs:
* - `colHeads`: _array_, the column heading names to be output in the json file. If not set, it will be
* autogenerated as "col-{i}", where {i} is the column index. If `slugColHeads` is set to `true`, the
* extension will attempt to autogenerate column heads based on table column heading, whereever
* possible.
* - `slugColHeads`: `boolean`, whether to auto-generate column identifiers as slugs based on the table
* column heading name. If the table column heading contains characters which cannot be slugified, then
* the extension will autogenerate the column name as "col-{i}".
* - `jsonReplacer``: array|JsExpression, the JSON replacer property - `can be an array or a JS function
* created using JsExpression. Refer the [JSON documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_native_JSON#The_replacer_parameter)
* for details on setting this property.
* - `indentSpace`: int, pretty print json output and indent by number of spaces specified. Defaults to `4`.
*/
public $exportConfig = [];
/**
* @var array conversion of defined patterns in the grid cells as a preprocessing before the gridview is formatted
* for export. Each array row must consist of the following two keys:
* - `from`: _string_, is the pattern to search for in each grid column's cells
* - `to`: _string_, is the string to replace the pattern in the grid column cells
* This defaults to:
* ```php
* [
* ['from'=>GridView::ICON_ACTIVE, 'to'=>Yii::t('kvgrid', 'Active')],
* ['from'=>GridView::ICON_INACTIVE, 'to'=>Yii::t('kvgrid', 'Inactive')]
* ]
* ```
*/
public $exportConversions = [];
/**
* @var boolean determines whether the exported EXCEL cell data will be automatically guessed and formatted based on
* [[DataColumn::format]] property. This property is applicable for EXCEL export content only. One can override this
* behavior and change the auto-derived format mask by setting [[DataColumn::xlFormat]].
*/
public $autoXlFormat = false;
/**
* @var array|boolean the HTML attributes for the grid container. The grid items will be wrapped in a `div`
* container with the configured HTML attributes. The ID for the container will be auto generated.
*/
public $containerOptions = [];
/**
* Whether to hash export config and prevent data tampering of the export config when transmitting this between
* client and server during grid data export. Defaults to `true`. You may set this to `false` if your config
* contains dynamic data (like current date time). However, note that when `false` it adds the possibility of
* your client data being tampered during grid export when read by server.
*/
public $hashExportConfig = true;
/**
* @var string the generated client script for the grid
*/
protected $_gridClientFunc = '';
/**
* @var Module the grid module.
*/
protected $_module;
/**
* @var string key to identify showing all data
*/
protected $_toggleDataKey;
/**
* @var string HTML attribute identifier for the toggle button
*/
protected $_toggleButtonId;
/**
* @var string the JS variable to store the toggle options
*/
protected $_toggleOptionsVar;
/**
* @var string generated plugin script for the toggle button
*/
protected $_toggleScript;
/**
* @var boolean whether the current mode is showing all data
*/
protected $_isShowAll = false;
/**
* Parses export configuration and returns the merged defaults.
*
* @param array $exportConfig the export configuration
* @param array $defaultExportConfig the default export configuration
*
* @return array
*/
protected static function parseExportConfig($exportConfig, $defaultExportConfig)
{
if (is_array($exportConfig) && !empty($exportConfig)) {
foreach ($exportConfig as $format => $setting) {
$setup = is_array($exportConfig[$format]) ? $exportConfig[$format] : [];
$exportConfig[$format] = empty($setup) ? $defaultExportConfig[$format] :
array_replace_recursive($defaultExportConfig[$format], $setup);
}
return $exportConfig;
}
return $defaultExportConfig;
}
/**
* Sets a default css class within `options` if not set
*
* @param array $options the HTML options
* @param string|array $css the CSS class to test and append
*/
protected static function initCss(&$options, $css)
{
if (!isset($options['class'])) {
$options['class'] = $css;
}
}
/**
* @inheritdoc
* @throws InvalidConfigException
*/
public function init()
{
$this->initModule();
if (isset($this->_module->bsVersion)) {
$this->bsVersion = $this->_module->bsVersion;
}
$this->initBsVersion();
Html::addCssClass($this->options, 'is-bs' . ($this->isBs4() ? '4' : '3'));
$this->initPjaxContainerId();
if (!isset($this->itemLabelSingle)) {
$this->itemLabelSingle = Yii::t('kvgrid', 'item');
}
if (!isset($this->itemLabelPlural)) {
$this->itemLabelPlural = Yii::t('kvgrid', 'items');
}
if (!isset($this->itemLabelFew)) {
$this->itemLabelFew = Yii::t('kvgrid', 'items-few');
}
if (!isset($this->itemLabelMany)) {
$this->itemLabelMany = Yii::t('kvgrid', 'items-many');
}
if (!isset($this->itemLabelAccusative)) {
$this->itemLabelAccusative = Yii::t('kvgrid', 'items-acc');
}
$isBs4 = $this->isBs4();
if ($isBs4) {
Html::addCssClass($this->options, 'kv-grid-bs4');
$this->setPagerOptionClass('linkContainerOptions', 'page-item');
$this->setPagerOptionClass('linkOptions', 'page-link');
$this->setPagerOptionClass('disabledListItemSubTagOptions', 'page-link');
}
if (!$this->toggleData) {
parent::init();
return;
}
$this->_toggleDataKey = '_tog' . hash('crc32', $this->options['id']);
/**
* @var Request $request
*/
$request = $this->_module->get('request', false);
if ($request === null || !($request instanceof Request)) {
$request = Yii::$app->request;
}
$this->_isShowAll = $request->getQueryParam($this->_toggleDataKey, $this->defaultPagination) === 'all';
if ($this->_isShowAll) {
/** @noinspection PhpUndefinedFieldInspection */
$this->dataProvider->pagination = false;
}
$this->_toggleButtonId = $this->options['id'] . '-togdata-' . ($this->_isShowAll ? 'all' : 'page');
parent::init();
}
/**
* Get pjax container identifier
* @return string
*/
public function getPjaxContainerId()
{
$this->initPjaxContainerId();
return $this->pjaxSettings['options']['id'];
}
/**
* Initializes pjax container identifier
*/
public function initPjaxContainerId()
{
if (empty($this->options['id'])) {
$this->options['id'] = $this->getId();
}
if (empty($this->pjaxSettings['options']['id'])) {
$this->pjaxSettings['options']['id'] = $this->options['id'] . '-pjax';
}
}
/**
* Adds CSS class to the pager parameter
* @param string $param the pager param
* @param string $css the CSS class
*/
protected function setPagerOptionClass($param, $css)
{
$opts = ArrayHelper::getValue($this->pager, $param, []);
Html::addCssClass($opts, $css);
$this->pager[$param] = $opts;
}
/**
* @inheritdoc
* @throws InvalidConfigException
* @throws \Exception
*/
public function run()
{
$this->initToggleData();
$this->initExport();
if ($this->export !== false && isset($this->exportConfig[self::PDF])) {
Config::checkDependency(
'mpdf\Pdf',
'yii2-mpdf',
'for PDF export functionality. To include PDF export, follow the install steps below. If you do not ' .
"need PDF export functionality, do not include 'PDF' as a format in the 'export' property. You can " .
"otherwise set 'export' to 'false' to disable all export functionality"
);
}
$this->initHeader();
$this->initBootstrapStyle();
$this->containerOptions['id'] = $this->options['id'] . '-container';
Html::addCssClass($this->containerOptions, 'kv-grid-container');
$this->initPanel();
$this->initLayout();
$this->registerAssets();
if ($this->pjax) {
$this->beginPjax();
parent::run();
$this->endPjax();
} else {
parent::run();
}
}
/**
* Renders the table page summary.
*
* @return string the rendering result.
* @throws InvalidConfigException
*/
public function renderPageSummary()
{
if (!$this->showPageSummary) {
return null;
}
if (!isset($this->pageSummaryRowOptions['class'])) {
$this->pageSummaryRowOptions['class'] = ($this->isBs4() ? 'table-' : '') . 'warning kv-page-summary';
}
Html::addCssClass($this->pageSummaryRowOptions, $this->options['id']);
$row = $this->getPageSummaryRow();
if ($row === null) {
return '';
}
$tag = ArrayHelper::remove($this->pageSummaryContainer, 'tag', 'tbody');
$content = Html::tag('tr', $row, $this->pageSummaryRowOptions);
return Html::tag($tag, $content, $this->pageSummaryContainer);
}
/**
* Get the page summary row markup
* @return string
*/
protected function getPageSummaryRow()
{
$columns = array_values($this->columns);
$cols = count($columns);
if ($cols === 0) {
return null;
}
$cells = [];
$skipped = [];
for ($i = 0; $i < $cols; $i++) {
/** @var DataColumn $column */
$column = $columns[$i];
if (!method_exists($column, 'renderPageSummaryCell')) {
$cells[] = Html::tag('td');
continue;
}
$cells[] = $column->renderPageSummaryCell();
if (!empty($column->pageSummaryOptions['colspan'])) {
$span = (int)$column->pageSummaryOptions['colspan'];
$dir = ArrayHelper::getValue($column->pageSummaryOptions, 'data-colspan-dir', 'ltr');
if ($span > 0) {
$fm = ($dir === 'ltr') ? ($i + 1) : ($i - $span + 1);
$to = ($dir === 'ltr') ? ($i + $span - 1) : ($i - 1);
for ($j = $fm; $j <= $to; $j++) {
$skipped[$j] = true;
}
}
}
}
if (!empty($skipped)) {
for ($i = 0; $i < $cols; $i++) {
if (isset($skipped[$i])) {
$cells[$i] = '';
}
}
}
return implode('', $cells);
}
/**
* @inheritdoc
* @throws InvalidConfigException
*/
public function renderTableBody()
{
$content = parent::renderTableBody();
if ($this->showPageSummary) {
$summary = $this->renderPageSummary();
return $this->pageSummaryPosition === self::POS_TOP ? ($summary . $content) : ($content . $summary);
}
return $content;
}
/**
* Renders a table row with the given data model and key.
* @param mixed $model the data model to be rendered
* @param mixed $key the key associated with the data model
* @param int $index the zero-based index of the data model among the model array returned by [[dataProvider]].
* @return string the rendering result
*/
public function renderTableRow($model, $key, $index)
{
$cells = [];
/* @var $column Column */
foreach ($this->columns as $column) {
$cells[] = $column->renderDataCell($model, $key, $index);
}
if ($this->rowOptions instanceof Closure) {
$options = call_user_func($this->rowOptions, $model, $key, $index, $this);
} else {
$options = $this->rowOptions;
}
$options['data-key'] = static::parseKey($key);
Html::addCssClass($options, $this->options['id']);
return Html::tag('tr', implode('', $cells), $options);
}
/**
* Parses the key and returns parsed key value as string based on the data type
* @param mixed $key
* @return string
*/
public static function parseKey($key)
{
return is_array($key) ? Json::encode($key) : (is_object($key) ? serialize($key) : (string)$key);
}
/**
* Renders the toggle data button.
*
* @return string
*/
public function renderToggleData()
{
if (!$this->toggleData) {
return '';
}
$maxCount = ArrayHelper::getValue($this->toggleDataOptions, 'maxCount', false);
if ($maxCount !== true && (!$maxCount || (int)$maxCount <= $this->dataProvider->getTotalCount())) {
return '';
}
$tag = $this->_isShowAll ? 'page' : 'all';
$options = $this->toggleDataOptions[$tag];
$label = ArrayHelper::remove($options, 'label', '');
$url = Url::current([$this->_toggleDataKey => $tag]);
static::initCss($this->toggleDataContainer, 'btn-group');
return Html::tag('div', Html::a($label, $url, $options), $this->toggleDataContainer);
}
/**
* Renders the export menu.
*
* @return string
* @throws InvalidConfigException
* @throws \Exception
*/
public function renderExport()
{
if ($this->export === false || !is_array($this->export) ||
empty($this->exportConfig) || !is_array($this->exportConfig)
) {
return '';
}
$isBs4 = $this->isBs4();
$title = $this->export['label'];
$icon = $this->export['icon'];
$options = $this->export['options'];
static::initCss($options, ['btn', $this->_defaultBtnCss]);
$menuOptions = $this->export['menuOptions'];
$title = ($icon == '') ? $title : "<i class='{$icon}'></i> {$title}";
$encoding = ArrayHelper::getValue($this->export, 'encoding', 'utf-8');
$bom = (int)ArrayHelper::getValue($this->export, 'bom', 1);
$items = empty($this->export['header']) ? [] : [$this->export['header']];
foreach ($this->exportConfig as $format => $setting) {
$iconOptions = ArrayHelper::getValue($setting, 'iconOptions', []);
Html::addCssClass($iconOptions, $setting['icon']);
$label = (empty($setting['icon']) || $setting['icon'] == '') ? $setting['label'] :
Html::tag('i', '', $iconOptions) . ' ' . $setting['label'];
$mime = ArrayHelper::getValue($setting, 'mime', 'text/plain');
$config = ArrayHelper::getValue($setting, 'config', []);
$cssStyles = ArrayHelper::getValue($setting, 'cssStyles', []);
if ($format === self::JSON) {
unset($config['jsonReplacer']);
}
$cfg = $this->hashExportConfig ? Json::encode($config) : '';
$intCfg = empty($this->hashExportConfig) ? 0 : 1;
$dataToHash = $this->moduleId . $setting['filename'] . $mime . $encoding . $bom . $intCfg . $cfg;
$hash = Yii::$app->security->hashData($dataToHash, $this->_module->exportEncryptSalt);
$items[] = [
'label' => $label,
'url' => '#',
'linkOptions' => [
'class' => 'export-' . $format,
'data-mime' => $mime,
'data-hash' => $hash,
'data-hash-export-config' => $intCfg,
'data-css-styles' => $cssStyles,
],
'options' => $setting['options'],
];
}
$itemsBefore = ArrayHelper::getValue($this->export, 'itemsBefore', []);
$itemsAfter = ArrayHelper::getValue($this->export, 'itemsAfter', []);
$items = ArrayHelper::merge($itemsBefore, $items, $itemsAfter);
$opts = [
'label' => $title,
'dropdown' => ['items' => $items, 'encodeLabels' => false, 'options' => $menuOptions],
'encodeLabel' => false,
];
Html::addCssClass($this->exportContainer, 'btn-group');
if ($isBs4) {
$opts['buttonOptions'] = $options;
$opts['renderContainer'] = false;
/** @noinspection PhpUnnecessaryFullyQualifiedNameInspection */
$out = Html::tag('div', \kartik\bs4dropdown\ButtonDropdown::widget($opts), $this->exportContainer);
} else {
$opts['options'] = $options;
$opts['containerOptions'] = $this->exportContainer;
/** @noinspection PhpUnnecessaryFullyQualifiedNameInspection */
$out = \yii\bootstrap\ButtonDropdown::widget($opts);
}
return $out;
}
/**
* @inheritdoc
*/
public function renderTableHeader()
{
$cells = [];
foreach ($this->columns as $index => $column) {
/* @var DataColumn $column */
if ($this->resizableColumns && $this->persistResize) {
$column->headerOptions['data-resizable-column-id'] = "kv-col-{$index}";
}
$cells[] = $column->renderHeaderCell();
}
$content = Html::tag('tr', implode('', $cells), $this->headerRowOptions);
if ($this->filterPosition == self::FILTER_POS_HEADER) {
$content = $this->renderFilters() . $content;
} elseif ($this->filterPosition == self::FILTER_POS_BODY) {
$content .= $this->renderFilters();
}
return "<thead>\n" .
$this->generateRows($this->beforeHeader) . "\n" .
$content . "\n" .
$this->generateRows($this->afterHeader) . "\n" .
'</thead>';
}
/**
* @inheritdoc
*/
public function renderTableFooter()
{
$content = parent::renderTableFooter();
return strtr(
$content,
[
'<tfoot>' => "<tfoot>\n" . $this->generateRows($this->beforeFooter),
'</tfoot>' => $this->generateRows($this->afterFooter) . "\n</tfoot>",
]
);
}
/**
* @inheritdoc
*/
public function renderColumnGroup()
{
$requireColumnGroup = false;
foreach ($this->columns as $column) {
/* @var $column Column */
if (!empty($column->options)) {
$requireColumnGroup = true;
break;
}
}
if ($requireColumnGroup) {
$cols = [];
foreach ($this->columns as $column) {
//Skip column with groupedRow
/** @noinspection PhpUndefinedFieldInspection */
if (property_exists($column, 'groupedRow') && $column->groupedRow) {
continue;
}
$cols[] = Html::tag('col', '', $column->options);
}
return Html::tag('colgroup', implode("\n", $cols));
} else {
return false;
}
}
/**
* @inheritdoc
*/
public function renderSummary()
{
$count = $this->dataProvider->getCount();
if ($count <= 0) {
return '';
}
$summaryOptions = $this->summaryOptions;
$tag = ArrayHelper::remove($summaryOptions, 'tag', 'div');
$configItems = [
'item' => $this->itemLabelSingle,
'items' => $this->itemLabelPlural,
'items-few' => $this->itemLabelFew,
'items-many' => $this->itemLabelMany,
'items-acc' => $this->itemLabelAccusative,
];
$pagination = $this->dataProvider->getPagination();
if ($pagination !== false) {
$totalCount = $this->dataProvider->getTotalCount();
$begin = $pagination->getPage() * $pagination->pageSize + 1;
$end = $begin + $count - 1;
if ($begin > $end) {
$begin = $end;
}
$page = $pagination->getPage() + 1;
$pageCount = $pagination->pageCount;
$configSummary = [
'begin' => $begin,
'end' => $end,
'count' => $count,
'totalCount' => $totalCount,
'page' => $page,
'pageCount' => $pageCount,
];
if (($summaryContent = $this->summary) === null) {
return Html::tag($tag, Yii::t('kvgrid',
'Showing <b>{begin, number}-{end, number}</b> of <b>{totalCount, number}</b> {totalCount, plural, one{{item}} other{{items}}}.',
$configSummary + $configItems
), $summaryOptions);
}
} else {
$begin = $page = $pageCount = 1;
$end = $totalCount = $count;
$configSummary = [
'begin' => $begin,
'end' => $end,
'count' => $count,
'totalCount' => $totalCount,
'page' => $page,
'pageCount' => $pageCount,
];
if (($summaryContent = $this->summary) === null) {
return Html::tag($tag,
Yii::t('kvgrid', 'Total <b>{count, number}</b> {count, plural, one{{item}} other{{items}}}.',
$configSummary + $configItems
), $summaryOptions);
}
}
return Yii::$app->getI18n()->format($summaryContent, $configSummary, Yii::$app->language);
}
/**
* Initialize the module based on module identifier
* @throws InvalidConfigException
*/
protected function initModule()
{
if (!isset($this->moduleId)) {
$this->_module = Module::getInstance();
if (isset($this->_module)) {
$this->moduleId = $this->_module->id;
return;
}
$this->moduleId = Module::MODULE;
}
$this->_module = Config::getModule($this->moduleId, Module::class);
if (isset($this->bsVersion)) {
return;
}
}
/**
* Initialize grid export.
* @throws InvalidConfigException
*/
protected function initExport()
{
if ($this->export === false) {
return;
}
$this->exportConversions = array_replace_recursive(
[
['from' => self::ICON_ACTIVE, 'to' => Yii::t('kvgrid', 'Active')],
['from' => self::ICON_INACTIVE, 'to' => Yii::t('kvgrid', 'Inactive')],
],
$this->exportConversions
);
if (!isset($this->export['fontAwesome'])) {
$this->export['fontAwesome'] = false;
}
$isFa = $this->export['fontAwesome'];
$isBs4 = $this->isBs4();
$this->export = array_replace_recursive(
[
'label' => '',
'icon' => $isFa ? 'fa fa-share-square-o' : ($this->isBs4() ? 'fas fa-external-link-alt' : 'glyphicon glyphicon-export'),
'messages' => [
'allowPopups' => Yii::t(
'kvgrid',
'Disable any popup blockers in your browser to ensure proper download.'
),
'confirmDownload' => Yii::t('kvgrid', 'Ok to proceed?'),
'downloadProgress' => Yii::t('kvgrid', 'Generating the export file. Please wait...'),
'downloadComplete' => Yii::t(
'kvgrid',
'Request submitted! You may safely close this dialog after saving your downloaded file.'
),
],
'options' => ['class' => 'btn ' . $this->_defaultBtnCss, 'title' => Yii::t('kvgrid', 'Export')],
'menuOptions' => ['class' => 'dropdown-menu dropdown-menu-right '],
'skipExportElements' => ['.sr-only', '.hide'],
],
$this->export
);
if (!isset($this->export['header'])) {
$this->export['header'] = '<li role="presentation" class="dropdown-header">' .
Yii::t('kvgrid', 'Export Page Data') . '</li>';
}
if (!isset($this->export['headerAll'])) {
$this->export['headerAll'] = '<li role="presentation" class="dropdown-header">' .
Yii::t('kvgrid', 'Export All Data') . '</li>';
}
$title = empty($this->caption) ? Yii::t('kvgrid', 'Grid Export') : $this->caption;
$pdfHeader = [
'L' => [
'content' => Yii::t('kvgrid', 'Yii2 Grid Export (PDF)'),
'font-size' => 8,
'color' => '#333333',
],
'C' => [
'content' => $title,
'font-size' => 16,
'color' => '#333333',
],
'R' => [
'content' => Yii::t('kvgrid', 'Generated') . ': ' . date('D, d-M-Y'),
'font-size' => 8,
'color' => '#333333',
],
];
$pdfFooter = [
'L' => [
'content' => Yii::t('kvgrid', '© Krajee Yii2 Extensions'),
'font-size' => 8,
'font-style' => 'B',
'color' => '#999999',
],
'R' => [
'content' => '[ {PAGENO} ]',
'font-size' => 10,
'font-style' => 'B',
'font-family' => 'serif',
'color' => '#333333',
],
'line' => true,
];
$cssStyles = [
'.kv-group-even' => ['background-color' => '#f0f1ff'],
'.kv-group-odd' => ['background-color' => '#f9fcff'],
'.kv-grouped-row' => ['background-color' => '#fff0f5', 'font-size' => '1.3em', 'padding' => '10px'],
'.kv-table-caption' => [
'border' => '1px solid #ddd',
'border-bottom' => 'none',
'font-size' => '1.5em',
'padding' => '8px',
],
'.kv-table-footer' => ['border-top' => '4px double #ddd', 'font-weight' => 'bold'],
'.kv-page-summary td' => [
'background-color' => '#ffeeba',
'border-top' => '4px double #ddd',
'font-weight' => 'bold',
],
'.kv-align-center' => ['text-align' => 'center'],
'.kv-align-left' => ['text-align' => 'left'],
'.kv-align-right' => ['text-align' => 'right'],
'.kv-align-top' => ['vertical-align' => 'top'],
'.kv-align-bottom' => ['vertical-align' => 'bottom'],
'.kv-align-middle' => ['vertical-align' => 'middle'],
'.kv-editable-link' => [
'color' => '#428bca',
'text-decoration' => 'none',
'background' => 'none',
'border' => 'none',
'border-bottom' => '1px dashed',
'margin' => '0',
'padding' => '2px 1px',
],
];
$defaultExportConfig = [
self::HTML => [
'label' => Yii::t('kvgrid', 'HTML'),
'icon' => $isBs4 ? 'fas fa-file-alt' : ($isFa ? 'fa fa-file-text' : 'glyphicon glyphicon-save'),
'iconOptions' => ['class' => 'text-info'],
'showHeader' => true,
'showPageSummary' => true,
'showFooter' => true,
'showCaption' => true,
'filename' => Yii::t('kvgrid', 'grid-export'),
'alertMsg' => Yii::t('kvgrid', 'The HTML export file will be generated for download.'),
'options' => ['title' => Yii::t('kvgrid', 'Hyper Text Markup Language')],
'mime' => 'text/plain',
'cssStyles' => $cssStyles,
'config' => [
'cssFile' => $this->isBs4() ?
[
'https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css',
//'https://use.fontawesome.com/releases/v5.3.1/css/all.css',
// Use CDN version to avoid impact China site. It also work for worldwide
'https://cdn.bootcss.com/font-awesome/5.3.1/css/all.css',
] :
['https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css'],
],
],
self::CSV => [
'label' => Yii::t('kvgrid', 'CSV'),
'icon' => $isBs4 ? 'fas fa-file-code' : ($isFa ? 'fa fa-file-code-o' : 'glyphicon glyphicon-floppy-open'),
'iconOptions' => ['class' => 'text-primary'],
'showHeader' => true,
'showPageSummary' => true,
'showFooter' => true,
'showCaption' => true,
'filename' => Yii::t('kvgrid', 'grid-export'),
'alertMsg' => Yii::t('kvgrid', 'The CSV export file will be generated for download.'),
'options' => ['title' => Yii::t('kvgrid', 'Comma Separated Values')],
'mime' => 'application/csv',
'config' => [
'colDelimiter' => ',',
'rowDelimiter' => "\r\n",
],
],
self::TEXT => [
'label' => Yii::t('kvgrid', 'Text'),
'icon' => $isBs4 ? 'far fa-file-alt' : ($isFa ? 'fa fa-file-text-o' : 'glyphicon glyphicon-floppy-save'),
'iconOptions' => ['class' => 'text-muted'],
'showHeader' => true,
'showPageSummary' => true,
'showFooter' => true,
'showCaption' => true,
'filename' => Yii::t('kvgrid', 'grid-export'),
'alertMsg' => Yii::t('kvgrid', 'The TEXT export file will be generated for download.'),
'options' => ['title' => Yii::t('kvgrid', 'Tab Delimited Text')],
'mime' => 'text/plain',
'config' => [
'colDelimiter' => "\t",
'rowDelimiter' => "\r\n",
],
],
self::EXCEL => [
'label' => Yii::t('kvgrid', 'Excel'),
'icon' => $isBs4 ? 'far fa-file-excel' : ($isFa ? 'fa fa-file-excel-o' : 'glyphicon glyphicon-floppy-remove'),
'iconOptions' => ['class' => 'text-success'],
'showHeader' => true,
'showPageSummary' => true,
'showFooter' => true,
'showCaption' => true,
'filename' => Yii::t('kvgrid', 'grid-export'),
'alertMsg' => Yii::t('kvgrid', 'The EXCEL export file will be generated for download.'),
'options' => ['title' => Yii::t('kvgrid', 'Microsoft Excel 95+')],
'mime' => 'application/vnd.ms-excel',
'cssStyles' => $cssStyles,
'config' => [
'worksheet' => Yii::t('kvgrid', 'ExportWorksheet'),
'cssFile' => '',
],
],
self::PDF => [
'label' => Yii::t('kvgrid', 'PDF'),
'icon' => $isBs4 ? 'far fa-file-pdf' : ($isFa ? 'fa fa-file-pdf-o' : 'glyphicon glyphicon-floppy-disk'),
'iconOptions' => ['class' => 'text-danger'],
'showHeader' => true,
'showPageSummary' => true,
'showFooter' => true,
'showCaption' => true,
'filename' => Yii::t('kvgrid', 'grid-export'),
'alertMsg' => Yii::t('kvgrid', 'The PDF export file will be generated for download.'),
'options' => ['title' => Yii::t('kvgrid', 'Portable Document Format')],
'mime' => 'application/pdf',
'cssStyles' => $cssStyles,
'config' => [
'mode' => 'UTF-8',
'format' => 'A4-L',
'destination' => 'D',
'marginTop' => 20,
'marginBottom' => 20,
'cssInline' => '.kv-wrap{padding:20px}',
'methods' => [
'SetHeader' => [
['odd' => $pdfHeader, 'even' => $pdfHeader],
],
'SetFooter' => [
['odd' => $pdfFooter, 'even' => $pdfFooter],
],
],
'options' => [
'title' => $title,
'subject' => Yii::t('kvgrid', 'PDF export generated by kartik-v/yii2-grid extension'),
'keywords' => Yii::t('kvgrid', 'krajee, grid, export, yii2-grid, pdf'),
],
'contentBefore' => '',
'contentAfter' => '',
],
],
self::JSON => [
'label' => Yii::t('kvgrid', 'JSON'),
'icon' => $isBs4 ? 'far fa-file-code' : ($isFa ? 'fa fa-file-code-o' : 'glyphicon glyphicon-floppy-open'),
'iconOptions' => ['class' => 'text-warning'],
'showHeader' => true,
'showPageSummary' => true,
'showFooter' => true,
'showCaption' => true,
'filename' => Yii::t('kvgrid', 'grid-export'),
'alertMsg' => Yii::t('kvgrid', 'The JSON export file will be generated for download.'),
'options' => ['title' => Yii::t('kvgrid', 'JavaScript Object Notation')],
'mime' => 'application/json',
'config' => [
'colHeads' => [],
'slugColHeads' => false,
'jsonReplacer' => new JsExpression("function(k,v){return typeof(v)==='string'?$.trim(v):v}"),
'indentSpace' => 4,
],
],
];
// Remove PDF if dependency is not loaded.
if (!class_exists('\\kartik\\mpdf\\Pdf')) {
unset($defaultExportConfig[self::PDF]);
}
$this->exportConfig = self::parseExportConfig($this->exportConfig, $defaultExportConfig);
}
/**
* Initialize toggle data button options.
* @throws InvalidConfigException
*/
protected function initToggleData()
{
if (!$this->toggleData) {
return;
}
$isBs4 = $this->isBs4();
$defBtnCss = 'btn ' . $this->_defaultBtnCss;
$defaultOptions = [
'maxCount' => 10000,
'minCount' => 500,
'confirmMsg' => Yii::t(
'kvgrid',
'There are {totalCount} records. Are you sure you want to display them all?',
['totalCount' => number_format($this->dataProvider->getTotalCount())]
),
'all' => [
'icon' => $isBs4 ? 'fas fa-expand' : 'glyphicon glyphicon-resize-full',
'label' => Yii::t('kvgrid', 'All'),
'class' => $defBtnCss,
'title' => Yii::t('kvgrid', 'Show all data'),
],
'page' => [
'icon' => $isBs4 ? 'fas fa-compress' : 'glyphicon glyphicon-resize-small',
'label' => Yii::t('kvgrid', 'Page'),
'class' => $defBtnCss,
'title' => Yii::t('kvgrid', 'Show first page data'),
],
];
$this->toggleDataOptions = array_replace_recursive($defaultOptions, $this->toggleDataOptions);
$tag = $this->_isShowAll ? 'page' : 'all';
$options = $this->toggleDataOptions[$tag];
$this->toggleDataOptions[$tag]['id'] = $this->_toggleButtonId;
$icon = ArrayHelper::remove($this->toggleDataOptions[$tag], 'icon', '');
$label = !isset($options['label']) ? $defaultOptions[$tag]['label'] : $options['label'];
if (!empty($icon)) {
$label = "<i class='{$icon}'></i> " . $label;
}
$this->toggleDataOptions[$tag]['label'] = $label;
if (!isset($this->toggleDataOptions[$tag]['title'])) {
$this->toggleDataOptions[$tag]['title'] = $defaultOptions[$tag]['title'];
}
$this->toggleDataOptions[$tag]['data-pjax'] = $this->pjax ? 'true' : false;
}
/**
* Initialize bootstrap specific styling.
* @throws InvalidConfigException
*/
protected function initBootstrapStyle()
{
Html::addCssClass($this->tableOptions, 'kv-grid-table');
if (!$this->bootstrap) {
return;
}
Html::addCssClass($this->tableOptions, 'table');
if ($this->hover) {
Html::addCssClass($this->tableOptions, 'table-hover');
}
if ($this->bordered) {
Html::addCssClass($this->tableOptions, 'table-bordered');
}
if ($this->striped) {
Html::addCssClass($this->tableOptions, 'table-striped');
}
if ($this->condensed) {
$this->addCssClass($this->tableOptions, self::BS_TABLE_CONDENSED);
}
if ($this->floatHeader) {
if ($this->perfectScrollbar) {
$this->floatOverflowContainer = true;
}
if ($this->floatOverflowContainer) {
$this->responsive = false;
Html::addCssClass($this->containerOptions, 'kv-grid-wrapper');
}
}
if ($this->responsive) {
Html::addCssClass($this->containerOptions, 'table-responsive');
}
if ($this->responsiveWrap) {
Html::addCssClass($this->tableOptions, 'kv-table-wrap');
}
}
/**
* Initialize table header.
*/
protected function initHeader()
{
if ($this->filterPosition === self::FILTER_POS_HEADER) {
// Float header plugin misbehaves when filter is placed on the first row.
// So disable it when `filterPosition` is `header`.
$this->floatHeader = false;
}
}
/**
* Initialize the grid layout.
* @throws InvalidConfigException
*/
protected function initLayout()
{
Html::addCssClass($this->filterRowOptions, 'skip-export');
if ($this->resizableColumns && $this->persistResize) {
$key = empty($this->resizeStorageKey) ? Yii::$app->user->id : $this->resizeStorageKey;
$gridId = empty($this->options['id']) ? $this->getId() : $this->options['id'];
$this->containerOptions['data-resizable-columns-id'] = (empty($key) ? "kv-{$gridId}" : "kv-{$key}-{$gridId}");
}
if ($this->hideResizeMobile) {
Html::addCssClass($this->options, 'hide-resize');
}
$this->replaceLayoutTokens([
'{toolbarContainer}' => $this->renderToolbarContainer(),
'{toolbar}' => $this->renderToolbar(),
'{export}' => $this->renderExport(),
'{toggleData}' => $this->renderToggleData(),
'{items}' => Html::tag('div', '{items}', $this->containerOptions),
]);
if (is_array($this->replaceTags) && !empty($this->replaceTags)) {
foreach ($this->replaceTags as $key => $value) {
if ($value instanceof \Closure) {
$value = call_user_func($value, $this);
}
$this->layout = str_replace($key, $value, $this->layout);
}
}
}
/**
* Replace layout tokens
* @param array $pairs the token to find and its replaced value as key value pairs
*/
protected function replaceLayoutTokens($pairs)
{
foreach ($pairs as $token => $replace) {
if (strpos($this->layout, $token) !== false) {
$this->layout = str_replace($token, $replace, $this->layout);
}
}
}
/**
* Begins the pjax widget rendering
*/
protected function beginPjax()
{
$view = $this->getView();
$container = 'jQuery("#' . $this->pjaxSettings['options']['id'] . '")';
$js = $container;
if (ArrayHelper::getValue($this->pjaxSettings, 'neverTimeout', true)) {
$js .= ".on('pjax:timeout', function(e){e.preventDefault()})";
}
$loadingCss = ArrayHelper::getValue($this->pjaxSettings, 'loadingCssClass', 'kv-grid-loading');
$postPjaxJs = "setTimeout({$this->_gridClientFunc}, 2500);";
$pjaxCont = '$("#' . $this->pjaxSettings['options']['id'] . '")';
if ($loadingCss !== false) {
if ($loadingCss === true) {
$loadingCss = 'kv-grid-loading';
}
$js .= ".on('pjax:send', function(){{$pjaxCont}.addClass('{$loadingCss}')})";
$postPjaxJs .= "{$pjaxCont}.removeClass('{$loadingCss}');";
}
$postPjaxJs .= "\n" . $this->_toggleScript;
if (!empty($postPjaxJs)) {
$event = 'pjax:complete.' . hash('crc32', $postPjaxJs);
$js .= ".off('{$event}').on('{$event}', function(){{$postPjaxJs}})";
}
if ($js != $container) {
$view->registerJs("{$js};");
}
Pjax::begin($this->pjaxSettings['options']);
echo '<div class="kv-loader-overlay"><div class="kv-loader"></div></div>';
echo ArrayHelper::getValue($this->pjaxSettings, 'beforeGrid', '');
}
/**
* Completes the pjax widget rendering
*/
protected function endPjax()
{
echo ArrayHelper::getValue($this->pjaxSettings, 'afterGrid', '');
Pjax::end();
}
/**
* Initializes and sets the grid panel layout based on the [[template]] and [[panel]] settings.
* @throws InvalidConfigException
*/
protected function initPanel()
{
if (!$this->bootstrap || !is_array($this->panel) || empty($this->panel)) {
return;
}
$options = ArrayHelper::getValue($this->panel, 'options', []);
$type = ArrayHelper::getValue($this->panel, 'type', 'default');
$heading = ArrayHelper::getValue($this->panel, 'heading', '');
$footer = ArrayHelper::getValue($this->panel, 'footer', '');
$before = ArrayHelper::getValue($this->panel, 'before', '');
$after = ArrayHelper::getValue($this->panel, 'after', '');
$headingOptions = ArrayHelper::getValue($this->panel, 'headingOptions', []);
$titleOptions = ArrayHelper::getValue($this->panel, 'titleOptions', []);
$footerOptions = ArrayHelper::getValue($this->panel, 'footerOptions', []);
$beforeOptions = ArrayHelper::getValue($this->panel, 'beforeOptions', []);
$afterOptions = ArrayHelper::getValue($this->panel, 'afterOptions', []);
$summaryOptions = ArrayHelper::getValue($this->panel, 'summaryOptions', []);
$panelHeading = '';
$panelBefore = '';
$panelAfter = '';
$panelFooter = '';
$isBs4 = $this->isBs4();
if (isset($this->panelPrefix)) {
static::initCss($options, $this->panelPrefix . $type);
} else {
$this->addCssClass($options, self::BS_PANEL);
Html::addCssClass($options, $isBs4 ? "border-{$type}" : "panel-{$type}");
}
static::initCss($summaryOptions, $this->getCssClass(self::BS_PULL_RIGHT));
$titleTag = ArrayHelper::remove($titleOptions, 'tag', ($isBs4 ? 'h5' : 'h3'));
static::initCss($titleOptions, $isBs4 ? 'm-0' : $this->getCssClass(self::BS_PANEL_TITLE));
if ($heading !== false) {
$color = $isBs4 ? ($type === 'default' ? ' bg-light' : " text-white bg-{$type}") : '';
static::initCss($headingOptions, $this->getCssClass(self::BS_PANEL_HEADING) . $color);
$panelHeading = Html::tag('div', $this->panelHeadingTemplate, $headingOptions);
}
if ($footer !== false) {
static::initCss($footerOptions, $this->getCssClass(self::BS_PANEL_FOOTER));
$content = strtr($this->panelFooterTemplate, ['{footer}' => $footer]);
$panelFooter = Html::tag('div', $content, $footerOptions);
}
if ($before !== false) {
static::initCss($beforeOptions, 'kv-panel-before');
$content = strtr($this->panelBeforeTemplate, ['{before}' => $before]);
$panelBefore = Html::tag('div', $content, $beforeOptions);
}
if ($after !== false) {
static::initCss($afterOptions, 'kv-panel-after');
$content = strtr($this->panelAfterTemplate, ['{after}' => $after]);
$panelAfter = Html::tag('div', $content, $afterOptions);
}
$out = strtr($this->panelTemplate, [
'{panelHeading}' => $panelHeading,
'{type}' => $type,
'{panelFooter}' => $panelFooter,
'{panelBefore}' => $panelBefore,
'{panelAfter}' => $panelAfter,
]);
$this->layout = Html::tag('div', strtr($out, [
'{title}' => Html::tag($titleTag, $heading, $titleOptions),
'{summary}' => Html::tag('div', '{summary}', $summaryOptions),
]), $options);
}
/**
* Generates the toolbar.
*
* @return string
*/
protected function renderToolbar()
{
if (empty($this->toolbar) || (!is_string($this->toolbar) && !is_array($this->toolbar))) {
return '';
}
if (is_string($this->toolbar)) {
return $this->toolbar;
}
$toolbar = '';
foreach ($this->toolbar as $item) {
if (is_array($item)) {
$content = ArrayHelper::getValue($item, 'content', '');
$options = ArrayHelper::getValue($item, 'options', []);
static::initCss($options, 'btn-group');
$toolbar .= Html::tag('div', $content, $options);
} else {
$toolbar .= "\n{$item}";
}
}
return $toolbar;
}
/**
* Generates the toolbar container with the toolbar
* @throws InvalidConfigException
*/
protected function renderToolbarContainer()
{
$tag = ArrayHelper::remove($this->toolbarContainerOptions, 'tag', 'div');
/**
* allow to override the float declaration:
* forcing float-right only if no float is defined in toolbarContainerOptions
*/
if (
!strpos($this->toolbarContainerOptions['class'], $this->getCssClass(self::BS_PULL_RIGHT))
&& !strpos($this->toolbarContainerOptions['class'], $this->getCssClass(self::BS_PULL_LEFT))
) {
$this->addCssClass($this->toolbarContainerOptions, self::BS_PULL_RIGHT);
}
return Html::tag($tag, $this->renderToolbar(), $this->toolbarContainerOptions);
}
/**
* Generate HTML markup for additional table rows for header and/or footer.
*
* @param array|string $data the table rows configuration
*
* @return string
*/
protected function generateRows($data)
{
if (empty($data)) {
return '';
}
if (is_string($data)) {
return $data;
}
$rows = '';
if (is_array($data)) {
foreach ($data as $row) {
if (empty($row['columns'])) {
continue;
}
$rowOptions = ArrayHelper::getValue($row, 'options', []);
$rows .= Html::beginTag('tr', $rowOptions);
foreach ($row['columns'] as $col) {
$colOptions = ArrayHelper::getValue($col, 'options', []);
$colContent = ArrayHelper::getValue($col, 'content', '');
$tag = ArrayHelper::getValue($col, 'tag', 'th');
$rows .= "\t" . Html::tag($tag, $colContent, $colOptions) . "\n";
}
$rows .= Html::endTag('tr') . "\n";
}
}
return $rows;
}
/**
* Generate toggle data client validation script.
*/
protected function genToggleDataScript()
{
$this->_toggleScript = '';
if (!$this->toggleData) {
return;
}
$minCount = ArrayHelper::getValue($this->toggleDataOptions, 'minCount', 0);
if (!$minCount || $minCount >= $this->dataProvider->getTotalCount()) {
return;
}
$view = $this->getView();
$opts = Json::encode(
[
'id' => $this->_toggleButtonId,
'pjax' => $this->pjax ? 1 : 0,
'mode' => $this->_isShowAll ? 'all' : 'page',
'msg' => ArrayHelper::getValue($this->toggleDataOptions, 'confirmMsg', ''),
'lib' => new JsExpression(
ArrayHelper::getValue($this->krajeeDialogSettings, 'libName', 'krajeeDialog')
),
]
);
$this->_toggleOptionsVar = 'kvTogOpts_' . hash('crc32', $opts);
$view->registerJs("{$this->_toggleOptionsVar}={$opts};");
GridToggleDataAsset::register($view);
$this->_toggleScript = "kvToggleData({$this->_toggleOptionsVar});";
}
/**
* Registers client assets for the [[GridView]] widget.
* @throws \Exception
*/
protected function registerAssets()
{
$view = $this->getView();
$script = '';
if ($this->bootstrap) {
GridViewAsset::register($view);
}
Dialog::widget($this->krajeeDialogSettings);
$gridId = $this->options['id'];
$NS = '.' . str_replace('-', '_', $gridId);
if ($this->export !== false && is_array($this->export) && !empty($this->export)) {
GridExportAsset::register($view);
if (!isset($this->_module->downloadAction)) {
$action = ["/{$this->moduleId}/export/download"];
} else {
$action = (array)$this->_module->downloadAction;
}
$gridOpts = Json::encode(
[
'gridId' => $gridId,
'action' => Url::to($action),
'module' => $this->moduleId,
'encoding' => ArrayHelper::getValue($this->export, 'encoding', 'utf-8'),
'bom' => (int)ArrayHelper::getValue($this->export, 'bom', 1),
'target' => ArrayHelper::getValue($this->export, 'target', self::TARGET_BLANK),
'messages' => $this->export['messages'],
'exportConversions' => $this->exportConversions,
'skipExportElements' => $this->export['skipExportElements'],
'showConfirmAlert' => ArrayHelper::getValue($this->export, 'showConfirmAlert', true),
]
);
$gridOptsVar = 'kvGridExp_' . hash('crc32', $gridOpts);
$view->registerJs("var {$gridOptsVar}={$gridOpts};");
foreach ($this->exportConfig as $format => $setting) {
$id = "jQuery('#{$gridId} .export-{$format}')";
$genOpts = Json::encode(
[
'filename' => $setting['filename'],
'showHeader' => $setting['showHeader'],
'showPageSummary' => $setting['showPageSummary'],
'showFooter' => $setting['showFooter'],
]
);
$genOptsVar = 'kvGridExp_' . hash('crc32', $genOpts);
$view->registerJs("var {$genOptsVar}={$genOpts};");
$expOpts = Json::encode(
[
'dialogLib' => ArrayHelper::getValue($this->krajeeDialogSettings, 'libName', 'krajeeDialog'),
'gridOpts' => new JsExpression($gridOptsVar),
'genOpts' => new JsExpression($genOptsVar),
'alertMsg' => ArrayHelper::getValue($setting, 'alertMsg', false),
'config' => ArrayHelper::getValue($setting, 'config', []),
]
);
$expOptsVar = 'kvGridExp_' . hash('crc32', $expOpts);
$view->registerJs("var {$expOptsVar}={$expOpts};");
$script .= "{$id}.gridexport({$expOptsVar});";
}
}
$contId = '#' . $this->containerOptions['id'];
$container = "jQuery('{$contId}')";
if ($this->resizableColumns) {
$rcDefaults = [];
if ($this->persistResize) {
GridResizeStoreAsset::register($view);
} else {
$rcDefaults = ['store' => null];
}
$rcOptions = Json::encode(array_replace_recursive($rcDefaults, $this->resizableColumnsOptions));
GridResizeColumnsAsset::register($view);
$script .= "{$container}.resizableColumns('destroy').resizableColumns({$rcOptions});";
}
if ($this->floatHeader) {
GridFloatHeadAsset::register($view);
// fix floating header for IE browser when using group grid functionality
$skipCss = '.kv-grid-group-row,.kv-group-header,.kv-group-footer'; // skip these CSS for IE
$js = 'function($table){return $table.find("tbody tr:not(' . $skipCss . '):visible:first>*");}';
$opts = [
'floatTableClass' => 'kv-table-float',
'floatContainerClass' => 'kv-thead-float',
'getSizingRow' => new JsExpression($js),
];
if ($this->floatOverflowContainer) {
$opts['scrollContainer'] = new JsExpression("function(){return {$container};}");
}
$this->floatHeaderOptions = array_replace_recursive($opts, $this->floatHeaderOptions);
$opts = Json::encode($this->floatHeaderOptions);
$script .= "jQuery('#{$gridId} .kv-grid-table:first').floatThead({$opts});";
// integrate resizeableColumns with floatThead
if ($this->resizableColumns) {
$script .= "{$container}.off('{$NS}').on('column:resize{$NS}', function(e){" .
"jQuery('#{$gridId} .kv-grid-table:nth-child(2)').floatThead('reflow');" .
'});';
}
}
$psVar = 'ps_' . Inflector::slug($this->containerOptions['id'], '_');
if ($this->perfectScrollbar) {
GridPerfectScrollbarAsset::register($view);
$script .= "var {$psVar} = new PerfectScrollbar('{$contId}', " .
Json::encode($this->perfectScrollbarOptions) . ');';
}
$this->genToggleDataScript();
$script .= $this->_toggleScript;
$this->_gridClientFunc = 'kvGridInit_' . hash('crc32', $script);
$this->options['data-krajee-grid'] = $this->_gridClientFunc;
$this->options['data-krajee-ps'] = $psVar;
$view->registerJs("var {$this->_gridClientFunc}=function(){\n{$script}\n};\n{$this->_gridClientFunc}();");
}
}