Overview

Packages

  • application
    • commands
    • components
      • actions
      • filters
      • leftWidget
      • permissions
      • sortableWidget
      • util
      • webupdater
      • x2flow
        • actions
        • triggers
      • X2GridView
      • X2Settings
    • controllers
    • models
      • embedded
    • modules
      • accounts
        • controllers
        • models
      • actions
        • controllers
        • models
      • calendar
        • controllers
        • models
      • charts
        • models
      • contacts
        • controllers
        • models
      • docs
        • components
        • controllers
        • models
      • groups
        • controllers
        • models
      • marketing
        • components
        • controllers
        • models
      • media
        • controllers
        • models
      • mobile
        • components
      • opportunities
        • controllers
        • models
      • products
        • controllers
        • models
      • quotes
        • controllers
        • models
      • services
        • controllers
        • models
      • template
        • models
      • users
        • controllers
        • models
      • workflow
        • controllers
        • models
      • x2Leads
        • controllers
        • models
  • None
  • system
    • base
    • caching
    • console
    • db
      • ar
      • schema
    • validators
    • web
      • actions
      • auth
      • helpers
      • widgets
        • captcha
        • pagers
  • zii
    • widgets
      • grid

Classes

  • AccountsGridViewProfileWidget
  • ActionMenu
  • ActionsGridViewProfileWidget
  • ActionsQuickCreateRelationshipBehavior
  • ActiveDateRangeInput
  • ApplicationConfigBehavior
  • Attachments
  • ChatBox
  • CommonControllerBehavior
  • ContactMapInlineTags
  • ContactsGridViewProfileWidget
  • CronForm
  • CSaveRelationsBehavior
  • DateRangeInputsWidget
  • DocsGridViewProfileWidget
  • DocViewer
  • DocViewerProfileWidget
  • EButtonColumnWithClearFilters
  • EmailDeliveryBehavior
  • EmailProgressControl
  • EncryptedFieldsBehavior
  • EventsChartProfileWidget
  • FileUploader
  • FontPickerInput
  • Formatter
  • FormView
  • GridViewWidget
  • History
  • IframeWidget
  • ImportExportBehavior
  • InlineActionForm
  • InlineEmailAction
  • InlineEmailForm
  • InlineEmailModelBehavior
  • InlineQuotes
  • JSONEmbeddedModelFieldsBehavior
  • JSONFieldsDefaultValuesBehavior
  • LeadRoutingBehavior
  • LeftWidget
  • LoginThemeHelper
  • LoginThemeHelperBase
  • MarketingGridViewProfileWidget
  • MediaBox
  • MessageBox
  • MobileFormatter
  • MobileFormLayoutRenderer
  • MobileLayoutRenderer
  • MobileLoginThemeHelper
  • MobileViewLayoutRenderer
  • ModelFileUploader
  • NewWebLeadsGridViewProfileWidget
  • NormalizedJSONFieldsBehavior
  • NoteBox
  • OnlineUsers
  • OpportunitiesGridViewProfileWidget
  • Panel
  • ProfileDashboardManager
  • ProfileGridViewWidget
  • ProfileLayoutEditor
  • ProfilesGridViewProfileWidget
  • Publisher
  • PublisherActionTab
  • PublisherCalendarEventTab
  • PublisherCallTab
  • PublisherCommentTab
  • PublisherEventTab
  • PublisherSmallCalendarEventTab
  • PublisherTab
  • PublisherTimeTab
  • QuickContact
  • QuickCreateRelationshipBehavior
  • QuotesGridViewProfileWidget
  • RecordAliasesWidget
  • RecordViewLayoutManager
  • RecordViewWidgetManager
  • RememberPagination
  • Reminders
  • ResponseBehavior
  • ResponsiveHtml
  • SearchIndexBehavior
  • ServicesGridViewProfileWidget
  • SmallCalendar
  • SmartActiveDataProvider
  • SmartDataProviderBehavior
  • SmartSort
  • SocialForm
  • SortableWidgetManager
  • SortableWidgets
  • TagBehavior
  • TagCloud
  • TemplatesGridViewProfileWidget
  • TimeZone
  • TopContacts
  • TopSites
  • TransformedFieldStorageBehavior
  • TranslationLogger
  • TwitterFeed
  • TwoColumnSortableWidgetManager
  • UpdaterBehavior
  • UpdatesForm
  • UserIdentity
  • UsersChartProfileWidget
  • WorkflowBehavior
  • X2ActiveGridView
  • X2ActiveGridViewForSortableWidgets
  • X2AssetManager
  • X2AuthManager
  • X2ChangeLogBehavior
  • X2ClientScript
  • X2Color
  • X2DateUtil
  • X2FixtureManager
  • X2FlowFormatter
  • X2GridView
  • X2GridViewBase
  • X2GridViewForSortableWidgets
  • X2GridViewSortableWidgetsBehavior
  • X2LeadsGridViewProfileWidget
  • X2LinkableBehavior
  • X2ListView
  • X2PillBox
  • X2ProgressBar
  • X2SmartSearchModelBehavior
  • X2TimestampBehavior
  • X2TranslationBehavior
  • X2UrlRule
  • X2WebModule
  • X2Widget
  • X2WidgetList
  • Overview
  • Package
  • Class
  • Tree
   1: <?php
   2: /*****************************************************************************************
   3:  * X2Engine Open Source Edition is a customer relationship management program developed by
   4:  * X2Engine, Inc. Copyright (C) 2011-2016 X2Engine Inc.
   5:  * 
   6:  * This program is free software; you can redistribute it and/or modify it under
   7:  * the terms of the GNU Affero General Public License version 3 as published by the
   8:  * Free Software Foundation with the addition of the following permission added
   9:  * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
  10:  * IN WHICH THE COPYRIGHT IS OWNED BY X2ENGINE, X2ENGINE DISCLAIMS THE WARRANTY
  11:  * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
  12:  * 
  13:  * This program is distributed in the hope that it will be useful, but WITHOUT
  14:  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  15:  * FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
  16:  * details.
  17:  * 
  18:  * You should have received a copy of the GNU Affero General Public License along with
  19:  * this program; if not, see http://www.gnu.org/licenses or write to the Free
  20:  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  21:  * 02110-1301 USA.
  22:  * 
  23:  * You can contact X2Engine, Inc. P.O. Box 66752, Scotts Valley,
  24:  * California 95067, USA. or at email address contact@x2engine.com.
  25:  * 
  26:  * The interactive user interfaces in modified source and object code versions
  27:  * of this program must display Appropriate Legal Notices, as required under
  28:  * Section 5 of the GNU Affero General Public License version 3.
  29:  * 
  30:  * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
  31:  * these Appropriate Legal Notices must retain the display of the "Powered by
  32:  * X2Engine" logo. If the display of the logo is not reasonably feasible for
  33:  * technical reasons, the Appropriate Legal Notices must display the words
  34:  * "Powered by X2Engine".
  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:  * Custom grid view display function.
  44:  *
  45:  * Displays a dynamic grid view that permits save-able resizing and reordering of
  46:  * columns and also the adding of new columns based on the available fields for
  47:  * the model.
  48:  *
  49:  * @package application.components
  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 $fixedHeader = 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 $showHeader = true;
  74:     public $hideFullHeader = false;
  75:     public $possibleResultsPerPage = array (10, 20, 30, 40, 50, 75, 100);
  76:     public $hideSummary = false;
  77: 
  78:     /**
  79:      * @var string $pagerClass
  80:      */
  81:     public $pagerClass = 'CLinkPager';
  82:      
  83:     /**
  84:      * @var bool If true, the users will be able to select & perform mass action on all records 
  85:      *  all records in the dataprovider.
  86:      */
  87:     public $enableSelectAllOnAllPages = false;
  88: 
  89:     public $calculateChecksum = false;
  90: 
  91:     /**
  92:      * @var string $gvControlsTemplate
  93:      */
  94:     public $gvControlsTemplate = '{view} {update} {delete}';
  95: 
  96:     /**
  97:      * @var string $dataColumnClass
  98:      */
  99:     public $dataColumnClass = 'CDataColumn'; 
 100: 
 101:     /**
 102:      * @var bool If true, window will automatically scroll to the top when the page is changed
 103:      */
 104:     public $enableScrollOnPageChange = true;
 105: 
 106:     // JS which will be executed before/after yiiGridView.update () updates the grid view
 107:     public $afterGridViewUpdateJSString = "";
 108:     public $beforeGridViewUpdateJSString = "";
 109: 
 110:     /**
 111:      * @var array the JS prototype name followed by properties of that prototype 
 112:      */
 113:     public $qtipManager;
 114: 
 115:     /**
 116:      * @var bool whether qtips should be used, refresh method should be defined in a JS sub 
 117:      *  prototype of X2GridViewQtipManager
 118:      */
 119:     public $enableQtips = false;
 120: 
 121:     /**
 122:      * @var string $moduleName Name of the module that the grid view is being
 123:      *  used in, for purposes of access control.
 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:      * @var string Set to view name if value not passed to constructor. Used to save/access
 136:      *  gridview settings saved as a JSON property in the profile model
 137:      */
 138:     protected $_gvSettingsName;
 139: 
 140:     /**
 141:      * @var string Used to prefix javascript namespaces, GET parameter keys, Script names, and HTML
 142:      *  attributes. Allows multiple instances of X2GridView to work on the same page. Generated by
 143:      *  whitelisting the gridview id. 
 144:      */
 145:     protected $_namespacePrefix;
 146: 
 147:     abstract protected function setSummaryText ();
 148: 
 149:     abstract protected function generateColumns ();
 150:     
 151:     /**
 152:      * Used instead of a closure because closure definition was causing errors, possibly related 
 153:      * to APC cache size settings.
 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:      * Magic setter for gvSettingsName. 
 209:      * @param string $gvSettingsName
 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:      * Magic getter for gvSettingsName. If not set explicitly, will be set to viewName
 233:      * @return string  
 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:      * Magic setter for _namespacePrefix 
 246:      * @param string
 247:      */
 248:     public function setNamespacePrefix ($namespacePrefix) {
 249:         $this->_namespacePrefix = $namespacePrefix;
 250:     }
 251: 
 252:     /**
 253:      * Magic getter for _namespacePrefix 
 254:      * @return string
 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:      * This method is Copyright (c) 2008-2014 by Yii Software LLC
 266:      * http://www.yiiframework.com/license/ 
 267:      */
 268:     public function renderKeys()
 269:     {
 270:         echo CHtml::openTag('div',array(
 271:             /* x2modstart */ 
 272:             // prevents name conflicts in nested grids
 273:             'class'=>'keys '.$this->namespacePrefix.'keys',
 274:             /* x2modend */ 
 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:      * Registers JS which makes the grid header sticky
 285:      * Preconditions:
 286:      *     - The CGridView template string must be set up in a highly specific way
 287:      *         - Example:
 288:      *              '<div id="x2-gridview-top-bar-outer" class="x2-gridview-fixed-top-bar-outer">
 289:      *               <div id="x2-gridview-top-bar-inner" class="x2-gridview-fixed-top-bar-inner">
 290:      *               <div id="x2-gridview-page-title" class="x2-gridview-fixed-title">
 291:      *               {items}{pager}'
 292:      *          - there must be a pager and items.
 293:      *          - the three opening divs with the specified classes and ids are required. The 
 294:      *              divs
 295:      *            get closed after the grid header is printed.
 296:      *     - the X2GridView propert fixedHeader must be set to true
 297:      */
 298:     public function setUpStickyHeader () {
 299: 
 300:         // if the user is a guest, the left widgets will be hidden. remove padding to compensate
 301:         // for missing widgets
 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:      * Used to populate allFieldNames property with attribute labels indexed by
 357:      * attribute names.
 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 extractGvSettings () {
 419:         // update columns if user has submitted data
 420:         // has the user changed column visibility?
 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:                 // search $_GET['columns'] for the column
 426:                 $index = array_search($key,$columnsSelected);
 427: 
 428:                 if($index === false) { // if it's not in there,
 429:                     unset($this->gvSettings[$key]); // delete that junk
 430:                 } else { // othwerise, remove it from $_GET['columns']
 431: 
 432:                     // so the next part doesn't add it a second time
 433:                     unset($columnsSelected[$index]);
 434:                 }
 435:             }
 436: 
 437:             /* now go through $allFieldNames and add any fields that
 438:                are present in $_GET['columns'] but not already in the list */
 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; // default width of 80
 444:                 }
 445:             }
 446:         }
 447:     }
 448: 
 449:     public function setPager () {
 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:         // $this->id is the rendered HTML element's ID, i.e. "contacts-grid"
 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:         Get gridview settings by looking in the URL:
 485:         This condition will pass in the case that an ajax update occurs following an ajax request 
 486:         to save the grid view settings. It is necessary because it allows the grid view to render 
 487:         properly even before the new grid view settings have been saved to the database.
 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:         // Use the hard-coded defaults (note: gvSettings has column name keys:
 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:         // add controls column if specified
 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:         // prevents columns data from ending up in sort/pagination links
 521:         unset($_GET[$this->namespacePrefix.'columns']); 
 522:         unset($_GET['viewName']);
 523:         unset($_GET[$this->namespacePrefix.'gvSettings']);
 524: 
 525:         // save the new Gridview Settings
 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); // sort column names
 534:         $this->generateColumnSelectorHtml ();
 535:         
 536:         // one blank column for the resizing widget
 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:         // Re-enable a datepicker widget in the data columns
 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:             // remove any external CSS files
 645:             Yii::app()->clientScript->scriptMap['*.css'] = false;
 646:         }
 647: 
 648:         // give this a special class so the javascript can tell it apart from the Yii's gridviews 
 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>&lt;</b> '        .Yii::t('app','less than')                .'</li>';
 685:         $text .= '<li><b>&lt;=</b> '    .Yii::t('app','less than or equal to')        .'</li>';
 686:         $text .= '<li><b>&gt;</b> '        .Yii::t('app','greater than')            .'</li>';
 687:         $text .= '<li><b>&gt;=</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>&lt;&gt</b> '    .Yii::t('app','not equal to')                .'</li>';
 690:         $text .= '</ul>';
 691:         return $text;
 692:     }
 693: 
 694:     public function renderTopPager () {
 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:      * Display mass actions ui buttons in top bar and set up related JS
 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:                 // reindex so it's still a valid JSON array
 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:             )//, false, ($this->ajax ? true : false)
 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:      * Renders the data items for the grid view.
 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; // TFOOT must appear before TBODY according to the standard.
 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:      * @return array options to pass to grid view JS class constructor
 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:      * Register JS which instantiates grid view class
 831:      */
 832:     protected function jSClassInstantiation () {
 833:         $this->addToAfterAjaxUpdate ("
 834:             $('#".$this->getId()."').$this->gridViewJSClass (".
 835:                 CJSON::encode ($this->getJSClassOptions ()).");
 836:         ");
 837:     }
 838: 
 839:     /**
 840:      * If enableQtips is true, instantiates the qtipManager prototype with configuration and 
 841:      * prototype specified in qtipManager
 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:      * Registers necessary client scripts.
 861:      * This method is Copyright (c) 2008-2014 by Yii Software LLC
 862:      * http://www.yiiframework.com/license/ 
 863:      */
 864:     public function registerClientScript()
 865:     {
 866:         $id=$this->getId();
 867: 
 868:         /* x2modstart */ 
 869:         $options=$this->getYiiGridViewOptions ();
 870:         $options=CJavaScript::encode($options);
 871:         /* x2modend */ 
 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:         /* x2modstart */ 
 883:         // Adds script essential to modifying the gridview (and saving its configuration).
 884:         Yii::app()->clientScript->registerScriptFile(Yii::app()->getBaseUrl().
 885:             '/js/X2GridView/x2gridview.js', CCLientScript::POS_END);
 886:         /* x2modend */ 
 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:      * Code moved out of registerClientScript, allowing it to be more easily overridden
 939:      * This method is Copyright (c) 2008-2014 by Yii Software LLC
 940:      * http://www.yiiframework.com/license/ 
 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:      * Echoes the markup for the gridview's table header.
 990:      *
 991:      * This method is Copyright (c) 2008-2014 by Yii Software LLC
 992:      * http://www.yiiframework.com/license/
 993:      */
 994:     public function renderTableHeader() {
 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:                 // determine sort state for this column (adapted from CSort::link())
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:      * Like renderFilter, but with html attribute options
1044:      * This method is Copyright (c) 2008-2014 by Yii Software LLC
1045:      * http://www.yiiframework.com/license/ 
1046:      */
1047:     public function renderFilterWithOptions (
1048:         /* x2modstart */array $htmlOptions = array ()/* x2modend */) {
1049: 
1050:         if($this->filter!==null)
1051:         {
1052:             /* x2modstart */ 
1053:             echo CHtml::openTag ('tr', X2Html::mergeHtmlOptions (array (
1054:                 'class' => $this->filterCssClass,
1055:             ), $htmlOptions))."\n";
1056:             /* x2modend */ 
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; // remove until fixed
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 renderContentBeforeHeader () {}
1149: 
1150:     /**
1151:      * Creates column objects and initializes them. Overrides {@link parent::initColumns}, 
1152:      * swapping hard coded reference to CDataColumn with the value of a public property.
1153:      *
1154:      * This method is Copyright (c) 2008-2014 by Yii Software LLC
1155:      * http://www.yiiframework.com/license/
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:                 // use the keys of the first row of data as the default columns
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:                     /* x2modstart */ 
1176:                     $column['class']=$this->dataColumnClass;
1177:                     /* x2modend */ 
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: 
X2CRM Documentation API documentation generated by ApiGen 2.8.0