Skip to content
Browse files

Initial commit of module

  • Loading branch information...
1 parent 0638c2d commit 710c7b88d2df485ed541fd47ab0b4872d9347415 @UndefinedOffset UndefinedOffset committed May 9, 2012
View
6 .buildpath
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<buildpath>
+ <buildpathentry kind="con" path="org.eclipse.php.core.LANGUAGE"/>
+ <buildpathentry kind="src" path=""/>
+ <buildpathentry kind="con" path="ca.edchipman.silverstripepdt.LANGUAGE"/>
+</buildpath>
View
29 .project
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>SortableGridField</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.wst.jsdt.core.javascriptValidator</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.wst.validation.validationbuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.dltk.core.scriptbuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>ca.edchipman.silverstripepdt.SilverStripeNature</nature>
+ <nature>org.eclipse.php.core.PHPNature</nature>
+ <nature>org.eclipse.wst.jsdt.core.jsNature</nature>
+ </natures>
+</projectDescription>
View
16 .settings/.jsdtscope
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="">
+ <attributes>
+ <attribute name="provider" value="org.eclipse.wst.jsdt.web.core.internal.project.ModuleSourcePathProvider"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="con" path="org.eclipse.wst.jsdt.launching.JRE_CONTAINER"/>
+ <classpathentry kind="con" path="org.eclipse.wst.jsdt.launching.WebProject">
+ <attributes>
+ <attribute name="hide" value="true"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="con" path="org.eclipse.wst.jsdt.launching.baseBrowserLibrary"/>
+ <classpathentry kind="output" path=""/>
+</classpath>
View
3 .settings/org.eclipse.php.core.prefs
@@ -0,0 +1,3 @@
+eclipse.preferences.version=1
+include_path=0;/SortableGridField\u00055;ca.edchipman.silverstripepdt.LANGUAGE
+silverstripe_version=SS2.4
View
1 .settings/org.eclipse.wst.jsdt.ui.superType.container
@@ -0,0 +1 @@
+org.eclipse.wst.jsdt.launching.baseBrowserLibrary
View
1 .settings/org.eclipse.wst.jsdt.ui.superType.name
@@ -0,0 +1 @@
+Window
View
3 _config.php
@@ -0,0 +1,3 @@
+<?php
+
+?>
View
135 code/extensions/GridFieldSortableObject.php
@@ -0,0 +1,135 @@
+<?php
+class GridFieldSortableObject extends DataExtension {
+ public static $db=array(
+ 'SortOrder'=>'Int'
+ );
+
+ protected static $sortable_classes = array();
+ protected static $many_many_sortable_relations = array();
+ protected static $sort_dir = "ASC";
+
+
+ public static function set_sort_dir($dir) {
+ self::$sort_dir=$dir;
+ }
+
+
+ public static function add_sortable_class($className) {
+ if(!self::is_sortable_class($className)) {
+ Object::add_extension($className, 'GridFieldSortableObject');
+
+ self::$sortable_classes[]=$className;
+ }
+ }
+
+ public static function add_sortable_classes(array $classes) {
+ foreach($classes as $class) {
+ self::add_sortable_class($class);
+ }
+ }
+
+ public static function add_sortable_many_many_relation($ownerClass, $componentName) {
+ list($parentClass, $componentClass, $parentField, $componentField, $table)=singleton($ownerClass)->many_many($componentName);
+
+ Object::add_static_var($ownerClass, 'many_many_extraFields', array(
+ $componentName=>array(
+ 'SortOrder'=>'Int'
+ )));
+
+
+ if(!isset(self::$many_many_sortable_relations[$componentClass])) {
+ self::$many_many_sortable_relations[$componentClass] = array();
+ }
+
+
+ self::$many_many_sortable_relations[$componentClass][$parentClass]=$table;
+ self::add_sortable_class($componentClass);
+ }
+
+ public static function remove_sortable_class($class) {
+ Object::remove_extension($class, 'GridFieldSortableObject');
+ }
+
+ public static function is_sortable_class($classname) {
+ if(in_array($classname, self::$sortable_classes)) {
+ return true;
+ }
+
+ foreach(self::$sortable_classes as $class) {
+ if(is_subclass_of($classname, $class)) {
+ return true;
+ }
+ }
+
+
+ return Object::has_extension($classname, 'GridFieldSortableObject');
+ }
+
+ public static function is_sortable_many_many($componentClass, $parentClass=null) {
+ $map=self::$many_many_sortable_relations;
+ if($parentClass===null) {
+ return isset($map[$componentClass]);
+ }else {
+ if(isset($map[$componentClass])) {
+ return isset($map[$componentClass][$parentClass]);
+ }
+
+ return false;
+ }
+
+ }
+
+ public static function get_join_tables($classname) {
+ if(isset(self::$many_many_sortable_relations[$classname])) {
+ return self::$many_many_sortable_relations[$classname];
+ }
+
+ return false;
+ }
+
+ public function augmentSQL(SQLQuery &$query) {
+ if(empty($query->select) || $query->delete || in_array("COUNT(*)", $query->select) || in_array("count(*)", $query->select)) {
+ return;
+ }
+
+
+ $sort_field=false;
+ if($join_tables=self::get_join_tables($this->owner->class)) {
+ foreach($query->from as $from) {
+ if($sort_field) {
+ break;
+ }
+
+ foreach($join_tables as $join_table) {
+ if(stristr($from,$join_table)) {
+ $sort_field="\"$join_table\".\"SortOrder\"";
+
+ if(isset($query->select['SortOrder'])) {
+ $query->select['SortOrder']="\"{$this->owner->class}\".SortOrder AS LocalSort";
+ }
+
+ break;
+ }
+ }
+ }
+ }
+
+
+ if(!$sort_field) {
+ $sort_field="\"SortOrder\"";
+ }
+
+ if(!$query->orderby || ($query->orderby==$this->owner->stat('default_sort'))) {
+ $query->orderby="$sort_field ".self::$sort_dir;
+ }
+ }
+
+ public function onBeforeWrite() {
+ if(!$this->owner->ID) {
+ if($peers=DataList::create($this->owner->class)) {
+ $this->owner->SortOrder=$peers->Count()+1;
+ }
+ }
+ }
+}
+?>
View
143 code/forms/GridFieldSortableRows.php
@@ -0,0 +1,143 @@
+<?php
+/**
+ * @package forms
+ */
+class GridFieldSortableRows implements GridField_HTMLProvider, GridField_ActionProvider {
+ /**
+ * Returns a map where the keys are fragment names and the values are pieces of HTML to add to these fragments.
+ * @param GridField $gridField Grid Field Reference
+ * @return {array} Map where the keys are fragment names and the values are pieces of HTML to add to these fragments.
+ */
+ public function getHTMLFragments($gridField) {
+ $state=$gridField->State->GridFieldSortableRows;
+ if(!is_bool($state->sortableToggle)) {
+ $state->sortableToggle=false;
+ }
+
+
+
+ if(Object::has_extension($gridField->getModelClass(), 'GridFieldSortableObject')) {
+ //Sort order toggle
+ $sortOrderToggle=new GridField_FormAction($gridField, 'sortablerows_toggle', 'Allow drag and drop re-ordering', 'saveGridRowSort', null);
+ $sortOrderToggle->addExtraClass('sortablerows_toggle');
+
+ //Disable Pagenator
+ if($gridField->getConfig()->getComponentByType('GridFieldPaginator')) {
+ $disablePagenator=new GridField_FormAction($gridField, 'sortablerows_disablepagenator', 'Disable Pagenator', 'sortableRowsDisablePaginator', null);
+ $disablePagenator->addExtraClass('sortablerows_disablepagenator');
+ }else {
+ $disablePagenator=null;
+ }
+
+ $forTemplate=new ArrayData(array(
+ 'SortableToggle'=>$sortOrderToggle,
+ 'PagenatorToggle'=>$disablePagenator,
+ 'Checked'=>($state->sortableToggle==true ? ' checked="checked"':'')
+ ));
+
+
+ //Inject Requirements
+ Requirements::css('SortableGridField/css/GridFieldSortableRows.css');
+ Requirements::javascript('SortableGridField/javascript/GridFieldSortableRows.js');
+
+
+ return array(
+ 'header'=>$forTemplate->renderWith('GridFieldSortableRows', array('Colspan'=>count($gridField->getColumns())))
+ );
+ }
+
+ return array();
+ }
+
+ /**
+ * Return a list of the actions handled by this action provider.
+ * @param GridField $gridField Grid Field Reference
+ * @return {array} Array with action identifier strings.
+ */
+ public function getActions($gridField) {
+ if(Object::has_extension($gridField->getModelClass(), 'GridFieldSortableObject')) {
+ if($gridField->getConfig()->getComponentByType('GridFieldPaginator')) {
+ return array('saveGridRowSort', 'sortableRowsDisablePaginator');
+ }else {
+ return array('saveGridRowSort');
+ }
+ }
+
+ return array();
+ }
+
+ /**
+ * Handle an action on the given grid field.
+ * @param {GridField} $gridField Grid Field Reference
+ * @param {string} $actionName Action identifier, see {@link getActions()}.
+ * @param {array} $arguments Arguments relevant for this
+ * @param {array} $data All form data
+ */
+ public function handleAction(GridField $gridField, $actionName, $arguments, $data) {
+ $state=$gridField->State->GridFieldSortableRows;
+ if(!is_bool($state->sortableToggle)) {
+ $state->sortableToggle=false;
+ }else if($state->sortableToggle==true) {
+ if($gridField->getConfig()->getComponentsByType('GridFieldPaginator')) {
+ $gridField->getConfig()->removeComponentsByType('GridFieldPaginator');
+ $gridField->getConfig()->addComponent(new GridFieldFooter());
+ }
+
+ $gridField->getConfig()->removeComponentsByType('GridFieldFilterHeader');
+ $gridField->getConfig()->removeComponentsByType('GridFieldSortableHeader');
+ }
+
+
+ if(Object::has_extension($gridField->getModelClass(), 'GridFieldSortableObject')) {
+ if($actionName=='savegridrowsort') {
+ return $this->saveGridRowSort($gridField, $data);
+ }
+ }
+ }
+
+ /**
+ * Handles saving of the row sort order
+ * @param {GridField} $gridField Grid Field Reference
+ * @param {array} $data Data submitted in the request
+ */
+ private function saveGridRowSort(GridField $gridField, $data) {
+ if(empty($data['Items'])) {
+ user_error('No items to sort', E_USER_ERROR);
+ }
+
+ $className=$gridField->getModelClass();
+ $ownerClass=$gridField->Form->Controller()->class;
+
+ $many_many=GridFieldSortableObject::is_sortable_many_many($className);
+ if($many_many) {
+ $candidates=singleton($ownerClass)->many_many();
+ if(is_array($candidates)) {
+ foreach($candidates as $name => $class)
+ if($class==$className) {
+ $relationName=$name;
+ break;
+ }
+ }
+
+ if(!isset($relationName)) {
+ return false;
+ }
+
+ list($parentClass, $componentClass, $parentField, $componentField, $table)=singleton($ownerClass)->many_many($relationName);
+ }
+
+
+ $data['Items']=explode(',', $data['Items']);
+ for($sort=0;$sort<count($data['Items']);$sort++) {
+ $id=intval($data['Items'][$sort]);
+ if($many_many) {
+ DB::query("UPDATE \"$table\" SET \"SortOrder\" = $sort WHERE \"{$className}ID\" = $id");
+ }else {
+ $obj=DataObject::get_by_id($className, $id);
+ $obj->SortOrder=$sort;
+ $obj->write();
+ }
+ }
+ }
+}
+?>
View
7 css/GridFieldSortableRows.css
@@ -0,0 +1,7 @@
+.cms table.ss-gridfield-table thead tr th.sortablerowsheading {
+ border-bottom: 1px solid rgba(0, 0, 0, 0.1);
+}
+
+.cms table.ss-gridfield-table thead tr th.sortablerowsheading .gridfield-sortablerows button {
+ display: none;
+}
View
43 javascript/GridFieldSortableRows.js
@@ -0,0 +1,43 @@
+(function($) {
+ $('.ss-gridfield .gridfield-sortablerows input').entwine({
+ onmatch: function() {
+ var refCheckbox=$(this);
+
+ var gridField=$(this).getGridField();
+ gridField.find('tbody').sortable({
+ disabled: ($(this).is(':checked')==false),
+ helper: function(e, ui) {
+ //Maintains width of the columns
+ ui.children().each(function() {
+ $(this).width($(this).width());
+ });
+
+ return ui;
+ },
+ update: function(event, ui) {
+ var dataRows=[];
+ var gridItems=gridField.getItems();
+ var button=refCheckbox.parent().find('.sortablerows_toggle');
+
+
+ for(var i=0;i<gridItems.length;i++) {
+ dataRows[i]=$(gridItems[i]).data('id');
+ }
+
+
+ gridField.reload({data: [{name: button.attr('name'), value: button.val()}, {name: 'Items', value: dataRows}]});
+ }
+ }).disableSelection();
+ },
+
+ onchange: function(e) {
+ var gridField=$(this).getGridField();
+ gridField.find('tbody').sortable('option', 'disabled', ($(this).is(':checked')==false));
+ gridField.setState('GridFieldSortableRows', {sortableToggle: $(this).is(':checked')});
+
+
+ var button=$(this).parent().find('.sortablerows_disablepagenator');
+ gridField.reload({data: [{name: button.attr('name'), value: button.val()}]});
+ }
+ });
+})(jQuery);
View
9 templates/Includes/GridFieldSortableRows.ss
@@ -0,0 +1,9 @@
+<tr>
+ <th class="extra sortablerowsheading" colspan="$Colspan">
+ <div class="gridfield-sortablerows">
+ <input type="checkbox" value="1"$Checked/> Allow drag and drop re-ordering
+ $SortableToggle
+ $PagenatorToggle
+ </div>
+ </th>
+</tr>

0 comments on commit 710c7b8

Please sign in to comment.
Something went wrong with that request. Please try again.