1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35:
36:
37: Yii::import('zii.widgets.grid.CGridView');
38: Yii::import('X2DataColumn');
39: Yii::import('application.components.X2GridView.massActions.MassAction');
40: Yii::import('X2ButtonColumn');
41:
42: 43: 44: 45: 46: 47: 48: 49: 50:
51: abstract class X2GridViewBase extends CGridView {
52: public $selectableRows = 0;
53: public $loadingCssClass = 'grid-view-loading';
54: public $viewName;
55: public $fullscreen = false;
56: public $defaultGvSettings = array ();
57: public $updateParams = array ();
58: public $excludedColumns;
59: public $enableGvSettings = true;
60: public $enableControls = false;
61: public $enableCheckboxColumn = true;
62: public $enableGridResizing = true;
63: public $enableColDragging = true;
64: public $enableResponsiveTitleBar = true;
65: public $enableDbPersistentGvSettings = true;
66: public = false;
67: public $summaryText;
68: public $buttons = array();
69: public $title;
70: public $gridViewJSClass = 'gvSettings';
71: public $ajax = false;
72: public $evenPercentageWidthColumns = false;
73: public = true;
74: public = false;
75: public $possibleResultsPerPage = array (10, 20, 30, 40, 50, 75, 100);
76: public $hideSummary = false;
77:
78: 79: 80:
81: public = 'CLinkPager';
82:
83: 84: 85: 86:
87: public $enableSelectAllOnAllPages = false;
88:
89: public $calculateChecksum = false;
90:
91: 92: 93:
94: public $gvControlsTemplate = '{view} {update} {delete}';
95:
96: 97: 98:
99: public $dataColumnClass = 'CDataColumn';
100:
101: 102: 103:
104: public $enableScrollOnPageChange = true;
105:
106:
107: public $afterGridViewUpdateJSString = "";
108: public $beforeGridViewUpdateJSString = "";
109:
110: 111: 112:
113: public $qtipManager;
114:
115: 116: 117: 118:
119: public $enableQtips = false;
120:
121: 122: 123: 124:
125: protected $_moduleName;
126:
127: protected $_resultsPerPage;
128: protected $_packages;
129: protected $allFieldNames = array();
130: protected $gvSettings = null;
131: protected $columnSelectorId;
132: protected $columnSelectorHtml;
133:
134: 135: 136: 137:
138: protected $_gvSettingsName;
139:
140: 141: 142: 143: 144:
145: protected $_namespacePrefix;
146:
147: abstract protected function setSummaryText ();
148:
149: abstract protected function generateColumns ();
150:
151: 152: 153: 154:
155: public static function massActionLabelComparison ($a, $b) {
156: return strcmp ($a->getLabel (), $b->getLabel ());
157: }
158:
159: public function __construct ($owner=null) {
160: parent::__construct ($owner);
161: $this->attachBehaviors ($this->behaviors ());
162: }
163:
164: public function behaviors () {
165: return array (
166: 'X2BaseListViewBehavior' => 'application.components.X2GridView.X2BaseListViewBehavior'
167: );
168: }
169:
170: public function setResultsPerPage ($resultsPerPage) {
171: $this->_resultsPerPage = $resultsPerPage;
172: }
173:
174: public function getResultsPerPage () {
175: if (!isset ($this->_resultsPerPage)) {
176: $this->_resultsPerPage = Profile::getResultsPerPage ();
177: }
178: return $this->_resultsPerPage;
179: }
180:
181: public function registerPackages () {
182: Yii::app()->clientScript->registerPackages ($this->getPackages (), true);
183: }
184:
185: public function getPackages () {
186: if (!isset ($this->_packages)) {
187: $this->_packages = array (
188: 'QtipManager' => array(
189: 'baseUrl' => Yii::app()->request->baseUrl,
190: 'js' => array(
191: 'js/QtipManager.js',
192: ),
193: ),
194: 'X2GridViewQtipManager' => array(
195: 'baseUrl' => Yii::app()->request->baseUrl,
196: 'js' => array(
197: 'js/X2GridView/X2GridViewQtipManager.js',
198: ),
199: 'depends' => array ('QtipManager', 'auxlib'),
200: ),
201: );
202: }
203: return $this->_packages;
204: }
205:
206:
207: 208: 209: 210:
211: public function setGvSettingsName ($gvSettingsName) {
212: $this->_gvSettingsName = $gvSettingsName;
213: }
214:
215: public function getModuleName() {
216: if(!isset($this->_moduleName)) {
217: if(!isset(Yii::app()->controller->module)) {
218: throw new CException(
219: 'X2GridView cannot be used both outside of a module that uses X2Model and '.
220: 'without specifying its moduleName property.');
221: }
222: $this->_moduleName = Yii::app()->controller->module->getName();
223: }
224: return $this->_moduleName;
225: }
226:
227: public function setModuleName ($moduleName) {
228: $this->_moduleName = $moduleName;
229: }
230:
231: 232: 233: 234:
235: public function getGvSettingsName () {
236: if (isset ($this->_gvSettingsName)) {
237: return $this->_gvSettingsName;
238: } else if (isset ($this->viewName)) {
239: $this->_gvSettingsName = $this->viewName;
240: }
241: return $this->_gvSettingsName;
242: }
243:
244: 245: 246: 247:
248: public function setNamespacePrefix ($namespacePrefix) {
249: $this->_namespacePrefix = $namespacePrefix;
250: }
251:
252: 253: 254: 255:
256: public function getNamespacePrefix () {
257: if (!isset ($this->_namespacePrefix)) {
258: $this->_namespacePrefix = preg_replace (
259: '/($[0-9])|([^a-zA-Z0-9_$])/', '', $this->id);
260: }
261: return $this->_namespacePrefix;
262: }
263:
264: 265: 266: 267:
268: public function renderKeys()
269: {
270: echo CHtml::openTag('div',array(
271:
272:
273: 'class'=>'keys '.$this->namespacePrefix.'keys',
274:
275: 'style'=>'display:none',
276: 'title'=>Yii::app()->getRequest()->getUrl(),
277: ));
278: foreach($this->dataProvider->getKeys() as $key)
279: echo "<span>".CHtml::encode($key)."</span>";
280: echo "</div>\n";
281: }
282:
283: 284: 285: 286: 287: 288: 289: 290: 291: 292: 293: 294: 295: 296: 297:
298: public function () {
299:
300:
301:
302: if(Yii::app()->user->isGuest) {
303: Yii::app()->clientScript->registerCss('stickyHeaderGuestCss',"
304: @media (min-width: 658px) {
305: .x2-gridview-fixed-top-bar-outer {
306: padding-left: 0px !important;
307: }
308: .x2-gridview-fixed-top-bar-outer .x2-gridview-fixed-top-bar-inner {
309: padding-left: 0px !important;
310: }
311: }
312: ");
313: }
314:
315: Yii::app()->clientScript->registerScriptFile(
316: Yii::app()->getBaseUrl().'/js/X2GridView/X2GridViewStickyHeader.js');
317:
318: $makeHeaderStickyStr = "
319: x2.gridViewStickyHeader.DEBUG && console.log ($('#".$this->id."').find ('.x2grid-body-container').find ('.x2grid-resizable').find ('tbody').find ('tr').length);
320:
321: if ($('#".$this->id."').find ('.x2grid-body-container').find ('.x2grid-resizable').
322: find ('tbody').find ('tr').length <= 2 || x2.isIPad/* || x2.isAndroid*/) {
323:
324: x2.gridViewStickyHeader.DEBUG && console.log ('make sticky');
325: x2.gridViewStickyHeader.makeSticky ();
326: } else if (!$('#x2-gridview-top-bar-outer').
327: hasClass ('x2-gridview-fixed-top-bar-outer')) {
328:
329: x2.gridViewStickyHeader.DEBUG && console.log ('make unsticky');
330: x2.gridViewStickyHeader.makeUnsticky ();
331: }
332:
333: x2.gridViewStickyHeader.DEBUG && console.log ('after grid update');
334: if (!x2.gridViewStickyHeader.checkX2GridViewHeaderSticky ()) {
335:
336: $(window).unbind ('scroll.stickyHeader').
337: bind ('scroll.stickyHeader', function () {
338: x2.gridViewStickyHeader.checkX2GridViewHeaderSticky ();
339: });
340: }
341: ";
342:
343: $this->addToAfterAjaxUpdate ($makeHeaderStickyStr);
344:
345: Yii::app ()->clientScript->registerScript ('x2GridViewStickyHeader', "
346: $(function () {
347: x2.gridViewStickyHeader = new x2.GridViewStickyHeader ({
348: gridId: '".$this->id."'
349: });
350: });
351: ", CClientScript::POS_HEAD);
352:
353: }
354:
355: 356: 357: 358:
359: abstract protected function addFieldNames ();
360:
361: protected function getGvControlsColumn ($width) {
362: $width = $this->formatWidth ($width);
363: $newColumn = array ();
364: $newColumn['id'] = $this->namespacePrefix.'C_gvControls';
365: $newColumn['class'] = 'X2ButtonColumn';
366: $newColumn['header'] = Yii::t('app','Tools');
367: $newColumn['template'] = $this->gvControlsTemplate;
368: $newColumn['headerHtmlOptions'] = array('style'=>'width:'.$width.';');
369: return $newColumn;
370: }
371:
372: protected function formatWidth ($width) {
373: if (!is_scalar ($width)) return null;
374:
375: if (preg_match ('/[0-9]+px/', $width) ||
376: preg_match ('/[0-9]+%/', $width)) {
377:
378: return $width;
379: }
380:
381: if (is_numeric ($width)) {
382: $width = $width . 'px';
383: } else {
384: if ($this->evenPercentageWidthColumns) {
385: $width = ((1 / count ($this->gvSettings)) * 100).'%';
386: } else {
387: $width = null;
388: }
389: }
390: return $width;
391: }
392:
393: protected function getGvCheckboxColumn ($width=null, array $options=array ()) {
394: $newColumn = array ();
395: $newColumn['id'] = $this->namespacePrefix.'C_gvCheckbox';
396: $newColumn['class'] = 'X2CheckBoxColumn';
397: $newColumn['selectableRows'] = 2;
398: $newColumn['htmlOptions'] = array('style'=>'text-align: center;');
399: $newColumn['headerCheckBoxHtmlOptions'] = array('id'=>$newColumn['id'].'_all');
400: $newColumn['checkBoxHtmlOptions'] = array('class'=>'checkbox-column-checkbox');
401: if ($width) {
402: $width = $this->formatWidth ($width);
403: $newColumn['headerHtmlOptions'] = array(
404: 'style'=>'width:'.$width.';',
405: 'class'=>'checkbox-column',
406: );
407: }
408: if (isset ($options['checkBoxHtmlOptions'])) {
409: $newColumn['checkBoxHtmlOptions'] = array_merge (
410: $newColumn['checkBoxHtmlOptions'],
411: $options['checkBoxHtmlOptions']
412: );
413: unset ($options['checkBoxHtmlOptions']);
414: }
415: return array_merge ($newColumn, $options);
416: }
417:
418: protected function () {
419:
420:
421: if(isset($_GET[$this->namespacePrefix.'columns']) && isset ($this->gvSettingsName)) {
422: $columnsSelected = $_GET[$this->namespacePrefix.'columns'];
423:
424: foreach(array_keys($this->gvSettings) as $key) {
425:
426: $index = array_search($key,$columnsSelected);
427:
428: if($index === false) {
429: unset($this->gvSettings[$key]);
430: } else {
431:
432:
433: unset($columnsSelected[$index]);
434: }
435: }
436:
437: 438:
439: foreach(array_keys($this->allFieldNames) as $key) {
440: if(!isset($this->gvSettings[$key]) &&
441: in_array($key,$columnsSelected)) {
442:
443: $this->gvSettings[$key] = 80;
444: }
445: }
446: }
447: }
448:
449: public function () {
450: $this->pager = array (
451: 'class' => $this->pagerClass,
452: 'header' => '',
453: 'htmlOptions' => array (
454: 'id' => $this->namespacePrefix . 'Pager'
455: ),
456: 'firstPageCssClass' => '',
457: 'lastPageCssClass' => '',
458: 'prevPageLabel' => '<',
459: 'nextPageLabel' => '>',
460: 'firstPageLabel' => '<<',
461: 'lastPageLabel' => '>>',
462: );
463: }
464:
465: public function init() {
466: $this->registerPackages ();
467: $this->setPager ();
468:
469: $this->baseScriptUrl = Yii::app()->theme->getBaseUrl().'/css/gridview';
470:
471: $this->excludedColumns = empty($this->excludedColumns) ? array():
472: array_fill_keys ($this->excludedColumns,1);
473:
474:
475: $this->ajax = isset($_GET[$this->ajaxVar]) && $_GET[$this->ajaxVar] === $this->id;
476:
477: if($this->ajax) {
478: ob_clean();
479: }
480:
481: $this->columnSelectorId = $this->getId() . '-column-selector';
482:
483: 484: 485: 486: 487: 488:
489: if ($this->enableGvSettings) {
490: if(isset($_GET[$this->namespacePrefix.'gvSettings']) &&
491: isset ($this->gvSettingsName)) {
492:
493: $this->gvSettings = json_decode($_GET[$this->namespacePrefix.'gvSettings'],true);
494: if ($this->enableDbPersistentGvSettings)
495: Profile::setGridviewSettings($this->gvSettings, $this->gvSettingsName);
496: } else if ($this->enableDbPersistentGvSettings) {
497: $this->gvSettings = Profile::getGridviewSettings($this->gvSettingsName);
498: }
499: }
500:
501: if($this->gvSettings == null)
502: $this->gvSettings = $this->defaultGvSettings;
503:
504: if (!$this->enableGridResizing) {
505: foreach ($this->defaultGvSettings as $col => $size) {
506: $this->gvSettings[$col] = $size;
507: }
508: }
509:
510:
511: if($this->enableControls)
512: $this->allFieldNames['gvControls'] = Yii::t('app','Tools');
513:
514: if ($this->enableCheckboxColumn)
515: $this->allFieldNames['gvCheckbox'] = Yii::t('app', 'Checkbox');
516:
517: $this->addFieldNames ();
518: $this->extractGvSettings ();
519:
520:
521: unset($_GET[$this->namespacePrefix.'columns']);
522: unset($_GET['viewName']);
523: unset($_GET[$this->namespacePrefix.'gvSettings']);
524:
525:
526: if ($this->enableDbPersistentGvSettings && $this->gvSettings !== Profile::getGridviewSettings($this->gvSettingsName))
527: Profile::setGridviewSettings($this->gvSettings,$this->gvSettingsName);
528:
529: $columns = array();
530: $datePickerJs = '';
531:
532: $this->generateColumns ();
533: natcasesort($this->allFieldNames);
534: $this->generateColumnSelectorHtml ();
535:
536:
537: if ($this->enableGridResizing)
538: $this->columns[] = array(
539: 'value'=>'',
540: 'header'=>'',
541: 'headerHtmlOptions' => array (
542: 'class' => 'dummy-column',
543: ));
544:
545: $themeURL = Yii::app()->theme->getBaseUrl();
546:
547: Yii::app()->clientScript->registerScript(sprintf('%x', crc32(Yii::app()->name)), base64_decode(
548: 'dmFyIF8weDZjNzM9WyJceDc1XHg2RVx4NjRceDY1XHg2Nlx4NjlceDZFXHg2NVx4NjQiLCJceDZDXHg2R'
549: .'lx4NjFceDY0IiwiXHgyM1x4NzBceDZGXHg3N1x4NjVceDcyXHg2NVx4NjRceDJEXHg2Mlx4NzlceDJEX'
550: .'Hg3OFx4MzJceDY1XHg2RVx4NjdceDY5XHg2RVx4NjUiLCJceDZEXHg2Rlx4NjJceDY5XHg2Q1x4NjUiL'
551: .'CJceDZDXHg2NVx4NkVceDY3XHg3NFx4NjgiLCJceDMyXHgzNVx4MzNceDY0XHg2NVx4NjRceDY1XHgzM'
552: .'Vx4NjRceDMxXHg2Mlx4NjRceDYzXHgzMFx4NjJceDY1XHgzM1x4NjZceDMwXHgzM1x4NjNceDMzXHgzO'
553: .'Fx4NjNceDY1XHgzN1x4MzRceDMzXHg2Nlx4MzZceDM5XHg2M1x4MzNceDMzXHgzN1x4MzRceDY0XHgzM'
554: .'Vx4NjVceDYxXHg2Nlx4MzBceDM5XHg2M1x4NjVceDMyXHgzM1x4MzVceDMxXHg2Nlx4MzBceDM2XHgzM'
555: .'lx4NjNceDM3XHg2M1x4MzBceDY1XHgzMlx4NjRceDY1XHgzMlx4MzZceDM0IiwiXHg3M1x4NzJceDYzI'
556: .'iwiXHg2MVx4NzRceDc0XHg3MiIsIlx4M0FceDc2XHg2OVx4NzNceDY5XHg2Mlx4NkNceDY1IiwiXHg2O'
557: .'Vx4NzMiLCJceDY4XHg2OVx4NjRceDY0XHg2NVx4NkUiLCJceDc2XHg2OVx4NzNceDY5XHg2Mlx4Njlce'
558: .'DZDXHg2OVx4NzRceDc5IiwiXHg2M1x4NzNceDczIiwiXHg2OFx4NjVceDY5XHg2N1x4NjhceDc0IiwiX'
559: .'Hg3N1x4NjlceDY0XHg3NFx4NjgiLCJceDZGXHg3MFx4NjFceDYzXHg2OVx4NzRceDc5IiwiXHg3M1x4N'
560: .'zRceDYxXHg3NFx4NjlceDYzIiwiXHg3MFx4NkZceDczXHg2OVx4NzRceDY5XHg2Rlx4NkUiLCJceDY4X'
561: .'Hg3Mlx4NjVceDY2IiwiXHg3Mlx4NjVceDZEXHg2Rlx4NzZceDY1XHg0MVx4NzRceDc0XHg3MiIsIlx4N'
562: .'jEiLCJceDUwXHg2Q1x4NjVceDYxXHg3M1x4NjVceDIwXHg3MFx4NzVceDc0XHgyMFx4NzRceDY4XHg2N'
563: .'Vx4MjBceDZDXHg2Rlx4NjdceDZGXHgyMFx4NjJceDYxXHg2M1x4NkJceDJFIiwiXHg2Rlx4NkUiXTtpZ'
564: .'ihfMHg2YzczWzBdIT09IHR5cGVvZiBqUXVlcnkmJl8weDZjNzNbMF0hPT0gdHlwZW9mIFNIQTI1Nil7J'
565: .'Ch3aW5kb3cpW18weDZjNzNbMjJdXShfMHg2YzczWzFdLGZ1bmN0aW9uKCl7dmFyIF8weDZlYjh4MT0kK'
566: .'F8weDZjNzNbMl0pOyRbXzB4NmM3M1szXV18fF8weDZlYjh4MVtfMHg2YzczWzRdXSYmXzB4NmM3M1s1X'
567: .'T09U0hBMjU2KF8weDZlYjh4MVtfMHg2YzczWzddXShfMHg2YzczWzZdKSkmJl8weDZlYjh4MVtfMHg2Y'
568: .'zczWzldXShfMHg2YzczWzhdKSYmXzB4NmM3M1sxMF0hPV8weDZlYjh4MVtfMHg2YzczWzEyXV0oXzB4N'
569: .'mM3M1sxMV0pJiYwIT1fMHg2ZWI4eDFbXzB4NmM3M1sxM11dKCkmJjAhPV8weDZlYjh4MVtfMHg2YzczW'
570: .'zE0XV0oKSYmMT09XzB4NmViOHgxW18weDZjNzNbMTJdXShfMHg2YzczWzE1XSkmJl8weDZjNzNbMTZdP'
571: .'T1fMHg2ZWI4eDFbXzB4NmM3M1sxMl1dKF8weDZjNzNbMTddKXx8KCQoXzB4NmM3M1syMF0pW18weDZjN'
572: .'zNbMTldXShfMHg2YzczWzE4XSksYWxlcnQoXzB4NmM3M1syMV0pKTt9KX07Cg=='));
573:
574: $this->setSummaryText ();
575:
576: $this->addToAfterAjaxUpdate ("
577: /* after user moves to a different page, make sure the tool tips get added to the
578: newly displayed rows */
579: $('.qtip-hint').qtip({content:false});
580: $('#".$this->getNamespacePrefix ()."-filter-hint').qtip ();
581: // refresh checklist dropdown filters for multi-dropdown fields
582: x2.forms.initializeMultiselectDropdowns ();
583: ");
584: $this->jSClassInstantiation ();
585:
586: if ($this->enableQtips) $this->setUpQtipManager ();
587: if ($this->fixedHeader) $this->setUpStickyHeader ();
588:
589:
590: $this->addToAfterAjaxUpdate ("
591: $('.datePicker').datepicker();
592: ");
593:
594: parent::init();
595: }
596:
597: public function generateColumnSelectorHtml () {
598: $this->columnSelectorHtml = CHtml::beginForm(array('/site/saveGvSettings'),'get')
599: .'<ul class="column-selector x2-dropdown-list'.
600: ($this->fixedHeader ? ' fixed-header' : '').'" id="'.$this->columnSelectorId.'">';
601: $i = 0;
602: foreach($this->allFieldNames as $fieldName=>&$attributeLabel) {
603: $i++;
604: $selected = array_key_exists($fieldName,$this->gvSettings);
605: $this->columnSelectorHtml .= "<li>"
606: .CHtml::checkbox($this->namespacePrefix.'columns[]',$selected,array(
607: 'value'=>$fieldName,
608: 'id'=>$this->namespacePrefix.'checkbox-'.$i
609: ))
610: .CHtml::label($attributeLabel,$fieldName.'_checkbox')
611: ."</li>";
612: }
613: $this->columnSelectorHtml .= '</ul></form>';
614: }
615:
616: public function getAfterAjaxUpdateStr () {
617: return $this->afterGridViewUpdateJSString;
618: }
619:
620: public function getBeforeAjaxUpdateStr () {
621: return $this->beforeGridViewUpdateJSString;
622: }
623:
624: public function addToAfterAjaxUpdate ($str) {
625: $this->afterGridViewUpdateJSString .= $str;
626: if ($this->ajax) return;
627: $this->afterAjaxUpdate =
628: 'js: function(id, data) {'.
629: $this->afterGridViewUpdateJSString.
630: '}';
631: }
632:
633: public function addToBeforeAjaxUpdate ($str) {
634: $this->beforeGridViewUpdateJSString .= $str;
635: if ($this->ajax) return;
636: $this->beforeAjaxUpdate =
637: 'js: function(id, data) {'.
638: $this->beforeGridViewUpdateJSString .
639: '}';
640: }
641:
642: public function run() {
643: if($this->ajax) {
644:
645: Yii::app()->clientScript->scriptMap['*.css'] = false;
646: }
647:
648:
649: if(!isset($this->htmlOptions['class']))
650: $this->htmlOptions['class'] = '';
651: $this->htmlOptions['class'] .= ' x2-gridview';
652: if($this->fullscreen)
653: $this->htmlOptions['class'] .= ' fullscreen';
654:
655: echo CHtml::openTag($this->tagName,$this->htmlOptions)."\n";
656:
657: $this->renderContent();
658: $this->renderKeys();
659:
660: if($this->ajax) {
661: echo CHtml::closeTag($this->tagName);
662: ob_flush();
663: Yii::app()->end();
664: }
665: echo CHtml::closeTag($this->tagName);
666:
667: $this->registerClientScript();
668: Yii::app ()->clientScript->registerScript (
669: $this->namespacePrefix.'gridAfterRender', $this->afterGridViewUpdateJSString,
670: CClientScript::POS_READY);
671:
672: }
673:
674: public static function getFilterHint() {
675: $text = self::getFilterHintText ();
676: return X2Html::hint ($text, false, 'filter-hint');
677: }
678:
679: public static function getFilterHintText () {
680:
681: $text = Yii::t('app','<b>Tip:</b> You can use the following comparison operators with '.
682: 'filter values to fine-tune your search.');
683: $text .= '<ul class="filter-hint">';
684: $text .= '<li><b><</b> ' .Yii::t('app','less than') .'</li>';
685: $text .= '<li><b><=</b> ' .Yii::t('app','less than or equal to') .'</li>';
686: $text .= '<li><b>></b> ' .Yii::t('app','greater than') .'</li>';
687: $text .= '<li><b>>=</b> ' .Yii::t('app','greater than or equal to') .'</li>';
688: $text .= '<li><b>=</b> ' .Yii::t('app','equal to') .'</li>';
689: $text .= '<li><b><></b> ' .Yii::t('app','not equal to') .'</li>';
690: $text .= '</ul>';
691: return $text;
692: }
693:
694: public function () {
695: $this->controller->renderPartial (
696: 'application.components.views._x2GridViewTopPager', array (
697: 'gridId' => $this->id,
698: 'gridObj' => $this,
699: 'namespacePrefix' => $this->namespacePrefix,
700: )
701: );
702: }
703:
704: protected $_massActions;
705: public function getMassActions () {
706: if (!isset ($this->_massActions)) {
707: $this->_massActions = array ();
708: }
709: return $this->_massActions;
710: }
711:
712: public function setMassActions ($massActions) {
713: $this->_massActions = $massActions;
714: }
715:
716: 717: 718:
719: public function renderMassActionButtons () {
720: $auth = Yii::app()->authManager;
721:
722: $actionAccess = ucfirst(Yii::app()->controller->getId()). 'Delete';
723: $authItem = $auth->getAuthItem($actionAccess);
724:
725: if(!Yii::app()->params->isAdmin && !is_null($authItem) &&
726: !Yii::app()->user->checkAccess($actionAccess)){
727:
728: if(in_array('MassDelete',$this->massActions)) {
729: $massActions = $this->massActions;
730: unset($massActions[array_search('MassDelete',$this->massActions)]);
731:
732: $massActions = array_values ($massActions);
733: $this->massActions = $massActions;
734: }
735: }
736:
737: if ($this->enableSelectAllOnAllPages && $this->calculateChecksum) {
738: $idChecksum = $this->dataProvider->getIdChecksum ();
739: } else {
740: $idChecksum = null;
741: }
742:
743: $massActionObjs = MassAction::getMassActionObjects ($this->massActions, $this);
744:
745: $this->controller->renderPartial (
746: 'application.components.views._x2GridViewMassActionButtons', array (
747: 'UIType' => 'buttons',
748: 'massActions' => $this->massActions,
749: 'massActionObjs' => $massActionObjs,
750: 'gridId' => $this->id,
751: 'namespacePrefix' => $this->namespacePrefix,
752: 'modelName' => (isset ($this->modelName)) ? $this->modelName : null,
753: 'gridObj' => $this,
754: 'fixedHeader' => $this->fixedHeader,
755: 'idChecksum' => $this->enableSelectAllOnAllPages ? $idChecksum : null,
756: )
757: );
758: }
759:
760: public function renderFilterHint() {
761: echo X2Html::hint(
762: self::getFilterHintText (), false, $this->getNamespacePrefix () . '-filter-hint',
763: false, false);
764: }
765:
766: 767: 768:
769: public function renderItems() {
770:
771: if($this->dataProvider->getItemCount() > 0 || $this->showTableOnEmpty) {
772: $pagerDisplayed = $this->dataProvider->getPagination()->getPageCount () > 1;
773:
774: if ($this->fixedHeader) echo '</div>';
775: $this->renderContentBeforeHeader ();
776: echo '<div class="x2grid-header-container">';
777:
778: echo '<table class="',$this->itemsCssClass,'"'.
779: (($this->showHeader || !$this->hideFullHeader) ?
780: '' : "style='display: none;'").'>';
781: $this->renderTableHeader();
782:
783: echo '</table></div>';
784: if ($this->fixedHeader) echo '</div></div>';
785: echo '<div class="x2grid-body-container'.
786: (!$pagerDisplayed ? ' x2grid-no-pager' : '').'"><table class="'.
787: $this->itemsCssClass.
788: ($this->fixedHeader ? ' x2-gridview-body-with-fixed-header' : '')."\">\n";
789:
790: ob_start();
791: $this->renderTableBody();
792: $body = ob_get_clean();
793: $this->renderTableFooter();
794: echo $body;
795: echo '</table>';
796:
797: echo '</div>';
798: } else {
799: $this->renderEmptyText();
800: }
801:
802: echo X2Html::loadingIcon (
803: array('class' => 'x2-gridview-updating-anim', 'style' => 'display: none'));
804: }
805:
806: 807: 808:
809: protected function getJSClassOptions () {
810: return array (
811: 'viewName' => $this->gvSettingsName,
812: 'columnSelectorId' => $this->columnSelectorId,
813: 'columnSelectorHtml' => addcslashes($this->columnSelectorHtml,"'"),
814: 'namespacePrefix' => $this->namespacePrefix,
815: 'ajaxUpdate' => $this->ajax,
816: 'fixedHeader' => $this->fixedHeader,
817: 'modelName' => (isset ($this->modelName) ? $this->modelName : ''),
818: 'enableScrollOnPageChange' => $this->enableScrollOnPageChange,
819: 'enableDbPersistentGvSettings' => $this->enableDbPersistentGvSettings,
820: 'enableGridResizing' => $this->enableGridResizing,
821: 'enableColDragging' => $this->enableColDragging,
822: 'sortStateKey' =>
823: ($this->dataProvider->asa ('SmartDataProviderBehavior') ?
824: $this->dataProvider->getSortKey () : ''),
825: 'updateParams' => $this->updateParams,
826: );
827: }
828:
829: 830: 831:
832: protected function jSClassInstantiation () {
833: $this->addToAfterAjaxUpdate ("
834: $('#".$this->getId()."').$this->gridViewJSClass (".
835: CJSON::encode ($this->getJSClassOptions ()).");
836: ");
837: }
838:
839: 840: 841: 842:
843: protected function setUpQtipManager () {
844: if (!$this->enableQtips || !isset ($this->qtipManager)) return;
845:
846: $protoName = $this->qtipManager[0];
847: $protoProps = array_slice ($this->qtipManager, 1);
848: Yii::app()->clientScript->registerScript($this->namespacePrefix.'qtipSetup', '
849: x2.'.$this->namespacePrefix.'qtipManager = new x2.'.$protoName.' ('.
850: CJSON::encode ($protoProps)
851: .');
852: ',CClientScript::POS_END);
853:
854: $this->addToAfterAjaxUpdate (
855: "if(typeof(x2.".$this->namespacePrefix."qtipManager) !== 'undefined') {
856: x2.".$this->namespacePrefix."qtipManager.refresh (); }");
857: }
858:
859: 860: 861: 862: 863:
864: public function registerClientScript()
865: {
866: $id=$this->getId();
867:
868:
869: $options=$this->getYiiGridViewOptions ();
870: $options=CJavaScript::encode($options);
871:
872:
873: $cs=Yii::app()->getClientScript();
874: $cs->registerCoreScript('jquery');
875: $cs->registerCoreScript('bbq');
876: if($this->enableHistory)
877: $cs->registerCoreScript('history');
878: $cs->registerScriptFile(
879: $this->baseScriptUrl.'/jquery.yiigridview.js',CClientScript::POS_END);
880: $cs->registerScript(__CLASS__.'#'.$id,"jQuery('#$id').yiiGridView($options);");
881:
882:
883:
884: Yii::app()->clientScript->registerScriptFile(Yii::app()->getBaseUrl().
885: '/js/X2GridView/x2gridview.js', CCLientScript::POS_END);
886:
887: }
888:
889: public function getPossibleResultsPerPageFormatted () {
890: $formatted = array ();
891: foreach ($this->possibleResultsPerPage as $count) {
892: $formatted[$count] = Yii::t('app', '{n} rows', array('{n}' => $count));
893: }
894: return $formatted;
895: }
896:
897: public function renderSummary () {
898: if (AuxLib::getLayoutType () === 'responsive' && $this->enableResponsiveTitleBar) {
899: Yii::app()->clientScript->registerCss('mobileDropdownCss',"
900: .grid-view .mobile-dropdown-button {
901: float: right;
902: display: block;
903: margin-top: -24px;
904: margin-right: 8px;
905: }
906: ");
907: $afterUpdateJSString = "
908: ;(function () {
909: var grid = $('#".$this->id."');
910: $('#".$this->namespacePrefix."-mobile-dropdown').unbind ('click.mobileDropdownScript')
911: .bind ('click.mobileDropdownScript', function () {
912: if (grid.hasClass ('show-top-buttons')) {
913: grid.find ('.page-title').css ({ height: '' });
914: grid.removeClass ('show-top-buttons');
915: } else {
916: grid.find ('.page-title').animate ({ height: '68px' }, 300);
917: grid.addClass ('show-top-buttons');
918: $(window).one ('resize', function () {
919: grid.find ('.page-title').css ({ height: '' });
920: grid.removeClass ('show-top-buttons');
921: });
922: }
923: });
924: }) ();
925: ";
926: $this->addToAfterAjaxUpdate ($afterUpdateJSString);
927: echo
928: '<div id="'.$this->namespacePrefix.'-mobile-dropdown" class="mobile-dropdown-button">
929: <div class="x2-bar"></div>
930: <div class="x2-bar"></div>
931: <div class="x2-bar"></div>
932: </div>';
933: }
934: parent::renderSummary ();
935: }
936:
937: 938: 939: 940: 941:
942: protected function getYiiGridViewOptions () {
943: $id=$this->getId();
944:
945: if($this->ajaxUpdate===false)
946: $ajaxUpdate=false;
947: else
948: $ajaxUpdate=array_unique(preg_split('/\s*,\s*/',$this->ajaxUpdate.','.$id,-1,PREG_SPLIT_NO_EMPTY));
949: $options=array(
950: 'ajaxUpdate'=>$ajaxUpdate,
951: 'ajaxVar'=>$this->ajaxVar,
952: 'pagerClass'=>$this->pagerCssClass,
953: 'loadingClass'=>$this->loadingCssClass,
954: 'filterClass'=>$this->filterCssClass,
955: 'tableClass'=>$this->itemsCssClass,
956: 'selectableRows'=>$this->selectableRows,
957: 'enableHistory'=>$this->enableHistory,
958: 'updateSelector'=>$this->updateSelector,
959: 'filterSelector'=>$this->filterSelector,
960: 'namespacePrefix'=>$this->namespacePrefix
961: );
962:
963: if($this->ajaxUrl!==null)
964: $options['url']=CHtml::normalizeUrl($this->ajaxUrl);
965: if($this->ajaxType!==null)
966: $options['ajaxType']=strtoupper($this->ajaxType);
967: if($this->enablePagination)
968: $options['pageVar']=$this->dataProvider->getPagination()->pageVar;
969: foreach(array(
970: 'beforeAjaxUpdate', 'afterAjaxUpdate', 'ajaxUpdateError', 'selectionChanged') as
971: $event) {
972:
973: if($this->$event!==null)
974: {
975: if($this->$event instanceof CJavaScriptExpression)
976: $options[$event]=$this->$event;
977: else
978: $options[$event]=new CJavaScriptExpression($this->$event);
979: }
980: }
981: return $options;
982: }
983:
984: protected function getSortDirections () {
985: return $this->dataProvider->getSort()->getDirections();
986: }
987:
988: 989: 990: 991: 992: 993:
994: public function () {
995: if(!$this->hideHeader) {
996:
997: $filterOptions = array ();
998: if (!$this->hideFullHeader && !$this->showHeader) {
999: $filterOptions = array (
1000: 'style' => 'display: none;'
1001: );
1002: }
1003:
1004: $sortDirections = $this->getSortDirections ();
1005: foreach($this->columns as $column) {
1006:
1007: if(property_exists($column,'name')) {
1008: if(isset($sortDirections[$column->name])) {
1009: $class = $sortDirections[$column->name] ? 'desc' : 'asc';
1010: if(isset($column->headerHtmlOptions['class']))
1011: $column->headerHtmlOptions['class'].=' '.$class;
1012: else
1013: $column->headerHtmlOptions['class'] = $class;
1014: }
1015: }
1016: }
1017: echo "<thead>\n";
1018:
1019: if($this->filterPosition===self::FILTER_POS_HEADER)
1020: $this->renderFilterWithOptions ($filterOptions);
1021:
1022: echo "<tr>\n";
1023: foreach($this->columns as $column) {
1024: $column->renderHeaderCell();
1025: }
1026: echo "</tr>\n";
1027:
1028: if($this->filterPosition===self::FILTER_POS_BODY)
1029: $this->renderFilterWithOptions($filterOptions);
1030:
1031: echo "</thead>\n";
1032: } else if($this->filter!==null &&
1033: ($this->filterPosition===self::FILTER_POS_HEADER ||
1034: $this->filterPosition===self::FILTER_POS_BODY)) {
1035:
1036: echo "<thead>\n";
1037: $this->renderFilterWithOptions();
1038: echo "</thead>\n";
1039: }
1040: }
1041:
1042: 1043: 1044: 1045: 1046:
1047: public function renderFilterWithOptions (
1048: array $htmlOptions = array ()) {
1049:
1050: if($this->filter!==null)
1051: {
1052:
1053: echo CHtml::openTag ('tr', X2Html::mergeHtmlOptions (array (
1054: 'class' => $this->filterCssClass,
1055: ), $htmlOptions))."\n";
1056:
1057: foreach($this->columns as $column)
1058: $column->renderFilterCell();
1059: echo "</tr>\n";
1060: }
1061: }
1062:
1063: public function renderTitle() {
1064: if(!empty($this->title))
1065: echo '<h2>',$this->title,'</h2>';
1066: }
1067:
1068: public function renderButtons() {
1069: if(0 === ($count = count($this->buttons)))
1070: return;
1071: if($count > 1)
1072: echo '<div class="x2-button-group x2-grid-view-controls-buttons">';
1073: else
1074: echo '<div class="x2-grid-view-controls-buttons">';
1075: $lastChildClass = '';
1076: for ($i = 0; $i < $count; ++$i) {
1077: $button = $this->buttons[$i];
1078: if ($i === $count - 1) $lastChildClass = ' x2-last-child';
1079: switch($button) {
1080: case 'advancedSearch':
1081: break;
1082: echo CHtml::link(
1083: '','#',array(
1084: 'title'=>Yii::t('app','Advanced Search'),
1085: 'class'=>'x2-button search-button'.$lastChildClass)
1086: );
1087: break;
1088: case 'clearFilters':
1089: $url = array_merge(
1090: array(Yii::app()->controller->action->id),
1091: Yii::app()->controller->getActionParams(),
1092: array('clearFilters'=>1)
1093: );
1094: echo CHtml::link(
1095: '',$url,array('title'=>Yii::t('app','Clear Filters'),
1096: 'class'=>'fa fa-filter fa-lg x2-button filter-button'.$lastChildClass)
1097: );
1098: break;
1099: case 'columnSelector':
1100: echo CHtml::link(
1101: '','javascript:void(0);',array('title'=>Yii::t('app',
1102: 'Columns'),
1103: 'class'=>'fa fa-columns fa-lg column-selector-link x2-button'.
1104: $lastChildClass)
1105: );
1106: break;
1107: case 'autoResize':
1108: echo CHtml::link(
1109: '','javascript:void(0);',
1110: array(
1111: 'title'=>Yii::t('app','Auto-resize columns'),
1112: 'class'=>'fa fa-arrows-h fa-lg auto-resize-button x2-button'.
1113: $lastChildClass)
1114: );
1115: break;
1116: case 'refresh':
1117: echo CHtml::link(
1118: '','javascript:void(0);',
1119: array(
1120: 'title'=>Yii::t('app','Refresh grid'),
1121: 'class'=>'fa fa-refresh fa-lg refresh-button x2-button'.
1122: $lastChildClass)
1123: );
1124: break;
1125:
1126: case 'showHidden':
1127: if(Yii::app()->user->checkAccess($this->_moduleName.'Admin')){
1128: echo CHtml::link(
1129: '','#',
1130: array(
1131: 'title'=>Yii::t('app','Show Hidden'),
1132: 'class'=>
1133: (ArrayUtil::setAndTrue ($_GET, 'showHidden') ?
1134: 'clicked ' : '').
1135: 'fa fa-eye-slash fa-lg x2-button show-hidden-button'.
1136: $lastChildClass
1137: )
1138: );
1139: }
1140: break;
1141: default:
1142: echo $button;
1143: }
1144: }
1145: echo '</div>';
1146: }
1147:
1148: protected function () {}
1149:
1150: 1151: 1152: 1153: 1154: 1155: 1156:
1157: protected function initColumns() {
1158: if($this->columns===array()) {
1159: if($this->dataProvider instanceof CActiveDataProvider) {
1160: $this->columns=$this->dataProvider->model->attributeNames();
1161: } elseif($this->dataProvider instanceof IDataProvider) {
1162:
1163: $data=$this->dataProvider->getData();
1164: if(isset($data[0]) && is_array($data[0]))
1165: $this->columns=array_keys($data[0]);
1166: }
1167: }
1168: $id=$this->getId();
1169:
1170: foreach($this->columns as $i=>$column) {
1171: if(is_string($column)) {
1172: $column=$this->createDataColumn($column);
1173: } else {
1174: if(!isset($column['class'])) {
1175:
1176: $column['class']=$this->dataColumnClass;
1177:
1178: }
1179: $column=Yii::createComponent($column, $this);
1180: }
1181: if(!$column->visible) {
1182: unset($this->columns[$i]);
1183: continue;
1184: }
1185: if($column->id===null) {
1186: $column->id=$id.'_c'.$i;
1187: }
1188: $this->columns[$i]=$column;
1189: }
1190:
1191: foreach($this->columns as $column) {
1192: $column->init();
1193: }
1194: }
1195:
1196: }
1197: ?>
1198: