Skip to content

Commit

Permalink
GridStackOptions.draggable.cancel option
Browse files Browse the repository at this point in the history
* you can now specify children that will prevent item from being dragged when clicked on.
* fix for gridstack#2205
* updated demo to showcase custom non draggable item
  • Loading branch information
adumesny committed May 6, 2023
1 parent 319b34a commit 771f546
Show file tree
Hide file tree
Showing 5 changed files with 23 additions and 16 deletions.
7 changes: 4 additions & 3 deletions demo/serialization.html
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ <h1>Serialization demo</h1>
<script type="text/javascript">
let grid = GridStack.init({
minRow: 1, // don't let it collapse when empty
cellHeight: '7rem'
cellHeight: '7rem',
draggable: { cancel: '.no-drag'} // example of additional custom elements to skip drag on
});

grid.on('added removed change', function(e, items) {
Expand All @@ -39,8 +40,8 @@ <h1>Serialization demo</h1>

let serializedData = [
{x: 0, y: 0, w: 2, h: 2, id: '0'},
{x: 3, y: 1, h: 2, id: '1',
content: "<button onclick=\"alert('clicked!')\">Press me</button><div>text area</div><div><textarea></textarea></div><div>Input Field</div><input type='text'><div contentEditable=\"true\">Editable Div</div>"},
{x: 3, y: 1, h: 3, id: '1',
content: "<button onclick=\"alert('clicked!')\">Press me</button><div>text area</div><div><textarea></textarea></div><div>Input Field</div><input type='text'><div contentEditable=\"true\">Editable Div</div><div class=\"no-drag\">no drag</div>"},
{x: 4, y: 1, id: '2'},
{x: 2, y: 3, w: 3, id: '3'},
{x: 1, y: 3, id: '4'}
Expand Down
1 change: 1 addition & 0 deletions doc/CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ Change log
* break: remove `GridStackOptions.minWidth` obsolete since 5.1, use `oneColumnSize` instead
* optimize: CSS files now even 25% smaller (after being halfed in 8.0.0) by removing `.grid-stack` prefix for anything already gs based, and 3 digit rounding.
* fix: [#2275](https://github.com/gridstack/gridstack.js/issues/2275) `setupDragIn()` signature tweaks (HTMLElement | Document)
* feat: [#2205](https://github.com/gridstack/gridstack.js/issues/2205) added `GridStackOptions.draggable.cancel` for list of selectors that should prevent item dragging

## 8.0.1 (2023-04-29)
* feat: [#2275](https://github.com/gridstack/gridstack.js/issues/2275) `setupDragIn()` now can take an array or elements (in addition to selector string) and optional parent root (for shadow DOM support)
Expand Down
3 changes: 2 additions & 1 deletion doc/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,9 +131,10 @@ GridStack will add it to the <style> elements it creates.
- `appendTo`?: string - default to 'body' (TODO: is this even used anymore ?)
- `pause`?: boolean | number - if set (true | msec), dragging placement (collision) will only happen after a pause by the user. Note: this is Global
- `scroll`?: boolean - default to 'true', enable or disable the scroll when an element is dragged on bottom or top of the grid.
- `cancel`?: string - prevents dragging from starting on specified elements, listed as comma separated selectors (eg: '.no-drag'). default built in is 'input,textarea,button,select,option'

### DDDragInOpt extends DDDragOpt
- `helper`?: string | ((event: Event) => HTMLElement) - helper function when dropping (ex: 'clone' or your own method)
- `helper`?: 'clone' | ((event: Event) => HTMLElement) - helper function when dropping (ex: 'clone' or your own method)

## Grid attributes

Expand Down
20 changes: 12 additions & 8 deletions src/dd-draggable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,11 @@ import { isTouch, touchend, touchmove, touchstart, pointerdown } from './dd-touc
export interface DDDraggableOpt {
appendTo?: string | HTMLElement;
handle?: string;
helper?: string | HTMLElement | ((event: Event) => HTMLElement);
helper?: 'clone' | HTMLElement | ((event: Event) => HTMLElement);
cancel?: string;
// containment?: string | HTMLElement; // TODO: not implemented yet
// revert?: string | boolean | unknown; // TODO: not implemented yet
// scroll?: boolean; // native support by HTML5 drag drop, can't be switch to off actually
// scroll?: boolean;
start?: (event: Event, ui: DDUIData) => void;
stop?: (event: Event) => void;
drag?: (event: Event, ui: DDUIData) => void;
Expand All @@ -34,6 +35,9 @@ interface DragOffset {

type DDDragEvent = 'drag' | 'dragstart' | 'dragstop';

// make sure we are not clicking on known object that handles mouseDown
const skipMouseDown = 'input,textarea,button,select,option,[contenteditable="true"],.ui-resizable-handle';

// let count = 0; // TEST

export class DDDraggable extends DDBaseImplement implements HTMLElementExtendOpt<DDDraggableOpt> {
Expand Down Expand Up @@ -64,6 +68,7 @@ export class DDDraggable extends DDBaseImplement implements HTMLElementExtendOpt
super();
this.el = el;
this.option = option;

// get the element that is actually supposed to be dragged by
let handleName = option.handle.substring(1);
this.dragEl = el.classList.contains(handleName) ? el : el.querySelector(option.handle) || el;
Expand Down Expand Up @@ -127,12 +132,11 @@ export class DDDraggable extends DDBaseImplement implements HTMLElementExtendOpt
if (DDManager.mouseHandled) return;
if (e.button !== 0) return true; // only left click

// make sure we are not clicking on known object that handles mouseDown (TODO: make this extensible ?) #2054
const skipMouseDown = ['input', 'textarea', 'button', 'select', 'option'];
const name = (e.target as HTMLElement).nodeName.toLowerCase();
if (skipMouseDown.find(skip => skip === name)) return true;
// also check for content editable
if ((e.target as HTMLElement).closest('[contenteditable="true"]')) return true;
// make sure we are not clicking on known object that handles mouseDown, or ones supplied by the user
if ((e.target as HTMLElement).closest(skipMouseDown)) return true;
if (this.option.cancel) {
if ((e.target as HTMLElement).closest(this.option.cancel)) return true;
}

// REMOVE: why would we get the event if it wasn't for us or child ?
// make sure we are clicking on a drag handle or child of it...
Expand Down
8 changes: 4 additions & 4 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -343,12 +343,12 @@ export interface DDDragOpt {
pause?: boolean | number;
/** default to `true` */
scroll?: boolean;
/** parent constraining where item can be dragged out from (default: null = no constrain) */
// containment?: string;
/** prevents dragging from starting on specified elements, listed as comma separated selectors (eg: '.no-drag'). default built in is 'input,textarea,button,select,option' */
cancel?: string;
}
export interface DDDragInOpt extends DDDragOpt {
/** helper function when dropping (ex: 'clone' or your own method) */
helper?: string | ((event: Event) => HTMLElement);
/** helper function when dropping: 'clone' or your own method */
helper?: 'clone' | ((event: Event) => HTMLElement);
/** used when dragging item from the outside, and canceling (ex: 'invalid' or your own method)*/
// revert?: string | ((event: Event) => HTMLElement);
}
Expand Down

0 comments on commit 771f546

Please sign in to comment.