├── .gitignore
├── CHANGELOG.md
├── DataColumn.php
├── GridView.php
├── LinkPageSizer.php
├── README.md
├── TotalColumn.php
├── actions
├── ResizableColumnsAction.php
└── VisibleColumnsAction.php
├── assets
├── GridViewAsset.php
└── SortableAsset.php
├── base
└── BaseAction.php
├── components
├── BaseManager.php
└── Manager.php
├── composer.json
├── docs
├── screenshot1.png
├── screenshot2.png
└── screenshot3.png
├── interfaces
├── ManagerInterface.php
└── StorageInterface.php
├── resources
├── css
│ ├── resizable-columns.css
│ └── resizable-columns.min.css
└── js
│ ├── resizable-columns.js
│ └── resizable-columns.min.js
└── widgets
└── VisibleColumnsWidget.php
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # yii2-grid
2 | ===========
3 |
4 | v1.1.6 [2017-06-09]
5 | -------------------
6 |
7 | - Fixed #4: README section *Adding ability resize width of columns*. (githubjeka)
8 | - Fixed #3: error `unknown property` if column is not `yii\grid\DataColumn` class. (githubjeka)
9 | - Enhancement: CHANGELOG.
10 | - Fixed: Failed to instantiate component or class "gridManager".
11 | - Enhancement #5: Update README section *Adding ability display all rows of grid*.
12 |
13 | v1.1.5 [2017-04-22]
14 | -------------------
15 |
16 | - Added ability formatting a footer value.
17 | - Fixed `calculateSummary()` method.
18 |
19 | v1.1.4 [2016-02-27]
20 | -------------------
21 |
22 | - Added keep last modified the page sizer.
23 |
24 | v1.1.3 [2016-02-08]
25 | -------------------
26 |
27 | - Added ability resizing columns.
28 | - Add class action `bupy7\grid\actions\ResizableColumnsAction`.
29 | - Moved base functional of grid actions to `bupy7\grid\base\BaseAction`.
30 | - Moved screenshots to `docs` directory.
31 | - Release of `resizable columns jQuery plugin` to Grid.
32 |
33 | v1.1.2 [2015-11-21]
34 | -------------------
35 |
36 | - Fix of panel HTML-template.
37 |
38 | v1.1.1 [2015-11-15]
39 | -------------------
40 |
41 | - Added ability sortering of visible a columns.
42 |
43 | v1.1.0 [2015-11-13]
44 | -------------------
45 |
46 | - Added ability realization custom storage (session, database and etc).
47 | - Rename manager class `GridSettings` to `Manager`.
48 |
49 | v1.0.1 [2015-09-01]
50 | -------------------
51 |
52 | - Added ability not add footer of grid column.
53 |
54 | v1.0.0 [2015-07-24]
55 | -------------------
56 |
57 | - First release.
58 |
--------------------------------------------------------------------------------
/DataColumn.php:
--------------------------------------------------------------------------------
1 |
8 | * @since 1.0.1
9 | */
10 | class DataColumn extends \yii\grid\DataColumn
11 | {
12 | /**
13 | * @var boolean Whether set this property `false` then footer column will not added.
14 | * @see renderFooterCell()
15 | */
16 | public $footerVisible = true;
17 |
18 | /**
19 | * @inheritdoc
20 | */
21 | public function renderFooterCell()
22 | {
23 | if ($this->footerVisible) {
24 | return parent::renderFooterCell();
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/GridView.php:
--------------------------------------------------------------------------------
1 |
71 | {panelHeading}
72 |
{items}
73 | {panelFooter}
74 |
75 | HTML;
76 | /**
77 | * @var boolean Whether set 'true' will be displays heading of panel.
78 | */
79 | public $panelHeading = true;
80 | /**
81 | * @var string HTML-template for heading of panel.
82 | * Allows uses:
83 | * - `{items}` - the summary section. See [[renderSummary()]].
84 | * - `{summary}` - the summary section. See [[renderSummary()]].
85 | * - `{pager}` - the pager. See [[renderPager()]].
86 | * - `{pageSizer}` - the page size. See [[renderPageSizer]].
87 | * - `{errors}` - the filter model error summary. See [[renderErrors()]].
88 | * - `{sorter}` - the sorter. See [[renderSorter()]].
89 | * @see http://getbootstrap.com/components/#panels-heading
90 | */
91 | public $panelHeadingTemplate = <<{pageSizer}
93 |
94 | HTML;
95 | /**
96 | * @var boolean Whether set 'true' will be displays footer of panel.
97 | */
98 | public $panelFooter = true;
99 | /**
100 | * @var string HTML-template for footer of panel.
101 | * Allows uses:
102 | * - `{items}` - the summary section. See [[renderSummary()]].
103 | * - `{summary}` - the summary section. See [[renderSummary()]].
104 | * - `{pager}` - the pager. See [[renderPager()]].
105 | * - `{pageSizer}` - the page size. See [[renderPageSizer]].
106 | * - `{errors}` - the filter model error summary. See [[renderErrors()]].
107 | * - `{sorter}` - the sorter. See [[renderSorter()]].
108 | * @see http://getbootstrap.com/components/#panels-footer
109 | */
110 | public $panelFooterTemplate = <<
112 | {summary}
113 | {pager}
114 |
115 | HTML;
116 | /**
117 | * Tags to replace in the rendered layout. Enter this as `$key => $value` pairs, where:
118 | * - $key: string, defines the flag.
119 | * - $value: string|Closure, the value that will be replaced. You can set it as a callback
120 | * function to return a string of the signature:
121 | * function ($widget) { return 'custom'; }
122 | *
123 | * For example:
124 | * ['{flag}' => ' '200',
214 | * 'username' => '123',
215 | * //and etc
216 | * ]
217 | * ~~~
218 | * @since 1.1.3
219 | */
220 | public $resizableColumns = false;
221 | /**
222 | * @var array Options of resizable columns plugin.
223 | * List options:
224 | * - `selector` (string): CSS relative path to header columns of table.
225 | */
226 | public $resizableColumnsOptions = [
227 | 'selector' => 'tr > th[data-resizable-column], tr > td[data-resizable-column]',
228 | ];
229 | /**
230 | * @var array|string URL to action for save width of resizable column after changes it.
231 | */
232 | public $resizableColumnsUrl = ['url/to/action'];
233 | /**
234 | * @var ManagerInterface|array|string
235 | * @since 1.1.4
236 | */
237 | public $gridManager = 'gridManager';
238 | /**
239 | * @var boolean Keeping the page sizer. If set as `true` then last modified page sizer will be keep to
240 | * the storage.
241 | * @since 1.1.4
242 | */
243 | public $keepPageSizer = false;
244 |
245 | /**
246 | * @inheritdoc
247 | * @since 1.1.4
248 | */
249 | public function init()
250 | {
251 | parent::init();
252 | if ($this->keepPageSizer) {
253 | $this->gridManager = Instance::ensure($this->gridManager, 'bupy7\grid\interfaces\ManagerInterface');
254 | }
255 | }
256 |
257 | /**
258 | * @inheritdoc
259 | */
260 | public function run()
261 | {
262 | Html::addCssClass($this->tableOptions, 'table');
263 | if ($this->hover) {
264 | Html::addCssClass($this->tableOptions, 'table-hover');
265 | }
266 | if ($this->bordered) {
267 | Html::addCssClass($this->tableOptions, 'table-bordered');
268 | }
269 | if ($this->striped) {
270 | Html::addCssClass($this->tableOptions, 'table-striped');
271 | }
272 | $this->initLayout();
273 |
274 | GridViewAsset::register($this->view);
275 |
276 | $options = Json::htmlEncode($this->getClientOptions());
277 | $this->view->registerJs("$('#{$this->options['id']}').yiiGridView({$options});");
278 |
279 | if ($this->resizableColumns !== false) {
280 | $options = Json::htmlEncode($this->resizableColumnsOptions);
281 | $url = Url::toRoute($this->resizableColumnsUrl);
282 | $js = <<options['id']}').resizableColumns({$options}).on('afterDragging.rc', function(event) {
284 | var column = $(this).closest('[data-resizable-column]'),
285 | data = {};
286 | data[column.data('resizable-column')] = column.outerWidth();
287 | $.ajax({
288 | type: 'post',
289 | url: '{$url}',
290 | data: data
291 | });
292 | });
293 | JS;
294 | $this->view->registerJs($js);
295 | }
296 | BaseListView::run();
297 | }
298 |
299 | /**
300 | * @inheritdoc
301 | */
302 | public function renderSection($name)
303 | {
304 | switch ($name) {
305 | case '{pageSizer}':
306 | return $this->renderPageSizer();
307 | default:
308 | return parent::renderSection($name);
309 | }
310 | }
311 |
312 | /**
313 | * Renders the page sizer.
314 | * @return string the rendering result
315 | */
316 | public function renderPageSizer()
317 | {
318 | $pagination = $this->getPagination();
319 | if ($pagination === false) {
320 | return '';
321 | }
322 | /* @var $class LinkPageSizer */
323 | $pageSizer = $this->pageSizer;
324 | $class = ArrayHelper::remove($pageSizer, 'class', LinkPageSizer::className());
325 | $pageSizer['pagination'] = clone $pagination;
326 | $pageSizer['view'] = $this->getView();
327 |
328 | return $class::widget($pageSizer);
329 | }
330 |
331 | /**
332 | * Generation layout with panel if it uses.
333 | */
334 | public function renderPanel()
335 | {
336 | if ($this->panel === false) {
337 | return;
338 | }
339 | $this->layout = strtr(
340 | $this->panelTemplate,
341 | [
342 | '{panelHeading}' => $this->panelHeading !== false
343 | ? Html::tag('div', $this->panelHeadingTemplate, ['class' => 'panel-heading'])
344 | : '',
345 | '{type}' => $this->panel,
346 | '{panelFooter}' => $this->panelFooter !== false
347 | ? Html::tag('div', $this->panelFooterTemplate, ['class' => 'panel-footer'])
348 | : '',
349 | ]
350 | );
351 | }
352 |
353 | /**
354 | * Initialization layout of GridView.
355 | */
356 | public function initLayout()
357 | {
358 | $this->renderPanel();
359 | foreach ($this->customTags as $key => $value) {
360 | if ($value instanceof \Closure) {
361 | $value = call_user_func($value, $this);
362 | }
363 | $this->layout = str_replace("{{$key}}", $value, $this->layout);
364 | }
365 | }
366 |
367 | /**
368 | * @inheritdoc
369 | */
370 | public function renderTableHeader()
371 | {
372 | $content = parent::renderTableHeader();
373 | return strtr(
374 | $content,
375 | [
376 | '' => "\n" . $this->generateRows($this->beforeHeader),
377 | '' => $this->generateRows($this->afterHeader) . "\n",
378 | ]
379 | );
380 | }
381 |
382 | /**
383 | * @inheritdoc
384 | */
385 | public function renderTableFooter()
386 | {
387 | $content = parent::renderTableFooter();
388 | return strtr(
389 | $content,
390 | [
391 | '' => "\n" . $this->generateRows($this->beforeFooter),
392 | '' => $this->generateRows($this->afterFooter) . "\n",
393 | ]
394 | );
395 | }
396 |
397 | /**
398 | * @inheritdoc
399 | */
400 | public function initColumns()
401 | {
402 | $visibleColumns = false;
403 | if (is_array($this->visibleColumns)) {
404 | $visibleColumns = array_flip($this->visibleColumns);
405 | }
406 | if (empty($this->columns)) {
407 | $this->guessColumns();
408 | }
409 | $dataColumns = [];
410 | $serviceColumns = [];
411 | foreach ($this->columns as $i => $column) {
412 | if (is_string($column)) {
413 | $column = $this->createDataColumn($column);
414 | } else {
415 | $column = Yii::createObject(array_merge([
416 | 'class' => $this->dataColumnClass ? : DataColumn::className(),
417 | 'grid' => $this,
418 | ], $column));
419 | }
420 | if ($column->visible) {
421 | $key = $i;
422 | if ($visibleColumns !== false) {
423 | if ($column instanceof DataColumn) {
424 | if (isset($visibleColumns[$column->attribute])) {
425 | $key = $visibleColumns[$column->attribute];
426 | } else {
427 | continue;
428 | }
429 | } else {
430 | $serviceColumns[$i] = $column;
431 | continue;
432 | }
433 | }
434 | $dataColumns[$key] = $column;
435 | }
436 | }
437 | if ($this->resizableColumns !== false) {
438 | foreach ($dataColumns as $column) {
439 | if (!($column instanceof DataColumn)) {
440 | continue;
441 | }
442 | $column->headerOptions['data-resizable-column'] = $column->attribute;
443 | if (isset($this->resizableColumns[$column->attribute])) {
444 | Html::addCssStyle($column->headerOptions, [
445 | 'width' => $this->resizableColumns[$column->attribute] . 'px',
446 | 'min-width' => $this->resizableColumns[$column->attribute] . 'px',
447 | ]);
448 | }
449 | }
450 | }
451 | $this->columns = $this->mergeColumns($dataColumns, $serviceColumns);
452 | }
453 |
454 | /**
455 | * Sorting and ordering columns by specific criteria.
456 | * @param array $dataColumns Array of columns DataColumn instance.
457 | * @param array $serviceColumns Array of columns with other class instance.
458 | * @return array
459 | * @since 1.1.3
460 | */
461 | protected function mergeColumns(array $dataColumns, array $serviceColumns)
462 | {
463 | $columns = $dataColumns;
464 | ksort($columns);
465 | foreach ($serviceColumns as $i => $column) {
466 | $tmp = array_slice($columns, 0, $i);
467 | $tmp[] = $column;
468 | $columns = array_merge($tmp, array_slice($columns, $i));
469 | }
470 | return $columns;
471 | }
472 |
473 | /**
474 | * Generate HTML markup for additional table rows for header and/or footer
475 | *
476 | * @param array|string $data the table rows configuration
477 | * @return string
478 | */
479 | protected function generateRows($data)
480 | {
481 | if (empty($data)) {
482 | return '';
483 | }
484 | if (is_string($data)) {
485 | return $data;
486 | }
487 | $rows = '';
488 | if (is_array($data)) {
489 | foreach ($data as $row) {
490 | if (empty($row['columns'])) {
491 | continue;
492 | }
493 | $rowOptions = ArrayHelper::getValue($row, 'options', []);
494 | $rows .= Html::beginTag('tr', $rowOptions);
495 | foreach ($row['columns'] as $col) {
496 | $colOptions = ArrayHelper::getValue($col, 'options', []);
497 | $colContent = ArrayHelper::getValue($col, 'content', '');
498 | $tag = ArrayHelper::getValue($col, 'tag', 'th');
499 | $rows .= "\t" . Html::tag($tag, $colContent, $colOptions) . "\n";
500 | }
501 | $rows .= Html::endTag('tr') . "\n";
502 | }
503 | }
504 | return $rows;
505 | }
506 |
507 | /**
508 | * @return Pagination|false The pagination object. If this is false, it means the pagination is disabled.
509 | * @since 1.1.4
510 | */
511 | protected function getPagination()
512 | {
513 | $pagination = $this->dataProvider->getPagination();
514 | if ($pagination === false) {
515 | return false;
516 | }
517 | if ($this->keepPageSizer) {
518 | $defaultPageSize = $this->gridManager->getDefaultPageSize($this->getId());
519 | if ($defaultPageSize !== false) {
520 | $pagination->defaultPageSize = $defaultPageSize;
521 | }
522 | $this->gridManager->setDefaultPageSize($this->getId(), $pagination->getPageSize());
523 | }
524 | return $pagination;
525 | }
526 | }
527 |
--------------------------------------------------------------------------------
/LinkPageSizer.php:
--------------------------------------------------------------------------------
1 | '10', 20 => '20', 40 => '40'];
37 | /**
38 | * @var array HTML attributes for the pager container tag.
39 | * @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
40 | */
41 | public $options = ['class' => 'pagination'];
42 | /**
43 | * @var array HTML attributes for the link in a pager container tag.
44 | * @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
45 | */
46 | public $linkOptions = [];
47 | /**
48 | * @var string the CSS class for the active (currently selected) page size button.
49 | */
50 | public $activePageSizeCssClass = 'active';
51 |
52 | /**
53 | * Initializes the pager.
54 | */
55 | public function init()
56 | {
57 | if ($this->pagination === null) {
58 | throw new InvalidConfigException('The "pagination" property must be set.');
59 | }
60 | }
61 |
62 | /**
63 | * Executes the widget.
64 | * This overrides the parent implementation by displaying the generated page size buttons.
65 | */
66 | public function run()
67 | {
68 | echo $this->renderPageSizerButtons();
69 | }
70 |
71 | /**
72 | * Renders the page buttons.
73 | * @return string the rendering result
74 | */
75 | protected function renderPageSizerButtons()
76 | {
77 | if (count($this->availableSizes) === 0) {
78 | return '';
79 | }
80 |
81 | $buttons = [];
82 | $currentPageSize = $this->pagination->getPageSize();
83 |
84 | foreach ($this->availableSizes as $size => $label) {
85 | $buttons[] = $this->renderPageSizeButton($label, $size, null, $size == $currentPageSize);
86 | }
87 |
88 | return Html::tag('ul', implode(PHP_EOL, $buttons), $this->options);
89 | }
90 |
91 | /**
92 | * Renders a page size button.
93 | * You may override this method to customize the generation of page size buttons.
94 | * @param string $label the text label for the button
95 | * @param integer $pageSize the page size
96 | * @param string $class the CSS class for the page button.
97 | * @param boolean $active whether this page button is active
98 | * @return string the rendering result
99 | */
100 | protected function renderPageSizeButton($label, $pageSize, $class, $active)
101 | {
102 | $options = ['class' => $class === '' ? null : $class];
103 | if ($active) {
104 | Html::addCssClass($options, $this->activePageSizeCssClass);
105 | }
106 | $linkOptions = $this->linkOptions;
107 | $linkOptions['data-page-size'] = $pageSize;
108 |
109 | return Html::tag(
110 | 'li',
111 | Html::a($label, $this->createUrl($this->pagination, $pageSize), $linkOptions),
112 | $options
113 | );
114 | }
115 |
116 | /**
117 | * Creates an url for the specified page size.
118 | * @param \yii\data\Pagination $pagination
119 | * @param integer $pageSize page size
120 | * @param boolean $absolute whether to create an absolute URL. Defaults to `false`.
121 | * @return string the created URL
122 | */
123 | protected function createUrl($pagination, $pageSize, $absolute = false)
124 | {
125 | if (($params = $pagination->params) === null) {
126 | $request = Yii::$app->getRequest();
127 | $params = $request instanceof Request ? $request->getQueryParams() : [];
128 | }
129 |
130 | $currentPageSize = $pagination->getPageSize();
131 | $currentPage = $pagination->getPage();
132 | $target = $currentPage * $currentPageSize;
133 | $page = (int)($target / $pageSize);
134 |
135 | if ($page > 0 || $page >= 0 && $pagination->forcePageParam) {
136 | $params[$pagination->pageParam] = $page + 1;
137 | } else {
138 | unset($params[$pagination->pageParam]);
139 | }
140 | if ($pageSize != $pagination->defaultPageSize) {
141 | $params[$pagination->pageSizeParam] = $pageSize;
142 | } else {
143 | unset($params[$pagination->pageSizeParam]);
144 | }
145 |
146 | $params[0] = $pagination->route === null ? Yii::$app->controller->getRoute() : $pagination->route;
147 | $urlManager = $pagination->urlManager === null ? Yii::$app->getUrlManager() : $pagination->urlManager;
148 | if ($absolute) {
149 | return $urlManager->createAbsoluteUrl($params);
150 | }
151 | return $urlManager->createUrl($params);
152 | }
153 | }
154 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | yii2-grid
2 | =========
3 | Simple extended `yii\grid\GridView`.
4 |
5 | **Features:**
6 |
7 | - Wrapping GridView in [Bootstrap3 Panel](http://getbootstrap.com/components/#panels).
8 | - Ability changing size of page.
9 | - Column of 'Total' with ability using custom formulas.
10 | - Hard-header.
11 | - Custom tags of template the GridView.
12 | - Ability disabling/enabling/sort visible columns of real-time.
13 | - Ability resize width of columns.
14 | - Keepping last modified page sizer.
15 |
16 | 
17 |
18 | 
19 |
20 | 
21 |
22 | Installation
23 | ------------
24 |
25 | The preferred way to install this extension is through [composer](http://getcomposer.org/download/).
26 |
27 | Either run
28 |
29 | ```
30 | php composer.phar require --prefer-dist bupy7/yii2-grid "*"
31 | ```
32 |
33 | or add
34 |
35 | ```
36 | "bupy7/yii2-grid": "*"
37 | ```
38 |
39 | to the require section of your `composer.json` file.
40 |
41 |
42 | Usage
43 | -----
44 |
45 | ### Simple usage
46 |
47 | ```php
48 | use bupy7\grid\GridView;
49 |
50 | echo GridView::widget([
51 | 'dataProvider' => $dataProvider,
52 | 'filterModel' => $searchModel,
53 | 'columns' => [
54 | ['class' => 'yii\grid\SerialColumn'],
55 | ['class' => 'yii\grid\CheckboxColumn'],
56 | 'attribute1',
57 | 'attribute2',
58 | ],
59 | ]);
60 | ```
61 |
62 | ### Adding delete button
63 |
64 | Adding your view:
65 |
66 | ```php
67 | use bupy7\grid\GridView;
68 |
69 | $panelHeadingTemplate = <<{controls}
71 | {pageSizer}
72 |
73 | HTML;
74 | echo GridView::widget([
75 | 'customTags' => [
76 | 'controls' => $this->render('_controls'),
77 | ],
78 | 'panelHeadingTemplate' => $panelHeadingTemplate,
79 | 'dataProvider' => $dataProvider,
80 | 'filterModel' => $searchModel,
81 | 'columns' => [
82 | ['class' => 'yii\grid\SerialColumn'],
83 | ['class' => 'yii\grid\CheckboxColumn'],
84 | 'attribute1',
85 | 'attribute2',
86 | ],
87 | ]);
88 | ```
89 |
90 | Adding your ```_controls``` view:
91 |
92 | ```php
93 |
97 | = Html::a(Yii::t('app', 'DELETE'), ['delete'], [
98 | 'id' => 'all-delete',
99 | 'class' => 'btn btn-danger',
100 | 'title' => Yii::t('app', 'DELETE'),
101 | ]); ?>
102 | registerJs($js);
115 | ```
116 |
117 | Adding your controller:
118 |
119 | ```php
120 | public function actionDelete($id = null)
121 | {
122 | if ($id === null) {
123 | $ids = (array)Yii::$app->request->post('ids');
124 | } else {
125 | $ids = (array)$id;
126 | }
127 | for ($i = 0; $i != count($ids); $i++) {
128 | $this->findModel($ids[$i])->delete();
129 | }
130 | return $this->redirect(['index']);
131 | }
132 | ```
133 |
134 | ### Adding ability change visible columns
135 |
136 | #### Via session
137 |
138 | Override session component:
139 |
140 | ```php
141 | use bupy7\grid\interfaces\StorageInterface;
142 |
143 | /**
144 | * @inheritdoc
145 | */
146 | class Session extends \yii\web\Session implements StorageInterface
147 | {
148 |
149 | }
150 | ```
151 |
152 | Adding your config of application:
153 |
154 | ```php
155 | 'components' => [
156 | 'gridManager' => [
157 | 'class' => 'bupy7\grid\components\Manager',
158 | 'storage' => 'session',
159 | ],
160 | ]
161 | ```
162 |
163 | Adding your controller:
164 |
165 | ```php
166 | use bupy7\grid\actions\VisibleColumnsAction;
167 | use yii\helpers\Url;
168 |
169 | public function actions()
170 | {
171 | return parent::actions() + [
172 | 'visible-columns' => [
173 | 'class' => VisibleColumnsAction::className(),
174 | 'gridId' => 'example-grid',
175 | ],
176 | ];
177 | }
178 |
179 | public function actionIndex()
180 | {
181 | Url::remember();
182 |
183 | $searchModel = new ExampleSearch();
184 | $dataProvider = $searchModel->search(Yii::$app->request->queryParams);
185 |
186 | $visibleColumns = Yii::$app->gridManager->getVisibleColumns('example-grid');
187 | if ($visibleColumns === false) {
188 | $visibleColumns = array_keys($searchModel->gridColumnsList());
189 | }
190 |
191 | return $this->render('index', [
192 | 'searchModel' => $searchModel,
193 | 'dataProvider' => $dataProvider,
194 | 'visibleColumns' => $visibleColumns,
195 | ]);
196 | }
197 | ```
198 |
199 | Adding your search model:
200 |
201 | ```php
202 | public function gridColumnsList()
203 | {
204 | return [
205 | 'attribute1' => 'Label of attribute1',
206 | 'attribute2' => 'Label of attribute2',
207 | ];
208 | }
209 | ```
210 |
211 | Adding your view:
212 |
213 | ```php
214 | use bupy7\grid\GridView;
215 |
216 | $panelHeadingTemplate = <<{controls}
218 | {pageSizer}
219 |
220 | HTML;
221 | echo GridView::widget([
222 | 'customTags' => [
223 | 'controls' => $this->render('_controls', [
224 | 'visibleColumns' => $visibleColumns,
225 | 'searchModel' => $searchModel,
226 | ]),
227 | ],
228 | 'panelHeadingTemplate' => $panelHeadingTemplate,
229 | 'dataProvider' => $dataProvider,
230 | 'filterModel' => $searchModel,
231 | 'visibleColumns' => $visibleColumns,
232 | 'columns' => [
233 | ['class' => 'yii\grid\SerialColumn'],
234 | 'attribute1',
235 | 'attribute2',
236 | ],
237 | ]);
238 | ```
239 |
240 | Adding your `_controls` view:
241 |
242 | ```php
243 | use bupy7\grid\widgets\VisibleColumnsWidget;
244 |
245 | = VisibleColumnsWidget::widget([
246 | 'gridId' => 'example-grid',
247 | 'modalOptions' => [
248 | 'header' => Yii::t('app', 'SELECT_COLUMNS'),
249 | 'toggleButton' => [
250 | 'label' => Yii::t('app', 'SELECT_COLUMNS'),
251 | 'class' => 'btn btn-default',
252 | ],
253 | ],
254 | 'actionForm' => ['visible-columns'],
255 | 'submitBtnLabel' => Yii::t('app', 'APPLY'),
256 | 'columnsList' => $searchModel->gridColumnsList(),
257 | ]); ?>
258 | ```
259 |
260 | ### Adding ability resize width of columns
261 |
262 | #### Via session
263 |
264 | Override session component:
265 |
266 | ```php
267 | use bupy7\grid\interfaces\StorageInterface;
268 |
269 | /**
270 | * @inheritdoc
271 | */
272 | class Session extends \yii\web\Session implements StorageInterface
273 | {
274 |
275 | }
276 | ```
277 |
278 | Adding your config of application:
279 |
280 | ```php
281 | 'components' => [
282 | 'gridManager' => [
283 | 'class' => 'bupy7\grid\components\Manager',
284 | 'storage' => 'session',
285 | ],
286 | ]
287 | ```
288 |
289 | Adding your controller:
290 |
291 | ```php
292 | use bupy7\grid\actions\ResizableColumnsAction;
293 | use yii\helpers\Url;
294 |
295 | public function actions()
296 | {
297 | return parent::actions() + [
298 | 'resizable-columns' => [
299 | 'class' => ResizableColumnsAction::className(),
300 | 'gridId' => 'example-grid',
301 | ],
302 | ];
303 | }
304 |
305 | public function actionIndex()
306 | {
307 | Url::remember();
308 |
309 | $searchModel = new ExampleSearch();
310 | $dataProvider = $searchModel->search(Yii::$app->request->queryParams);
311 |
312 | $resizableColumns = Yii::$app->gridManager->getResizableColumns('example-grid');
313 |
314 | return $this->render('index', [
315 | 'searchModel' => $searchModel,
316 | 'dataProvider' => $dataProvider,
317 | 'resizableColumns' => $resizableColumns,
318 | 'resizableColumnsUrl' => ['resizable-columns'],
319 | ]);
320 | }
321 | ```
322 |
323 | Adding your view:
324 |
325 | ```php
326 | use bupy7\grid\GridView;
327 |
328 | echo GridView::widget([
329 | 'resizableColumns' => $resizableColumns,
330 | 'resizableColumnsUrl' => $resizableColumnsUrl,
331 | 'dataProvider' => $dataProvider,
332 | 'filterModel' => $searchModel,
333 | 'columns' => [
334 | ['class' => 'yii\grid\SerialColumn'],
335 | 'attribute1',
336 | 'attribute2',
337 | ],
338 | ]);
339 | ```
340 |
341 |
342 | ### Adding ability display all rows of grid
343 |
344 | ```php
345 | echo GridView::widget([
346 |
347 | ...
348 |
349 | 'pageSizer' => [
350 | 'availableSizes' => [20 => '20', 50 => '50', 100 => '100', -1 => Yii::t('app', 'ALL_PAGES')],
351 | ],
352 |
353 | ...
354 | ]);
355 | ```
356 |
357 | And change `$pageSizeLimit` in your model:
358 |
359 | ```php
360 | $dataProvider = new ActiveDataProvider([
361 | 'query' => $query,
362 | 'pagination' => [
363 | 'pageSizeLimit' => [-1, 100],
364 | ],
365 | ]);
366 | ```
367 |
368 | More information to `bupy7\grid\LinkPageSizer`.
369 |
370 | ### Adding total column of grid
371 |
372 | Added sum total:
373 |
374 | ```php
375 | [
376 | 'class' => 'bupy7\grid\TotalColumn',
377 | 'format' => 'currency',
378 | 'attribute' => 'total_cost',
379 | ]
380 | ```
381 |
382 | More information to `bupy7\grid\TotalColumn`.
383 |
384 | --------------------------------------------------------------------------------
385 |
386 | More information about `GridView` to `bupy7\grid\GridView`.
387 |
388 | ### Keeping last modified the page sizer
389 |
390 | By default this function disabled.
391 |
392 | ```php
393 | echo GridView::widget([
394 | ...
395 |
396 | 'id' => 'unique-id-of-this-grid',
397 | 'keepPageSizer' => true,
398 |
399 | ...
400 | ]);
401 | ```
402 |
403 | You need to specify `id` as unique for correct work.
404 |
405 | > `id` and `options[id]` - not the same! `id` it identificator of widget, and
406 | `options[id]` it HTML-identificator of grid view.
407 |
408 | ##License
409 |
410 | yii2-grid is released under the BSD 3-Clause License.
411 |
--------------------------------------------------------------------------------
/TotalColumn.php:
--------------------------------------------------------------------------------
1 | grid->showFooter = true;
79 | parent::init();
80 | }
81 |
82 | /**
83 | * @inheritdoc
84 | */
85 | public function getDataCellValue($model, $key, $index)
86 | {
87 | if (isset($this->realValue)) {
88 | if (is_string($this->realValue)) {
89 | $this->_data[] = ArrayHelper::getValue($model, $this->realValue);
90 | } else {
91 | $this->_data[] = call_user_func($this->realValue, $model, $key, $index, $this);
92 | }
93 | } else {
94 | $this->_data[] = parent::getDataCellValue($model, $key, $index);
95 | }
96 | $this->_models[] = $model;
97 | return parent::getDataCellValue($model, $key, $index);
98 | }
99 |
100 | /**
101 | * @inheritdoc
102 | */
103 | protected function renderFooterCellContent()
104 | {
105 | $footer = $this->calculateSummary();
106 | return trim($footer) !== '' ? $this->formattingFooter($footer) : $this->grid->emptyCell;
107 | }
108 |
109 | /**
110 | * Calculates the summary of an input data based on page summary aggregration function.
111 | * @return mixed
112 | * @throws InvalidConfigException
113 | */
114 | protected function calculateSummary()
115 | {
116 | if (empty($this->_data)) {
117 | return '';
118 | }
119 | $formula = $this->footer;
120 | if ($formula instanceof Closure) {
121 | $result = call_user_func($this->footer, $this->_data, $this->_models);
122 | } else {
123 | switch ($formula) {
124 | case self::FORMULA_SUM:
125 | $result = array_sum($this->_data);
126 | break;
127 |
128 | case self::FORMULA_COUNT:
129 | $result = count($this->_data);
130 | break;
131 |
132 | case self::FORMULA_AVG:
133 | $result = count($this->_data) > 0 ? array_sum($this->_data) / count($$this->_data) : null;
134 | break;
135 |
136 | case self::FORMULA_MAX:
137 | $result = max($this->_data);
138 | break;
139 |
140 | case self::FORMULA_MIN:
141 | $result = min($this->_data);
142 | break;
143 |
144 | default:
145 | throw new InvalidConfigException('There is invalid value `$footer`.');
146 | }
147 | }
148 | return $result;
149 | }
150 |
151 | /**
152 | * Formatting footer value uses Formatter component or an anonymous function.
153 | * @param string $value
154 | * @return mixed
155 | * @since 1.1.5
156 | * @throws InvalidConfigException
157 | */
158 | protected function formattingFooter($value)
159 | {
160 | if (is_string($this->footerFormat) || is_array($this->footerFormat)) {
161 | return $this->grid->formatter->format($value, $this->footerFormat);
162 | } elseif ($this->footerFormat instanceof Closure) {
163 | return call_user_func($this->footerFormat, $value);
164 | } else {
165 | throw new InvalidConfigException('There is invalid value `$footerFormat`.');
166 | }
167 | }
168 | }
169 |
170 |
--------------------------------------------------------------------------------
/actions/ResizableColumnsAction.php:
--------------------------------------------------------------------------------
1 |
11 | * @since 1.1.3
12 | */
13 | class ResizableColumnsAction extends BaseAction
14 | {
15 | /**
16 | * Saving settings of resizable column.
17 | * @return mixed
18 | */
19 | public function run()
20 | {
21 | $bodyParams = Yii::$app->request->getBodyParams();
22 | $resizableColumns = $this->gridManager->getResizableColumns($this->gridId);
23 | foreach ($bodyParams as $attribute => $width) {
24 | if (is_string($attribute)) {
25 | $resizableColumns[$attribute] = $width;
26 | }
27 | }
28 | $this->gridManager->setResizableColumns($this->gridId, $resizableColumns);
29 | }
30 | }
--------------------------------------------------------------------------------
/actions/VisibleColumnsAction.php:
--------------------------------------------------------------------------------
1 |
13 | * @since 1.0.0
14 | */
15 | class VisibleColumnsAction extends BaseAction
16 | {
17 | /**
18 | * @var mixed URL of redirect. If this property not set, will be used goBack().
19 | */
20 | public $redirectUrl;
21 |
22 | /**
23 | * @inheritdoc
24 | */
25 | public function init()
26 | {
27 | parent::init();
28 | if (!isset($this->redirectUrl)) {
29 | $this->redirectUrl = Url::previous();
30 | }
31 | }
32 |
33 | /**
34 | * Saving settings of visible columns. If body params is invalid - redirect.
35 | * @return mixed
36 | */
37 | public function run()
38 | {
39 | $params = $this->getBodyParams();
40 | if (empty($params)) {
41 | return $this->controller->redirect($this->redirectUrl);
42 | }
43 | $this->saveSettings($params);
44 | return $this->controller->redirect($this->redirectUrl);
45 | }
46 |
47 | /**
48 | * Save settings of visible columns to storage of user.
49 | * @param array $params Body params of request.
50 | */
51 | protected function saveSettings($params)
52 | {
53 | $visibleColumns = [];
54 | foreach ($params['columns'] as $column) {
55 | if (is_string($column)) {
56 | $visibleColumns[] = $column;
57 | }
58 | }
59 | $this->gridManager->setVisibleColumns($this->gridId, $visibleColumns);
60 | }
61 |
62 | /**
63 | * Returned body params of request.
64 | * @return array
65 | */
66 | protected function getBodyParams()
67 | {
68 | $params = Yii::$app->request->getBodyParams();
69 | if (empty($params['columns'])) {
70 | return [];
71 | }
72 | return $params;
73 | }
74 | }
--------------------------------------------------------------------------------
/assets/GridViewAsset.php:
--------------------------------------------------------------------------------
1 |
12 | * @since 1.1.3
13 | */
14 | class GridViewAsset extends AssetBundle
15 | {
16 | /**
17 | * @inheritdoc
18 | */
19 | public $sourcePath = '@bupy7/grid/resources';
20 | public $js = [];
21 | /**
22 | * @inheritdoc
23 | */
24 | public $css = [];
25 | /**
26 | * @inheritdoc
27 | */
28 | public $depends = [
29 | 'yii\grid\GridViewAsset',
30 | ];
31 |
32 | /**
33 | * @inheritdoc
34 | */
35 | public function init()
36 | {
37 | parent::init();
38 | $this->css[] = 'css/resizable-columns' . (!YII_DEBUG ? '.min' : '') . '.css';
39 | $this->js[] = 'js/resizable-columns' . (!YII_DEBUG ? '.min' : '') . '.js';
40 | }
41 | }
--------------------------------------------------------------------------------
/assets/SortableAsset.php:
--------------------------------------------------------------------------------
1 |
11 | * @see https://github.com/RubaXa/Sortable
12 | * @since 1.1.1
13 | */
14 | class SortableAsset extends AssetBundle
15 | {
16 | /**
17 | * @inheritdoc
18 | */
19 | public $sourcePath = '@npm/sortablejs';
20 | /**
21 | * @inheritdoc
22 | */
23 | public $js = [
24 | 'Sortable.min.js',
25 | 'jquery.binding.js',
26 | ];
27 | /**
28 | * @inheritdoc
29 | */
30 | public $depends = [
31 | 'yii\web\JqueryAsset',
32 | ];
33 | }
34 |
--------------------------------------------------------------------------------
/base/BaseAction.php:
--------------------------------------------------------------------------------
1 |
14 | * @since 1.1.3
15 | */
16 | class BaseAction extends Action
17 | {
18 | /**
19 | * @var mixed Uniqal ID of grid. You can uses not only string, but also other types of variable.
20 | * Example:
21 | * ~~~
22 | * 'main-grid'
23 | * ~~~
24 | */
25 | public $gridId;
26 | /**
27 | * @var array|string|ManagerInterface the grid settings used for set/get actual visible columns of $gridId.
28 | * @since 1.1.0
29 | */
30 | public $gridManager = 'gridManager';
31 |
32 | /**
33 | * @inheritdoc
34 | * @throws InvalidConfigException
35 | */
36 | public function init()
37 | {
38 | parent::init();
39 | if (empty($this->gridId) || empty($this->gridManager)) {
40 | throw new InvalidConfigException('Property "gridId" and "gridManager" must be specified.');
41 | }
42 | $this->gridManager = Instance::ensure($this->gridManager, 'bupy7\grid\interfaces\ManagerInterface');
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/components/BaseManager.php:
--------------------------------------------------------------------------------
1 |
13 | * @since 1.1.0
14 | */
15 | abstract class BaseManager extends Component implements ManagerInterface
16 | {
17 | /**
18 | * @var string|array|StorageInterface A place to store the setting and follow-up with this.
19 | * You can pointer name of component, configuration array or instance of which implement from StorageInterface.
20 | */
21 | public $storage;
22 |
23 | /**
24 | * @inheritdoc
25 | */
26 | public function init()
27 | {
28 | parent::init();
29 | $this->storage = Instance::ensure($this->storage, 'bupy7\grid\interfaces\StorageInterface');
30 | }
31 |
32 | /**
33 | * Generation and returned storage key for indentified the data.
34 | * @param mixed $name Name of storage data.
35 | * @return mixed
36 | */
37 | public function getStorageKey($name)
38 | {
39 | return md5(serialize([__CLASS__, $name]));
40 | }
41 | }
42 |
43 |
--------------------------------------------------------------------------------
/components/Manager.php:
--------------------------------------------------------------------------------
1 |
8 | * @since 1.1.0
9 | */
10 | class Manager extends BaseManager
11 | {
12 | /**
13 | * @inheritdoc
14 | */
15 | public function setVisibleColumns($gridId, $columns)
16 | {
17 | $key = $this->getStorageKey([$gridId, 'visible-columns']);
18 | $this->storage->set($key, serialize($columns));
19 | }
20 |
21 | /**
22 | * @inheritdoc
23 | */
24 | public function getVisibleColumns($gridId)
25 | {
26 | $key = $this->getStorageKey([$gridId, 'visible-columns']);
27 | if ($this->storage->has($key)) {
28 | $columns = @unserialize($this->storage->get($key));
29 | if (!is_array($columns)) {
30 | return false;
31 | }
32 | return $columns;
33 | }
34 | return false;
35 | }
36 |
37 | /**
38 | * @inheritdoc
39 | */
40 | public function setResizableColumns($gridId, $columns)
41 | {
42 | $key = $this->getStorageKey([$gridId, 'resizable-columns']);
43 | $this->storage->set($key, serialize($columns));
44 | }
45 |
46 | /**
47 | * @inheritdoc
48 | */
49 | public function getResizableColumns($gridId)
50 | {
51 | $key = $this->getStorageKey([$gridId, 'resizable-columns']);
52 | if ($this->storage->has($key)) {
53 | $columns = @unserialize($this->storage->get($key));
54 | if (!is_array($columns)) {
55 | return [];
56 | }
57 | return $columns;
58 | }
59 | return [];
60 | }
61 |
62 | /**
63 | * @inheritdoc
64 | */
65 | public function setDefaultPageSize($gridId, $pageSize)
66 | {
67 | $key = $this->getStorageKey([$gridId, 'default-page-size']);
68 | $this->storage->set($key, serialize($pageSize));
69 | }
70 |
71 | /**
72 | * @inheritdoc
73 | */
74 | public function getDefaultPageSize($gridId)
75 | {
76 | $key = $this->getStorageKey([$gridId, 'default-page-size']);
77 | if ($this->storage->has($key)) {
78 | return @unserialize($this->storage->get($key));
79 | }
80 | return false;
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "bupy7/yii2-grid",
3 | "description": "Simple extended `yii\\grid\\GridView` with buns.",
4 | "type": "yii2-extension",
5 | "keywords": ["yii2","extension","module","grid","grid view"],
6 | "license": "BSD-3-Clause",
7 | "version": "1.1.6",
8 | "authors": [
9 | {
10 | "name": "Vasilij Belosludcev",
11 | "email": "bupy765@gmail.com"
12 | }
13 | ],
14 | "require": {
15 | "yiisoft/yii2": "*",
16 | "yiisoft/yii2-bootstrap": "*",
17 | "npm-asset/sortablejs": "1.4.2"
18 | },
19 | "autoload": {
20 | "psr-4": {
21 | "bupy7\\grid\\": ""
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/docs/screenshot1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bupy7/yii2-grid/343ee8f9bab48bdd7e6087b5020cc18d0c8ed46c/docs/screenshot1.png
--------------------------------------------------------------------------------
/docs/screenshot2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bupy7/yii2-grid/343ee8f9bab48bdd7e6087b5020cc18d0c8ed46c/docs/screenshot2.png
--------------------------------------------------------------------------------
/docs/screenshot3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bupy7/yii2-grid/343ee8f9bab48bdd7e6087b5020cc18d0c8ed46c/docs/screenshot3.png
--------------------------------------------------------------------------------
/interfaces/ManagerInterface.php:
--------------------------------------------------------------------------------
1 |
7 | * @since 1.1.0
8 | */
9 | interface ManagerInterface
10 | {
11 | /**
12 | * Save visible columns settings.
13 | * @param mixed $gridId ID of grid.
14 | * @param array $columns List of columns.
15 | */
16 | public function setVisibleColumns($gridId, $columns);
17 |
18 | /**
19 | * Returned visible columns of grid.
20 | * @param mixed $gridId ID of grid.
21 | * @return false|array
22 | */
23 | public function getVisibleColumns($gridId);
24 |
25 | /**
26 | * Save resizable columns settings.
27 | * @param mixed $gridId ID of grid.
28 | * @param array $columns List of columns.
29 | * @since 1.1.3
30 | */
31 | public function setResizableColumns($gridId, $columns);
32 |
33 | /**
34 | * Returned resizable columns of grid.
35 | * @param mixed $gridId ID of grid.
36 | * @return array
37 | * @since 1.1.3
38 | */
39 | public function getResizableColumns($gridId);
40 |
41 | /**
42 | * Save default page size per page.
43 | * @param mixed $gridId ID of grid.
44 | * @param array $pageSize Default page size.
45 | * @since 1.1.4
46 | */
47 | public function setDefaultPageSize($gridId, $pageSize);
48 |
49 | /**
50 | * Returned default page size per page.
51 | * @param mixed $gridId ID of grid.
52 | * @return false|integer
53 | * @since 1.1.4
54 | */
55 | public function getDefaultPageSize($gridId);
56 | }
57 |
58 |
--------------------------------------------------------------------------------
/interfaces/StorageInterface.php:
--------------------------------------------------------------------------------
1 |
8 | * @since 1.1.0
9 | */
10 | interface StorageInterface
11 | {
12 | /**
13 | * Adds a storage data.
14 | * If the specified name already exists, the old value will be overwritten.
15 | * @param string $key Storage data name.
16 | * @param mixed $value Storage data value.
17 | */
18 | public function set($key, $value);
19 |
20 | /**
21 | * Returns the storage data value with the storage data name.
22 | * If the storage data does not exist, the `$defaultValue` will be returned.
23 | * @param string $key The storage data name.
24 | * @param mixed $defaultValue The default value to be returned when the storage data does not exist.
25 | * @return mixed The storage data value, or $defaultValue if the storage data does not exist.
26 | */
27 | public function get($key, $defaultValue = null);
28 |
29 | /**
30 | * @param mixed $key Storage data name.
31 | * @return boolean Whether the name storage data is exists.
32 | */
33 | public function has($key);
34 |
35 | /**
36 | * Removes a storage data.
37 | * @param string $key The name of the storage data to be removed.
38 | * @return mixed The removed value, null if no such storage data.
39 | */
40 | public function remove($key);
41 | }
--------------------------------------------------------------------------------
/resources/css/resizable-columns.css:
--------------------------------------------------------------------------------
1 | body.resizing-columns {
2 | -webkit-user-select:none;
3 | -moz-user-select:none;
4 | -ms-user-select:none;
5 | user-select:none
6 | }
7 | .grid-view .resizable-columns {
8 | position:relative
9 | }
10 | .grid-view .resizable-columns .resizer {
11 | position:absolute;
12 | top:0;
13 | right:-8px;
14 | bottom:0;
15 | left:auto;
16 | width:16px;
17 | cursor:col-resize;
18 | z-index:1
19 | }
--------------------------------------------------------------------------------
/resources/css/resizable-columns.min.css:
--------------------------------------------------------------------------------
1 | body.resizing-columns{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.grid-view .resizable-columns{position:relative}.grid-view .resizable-columns .resizer{position:absolute;top:0;right:-8px;bottom:0;left:auto;width:16px;cursor:col-resize;z-index:1}
--------------------------------------------------------------------------------
/resources/js/resizable-columns.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Resizable table columns jQuery plugin.
3 | * Options (optional):
4 | * - `selector` (string): CSS relative path to header columns of table.
5 | * @author Vasilij Belosludcev
6 | * @since 1.1.3
7 | */
8 | 'use strict';
9 | (function($) {
10 | // constants
11 | var EVENT_MOUSE_DOWN = 'mousedown',
12 | EVENT_MOUSE_UP = 'mouseup',
13 | EVENT_MOUSE_MOVE = 'mousemove',
14 | EVENT_AFTER_DRAGGING = 'afterDragging.rc';
15 | // protected properties
16 | var startPos = null,
17 | $document = $(document),
18 | $body = $('body');
19 | // public methods
20 | var methods = {
21 | init: function(options) {
22 | var $columns = this;
23 | if (typeof options.selector != 'undefined') {
24 | $columns = this.find(options.selector);
25 | }
26 | return $columns.each(function () {
27 | var $th = $(this);
28 |
29 | $th
30 | .prepend($('').on(EVENT_MOUSE_DOWN, $th, startDragging))
31 | .addClass('resizable-columns');
32 | });
33 | }
34 | };
35 | // protected methods
36 | var startDragging = function(event) {
37 | $body.addClass('resizing-columns');
38 |
39 | startPos = getMousePos(event);
40 | startPos.width = parseInt(event.data.width(), 10);
41 | startPos.height = parseInt(event.data.height(), 10);
42 |
43 | $document.on(EVENT_MOUSE_MOVE, event.data, doDrag);
44 | $document.on(EVENT_MOUSE_UP, event.data, stopDragging);
45 | },
46 | doDrag = function(event) {
47 | var pos = getMousePos(event),
48 | newWidth = startPos.width + pos.x - startPos.x;
49 |
50 | event.data.css({
51 | width: newWidth,
52 | minWidth: newWidth
53 | });
54 | },
55 | stopDragging = function(event) {
56 | noop(event);
57 |
58 | $document.off(EVENT_MOUSE_MOVE);
59 | $document.off(EVENT_MOUSE_UP);
60 |
61 | $body.removeClass('resizing-columns');
62 |
63 | event.data.trigger(EVENT_AFTER_DRAGGING);
64 | },
65 | getMousePos = function(event) {
66 | var pos = {
67 | x: 0,
68 | y: 0,
69 | width: 0,
70 | height: 0
71 | };
72 |
73 | if (typeof event.clientX === 'number') {
74 | pos.x = event.clientX;
75 | pos.y = event.clientY;
76 | } else if (event.originalEvent.touches) {
77 | pos.x = event.originalEvent.touches[0].clientX;
78 | pos.y = event.originalEvent.touches[0].clientY;
79 | } else {
80 | return null;
81 | }
82 |
83 | return pos;
84 | },
85 | noop = function(event) {
86 | event.stopPropagation();
87 | event.preventDefault();
88 | };
89 |
90 | $.fn.resizableColumns = function(options) {
91 | if (methods[options]) {
92 | return methods[options].apply(this, Array.prototype.slice.call(arguments, 1));
93 | } else if (typeof options === 'object' || ! options) {
94 | return methods.init.apply(this, arguments);
95 | } else {
96 | $.error('Method "' + options + '" not exists.');
97 | }
98 | };
99 | })(jQuery);
--------------------------------------------------------------------------------
/resources/js/resizable-columns.min.js:
--------------------------------------------------------------------------------
1 | "use strict";(function(f){var g="mousedown",h="mouseup",m="mousemove",j="afterDragging.rc";var i=null,d=f(document),e=f("body");var b={init:function(p){var o=this;if(typeof p.selector!="undefined"){o=this.find(p.selector)}return o.each(function(){var q=f(this);q.prepend(f('').on(g,q,k)).addClass("resizable-columns")})}};var k=function(o){e.addClass("resizing-columns");i=c(o);i.width=parseInt(o.data.width(),10);i.height=parseInt(o.data.height(),10);d.on(m,o.data,l);d.on(h,o.data,a)},l=function(p){var q=c(p),o=i.width+q.x-i.x;p.data.css({width:o,minWidth:o})},a=function(o){n(o);d.off(m);d.off(h);e.removeClass("resizing-columns");o.data.trigger(j)},c=function(o){var p={x:0,y:0,width:0,height:0};if(typeof o.clientX==="number"){p.x=o.clientX;p.y=o.clientY}else{if(o.originalEvent.touches){p.x=o.originalEvent.touches[0].clientX;p.y=o.originalEvent.touches[0].clientY}else{return null}}return p},n=function(o){o.stopPropagation();o.preventDefault()};f.fn.resizableColumns=function(o){if(b[o]){return b[o].apply(this,Array.prototype.slice.call(arguments,1))}else{if(typeof o==="object"||!o){return b.init.apply(this,arguments)}else{f.error('Method "'+o+'" not exists.')}}}})(jQuery);
--------------------------------------------------------------------------------
/widgets/VisibleColumnsWidget.php:
--------------------------------------------------------------------------------
1 |
17 | * @since 1.0.0
18 | */
19 | class VisibleColumnsWidget extends Widget
20 | {
21 | /**
22 | * @var mixed Uniqal ID of grid. You can uses not only string, but also other types of variable.
23 | * Example:
24 | * ~~~
25 | * 'main-grid'
26 | * ~~~
27 | */
28 | public $gridId;
29 | /**
30 | * @var array|string|ManagerInterface the grid settings used for set/get actual visible columns of $gridId.
31 | * @since 1.1.0
32 | */
33 | public $gridManager = 'gridManager';
34 | /**
35 | * @var array Modal window widget options.
36 | * @see \yii\bootstrap\Modal
37 | */
38 | public $modalOptions = [];
39 | /**
40 | * @var string|array Action URL of form.
41 | * @see Html::beginForm()
42 | */
43 | public $actionForm = '';
44 | /**
45 | * @var string Method of form.
46 | * @see Html::beginForm()
47 | */
48 | public $methodForm = 'post';
49 | /**
50 | * @var array Options of form.
51 | * @see Html::beginForm()
52 | */
53 | public $formOptions = [];
54 | /**
55 | * @var array List of available columns in grid with labels:
56 | * Example:
57 | * [
58 | * 'attribute1' => 'Label of attribute1',
59 | * 'attribute2' => 'Label of attribute2',
60 | * ]
61 | */
62 | public $columnsList = [];
63 | /**
64 | * @var string Label of submit button.
65 | * @see Html::submitButton()
66 | */
67 | public $submitBtnLabel = 'Apply';
68 | /**
69 | * @var array Options of submit button.
70 | * @see Html::submitButton()
71 | */
72 | public $submitBtnOptions = ['class' => 'btn btn-primary'];
73 | /**
74 | * @var array Options of Sortable plugin.
75 | * @see https://github.com/RubaXa/Sortable
76 | * @since 1.1.1
77 | */
78 | public $pluginSortableOptions = [];
79 |
80 | /**
81 | * @inheritdoc
82 | * @throws InvalidConfigException
83 | */
84 | public function init()
85 | {
86 | parent::init();
87 | if (empty($this->gridId) || empty($this->gridManager)) {
88 | throw new InvalidConfigException('Property "gridId" and "gridManager" must be specified.');
89 | }
90 | $this->gridManager = Instance::ensure($this->gridManager, 'bupy7\grid\interfaces\ManagerInterface');
91 | SortableAsset::register($this->view);
92 | }
93 |
94 | /**
95 | * Display modal window with form for selecting visible columns.
96 | */
97 | public function run()
98 | {
99 | $visibleColumns = $this->gridManager->getVisibleColumns($this->gridId);
100 | if ($visibleColumns === false) {
101 | $visibleColumns = array_keys($this->columnsList);
102 | }
103 | $columnsList = [];
104 | for ($i = 0; $i != count($visibleColumns); $i++) {
105 | $key = $visibleColumns[$i];
106 | if (isset($this->columnsList[$key])) {
107 | $columnsList[$key] = $this->columnsList[$key];
108 | unset($this->columnsList[$key]);
109 | }
110 | }
111 | $columnsList = array_merge($columnsList, $this->columnsList);
112 | $modal = Modal::begin($this->modalOptions);
113 | echo Html::beginForm($this->actionForm, $this->methodForm, $this->formOptions);
114 | echo Html::checkboxList('columns', $visibleColumns, $columnsList, ['class' => 'checkbox columns-list']);
115 | echo Html::beginTag('div', ['class' => 'form-group']);
116 | echo Html::submitButton($this->submitBtnLabel, $this->submitBtnOptions);
117 | echo Html::endTag('div');
118 | echo Html::endForm();
119 | Modal::end();
120 | $pluginSortableOptions = Json::encode($this->pluginSortableOptions);
121 | $this->view->registerJs("jQuery('#{$modal->id} .columns-list').sortable({$pluginSortableOptions});");
122 | }
123 | }
124 |
125 |
--------------------------------------------------------------------------------