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.