Why does slickgrid add 1000px in JS, then reverse it in CSS style? - slickgrid

When calculating the avaialable space for headers, slickgrid carefully measures each column, then adds 1000.
function getHeadersWidth() {
var headersWidth = 0;
for (var i = 0, ii = columns.length; i < ii; i++) {
var width = columns[i].width;
headersWidth += width;
}
headersWidth += scrollbarDimensions.width;
return Math.max(headersWidth, viewportW) + 1000;
}
When it puts it in the DOM, this 1000 is reversed out with CSS:
$headers = $("<div class='slick-header-columns' style='left:-1000px' />").appendTo($headerScroller);
You can see this live in this example, just inspect the .slick-header-columns element.
What I would like to know is, why? What does this css trick do?

git bisect delivers the answer:
https://github.com/mleibman/SlickGrid/commit/c299a5628c791a3b3cb390a22312eb2247b07cd5
Author: David Lee
Date: Fri Mar 12 07:39:02 2010 +0800
Comment:
Improve column reorder behavior
Compatible with jquery-ui 1.8rc3
Columns can be dragged beyond the left edge, as can be done beyond the
right edge, so that columns can be dragged to the leftmost position,
even if the distance from the column's left edge to the initial
mousedown is greater than the distance between the left edge of the grid
and the midpoint of the previous leftmost column.
Notes:
The rationale is this:
When you reorder the columns using the jQuery UI 'sortable' component, you, the user, can drag a column to the left and the leftmost column will move aside to give you room to preview the reorder action: that means columnn 0 will be, at least temporarily, positioned in negative coordinate space (left # -columnwidth, right # 0px=left viewport edge).
Since SlickGrid allows for arbitrary width columns, which may be changed during the grid lifetime, David Lee (the author of the edit merged by Michael Leibman) apparently (I assume here; I didn't check his pull request or other source datums) used a worst-case column width assumption of 10000 pixels (see the c299 commit) to give the SlickGrid init code a one-size-fits-all setup/init.
See the next note for the commit when Michael Leibman changed this to the current -1000px value.
I had the same question for quite a while and couldn't find why -- earlier git bisect attempts misled me to https://github.com/mleibman/SlickGrid/commit/f2d480ce959b9f8504f718d6f7a825782d488415 which only changes the negative offset by a decade, while I did not know SlickGrid internals well enough back then to confidently set up a proper git bisect to hunt this one down. (The real change was done back in the SlickGrid 1.x series and there was a lot of code changed then)
Only now that I took out the -1000px myself and noted the column reordering getting worse, did git bisect help me dig up the relevant bit of history.
Off topic: using git bisect taught me once again that git considers bad to be 'the new situation' and git bisect good to represent the old situation: I had to remind myself this while using git bisect as here the old situation (when the -1000px/-10000px code was not part of SlickGrid yet) was the 'bad' situation, at least to my mind. I.e. git bisect bad ~ 'this is like the new situation; git bisect good ~ 'this looks like the old situation'.

Related

DC.js Line Chart - no line being displayed

Need to display line in a line-chart , with the ability to move the tiles, to see a max bitrate value line, to see labels and axis pointers on hover, grouped with a table and time Slider.Y dimension needs to display "bitrate total" or "bitrate Avg" (as defined in code). X dimension needs to display 15 min interval in scope of weeks.
I can upload my data into a table but not into the line graph. I can see points on the graph using .renderDataPoints() but no lines.
I checked the data - could not find any null/NaN values being returned, not using any old version of colors.
The code can be found in https://jsfiddle.net/dani2011/bu2ag0f7/8/. Tried to replace my CSV with var data but nothing is being displayed at the moment in the fiddle. The code as whole is displayed in https://groups.google.com/forum/#!topic/dc-js-user-group/MEslyF2RWRI
Any help would be greatly appreciated.
Here's my go-to-answer for how to put data into a jsFiddle. Basically it's easiest to stick it in an unused tag in the HTML. bl.ocks.org / blockbuilder.org is easier for this.
Here's a fork of your fiddle with the data loaded that way:
http://jsfiddle.net/gordonwoodhull/bu2ag0f7/17/
I also had to remove the spaces from the column names, because those got d3.csv confused and caused the BITRATE calculations to fail.
There was also some stray code inside the renderlet which was failing with a complaint about dim not existing.
The main reason why data was not displaying was because the input groups were not producing usable aggregated data. Your data is very close together in time, so aggregating by week would aggregate everything.
The way to debug this is to put a breakpoint or a console.log before the chart initialization and look at the results of group.all()
In this case bitrateWeekMinIntervalGroupMove and minIntervalWeekBitrateGroup were returning an array with one key/value pair. No lines can be drawn with one point. :)
It looks like you originally wanted to aggregate by 15 minute intervals, so let's get that working.
For whatever reason, there are two levels of aggregation in crossfilter, the dimension level and the group level. The dimension will have first crack at generating a key, and then the group will further refine these keys.
Your min15 function will map each time-key to the 15-minute mark before it, but it needs data that is higher than 15 minutes in resolution. So let's put these groups on the dateDimension, which hasn't already been mapped to a lower resolution:
var minIntervalWeekBitrateGroup = dateDimension.group(min15).reduceSum(function (d) {
return +d.BITRATE
});
var bitrateWeekMinIntervalGroupMove = dateDimension.group(min15).reduce(
...
Great, now there are 30 data points. And it draws lines.
I made the dots a bit smaller :) because at 30 pixels it was hard to see the lines.
Zooming in using the range chart reveals more of lines:
There still seem to be glitches in the reduce function (or somewhere) because the lines drop to zero when you zoom in too far, but hopefully this is enough to get you moving again.
My fork of your fiddle: http://jsfiddle.net/gordonwoodhull/bu2ag0f7/25/

D3.js: Need help grabbing data for tooltip

I've got a graph of small multiples with line charts. All is spiffy, except I cannot figure out how to get the tooltip to grab the data I need it to.
The sample and the code is at http://bl.ocks.org/emagee/8b2f557396d6f16ba65f. The tooltip code starts at line 198, with the toolTip variable declared just above that. The tooltip itself is working awesomely, but I cannot figure out how to get the tooltip to show the "date" and "count" variables. I did figure out how to get the "subject" in tool tip, but that is redundant, as you will see.
Specifically, my problem stems from not knowing how to skip a level as I dig deeper into the object -- "key" is the first level, then "values", then an unnamed construct, THEN the data I need ("date" and "count").
Any guidance on how to get from "key" to the "date" and "count" data would be most appreciated. I do understand that it may be more of a basic JS problem than a D3.js problem, but I'm a bit shaky with both!
Addendum (and, I'm afraid, a second question) -- I'm also wondering now if part of the problem is that I'm accessing the entire line/path -- as opposed to individual points. Should I perhaps overlay some appropriately sized, invisible circles/points on the lines and have the tooltip try to take readings from those...
First question you have to ask is do you want the date and count of where they moused over or do you want the date and count of the closest point to where they moused over? I'm assuming the later, so that's what I'll answer.
To do this, I'd use a combination of invert and a bisector:
.on("mouseover", function(s) {
var xDate = x.invert(d3.mouse(this)[0]), //<-- give me the date at the x mouse position
bisect = d3.bisector(function(d) { return d.date; }).left, //<-- set up a bisector to search the array for the closest point to the left
idx = bisect(s.values, xDate); //<-- find that point given our mouse position
You can now use:
s.values[idx].date
s.values[idx].count
Here's a working example.

dc.js heatmap expanding data

I am trying to show machine states over time. Part of this is to reproduce/automate a report that used to be done by hand. It consists of coloring 2minute 'time slices' in Excel based on what the machine is doing.
(Sorry, not enough reputation to post a picture, but it is a classic heatmap where the state drives the color. Some non DC-JS fiddle: http://jsfiddle.net/ww6Lbnc5/4/)
I was able to generate most of what I want in the following jsfiddle:
http://jsfiddle.net/hwhfxz2t/14/
See fiddle for code.
The total state duration (for selected time frame) is shown in the pieChart, followed by the individual state lines and then the heatmap that people are used to. (the ZOOM and date selection buttons do not work in the fiddle but are there to select specific data ranges or zoom in if you like).
The line charts uses the original representation of the states, which consists of a time the state is entered and a duration.
In order to make the heat map work, I had to (I think) take the original data and convert it into individual minute chunks and mark them with a state. So for instance the original data specifying:
RUN state starting 14:30 for 300 seconds
becomes:
14:30=RUN, 14:31=RUN, 14:32=RUN, 14:33=RUN and 14:34=RUN
The code in lines 233-297 loops through the original data and generates a new one that does this. In cases where there is more than one state within a given minute, the last state survives.
This works okay but it seems that this code is exactly what is normally done in group().reduce(add,remove,init). But in this case I need to add multiple timeslots depending on the duration of a state.
Also, because it is now using a different crossfilter, maps do not update each other.
Here are my questions related to this:
Can I display a heatmap without supplying information for all individual
'cells'? (i.e. straddle cells based on a value, similar to rowspan in a table)
Can I add multiple values at once inside group().reduce()?
Is there an easy way to invert the yAxis so 0 is at the top?
When clicking a row in the heatmap, it selects a column and vice-versa?
I'm not sure if this should be in the crossfilter group. If so please ignore my rambling. If someone knows how to keep the charts linked by grouping better, please let me know.
--Nico
Concerning Question 3:
DC.js heatmaps currently do not support custom order functions on axis but there is a pull request that has been merged into the developing branch and should be accessible to the public soon.
You could manually edit the dc.js file to set the sorting in heatmaps to a custom function. In the latest (2.0.0-beta10) version it is the following line:
rowValues.sort(d3.ascending);
and accordingly
colValues.sort(d3.ascending);

Independently jumping over full column span rows in the grid regardless of source order

I'm using singularitygs as my grid system and am really like the flexibility but I have come across a fairly unique situation and I'm not sure if singularity (or any other grid system) addresses
I have a row that span the entire column width, that breaks up the header portion and the content portion of the document. There is an element, div.b, that sits within above the full column bars next to div.a in larger layout. But on a medium sized layout and below, that element falls below the full span row. Here is the source order and the desired output, showed using a 10 column layout for simplicity.
Source Order
div.a
div.b
div.c
div.d
div.e
div.f
div.g
div.h
Large Layout
Medium Layout
Thanks in advance for any help and ++ to the creators of the grid system
Interesting use case. Honestly it’s going to be pretty hard until CSS grid layout comes out. While Singularity can handle any order horizontally, the vertical reordering like "D" and "G" stacked is going to be tricky. There might be a clever use of floats to get this working but it will probably be more hand manipulation of elements than pure Singularity magic.

How to exit().transition rects under a col in d3

I have a stacked bar chart that shows values either for month or year.
It is composed of a series of columns (1 or 12), and rects within each column (9 individual values).
You can see it here: (Note - this is a valid web page, currently running on AWS.)
http://54.245.225.47/stackedbar_ex_good
When I go from months to year view, I want to move all the positions to the yearly value, then fade them out as the year values .enter().
The problem is that the rects (where I would normally do the .exit().transition().attr("y", new_val) never gets called since the column gets deleted (.exit()). And when I tried referencing the child .rects from the svg.selectAll(".col").exit().transition(), they seemed to disappear all at once. I'm guessing this is the wrong way.
Sorry this is so confusing! I'm sure this sort of thing is answered elsewhere, but I don't even know the language to describe it properly (and hence search for it). Any tips / pointers would be appreciated.
(There is a lot of code - I don't know how to simplify in order to even post it.)
Yeah, kinda hard to understand the problem... As I understand it, you want to animate the exiting rects to some position before they're removed from the SVG. But your problem is that the rects' parents –– col in your code –– are removed immediately, and so the nested rects never have a chance to animate. Right?
If so, one way around it is to delay the removal of the exiting col's in order to give the rects animation time to play. So, rather than doing:
col.exit().remove()
apply a the delay like so:
col.exit().transition().delay(2000).remove()
There's no actual, visible transition here; it's just a way to delay the call to remove().

Resources