@@ -53,6 +53,13 @@ var GridItem = module.exports = React.createClass({
53
53
} ;
54
54
} ,
55
55
56
+ getInitialState ( ) {
57
+ return {
58
+ resizing : false ,
59
+ className : ''
60
+ } ;
61
+ } ,
62
+
56
63
/**
57
64
* Return position on the page given an x, y, w, h.
58
65
* left, top, width, height are all in pixels.
@@ -65,9 +72,13 @@ var GridItem = module.exports = React.createClass({
65
72
var out = {
66
73
left : width * ( p . x / p . cols ) + p . margin [ 0 ] ,
67
74
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 ] ,
69
76
height : p . h * p . rowHeight - p . margin [ 1 ]
70
77
} ;
78
+ if ( this . state . resizing ) {
79
+ out . width = this . state . resizing . width ;
80
+ out . height = this . state . resizing . height ;
81
+ }
71
82
return out ;
72
83
} ,
73
84
@@ -87,13 +98,42 @@ var GridItem = module.exports = React.createClass({
87
98
return { x, y} ;
88
99
} ,
89
100
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
+ } ,
96
124
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
+ ) ;
97
137
} ,
98
138
99
139
/**
@@ -104,7 +144,7 @@ var GridItem = module.exports = React.createClass({
104
144
* @param {String } handlerName Handler name to wrap.
105
145
* @return {Function } Handler function.
106
146
*/
107
- dragHandler ( handlerName ) {
147
+ onDragHandler ( handlerName ) {
108
148
var me = this ;
109
149
return function ( e , { element, position} ) {
110
150
if ( ! me . props [ handlerName ] ) return ;
@@ -120,64 +160,67 @@ var GridItem = module.exports = React.createClass({
120
160
} ;
121
161
} ,
122
162
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 ;
125
175
126
- var p = this . props ;
127
- var { left , top , width , height } = this . calcPosition ( ) ;
176
+ // Get new XY
177
+ var { w , h } = me . calcWH ( size ) ;
128
178
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
+ } ,
135
189
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 ( ' ' ) ,
137
197
// We can set the width and height on the child, but unfortunately we can't set the position.
138
198
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' ,
141
201
position : 'absolute'
142
202
}
143
203
} ) ;
144
204
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 ) ;
148
210
}
149
211
150
- child . props . className = 'react-grid-item ' + ( child . props . className || "" ) + " " + this . props . className ;
151
-
152
212
// Resizable support. This is usually on but the user can toggle it off.
153
213
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 ) ;
164
215
}
165
216
166
217
// Draggable support. This is always on, except for with placeholders.
167
218
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 ;
181
224
}
182
225
183
226
return child ;
0 commit comments