diff --git a/code/GridFieldOrderableRows.php b/code/GridFieldOrderableRows.php index ee7bef9..97357e4 100755 --- a/code/GridFieldOrderableRows.php +++ b/code/GridFieldOrderableRows.php @@ -10,7 +10,14 @@ class GridFieldOrderableRows extends RequestHandler implements GridField_ColumnProvider, GridField_DataManipulator, GridField_HTMLProvider, - GridField_URLHandler { + GridField_URLHandler, + GridField_SaveHandler { + + /** + * @see $immediateUpdate + * @var boolean + */ + private static $default_immediate_update = true; private static $allowed_actions = array( 'handleReorder', @@ -25,6 +32,15 @@ class GridFieldOrderableRows extends RequestHandler implements */ protected $sortField; + /** + * If set to true, when an item is re-ordered, it will update on the + * database and refresh the gridfield. When set to false, it will only + * update the sort order when the record is saved. + * + * @var boolean + */ + protected $immediateUpdate; + /** * Extra sort fields to apply before the sort field. * @@ -47,6 +63,7 @@ class GridFieldOrderableRows extends RequestHandler implements public function __construct($sortField = 'Sort') { parent::__construct(); $this->sortField = $sortField; + $this->immediateUpdate = $this->config()->default_immediate_update; } /** @@ -67,6 +84,23 @@ class GridFieldOrderableRows extends RequestHandler implements return $this; } + /** + * @return boolean + */ + public function getImmediateUpdate() { + return $this->immediateUpdate; + } + + /** + * @see $immediateUpdate + * @param boolean $immediateUpdate + * @return GridFieldOrderableRows $this + */ + public function setImmediateUpdate($bool) { + $this->immediateUpdate = $bool; + return $this; + } + /** * @return string|array */ @@ -146,6 +180,7 @@ class GridFieldOrderableRows extends RequestHandler implements GridFieldExtensions::include_requirements(); $field->addExtraClass('ss-gridfield-orderable'); + $field->setAttribute('data-immediate-update', (string)(int)$this->immediateUpdate); $field->setAttribute('data-url-reorder', $field->Link('reorder')); $field->setAttribute('data-url-movetopage', $field->Link('movetopage')); } @@ -206,6 +241,10 @@ class GridFieldOrderableRows extends RequestHandler implements * @return SS_HTTPResponse */ public function handleReorder($grid, $request) { + if (!$this->immediateUpdate) + { + $this->httpError(400); + } $list = $grid->getList(); $modelClass = $grid->getModelClass(); if ($list instanceof ManyManyList && !singleton($modelClass)->canView()) { @@ -214,63 +253,17 @@ class GridFieldOrderableRows extends RequestHandler implements $this->httpError(403); } - $ids = $request->postVar('order'); - $field = $this->getSortField(); - - if(!is_array($ids)) { - $this->httpError(400); - } - - $sortterm = ''; - if ($this->extraSortFields) { - if (is_array($this->extraSortFields)) { - foreach($this->extraSortFields as $col => $dir) { - $sortterm .= "$col $dir, "; - } - } else { - $sortterm = $this->extraSortFields.', '; - } - } - $sortterm .= '"'.$this->getSortTable($list).'"."'.$field.'"'; - $items = $list->filter('ID', $ids)->sort($sortterm); - - // Ensure that each provided ID corresponded to an actual object. - if(count($items) != count($ids)) { - $this->httpError(404); - } - // Save any un-comitted changes to the gridfield if(($form = $grid->getForm()) && ($record = $form->getRecord()) ) { $form->loadDataFrom($request->requestVars(), true); $grid->saveInto($record); } - // Populate each object we are sorting with a sort value. - $this->populateSortValues($items); - - // Generate the current sort values. - if ($items instanceof ManyManyList) + $ids = $request->postVar('order'); + if (!$this->executeReorder($grid, $ids)) { - $current = array(); - foreach ($items->toArray() as $record) - { - // NOTE: _SortColumn0 is the first ->sort() field - // used by SS when functions are detected in a SELECT - // or CASE WHEN. - if (isset($record->_SortColumn0)) { - $current[$record->ID] = $record->_SortColumn0; - } else { - $current[$record->ID] = $record->$field; - } - } + $this->httpError(400); } - else - { - $current = $items->map('ID', $field)->toArray(); - } - - // Perform the actual re-ordering. - $this->reorderItems($list, $current, $ids); return $grid->FieldHolder(); } @@ -334,6 +327,82 @@ class GridFieldOrderableRows extends RequestHandler implements return $grid->FieldHolder(); } + /** + * Handle saving when 'immediateUpdate' is disabled, otherwise this isn't + * necessary for the default sort mode. + */ + public function handleSave(GridField $grid, DataObjectInterface $record) { + if (!$this->immediateUpdate) + { + $list = $grid->getList(); + $value = $grid->Value(); + if (isset($value['GridFieldEditableColumns']) && $value['GridFieldEditableColumns']) + { + $rows = $value['GridFieldEditableColumns']; + $ids = array(); + foreach ($rows as $id => $data) + { + $ids[] = $id; + } + $this->executeReorder($grid, $ids); + } + } + } + + protected function executeReorder(GridField $grid, $ids) { + if(!is_array($ids)) { + return false; + } + $field = $this->getSortField(); + + $sortterm = ''; + if ($this->extraSortFields) { + if (is_array($this->extraSortFields)) { + foreach($this->extraSortFields as $col => $dir) { + $sortterm .= "$col $dir, "; + } + } else { + $sortterm = $this->extraSortFields.', '; + } + } + $list = $grid->getList(); + $sortterm .= '"'.$this->getSortTable($list).'"."'.$field.'"'; + $items = $list->filter('ID', $ids)->sort($sortterm); + + // Ensure that each provided ID corresponded to an actual object. + if(count($items) != count($ids)) { + return false; + } + + // Populate each object we are sorting with a sort value. + $this->populateSortValues($items); + + // Generate the current sort values. + if ($items instanceof ManyManyList) + { + $current = array(); + foreach ($items->toArray() as $record) + { + // NOTE: _SortColumn0 is the first ->sort() field + // used by SS when functions are detected in a SELECT + // or CASE WHEN. + if (isset($record->_SortColumn0)) { + $current[$record->ID] = $record->_SortColumn0; + } else { + $current[$record->ID] = $record->$field; + } + } + } + else + { + $current = $items->map('ID', $field)->toArray(); + } + + // Perform the actual re-ordering. + $this->reorderItems($list, $current, $ids); + return true; + } + protected function reorderItems($list, array $values, array $order) { // Get a list of sort values that can be used. $pool = array_values($values); diff --git a/javascript/GridFieldExtensions.js b/javascript/GridFieldExtensions.js index 182fc6e..44d5aa0 100644 --- a/javascript/GridFieldExtensions.js +++ b/javascript/GridFieldExtensions.js @@ -198,10 +198,21 @@ return { name: "order[]", value: $(this).data("id") }; }); - grid.reload({ - url: grid.data("url-reorder"), - data: data.get() - }); + if (grid.data("immediate-update")) + { + grid.reload({ + url: grid.data("url-reorder"), + data: data.get() + }); + } + else + { + // Tells the user they have unsaved changes when they + // try and leave the page after sorting, also updates the + // save buttons to show the user they've made a change. + var form = $('.cms-edit-form'); + form.addClass('changed'); + } }; this.sortable({