Sunday, May 12, 2024
 Popular · Latest · Hot · Upcoming
-1
rated 0 times [  4] [ 5]  / answers: 1 / hits: 47880  / 9 Years ago, tue, march 10, 2015, 12:00:00

I'm struggling a little trying to determine the current location and size of an element within the DOM. I've put together a fragment to illustrate a card based system down the right hand side of the screen.



The behavior that I'm trying to build is that when you click on one of those cards, another card will be added (ultimately underneath, but on top for now) which will fly out to the top left corner of the screen before filling the available space.





d3.selectAll(attribute-card).on(click, function (d) {

var rect = this.getBoundingClientRect();
var card = d3.select(body)
.append(div)
.attr(class, card)
.style(background, transparent)
.style(border, thin solid red)
.style(left, rect.left + px)
.style(top, rect.top + px)
.style(width, (rect.right - rect.left) + px)
.style(height, (rect.bottom - rect.top) + px)
.style(position, absolute);
});

html {
height: 100%;
margin: 0;
font-family: Arial;
overflow: hidden;
}
body {
height: 100%;
}
svg {
background: #2c272b;
width: 100%;
height: 100%;
}
.radial-menu .segment {
fill: #3b3944;
}
.radial-menu .segment:hover {
fill: #535060;
}
.radial-menu .symbol {
pointer-events: none;
fill: white;
}
.radial-menu .symbol.icon {
font-family: 'FontAwesome';
}
.beam {
stroke: #fff;
}
.planet circle {
fill: #399745;
stroke: #3b3944;
stroke-width: 0;
stroke-dasharray: 33,11;
}
.planet .related {
fill: none;
stroke: #3b3944;
stroke-dasharray: none;
stroke-width: 25px;
}
.planet text {
fill: #000;
opacity: 0.4;
text-anchor: middle;
pointer-events: none;
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.planet .name {
font-size: 2.5em;
width: 94%;
margin: 125px 0px 0px 10px;
}
.planet.selected text {
fill: white;
opacity: 1;
}
.planet.focused text {
fill: white;
opacity: 1;
}
.moon circle {
fill: #3b3944;
}
.moon:hover {
fill: #535060;
}
.moon text {
fill: white;
text-anchor: middle;
pointer-events: none;
}
.gravity {
stroke: #3b3944;
fill: #3b3944;
stroke-linecap: round;
stroke-width: 2px;
}
.card-list {
background: #2c272b;
position: absolute;
top: 0;
right: 0;
width: 200px;
min-height: 100%;
opacity: 1;
}
.card {
background: #dedede;
border: 2px solid #ebebeb;
margin: 5px 5px 5px 5px;
border-radius: 8px;
padding: 5px 15px 5px 15px;
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.card .title {
font-weight: bold;
}
.card .summary {
color: #cc8b11;
font-weight: bold;
font-size: 12px;
}
.card .summary .summary-item {
margin: 0;
}
/*# sourceMappingURL=style.css.map */

<script src=https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js></script>
<html><head>
<meta charset=utf-8>
<meta name=msapplication-tap-highlight content=no>
<title name=Business Landscape Explorer Prototype></title>
<link href=bootstrap.min.css rel=stylesheet>
<link rel=stylesheet href=//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css>
<link rel=stylesheet type=text/css href=styles/style.css>
<script src=d3.v3.js charset=utf-8></script><style type=text/css></style>
</head>
<body>

<div id=card-list class=card-list>
<div id=attributes class=attribute-list data-bind=foreach: attributes>
<attribute-card params=value: $data><div class=card attribute-card> <p class=title data-bind=text: name>Name</p> <div class=summary data-bind=foreach: summaries></div> </div></attribute-card>

<attribute-card params=value: $data><div class=card attribute-card> <p class=title data-bind=text: name>Cost</p> <div class=summary data-bind=foreach: summaries> <p class=summary-item data-bind=text: $data>Average: £9 million</p> <p class=summary-item data-bind=text: $data>Total: £2,700 million</p> </div> </div></attribute-card>

<attribute-card params=value: $data><div class=card attribute-card> <p class=title data-bind=text: name>Start Date</p> <div class=summary data-bind=foreach: summaries> <p class=summary-item data-bind=text: $data>Earliest: 31st Jan 2007</p> <p class=summary-item data-bind=text: $data>Latest: 27th Nov 2019</p> </div> </div></attribute-card>

<attribute-card params=value: $data><div class=card attribute-card> <p class=title data-bind=text: name>Enabled</p> <div class=summary data-bind=foreach: summaries> <p class=summary-item data-bind=text: $data>True: 71%</p> <p class=summary-item data-bind=text: $data>False: 29%</p> </div> </div></attribute-card>

<attribute-card params=value: $data><div class=card attribute-card> <p class=title data-bind=text: name>Status</p> <div class=summary data-bind=foreach: summaries> <p class=summary-item data-bind=text: $data>Red: 11%</p> <p class=summary-item data-bind=text: $data>Amber: 36%</p> <p class=summary-item data-bind=text: $data>Green: 41%</p> </div> </div></attribute-card>
</div>
</div>

</body></html>





What I am doing is fairly basic, grab the clicked element, measure it's bounding rectangle and adding a new element to the body with the same size and position:



d3.selectAll(attribute-card).on(click, function (d) {

var rect = this.getBoundingClientRect();
var card = d3.select(body)
.append(div)
.attr(class, card)
.style(background, transparent)
.style(border, thin solid red)
.style(left, rect.left + px)
.style(top, rect.top + px)
.style(width, (rect.right - rect.left) + px)
.style(height, (rect.bottom - rect.top) + px)
.style(position, absolute);
});


I've been reading about getBoundingClientRect() and it seems to do what I want according to the spec, it's just not doing what I expect it to here as the width/height are all off, and Firefox can't even get the left correct. Is this function simply broken (which would surprise me) or is some of my CSS somehow breaking this native function?



I should add here is a screenshot of the results being off in different browsers. IE is by far the nearest but still seems to struggle with the bottom/right values.



enter


More From » html

 Answers
16

Well I'm mightily confused but managed to get the thing working as I wanted. I changed the calculation to take into account padding, margin and borders based on a little guess work, and modifying some styles to verify it all still worked. This gave me the following calculation:


var rect = element.getBoundingClientRect();
rect = {
left: rect.left - margin.left,
right: rect.right - margin.right - padding.left - padding.right,
top: rect.top - margin.top,
bottom: rect.bottom - margin.bottom - padding.top - padding.bottom - border.bottom
};
rect.width = rect.right - rect.left;
rect.height = rect.bottom - rect.top;
return rect;

Oddly though when I tried plugging this into my application it didn't work at all. Taking out some of the padding and ended up with:


rect = {
left: rect.left - margin.left,
right: rect.right - border.right,
top: rect.top - margin.top,
bottom: rect.bottom - border.bottom - border.top
};
rect.height = rect.bottom - rect.top;
rect.width = rect.right - rect.left;
return rect;



function getBoundingRect(element) {

var style = window.getComputedStyle(element);
var margin = {
left: parseInt(style[margin-left]),
right: parseInt(style[margin-right]),
top: parseInt(style[margin-top]),
bottom: parseInt(style[margin-bottom])
};
var padding = {
left: parseInt(style[padding-left]),
right: parseInt(style[padding-right]),
top: parseInt(style[padding-top]),
bottom: parseInt(style[padding-bottom])
};
var border = {
left: parseInt(style[border-left]),
right: parseInt(style[border-right]),
top: parseInt(style[border-top]),
bottom: parseInt(style[border-bottom])
};


var rect = element.getBoundingClientRect();
rect = {
left: rect.left - margin.left,
right: rect.right - margin.right - padding.left - padding.right,
top: rect.top - margin.top,
bottom: rect.bottom - margin.bottom - padding.top - padding.bottom - border.bottom
};
rect.width = rect.right - rect.left;
rect.height = rect.bottom - rect.top;
return rect;

};

d3.selectAll(.card).on(click, function (d) {

var rect = getBoundingRect(this);

var card = d3.select(body)
.append(div)
.attr(class, card)
.style(background, transparent)
.style(border, thin solid red)
.style(left, rect.left + px)
.style(top, rect.top + px)
.style(width, rect.width + px)
.style(height, rect.height + px)
.style(position, absolute);
});

html {
height: 100%;
margin: 0;
font-family: Arial;
overflow: hidden;
}
body {
height: 100%;
}
svg {
background: #2c272b;
width: 100%;
height: 100%;
}
.radial-menu .segment {
fill: #3b3944;
}
.radial-menu .segment:hover {
fill: #535060;
}
.radial-menu .symbol {
pointer-events: none;
fill: white;
}
.radial-menu .symbol.icon {
font-family: 'FontAwesome';
}
.beam {
stroke: #fff;
}
.planet circle {
fill: #399745;
stroke: #3b3944;
stroke-width: 0;
stroke-dasharray: 33,11;
}
.planet .related {
fill: none;
stroke: #3b3944;
stroke-dasharray: none;
stroke-width: 25px;
}
.planet text {
fill: #000;
opacity: 0.4;
text-anchor: middle;
pointer-events: none;
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.planet .name {
font-size: 2.5em;
width: 94%;
margin: 125px 0px 0px 10px;
}
.planet.selected text {
fill: white;
opacity: 1;
}
.planet.focused text {
fill: white;
opacity: 1;
}
.moon circle {
fill: #3b3944;
}
.moon:hover {
fill: #535060;
}
.moon text {
fill: white;
text-anchor: middle;
pointer-events: none;
}
.gravity {
stroke: #3b3944;
fill: #3b3944;
stroke-linecap: round;
stroke-width: 2px;
}
.card-list {
background: #2c272b;
position: absolute;
top: 0;
right: 0;
width: 200px;
min-height: 100%;
opacity: 1;
}
.card {
background: #dedede;
border: 2px solid #ebebeb;
margin: 5px 5px 5px 5px;
border-radius: 8px;
padding: 5px 15px 5px 15px;
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.card .title {
font-weight: bold;
}
.card .summary {
color: #cc8b11;
font-weight: bold;
font-size: 12px;
}
.card .summary .summary-item {
margin: 0;
}
/*# sourceMappingURL=style.css.map */

<script src=https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js></script>
<html><head>
<meta charset=utf-8>
<meta name=msapplication-tap-highlight content=no>
<title name=Business Landscape Explorer Prototype></title>
<link href=bootstrap.min.css rel=stylesheet>
<link rel=stylesheet href=//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css>
<link rel=stylesheet type=text/css href=styles/style.css>
<script src=d3.v3.js charset=utf-8></script><style type=text/css></style>
</head>
<body>

<div id=card-list class=card-list>
<div id=attributes class=attribute-list data-bind=foreach: attributes>
<attribute-card params=value: $data><div class=card attribute-card> <p class=title data-bind=text: name>Name</p> <div class=summary data-bind=foreach: summaries></div> </div></attribute-card>

<attribute-card params=value: $data><div class=card attribute-card> <p class=title data-bind=text: name>Cost</p> <div class=summary data-bind=foreach: summaries> <p class=summary-item data-bind=text: $data>Average: £9 million</p> <p class=summary-item data-bind=text: $data>Total: £2,700 million</p> </div> </div></attribute-card>

<attribute-card params=value: $data><div class=card attribute-card> <p class=title data-bind=text: name>Start Date</p> <div class=summary data-bind=foreach: summaries> <p class=summary-item data-bind=text: $data>Earliest: 31st Jan 2007</p> <p class=summary-item data-bind=text: $data>Latest: 27th Nov 2019</p> </div> </div></attribute-card>

<attribute-card params=value: $data><div class=card attribute-card> <p class=title data-bind=text: name>Enabled</p> <div class=summary data-bind=foreach: summaries> <p class=summary-item data-bind=text: $data>True: 71%</p> <p class=summary-item data-bind=text: $data>False: 29%</p> </div> </div></attribute-card>

<attribute-card params=value: $data><div class=card attribute-card> <p class=title data-bind=text: name>Status</p> <div class=summary data-bind=foreach: summaries> <p class=summary-item data-bind=text: $data>Red: 11%</p> <p class=summary-item data-bind=text: $data>Amber: 36%</p> <p class=summary-item data-bind=text: $data>Green: 41%</p> </div> </div></attribute-card>
</div>
</div>

</body></html>




[#67500] Sunday, March 8, 2015, 9 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
gavenmekhio

Total Points: 732
Total Questions: 89
Total Answers: 93

Location: Central African Republic
Member since Mon, Aug 10, 2020
4 Years ago
;