Skip to content

Commit a682cf9

Browse files
committed
mobile support tweaks
* `alwaysShowResizeHandle` now support `'mobile'` which is the default, making it much easier (see doc) everything seems to be working now, just need to release next #1757 * tested on: Win10: Chrome 104, Firefox 103, Edge 104 Android 10: Chrome
1 parent e829f3e commit a682cf9

File tree

10 files changed

+53
-41
lines changed

10 files changed

+53
-41
lines changed

README.md

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -295,21 +295,19 @@ GridStack.init({
295295

296296
## Touch devices support
297297

298-
gridstack v3.2 jq version compiles touch support (html5 version does not yet support `touchmove` events. This will be added in a future release), so it works out of the box, no need for anything.
299-
You **used** to need [jQuery UI Touch Punch](https://github.com/RWAP/jquery-ui-touch-punch) to make jQuery UI Draggable/Resizable
300-
work on touch-based devices (now distributed as `dist/jq/jquery.ui.touch-punch.js` for reference).
298+
gridstack v6+ now support mobile out of the box, with the addition of native touch event (along with mouse event) for drag&drop and resize.
299+
Older versions (3.2+) required the jq version with added touch punch, but doesn't work well with nested grids.
301300

302-
303-
This option will be useful:
301+
This option is now the default:
304302

305303
```js
306304
let options = {
307-
alwaysShowResizeHandle: /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)
305+
alwaysShowResizeHandle: 'mobile' // which defaults to /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)
308306
};
309307
GridStack.init(options);
310308
```
311309

312-
See [example](http://gridstack.github.io/gridstack.js/demo/mobile.html). If you're still experiencing issues on touch devices please check [#444](https://github.com/gridstack/gridstack.js/issues/444)
310+
See [example](http://gridstack.github.io/gridstack.js/demo/mobile.html).
313311

314312
# gridstack.js for specific frameworks
315313

demo/mobile.html

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ <h1>Simple mobile demo</h1>
1919
let grid = GridStack.init({
2020
column: 3,
2121
disableOneColumnMode: true,
22-
alwaysShowResizeHandle: /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)
2322
});
2423
grid.load([{x:0, y:0, content: '1'}, {x:1, y:0, h:2, content: '2'}, {x:2, y:0, content: '3'}])
2524
</script>

demo/nested.html

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,6 @@ <h1>Nested grids demo</h1>
6767
minRow: 2, // don't collapse when empty
6868
disableOneColumnMode: true,
6969
acceptWidgets: true,
70-
alwaysShowResizeHandle: /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent),
7170
id: 'main',
7271
children: [
7372
{x:0, y:0, content: 'regular item'},

demo/website.html

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -364,13 +364,11 @@ <h1>Used by</h1>
364364
];
365365

366366
var simpleGrid = GridStack.init({
367-
alwaysShowResizeHandle: /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent),
368367
margin: 5,
369368
}, '#simple-grid');
370369
simpleGrid.load(simple);
371370

372371
var advGrid = GridStack.init({
373-
alwaysShowResizeHandle: /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent),
374372
margin: 5,
375373
acceptWidgets: true,
376374
dragIn: '.newWidget', // class that can be dragged from outside

doc/CHANGES.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ Change log
7272
## 6.0.0-beta (TBD)
7373
* converted previous HTML5 `draggable=true` based code to simple Mouse Events and Touch mobile support for drag&Drop.
7474
* removed all jquery-ui related code, and D7D plugging as we only support native events now
75+
* `alwaysShowResizeHandle` now support `'mobile'` which is the default, making it much easier (see doc)
7576
* changed `commit()` to be `batchUpdate(false)` to make it easier to turn batch on/off. updated doc. old API remains for now
7677

7778
## 5.1.1 (2022-06-16)

doc/README.md

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -70,11 +70,15 @@ gridstack.js API
7070
* `true` (uses `'.grid-stack-item'` class filter) or `false`
7171
* string for explicit class name
7272
* `function (i: number, element: Element): boolean` See [example](http://gridstack.github.io/gridstack.js/demo/two.html)
73-
- `alwaysShowResizeHandle` - possible values (default: `false` only show on hover)
74-
* `true` the resizing handles are always shown even if the user is not hovering over the widget
75-
* advance condition such as this mobile browser agent check:
76-
`alwaysShowResizeHandle: /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test( navigator.userAgent )`
77-
See [example](http://gridstack.github.io/gridstack.js/demo/mobile.html)
73+
- `alwaysShowResizeHandle` - possible values (default: `mobile`) - does not apply to non-resizable widgets
74+
* `false` the resizing handles are only shown while hovering over a widget
75+
* `true` the resizing handles are always shown
76+
* `'mobile'` if running on a mobile device, default to `true` (since there is no hovering per say), else `false`.
77+
this uses this condition on browser agent check:
78+
`alwaysShowResizeHandle: /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test( navigator.userAgent )`
79+
See [mobile](http://gridstack.github.io/gridstack.js/demo/mobile.html)
80+
81+
7882
- `animate` - turns animation on to smooth transitions (default: `true`)
7983
- `auto` - if `false` gridstack will not initialize existing items (default: `true`)
8084
- `cellHeight`- one cell height (default?: 'auto'). Can be:
@@ -118,7 +122,7 @@ gridstack.js API
118122
- `oneColumnModeDomSort` - set to `true` if you want oneColumnMode to use the DOM order and ignore x,y from normal multi column layouts during sorting. This enables you to have custom 1 column layout that differ from the rest. (default?: `false`)
119123
- `placeholderClass` - class for placeholder (default: `'grid-stack-placeholder'`)
120124
- `placeholderText` - placeholder default content (default: `''`)
121-
- `resizable` - allows to override resizable options. (default: `{autoHide: true, handles: 'se'}`). `handles` can be any combo of `n,ne,e,se,s,sw,w,nw` or `all`.
125+
- `resizable` - allows to override resizable options. (default: `{handles: 'se'}`). `handles` can be any combo of `n,ne,e,se,s,sw,w,nw` or `all`.
122126
- `removable` - if `true` widgets could be removed by dragging outside of the grid. It could also be a selector string, in this case widgets will be removed by dropping them there (default: `false`) See [example](http://gridstackjs.com/demo/two.html)
123127
- `removeTimeout` - time in milliseconds before widget is being removed while dragging outside of the grid. (default: `2000`)
124128
- `row` - fix grid number of rows. This is a shortcut of writing `minRow:N, maxRow:N`. (default `0` no constrain)

src/dd-gridstack.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,10 @@ export class DDGridStack {
4848
} else {
4949
const grid = dEl.el.gridstackNode.grid;
5050
let handles = dEl.el.getAttribute('gs-resize-handles') ? dEl.el.getAttribute('gs-resize-handles') : grid.opts.resizable.handles;
51+
let autoHide = !grid.opts.alwaysShowResizeHandle;
5152
dEl.setupResizable({
5253
...grid.opts.resizable,
53-
...{ handles: handles },
54+
...{ handles, autoHide },
5455
...{
5556
start: opts.start,
5657
stop: opts.stop,

src/dd-touch.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import { DDManager } from './dd-manager';
77

88
/**
99
* Detect touch support - Windows Surface devices and other touch devices
10+
* should we use this instead ? (what we had for always showing resize handles)
11+
* /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)
1012
*/
1113
export const isTouch: boolean = ( 'ontouchstart' in document
1214
|| 'ontouchstart' in window
@@ -16,7 +18,6 @@ export const isTouch: boolean = ( 'ontouchstart' in document
1618
|| (navigator as any).msMaxTouchPoints > 0
1719
);
1820

19-
2021
// interface TouchCoord {x: number, y: number};
2122

2223
class DDTouch {

src/gridstack.ts

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,8 @@ const GridDefaults: GridStackOptions = {
5858
float: false,
5959
staticGrid: false,
6060
animate: true,
61-
alwaysShowResizeHandle: false,
61+
alwaysShowResizeHandle: 'mobile',
6262
resizable: {
63-
autoHide: true,
6463
handles: 'se'
6564
},
6665
draggable: {
@@ -265,25 +264,23 @@ export class GridStack {
265264
opts.oneColumnSize = opts.oneColumnSize || anyOpts.minWidth;
266265
delete anyOpts.minWidth;
267266
}
267+
// save original setting so we can restore on save
268+
if (opts.alwaysShowResizeHandle !== undefined) {
269+
(opts as any)._alwaysShowResizeHandle = opts.alwaysShowResizeHandle;
270+
}
268271

269-
// elements attributes override any passed options (like CSS style) - merge the two together
272+
// elements DOM attributes override any passed options (like CSS style) - merge the two together
270273
let defaults: GridStackOptions = {...Utils.cloneDeep(GridDefaults),
271-
column: Utils.toNumber(el.getAttribute('gs-column')) || 12,
272-
minRow: rowAttr ? rowAttr : Utils.toNumber(el.getAttribute('gs-min-row')) || 0,
273-
maxRow: rowAttr ? rowAttr : Utils.toNumber(el.getAttribute('gs-max-row')) || 0,
274-
staticGrid: Utils.toBool(el.getAttribute('gs-static')) || false,
274+
column: Utils.toNumber(el.getAttribute('gs-column')) || GridDefaults.column,
275+
minRow: rowAttr ? rowAttr : Utils.toNumber(el.getAttribute('gs-min-row')) || GridDefaults.minRow,
276+
maxRow: rowAttr ? rowAttr : Utils.toNumber(el.getAttribute('gs-max-row')) || GridDefaults.maxRow,
277+
staticGrid: Utils.toBool(el.getAttribute('gs-static')) || GridDefaults.staticGrid,
275278
_styleSheetClass: 'grid-stack-instance-' + (Math.random() * 10000).toFixed(0),
276-
alwaysShowResizeHandle: opts.alwaysShowResizeHandle || false,
277-
resizable: {
278-
autoHide: !(opts.alwaysShowResizeHandle || false),
279-
handles: 'se'
280-
},
281279
draggable: {
282-
handle: (opts.handleClass ? '.' + opts.handleClass : (opts.handle ? opts.handle : '')) || '.grid-stack-item-content',
283-
appendTo: 'body'
280+
handle: (opts.handleClass ? '.' + opts.handleClass : (opts.handle ? opts.handle : '')) || GridDefaults.draggable.handle,
284281
},
285282
removableOptions: {
286-
accept: '.' + (opts.itemClass || 'grid-stack-item')
283+
accept: opts.itemClass ? '.' + opts.itemClass : GridDefaults.removableOptions.accept,
287284
},
288285
};
289286
if (el.getAttribute('gs-animate')) { // default to true, but if set to false use that instead
@@ -303,7 +300,6 @@ export class GridStack {
303300
if (this.opts.rtl === 'auto') {
304301
this.opts.rtl = (el.style.direction === 'rtl');
305302
}
306-
307303
if (this.opts.rtl) {
308304
this.el.classList.add('grid-stack-rtl');
309305
}
@@ -330,6 +326,11 @@ export class GridStack {
330326
this.cellHeight(this.opts.cellHeight, false);
331327
}
332328

329+
// see if we need to adjust auto-hide
330+
if (this.opts.alwaysShowResizeHandle === 'mobile') {
331+
this.opts.alwaysShowResizeHandle = isTouch;
332+
}
333+
333334
this.el.classList.add(this.opts._styleSheetClass);
334335

335336
this._setStaticClass();
@@ -520,6 +521,13 @@ export class GridStack {
520521
o.column = 'auto';
521522
delete o.disableOneColumnMode;
522523
}
524+
const origShow = (o as any)._alwaysShowResizeHandle;
525+
delete (o as any)._alwaysShowResizeHandle;
526+
if (origShow !== undefined) {
527+
o.alwaysShowResizeHandle = origShow;
528+
} else {
529+
delete o.alwaysShowResizeHandle;
530+
}
523531
Utils.removeInternalAndSame(o, GridDefaults);
524532
o.children = list;
525533
return o;
@@ -1590,4 +1598,5 @@ export class GridStack {
15901598
* I don't know how to generate the DD only code at the remaining 31k to delay load as code depends on Gridstack.ts
15911599
*/
15921600
import { DDGridStack } from './dd-gridstack';
1601+
import { isTouch } from './dd-touch';
15931602
export * from './dd-gridstack';

src/types.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,14 @@ export interface GridStackOptions {
3838
*/
3939
acceptWidgets?: boolean | string | ((element: Element) => boolean);
4040

41-
/** possible values (default: `false` only show on hover)
42-
* `true` the resizing handles are always shown even if the user is not hovering over the widget
43-
* advance condition such as this mobile browser agent check:
41+
/** possible values (default: `mobile`) - does not apply to non-resizable widgets
42+
* `false` the resizing handles are only shown while hovering over a widget
43+
* `true` the resizing handles are always shown
44+
* 'mobile' if running on a mobile device, default to `true` (since there is no hovering per say), else `false`.
45+
* this uses this condition on browser agent check:
4446
`alwaysShowResizeHandle: /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test( navigator.userAgent )`
4547
See [example](http://gridstack.github.io/gridstack.js/demo/mobile.html) */
46-
alwaysShowResizeHandle?: boolean;
48+
alwaysShowResizeHandle?: true | false | 'mobile';
4749

4850
/** turns animation on (default?: true) */
4951
animate?: boolean;
@@ -165,7 +167,7 @@ export interface GridStackOptions {
165167
/** placeholder default content (default?: '') */
166168
placeholderText?: string;
167169

168-
/** allows to override UI resizable options. (default?: { autoHide: true, handles: 'se' }) */
170+
/** allows to override UI resizable options. (default?: { handles: 'se' }) */
169171
resizable?: DDResizeOpt;
170172

171173
/**
@@ -267,7 +269,7 @@ export interface GridStackWidget extends GridStackPosition {
267269

268270
/** Drag&Drop resize options */
269271
export interface DDResizeOpt {
270-
/** do resize handle hide by default until mouse over ? - default: true */
272+
/** do resize handle hide by default until mouse over ? - default: true on desktop, false on mobile*/
271273
autoHide?: boolean;
272274
/**
273275
* sides where you can resize from (ex: 'e, se, s, sw, w') - default 'se' (south-east)

0 commit comments

Comments
 (0)