Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit a04c337

Browse files
author
harrydeluxe
committed
add Ext.ux.grid.plugin.MultipleSort
1 parent 4c5b134 commit a04c337

File tree

1 file changed

+318
-0
lines changed

1 file changed

+318
-0
lines changed

ux/grid/plugin/MultipleSort.js

Lines changed: 318 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,318 @@
1+
/**
2+
* @class Ext.ux.grid.plugin.MultipleSort
3+
* @extends Ext.toolbar.Toolbar
4+
*
5+
* @author Harald Hanek (c) 2012
6+
* @license http://harrydeluxe.mit-license.org
7+
*
8+
* This plugin is based on Senchas multiple grid sorting example.
9+
* @see http://dev.sencha.com/deploy/ext-4.1.0-gpl/examples/grid/multiple-sorting.html
10+
*/
11+
Ext.define('Ext.ux.grid.plugin.MultipleSort', {
12+
extend: 'Ext.toolbar.Toolbar',
13+
alias: 'plugin.ux.multiplesort',
14+
require: ['Ext.ux.BoxReorderer',
15+
'Ext.ux.ToolbarDroppable',
16+
'Ext.menu.Menu'],
17+
18+
clone: function()
19+
{
20+
return {
21+
init: Ext.emptyFn
22+
};
23+
},
24+
25+
layout: {
26+
overflowHandler: 'Menu'
27+
},
28+
29+
minHeight: 29,
30+
31+
autoHide: false,
32+
33+
removeText: 'remove',
34+
35+
removeAllText: 'remove all',
36+
37+
initComponent: function()
38+
{
39+
var me = this;
40+
41+
me.reorderer = new Ext.ux.BoxReorderer({
42+
listeners: {
43+
scope: me,
44+
Drop: function(r, c, button)
45+
{ // update sort direction when button is dropped
46+
me.changeSortDirection(button, false);
47+
}
48+
}
49+
});
50+
51+
me.droppable = new Ext.ux.ToolbarDroppable({
52+
/**
53+
* Creates the new toolbar item from the drop event
54+
*/
55+
createItem: function(data)
56+
{
57+
var header = data.header,
58+
headerCt = header.ownerCt,
59+
reorderer = headerCt.reorderer;
60+
61+
// Hide the drop indicators of the standard
62+
// HeaderDropZone
63+
// in case user had a pending valid drop in
64+
if(reorderer)
65+
{
66+
reorderer.dropZone.invalidateDrop();
67+
}
68+
69+
return me.createSorterButtonConfig({
70+
text: header.text,
71+
sortData: {
72+
property: header.dataIndex,
73+
direction: "ASC"
74+
}
75+
});
76+
},
77+
78+
/**
79+
* Custom canDrop implementation which returns true
80+
* if a column can be added to the toolbar
81+
*
82+
* @param {Object} data Arbitrary data from the drag
83+
* source. For a HeaderContainer, it will
84+
* contain a header property which is the
85+
* Header being dragged.
86+
* @return {Boolean} True if the drop is allowed
87+
*/
88+
canDrop: function(dragSource, event, data)
89+
{
90+
var sorters = me.getSorters(),
91+
header = data.header,
92+
length = sorters.length,
93+
entryIndex = this.calculateEntryIndex(event),
94+
targetItem = this.toolbar.getComponent(entryIndex),
95+
i;
96+
97+
// Group columns have no dataIndex and therefore
98+
// cannot be sorted
99+
// If target isn't reorderable it could not be
100+
// replaced
101+
if(!header.dataIndex || (targetItem && targetItem.reorderable === false))
102+
return false;
103+
104+
for(i = 0; i < length; i++)
105+
{
106+
if(sorters[i].property == header.dataIndex)
107+
return false;
108+
}
109+
110+
return true;
111+
},
112+
113+
afterLayout: me.doSort
114+
});
115+
116+
me.plugins = [me.reorderer,
117+
me.droppable];
118+
119+
Ext.each(me.items, function(item)
120+
{
121+
if(item.sortData)
122+
Ext.applyIf(item, me.createSorterButtonConfig(item));
123+
}, me);
124+
125+
me.callParent(arguments);
126+
},
127+
128+
init: function(grid)
129+
{
130+
var me = this;
131+
132+
if(!me.grid)
133+
me.grid = grid;
134+
135+
me.grid.on('render', me.onGridRender, me, {
136+
single: true
137+
});
138+
},
139+
140+
onGridRender: function(grid)
141+
{
142+
grid.on('afterlayout', this.onGridAfterLayout, this, {
143+
single: true
144+
});
145+
},
146+
147+
onGridAfterLayout: function(grid)
148+
{
149+
var me = this,
150+
headerCt = (grid.ownerCt.lockedGrid) ? grid.ownerCt.lockedGrid.headerCt : grid.headerCt,
151+
dragZone = headerCt.reorderer.dragZone;
152+
153+
/**
154+
* stops here if the toolbar is never rendered!
155+
* @todo addDocked add toolbar to grid
156+
*/
157+
if(!me.rendered)
158+
return false;
159+
160+
me.droppable.addDDGroup(dragZone.ddGroup);
161+
162+
dragZone.self.override(
163+
{
164+
onStartDrag: function()
165+
{
166+
if(me.autoHide && me.isHidden())
167+
{
168+
me.show(null, function(){
169+
Ext.dd.DragDropManager.refreshCache(dragZone.groups);
170+
}, me);
171+
}
172+
},
173+
onEndDrag: function(data, e)
174+
{
175+
if(me.autoHide && me.getSorters().length == 0)
176+
{
177+
me.hide();
178+
}
179+
}
180+
181+
});
182+
183+
me.doSort();
184+
},
185+
186+
/**
187+
* Tells the store to sort itself according to our sort data
188+
*/
189+
doSort: function()
190+
{
191+
var me = this.toolbar ? this.toolbar : this,
192+
sorters = me.getSorters();
193+
194+
if(sorters.length >= 1)
195+
{
196+
me.show();
197+
me.grid.store.sort(sorters);
198+
}
199+
else
200+
{
201+
if(me.autoHide)
202+
me.hide();
203+
}
204+
},
205+
206+
/**
207+
* Callback handler used when a sorter button is clicked or
208+
* reordered
209+
*
210+
* @param {Ext.Button} button The button that was clicked
211+
* @param {Boolean} changeDirection True to change direction
212+
* (default). Set to false for reorder operations as we
213+
* wish to preserve ordering there
214+
*/
215+
changeSortDirection: function(button, changeDirection)
216+
{
217+
var sortData = button.sortData,
218+
iconCls = button.iconCls;
219+
220+
if(sortData)
221+
{
222+
if(changeDirection !== false)
223+
{
224+
button.sortData.direction = Ext.String.toggle(button.sortData.direction, "ASC", "DESC");
225+
button.setIconCls(Ext.String.toggle(iconCls, "sort-asc", "sort-desc"));
226+
}
227+
228+
this.grid.store.clearFilter();
229+
this.doSort();
230+
}
231+
},
232+
233+
/**
234+
* Returns an array of sortData from the sorter buttons
235+
*
236+
* @return {Array} Ordered sort data from each of the sorter buttons
237+
*/
238+
getSorters: function()
239+
{
240+
var sorters = [];
241+
242+
Ext.each(this.query('button'), function(button)
243+
{
244+
if(button.sortData)
245+
sorters.push(button.sortData);
246+
}, this);
247+
248+
return sorters;
249+
},
250+
251+
/**
252+
* Convenience function for creating Toolbar Buttons that are tied
253+
* to sorters
254+
*
255+
* @param {Object} config Optional config object
256+
* @return {Object} The new Button configuration
257+
*/
258+
createSorterButtonConfig: function(config)
259+
{
260+
var me = this;
261+
262+
if(!config.sortData.direction)
263+
config.sortData.direction = 'ASC';
264+
265+
Ext.applyIf(config, {
266+
listeners: {
267+
click: function(button, event)
268+
{
269+
me.changeSortDirection(button, true);
270+
},
271+
272+
render: function(button)
273+
{
274+
var removeAllItem = new Ext.menu.Item({
275+
text: me.removeAllText,
276+
handler: function()
277+
{
278+
Ext.each(me.query('button'), function(button)
279+
{
280+
if(button.sortData)
281+
me.remove(button);
282+
}, me);
283+
284+
me.doSort();
285+
}
286+
}),
287+
contextMenu = new Ext.menu.Menu({
288+
showSeparator: false,
289+
items: [{
290+
text: me.removeText,
291+
handler: function()
292+
{
293+
me.remove(button);
294+
me.doSort();
295+
}
296+
}, removeAllItem]
297+
}),
298+
el = button.getEl();
299+
300+
el.on('contextmenu', function(event) {
301+
var sorters = me.getSorters();
302+
303+
removeAllItem.setVisible(sorters.length > 1);
304+
event.stopEvent();
305+
contextMenu.showAt(event.getXY());
306+
});
307+
},
308+
309+
scope: me
310+
},
311+
iconCls: 'sort-' + config.sortData.direction.toLowerCase(),
312+
reorderable: true,
313+
xtype: 'button'
314+
});
315+
316+
return config;
317+
}
318+
});

0 commit comments

Comments
 (0)