Skip to content

Commit 96f126c

Browse files
committed
Resizing is working, update examples to show live state
1 parent 34bd0b4 commit 96f126c

File tree

10 files changed

+246
-150
lines changed

10 files changed

+246
-150
lines changed

README.md

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
### React-Grid-Layout
22

3-
[View the Demo](https://strml.github.io/react-grid-layout/examples/1.html)
3+
[View the Demo](https://strml.github.io/react-grid-layout/examples/1-basic.html)
44

55
React-Grid-Layout is a grid layout system much like [Packery](http://packery.metafizzy.co/) or
66
[Gridster](http://gridster.net), for React.
@@ -16,6 +16,11 @@ More demos are coming soon. RGL supports adding and removing components without
1616

1717
If you have a feature request, add it as an issue.
1818

19+
#### Demos
20+
21+
[1. Basic](https://strml.github.io/react-grid-layout/examples/1-basic.html)
22+
[1. No Dragging/Resizing (Layout Only)](https://strml.github.io/react-grid-layout/examples/2-no-dragging.html)
23+
1924
----
2025

2126
#### TODO List
@@ -25,5 +30,5 @@ If you have a feature request, add it as an issue.
2530
- [x] Grid packing
2631
- [x] Draggable grid items
2732
- [x] Live grid packing while dragging
33+
- [x] Resizable grid items
2834
- [ ] Define grid attributes on children themselves (`_grid` key)
29-
- [ ] Resizable grid items

examples/1-basic.html

Lines changed: 7 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,12 @@
11
<html>
22
<head>
3-
<style>
4-
body {
5-
background: white;
6-
padding: 20px;
7-
}
8-
#content {
9-
width: 100%;
10-
background: #eee;
11-
}
12-
.react-grid-item {
13-
background: #ccc;
14-
border: 1px solid black;
15-
}
16-
.react-grid-item .text {
17-
font-size: 24px;
18-
text-align: center;
19-
position: absolute;
20-
top: 0;
21-
bottom: 0;
22-
left: 0;
23-
right: 0;
24-
margin: auto;
25-
height: 24px;
26-
}
27-
</style>
3+
<script>
4+
window.gridProps = {
5+
isDraggable: true,
6+
isResizable: true,
7+
items: 20
8+
};
9+
</script>
2810
<script src="http://localhost:4002/bundle.js"></script>
2911
<title>RGL Example</title>
3012
</head>

examples/2-no-dragging.html

Lines changed: 2 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,11 @@
11
<html>
22
<head>
3-
<style>
4-
body {
5-
background: white;
6-
padding: 20px;
7-
}
8-
#content {
9-
width: 100%;
10-
background: #eee;
11-
}
12-
.react-grid-item {
13-
background: #ccc;
14-
border: 1px solid black;
15-
}
16-
.react-grid-item .text {
17-
font-size: 24px;
18-
text-align: center;
19-
position: absolute;
20-
top: 0;
21-
bottom: 0;
22-
left: 0;
23-
right: 0;
24-
margin: auto;
25-
height: 24px;
26-
}
27-
</style>
283
<script>
294
window.gridProps = {
305
isDraggable: false,
316
isResizable: false,
32-
items: 50
7+
items: 50,
8+
w: 2
339
};
3410
</script>
3511
<script src="http://localhost:4002/bundle.js"></script>

examples/example-styles.css

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
body {
2+
background: white;
3+
padding: 20px;
4+
}
5+
#content {
6+
width: 100%;
7+
}
8+
.react-grid-layout {
9+
background: #eee;
10+
}
11+
.layoutJSON {
12+
background: #ddd;
13+
border: 1px solid black;
14+
margin-top: 10px;
15+
padding: 10px;
16+
}
17+
.columns {
18+
-moz-columns: 100px;
19+
-webkit-columns: 100px;
20+
columns: 100px;
21+
}
22+
.react-grid-item:not(.react-grid-placeholder) {
23+
background: #ccc;
24+
border: 1px solid black;
25+
}
26+
.react-grid-item .text {
27+
font-size: 24px;
28+
text-align: center;
29+
position: absolute;
30+
top: 0;
31+
bottom: 0;
32+
left: 0;
33+
right: 0;
34+
margin: auto;
35+
height: 24px;
36+
}

index.html

Lines changed: 8 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,17 @@
11
<html>
22
<head>
3-
<style>
4-
body {
5-
background: white;
6-
padding: 20px;
7-
}
8-
#content {
9-
width: 100%;
10-
background: #eee;
11-
}
12-
.react-grid-item {
13-
background: #ccc;
14-
border: 1px solid black;
15-
}
16-
.react-grid-item .text {
17-
font-size: 24px;
18-
text-align: center;
19-
position: absolute;
20-
top: 0;
21-
bottom: 0;
22-
left: 0;
23-
right: 0;
24-
margin: auto;
25-
height: 24px;
26-
}
27-
</style>
3+
<script>
4+
window.gridProps = {
5+
isDraggable: true,
6+
isResizable: true,
7+
items: 20
8+
};
9+
</script>
2810
<script src="http://localhost:4002/bundle.js"></script>
2911
<title>RGL Example</title>
3012
</head>
3113
<body>
32-
<h3>React-Grid-Layout Demo</h3>
14+
<h3>React-Grid-Layout Dev</h3>
3315
<p>Try dragging the elements around.</p>
3416
<p>If you don't see any content, run webpack (<span style="font-family:monospace">npm run dev-server</span>)
3517
and load this file from the server it opens.</p>

lib/GridItem.jsx

Lines changed: 92 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,13 @@ var GridItem = module.exports = React.createClass({
5353
};
5454
},
5555

56+
getInitialState() {
57+
return {
58+
resizing: false,
59+
className: ''
60+
};
61+
},
62+
5663
/**
5764
* Return position on the page given an x, y, w, h.
5865
* left, top, width, height are all in pixels.
@@ -65,9 +72,13 @@ var GridItem = module.exports = React.createClass({
6572
var out = {
6673
left: width * (p.x / p.cols) + p.margin[0],
6774
top: p.rowHeight * p.y + p.margin[1],
68-
width: (width * p.w / p.cols) - ((p.w - 1) * p.margin[0]),
75+
width: width * (p.w / p.cols) - p.margin[0],
6976
height: p.h * p.rowHeight - p.margin[1]
7077
};
78+
if (this.state.resizing) {
79+
out.width = this.state.resizing.width;
80+
out.height = this.state.resizing.height;
81+
}
7182
return out;
7283
},
7384

@@ -87,13 +98,42 @@ var GridItem = module.exports = React.createClass({
8798
return {x, y};
8899
},
89100

90-
/**
91-
* Given a resize handle, figure out a new w and h for this element.
92-
* @param {DOMElement} element DOM Element (resize handle)
93-
* @return {Object} w and h.
94-
*/
95-
calcWH(element) {
101+
calcWH({height, width}) {
102+
var w = Math.round((width / this.props.containerWidth) * this.props.cols);
103+
var h = Math.round(height / this.props.rowHeight);
104+
w = Math.max(Math.min(w, this.props.cols - this.props.x), 0);
105+
h = Math.max(h, 0);
106+
return {w, h};
107+
},
108+
109+
mixinDraggable(child, position) {
110+
return (
111+
<Draggable
112+
start={{x: position.left, y: position.top}}
113+
moveOnStartChange={this.props.moveOnStartChange}
114+
onStop={this.onDragHandler('onDragStop')}
115+
onStart={this.onDragHandler('onDragStart')}
116+
onDrag={this.onDragHandler('onDrag')}
117+
handle={this.props.handle}
118+
cancel=".react-resizable-handle"
119+
>
120+
{child}
121+
</Draggable>
122+
);
123+
},
96124

125+
mixinResizable(child, position) {
126+
return (
127+
<Resizable
128+
width={position.width}
129+
height={position.height}
130+
onResizeStop={this.onResizeHandler('onResizeStop')}
131+
onResizeStart={this.onResizeHandler('onResizeStart')}
132+
onResize={this.onResizeHandler('onResize')}
133+
>
134+
{child}
135+
</Resizable>
136+
);
97137
},
98138

99139
/**
@@ -104,7 +144,7 @@ var GridItem = module.exports = React.createClass({
104144
* @param {String} handlerName Handler name to wrap.
105145
* @return {Function} Handler function.
106146
*/
107-
dragHandler(handlerName) {
147+
onDragHandler(handlerName) {
108148
var me = this;
109149
return function(e, {element, position}) {
110150
if (!me.props[handlerName]) return;
@@ -120,64 +160,67 @@ var GridItem = module.exports = React.createClass({
120160
};
121161
},
122162

123-
render() {
124-
var child = React.Children.only(this.props.children);
163+
/**
164+
* Wrapper around drag events to provide more useful data.
165+
* All drag events call the function with the given handler name,
166+
* with the signature (index, x, y).
167+
*
168+
* @param {String} handlerName Handler name to wrap.
169+
* @return {Function} Handler function.
170+
*/
171+
onResizeHandler(handlerName) {
172+
var me = this;
173+
return function(e, {element, size}) {
174+
if (!me.props[handlerName]) return;
125175

126-
var p = this.props;
127-
var {left, top, width, height} = this.calcPosition();
176+
// Get new XY
177+
var {w, h} = me.calcWH(size);
128178

129-
// If we're not mounted yet, use percentages; otherwise items won't fit the window properly
130-
// because this.props.width hasn't actually been populated with a real value
131-
if (!this.isMounted()) {
132-
left = utils.perc(left / p.containerWidth);
133-
width = utils.perc(width / p.containerWidth);
134-
}
179+
// Cap w at numCols
180+
if (w + me.props.x > me.props.cols) {
181+
w = me.props.cols - me.props.x;
182+
}
183+
184+
me.setState({resizing: handlerName === 'onResizeStop' ? null : size});
185+
186+
me.props[handlerName](me.props.i, w, h);
187+
};
188+
},
135189

136-
child = React.addons.cloneWithProps(child, {
190+
render() {
191+
var p = this.props, pos = this.calcPosition();
192+
193+
var child = React.addons.cloneWithProps(React.Children.only(this.props.children), {
194+
// Munge a classname. Use passed in classnames, child classnames, and resizing.
195+
className: ['react-grid-item', this.props.children.props.className || '', this.props.className,
196+
this.state.resizing ? 'resizing' : ''].join(' '),
137197
// We can set the width and height on the child, but unfortunately we can't set the position.
138198
style: {
139-
width: typeof width === "number" ? width + 'px' : width,
140-
height: typeof height === "number" ? height + 'px' : height,
199+
width: pos.width + 'px',
200+
height: pos.height + 'px',
141201
position: 'absolute'
142202
}
143203
});
144204

145-
// Place the element directly if draggability is turned off.
146-
if (!this.props.isDraggable) {
147-
child.props.style.left = left, child.props.style.top = top;
205+
// If we're not mounted yet, use percentages; otherwise items won't fit the window properly
206+
// because this.props.width hasn't actually been populated with a real value
207+
if (!this.isMounted()) {
208+
pos.left = utils.perc(pos.left / p.containerWidth);
209+
child.props.style.width = utils.perc(pos.width / p.containerWidth);
148210
}
149211

150-
child.props.className = 'react-grid-item ' + (child.props.className || "") + " " + this.props.className;
151-
152212
// Resizable support. This is usually on but the user can toggle it off.
153213
if (this.props.isResizable && this.isMounted()) {
154-
child = (
155-
<Resizable
156-
width={width}
157-
height={height}
158-
onResize={this.props.onResize}
159-
onResizeStop={this.props.onResizeStop}
160-
>
161-
{child}
162-
</Resizable>
163-
);
214+
child = this.mixinResizable(child, pos);
164215
}
165216

166217
// Draggable support. This is always on, except for with placeholders.
167218
if (this.props.isDraggable) {
168-
child = (
169-
<Draggable
170-
start={{x: left, y: top}}
171-
moveOnStartChange={this.props.moveOnStartChange}
172-
onStop={this.dragHandler('onDragStop')}
173-
onStart={this.dragHandler('onDragStart')}
174-
onDrag={this.dragHandler('onDrag')}
175-
handle={this.props.handle}
176-
cancel=".react-resizable-handle"
177-
>
178-
{child}
179-
</Draggable>
180-
);
219+
child = this.mixinDraggable(child, pos);
220+
}
221+
// Place the element directly if draggability is turned off.
222+
else {
223+
child.props.style.left = pos.left, child.props.style.top = pos.top;
181224
}
182225

183226
return child;

0 commit comments

Comments
 (0)