Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions demo/demo.css
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,16 @@ h1 {
cursor: move;
min-height: 25px;
background-color: #16af91;
&.outside {
display: none;
width: fit-content;
position: absolute;
cursor: move;
z-index: 99999;
&:hover {
display: block;
}
}
}
.card-header:hover {
background-color: #149b80;
Expand Down
1 change: 1 addition & 0 deletions demo/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ <h1>Demos</h1>
<li><a href="sizeToContent.html">Size To Content</a></li>
<li><a href="static.html">Static</a></li>
<li><a href="title_drag.html">Title drag</a></li>
<li><a href="title_drag_from_outside_gs_item.html">Title drag from outside grid stack item</a></li>
<li><a href="transform.html">Transform (scale+offset)</a></li>
<li><a href="two.html">Two grids</a></li>
<li><a href="two_vertical.html">Two grids Vertical</a></li>
Expand Down
61 changes: 61 additions & 0 deletions demo/title_drag_from_outside_gs_item.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Title area drag from outside GridStack item</title>

<link rel="stylesheet" href="demo.css" />
<script src="../dist/gridstack-all.js"></script>
</head>

<body>
<div class="container-fluid">
<h1>Title area drag from outside GridStack item</h1>
<br><br>
<div class="card-header outside">- Drag here -</div>
<div class="grid-stack">
<div class="grid-stack-item external" gs-w="3" gs-h="3">
<div class="grid-stack-item-content">
<div class="card">Hover on the panel to toggle drag title (which is outside grid-stack-item) visibility. The
rest of the panel content doesn't drag.</div>
</div>
</div>
<div class="grid-stack-item" gs-w="3" gs-h="3">
<div class="grid-stack-item-content">
<div class="card-header">- Drag here -</div>
<div class="card">This panel has title inside grid item. Only title drags, rest of the panel content doesn't drag.</div>
</div>
</div>
</div>
</div>
<script src="events.js"></script>
<script type="text/javascript">
let grid = GridStack.init({
handle: '.card-header'
}); // drag by the header only
addEvents(grid);
const itemWithExternalTitle = document.querySelector('.grid-stack-item.external');
const externalTitle = document.querySelector('.card-header.outside');
grid.update(itemWithExternalTitle, {noResize: true, noMove: true});
GridStack.setupDragIn([itemWithExternalTitle], {
dragElements: [externalTitle]
});
grid.update(itemWithExternalTitle, {noResize: false, noMove: false});
itemWithExternalTitle.addEventListener('mouseover', () => {
externalTitle.style.display = 'block';
externalTitle.style.left = `calc(${itemWithExternalTitle.getBoundingClientRect().left}px + 10px)`;
externalTitle.style.top = `calc(${itemWithExternalTitle.getBoundingClientRect().top}px - 14px)`;
});
itemWithExternalTitle.addEventListener('mouseout', () => {
externalTitle.style.display = '';
});
grid.on('dragstop', () => {
externalTitle.style.left = `calc(${itemWithExternalTitle.getBoundingClientRect().left}px + 10px)`;
});
</script>
</body>

</html>
1 change: 1 addition & 0 deletions doc/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ v10.x supports a much richer responsive behavior, you can have breakpoints of wi
- `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'
- `helper`?: 'clone' | ((el: HTMLElement) => HTMLElement) - helper function when dragging side panel items that need to be cloned before dropping (ex: 'clone' or your own method)
- `dragElements`?: HTMLElement[] - references to the elements (outside the grid item) to be used for dragging grid item
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

honestly this wouldn't work in general since you assume a fix set of elements (really a single one shared in your case) which doesn't work for dynamic elements. what happens when you add/remove/reparent items ?


## Grid attributes

Expand Down
73 changes: 73 additions & 0 deletions spec/gridstack-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,20 @@ describe('gridstack >', function() {
'</div>';
// generic widget with no param
let widgetHTML = '<div id="item3"><div class="grid-stack-item-content"> hello </div></div>';
// grid with one grid item which has item title outside grid
let gridstackExternalItemTitle = `
<div style="width: 800px; height: 600px" id="gs-cont">
<div class="title-header">- Drag Here -</div>
<div class="grid-stack">
<div class="grid-stack-item" gs-w="3" gs-h="3">
<div class="grid-stack-item-content">
<div class="card">Hover on the panel to toggle drag title (which is outside grid-stack-item) visibility. The
rest of the panel content doesn't drag.</div>
</div>
</div>
</div>
</div>
`;

describe('grid.init() / initAll() >', function() {
beforeEach(function() {
Expand Down Expand Up @@ -1986,4 +2000,63 @@ describe('gridstack >', function() {
});
});

describe("grid.moveExternal >", function () {
beforeEach(function () {
document.body.insertAdjacentHTML("afterbegin", gridstackExternalItemTitle);
});
afterEach(function () {
document.body.removeChild(document.getElementById("gs-cont"));
});
it("dragstart event not triggered on external element drag >", function () {
let externalTitle = document.querySelector<HTMLElement>(".title-header")!;
grid = GridStack.init();
let test = 0;
grid.on("dragstart", () => {
test++;
});
let mouseDownEvt = new MouseEvent("mousedown", {
bubbles: true,
cancelable: true,
clientX: externalTitle.getBoundingClientRect().x,
clientY: externalTitle.getBoundingClientRect().y,
});
externalTitle?.dispatchEvent(mouseDownEvt);
let mousemove_event = new MouseEvent("mousemove", {
bubbles: true,
cancelable: true,
clientX: externalTitle.getBoundingClientRect().x + 5,
clientY: externalTitle.getBoundingClientRect().y + 5,
});
document.dispatchEvent(mousemove_event);
expect(test).toBe(0);
});
it("dragstart event triggered on external element drag >", function () {
let externalTitle = document.querySelector<HTMLElement>(".title-header")!;
grid = GridStack.init({
draggable: {
dragElements: [externalTitle],
},
});
let test = 0;
grid.on("dragstart", () => {
test++;
});
let mouseDownEvt = new MouseEvent("mousedown", {
bubbles: true,
cancelable: true,
clientX: externalTitle.getBoundingClientRect().x,
clientY: externalTitle.getBoundingClientRect().y,
});
externalTitle?.dispatchEvent(mouseDownEvt);
let mousemove_event = new MouseEvent("mousemove", {
bubbles: true,
cancelable: true,
clientX: externalTitle.getBoundingClientRect().x + 5,
clientY: externalTitle.getBoundingClientRect().y + 5,
});
document.dispatchEvent(mousemove_event);
expect(test).not.toBe(0);
});
});

});
3 changes: 3 additions & 0 deletions src/dd-draggable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ export class DDDraggable extends DDBaseImplement implements HTMLElementExtendOpt
const handleName = option?.handle?.substring(1);
const n = el.gridstackNode;
this.dragEls = !handleName || el.classList.contains(handleName) ? [el] : (n?.subGrid ? [el.querySelector(option.handle) || el] : Array.from(el.querySelectorAll(option.handle)));
if(option?.dragElements?.length) {
this.dragEls = option.dragElements
}
if (this.dragEls.length === 0) {
this.dragEls = [el];
}
Expand Down
2 changes: 2 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,8 @@ export interface DDDragOpt {
cancel?: string;
/** helper function when dropping: 'clone' or your own method */
helper?: 'clone' | ((el: HTMLElement) => HTMLElement);
/** references to the elements (outside the grid item) to be used for dragging grid item */
dragElements?: HTMLElement[];
/** callbacks */
start?: (event: Event, ui: DDUIData) => void;
stop?: (event: Event) => void;
Expand Down
2 changes: 1 addition & 1 deletion src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -434,7 +434,7 @@ export class Utils {
*/
static cloneDeep<T>(obj: T): T {
// list of fields we will skip during cloneDeep (nested objects, other internal)
const skipFields = ['parentGrid', 'el', 'grid', 'subGrid', 'engine'];
const skipFields = ['parentGrid', 'el', 'grid', 'subGrid', 'engine', 'dragElements'];
// return JSON.parse(JSON.stringify(obj)); // doesn't work with date format ?
const ret = Utils.clone(obj);
for (const key in ret) {
Expand Down