OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 part of html; | 5 part of html; |
6 | 6 |
7 /** | 7 /** |
8 * A rectangle representing all the content of the element in the | 8 * A rectangle representing all the content of the element in the |
9 * [box model](http://www.w3.org/TR/CSS2/box.html). | 9 * [box model](http://www.w3.org/TR/CSS2/box.html). |
10 */ | 10 */ |
11 class _ContentCssRect extends CssRect { | 11 class _ContentCssRect extends CssRect { |
12 | |
13 _ContentCssRect(Element element) : super(element); | 12 _ContentCssRect(Element element) : super(element); |
14 | 13 |
15 num get height => _element.offsetHeight + | 14 num get height => |
16 _addOrSubtractToBoxModel(_HEIGHT, _CONTENT); | 15 _element.offsetHeight + _addOrSubtractToBoxModel(_HEIGHT, _CONTENT); |
17 | 16 |
18 num get width => _element.offsetWidth + | 17 num get width => |
19 _addOrSubtractToBoxModel(_WIDTH, _CONTENT); | 18 _element.offsetWidth + _addOrSubtractToBoxModel(_WIDTH, _CONTENT); |
20 | 19 |
21 /** | 20 /** |
22 * Set the height to `newHeight`. | 21 * Set the height to `newHeight`. |
23 * | 22 * |
24 * newHeight can be either a [num] representing the height in pixels or a | 23 * newHeight can be either a [num] representing the height in pixels or a |
25 * [Dimension] object. Values of newHeight that are less than zero are | 24 * [Dimension] object. Values of newHeight that are less than zero are |
26 * converted to effectively setting the height to 0. This is equivalent to the | 25 * converted to effectively setting the height to 0. This is equivalent to the |
27 * `height` function in jQuery and the calculated `height` CSS value, | 26 * `height` function in jQuery and the calculated `height` CSS value, |
28 * converted to a num in pixels. | 27 * converted to a num in pixels. |
29 */ | 28 */ |
(...skipping 22 matching lines...) Expand all Loading... |
52 if (newWidth.value < 0) newWidth = new Dimension.px(0); | 51 if (newWidth.value < 0) newWidth = new Dimension.px(0); |
53 _element.style.width = newWidth.toString(); | 52 _element.style.width = newWidth.toString(); |
54 } else if (newWidth is num) { | 53 } else if (newWidth is num) { |
55 if (newWidth < 0) newWidth = 0; | 54 if (newWidth < 0) newWidth = 0; |
56 _element.style.width = '${newWidth}px'; | 55 _element.style.width = '${newWidth}px'; |
57 } else { | 56 } else { |
58 throw new ArgumentError("newWidth is not a Dimension or num"); | 57 throw new ArgumentError("newWidth is not a Dimension or num"); |
59 } | 58 } |
60 } | 59 } |
61 | 60 |
62 num get left => _element.getBoundingClientRect().left - | 61 num get left => |
| 62 _element.getBoundingClientRect().left - |
63 _addOrSubtractToBoxModel(['left'], _CONTENT); | 63 _addOrSubtractToBoxModel(['left'], _CONTENT); |
64 num get top => _element.getBoundingClientRect().top - | 64 num get top => |
| 65 _element.getBoundingClientRect().top - |
65 _addOrSubtractToBoxModel(['top'], _CONTENT); | 66 _addOrSubtractToBoxModel(['top'], _CONTENT); |
66 } | 67 } |
67 | 68 |
68 /** | 69 /** |
69 * A list of element content rectangles in the | 70 * A list of element content rectangles in the |
70 * [box model](http://www.w3.org/TR/CSS2/box.html). | 71 * [box model](http://www.w3.org/TR/CSS2/box.html). |
71 */ | 72 */ |
72 class _ContentCssListRect extends _ContentCssRect { | 73 class _ContentCssListRect extends _ContentCssRect { |
73 List<Element> _elementList; | 74 List<Element> _elementList; |
74 | 75 |
(...skipping 24 matching lines...) Expand all Loading... |
99 } | 100 } |
100 } | 101 } |
101 | 102 |
102 /** | 103 /** |
103 * A rectangle representing the dimensions of the space occupied by the | 104 * A rectangle representing the dimensions of the space occupied by the |
104 * element's content + padding in the | 105 * element's content + padding in the |
105 * [box model](http://www.w3.org/TR/CSS2/box.html). | 106 * [box model](http://www.w3.org/TR/CSS2/box.html). |
106 */ | 107 */ |
107 class _PaddingCssRect extends CssRect { | 108 class _PaddingCssRect extends CssRect { |
108 _PaddingCssRect(element) : super(element); | 109 _PaddingCssRect(element) : super(element); |
109 num get height => _element.offsetHeight + | 110 num get height => |
110 _addOrSubtractToBoxModel(_HEIGHT, _PADDING); | 111 _element.offsetHeight + _addOrSubtractToBoxModel(_HEIGHT, _PADDING); |
111 num get width => _element.offsetWidth + | 112 num get width => |
112 _addOrSubtractToBoxModel(_WIDTH, _PADDING); | 113 _element.offsetWidth + _addOrSubtractToBoxModel(_WIDTH, _PADDING); |
113 | 114 |
114 num get left => _element.getBoundingClientRect().left - | 115 num get left => |
| 116 _element.getBoundingClientRect().left - |
115 _addOrSubtractToBoxModel(['left'], _PADDING); | 117 _addOrSubtractToBoxModel(['left'], _PADDING); |
116 num get top => _element.getBoundingClientRect().top - | 118 num get top => |
| 119 _element.getBoundingClientRect().top - |
117 _addOrSubtractToBoxModel(['top'], _PADDING); | 120 _addOrSubtractToBoxModel(['top'], _PADDING); |
118 } | 121 } |
119 | 122 |
120 /** | 123 /** |
121 * A rectangle representing the dimensions of the space occupied by the | 124 * A rectangle representing the dimensions of the space occupied by the |
122 * element's content + padding + border in the | 125 * element's content + padding + border in the |
123 * [box model](http://www.w3.org/TR/CSS2/box.html). | 126 * [box model](http://www.w3.org/TR/CSS2/box.html). |
124 */ | 127 */ |
125 class _BorderCssRect extends CssRect { | 128 class _BorderCssRect extends CssRect { |
126 _BorderCssRect(element) : super(element); | 129 _BorderCssRect(element) : super(element); |
127 num get height => _element.offsetHeight; | 130 num get height => _element.offsetHeight; |
128 num get width => _element.offsetWidth; | 131 num get width => _element.offsetWidth; |
129 | 132 |
130 num get left => _element.getBoundingClientRect().left; | 133 num get left => _element.getBoundingClientRect().left; |
131 num get top => _element.getBoundingClientRect().top; | 134 num get top => _element.getBoundingClientRect().top; |
132 } | 135 } |
133 | 136 |
134 /** | 137 /** |
135 * A rectangle representing the dimensions of the space occupied by the | 138 * A rectangle representing the dimensions of the space occupied by the |
136 * element's content + padding + border + margin in the | 139 * element's content + padding + border + margin in the |
137 * [box model](http://www.w3.org/TR/CSS2/box.html). | 140 * [box model](http://www.w3.org/TR/CSS2/box.html). |
138 */ | 141 */ |
139 class _MarginCssRect extends CssRect { | 142 class _MarginCssRect extends CssRect { |
140 _MarginCssRect(element) : super(element); | 143 _MarginCssRect(element) : super(element); |
141 num get height => _element.offsetHeight + | 144 num get height => |
142 _addOrSubtractToBoxModel(_HEIGHT, _MARGIN); | 145 _element.offsetHeight + _addOrSubtractToBoxModel(_HEIGHT, _MARGIN); |
143 num get width => | 146 num get width => |
144 _element.offsetWidth + _addOrSubtractToBoxModel(_WIDTH, _MARGIN); | 147 _element.offsetWidth + _addOrSubtractToBoxModel(_WIDTH, _MARGIN); |
145 | 148 |
146 num get left => _element.getBoundingClientRect().left - | 149 num get left => |
| 150 _element.getBoundingClientRect().left - |
147 _addOrSubtractToBoxModel(['left'], _MARGIN); | 151 _addOrSubtractToBoxModel(['left'], _MARGIN); |
148 num get top => _element.getBoundingClientRect().top - | 152 num get top => |
| 153 _element.getBoundingClientRect().top - |
149 _addOrSubtractToBoxModel(['top'], _MARGIN); | 154 _addOrSubtractToBoxModel(['top'], _MARGIN); |
150 } | 155 } |
151 | 156 |
152 /** | 157 /** |
153 * A class for representing CSS dimensions. | 158 * A class for representing CSS dimensions. |
154 * | 159 * |
155 * In contrast to the more general purpose [Rectangle] class, this class's | 160 * In contrast to the more general purpose [Rectangle] class, this class's |
156 * values are mutable, so one can change the height of an element | 161 * values are mutable, so one can change the height of an element |
157 * programmatically. | 162 * programmatically. |
158 * | 163 * |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
218 set width(newWidth) { | 223 set width(newWidth) { |
219 throw new UnsupportedError("Can only set width for content rect."); | 224 throw new UnsupportedError("Can only set width for content rect."); |
220 } | 225 } |
221 | 226 |
222 /** | 227 /** |
223 * Return a value that is used to modify the initial height or width | 228 * Return a value that is used to modify the initial height or width |
224 * measurement of an element. Depending on the value (ideally an enum) passed | 229 * measurement of an element. Depending on the value (ideally an enum) passed |
225 * to augmentingMeasurement, we may need to add or subtract margin, padding, | 230 * to augmentingMeasurement, we may need to add or subtract margin, padding, |
226 * or border values, depending on the measurement we're trying to obtain. | 231 * or border values, depending on the measurement we're trying to obtain. |
227 */ | 232 */ |
228 num _addOrSubtractToBoxModel(List<String> dimensions, | 233 num _addOrSubtractToBoxModel( |
229 String augmentingMeasurement) { | 234 List<String> dimensions, String augmentingMeasurement) { |
230 // getComputedStyle always returns pixel values (hence, computed), so we're | 235 // getComputedStyle always returns pixel values (hence, computed), so we're |
231 // always dealing with pixels in this method. | 236 // always dealing with pixels in this method. |
232 var styles = _element.getComputedStyle(); | 237 var styles = _element.getComputedStyle(); |
233 | 238 |
234 var val = 0; | 239 var val = 0; |
235 | 240 |
236 for (String measurement in dimensions) { | 241 for (String measurement in dimensions) { |
237 // The border-box and default box model both exclude margin in the regular | 242 // The border-box and default box model both exclude margin in the regular |
238 // height/width calculation, so add it if we want it for this measurement. | 243 // height/width calculation, so add it if we want it for this measurement. |
239 if (augmentingMeasurement == _MARGIN) { | 244 if (augmentingMeasurement == _MARGIN) { |
240 val += new Dimension.css(styles.getPropertyValue( | 245 val += new Dimension.css( |
241 '$augmentingMeasurement-$measurement')).value; | 246 styles.getPropertyValue('$augmentingMeasurement-$measurement')) |
| 247 .value; |
242 } | 248 } |
243 | 249 |
244 // The border-box includes padding and border, so remove it if we want | 250 // The border-box includes padding and border, so remove it if we want |
245 // just the content itself. | 251 // just the content itself. |
246 if (augmentingMeasurement == _CONTENT) { | 252 if (augmentingMeasurement == _CONTENT) { |
247 » val -= new Dimension.css( | 253 val -= new Dimension.css( |
248 styles.getPropertyValue('${_PADDING}-$measurement')).value; | 254 styles.getPropertyValue('${_PADDING}-$measurement')) |
| 255 .value; |
249 } | 256 } |
250 | 257 |
251 // At this point, we don't wan't to augment with border or margin, | 258 // At this point, we don't wan't to augment with border or margin, |
252 // so remove border. | 259 // so remove border. |
253 if (augmentingMeasurement != _MARGIN) { | 260 if (augmentingMeasurement != _MARGIN) { |
254 » val -= new Dimension.css(styles.getPropertyValue( | 261 val -= new Dimension.css( |
255 'border-${measurement}-width')).value; | 262 styles.getPropertyValue('border-${measurement}-width')) |
| 263 .value; |
256 } | 264 } |
257 } | 265 } |
258 return val; | 266 return val; |
259 } | 267 } |
260 | 268 |
261 // TODO(jacobr): these methods are duplicated from _RectangleBase in dart:math | 269 // TODO(jacobr): these methods are duplicated from _RectangleBase in dart:math |
262 // Ideally we would provide a RectangleMixin class that provides this implemen
tation. | 270 // Ideally we would provide a RectangleMixin class that provides this implemen
tation. |
263 // In an ideal world we would exp | 271 // In an ideal world we would exp |
264 /** The x-coordinate of the right edge. */ | 272 /** The x-coordinate of the right edge. */ |
265 num get right => left + width; | 273 num get right => left + width; |
266 /** The y-coordinate of the bottom edge. */ | 274 /** The y-coordinate of the bottom edge. */ |
267 num get bottom => top + height; | 275 num get bottom => top + height; |
268 | 276 |
269 String toString() { | 277 String toString() { |
270 return 'Rectangle ($left, $top) $width x $height'; | 278 return 'Rectangle ($left, $top) $width x $height'; |
271 } | 279 } |
272 | 280 |
273 bool operator ==(other) { | 281 bool operator ==(other) { |
274 if (other is !Rectangle) return false; | 282 if (other is! Rectangle) return false; |
275 return left == other.left && top == other.top && right == other.right && | 283 return left == other.left && |
| 284 top == other.top && |
| 285 right == other.right && |
276 bottom == other.bottom; | 286 bottom == other.bottom; |
277 } | 287 } |
278 | 288 |
279 int get hashCode => _JenkinsSmiHash.hash4(left.hashCode, top.hashCode, | 289 int get hashCode => _JenkinsSmiHash.hash4( |
280 right.hashCode, bottom.hashCode); | 290 left.hashCode, top.hashCode, right.hashCode, bottom.hashCode); |
281 | 291 |
282 /** | 292 /** |
283 * Computes the intersection of `this` and [other]. | 293 * Computes the intersection of `this` and [other]. |
284 * | 294 * |
285 * The intersection of two axis-aligned rectangles, if any, is always another | 295 * The intersection of two axis-aligned rectangles, if any, is always another |
286 * axis-aligned rectangle. | 296 * axis-aligned rectangle. |
287 * | 297 * |
288 * Returns the intersection of this and `other`, or `null` if they don't | 298 * Returns the intersection of this and `other`, or `null` if they don't |
289 * intersect. | 299 * intersect. |
290 */ | 300 */ |
291 Rectangle<num> intersection(Rectangle<num> other) { | 301 Rectangle<num> intersection(Rectangle<num> other) { |
292 var x0 = max(left, other.left); | 302 var x0 = max(left, other.left); |
293 var x1 = min(left + width, other.left + other.width); | 303 var x1 = min(left + width, other.left + other.width); |
294 | 304 |
295 if (x0 <= x1) { | 305 if (x0 <= x1) { |
296 var y0 = max(top, other.top); | 306 var y0 = max(top, other.top); |
297 var y1 = min(top + height, other.top + other.height); | 307 var y1 = min(top + height, other.top + other.height); |
298 | 308 |
299 if (y0 <= y1) { | 309 if (y0 <= y1) { |
300 return new Rectangle<num>(x0, y0, x1 - x0, y1 - y0); | 310 return new Rectangle<num>(x0, y0, x1 - x0, y1 - y0); |
301 } | 311 } |
302 } | 312 } |
303 return null; | 313 return null; |
304 } | 314 } |
305 | 315 |
306 | |
307 /** | 316 /** |
308 * Returns true if `this` intersects [other]. | 317 * Returns true if `this` intersects [other]. |
309 */ | 318 */ |
310 bool intersects(Rectangle<num> other) { | 319 bool intersects(Rectangle<num> other) { |
311 return (left <= other.left + other.width && | 320 return (left <= other.left + other.width && |
312 other.left <= left + width && | 321 other.left <= left + width && |
313 top <= other.top + other.height && | 322 top <= other.top + other.height && |
314 other.top <= top + height); | 323 other.top <= top + height); |
315 } | 324 } |
316 | 325 |
317 /** | 326 /** |
318 * Returns a new rectangle which completely contains `this` and [other]. | 327 * Returns a new rectangle which completely contains `this` and [other]. |
319 */ | 328 */ |
320 Rectangle<num> boundingBox(Rectangle<num> other) { | 329 Rectangle<num> boundingBox(Rectangle<num> other) { |
321 var right = max(this.left + this.width, other.left + other.width); | 330 var right = max(this.left + this.width, other.left + other.width); |
322 var bottom = max(this.top + this.height, other.top + other.height); | 331 var bottom = max(this.top + this.height, other.top + other.height); |
323 | 332 |
324 var left = min(this.left, other.left); | 333 var left = min(this.left, other.left); |
325 var top = min(this.top, other.top); | 334 var top = min(this.top, other.top); |
326 | 335 |
327 return new Rectangle<num>(left, top, right - left, bottom - top); | 336 return new Rectangle<num>(left, top, right - left, bottom - top); |
328 } | 337 } |
329 | 338 |
330 /** | 339 /** |
331 * Tests whether `this` entirely contains [another]. | 340 * Tests whether `this` entirely contains [another]. |
332 */ | 341 */ |
333 bool containsRectangle(Rectangle<num> another) { | 342 bool containsRectangle(Rectangle<num> another) { |
334 return left <= another.left && | 343 return left <= another.left && |
335 left + width >= another.left + another.width && | 344 left + width >= another.left + another.width && |
336 top <= another.top && | 345 top <= another.top && |
337 top + height >= another.top + another.height; | 346 top + height >= another.top + another.height; |
338 } | 347 } |
339 | 348 |
340 /** | 349 /** |
341 * Tests whether [another] is inside or along the edges of `this`. | 350 * Tests whether [another] is inside or along the edges of `this`. |
342 */ | 351 */ |
343 bool containsPoint(Point<num> another) { | 352 bool containsPoint(Point<num> another) { |
344 return another.x >= left && | 353 return another.x >= left && |
345 another.x <= left + width && | 354 another.x <= left + width && |
346 another.y >= top && | 355 another.y >= top && |
347 another.y <= top + height; | 356 another.y <= top + height; |
348 } | 357 } |
349 | 358 |
350 Point<num> get topLeft => new Point<num>(this.left, this.top); | 359 Point<num> get topLeft => new Point<num>(this.left, this.top); |
351 Point<num> get topRight => new Point<num>(this.left + this.width, this.top); | 360 Point<num> get topRight => new Point<num>(this.left + this.width, this.top); |
352 Point<num> get bottomRight => new Point<num>(this.left + this.width, | 361 Point<num> get bottomRight => |
353 this.top + this.height); | 362 new Point<num>(this.left + this.width, this.top + this.height); |
354 Point<num> get bottomLeft => new Point<num>(this.left, | 363 Point<num> get bottomLeft => |
355 this.top + this.height); | 364 new Point<num>(this.left, this.top + this.height); |
356 } | 365 } |
357 | 366 |
358 final _HEIGHT = ['top', 'bottom']; | 367 final _HEIGHT = ['top', 'bottom']; |
359 final _WIDTH = ['right', 'left']; | 368 final _WIDTH = ['right', 'left']; |
360 final _CONTENT = 'content'; | 369 final _CONTENT = 'content'; |
361 final _PADDING = 'padding'; | 370 final _PADDING = 'padding'; |
362 final _MARGIN = 'margin'; | 371 final _MARGIN = 'margin'; |
OLD | NEW |